Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
commita7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch)
tree7452bd5c3545c2fa67a28aa013835fb4fa071baf
parentee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff)
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
-rw-r--r--.eslintrc.yml4
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml9
-rw-r--r--.gitlab/CODEOWNERS628
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml53
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml30
-rw-r--r--.gitlab/ci/memory.gitlab-ci.yml27
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml86
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml3
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml48
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml12
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml608
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml4
-rw-r--r--.gitlab/issue_templates/Actionable Insight - Exploration needed.md (renamed from .gitlab/issue_templates/Actionable Insight.md)10
-rw-r--r--.gitlab/issue_templates/Actionable Insight - Product change.md33
-rw-r--r--.gitlab/issue_templates/Deprecations.md18
-rw-r--r--.gitlab/issue_templates/Feature Flag Cleanup.md52
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md4
-rw-r--r--.gitlab/issue_templates/Feature Proposal - lean.md2
-rw-r--r--.gitlab/issue_templates/Feature proposal - detailed.md23
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md34
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md34
-rw-r--r--.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md38
-rw-r--r--.gitlab/issue_templates/Problem Validation.md2
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md6
-rw-r--r--.gitlab/merge_request_templates/Deprecations.md21
-rw-r--r--.gitlab/merge_request_templates/Removals.md30
-rw-r--r--.markdownlint.yml4
-rw-r--r--.projections.json.example8
-rw-r--r--.rubocop.yml34
-rw-r--r--.rubocop_todo.yml1
-rw-r--r--.rubocop_todo/database/multiple_databases.yml4
-rw-r--r--.rubocop_todo/gitlab/namespaced_class.yml2
-rw-r--r--.rubocop_todo/graphql/field_definitions.yml4
-rw-r--r--.rubocop_todo/graphql/ordered_arguments.yml4
-rw-r--r--.rubocop_todo/rails/save_bang.yml41
-rw-r--r--.rubocop_todo/rspec/any_instance_of.yml1
-rw-r--r--.rubocop_todo/rspec/leaky_constant_declaration.yml15
-rw-r--r--.rubocop_todo/rspec/multiple_memoized_helpers.yml11
-rw-r--r--.rubocop_todo/rspec/timecop_freeze.yml2
-rw-r--r--.rubocop_todo/style/open_struct_use.yml10
-rw-r--r--CHANGELOG.md16
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile29
-rw-r--r--Gemfile.lock174
-rw-r--r--PROCESS.md6
-rw-r--r--app/assets/images/auth_buttons/atlassian_64.pngbin1512 -> 1364 bytes
-rw-r--r--app/assets/images/auth_buttons/auth0_64.pngbin1815 -> 2873 bytes
-rw-r--r--app/assets/images/auth_buttons/bitbucket_64.pngbin1299 -> 1490 bytes
-rw-r--r--app/assets/images/auth_buttons/facebook_64.pngbin870 -> 1033 bytes
-rw-r--r--app/assets/images/auth_buttons/twitter_64.pngbin3110 -> 3695 bytes
-rw-r--r--app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql1
-rw-r--r--app/assets/javascripts/actioncable_link.js2
-rw-r--r--app/assets/javascripts/activities.js4
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue7
-rw-r--r--app/assets/javascripts/admin/application_settings/setup_service_usage_data.js15
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue15
-rw-r--r--app/assets/javascripts/alert_management/list.js2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js12
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql1
-rw-r--r--app/assets/javascripts/analytics/shared/components/daterange.vue33
-rw-r--r--app/assets/javascripts/analytics/shared/components/metric_popover.vue (renamed from app/assets/javascripts/cycle_analytics/components/metric_popover.vue)0
-rw-r--r--app/assets/javascripts/analytics/shared/components/metric_tile.vue51
-rw-r--r--app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue (renamed from app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue)53
-rw-r--r--app/assets/javascripts/analytics/shared/constants.js45
-rw-r--r--app/assets/javascripts/analytics/shared/utils.js27
-rw-r--r--app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql1
-rw-r--r--app/assets/javascripts/authentication/webauthn/util.js49
-rw-r--r--app/assets/javascripts/awards_handler.js8
-rw-r--r--app/assets/javascripts/badges/components/badge.vue9
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue12
-rw-r--r--app/assets/javascripts/badges/components/badge_list.vue10
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue5
-rw-r--r--app/assets/javascripts/batch_comments/components/diff_file_drafts.vue11
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue18
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/bold.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/code.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/italic.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/link.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/math.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/blockquote.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/heading.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/image.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/list_item.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/paragraph.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/playable.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/text.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/serializer.js2
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js19
-rw-r--r--app/assets/javascripts/blob/components/blob_header.vue15
-rw-r--r--app/assets/javascripts/blob/components/blob_header_default_actions.vue35
-rw-r--r--app/assets/javascripts/blob/components/blob_header_filepath.vue18
-rw-r--r--app/assets/javascripts/blob/components/constants.js2
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue6
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue18
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue32
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue48
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue3
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue3
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_new_item.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue43
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue54
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue1
-rw-r--r--app/assets/javascripts/boards/config_toggle.js1
-rw-r--r--app/assets/javascripts/boards/graphql.js9
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql7
-rw-r--r--app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql14
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql7
-rw-r--r--app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql14
-rw-r--r--app/assets/javascripts/boards/index.js3
-rw-r--r--app/assets/javascripts/boards/mount_filtered_search_issue_boards.js1
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js17
-rw-r--r--app/assets/javascripts/boards/stores/actions.js2
-rw-r--r--app/assets/javascripts/boards/toggle_focus.js1
-rw-r--r--app/assets/javascripts/broadcast_notification.js4
-rw-r--r--app/assets/javascripts/captcha/apollo_captcha_link.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue6
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue45
-rw-r--r--app/assets/javascripts/clusters/agents/components/show.vue3
-rw-r--r--app/assets/javascripts/clusters/agents/constants.js1
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/provider.js17
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql9
-rw-r--r--app/assets/javascripts/clusters/agents/index.js11
-rw-r--r--app/assets/javascripts/clusters/agents/router.js22
-rw-r--r--app/assets/javascripts/clusters_list/components/agent_table.vue152
-rw-r--r--app/assets/javascripts/clusters_list/components/agents.vue55
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue2
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_actions.vue34
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_view_all.vue60
-rw-r--r--app/assets/javascripts/clusters_list/components/delete_agent_button.vue (renamed from app/assets/javascripts/clusters_list/components/agent_options.vue)62
-rw-r--r--app/assets/javascripts/clusters_list/components/install_agent_modal.vue52
-rw-r--r--app/assets/javascripts/clusters_list/constants.js57
-rw-r--r--app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql7
-rw-r--r--app/assets/javascripts/clusters_list/load_main_view.js7
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js4
-rw-r--r--app/assets/javascripts/contextual_sidebar.js7
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue8
-rw-r--r--app/assets/javascripts/cycle_analytics/components/metric_tile.vue51
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_table.vue2
-rw-r--r--app/assets/javascripts/cycle_analytics/constants.js25
-rw-r--r--app/assets/javascripts/cycle_analytics/utils.js30
-rw-r--r--app/assets/javascripts/deprecated_notes.js8
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue1
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue8
-rw-r--r--app/assets/javascripts/design_management/graphql.js8
-rw-r--r--app/assets/javascripts/design_management/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/design_management/index.js1
-rw-r--r--app/assets/javascripts/diffs/components/app.vue87
-rw-r--r--app/assets/javascripts/diffs/components/collapsed_files_warning.vue14
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue17
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue31
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue26
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue8
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue45
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue44
-rw-r--r--app/assets/javascripts/diffs/components/merge_conflict_warning.vue14
-rw-r--r--app/assets/javascripts/diffs/constants.js6
-rw-r--r--app/assets/javascripts/diffs/index.js16
-rw-r--r--app/assets/javascripts/diffs/store/actions.js29
-rw-r--r--app/assets/javascripts/diffs/store/getters.js17
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js4
-rw-r--r--app/assets/javascripts/diffs/store/utils.js18
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js94
-rw-r--r--app/assets/javascripts/editor/schema/ci.json3
-rw-r--r--app/assets/javascripts/emoji/awards_app/index.js1
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/actions.js41
-rw-r--r--app/assets/javascripts/emoji/components/utils.js8
-rw-r--r--app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js3
-rw-r--r--app/assets/javascripts/environments/components/canary_ingress.vue15
-rw-r--r--app/assets/javascripts/environments/components/canary_update_modal.vue2
-rw-r--r--app/assets/javascripts/environments/components/commit.vue54
-rw-r--r--app/assets/javascripts/environments/components/deploy_board.vue68
-rw-r--r--app/assets/javascripts/environments/components/deploy_board_wrapper.vue86
-rw-r--r--app/assets/javascripts/environments/components/deployment.vue217
-rw-r--r--app/assets/javascripts/environments/components/empty_state.vue4
-rw-r--r--app/assets/javascripts/environments/components/environment_pin.vue15
-rw-r--r--app/assets/javascripts/environments/components/new_environment_item.vue77
-rw-r--r--app/assets/javascripts/environments/components/new_environments_app.vue12
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql4
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_to_change_canary.query.graphql4
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers.js11
-rw-r--r--app/assets/javascripts/environments/graphql/typedefs.graphql3
-rw-r--r--app/assets/javascripts/files_comment_button.js4
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js15
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js5
-rw-r--r--app/assets/javascripts/filtered_search/constants.js2
-rw-r--r--app/assets/javascripts/flash.js12
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js74
-rw-r--r--app/assets/javascripts/google_cloud/components/deployments_service_table.vue25
-rw-r--r--app/assets/javascripts/google_cloud/components/home.vue8
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts_form.vue12
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts_list.vue48
-rw-r--r--app/assets/javascripts/google_tag_manager/index.js111
-rw-r--r--app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js17
-rw-r--r--app/assets/javascripts/graphql_shared/possibleTypes.json1
-rw-r--r--app/assets/javascripts/groups/components/app.vue10
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue19
-rw-r--r--app/assets/javascripts/groups/components/invite_members_banner.vue1
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue81
-rw-r--r--app/assets/javascripts/groups/components/transfer_group_form.vue80
-rw-r--r--app/assets/javascripts/groups/constants.js6
-rw-r--r--app/assets/javascripts/groups/init_transfer_group_form.js52
-rw-r--r--app/assets/javascripts/groups/landing.js7
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js1
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js39
-rw-r--r--app/assets/javascripts/groups/transfer_edit.js11
-rw-r--r--app/assets/javascripts/groups_select.js2
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue11
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue2
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue18
-rw-r--r--app/assets/javascripts/ide/constants.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/clientside/actions.js4
-rw-r--r--app/assets/javascripts/image_diff/helpers/badge_helper.js14
-rw-r--r--app/assets/javascripts/image_diff/helpers/dom_helper.js4
-rw-r--r--app/assets/javascripts/image_diff/image_diff.js2
-rw-r--r--app/assets/javascripts/image_diff/replaced_image_diff.js2
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue15
-rw-r--r--app/assets/javascripts/integrations/constants.js4
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue19
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue83
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue21
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue19
-rw-r--r--app/assets/javascripts/integrations/edit/event_hub.js3
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js3
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js4
-rw-r--r--app/assets/javascripts/invite_members/components/group_select.vue47
-rw-r--r--app/assets/javascripts/invite_members/components/invite_group_trigger.vue2
-rw-r--r--app/assets/javascripts/invite_members/components/invite_groups_modal.vue146
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue419
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue2
-rw-r--r--app/assets/javascripts/invite_members/components/invite_modal_base.vue276
-rw-r--r--app/assets/javascripts/invite_members/constants.js91
-rw-r--r--app/assets/javascripts/invite_members/init_invite_groups_modal.js44
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js3
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_trigger.js1
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/index.js1
-rw-r--r--app/assets/javascripts/issuable/index.js3
-rw-r--r--app/assets/javascripts/issuable/issuable_context.js4
-rw-r--r--app/assets/javascripts/issuable/issuable_form.js1
-rw-r--r--app/assets/javascripts/issues/create_merge_request_dropdown.js35
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue182
-rw-r--r--app/assets/javascripts/issues/list/components/new_issue_dropdown.vue2
-rw-r--r--app/assets/javascripts/issues/list/constants.js17
-rw-r--r--app/assets/javascripts/issues/list/index.js4
-rw-r--r--app/assets/javascripts/issues/list/queries/issue.fragment.graphql3
-rw-r--r--app/assets/javascripts/issues/list/queries/search_milestones.query.graphql15
-rw-r--r--app/assets/javascripts/issues/list/queries/set_sort_preference.mutation.graphql5
-rw-r--r--app/assets/javascripts/issues/list/utils.js17
-rw-r--r--app/assets/javascripts/issues/manual_ordering.js5
-rw-r--r--app/assets/javascripts/issues/new/index.js2
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/index.js1
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue126
-rw-r--r--app/assets/javascripts/issues/show/components/fields/description.vue5
-rw-r--r--app/assets/javascripts/issues/show/index.js7
-rw-r--r--app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue99
-rw-r--r--app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue33
-rw-r--r--app/assets/javascripts/jira_connect/branches/constants.js3
-rw-r--r--app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql3
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue34
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/app.vue58
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue63
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue6
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/sign_in.vue40
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/subscriptions.vue43
-rw-r--r--app/assets/javascripts/jobs/components/table/cells/actions_cell.vue20
-rw-r--r--app/assets/javascripts/jobs/components/table/cells/duration_cell.vue1
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_app.vue4
-rw-r--r--app/assets/javascripts/labels/index.js2
-rw-r--r--app/assets/javascripts/lib/apollo/instrumentation_link.js2
-rw-r--r--app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js4
-rw-r--r--app/assets/javascripts/lib/graphql.js99
-rw-r--r--app/assets/javascripts/lib/prosemirror_markdown_serializer.js3
-rw-r--r--app/assets/javascripts/lib/utils/apollo_startup_js_link.js2
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js5
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue34
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js8
-rw-r--r--app/assets/javascripts/lib/utils/constants.js1
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js23
-rw-r--r--app/assets/javascripts/lib/utils/table_utility.js35
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js65
-rw-r--r--app/assets/javascripts/lib/utils/yaml.js121
-rw-r--r--app/assets/javascripts/listbox/index.js67
-rw-r--r--app/assets/javascripts/listbox/redirect_behavior.js22
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue38
-rw-r--r--app/assets/javascripts/main.js2
-rw-r--r--app/assets/javascripts/members/components/avatars/user_avatar.vue14
-rw-r--r--app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue1
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue14
-rw-r--r--app/assets/javascripts/members/constants.js1
-rw-r--r--app/assets/javascripts/merge_conflicts/store/actions.js4
-rw-r--r--app/assets/javascripts/merge_conflicts/store/state.js4
-rw-r--r--app/assets/javascripts/merge_request_tabs.js17
-rw-r--r--app/assets/javascripts/milestones/index.js2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue51
-rw-r--r--app/assets/javascripts/nav/components/top_nav_menu_item.vue2
-rw-r--r--app/assets/javascripts/nav/mount.js1
-rw-r--r--app/assets/javascripts/network/raphael.js11
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue5
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue8
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue26
-rw-r--r--app/assets/javascripts/notes/discussion_filters.js2
-rw-r--r--app/assets/javascripts/notes/index.js1
-rw-r--r--app/assets/javascripts/notes/mixins/discussion_navigation.js12
-rw-r--r--app/assets/javascripts/notes/sort_discussions.js1
-rw-r--r--app/assets/javascripts/notifications/components/notifications_dropdown.vue4
-rw-r--r--app/assets/javascripts/notifications/index.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue14
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue14
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue12
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue43
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json17
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js15
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue (renamed from app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue)17
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/tags_loader.vue (renamed from app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants/index.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js (renamed from app/assets/javascripts/packages_and_registries/shared/constants.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants/quick_start.js9
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue6
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_downloader.js52
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_previewer.js21
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/service_usage_data/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/runners/show/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js7
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/imports/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue16
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue12
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/index/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/new/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue8
-rw-r--r--app/assets/javascripts/pages/projects/planning_hierarchy/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/project.js8
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/security/configuration/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/serverless/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue2
-rw-r--r--app/assets/javascripts/pages/users/index.js4
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue12
-rw-r--r--app/assets/javascripts/performance_bar/index.js1
-rw-r--r--app/assets/javascripts/persistent_user_callout.js4
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue36
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue70
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue55
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js1
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue75
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue2
-rw-r--r--app/assets/javascripts/pipeline_new/constants.js7
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/commit.vue224
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/editor.vue94
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/step_nav.vue54
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/widgets/text.vue126
-rw-r--r--app/assets/javascripts/pipeline_wizard/queries/create_commit.graphql9
-rw-r--r--app/assets/javascripts/pipeline_wizard/queries/get_file_meta.graphql12
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue30
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue98
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue22
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/jobs_app.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/notification/deprecated_type_keyword_notification.vue102
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue18
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue167
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue25
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue6
-rw-r--r--app/assets/javascripts/pipelines/constants.js9
-rw-r--r--app/assets/javascripts/pipelines/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_warnings.query.graphql12
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js18
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js10
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_notification.js31
-rw-r--r--app/assets/javascripts/pipelines/pipeline_shared_client.js9
-rw-r--r--app/assets/javascripts/popovers/index.js2
-rw-r--r--app/assets/javascripts/projects/components/project_delete_button.vue71
-rw-r--r--app/assets/javascripts/projects/components/shared/delete_button.vue84
-rw-r--r--app/assets/javascripts/projects/new/components/deployment_target_select.vue61
-rw-r--r--app/assets/javascripts/projects/new/constants.js20
-rw-r--r--app/assets/javascripts/projects/new/index.js14
-rw-r--r--app/assets/javascripts/projects/project_new.js93
-rw-r--r--app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue23
-rw-r--r--app/assets/javascripts/projects/settings/components/transfer_project_form.vue12
-rw-r--r--app/assets/javascripts/projects/settings/constants.js7
-rw-r--r--app/assets/javascripts/projects/settings/init_transfer_project_form.js10
-rw-r--r--app/assets/javascripts/related_issues/components/add_issuable_form.vue12
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue19
-rw-r--r--app/assets/javascripts/related_issues/constants.js25
-rw-r--r--app/assets/javascripts/related_issues/index.js1
-rw-r--r--app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue9
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue95
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue20
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue14
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/index.js61
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue38
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue14
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/video_viewer.vue9
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue4
-rw-r--r--app/assets/javascripts/repository/components/table/parent_row.vue13
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue1
-rw-r--r--app/assets/javascripts/repository/constants.js51
-rw-r--r--app/assets/javascripts/repository/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/repository/graphql.js9
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql13
-rw-r--r--app/assets/javascripts/right_sidebar.js4
-rw-r--r--app/assets/javascripts/runner/admin_runner_show/admin_runner_show_app.vue77
-rw-r--r--app/assets/javascripts/runner/admin_runner_show/index.js32
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue11
-rw-r--r--app/assets/javascripts/runner/components/cells/link_cell.vue27
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_actions_cell.vue73
-rw-r--r--app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue19
-rw-r--r--app/assets/javascripts/runner/components/runner_assigned_item.vue39
-rw-r--r--app/assets/javascripts/runner/components/runner_detail.vue50
-rw-r--r--app/assets/javascripts/runner/components/runner_details.vue124
-rw-r--r--app/assets/javascripts/runner/components/runner_edit_button.vue26
-rw-r--r--app/assets/javascripts/runner/components/runner_groups.vue37
-rw-r--r--app/assets/javascripts/runner/components/runner_header.vue52
-rw-r--r--app/assets/javascripts/runner/components/runner_jobs.vue82
-rw-r--r--app/assets/javascripts/runner/components/runner_jobs_table.vue95
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue30
-rw-r--r--app/assets/javascripts/runner/components/runner_pagination.vue12
-rw-r--r--app/assets/javascripts/runner/components/runner_pause_button.vue122
-rw-r--r--app/assets/javascripts/runner/components/runner_projects.vue111
-rw-r--r--app/assets/javascripts/runner/components/runner_tags.vue4
-rw-r--r--app/assets/javascripts/runner/components/runner_type_tabs.vue59
-rw-r--r--app/assets/javascripts/runner/constants.js23
-rw-r--r--app/assets/javascripts/runner/graphql/get_group_runners.query.graphql2
-rw-r--r--app/assets/javascripts/runner/graphql/get_runner.query.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/get_runner_jobs.query.graphql36
-rw-r--r--app/assets/javascripts/runner/graphql/get_runner_projects.query.graphql26
-rw-r--r--app/assets/javascripts/runner/graphql/get_runners.query.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql14
-rw-r--r--app/assets/javascripts/runner/graphql/runner_details_shared.fragment.graphql20
-rw-r--r--app/assets/javascripts/runner/graphql/runner_node.fragment.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/runner_toggle_active.mutation.graphql12
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue81
-rw-r--r--app/assets/javascripts/runner/runner_search_utils.js26
-rw-r--r--app/assets/javascripts/runner/utils.js72
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue6
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js34
-rw-r--r--app/assets/javascripts/security_configuration/components/feature_card.vue23
-rw-r--r--app/assets/javascripts/security_configuration/components/training_provider_list.vue106
-rw-r--r--app/assets/javascripts/security_configuration/components/upgrade_banner.vue18
-rw-r--r--app/assets/javascripts/security_configuration/constants.js2
-rw-r--r--app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql7
-rw-r--r--app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql16
-rw-r--r--app/assets/javascripts/security_configuration/index.js7
-rw-r--r--app/assets/javascripts/security_configuration/resolver.js56
-rw-r--r--app/assets/javascripts/security_configuration/utils.js13
-rw-r--r--app/assets/javascripts/serverless/components/empty_state.vue25
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue24
-rw-r--r--app/assets/javascripts/serverless/constants.js3
-rw-r--r--app/assets/javascripts/serverless/survey_banner.js36
-rw-r--r--app/assets/javascripts/serverless/survey_banner.vue52
-rw-r--r--app/assets/javascripts/settings_panels.js23
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue36
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue37
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue15
-rw-r--r--app/assets/javascripts/sidebar/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/sidebar/graphql.js15
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js1
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js16
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js2
-rw-r--r--app/assets/javascripts/tabs/constants.js6
-rw-r--r--app/assets/javascripts/terraform/components/states_table.vue17
-rw-r--r--app/assets/javascripts/terraform/index.js2
-rw-r--r--app/assets/javascripts/toggles/index.js65
-rw-r--r--app/assets/javascripts/tooltips/index.js1
-rw-r--r--app/assets/javascripts/user_callout.js6
-rw-r--r--app/assets/javascripts/vue_alerts.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue20
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue31
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue66
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue60
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue45
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue99
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js120
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/i18n.js17
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/index.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_fork_modal.vue68
-rw-r--r--app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js14
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue106
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js195
-rw-r--r--app/assets/javascripts/vue_shared/components/help_popover.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue24
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue255
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue104
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue48
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue49
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue148
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/constants.js111
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue (renamed from app/assets/javascripts/vue_shared/components/source_viewer.vue)51
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/utils.js26
-rw-r--r--app/assets/javascripts/vue_shared/components/svg_gradient.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue27
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue16
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue13
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue8
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue8
-rw-r--r--app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue2
-rw-r--r--app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue4
-rw-r--r--app/assets/javascripts/work_items/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/work_items/graphql/project_work_item_types.query.graphql11
-rw-r--r--app/assets/javascripts/work_items/graphql/provider.js9
-rw-r--r--app/assets/javascripts/work_items/index.js4
-rw-r--r--app/assets/javascripts/work_items/pages/create_work_item.vue116
-rw-r--r--app/assets/javascripts/work_items_hierarchy/components/app.vue101
-rw-r--r--app/assets/javascripts/work_items_hierarchy/components/hierarchy.vue119
-rw-r--r--app/assets/javascripts/work_items_hierarchy/constants.js62
-rw-r--r--app/assets/javascripts/work_items_hierarchy/hierarchy_util.js10
-rw-r--r--app/assets/javascripts/work_items_hierarchy/static_response.js142
-rw-r--r--app/assets/javascripts/work_items_hierarchy/work_items_hierarchy_bundle.js26
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-rw-r--r--app/assets/stylesheets/components/design_management/design.scss108
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/blank.scss118
-rw-r--r--app/assets/stylesheets/framework/buttons.scss33
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss5
-rw-r--r--app/assets/stylesheets/framework/diffs.scss67
-rw-r--r--app/assets/stylesheets/framework/files.scss5
-rw-r--r--app/assets/stylesheets/framework/forms.scss4
-rw-r--r--app/assets/stylesheets/framework/header.scss45
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss21
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss5
-rw-r--r--app/assets/stylesheets/framework/typography.scss22
-rw-r--r--app/assets/stylesheets/framework/variables.scss11
-rw-r--r--app/assets/stylesheets/highlight/common.scss22
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss6
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss6
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss7
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss6
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss6
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss17
-rw-r--r--app/assets/stylesheets/mailers/highlighted_diff_email.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/dashboard_projects.scss35
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss641
-rw-r--r--app/assets/stylesheets/page_bundles/milestone.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/project.scss133
-rw-r--r--app/assets/stylesheets/page_bundles/projects_edit.scss25
-rw-r--r--app/assets/stylesheets/pages/clusters.scss14
-rw-r--r--app/assets/stylesheets/pages/groups.scss13
-rw-r--r--app/assets/stylesheets/pages/hierarchy.scss15
-rw-r--r--app/assets/stylesheets/pages/issuable.scss73
-rw-r--r--app/assets/stylesheets/pages/issues.scss31
-rw-r--r--app/assets/stylesheets/pages/login.scss8
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss637
-rw-r--r--app/assets/stylesheets/pages/pages.scss5
-rw-r--r--app/assets/stylesheets/pages/projects.scss162
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss111
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss95
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss23
-rw-r--r--app/assets/stylesheets/themes/_dark.scss16
-rw-r--r--app/assets/stylesheets/utilities.scss96
-rw-r--r--app/assets/stylesheets/vendors/tribute.scss41
-rw-r--r--app/controllers/abuse_reports_controller.rb4
-rw-r--r--app/controllers/admin/application_settings_controller.rb9
-rw-r--r--app/controllers/admin/instance_review_controller.rb2
-rw-r--r--app/controllers/admin/runners_controller.rb18
-rw-r--r--app/controllers/admin/users_controller.rb4
-rw-r--r--app/controllers/clusters/base_controller.rb6
-rw-r--r--app/controllers/clusters/clusters_controller.rb2
-rw-r--r--app/controllers/concerns/bizible_csp.rb15
-rw-r--r--app/controllers/concerns/integrations/actions.rb3
-rw-r--r--app/controllers/concerns/integrations/params.rb1
-rw-r--r--app/controllers/concerns/issuable_actions.rb5
-rw-r--r--app/controllers/concerns/multiple_boards_actions.rb2
-rw-r--r--app/controllers/concerns/planning_hierarchy.rb15
-rw-r--r--app/controllers/concerns/uploads_actions.rb8
-rw-r--r--app/controllers/dashboard/projects_controller.rb8
-rw-r--r--app/controllers/dashboard_controller.rb4
-rw-r--r--app/controllers/explore/projects_controller.rb7
-rw-r--r--app/controllers/graphql_controller.rb6
-rw-r--r--app/controllers/groups/boards_controller.rb4
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb2
-rw-r--r--app/controllers/groups/runners_controller.rb16
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb5
-rw-r--r--app/controllers/groups/uploads_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb22
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb2
-rw-r--r--app/controllers/metrics_controller.rb1
-rw-r--r--app/controllers/oauth/authorizations_controller.rb51
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb11
-rw-r--r--app/controllers/projects/badges_controller.rb12
-rw-r--r--app/controllers/projects/boards_controller.rb4
-rw-r--r--app/controllers/projects/branches_controller.rb19
-rw-r--r--app/controllers/projects/cluster_agents_controller.rb2
-rw-r--r--app/controllers/projects/clusters_controller.rb1
-rw-r--r--app/controllers/projects/commit_controller.rb2
-rw-r--r--app/controllers/projects/commits_controller.rb12
-rw-r--r--app/controllers/projects/compare_controller.rb21
-rw-r--r--app/controllers/projects/design_management/designs_controller.rb1
-rw-r--r--app/controllers/projects/forks_controller.rb10
-rw-r--r--app/controllers/projects/google_cloud/deployments_controller.rb55
-rw-r--r--app/controllers/projects/google_cloud_controller.rb2
-rw-r--r--app/controllers/projects/group_links_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb19
-rw-r--r--app/controllers/projects/merge_requests/drafts_controller.rb3
-rw-r--r--app/controllers/projects/merge_requests_controller.rb38
-rw-r--r--app/controllers/projects/packages/infrastructure_registry_controller.rb6
-rw-r--r--app/controllers/projects/pipelines_controller.rb3
-rw-r--r--app/controllers/projects/project_members_controller.rb3
-rw-r--r--app/controllers/projects/refs_controller.rb10
-rw-r--r--app/controllers/projects/repositories_controller.rb2
-rw-r--r--app/controllers/projects/runners_controller.rb2
-rw-r--r--app/controllers/projects/security/configuration_controller.rb2
-rw-r--r--app/controllers/projects/service_desk_controller.rb1
-rw-r--r--app/controllers/projects/service_ping_controller.rb8
-rw-r--r--app/controllers/projects/services_controller.rb3
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb2
-rw-r--r--app/controllers/projects/settings/repository_controller.rb2
-rw-r--r--app/controllers/projects/tags_controller.rb12
-rw-r--r--app/controllers/projects/uploads_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb23
-rw-r--r--app/controllers/registrations_controller.rb10
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb9
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb1
-rw-r--r--app/controllers/search_controller.rb1
-rw-r--r--app/controllers/sessions_controller.rb1
-rw-r--r--app/controllers/users_controller.rb17
-rw-r--r--app/events/ci/job_artifacts_deleted_event.rb20
-rw-r--r--app/events/members/members_added_event.rb16
-rw-r--r--app/events/projects/project_deleted_event.rb16
-rw-r--r--app/experiments/application_experiment.rb26
-rw-r--r--app/experiments/combined_registration_experiment.rb2
-rw-r--r--app/experiments/empty_repo_upload_experiment.rb2
-rw-r--r--app/experiments/force_company_trial_experiment.rb2
-rw-r--r--app/experiments/in_product_guidance_environments_webide_experiment.rb2
-rw-r--r--app/experiments/new_project_readme_content_experiment.rb30
-rw-r--r--app/experiments/new_project_sast_enabled_experiment.rb2
-rw-r--r--app/experiments/require_verification_for_namespace_creation_experiment.rb12
-rw-r--r--app/experiments/security_reports_mr_widget_prompt_experiment.rb2
-rw-r--r--app/experiments/templates/new_project_readme_content/readme_basic.md.tt3
-rw-r--r--app/finders/autocomplete/users_finder.rb8
-rw-r--r--app/finders/ci/jobs_finder.rb14
-rw-r--r--app/finders/ci/runners_finder.rb10
-rw-r--r--app/finders/crm/contacts_finder.rb39
-rw-r--r--app/finders/deployments_finder.rb12
-rw-r--r--app/finders/environments/environments_by_deployments_finder.rb10
-rw-r--r--app/finders/git_refs_finder.rb4
-rw-r--r--app/finders/group_descendants_finder.rb11
-rw-r--r--app/finders/group_projects_finder.rb18
-rw-r--r--app/finders/issues_finder.rb6
-rw-r--r--app/finders/issues_finder/params.rb12
-rw-r--r--app/finders/merge_requests_finder.rb10
-rw-r--r--app/finders/merge_requests_finder/params.rb6
-rw-r--r--app/finders/packages/package_file_finder.rb8
-rw-r--r--app/finders/projects_finder.rb6
-rw-r--r--app/finders/releases_finder.rb14
-rw-r--r--app/finders/users_finder.rb6
-rw-r--r--app/graphql/graphql_triggers.rb4
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb4
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb4
-rw-r--r--app/graphql/mutations/boards/create.rb3
-rw-r--r--app/graphql/mutations/branches/create.rb4
-rw-r--r--app/graphql/mutations/ci/ci_cd_settings_update.rb4
-rw-r--r--app/graphql/mutations/ci/job_token_scope/add_project.rb4
-rw-r--r--app/graphql/mutations/ci/job_token_scope/remove_project.rb4
-rw-r--r--app/graphql/mutations/ci/runner/delete.rb2
-rw-r--r--app/graphql/mutations/ci/runner/update.rb7
-rw-r--r--app/graphql/mutations/clusters/agents/create.rb4
-rw-r--r--app/graphql/mutations/commits/create.rb4
-rw-r--r--app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb51
-rw-r--r--app/graphql/mutations/container_expiration_policies/update.rb4
-rw-r--r--app/graphql/mutations/container_repositories/destroy_tags.rb5
-rw-r--r--app/graphql/mutations/custom_emoji/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/contacts/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/contacts/update.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/update.rb4
-rw-r--r--app/graphql/mutations/dependency_proxy/group_settings/update.rb4
-rw-r--r--app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb4
-rw-r--r--app/graphql/mutations/design_management/delete.rb4
-rw-r--r--app/graphql/mutations/groups/update.rb4
-rw-r--r--app/graphql/mutations/issues/create.rb19
-rw-r--r--app/graphql/mutations/issues/set_confidential.rb4
-rw-r--r--app/graphql/mutations/issues/set_escalation_status.rb6
-rw-r--r--app/graphql/mutations/jira_import/import_users.rb4
-rw-r--r--app/graphql/mutations/jira_import/start.rb4
-rw-r--r--app/graphql/mutations/labels/create.rb4
-rw-r--r--app/graphql/mutations/merge_requests/accept.rb12
-rw-r--r--app/graphql/mutations/merge_requests/create.rb4
-rw-r--r--app/graphql/mutations/namespace/package_settings/update.rb4
-rw-r--r--app/graphql/mutations/release_asset_links/create.rb7
-rw-r--r--app/graphql/mutations/snippets/create.rb5
-rw-r--r--app/graphql/mutations/snippets/update.rb5
-rw-r--r--app/graphql/mutations/user_preferences/update.rb28
-rw-r--r--app/graphql/mutations/work_items/create.rb18
-rw-r--r--app/graphql/mutations/work_items/delete.rb47
-rw-r--r--app/graphql/mutations/work_items/update.rb61
-rw-r--r--app/graphql/queries/pipelines/get_pipeline_details.query.graphql1
-rw-r--r--app/graphql/resolvers/ci/project_pipeline_counts_resolver.rb28
-rw-r--r--app/graphql/resolvers/ci/runner_jobs_resolver.rb45
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb12
-rw-r--r--app/graphql/resolvers/clusters/agent_tokens_resolver.rb2
-rw-r--r--app/graphql/resolvers/kas/agent_configurations_resolver.rb2
-rw-r--r--app/graphql/resolvers/kas/agent_connections_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb19
-rw-r--r--app/graphql/resolvers/paginated_tree_resolver.rb8
-rw-r--r--app/graphql/resolvers/project_jobs_resolver.rb3
-rw-r--r--app/graphql/resolvers/recent_boards_resolver.rb17
-rw-r--r--app/graphql/resolvers/tree_resolver.rb8
-rw-r--r--app/graphql/resolvers/users/groups_resolver.rb6
-rw-r--r--app/graphql/types/admin/analytics/usage_trends/measurement_type.rb3
-rw-r--r--app/graphql/types/alert_management/prometheus_integration_type.rb4
-rw-r--r--app/graphql/types/board_list_type.rb4
-rw-r--r--app/graphql/types/ci/pipeline_counts_type.rb24
-rw-r--r--app/graphql/types/ci/runner_sort_enum.rb2
-rw-r--r--app/graphql/types/ci/runner_status_enum.rb12
-rw-r--r--app/graphql/types/ci/runner_type.rb50
-rw-r--r--app/graphql/types/clusters/agent_activity_event_type.rb2
-rw-r--r--app/graphql/types/clusters/agent_token_type.rb2
-rw-r--r--app/graphql/types/clusters/agent_type.rb2
-rw-r--r--app/graphql/types/commit_type.rb14
-rw-r--r--app/graphql/types/group_invitation_type.rb6
-rw-r--r--app/graphql/types/group_member_type.rb6
-rw-r--r--app/graphql/types/group_type.rb24
-rw-r--r--app/graphql/types/issuable_type.rb4
-rw-r--r--app/graphql/types/issue_type.rb11
-rw-r--r--app/graphql/types/label_type.rb3
-rw-r--r--app/graphql/types/member_interface.rb12
-rw-r--r--app/graphql/types/merge_request_sort_enum.rb2
-rw-r--r--app/graphql/types/merge_requests/assignee_type.rb5
-rw-r--r--app/graphql/types/merge_requests/interacts_with_merge_request.rb5
-rw-r--r--app/graphql/types/merge_requests/reviewer_type.rb5
-rw-r--r--app/graphql/types/metrics/dashboards/annotation_type.rb2
-rw-r--r--app/graphql/types/mutation_type.rb9
-rw-r--r--app/graphql/types/notes/discussion_type.rb4
-rw-r--r--app/graphql/types/packages/package_details_type.rb15
-rw-r--r--app/graphql/types/permission_types/issue.rb2
-rw-r--r--app/graphql/types/permission_types/merge_request.rb9
-rw-r--r--app/graphql/types/project_type.rb14
-rw-r--r--app/graphql/types/query_complexity_type.rb4
-rw-r--r--app/graphql/types/repository/blob_type.rb18
-rw-r--r--app/graphql/types/root_storage_statistics_type.rb1
-rw-r--r--app/graphql/types/subscription_type.rb3
-rw-r--r--app/graphql/types/terraform/state_version_type.rb4
-rw-r--r--app/graphql/types/tree/blob_type.rb5
-rw-r--r--app/graphql/types/tree/submodule_type.rb4
-rw-r--r--app/graphql/types/tree/tree_entry_type.rb7
-rw-r--r--app/graphql/types/user_interface.rb4
-rw-r--r--app/graphql/types/user_preferences_type.rb17
-rw-r--r--app/graphql/types/work_item_state_enum.rb11
-rw-r--r--app/graphql/types/work_item_type.rb2
-rw-r--r--app/graphql/types/work_items/state_event_enum.rb13
-rw-r--r--app/helpers/application_helper.rb5
-rw-r--r--app/helpers/application_settings_helper.rb9
-rw-r--r--app/helpers/avatars_helper.rb30
-rw-r--r--app/helpers/bizible_helper.rb10
-rw-r--r--app/helpers/boards_helper.rb5
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb4
-rw-r--r--app/helpers/clusters_helper.rb6
-rw-r--r--app/helpers/groups_helper.rb4
-rw-r--r--app/helpers/ide_helper.rb2
-rw-r--r--app/helpers/integrations_helper.rb4
-rw-r--r--app/helpers/invite_members_helper.rb21
-rw-r--r--app/helpers/issuables_description_templates_helper.rb8
-rw-r--r--app/helpers/issuables_helper.rb5
-rw-r--r--app/helpers/issues_helper.rb9
-rw-r--r--app/helpers/learn_gitlab_helper.rb4
-rw-r--r--app/helpers/listbox_helper.rb57
-rw-r--r--app/helpers/nav/top_nav_helper.rb8
-rw-r--r--app/helpers/projects/cluster_agents_helper.rb1
-rw-r--r--app/helpers/projects_helper.rb32
-rw-r--r--app/helpers/search_helper.rb17
-rw-r--r--app/helpers/storage_helper.rb38
-rw-r--r--app/helpers/system_note_helper.rb3
-rw-r--r--app/helpers/tab_helper.rb2
-rw-r--r--app/helpers/tags_helper.rb6
-rw-r--r--app/helpers/tree_helper.rb15
-rw-r--r--app/helpers/users/group_callouts_helper.rb1
-rw-r--r--app/helpers/users_helper.rb7
-rw-r--r--app/models/application_record.rb1
-rw-r--r--app/models/application_setting.rb6
-rw-r--r--app/models/application_setting_implementation.rb14
-rw-r--r--app/models/audit_event.rb5
-rw-r--r--app/models/blob.rb4
-rw-r--r--app/models/board.rb2
-rw-r--r--app/models/ci/namespace_mirror.rb4
-rw-r--r--app/models/ci/pipeline.rb26
-rw-r--r--app/models/ci/runner.rb120
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/commit.rb4
-rw-r--r--app/models/concerns/analytics/cycle_analytics/stage_event_model.rb40
-rw-r--r--app/models/concerns/ci/contextable.rb47
-rw-r--r--app/models/concerns/ci/has_variable.rb17
-rw-r--r--app/models/concerns/cross_database_modification.rb122
-rw-r--r--app/models/concerns/has_environment_scope.rb8
-rw-r--r--app/models/concerns/issuable.rb14
-rw-r--r--app/models/concerns/mirror_authentication.rb9
-rw-r--r--app/models/concerns/noteable.rb6
-rw-r--r--app/models/concerns/packages/debian/distribution.rb8
-rw-r--r--app/models/concerns/resolvable_discussion.rb10
-rw-r--r--app/models/concerns/taskable.rb15
-rw-r--r--app/models/concerns/timebox.rb13
-rw-r--r--app/models/concerns/token_authenticatable.rb12
-rw-r--r--app/models/concerns/token_authenticatable_strategies/base.rb36
-rw-r--r--app/models/container_repository.rb301
-rw-r--r--app/models/customer_relations/contact.rb18
-rw-r--r--app/models/customer_relations/issue_contact.rb6
-rw-r--r--app/models/dependency_proxy/blob.rb4
-rw-r--r--app/models/dependency_proxy/manifest.rb3
-rw-r--r--app/models/deployment.rb14
-rw-r--r--app/models/discussion.rb2
-rw-r--r--app/models/draft_note.rb7
-rw-r--r--app/models/environment.rb4
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/hooks/web_hook.rb5
-rw-r--r--app/models/instance_configuration.rb9
-rw-r--r--app/models/integration.rb3
-rw-r--r--app/models/integrations/chat_message/base_message.rb5
-rw-r--r--app/models/integrations/datadog.rb54
-rw-r--r--app/models/issue.rb11
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/loose_foreign_keys/deleted_record.rb32
-rw-r--r--app/models/member.rb15
-rw-r--r--app/models/members/project_member.rb7
-rw-r--r--app/models/merge_request.rb66
-rw-r--r--app/models/milestone.rb11
-rw-r--r--app/models/namespace.rb11
-rw-r--r--app/models/namespace/root_storage_statistics.rb30
-rw-r--r--app/models/namespace_statistics.rb60
-rw-r--r--app/models/namespaces/sync_event.rb4
-rw-r--r--app/models/namespaces/traversal/linear.rb11
-rw-r--r--app/models/namespaces/traversal/linear_scopes.rb22
-rw-r--r--app/models/namespaces/traversal/recursive_scopes.rb5
-rw-r--r--app/models/namespaces/user_namespace.rb4
-rw-r--r--app/models/note.rb27
-rw-r--r--app/models/packages/package.rb2
-rw-r--r--app/models/packages/package_file.rb21
-rw-r--r--app/models/pages_domain.rb4
-rw-r--r--app/models/personal_access_token.rb5
-rw-r--r--app/models/preloaders/single_hierarchy_project_group_plans_preloader.rb17
-rw-r--r--app/models/preloaders/users_max_access_level_in_projects_preloader.rb46
-rw-r--r--app/models/project.rb85
-rw-r--r--app/models/project_import_state.rb6
-rw-r--r--app/models/project_setting.rb12
-rw-r--r--app/models/project_team.rb4
-rw-r--r--app/models/projects/sync_event.rb4
-rw-r--r--app/models/projects/topic.rb23
-rw-r--r--app/models/resource_label_event.rb6
-rw-r--r--app/models/state_note.rb4
-rw-r--r--app/models/system_note_metadata.rb2
-rw-r--r--app/models/user.rb51
-rw-r--r--app/models/users/callout.rb5
-rw-r--r--app/models/users/group_callout.rb7
-rw-r--r--app/models/users_star_project.rb2
-rw-r--r--app/models/vulnerability.rb1
-rw-r--r--app/models/work_item.rb4
-rw-r--r--app/policies/ci/project_pipelines_policy.rb7
-rw-r--r--app/policies/ci/runner_policy.rb4
-rw-r--r--app/policies/group_policy.rb3
-rw-r--r--app/policies/note_policy.rb2
-rw-r--r--app/policies/project_policy.rb8
-rw-r--r--app/policies/work_item_policy.rb12
-rw-r--r--app/presenters/README.md8
-rw-r--r--app/presenters/alert_management/alert_presenter.rb2
-rw-r--r--app/presenters/blob_presenter.rb30
-rw-r--r--app/presenters/blobs/unfold_presenter.rb2
-rw-r--r--app/presenters/ci/pipeline_presenter.rb2
-rw-r--r--app/presenters/ci/runner_presenter.rb4
-rw-r--r--app/presenters/clusterable_presenter.rb4
-rw-r--r--app/presenters/clusters/cluster_presenter.rb2
-rw-r--r--app/presenters/merge_request_presenter.rb2
-rw-r--r--app/presenters/packages/conan/package_presenter.rb6
-rw-r--r--app/presenters/packages/detail/package_presenter.rb6
-rw-r--r--app/presenters/packages/npm/package_presenter.rb6
-rw-r--r--app/presenters/packages/nuget/presenter_helpers.rb11
-rw-r--r--app/presenters/packages/pypi/package_presenter.rb6
-rw-r--r--app/presenters/project_presenter.rb2
-rw-r--r--app/presenters/projects/import_export/project_export_presenter.rb5
-rw-r--r--app/presenters/projects/security/configuration_presenter.rb3
-rw-r--r--app/presenters/snippet_blob_presenter.rb2
-rw-r--r--app/serializers/analytics_summary_entity.rb1
-rw-r--r--app/serializers/codequality_degradation_entity.rb4
-rw-r--r--app/serializers/environment_serializer.rb14
-rw-r--r--app/serializers/group_child_entity.rb4
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb1
-rw-r--r--app/serializers/issue_sidebar_basic_entity.rb6
-rw-r--r--app/serializers/member_user_entity.rb1
-rw-r--r--app/serializers/merge_request_poll_cached_widget_entity.rb6
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb2
-rw-r--r--app/serializers/test_case_entity.rb2
-rw-r--r--app/services/alert_management/alerts/update_service.rb15
-rw-r--r--app/services/alert_management/create_alert_issue_service.rb13
-rw-r--r--app/services/audit_event_service.rb4
-rw-r--r--app/services/auth/container_registry_authentication_service.rb41
-rw-r--r--app/services/boards/base_item_move_service.rb4
-rw-r--r--app/services/boards/issues/move_service.rb4
-rw-r--r--app/services/branches/create_service.rb2
-rw-r--r--app/services/ci/after_requeue_job_service.rb10
-rw-r--r--app/services/ci/copy_cross_database_associations_service.rb11
-rw-r--r--app/services/ci/create_downstream_pipeline_service.rb6
-rw-r--r--app/services/ci/pipeline_schedule_service.rb2
-rw-r--r--app/services/ci/process_sync_events_service.rb15
-rw-r--r--app/services/ci/register_job_service.rb2
-rw-r--r--app/services/ci/register_runner_service.rb30
-rw-r--r--app/services/ci/retry_build_service.rb29
-rw-r--r--app/services/ci/unregister_runner_service.rb16
-rw-r--r--app/services/ci/update_build_queue_service.rb2
-rw-r--r--app/services/ci/update_runner_service.rb2
-rw-r--r--app/services/concerns/members/bulk_create_users.rb1
-rw-r--r--app/services/concerns/rate_limited_service.rb19
-rw-r--r--app/services/google_cloud/create_service_accounts_service.rb5
-rw-r--r--app/services/google_cloud/enable_cloud_run_service.rb34
-rw-r--r--app/services/google_cloud/generate_pipeline_service.rb79
-rw-r--r--app/services/groups/create_service.rb11
-rw-r--r--app/services/groups/update_statistics_service.rb28
-rw-r--r--app/services/incident_management/create_incident_label_service.rb22
-rw-r--r--app/services/incident_management/incidents/create_service.rb16
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/after_update_service.rb18
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb29
-rw-r--r--app/services/issuable/common_system_notes_service.rb2
-rw-r--r--app/services/issuable_base_service.rb13
-rw-r--r--app/services/issues/base_service.rb16
-rw-r--r--app/services/issues/close_service.rb4
-rw-r--r--app/services/issues/create_service.rb2
-rw-r--r--app/services/issues/move_service.rb17
-rw-r--r--app/services/issues/reorder_service.rb36
-rw-r--r--app/services/issues/set_crm_contacts_service.rb34
-rw-r--r--app/services/issues/update_service.rb35
-rw-r--r--app/services/loose_foreign_keys/batch_cleaner_service.rb52
-rw-r--r--app/services/members/create_service.rb12
-rw-r--r--app/services/members/creator_service.rb1
-rw-r--r--app/services/merge_requests/after_create_service.rb23
-rw-r--r--app/services/merge_requests/base_service.rb4
-rw-r--r--app/services/merge_requests/bulk_remove_attention_requested_service.rb10
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb2
-rw-r--r--app/services/merge_requests/rebase_service.rb4
-rw-r--r--app/services/merge_requests/squash_service.rb4
-rw-r--r--app/services/packages/maven/metadata/sync_service.rb6
-rw-r--r--app/services/projects/autocomplete_service.rb5
-rw-r--r--app/services/projects/container_repository/delete_tags_service.rb1
-rw-r--r--app/services/projects/create_service.rb4
-rw-r--r--app/services/projects/destroy_service.rb36
-rw-r--r--app/services/projects/import_export/export_service.rb7
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb4
-rw-r--r--app/services/projects/overwrite_project_service.rb108
-rw-r--r--app/services/projects/readme_renderer_service.rb27
-rw-r--r--app/services/projects/transfer_service.rb14
-rw-r--r--app/services/quick_actions/interpret_service.rb34
-rw-r--r--app/services/resource_events/change_state_service.rb2
-rw-r--r--app/services/security/ci_configuration/container_scanning_create_service.rb25
-rw-r--r--app/services/service_ping/build_payload_service.rb2
-rw-r--r--app/services/service_ping/submit_service.rb24
-rw-r--r--app/services/system_note_service.rb12
-rw-r--r--app/services/system_notes/alert_management_service.rb26
-rw-r--r--app/services/system_notes/incident_service.rb15
-rw-r--r--app/services/system_notes/issuables_service.rb29
-rw-r--r--app/services/task_list_toggle_service.rb2
-rw-r--r--app/services/test_hooks/base_service.rb2
-rw-r--r--app/services/update_container_registry_info_service.rb6
-rw-r--r--app/services/users/destroy_service.rb5
-rw-r--r--app/services/web_hook_service.rb39
-rw-r--r--app/services/work_items/create_service.rb22
-rw-r--r--app/services/work_items/delete_service.rb17
-rw-r--r--app/services/work_items/update_service.rb13
-rw-r--r--app/uploaders/import_export_uploader.rb4
-rw-r--r--app/validators/x509_certificate_credentials_validator.rb2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml1
-rw-r--r--app/views/admin/application_settings/_note_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_check.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_size_limit_setting_registration_features_cta.html.haml8
-rw-r--r--app/views/admin/application_settings/_usage.html.haml4
-rw-r--r--app/views/admin/application_settings/_users_api_limits.html.haml14
-rw-r--r--app/views/admin/application_settings/network.html.haml12
-rw-r--r--app/views/admin/application_settings/service_usage_data.html.haml16
-rw-r--r--app/views/admin/background_migrations/index.html.haml51
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml58
-rw-r--r--app/views/admin/dashboard/index.html.haml5
-rw-r--r--app/views/admin/groups/_group.html.haml2
-rw-r--r--app/views/admin/hooks/edit.html.haml2
-rw-r--r--app/views/admin/labels/_label.html.haml2
-rw-r--r--app/views/admin/projects/show.html.haml6
-rw-r--r--app/views/admin/runners/edit.html.haml2
-rw-r--r--app/views/admin/runners/show.html.haml2
-rw-r--r--app/views/admin/users/_access_levels.html.haml6
-rw-r--r--app/views/admin/users/_users.html.haml75
-rw-r--r--app/views/admin/users/projects.html.haml4
-rw-r--r--app/views/admin/users/show.html.haml2
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml2
-rw-r--r--app/views/clusters/clusters/show.html.haml2
-rw-r--r--app/views/dashboard/_projects_nav.html.haml2
-rw-r--r--app/views/dashboard/projects/_blank_state_admin_welcome.html.haml52
-rw-r--r--app/views/dashboard/projects/_blank_state_welcome.html.haml65
-rw-r--r--app/views/dashboard/projects/_zero_authorized_projects.html.haml23
-rw-r--r--app/views/dashboard/projects/index.html.haml1
-rw-r--r--app/views/devise/confirmations/almost_there.haml1
-rw-r--r--app/views/devise/registrations/new.html.haml1
-rw-r--r--app/views/devise/sessions/new.html.haml1
-rw-r--r--app/views/devise/shared/_signup_box.html.haml3
-rw-r--r--app/views/discussions/_diff_with_notes.html.haml2
-rw-r--r--app/views/discussions/_notes.html.haml4
-rw-r--r--app/views/doorkeeper/authorized_applications/_delete_form.html.haml2
-rw-r--r--app/views/groups/_home_panel.html.haml2
-rw-r--r--app/views/groups/_import_group_from_file_panel.html.haml5
-rw-r--r--app/views/groups/_invite_groups_modal.html.haml3
-rw-r--r--app/views/groups/_invite_members_modal.html.haml3
-rw-r--r--app/views/groups/group_members/index.html.haml5
-rw-r--r--app/views/groups/issues.html.haml2
-rw-r--r--app/views/groups/runners/index.html.haml3
-rw-r--r--app/views/groups/settings/_export.html.haml6
-rw-r--r--app/views/groups/settings/_general.html.haml16
-rw-r--r--app/views/groups/settings/_transfer.html.haml15
-rw-r--r--app/views/jira_connect/branches/new.html.haml2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml8
-rw-r--r--app/views/layouts/_bizible.html.haml14
-rw-r--r--app/views/layouts/_flash.html.haml3
-rw-r--r--app/views/layouts/_page.html.haml3
-rw-r--r--app/views/layouts/header/_default.html.haml24
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml1
-rw-r--r--app/views/layouts/header/_whats_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/nav/_classification_level_banner.html.haml4
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml9
-rw-r--r--app/views/profiles/accounts/_providers.html.haml2
-rw-r--r--app/views/projects/_bitbucket_import_modal.html.haml14
-rw-r--r--app/views/projects/_home_panel.html.haml10
-rw-r--r--app/views/projects/_import_project_pane.html.haml8
-rw-r--r--app/views/projects/_invite_groups_modal.html.haml3
-rw-r--r--app/views/projects/_merge_request_merge_checks_settings.html.haml4
-rw-r--r--app/views/projects/_merge_request_merge_commit_template.html.haml6
-rw-r--r--app/views/projects/_merge_request_merge_method_settings.html.haml6
-rw-r--r--app/views/projects/_merge_request_merge_suggestions_settings.html.haml2
-rw-r--r--app/views/projects/_merge_request_squash_commit_template.html.haml5
-rw-r--r--app/views/projects/_new_project_fields.html.haml48
-rw-r--r--app/views/projects/_new_project_initialize_with_sast.html.haml16
-rw-r--r--app/views/projects/_remove.html.haml3
-rw-r--r--app/views/projects/blob/_blob.html.haml3
-rw-r--r--app/views/projects/blob/_header_content.html.haml4
-rw-r--r--app/views/projects/branches/index.html.haml2
-rw-r--r--app/views/projects/ci/lints/show.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/compare/index.html.haml2
-rw-r--r--app/views/projects/edit.html.haml5
-rw-r--r--app/views/projects/environments/index.html.haml2
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/hooks/edit.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml4
-rw-r--r--app/views/projects/issues/_new_branch.html.haml4
-rw-r--r--app/views/projects/learn_gitlab/index.html.haml3
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml2
-rw-r--r--app/views/projects/no_repo.html.haml2
-rw-r--r--app/views/projects/notes/_actions.html.haml30
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml2
-rw-r--r--app/views/projects/pages/_pages_settings.html.haml15
-rw-r--r--app/views/projects/pages_domains/_dns.html.haml7
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml2
-rw-r--r--app/views/projects/pipelines/_info.html.haml2
-rw-r--r--app/views/projects/pipelines/show.html.haml1
-rw-r--r--app/views/projects/project_members/index.html.haml7
-rw-r--r--app/views/projects/protected_branches/shared/_protected_branch.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_protected_tag.html.haml2
-rw-r--r--app/views/projects/readme_templates/default.md.tt93
-rw-r--r--app/views/projects/security/configuration/show.html.haml4
-rw-r--r--app/views/projects/serverless/functions/index.html.haml2
-rw-r--r--app/views/projects/services/_form.html.haml8
-rw-r--r--app/views/projects/settings/_archive.html.haml4
-rw-r--r--app/views/projects/settings/_general.html.haml3
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/projects/settings/operations/show.html.haml15
-rw-r--r--app/views/projects/starrers/index.html.haml18
-rw-r--r--app/views/projects/tags/index.html.haml3
-rw-r--r--app/views/projects/tracings/show.html.haml15
-rw-r--r--app/views/projects/triggers/_trigger.html.haml2
-rw-r--r--app/views/projects/usage_quotas/index.html.haml11
-rw-r--r--app/views/registrations/welcome/show.html.haml1
-rw-r--r--app/views/shared/_confirm_fork_modal.html.haml12
-rw-r--r--app/views/shared/_gl_toggle.html.haml28
-rw-r--r--app/views/shared/_global_alert.html.haml3
-rw-r--r--app/views/shared/_group_form.html.haml22
-rw-r--r--app/views/shared/_issues.html.haml2
-rw-r--r--app/views/shared/_registration_features_discovery_message.html.haml7
-rw-r--r--app/views/shared/_repository_size_limit_setting_registration_features_cta.html.haml9
-rw-r--r--app/views/shared/_web_ide_button.html.haml9
-rw-r--r--app/views/shared/access_tokens/_table.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml2
-rw-r--r--app/views/shared/hook_logs/_content.html.haml2
-rw-r--r--app/views/shared/icons/_icon_resolve_discussion.svg1
-rw-r--r--app/views/shared/icons/_icon_status_success_solid.svg1
-rw-r--r--app/views/shared/icons/_mr_widget_empty_state.svg2
-rw-r--r--app/views/shared/integrations/_form.html.haml4
-rw-r--r--app/views/shared/integrations/edit.html.haml5
-rw-r--r--app/views/shared/issuable/_assignees.html.haml7
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--app/views/shared/issuable/_merge_request_assignees.html.haml8
-rw-r--r--app/views/shared/issuable/_merge_request_reviewers.html.haml8
-rw-r--r--app/views/shared/issuable/_reviewers.html.haml7
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml14
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml5
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/form/_title.html.haml6
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml2
-rw-r--r--app/views/shared/members/_access_request_links.html.haml3
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/planning_hierarchy.html.haml5
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml2
-rw-r--r--app/views/users/_overview.html.haml3
-rw-r--r--app/views/users/show.html.haml6
-rw-r--r--app/views/users/terms/index.html.haml1
-rw-r--r--app/workers/all_queues.yml75
-rw-r--r--app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb1
-rw-r--r--app/workers/auto_devops/disable_worker.rb8
-rw-r--r--app/workers/background_migration/ci_database_worker.rb11
-rw-r--r--app/workers/background_migration/single_database_worker.rb14
-rw-r--r--app/workers/background_migration_worker.rb4
-rw-r--r--app/workers/ci/delete_objects_worker.rb8
-rw-r--r--app/workers/concerns/application_worker.rb19
-rw-r--r--app/workers/container_expiration_policy_worker.rb2
-rw-r--r--app/workers/container_registry/migration/enqueuer_worker.rb116
-rw-r--r--app/workers/container_registry/migration/guard_worker.rb101
-rw-r--r--app/workers/container_registry/migration/observer_worker.rb40
-rw-r--r--app/workers/expire_job_cache_worker.rb2
-rw-r--r--app/workers/groups/update_statistics_worker.rb29
-rw-r--r--app/workers/hashed_storage/migrator_worker.rb3
-rw-r--r--app/workers/hashed_storage/project_migrate_worker.rb3
-rw-r--r--app/workers/hashed_storage/project_rollback_worker.rb3
-rw-r--r--app/workers/hashed_storage/rollbacker_worker.rb3
-rw-r--r--app/workers/loose_foreign_keys/cleanup_worker.rb2
-rw-r--r--app/workers/merge_requests/update_head_pipeline_worker.rb1
-rw-r--r--app/workers/namespaces/process_sync_events_worker.rb8
-rw-r--r--app/workers/namespaces/update_root_statistics_worker.rb17
-rw-r--r--app/workers/pages_update_configuration_worker.rb17
-rw-r--r--app/workers/pipeline_schedule_worker.rb2
-rw-r--r--app/workers/project_export_worker.rb15
-rw-r--r--app/workers/projects/git_garbage_collect_worker.rb10
-rw-r--r--app/workers/projects/process_sync_events_worker.rb8
-rw-r--r--app/workers/run_pipeline_schedule_worker.rb2
-rw-r--r--app/workers/web_hook_worker.rb16
-rwxr-xr-xbin/feature-flag16
-rwxr-xr-xbin/metrics-server3
-rw-r--r--config/application.rb12
-rw-r--r--config/events/1643968255_projectsnew_select_deployment_target.yml20
-rw-r--r--config/events/202109151015_notes__create_service_execute.yml2
-rw-r--r--config/events/20211215022206_default_review_app_open_review_app.yml2
-rw-r--r--config/feature_flags/development/admin_application_settings_service_usage_data_center.yml (renamed from config/feature_flags/development/api_caching_rate_limit_branches.yml)10
-rw-r--r--config/feature_flags/development/artifacts_management_page.yml2
-rw-r--r--config/feature_flags/development/auto_devops_banner_disabled.yml2
-rw-r--r--config/feature_flags/development/ban_user_feature_flag.yml2
-rw-r--r--config/feature_flags/development/block_external_fork_network_mirrors.yml8
-rw-r--r--config/feature_flags/development/bulk_expire_project_artifacts.yml2
-rw-r--r--config/feature_flags/development/cache_shared_runners_enabled.yml2
-rw-r--r--config/feature_flags/development/ci_bulk_insert_tags.yml2
-rw-r--r--config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml2
-rw-r--r--config/feature_flags/development/ci_enable_live_trace.yml2
-rw-r--r--config/feature_flags/development/ci_order_subsequent_jobs_by_stage.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_queue_source.yml2
-rw-r--r--config/feature_flags/development/ci_pipeline_merge_request_presence_check.yml (renamed from config/feature_flags/development/ci_delete_objects_medium_concurrency.yml)10
-rw-r--r--config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml8
-rw-r--r--config/feature_flags/development/ci_secure_files.yml (renamed from config/feature_flags/development/deployment_approvals.yml)10
-rw-r--r--config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml2
-rw-r--r--config/feature_flags/development/ci_skip_require_credit_card_for_addon_ci_minutes.yml8
-rw-r--r--config/feature_flags/development/ci_update_unlocked_job_artifacts.yml2
-rw-r--r--config/feature_flags/development/ci_variables_builder_memoize_secret_variables.yml (renamed from config/feature_flags/development/ci_delete_objects_high_concurrency.yml)8
-rw-r--r--config/feature_flags/development/cluster_vulnerabilities.yml2
-rw-r--r--config/feature_flags/development/contacts_autocomplete.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_limit_gitlab_org.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_capacity_1.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_capacity_10.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_capacity_25.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_enabled.yml (renamed from config/feature_flags/development/container_registry_cdn_redirect.yml)8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_fast.yml8
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_slow.yml8
-rw-r--r--config/feature_flags/development/create_deployment_in_separate_transaction.yml8
-rw-r--r--config/feature_flags/development/custom_preloader_for_deployments.yml8
-rw-r--r--config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml2
-rw-r--r--config/feature_flags/development/enforce_auth_checks_on_uploads.yml (renamed from config/feature_flags/development/early_prepare_for_mergeability.yml)8
-rw-r--r--config/feature_flags/development/enforce_runner_token_expires_at.yml (renamed from config/feature_flags/development/ci_find_runners_by_ci_mirrors.yml)8
-rw-r--r--config/feature_flags/development/enforce_security_report_validation.yml (renamed from config/feature_flags/development/security_finding_build_disable_joins.yml)10
-rw-r--r--config/feature_flags/development/export_reduce_relation_batch_size.yml8
-rw-r--r--config/feature_flags/development/force_no_sharing_primary_model.yml8
-rw-r--r--config/feature_flags/development/geo_token_user_authentication.yml8
-rw-r--r--config/feature_flags/development/git_push_create_all_pipelines.yml2
-rw-r--r--config/feature_flags/development/github_importer_use_diff_note_with_suggestions.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_queuing_metrics.yml2
-rw-r--r--config/feature_flags/development/gitlab_shell_upload_pack_sidechannel.yml8
-rw-r--r--config/feature_flags/development/group_project_api_preload_plans.yml (renamed from config/feature_flags/development/linear_mirrors_worker_roots.yml)6
-rw-r--r--config/feature_flags/development/header_read_timeout_buffered_io.yml (renamed from config/feature_flags/development/vue_integration_form.yml)8
-rw-r--r--config/feature_flags/development/hide_public_email_on_profile.yml8
-rw-r--r--config/feature_flags/development/import_project_from_remote_file.yml2
-rw-r--r--config/feature_flags/development/import_redis_increment_by.yml8
-rw-r--r--config/feature_flags/development/incident_escalations.yml2
-rw-r--r--config/feature_flags/development/invite_members_group_modal.yml2
-rw-r--r--config/feature_flags/development/issue_boards_filtered_search.yml2
-rw-r--r--config/feature_flags/development/jobs_tab_vue.yml2
-rw-r--r--config/feature_flags/development/json_limited_encoder.yml8
-rw-r--r--config/feature_flags/development/lfk_fair_queueing.yml (renamed from config/feature_flags/development/ci_namespace_project_mirrors.yml)8
-rw-r--r--config/feature_flags/development/lfs_auto_link_fork_source.yml8
-rw-r--r--config/feature_flags/development/linear_group_descendants_finder_upto.yml (renamed from config/feature_flags/development/ci_decompose_for_namespace_monthly_usage_query.yml)10
-rw-r--r--config/feature_flags/development/loose_foreign_key_cleanup.yml8
-rw-r--r--config/feature_flags/development/markdown_continue_lists.yml (renamed from config/feature_flags/development/tribute_autocomplete.yml)8
-rw-r--r--config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml2
-rw-r--r--config/feature_flags/development/mr_changes_fluid_layout.yml8
-rw-r--r--config/feature_flags/development/new_route_ci_minutes_purchase.yml8
-rw-r--r--config/feature_flags/development/notes_create_service_tracking.yml4
-rw-r--r--config/feature_flags/development/omniauth_login_minimal_scopes.yml8
-rw-r--r--config/feature_flags/development/overage_members_modal.yml (renamed from config/feature_flags/development/new_route_storage_purchase.yml)8
-rw-r--r--config/feature_flags/development/packages_installable_package_files.yml8
-rw-r--r--config/feature_flags/development/permit_all_shared_groups_for_approval.yml (renamed from config/feature_flags/development/check_mergeability_async_in_widget.yml)8
-rw-r--r--config/feature_flags/development/prohibit_hexadecimal_branch_names.yml8
-rw-r--r--config/feature_flags/development/project_import_schedule_worker_job_tracker.yml8
-rw-r--r--config/feature_flags/development/project_overwrite_service_tracking.yml2
-rw-r--r--config/feature_flags/development/prometheus_computed_alerts.yml2
-rw-r--r--config/feature_flags/development/publish_project_deleted_event.yml8
-rw-r--r--config/feature_flags/development/rate_limit_gitlab_shell.yml2
-rw-r--r--config/feature_flags/development/read_from_vulnerability_finding_evidence.yml8
-rw-r--r--config/feature_flags/development/rearrange_pipelines_table.yml (renamed from config/feature_flags/development/ci_use_variables_builder_definitions.yml)10
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_jobs_build.yml8
-rw-r--r--config/feature_flags/development/remove_import_data_on_failure.yml (renamed from config/feature_flags/development/api_caching_merge_requests.yml)8
-rw-r--r--config/feature_flags/development/roadmap_settings.yml (renamed from config/feature_flags/development/ci_preload_runner_tags.yml)10
-rw-r--r--config/feature_flags/development/runner_read_only_admin_view.yml2
-rw-r--r--config/feature_flags/development/s3_multithreaded_uploads.yml2
-rw-r--r--config/feature_flags/development/security_report_ingestion_framework.yml4
-rw-r--r--config/feature_flags/development/settings_operations_prometheus_service.yml2
-rw-r--r--config/feature_flags/development/skip_scheduling_workers_for_replicas.yml8
-rw-r--r--config/feature_flags/development/strong_parameters_for_project_controller.yml (renamed from config/feature_flags/development/api_caching_tags.yml)8
-rw-r--r--config/feature_flags/development/sync_traversal_ids_before_commit.yml8
-rw-r--r--config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml8
-rw-r--r--config/feature_flags/development/update_all_mirrors_job_tracker.yml8
-rw-r--r--config/feature_flags/development/usage_data_diff_searches.yml (renamed from config/feature_flags/development/diff_searching_usage_data.yml)2
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_jetbrains_api_request.yml (renamed from config/feature_flags/development/diffs_virtual_scrolling.yml)6
-rw-r--r--config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml2
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_descendants_scopes.yml (renamed from config/feature_flags/development/api_caching_rate_limit_repository_compare.yml)10
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_self_and_hierarchy_scopes.yml8
-rw-r--r--config/feature_flags/development/vulnerability_report_pagination.yml8
-rw-r--r--config/feature_flags/experiment/new_project_readme_content.yml8
-rw-r--r--config/feature_flags/experiment/redirect_trial_user_to_feature.yml8
-rw-r--r--config/feature_flags/experiment/require_verification_for_group_creation.yml8
-rw-r--r--config/feature_flags/ops/elastic_migration_worker.yml (renamed from config/feature_flags/development/track_geo_proxy_events.yml)12
-rw-r--r--config/feature_flags/ops/legacy_open_source_license_available.yml8
-rw-r--r--config/feature_flags/ops/prometheus_notify_max_alerts.yml2
-rw-r--r--config/feature_flags/ops/show_gitlab_agent_feedback.yml (renamed from config/feature_flags/development/grape_gitlab_json.yml)10
-rw-r--r--config/gitlab.yml.example22
-rw-r--r--config/gitlab_loose_foreign_keys.yml (renamed from lib/gitlab/database/gitlab_loose_foreign_keys.yml)223
-rw-r--r--config/helpers/incremental_webpack_compiler/compiler.js24
-rw-r--r--config/initializers/1_settings.rb10
-rw-r--r--config/initializers/7_prometheus_metrics.rb7
-rw-r--r--config/initializers/console_message.rb22
-rw-r--r--config/initializers/gitlab_experiment.rb32
-rw-r--r--config/initializers/google_api_client.rb11
-rw-r--r--config/initializers/google_api_client_patch.rb67
-rw-r--r--config/initializers/postgres_partitioning.rb8
-rw-r--r--config/initializers/request_profiler.rb1
-rw-r--r--config/initializers/rspec_profiling.rb2
-rw-r--r--config/initializers/rubyzip.rb4
-rw-r--r--config/initializers_before_autoloader/004_zeitwerk.rb2
-rw-r--r--config/metrics/aggregates/code_review.yml2
-rw-r--r--config/metrics/aggregates/common.yml2
-rw-r--r--config/metrics/counts_28d/20210201124930_deployments.yml2
-rw-r--r--config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210216182125_user_sast_jobs.yml23
-rw-r--r--config/metrics/counts_28d/20210216182127_user_secret_detection_jobs.yml23
-rw-r--r--config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_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/20210413205507_i_testing_summary_widget_total_monthly.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/20210514013545_i_code_review_user_resolve_conflict_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210902191057_i_quickactions_unapprove_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20211216083832_users_clicking_license_testing_visiting_external_website_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20220121140644_user_jetbrains_api_request_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20220131143209_i_quickactions_attention_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220131153230_i_quickactions_remove_attention_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_dependency_scanning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_license_scanning_monthly.yml25
-rw-r--r--config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml5
-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/20210413205507_i_testing_summary_widget_total_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml1
-rw-r--r--config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml1
-rw-r--r--config/metrics/counts_7d/20210902191054_i_quickactions_unapprove_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20211216084934_users_clicking_license_testing_visiting_external_website_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20220121140634_user_jetbrains_api_request_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20220131143201_i_quickactions_attention_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220131153223_i_quickactions_remove_attention_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_dependency_scanning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_license_scanning_weekly.yml25
-rw-r--r--config/metrics/counts_all/20210216175206_merged_merge_requests_using_approval_rules.yml21
-rw-r--r--config/metrics/counts_all/20210216180451_incident_labeled_issues.yml3
-rw-r--r--config/metrics/counts_all/20210216182116_user_sast_jobs.yml20
-rw-r--r--config/metrics/counts_all/20210216182118_user_secret_detection_jobs.yml20
-rw-r--r--config/metrics/counts_all/20210216183023_wiki_pages_view.yml1
-rw-r--r--config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml1
-rw-r--r--config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml1
-rw-r--r--config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml2
-rw-r--r--config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml1
-rw-r--r--config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml1
-rw-r--r--config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml1
-rw-r--r--config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml1
-rw-r--r--config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml1
-rw-r--r--config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml2
-rw-r--r--config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml2
-rw-r--r--config/metrics/counts_all/20220122022215_web_ide_previews_success.yml21
-rw-r--r--config/metrics/settings/20210323120839_topology.yml2
-rw-r--r--config/routes.rb1
-rw-r--r--config/routes/admin.rb2
-rw-r--r--config/routes/project.rb12
-rw-r--r--config/sidekiq_queues.yml18
-rw-r--r--config/webpack.config.js53
-rw-r--r--config/webpack.vendor.config.js2
-rw-r--r--danger/sidekiq_queues/Dangerfile2
-rw-r--r--data/deprecations/14-0-nfs-fot-git-repository-storage.yml2
-rw-r--r--data/deprecations/14-3-repository-push-audit-events.yml4
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml18
-rw-r--r--data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml2
-rw-r--r--data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml2
-rw-r--r--data/deprecations/14-5-deprecate-sles-12sp2.yml2
-rw-r--r--data/deprecations/14-5-deprecation-versions-packagetype.yml2
-rw-r--r--data/deprecations/14-5-geo-deprecate-promote-db.yml2
-rw-r--r--data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml2
-rw-r--r--data/deprecations/14-5-remove-dependency-proxy-permissions-flag.yml2
-rw-r--r--data/deprecations/14-5-remove-pipelines-from-version-field.yml2
-rw-r--r--data/deprecations/14-5-runner-api-status-does-contain-paused.yml4
-rw-r--r--data/deprecations/14-6-deprecate-types.yml2
-rw-r--r--data/deprecations/14-6-deprecation-license-compliance-api-terms.yml2
-rw-r--r--data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml2
-rw-r--r--data/deprecations/14-6-pipeline-fields-package-deprecation.yml2
-rw-r--r--data/deprecations/14-6-runner-api-status-renames-not_connected.yml2
-rw-r--r--data/deprecations/14-7-deprecate-artifacts-keyword.yml2
-rw-r--r--data/deprecations/14-7-deprecate-merged_by-api-field.yml2
-rw-r--r--data/deprecations/14-7-deprecate-static-site-editor.yml2
-rw-r--r--data/deprecations/14-8-Elasticsearch-6-8.yml18
-rw-r--r--data/deprecations/14-8-ci-build-variables.yml16
-rw-r--r--data/deprecations/14-8-compliance-required-pipeline-configuration-premium.yml16
-rw-r--r--data/deprecations/14-8-compliance-status-check-api-field.yml25
-rw-r--r--data/deprecations/14-8-deprecate-projectFingerprint-from-PipelineSecurityReportFinding-GraphQL.yml19
-rw-r--r--data/deprecations/14-8-deprecation-secure-dependency-scanning-retire-js.yml17
-rw-r--r--data/deprecations/14-8-enforce-pat-expiration.yml13
-rw-r--r--data/deprecations/14-8-enforce-ssh-expiration.yml13
-rw-r--r--data/deprecations/14-8-geo-deprecate-db-rake-tasks.yml34
-rw-r--r--data/deprecations/14-8-geo-deprecate-replication-detail-routes.yml15
-rw-r--r--data/deprecations/14-8-gitaly-deprecate-legacy-config-options.yml20
-rw-r--r--data/deprecations/14-8-gitaly-remove-per-repository-election.yml19
-rw-r--r--data/deprecations/14-8-graphql-ids.yml66
-rw-r--r--data/deprecations/14-8-grpc-proxy.yml26
-rw-r--r--data/deprecations/14-8-iteration-started-field.yml15
-rw-r--r--data/deprecations/14-8-nfs_support.yml28
-rw-r--r--data/deprecations/14-8-protect-cns-chs.yml20
-rw-r--r--data/deprecations/14-8-protect-vulnerability-check.yml18
-rw-r--r--data/deprecations/14-8-remove_ff_push_rules_supersede_code_owners.yml16
-rw-r--r--data/deprecations/14-8-request-profiling.yml19
-rw-r--r--data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml33
-rw-r--r--data/deprecations/14-8-runner-api-project_type-breaking-change.yml15
-rw-r--r--data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml18
-rw-r--r--data/deprecations/14-8-sast-analyzer-removals.yml32
-rw-r--r--data/deprecations/14-8-sast-dotnet-21.yml31
-rw-r--r--data/deprecations/14-8-sast-secret-analyzer-image.yml27
-rw-r--r--data/deprecations/14-8-sast-spotbugs-java-8.yml24
-rw-r--r--data/deprecations/14-8-secret-detection-configurations.yml28
-rw-r--r--data/deprecations/14-8-secure-ca-python-deprecation.yml33
-rw-r--r--data/deprecations/14-9-deprecate-testcoveragesetting.yml14
-rw-r--r--data/deprecations/15-0-deprecate-monitor-tracing.yml1
-rw-r--r--data/deprecations/15-0-instance-statistics-graphql-node-removal.yml13
-rw-r--r--data/deprecations/15-0-oauth-noexpiry.yml24
-rw-r--r--data/deprecations/15-0-oauth.yml15
-rw-r--r--data/deprecations/JTW_v2_update.yml28
-rw-r--r--data/deprecations/data/deprecations/14-9-secure-and-protect-analyzer-bump.yml.yml44
-rw-r--r--data/deprecations/templates/_deprecation_template.md.erb4
-rw-r--r--data/deprecations/templates/example.yml27
-rw-r--r--data/removals/14_0/14_0-ds-deprecations.yml3
-rw-r--r--data/removals/14_0/14_0-lc-deprecations.yml3
-rw-r--r--data/removals/14_0/change_default_branch_name_to_main.yml1
-rw-r--r--data/removals/14_0/create-code-review-draft-wip.yml1
-rw-r--r--data/removals/14_0/create-code-review-w-parameter-removal.yml3
-rw-r--r--data/removals/14_0/deprecate_ci_project_config_path_variable.yml6
-rw-r--r--data/removals/14_0/deprecation_bump_terraform_template_version.yml3
-rw-r--r--data/removals/14_0/deprecation_manage_access_14_0.yml6
-rw-r--r--data/removals/14_0/deprecation_update_cicd_templates_to_stop_using_hardcode_master.yml3
-rw-r--r--data/removals/14_0/deuley_servicetemplates_removal.yml3
-rw-r--r--data/removals/14_0/release_announce_deprecation_of_release_notes_api.yml3
-rw-r--r--data/removals/14_0/release_deprecation_auto-deploy-image.yml5
-rw-r--r--data/removals/14_0/release_domainsource_configuration_for_gitlab_pages_deprecation.yml3
-rw-r--r--data/removals/14_0/release_legacy_feature_flags_deprecation.yml3
-rw-r--r--data/removals/14_0/release_remove_redundant_keyvalue_pair_from_the_payload_of_dora.yml3
-rw-r--r--data/removals/14_0/removal-geo-fdw-settings.yml3
-rw-r--r--data/removals/14_0/removal-graphql-fields.yml3
-rw-r--r--data/removals/14_0/removal-legacy-storage.yml3
-rw-r--r--data/removals/14_0/removal-protect-features.yml2
-rw-r--r--data/removals/14_0/removal-sidekiq_experimental_queue_selector.yml3
-rw-r--r--data/removals/14_0/removal-unicorn.yml3
-rw-r--r--data/removals/14_0/removal_ci_project_config_path.yml3
-rw-r--r--data/removals/14_0/removal_enablement_helm2.yml1
-rw-r--r--data/removals/14_0/removal_enablement_opensuse_15_1.yml1
-rw-r--r--data/removals/14_0/removal_enablement_pg11.yml1
-rw-r--r--data/removals/14_0/removal_enablement_ubuntu_16.yml1
-rw-r--r--data/removals/14_0/removal_repost_static_analysis_notices.yml11
-rw-r--r--data/removals/14_0/removal_runner_25555.yml3
-rw-r--r--data/removals/14_0/removal_runner_26036.yml3
-rw-r--r--data/removals/14_0/removal_runner_26419.yml1
-rw-r--r--data/removals/14_0/removal_runner_4845.yml1
-rw-r--r--data/removals/14_0/removal_runner_6413.yml3
-rw-r--r--data/removals/14_0/removals-14-testing-team.yml3
-rw-r--r--data/removals/14_0/removals_runner_26651.yml3
-rw-r--r--data/removals/14_0/removals_runner_26679.yml3
-rw-r--r--data/removals/14_0/removals_runner_26900.yml3
-rw-r--r--data/removals/14_0/removals_runner_27175.yml3
-rw-r--r--data/removals/14_0/removals_runner_27218.yml1
-rw-r--r--data/removals/14_0/removals_runner_27551.yml3
-rw-r--r--data/removals/14_0/removals_runner_27899.yml3
-rw-r--r--data/removals/14_0/remove-sql-elector.yml3
-rw-r--r--data/removals/14_0/remove_dast_env_variables.yml1
-rw-r--r--data/removals/14_0/remove_dast_legacy_domain_validation.yml3
-rw-r--r--data/removals/14_0/remove_dast_legacy_report_fields.yml3
-rw-r--r--data/removals/14_0/remove_dast_spider_host_reset.yml1
-rw-r--r--data/removals/14_0/remove_dast_template_stages.yml3
-rw-r--r--data/removals/14_0/remove_optimize_api.yml3
-rw-r--r--data/removals/14_0/remove_terraform_template.yml1
-rw-r--r--data/removals/14_0/verify-ci-removal-parametertrace.yml3
-rw-r--r--data/removals/14_0/verify-ci-removalpipelineservice.yml1
-rw-r--r--data/removals/14_1/removal-memory-prometheus-options-source.yml1
-rw-r--r--data/removals/14_1/removal-outdated-browser-support.yml1
-rw-r--r--data/removals/14_2/removal-verify-build-log.yml1
-rw-r--r--data/removals/14_3/removal-limit-tags-to-50.yml3
-rw-r--r--data/removals/14_3/removal-verify-pe-pipelinefindername.yml1
-rw-r--r--data/removals/14_3/removal_legacy_storage_setting.yml1
-rw-r--r--data/removals/14_6/limit_trigger_pipelines.yml6
-rw-r--r--data/removals/14_6/removal-release-cli-s3.yml6
-rw-r--r--data/removals/templates/_removal_template.md.erb1
-rw-r--r--data/removals/templates/example.yml27
-rw-r--r--data/whats_new/2021111800001_14_05.yml2
-rw-r--r--db/migrate/20210316171009_create_packages_helm_file_metadata.rb8
-rw-r--r--db/migrate/20210504153354_create_clusters_integration_elasticstack.rb8
-rw-r--r--db/migrate/20210628154900_create_detached_partitions_table.rb8
-rw-r--r--db/migrate/20210720140841_create_postgres_async_indexes_table.rb8
-rw-r--r--db/migrate/20210729081351_create_topics.rb8
-rw-r--r--db/migrate/20210811193033_add_unique_index_to_vulnerability_finding_links.rb12
-rw-r--r--db/migrate/20211119111006_create_job_artifact_states.rb32
-rw-r--r--db/migrate/20211122103051_add_line_code_to_draft_notes.rb10
-rw-r--r--db/migrate/20211123135255_create_batched_background_migration_job_transition_logs.rb38
-rw-r--r--db/migrate/20211124095704_add_draft_notes_line_code_text_limit.rb13
-rw-r--r--db/migrate/20220105082217_add_verification_token_to_external_ae_destinations.rb13
-rw-r--r--db/migrate/20220106111958_add_insert_or_update_vulnerability_reads_trigger.rb58
-rw-r--r--db/migrate/20220106112043_add_update_vulnerability_reads_trigger.rb40
-rw-r--r--db/migrate/20220106112085_add_update_vulnerability_reads_location_trigger.rb41
-rw-r--r--db/migrate/20220106163326_add_has_issues_on_vulnerability_reads_trigger.rb79
-rw-r--r--db/migrate/20220111154950_add_token_expires_at_to_ci_runners.rb7
-rw-r--r--db/migrate/20220111154951_add_index_to_ci_runners_token_expires_at.rb15
-rw-r--r--db/migrate/20220117082611_add_text_limit_to_exad_verification_tokens.rb13
-rw-r--r--db/migrate/20220118015633_add_url_text_to_issuable_metric_images.rb10
-rw-r--r--db/migrate/20220118020026_add_url_text_limit_to_issuable_metric_images.rb13
-rw-r--r--db/migrate/20220119094023_add_unique_index_to_aed_verification_token.rb15
-rw-r--r--db/migrate/20220119141407_add_dependency_proxy_size_to_namespace_statistics.rb7
-rw-r--r--db/migrate/20220119144253_add_dependency_proxy_size_to_namespace_root_storage_statistics.rb7
-rw-r--r--db/migrate/20220119170426_remove_temporary_vulnerability_occurrences_deduplication_index.rb20
-rw-r--r--db/migrate/20220119220620_add_scan_method_to_dast_site_profile.rb11
-rw-r--r--db/migrate/20220120033115_create_alert_management_alert_metric_images.rb18
-rw-r--r--db/migrate/20220120085655_add_ci_runner_project_index_to_runner_id_and_project_id.rb19
-rw-r--r--db/migrate/20220125084127_add_cleanup_attempts_to_loose_foreign_keys_deleted_records.rb13
-rw-r--r--db/migrate/20220125122228_add_topics_non_private_projects_count.rb11
-rw-r--r--db/migrate/20220125122725_add_topics_non_private_projects_count_index.rb15
-rw-r--r--db/migrate/20220125230538_add_compound_index_on_project_id_and_id_for_vulnerabilities.rb15
-rw-r--r--db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb10
-rw-r--r--db/migrate/20220128194722_add_index_on_migration_state_and_import_done_at_to_container_repositories.rb14
-rw-r--r--db/migrate/20220131135725_add_severity_level_to_merge_requests_compliance_violations.rb7
-rw-r--r--db/migrate/20220131192643_add_show_diff_preview_in_email_to_project_settings.rb9
-rw-r--r--db/migrate/20220201205300_remove_index_for_vulnerability_occurrences.rb17
-rw-r--r--db/migrate/20220202034409_add_tmp_index_on_id_and_migration_state_to_container_repositories.rb16
-rw-r--r--db/migrate/20220202115350_add_migration_indexes_to_container_repositories.rb21
-rw-r--r--db/migrate/20220203123333_add_batched_migration_max_batch.rb7
-rw-r--r--db/migrate/20220203133652_add_legacy_open_source_license_available_to_project_settings.rb9
-rw-r--r--db/migrate/20220204154220_add_index_on_greatest_done_at_to_container_repositories.rb17
-rw-r--r--db/migrate/20220207083129_add_users_get_by_id_limit_to_application_setting.rb15
-rw-r--r--db/migrate/20220208170445_add_not_valid_foreign_key_to_ci_builds_runner_id.rb15
-rw-r--r--db/migrate/20220208171826_update_default_scan_method_of_dast_site_profile.rb24
-rw-r--r--db/migrate/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe.rb36
-rw-r--r--db/post_migrate/20210415155043_move_container_registry_enabled_to_project_features3.rb1
-rw-r--r--db/post_migrate/20210525075724_clean_up_pending_builds_table.rb2
-rw-r--r--db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb2
-rw-r--r--db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb10
-rw-r--r--db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb15
-rw-r--r--db/post_migrate/20211209103048_backfill_project_namespaces_for_group.rb42
-rw-r--r--db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb15
-rw-r--r--db/post_migrate/20220106185033_remove_finding_evidence_summary.rb15
-rw-r--r--db/post_migrate/20220107064845_populate_vulnerability_reads.rb25
-rw-r--r--db/post_migrate/20220111093534_remove_index_on_auto_stop_in.rb17
-rw-r--r--db/post_migrate/20220111101421_remove_index_on_merge_request_id.rb17
-rw-r--r--db/post_migrate/20220113111440_schedule_fix_incorrect_max_seats_used.rb20
-rw-r--r--db/post_migrate/20220117034056_remove_index_cluster_agent_tokens_on_agent_id_and_last_used_at.rb15
-rw-r--r--db/post_migrate/20220118204039_self_managed_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb29
-rw-r--r--db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb19
-rw-r--r--db/post_migrate/20220119143130_remove_projects_ci_sources_pipelines_source_project_id_fk.rb17
-rw-r--r--db/post_migrate/20220119144458_remove_users_ci_triggers_owner_id_fk.rb17
-rw-r--r--db/post_migrate/20220119151221_remove_merge_requests_ci_pipelines_merge_request_id_fk.rb19
-rw-r--r--db/post_migrate/20220119153706_remove_ci_pipelines_merge_trains_pipeline_id_fk.rb17
-rw-r--r--db/post_migrate/20220119154442_remove_ci_pipelines_merge_requests_head_pipeline_id_fk.rb17
-rw-r--r--db/post_migrate/20220119193130_remove_ci_pipelines_dast_profiles_pipelines_ci_pipeline_id_fk.rb17
-rw-r--r--db/post_migrate/20220119201340_remove_ci_pipelines_vulnerability_statistics_latest_pipeline_id_fk.rb17
-rw-r--r--db/post_migrate/20220119203119_remove_ci_pipelines_vulnerability_occurrence_pipelines_pipeline_id_fk.rb17
-rw-r--r--db/post_migrate/20220120094340_drop_position_from_security_findings.rb9
-rw-r--r--db/post_migrate/20220120123700_add_tmp_index_routes_id_for_namespaces.rb17
-rw-r--r--db/post_migrate/20220120123800_backfill_namespace_id_for_namespace_routes.rb27
-rw-r--r--db/post_migrate/20220121214752_remove_projects_ci_stages_project_id_fk.rb20
-rw-r--r--db/post_migrate/20220121214753_re_remove_projects_ci_stages_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220121221651_remove_projects_ci_variables_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124130028_dedup_runner_projects.rb71
-rw-r--r--db/post_migrate/20220124145019_remove_projects_external_pull_requests_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124151456_remove_projects_ci_triggers_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124151949_remove_projects_ci_runner_projects_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124152824_remove_projects_ci_subscriptions_projects_downstream_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124153233_remove_projects_ci_job_artifacts_project_id_fk.rb20
-rw-r--r--db/post_migrate/20220124153234_re_remove_projects_ci_job_artifacts_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124180704_remove_projects_ci_builds_metadata_project_id_fk.rb20
-rw-r--r--db/post_migrate/20220124180705_re_remove_projects_ci_builds_metadata_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124184338_remove_projects_ci_subscriptions_projects_upstream_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124204046_remove_projects_ci_sources_pipelines_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124214131_remove_projects_ci_refs_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124215857_remove_projects_ci_job_token_project_scope_links_source_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220124221521_remove_projects_ci_project_monthly_usages_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220125083520_remove_ci_pipelines_dast_site_profiles_pipelines_ci_pipeline_id_fk.rb19
-rw-r--r--db/post_migrate/20220125084348_remove_ci_pipelines_vulnerability_feedback_pipeline_id_fk.rb19
-rw-r--r--db/post_migrate/20220125122640_schedule_populate_topics_non_private_projects_count.rb23
-rw-r--r--db/post_migrate/20220126201752_remove_projects_ci_job_token_project_scope_links_target_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220126202654_remove_projects_ci_sources_projects_source_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220126203421_remove_projects_ci_pipeline_schedules_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220126210021_remove_projects_ci_builds_project_id_fk.rb20
-rw-r--r--db/post_migrate/20220126210022_re_remove_projects_ci_builds_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220126210657_remove_projects_ci_pipelines_project_id_fk.rb19
-rw-r--r--db/post_migrate/20220127112243_add_index_to_merge_request_assignees_state.rb15
-rw-r--r--db/post_migrate/20220127112412_add_index_to_merge_request_reviewers_state.rb15
-rw-r--r--db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb15
-rw-r--r--db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb15
-rw-r--r--db/post_migrate/20220128155251_remove_dangling_running_builds.rb25
-rw-r--r--db/post_migrate/20220128155814_fix_approval_rules_code_owners_rule_type_index.rb23
-rw-r--r--db/post_migrate/20220201034731_remove_index_clusters_kubernetes_namespaces_on_cluster_id.rb15
-rw-r--r--db/post_migrate/20220201141705_cleanup_background_migration_populate_test_reports_issue_id.rb15
-rw-r--r--db/post_migrate/20220201173212_add_user_details_provisioning_index.rb18
-rw-r--r--db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb20
-rw-r--r--db/post_migrate/20220202105733_delete_service_template_records.rb15
-rw-r--r--db/post_migrate/20220204053655_remove_index_epic_issues_on_epic_id.rb15
-rw-r--r--db/post_migrate/20220208115439_start_backfill_ci_queuing_tables.rb24
-rw-r--r--db/post_migrate/20220209111007_add_partial_index_for_batching_active_cluster_image_scanning_vulnerabilities.rb16
-rw-r--r--db/post_migrate/20220212120735_schedule_fix_incorrect_max_seats_used2.rb20
-rw-r--r--db/post_migrate/20220213104531_create_indexes_on_integration_type_new.rb60
-rw-r--r--db/schema_migrations/202111191110061
-rw-r--r--db/schema_migrations/202111221030511
-rw-r--r--db/schema_migrations/202111231352551
-rw-r--r--db/schema_migrations/202111240957041
-rw-r--r--db/schema_migrations/202112091030481
-rw-r--r--db/schema_migrations/202201050822171
-rw-r--r--db/schema_migrations/202201061119581
-rw-r--r--db/schema_migrations/202201061120431
-rw-r--r--db/schema_migrations/202201061120851
-rw-r--r--db/schema_migrations/202201061633261
-rw-r--r--db/schema_migrations/202201061850331
-rw-r--r--db/schema_migrations/202201070648451
-rw-r--r--db/schema_migrations/202201110935341
-rw-r--r--db/schema_migrations/202201111014211
-rw-r--r--db/schema_migrations/202201111549501
-rw-r--r--db/schema_migrations/202201111549511
-rw-r--r--db/schema_migrations/202201131114401
-rw-r--r--db/schema_migrations/202201170340561
-rw-r--r--db/schema_migrations/202201170826111
-rw-r--r--db/schema_migrations/202201180156331
-rw-r--r--db/schema_migrations/202201180200261
-rw-r--r--db/schema_migrations/202201182040391
-rw-r--r--db/schema_migrations/202201190940231
-rw-r--r--db/schema_migrations/202201190945031
-rw-r--r--db/schema_migrations/202201191414071
-rw-r--r--db/schema_migrations/202201191431301
-rw-r--r--db/schema_migrations/202201191442531
-rw-r--r--db/schema_migrations/202201191444581
-rw-r--r--db/schema_migrations/202201191512211
-rw-r--r--db/schema_migrations/202201191537061
-rw-r--r--db/schema_migrations/202201191544421
-rw-r--r--db/schema_migrations/202201191704261
-rw-r--r--db/schema_migrations/202201191931301
-rw-r--r--db/schema_migrations/202201192013401
-rw-r--r--db/schema_migrations/202201192031191
-rw-r--r--db/schema_migrations/202201192206201
-rw-r--r--db/schema_migrations/202201200331151
-rw-r--r--db/schema_migrations/202201200856551
-rw-r--r--db/schema_migrations/202201200943401
-rw-r--r--db/schema_migrations/202201201237001
-rw-r--r--db/schema_migrations/202201201238001
-rw-r--r--db/schema_migrations/202201212147521
-rw-r--r--db/schema_migrations/202201212147531
-rw-r--r--db/schema_migrations/202201212216511
-rw-r--r--db/schema_migrations/202201241300281
-rw-r--r--db/schema_migrations/202201241450191
-rw-r--r--db/schema_migrations/202201241514561
-rw-r--r--db/schema_migrations/202201241519491
-rw-r--r--db/schema_migrations/202201241528241
-rw-r--r--db/schema_migrations/202201241532331
-rw-r--r--db/schema_migrations/202201241532341
-rw-r--r--db/schema_migrations/202201241807041
-rw-r--r--db/schema_migrations/202201241807051
-rw-r--r--db/schema_migrations/202201241843381
-rw-r--r--db/schema_migrations/202201242040461
-rw-r--r--db/schema_migrations/202201242141311
-rw-r--r--db/schema_migrations/202201242158571
-rw-r--r--db/schema_migrations/202201242215211
-rw-r--r--db/schema_migrations/202201250835201
-rw-r--r--db/schema_migrations/202201250841271
-rw-r--r--db/schema_migrations/202201250843481
-rw-r--r--db/schema_migrations/202201251222281
-rw-r--r--db/schema_migrations/202201251226401
-rw-r--r--db/schema_migrations/202201251227251
-rw-r--r--db/schema_migrations/202201252305381
-rw-r--r--db/schema_migrations/202201262017521
-rw-r--r--db/schema_migrations/202201262026541
-rw-r--r--db/schema_migrations/202201262034211
-rw-r--r--db/schema_migrations/202201262100211
-rw-r--r--db/schema_migrations/202201262100221
-rw-r--r--db/schema_migrations/202201262106571
-rw-r--r--db/schema_migrations/202201271122431
-rw-r--r--db/schema_migrations/202201271124121
-rw-r--r--db/schema_migrations/202201271322001
-rw-r--r--db/schema_migrations/202201271322011
-rw-r--r--db/schema_migrations/202201280937561
-rw-r--r--db/schema_migrations/202201281552511
-rw-r--r--db/schema_migrations/202201281558141
-rw-r--r--db/schema_migrations/202201281947221
-rw-r--r--db/schema_migrations/202201311357251
-rw-r--r--db/schema_migrations/202201311926431
-rw-r--r--db/schema_migrations/202202010347311
-rw-r--r--db/schema_migrations/202202011417051
-rw-r--r--db/schema_migrations/202202011732121
-rw-r--r--db/schema_migrations/202202011930331
-rw-r--r--db/schema_migrations/202202012053001
-rw-r--r--db/schema_migrations/202202020344091
-rw-r--r--db/schema_migrations/202202021057331
-rw-r--r--db/schema_migrations/202202021153501
-rw-r--r--db/schema_migrations/202202031233331
-rw-r--r--db/schema_migrations/202202031336521
-rw-r--r--db/schema_migrations/202202040536551
-rw-r--r--db/schema_migrations/202202041542201
-rw-r--r--db/schema_migrations/202202070831291
-rw-r--r--db/schema_migrations/202202081154391
-rw-r--r--db/schema_migrations/202202081704451
-rw-r--r--db/schema_migrations/202202081718261
-rw-r--r--db/schema_migrations/202202091110071
-rw-r--r--db/schema_migrations/202202112146051
-rw-r--r--db/schema_migrations/202202121207351
-rw-r--r--db/schema_migrations/202202131045311
-rw-r--r--db/structure.sql418
-rw-r--r--doc/.vale/gitlab/BadPlurals.yml14
-rw-r--r--doc/.vale/gitlab/SubstitutionSuggestions.yml1
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml3
-rw-r--r--doc/.vale/gitlab/Substitutions.yml6
-rw-r--r--doc/administration/audit_event_streaming.md18
-rw-r--r--doc/administration/audit_events.md11
-rw-r--r--doc/administration/auditor_users.md2
-rw-r--r--doc/administration/auth/atlassian.md2
-rw-r--r--doc/administration/auth/authentiq.md2
-rw-r--r--doc/administration/auth/cognito.md2
-rw-r--r--doc/administration/auth/crowd.md2
-rw-r--r--doc/administration/auth/index.md30
-rw-r--r--doc/administration/auth/jwt.md2
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md6
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md4
-rw-r--r--doc/administration/auth/ldap/ldap_synchronization.md6
-rw-r--r--doc/administration/auth/oidc.md61
-rw-r--r--doc/administration/auth/smartcard.md2
-rw-r--r--doc/administration/clusters/kas.md17
-rw-r--r--doc/administration/compliance.md4
-rw-r--r--doc/administration/docs_self_host.md124
-rw-r--r--doc/administration/feature_flags.md30
-rw-r--r--doc/administration/geo/glossary.md4
-rw-r--r--doc/administration/geo/index.md1
-rw-r--r--doc/administration/geo/replication/datatypes.md2
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md11
-rw-r--r--doc/administration/geo/replication/location_aware_git_url.md12
-rw-r--r--doc/administration/geo/replication/troubleshooting.md63
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md4
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md41
-rw-r--r--doc/administration/geo/secondary_proxy/index.md12
-rw-r--r--doc/administration/geo/setup/database.md5
-rw-r--r--doc/administration/get_started.md2
-rw-r--r--doc/administration/gitaly/configure_gitaly.md19
-rw-r--r--doc/administration/gitaly/faq.md8
-rw-r--r--doc/administration/gitaly/index.md10
-rw-r--r--doc/administration/gitaly/praefect.md100
-rw-r--r--doc/administration/gitaly/recovery.md2
-rw-r--r--doc/administration/gitaly/troubleshooting.md9
-rw-r--r--doc/administration/img/custom_hooks_error_msg.pngbin31281 -> 0 bytes
-rw-r--r--doc/administration/incoming_email.md14
-rw-r--r--doc/administration/instance_limits.md34
-rw-r--r--doc/administration/job_artifacts.md12
-rw-r--r--doc/administration/load_balancer.md27
-rw-r--r--doc/administration/logs.md2
-rw-r--r--doc/administration/monitoring/github_imports.md2
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md12
-rw-r--r--doc/administration/monitoring/index.md2
-rw-r--r--doc/administration/monitoring/ip_whitelist.md2
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/index.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md4
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md10
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md15
-rw-r--r--doc/administration/monitoring/prometheus/index.md62
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/puma_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/registry_exporter.md2
-rw-r--r--doc/administration/nfs.md6
-rw-r--r--doc/administration/object_storage.md2
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md2
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md21
-rw-r--r--doc/administration/package_information/supported_os.md4
-rw-r--r--doc/administration/packages/container_registry.md48
-rw-r--r--doc/administration/packages/dependency_proxy.md49
-rw-r--r--doc/administration/packages/index.md2
-rw-r--r--doc/administration/pages/img/pages_deploy_failure_v14_8.pngbin0 -> 32510 bytes
-rw-r--r--doc/administration/pages/index.md65
-rw-r--r--doc/administration/postgresql/database_load_balancing.md4
-rw-r--r--doc/administration/postgresql/replication_and_failover.md7
-rw-r--r--doc/administration/raketasks/ldap.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md10
-rw-r--r--doc/administration/reference_architectures/1k_users.md1
-rw-r--r--doc/administration/reference_architectures/25k_users.md10
-rw-r--r--doc/administration/reference_architectures/2k_users.md4
-rw-r--r--doc/administration/reference_architectures/3k_users.md10
-rw-r--r--doc/administration/reference_architectures/50k_users.md10
-rw-r--r--doc/administration/reference_architectures/5k_users.md10
-rw-r--r--doc/administration/reference_architectures/index.md234
-rw-r--r--doc/administration/restart_gitlab.md2
-rw-r--r--doc/administration/server_hooks.md192
-rw-r--r--doc/administration/sidekiq.md345
-rw-r--r--doc/administration/troubleshooting/diagnostics_tools.md4
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md60
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md5
-rw-r--r--doc/administration/troubleshooting/img/AzureAD-scim_provisioning.pngbin0 -> 539414 bytes
-rw-r--r--doc/administration/troubleshooting/postgresql.md9
-rw-r--r--doc/administration/user_settings.md2
-rw-r--r--doc/api/access_requests.md2
-rw-r--r--doc/api/api_resources.md1
-rw-r--r--doc/api/appearance.md2
-rw-r--r--doc/api/applications.md2
-rw-r--r--doc/api/audit_events.md2
-rw-r--r--doc/api/avatar.md2
-rw-r--r--doc/api/commits.md10
-rw-r--r--doc/api/container_registry.md33
-rw-r--r--doc/api/dependency_proxy.md3
-rw-r--r--doc/api/deploy_keys.md2
-rw-r--r--doc/api/deploy_tokens.md6
-rw-r--r--doc/api/deployments.md77
-rw-r--r--doc/api/dora/metrics.md2
-rw-r--r--doc/api/epics.md9
-rw-r--r--doc/api/error_tracking.md8
-rw-r--r--doc/api/geo_nodes.md39
-rw-r--r--doc/api/graphql/index.md2
-rw-r--r--doc/api/graphql/reference/index.md587
-rw-r--r--doc/api/group_access_tokens.md4
-rw-r--r--doc/api/group_badges.md2
-rw-r--r--doc/api/group_clusters.md2
-rw-r--r--doc/api/groups.md80
-rw-r--r--doc/api/index.md15
-rw-r--r--doc/api/instance_clusters.md3
-rw-r--r--doc/api/integrations.md7
-rw-r--r--doc/api/issues.md51
-rw-r--r--doc/api/job_artifacts.md6
-rw-r--r--doc/api/jobs.md88
-rw-r--r--doc/api/lint.md6
-rw-r--r--doc/api/members.md2
-rw-r--r--doc/api/merge_request_approvals.md40
-rw-r--r--doc/api/merge_requests.md144
-rw-r--r--doc/api/metrics_dashboard_annotations.md2
-rw-r--r--doc/api/metrics_user_starred_dashboards.md2
-rw-r--r--doc/api/namespaces.md2
-rw-r--r--doc/api/notes.md2
-rw-r--r--doc/api/oauth2.md35
-rw-r--r--doc/api/pages.md2
-rw-r--r--doc/api/pages_domains.md2
-rw-r--r--doc/api/plan_limits.md5
-rw-r--r--doc/api/project_access_tokens.md2
-rw-r--r--doc/api/project_clusters.md2
-rw-r--r--doc/api/project_import_export.md8
-rw-r--r--doc/api/project_relations_export.md2
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/api/projects.md109
-rw-r--r--doc/api/repository_files.md64
-rw-r--r--doc/api/runners.md200
-rw-r--r--doc/api/scim.md2
-rw-r--r--doc/api/settings.md9
-rw-r--r--doc/api/statistics.md2
-rw-r--r--doc/api/status_checks.md5
-rw-r--r--doc/api/suggestions.md4
-rw-r--r--doc/api/tags.md2
-rw-r--r--doc/api/usage_data.md2
-rw-r--r--doc/api/users.md87
-rw-r--r--doc/api/v3_to_v4.md19
-rw-r--r--doc/api/visual_review_discussions.md5
-rw-r--r--doc/architecture/blueprints/ci_data_decay/index.md35
-rw-r--r--doc/architecture/blueprints/consolidating_groups_and_projects/index.md2
-rw-r--r--doc/architecture/blueprints/database_testing/index.md4
-rw-r--r--doc/architecture/blueprints/object_storage/index.md9
-rw-r--r--doc/architecture/blueprints/runner_scaling/index.md42
-rw-r--r--doc/ci/chatops/index.md4
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md2
-rw-r--r--doc/ci/cloud_services/aws/index.md6
-rw-r--r--doc/ci/cloud_services/google_cloud/index.md182
-rw-r--r--doc/ci/cloud_services/index.md11
-rw-r--r--doc/ci/docker/using_docker_images.md23
-rw-r--r--doc/ci/environments/deployment_approvals.md27
-rw-r--r--doc/ci/environments/deployment_safety.md6
-rw-r--r--doc/ci/environments/img/environments_open_live_environment_v14_8.pngbin0 -> 33534 bytes
-rw-r--r--doc/ci/environments/index.md16
-rw-r--r--doc/ci/environments/protected_environments.md25
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md4
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md2
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md2
-rw-r--r--doc/ci/git_submodules.md9
-rw-r--r--doc/ci/img/ci_lint.pngbin11525 -> 0 bytes
-rw-r--r--doc/ci/img/ci_lint_dry_run.pngbin6811 -> 0 bytes
-rw-r--r--doc/ci/img/environments_available_13_10.pngbin13245 -> 0 bytes
-rw-r--r--doc/ci/index.md2
-rw-r--r--doc/ci/jobs/ci_job_token.md3
-rw-r--r--doc/ci/jobs/index.md3
-rw-r--r--doc/ci/jobs/job_control.md36
-rw-r--r--doc/ci/lint.md64
-rw-r--r--doc/ci/metrics_reports.md3
-rw-r--r--doc/ci/migration/jenkins.md2
-rw-r--r--doc/ci/pipelines/cicd_minutes.md6
-rw-r--r--doc/ci/pipelines/img/merged_result_pipeline.pngbin7374 -> 0 bytes
-rw-r--r--doc/ci/pipelines/index.md14
-rw-r--r--doc/ci/pipelines/job_artifacts.md10
-rw-r--r--doc/ci/pipelines/merge_request_pipelines.md68
-rw-r--r--doc/ci/pipelines/merge_trains.md43
-rw-r--r--doc/ci/pipelines/merged_results_pipelines.md78
-rw-r--r--doc/ci/pipelines/multi_project_pipelines.md2
-rw-r--r--doc/ci/pipelines/parent_child_pipelines.md2
-rw-r--r--doc/ci/pipelines/pipeline_artifacts.md3
-rw-r--r--doc/ci/pipelines/pipelines_for_merged_results.md134
-rw-r--r--doc/ci/pipelines/schedules.md24
-rw-r--r--doc/ci/pipelines/settings.md48
-rw-r--r--doc/ci/quick_start/index.md2
-rw-r--r--doc/ci/resource_groups/index.md2
-rw-r--r--doc/ci/review_apps/index.md5
-rw-r--r--doc/ci/runners/configure_runners.md56
-rw-r--r--doc/ci/runners/runners_scope.md12
-rw-r--r--doc/ci/runners/saas/macos_saas_runner.md2
-rw-r--r--doc/ci/runners/saas/windows_saas_runner.md8
-rw-r--r--doc/ci/secrets/index.md4
-rw-r--r--doc/ci/services/index.md6
-rw-r--r--doc/ci/test_cases/index.md10
-rw-r--r--doc/ci/triggers/index.md2
-rw-r--r--doc/ci/troubleshooting.md35
-rw-r--r--doc/ci/unit_test_reports.md9
-rw-r--r--doc/ci/variables/index.md16
-rw-r--r--doc/ci/variables/predefined_variables.md8
-rw-r--r--doc/ci/yaml/artifacts_reports.md2
-rw-r--r--doc/ci/yaml/includes.md63
-rw-r--r--doc/ci/yaml/index.md48
-rw-r--r--doc/ci/yaml/script.md2
-rw-r--r--doc/ci/yaml/workflow.md4
-rw-r--r--doc/development/agent/gitops.md4
-rw-r--r--doc/development/agent/identity.md4
-rw-r--r--doc/development/agent/index.md4
-rw-r--r--doc/development/agent/local.md4
-rw-r--r--doc/development/agent/repository_overview.md4
-rw-r--r--doc/development/agent/routing.md4
-rw-r--r--doc/development/agent/user_stories.md4
-rw-r--r--doc/development/application_slis/index.md29
-rw-r--r--doc/development/architecture.md4
-rw-r--r--doc/development/avoiding_downtime_in_migrations.md4
-rw-r--r--doc/development/cached_queries.md2
-rw-r--r--doc/development/cascading_settings.md2
-rw-r--r--doc/development/changelog.md4
-rw-r--r--doc/development/cicd/index.md2
-rw-r--r--doc/development/cicd/templates.md74
-rw-r--r--doc/development/code_review.md19
-rw-r--r--doc/development/contributing/design.md2
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/issue_workflow.md30
-rw-r--r--doc/development/contributing/merge_request_workflow.md7
-rw-r--r--doc/development/contributing/style_guides.md16
-rw-r--r--doc/development/dangerbot.md2
-rw-r--r--doc/development/database/dbcheck-migrations-job.md67
-rw-r--r--doc/development/database/efficient_in_operator_queries.md6
-rw-r--r--doc/development/database/index.md1
-rw-r--r--doc/development/database/loose_foreign_keys.md2
-rw-r--r--doc/development/database_review.md4
-rw-r--r--doc/development/dependencies.md2
-rw-r--r--doc/development/deprecation_guidelines/index.md4
-rw-r--r--doc/development/diffs.md4
-rw-r--r--doc/development/directory_structure.md2
-rw-r--r--doc/development/distributed_tracing.md2
-rw-r--r--doc/development/documentation/index.md6
-rw-r--r--doc/development/documentation/review_apps.md4
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md2
-rw-r--r--doc/development/documentation/site_architecture/folder_structure.md98
-rw-r--r--doc/development/documentation/site_architecture/index.md15
-rw-r--r--doc/development/documentation/structure.md8
-rw-r--r--doc/development/documentation/styleguide/index.md132
-rw-r--r--doc/development/documentation/styleguide/word_list.md66
-rw-r--r--doc/development/documentation/testing.md40
-rw-r--r--doc/development/documentation/workflow.md4
-rw-r--r--doc/development/ee_features.md4
-rw-r--r--doc/development/emails.md6
-rw-r--r--doc/development/event_store.md18
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md255
-rw-r--r--doc/development/experiment_guide/index.md2
-rw-r--r--doc/development/export_csv.md4
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md2
-rw-r--r--doc/development/fe_guide/development_process.md24
-rw-r--r--doc/development/fe_guide/graphql.md221
-rw-r--r--doc/development/fe_guide/style/javascript.md30
-rw-r--r--doc/development/feature_flags/index.md4
-rw-r--r--doc/development/features_inside_dot_gitlab.md2
-rw-r--r--doc/development/img/architecture_simplified.pngbin38060 -> 28516 bytes
-rw-r--r--doc/development/import_project.md8
-rw-r--r--doc/development/index.md4
-rw-r--r--doc/development/integrations/img/copy_cookies.pngbin44311 -> 0 bytes
-rw-r--r--doc/development/integrations/img/copy_curl.pngbin60175 -> 0 bytes
-rw-r--r--doc/development/integrations/jira_connect.md24
-rw-r--r--doc/development/integrations/secure.md2
-rw-r--r--doc/development/internal_api/index.md33
-rw-r--r--doc/development/issuable-like-models.md2
-rw-r--r--doc/development/issue_types.md2
-rw-r--r--doc/development/iterating_tables_in_batches.md6
-rw-r--r--doc/development/jh_features_review.md12
-rw-r--r--doc/development/logging.md13
-rw-r--r--doc/development/merge_request_performance_guidelines.md8
-rw-r--r--doc/development/multi_version_compatibility.md8
-rw-r--r--doc/development/new_fe_guide/modules/widget_extensions.md280
-rw-r--r--doc/development/permissions.md2
-rw-r--r--doc/development/pipelines.md39
-rw-r--r--doc/development/policies.md4
-rw-r--r--doc/development/product_qualified_lead_guide/index.md94
-rw-r--r--doc/development/profiling.md5
-rw-r--r--doc/development/prometheus_metrics.md2
-rw-r--r--doc/development/ruby_upgrade.md2
-rw-r--r--doc/development/scalability.md2
-rw-r--r--doc/development/secure_coding_guidelines.md4
-rw-r--r--doc/development/service_ping/implement.md2
-rw-r--r--doc/development/service_ping/index.md55
-rw-r--r--doc/development/service_ping/metrics_dictionary.md23
-rw-r--r--doc/development/service_ping/metrics_lifecycle.md12
-rw-r--r--doc/development/service_ping/review_guidelines.md2
-rw-r--r--doc/development/service_ping/troubleshooting.md31
-rw-r--r--doc/development/sidekiq/compatibility_across_updates.md159
-rw-r--r--doc/development/sidekiq/idempotent_jobs.md208
-rw-r--r--doc/development/sidekiq/index.md190
-rw-r--r--doc/development/sidekiq/limited_capacity_worker.md84
-rw-r--r--doc/development/sidekiq/logging.md155
-rw-r--r--doc/development/sidekiq/worker_attributes.md325
-rw-r--r--doc/development/sidekiq_style_guide.md1102
-rw-r--r--doc/development/snowplow/implementation.md168
-rw-r--r--doc/development/snowplow/index.md16
-rw-r--r--doc/development/snowplow/review_guidelines.md2
-rw-r--r--doc/development/snowplow/schemas.md28
-rw-r--r--doc/development/snowplow/troubleshooting.md50
-rw-r--r--doc/development/stage_group_dashboards.md4
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md6
-rw-r--r--doc/development/testing_guide/end_to_end/execution_context_selection.md2
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md8
-rw-r--r--doc/development/testing_guide/end_to_end/index.md10
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md80
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md1
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md28
-rw-r--r--doc/development/testing_guide/flaky_tests.md29
-rw-r--r--doc/development/testing_guide/frontend_testing.md2
-rw-r--r--doc/development/testing_guide/review_apps.md3
-rw-r--r--doc/development/transient/prevention-patterns.md2
-rw-r--r--doc/development/uploads.md82
-rw-r--r--doc/development/value_stream_analytics.md4
-rw-r--r--doc/development/value_stream_analytics/img/object_hierarchy_example_V14_10.pngbin0 -> 55849 bytes
-rw-r--r--doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md330
-rw-r--r--doc/install/aws/eks_clusters_aws.md2
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md12
-rw-r--r--doc/install/aws/manual_install_aws.md10
-rw-r--r--doc/install/index.md2
-rw-r--r--doc/install/installation.md26
-rw-r--r--doc/install/requirements.md4
-rw-r--r--doc/integration/datadog.md4
-rw-r--r--doc/integration/elasticsearch.md122
-rw-r--r--doc/integration/github.md298
-rw-r--r--doc/integration/gitlab.md36
-rw-r--r--doc/integration/img/enable_trello_powerup.pngbin17791 -> 0 bytes
-rw-r--r--doc/integration/jenkins.md3
-rw-r--r--doc/integration/jenkins_deprecated.md2
-rw-r--r--doc/integration/jira/connect-app.md11
-rw-r--r--doc/integration/kerberos.md2
-rw-r--r--doc/integration/mattermost/index.md10
-rw-r--r--doc/integration/oauth_provider.md25
-rw-r--r--doc/integration/openid_connect_provider.md7
-rw-r--r--doc/integration/saml.md6
-rw-r--r--doc/integration/trello_power_up.md49
-rw-r--r--doc/operations/error_tracking.md2
-rw-r--r--doc/operations/feature_flags.md4
-rw-r--r--doc/operations/incident_management/alerts.md10
-rw-r--r--doc/operations/incident_management/escalation_policies.md4
-rw-r--r--doc/operations/incident_management/incidents.md18
-rw-r--r--doc/operations/incident_management/index.md2
-rw-r--r--doc/operations/incident_management/integrations.md12
-rw-r--r--doc/operations/incident_management/oncall_schedules.md4
-rw-r--r--doc/operations/incident_management/paging.md2
-rw-r--r--doc/operations/incident_management/status_page.md6
-rw-r--r--doc/operations/index.md2
-rw-r--r--doc/operations/metrics/alerts.md5
-rw-r--r--doc/operations/metrics/dashboards/default.md2
-rw-r--r--doc/operations/metrics/dashboards/develop.md2
-rw-r--r--doc/operations/metrics/dashboards/index.md2
-rw-r--r--doc/operations/metrics/dashboards/panel_types.md2
-rw-r--r--doc/operations/metrics/dashboards/settings.md2
-rw-r--r--doc/operations/metrics/dashboards/templating_variables.md2
-rw-r--r--doc/operations/metrics/dashboards/variables.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml_number_format.md2
-rw-r--r--doc/operations/metrics/embed.md4
-rw-r--r--doc/operations/metrics/embed_grafana.md2
-rw-r--r--doc/operations/metrics/index.md2
-rw-r--r--doc/operations/product_analytics.md2
-rw-r--r--doc/operations/tracing.md2
-rw-r--r--doc/public_access/public_access.md10
-rw-r--r--doc/push_rules/push_rules.md274
-rw-r--r--doc/raketasks/backup_restore.md4
-rw-r--r--doc/raketasks/generate_sample_prometheus_data.md2
-rw-r--r--doc/security/asset_proxy.md2
-rw-r--r--doc/security/crime_vulnerability.md2
-rw-r--r--doc/security/index.md4
-rw-r--r--doc/security/information_exclusivity.md2
-rw-r--r--doc/security/password_length_limits.md2
-rw-r--r--doc/security/password_storage.md2
-rw-r--r--doc/security/passwords_for_integrated_authentication_methods.md2
-rw-r--r--doc/security/project_import_decompressed_archive_size_limits.md2
-rw-r--r--doc/security/rate_limits.md15
-rw-r--r--doc/security/reset_user_password.md2
-rw-r--r--doc/security/ssh_keys_restrictions.md10
-rw-r--r--doc/security/token_overview.md19
-rw-r--r--doc/security/two_factor_authentication.md8
-rw-r--r--doc/security/unlock_user.md2
-rw-r--r--doc/security/user_email_confirmation.md2
-rw-r--r--doc/security/user_file_uploads.md4
-rw-r--r--doc/security/webhooks.md2
-rw-r--r--doc/ssh/index.md89
-rw-r--r--doc/subscriptions/bronze_starter.md6
-rw-r--r--doc/subscriptions/gitlab_com/index.md33
-rw-r--r--doc/subscriptions/index.md4
-rw-r--r--doc/subscriptions/self_managed/index.md15
-rw-r--r--doc/system_hooks/system_hooks.md42
-rw-r--r--doc/tools/email.md2
-rw-r--r--doc/topics/authentication/index.md2
-rw-r--r--doc/topics/autodevops/customize.md6
-rw-r--r--doc/topics/cron/index.md2
-rw-r--r--doc/topics/git/lfs/index.md2
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md2
-rw-r--r--doc/topics/git/merge_conflicts.md2
-rw-r--r--doc/topics/gitlab_flow.md8
-rw-r--r--doc/topics/release_your_application.md6
-rw-r--r--doc/tutorials/index.md2
-rw-r--r--doc/update/deprecations.md885
-rw-r--r--doc/update/index.md20
-rw-r--r--doc/update/removals.md552
-rw-r--r--doc/update/upgrading_from_source.md18
-rw-r--r--doc/update/zero_downtime.md10
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md2
-rw-r--r--doc/user/admin_area/analytics/usage_trends.md2
-rw-r--r--doc/user/admin_area/credentials_inventory.md28
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_10.pngbin30223 -> 0 bytes
-rw-r--r--doc/user/admin_area/index.md19
-rw-r--r--doc/user/admin_area/license.md13
-rw-r--r--doc/user/admin_area/moderate_users.md10
-rw-r--r--doc/user/admin_area/monitoring/health_check.md2
-rw-r--r--doc/user/admin_area/reporting/spamcheck.md65
-rw-r--r--doc/user/admin_area/review_abuse_reports.md2
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md12
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md6
-rw-r--r--doc/user/admin_area/settings/deprecated_api_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/email.md2
-rw-r--r--doc/user/admin_area/settings/external_authorization.md4
-rw-r--r--doc/user/admin_area/settings/files_api_rate_limits.md4
-rw-r--r--doc/user/admin_area/settings/git_lfs_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/img/classification_label_on_project_page.pngbin19568 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/classification_label_on_project_page_v14_8.pngbin0 -> 17728 bytes
-rw-r--r--doc/user/admin_area/settings/index.md3
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_users_api.md33
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md5
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md30
-rw-r--r--doc/user/analytics/code_review_analytics.md2
-rw-r--r--doc/user/analytics/img/issues_created_per_month_v13_11.pngbin21731 -> 0 bytes
-rw-r--r--doc/user/analytics/img/issues_created_per_month_v14_8.pngbin0 -> 17292 bytes
-rw-r--r--doc/user/analytics/img/mr_mean_time_to_merge_metric_v13_9.pngbin12299 -> 0 bytes
-rw-r--r--doc/user/analytics/img/mr_throughput_table_v13_3.pngbin20273 -> 0 bytes
-rw-r--r--doc/user/analytics/issue_analytics.md2
-rw-r--r--doc/user/analytics/merge_request_analytics.md127
-rw-r--r--doc/user/analytics/productivity_analytics.md4
-rw-r--r--doc/user/application_security/api_fuzzing/index.md191
-rw-r--r--doc/user/application_security/cluster_image_scanning/index.md6
-rw-r--r--doc/user/application_security/configuration/index.md4
-rw-r--r--doc/user/application_security/container_scanning/index.md15
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md134
-rw-r--r--doc/user/application_security/dast/browser_based.md2
-rw-r--r--doc/user/application_security/dast/checks/1004.1.md2
-rw-r--r--doc/user/application_security/dast/checks/16.2.md2
-rw-r--r--doc/user/application_security/dast/checks/16.3.md2
-rw-r--r--doc/user/application_security/dast/checks/200.1.md29
-rw-r--r--doc/user/application_security/dast/checks/548.1.md45
-rw-r--r--doc/user/application_security/dast/checks/614.1.md4
-rw-r--r--doc/user/application_security/dast/checks/index.md6
-rw-r--r--doc/user/application_security/dast/index.md36
-rw-r--r--doc/user/application_security/dast/run_dast_offline.md2
-rw-r--r--doc/user/application_security/dast_api/index.md200
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md7
-rw-r--r--doc/user/application_security/dependency_scanning/index.md131
-rw-r--r--doc/user/application_security/iac_scanning/index.md6
-rw-r--r--doc/user/application_security/index.md51
-rw-r--r--doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.pngbin0 -> 76484 bytes
-rw-r--r--doc/user/application_security/policies/index.md335
-rw-r--r--doc/user/application_security/policies/scan-execution-policies.md219
-rw-r--r--doc/user/application_security/policies/scan-result-policies.md175
-rw-r--r--doc/user/application_security/sast/index.md183
-rw-r--r--doc/user/application_security/secret_detection/index.md117
-rw-r--r--doc/user/application_security/secret_detection/post_processing.md179
-rw-r--r--doc/user/application_security/security_dashboard/index.md2
-rw-r--r--doc/user/application_security/threat_monitoring/index.md8
-rw-r--r--doc/user/application_security/vulnerabilities/index.md21
-rw-r--r--doc/user/application_security/vulnerabilities/severities.md8
-rw-r--r--doc/user/application_security/vulnerability_report/index.md6
-rw-r--r--doc/user/asciidoc.md5
-rw-r--r--doc/user/clusters/agent/ci_cd_tunnel.md71
-rw-r--r--doc/user/clusters/agent/index.md347
-rw-r--r--doc/user/clusters/agent/install/index.md250
-rw-r--r--doc/user/clusters/agent/repository.md102
-rw-r--r--doc/user/clusters/agent/troubleshooting.md193
-rw-r--r--doc/user/clusters/cost_management.md2
-rw-r--r--doc/user/clusters/img/cluster_agent_security_tab_v14_8.pngbin0 -> 31764 bytes
-rw-r--r--doc/user/clusters/img/gitlab_agent_activity_events_v14_6.pngbin56049 -> 0 bytes
-rw-r--r--doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.pngbin31309 -> 0 bytes
-rw-r--r--doc/user/clusters/img/kubernetes-agent-ui-list_v14_8.pngbin0 -> 22175 bytes
-rw-r--r--doc/user/clusters/migrating_from_gma_to_project_template.md73
-rw-r--r--doc/user/compliance/license_compliance/index.md77
-rw-r--r--doc/user/crm/index.md26
-rw-r--r--doc/user/discussions/index.md9
-rw-r--r--doc/user/gitlab_com/index.md26
-rw-r--r--doc/user/group/contribution_analytics/index.md3
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/devops_adoption/index.md4
-rw-r--r--doc/user/group/epics/epic_boards.md14
-rw-r--r--doc/user/group/epics/manage_epics.md6
-rw-r--r--doc/user/group/import/index.md135
-rw-r--r--doc/user/group/index.md90
-rw-r--r--doc/user/group/iterations/index.md10
-rw-r--r--doc/user/group/planning_hierarchy/img/view-project-work-item-hierarchy_v14_8.pngbin0 -> 38783 bytes
-rw-r--r--doc/user/group/planning_hierarchy/index.md30
-rw-r--r--doc/user/group/repositories_analytics/index.md3
-rw-r--r--doc/user/group/roadmap/index.md20
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md2
-rw-r--r--doc/user/group/saml_sso/index.md36
-rw-r--r--doc/user/group/saml_sso/scim_setup.md30
-rw-r--r--doc/user/group/settings/group_access_tokens.md11
-rw-r--r--doc/user/group/settings/import_export.md4
-rw-r--r--doc/user/group/subgroups/index.md4
-rw-r--r--doc/user/group/value_stream_analytics/index.md15
-rw-r--r--doc/user/index.md8
-rw-r--r--doc/user/infrastructure/clusters/connect/index.md22
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md47
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md2
-rw-r--r--doc/user/infrastructure/iac/index.md102
-rw-r--r--doc/user/infrastructure/iac/mr_integration.md14
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md72
-rw-r--r--doc/user/infrastructure/iac/troubleshooting.md68
-rw-r--r--doc/user/markdown.md1
-rw-r--r--doc/user/packages/composer_repository/index.md10
-rw-r--r--doc/user/packages/container_registry/index.md112
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_data_transfer.md133
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md112
-rw-r--r--doc/user/packages/dependency_proxy/index.md66
-rw-r--r--doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md74
-rw-r--r--doc/user/packages/generic_packages/index.md2
-rw-r--r--doc/user/packages/maven_repository/index.md10
-rw-r--r--doc/user/packages/npm_registry/index.md3
-rw-r--r--doc/user/packages/package_registry/index.md62
-rw-r--r--doc/user/packages/package_registry/reduce_package_registry_storage.md52
-rw-r--r--doc/user/packages/pypi_repository/index.md10
-rw-r--r--doc/user/packages/terraform_module_registry/index.md2
-rw-r--r--doc/user/permissions.md636
-rw-r--r--doc/user/profile/account/create_accounts.md2
-rw-r--r--doc/user/profile/account/delete_account.md42
-rw-r--r--doc/user/profile/account/two_factor_authentication.md2
-rw-r--r--doc/user/profile/img/personal_readme_setup_v14_5.pngbin0 -> 26192 bytes
-rw-r--r--doc/user/profile/index.md30
-rw-r--r--doc/user/profile/personal_access_tokens.md6
-rw-r--r--doc/user/profile/preferences.md2
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md2
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md6
-rw-r--r--doc/user/project/clusters/add_existing_cluster.md4
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md6
-rw-r--r--doc/user/project/clusters/multiple_kubernetes_clusters.md4
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md11
-rw-r--r--doc/user/project/clusters/protect/container_host_security/quick_start_guide.md7
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md11
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md7
-rw-r--r--doc/user/project/clusters/protect/index.md9
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/code_owners.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.md42
-rw-r--r--doc/user/project/file_lock.md6
-rw-r--r--doc/user/project/img/time_tracking_example_v12_2.pngbin16362 -> 0 bytes
-rw-r--r--doc/user/project/import/bitbucket.md2
-rw-r--r--doc/user/project/import/bitbucket_server.md158
-rw-r--r--doc/user/project/import/github.md5
-rw-r--r--doc/user/project/import/index.md2
-rw-r--r--doc/user/project/import/jira.md5
-rw-r--r--doc/user/project/import/phabricator.md2
-rw-r--r--doc/user/project/index.md1
-rw-r--r--doc/user/project/integrations/bamboo.md1
-rw-r--r--doc/user/project/integrations/index.md2
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md2
-rw-r--r--doc/user/project/integrations/overview.md9
-rw-r--r--doc/user/project/integrations/prometheus.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/cloudwatch.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/haproxy.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md2
-rw-r--r--doc/user/project/integrations/webex_teams.md2
-rw-r--r--doc/user/project/integrations/webhook_events.md2
-rw-r--r--doc/user/project/integrations/webhooks.md11
-rw-r--r--doc/user/project/issue_board.md12
-rw-r--r--doc/user/project/issues/associate_zoom_meeting.md4
-rw-r--r--doc/user/project/issues/confidential_issues.md24
-rw-r--r--doc/user/project/issues/csv_export.md46
-rw-r--r--doc/user/project/issues/csv_import.md4
-rw-r--r--doc/user/project/issues/design_management.md26
-rw-r--r--doc/user/project/issues/due_dates.md2
-rw-r--r--doc/user/project/issues/issue_weight.md6
-rw-r--r--doc/user/project/issues/managing_issues.md42
-rw-r--r--doc/user/project/issues/multiple_assignees_for_issues.md2
-rw-r--r--doc/user/project/issues/related_issues.md24
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md2
-rw-r--r--doc/user/project/members/index.md87
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md3
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md2
-rw-r--r--doc/user/project/merge_requests/approvals/index.md6
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md35
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md6
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md5
-rw-r--r--doc/user/project/merge_requests/changes.md192
-rw-r--r--doc/user/project/merge_requests/code_quality.md29
-rw-r--r--doc/user/project/merge_requests/commits.md37
-rw-r--r--doc/user/project/merge_requests/confidential.md2
-rw-r--r--doc/user/project/merge_requests/drafts.md13
-rw-r--r--doc/user/project/merge_requests/fail_fast_testing.md7
-rw-r--r--doc/user/project/merge_requests/getting_started.md6
-rw-r--r--doc/user/project/merge_requests/img/changes-inline_v14_8.pngbin0 -> 8494 bytes
-rw-r--r--doc/user/project/merge_requests/img/changes-sidebyside_v14_8.pngbin0 -> 9366 bytes
-rw-r--r--doc/user/project/merge_requests/img/collapse-comment_v14_8.pngbin0 -> 9843 bytes
-rw-r--r--doc/user/project/merge_requests/img/expand-comment_v14_8.pngbin0 -> 13735 bytes
-rw-r--r--doc/user/project/merge_requests/img/file_by_file_v13_2.pngbin81874 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/incrementally_expand_merge_request_diffs_v12_2.pngbin28918 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin68704 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/mr-diff-example_v14_8.pngbin0 -> 17683 bytes
-rw-r--r--doc/user/project/merge_requests/index.md3
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md5
-rw-r--r--doc/user/project/merge_requests/merge_request_dependencies.md6
-rw-r--r--doc/user/project/merge_requests/reviews/index.md12
-rw-r--r--doc/user/project/merge_requests/reviews/suggestions.md4
-rw-r--r--doc/user/project/merge_requests/status_checks.md26
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md106
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md33
-rw-r--r--doc/user/project/milestones/burndown_and_burnup_charts.md29
-rw-r--r--doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.pngbin47296 -> 0 bytes
-rw-r--r--doc/user/project/milestones/index.md39
-rw-r--r--doc/user/project/pages/index.md2
-rw-r--r--doc/user/project/pages/introduction.md2
-rw-r--r--doc/user/project/protected_branches.md16
-rw-r--r--doc/user/project/protected_tags.md24
-rw-r--r--doc/user/project/push_options.md2
-rw-r--r--doc/user/project/quick_actions.md6
-rw-r--r--doc/user/project/releases/index.md18
-rw-r--r--doc/user/project/repository/branches/default.md8
-rw-r--r--doc/user/project/repository/forking_workflow.md43
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md2
-rw-r--r--doc/user/project/repository/mirror/index.md8
-rw-r--r--doc/user/project/repository/push_rules.md288
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md4
-rw-r--r--doc/user/project/repository/x509_signed_commits/index.md7
-rw-r--r--doc/user/project/requirements/index.md12
-rw-r--r--doc/user/project/service_desk.md9
-rw-r--r--doc/user/project/settings/import_export.md5
-rw-r--r--doc/user/project/settings/index.md26
-rw-r--r--doc/user/project/settings/project_access_tokens.md17
-rw-r--r--doc/user/project/static_site_editor/index.md8
-rw-r--r--doc/user/project/time_tracking.md126
-rw-r--r--doc/user/project/wiki/group.md4
-rw-r--r--doc/user/project/wiki/index.md22
-rw-r--r--doc/user/project/working_with_projects.md25
-rw-r--r--doc/user/search/advanced_search.md25
-rw-r--r--doc/user/search/index.md40
-rw-r--r--doc/user/shortcuts.md57
-rw-r--r--doc/user/upgrade_email_bypass.md2
-rw-r--r--doc/user/usage_quotas.md2
-rw-r--r--doc/user/workspace/img/1.1-Instance_overview.pngbin15189 -> 0 bytes
-rw-r--r--doc/user/workspace/img/1.2-Groups_overview.pngbin12431 -> 0 bytes
-rw-r--r--doc/user/workspace/img/1.3-Admin.pngbin16113 -> 0 bytes
-rw-r--r--doc/user/workspace/img/Admin_Settings.pngbin76891 -> 0 bytes
-rw-r--r--doc/user/workspace/img/hardware_settings.pngbin29457 -> 0 bytes
-rw-r--r--doc/user/workspace/index.md34
-rw-r--r--lefthook.yml10
-rw-r--r--lib/api/api.rb6
-rw-r--r--lib/api/branches.rb6
-rw-r--r--lib/api/ci/job_artifacts.rb4
-rw-r--r--lib/api/ci/pipelines.rb2
-rw-r--r--lib/api/ci/runner.rb29
-rw-r--r--lib/api/ci/runners.rb39
-rw-r--r--lib/api/ci/secure_files.rb98
-rw-r--r--lib/api/deployments.rb12
-rw-r--r--lib/api/discussions.rb2
-rw-r--r--lib/api/entities/ci/reset_token_result.rb3
-rw-r--r--lib/api/entities/ci/runner.rb5
-rw-r--r--lib/api/entities/ci/runner_details.rb8
-rw-r--r--lib/api/entities/ci/runner_registration_details.rb2
-rw-r--r--lib/api/entities/ci/secure_file.rb15
-rw-r--r--lib/api/entities/deployment_extended.rb10
-rw-r--r--lib/api/entities/user_safe.rb2
-rw-r--r--lib/api/groups.rb11
-rw-r--r--lib/api/helpers.rb4
-rw-r--r--lib/api/helpers/container_registry_helpers.rb2
-rw-r--r--lib/api/helpers/integrations_helpers.rb8
-rw-r--r--lib/api/helpers/internal_helpers.rb3
-rw-r--r--lib/api/helpers/members_helpers.rb2
-rw-r--r--lib/api/helpers/merge_requests_helpers.rb20
-rw-r--r--lib/api/helpers/rate_limiter.rb2
-rw-r--r--lib/api/internal/container_registry/migration.rb63
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/lint.rb11
-rw-r--r--lib/api/merge_requests.rb9
-rw-r--r--lib/api/package_files.rb18
-rw-r--r--lib/api/pagination_params.rb2
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--lib/api/projects_relation_builder.rb1
-rw-r--r--lib/api/repositories.rb3
-rw-r--r--lib/api/rubygem_packages.rb4
-rw-r--r--lib/api/scope.rb1
-rw-r--r--lib/api/settings.rb4
-rw-r--r--lib/api/support/token_with_expiration.rb24
-rw-r--r--lib/api/tags.rb6
-rw-r--r--lib/api/terraform/modules/v1/packages.rb8
-rw-r--r--lib/api/usage_data_non_sql_metrics.rb2
-rw-r--r--lib/api/usage_data_queries.rb2
-rw-r--r--lib/api/users.rb7
-rw-r--r--lib/backup/artifacts.rb4
-rw-r--r--lib/backup/builds.rb4
-rw-r--r--lib/backup/database.rb21
-rw-r--r--lib/backup/files.rb4
-rw-r--r--lib/backup/lfs.rb4
-rw-r--r--lib/backup/manager.rb158
-rw-r--r--lib/backup/packages.rb4
-rw-r--r--lib/backup/pages.rb4
-rw-r--r--lib/backup/registry.rb8
-rw-r--r--lib/backup/repositories.rb21
-rw-r--r--lib/backup/terraform_state.rb4
-rw-r--r--lib/backup/uploads.rb4
-rw-r--r--lib/banzai/filter/external_link_filter.rb4
-rw-r--r--lib/banzai/filter/inline_embeds_filter.rb4
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb2
-rw-r--r--lib/bitbucket_server/representation/repo.rb2
-rw-r--r--lib/bulk_imports/common/extractors/graphql_extractor.rb7
-rw-r--r--lib/bulk_imports/common/graphql/get_members_query.rb (renamed from lib/bulk_imports/groups/graphql/get_members_query.rb)37
-rw-r--r--lib/bulk_imports/common/pipelines/lfs_objects_pipeline.rb134
-rw-r--r--lib/bulk_imports/common/pipelines/members_pipeline.rb54
-rw-r--r--lib/bulk_imports/groups/graphql/get_group_query.rb10
-rw-r--r--lib/bulk_imports/groups/graphql/get_projects_query.rb10
-rw-r--r--lib/bulk_imports/groups/pipelines/members_pipeline.rb26
-rw-r--r--lib/bulk_imports/groups/stage.rb2
-rw-r--r--lib/bulk_imports/groups/transformers/member_attributes_transformer.rb43
-rw-r--r--lib/bulk_imports/projects/graphql/get_project_query.rb5
-rw-r--r--lib/bulk_imports/projects/graphql/get_repository_query.rb5
-rw-r--r--lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb7
-rw-r--r--lib/bulk_imports/projects/graphql/queryable.rb8
-rw-r--r--lib/bulk_imports/projects/stage.rb8
-rw-r--r--lib/container_registry/base_client.rb136
-rw-r--r--lib/container_registry/client.rb135
-rw-r--r--lib/container_registry/gitlab_api_client.rb76
-rw-r--r--lib/container_registry/migration.rb53
-rw-r--r--lib/container_registry/registry.rb18
-rw-r--r--lib/extracts_path.rb2
-rw-r--r--lib/extracts_ref.rb6
-rw-r--r--lib/feature.rb11
-rw-r--r--lib/generators/gitlab/snowplow_event_definition_generator.rb7
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb10
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb27
-rw-r--r--lib/gitlab/analytics/cycle_analytics/data_collector.rb6
-rw-r--r--lib/gitlab/application_context.rb16
-rw-r--r--lib/gitlab/application_rate_limiter.rb29
-rw-r--r--lib/gitlab/audit/ci_runner_token_author.rb41
-rw-r--r--lib/gitlab/audit/null_author.rb14
-rw-r--r--lib/gitlab/auth.rb40
-rw-r--r--lib/gitlab/auth/request_authenticator.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_ci_queuing_tables.rb153
-rw-r--r--lib/gitlab/background_migration/backfill_designs_relative_position.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_integrations_type_new.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_legacy_project_repositories.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route.rb38
-rw-r--r--lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb22
-rw-r--r--lib/gitlab/background_migration/backfill_user_namespace.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb13
-rw-r--r--lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb38
-rw-r--r--lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb5
-rw-r--r--lib/gitlab/background_migration/calculate_wiki_sizes.rb18
-rw-r--r--lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb32
-rw-r--r--lib/gitlab/background_migration/copy_column_using_background_migration_job.rb8
-rw-r--r--lib/gitlab/background_migration/delete_orphaned_deployments.rb2
-rw-r--r--lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb33
-rw-r--r--lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb13
-rw-r--r--lib/gitlab/background_migration/fix_pages_access_level.rb128
-rw-r--r--lib/gitlab/background_migration/generate_gitlab_subscriptions.rb13
-rw-r--r--lib/gitlab/background_migration/job_coordinator.rb28
-rw-r--r--lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb13
-rw-r--r--lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb124
-rw-r--r--lib/gitlab/background_migration/populate_issue_email_participants.rb28
-rw-r--r--lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb36
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_reads.rb84
-rw-r--r--lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb33
-rw-r--r--lib/gitlab/background_migration/recalculate_project_authorizations.rb12
-rw-r--r--lib/gitlab/background_migration/remove_vulnerability_finding_links.rb4
-rw-r--r--lib/gitlab/background_migration/sync_blocking_issues_count.rb13
-rw-r--r--lib/gitlab/background_migration/sync_issues_state_id.rb21
-rw-r--r--lib/gitlab/background_migration/sync_merge_requests_state_id.rb23
-rw-r--r--lib/gitlab/background_migration/update_timelogs_null_spent_at.rb11
-rw-r--r--lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb98
-rw-r--r--lib/gitlab/buffered_io.rb46
-rw-r--r--lib/gitlab/changelog/config.rb2
-rw-r--r--lib/gitlab/changelog/release.rb2
-rw-r--r--lib/gitlab/checks/branch_check.rb1
-rw-r--r--lib/gitlab/ci/badge/release/latest_release.rb42
-rw-r--r--lib/gitlab/ci/badge/release/metadata.rb25
-rw-r--r--lib/gitlab/ci/badge/release/template.rb44
-rw-r--r--lib/gitlab/ci/build/artifacts/expire_in_parser.rb20
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/changes.rb2
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/if.rb2
-rw-r--r--lib/gitlab/ci/config.rb10
-rw-r--r--lib/gitlab/ci/config/entry/default.rb4
-rw-r--r--lib/gitlab/ci/config/entry/job.rb10
-rw-r--r--lib/gitlab/ci/config/entry/jobs.rb2
-rw-r--r--lib/gitlab/ci/config/entry/root.rb8
-rw-r--r--lib/gitlab/ci/config/entry/script.rb24
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb14
-rw-r--r--lib/gitlab/ci/lint.rb41
-rw-r--r--lib/gitlab/ci/parsers/security/common.rb17
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/container-scanning-report-format.json741
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/coverage-fuzzing-report-format.json711
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dast-report-format.json1128
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dependency-scanning-report-format.json805
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/sast-report-format.json706
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/secret-detection-report-format.json729
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/container-scanning-report-format.json809
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/coverage-fuzzing-report-format.json779
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dast-report-format.json1196
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dependency-scanning-report-format.json873
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/sast-report-format.json774
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/secret-detection-report-format.json797
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/container-scanning-report-format.json871
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/coverage-fuzzing-report-format.json841
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dast-report-format.json1258
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dependency-scanning-report-format.json935
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/sast-report-format.json836
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/secret-detection-report-format.json859
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/container-scanning-report-format.json904
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/coverage-fuzzing-report-format.json874
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dast-report-format.json1291
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dependency-scanning-report-format.json968
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/sast-report-format.json869
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/secret-detection-report-format.json892
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/cluster-image-scanning-report-format.json977
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/container-scanning-report-format.json904
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/coverage-fuzzing-report-format.json874
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dast-report-format.json1291
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dependency-scanning-report-format.json968
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/sast-report-format.json869
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/secret-detection-report-format.json892
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/cluster-image-scanning-report-format.json977
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/container-scanning-report-format.json910
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/coverage-fuzzing-report-format.json874
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dast-report-format.json1291
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dependency-scanning-report-format.json968
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/sast-report-format.json869
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/secret-detection-report-format.json892
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/cluster-image-scanning-report-format.json977
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/container-scanning-report-format.json910
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/coverage-fuzzing-report-format.json874
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dast-report-format.json1291
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dependency-scanning-report-format.json968
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/sast-report-format.json869
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/secret-detection-report-format.json892
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/cluster-image-scanning-report-format.json977
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/container-scanning-report-format.json911
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/coverage-fuzzing-report-format.json874
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dast-report-format.json1291
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dependency-scanning-report-format.json968
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/sast-report-format.json869
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/secret-detection-report-format.json892
l---------lib/gitlab/ci/parsers/security/validators/schemas/dependency-scanning-report-format.json1
-rw-r--r--lib/gitlab/ci/parsers/test/junit.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/create_deployments.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_environments.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb2
-rw-r--r--lib/gitlab/ci/pipeline/logger.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb35
-rw-r--r--lib/gitlab/ci/reports/codequality_reports.rb5
-rw-r--r--lib/gitlab/ci/reports/security/finding.rb25
-rw-r--r--lib/gitlab/ci/reports/security/finding_key.rb2
-rw-r--r--lib/gitlab/ci/reports/security/report.rb2
-rw-r--r--lib/gitlab/ci/runner_instructions/templates/linux/install.sh6
-rw-r--r--lib/gitlab/ci/runner_instructions/templates/osx/install.sh6
-rw-r--r--lib/gitlab/ci/runner_instructions/templates/windows/install.ps18
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml177
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml21
-rw-r--r--lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml38
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml27
-rw-r--r--lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml35
-rw-r--r--lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml47
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml168
-rw-r--r--lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml41
-rw-r--r--lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/variables/builder.rb55
-rw-r--r--lib/gitlab/ci/variables/builder/instance.rb23
-rw-r--r--lib/gitlab/ci/variables/builder/project.rb25
-rw-r--r--lib/gitlab/config/entry/validators.rb35
-rw-r--r--lib/gitlab/console.rb41
-rw-r--r--lib/gitlab/current_settings.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/base.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/commit.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/deploy.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/issue.rb4
-rw-r--r--lib/gitlab/daemon.rb2
-rw-r--r--lib/gitlab/database.rb20
-rw-r--r--lib/gitlab/database/background_migration/batch_optimizer.rb6
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb58
-rw-r--r--lib/gitlab/database/background_migration/batched_job_transition_log.rb27
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb6
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_runner.rb7
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_wrapper.rb26
-rw-r--r--lib/gitlab/database/dynamic_model_helpers.rb15
-rw-r--r--lib/gitlab/database/each_database.rb32
-rw-r--r--lib/gitlab/database/gitlab_schema.rb6
-rw-r--r--lib/gitlab/database/gitlab_schemas.yml3
-rw-r--r--lib/gitlab/database/load_balancing/configuration.rb19
-rw-r--r--lib/gitlab/database/loose_foreign_keys.rb6
-rw-r--r--lib/gitlab/database/migration_helpers.rb28
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb30
-rw-r--r--lib/gitlab/database/migrations/instrumentation.rb24
-rw-r--r--lib/gitlab/database/migrations/lock_retry_mixin.rb5
-rw-r--r--lib/gitlab/database/migrations/observation.rb3
-rw-r--r--lib/gitlab/database/partitioning.rb25
-rw-r--r--lib/gitlab/database/partitioning/partition_manager.rb27
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb2
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb1
-rw-r--r--lib/gitlab/database/query_analyzers/base.rb8
-rw-r--r--lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb5
-rw-r--r--lib/gitlab/database/schema_helpers.rb1
-rw-r--r--lib/gitlab/database/shared_model.rb4
-rw-r--r--lib/gitlab/database/with_lock_retries.rb2
-rw-r--r--lib/gitlab/email/handler/create_note_handler.rb13
-rw-r--r--lib/gitlab/event_store.rb15
-rw-r--r--lib/gitlab/event_store/store.rb2
-rw-r--r--lib/gitlab/event_store/subscriber.rb9
-rw-r--r--lib/gitlab/experiment/rollout/feature.rb67
-rw-r--r--lib/gitlab/git/reference_update_error.rb16
-rw-r--r--lib/gitlab/git/repository.rb12
-rw-r--r--lib/gitlab/git_access.rb10
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb12
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb5
-rw-r--r--lib/gitlab/github_import/importer/diff_note_importer.rb13
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/releases_importer.rb4
-rw-r--r--lib/gitlab/github_import/importer/repository_importer.rb2
-rw-r--r--lib/gitlab/github_import/object_counter.rb6
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb22
-rw-r--r--lib/gitlab/gon_helper.rb1
-rw-r--r--lib/gitlab/graphql/project/dast_profile_connection_extension.rb22
-rw-r--r--lib/gitlab/hook_data/project_builder.rb21
-rw-r--r--lib/gitlab/http.rb3
-rw-r--r--lib/gitlab/http_connection_adapter.rb38
-rw-r--r--lib/gitlab/i18n.rb20
-rw-r--r--lib/gitlab/import_export/base/object_builder.rb8
-rw-r--r--lib/gitlab/import_export/command_line_util.rb12
-rw-r--r--lib/gitlab/import_export/group/object_builder.rb6
-rw-r--r--lib/gitlab/import_export/json/streaming_serializer.rb9
-rw-r--r--lib/gitlab/import_export/project/object_builder.rb6
-rw-r--r--lib/gitlab/import_export/saver.rb47
-rw-r--r--lib/gitlab/json.rb11
-rw-r--r--lib/gitlab/legacy_github_import/release_formatter.rb2
-rw-r--r--lib/gitlab/metrics/boot_time_tracker.rb34
-rw-r--r--lib/gitlab/metrics/exporter/base_exporter.rb8
-rw-r--r--lib/gitlab/metrics/exporter/web_exporter.rb55
-rw-r--r--lib/gitlab/metrics/rails_slis.rb2
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb36
-rw-r--r--lib/gitlab/metrics/system.rb69
-rw-r--r--lib/gitlab/middleware/memory_report.rb45
-rw-r--r--lib/gitlab/net_http_adapter.rb32
-rw-r--r--lib/gitlab/omniauth_initializer.rb4
-rw-r--r--lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb1
-rw-r--r--lib/gitlab/pipeline_scope_counts.rb41
-rw-r--r--lib/gitlab/popen.rb11
-rw-r--r--lib/gitlab/process_memory_cache/helper.rb2
-rw-r--r--lib/gitlab/project_authorizations.rb6
-rw-r--r--lib/gitlab/project_template.rb2
-rw-r--r--lib/gitlab/quick_actions/command_definition.rb12
-rw-r--r--lib/gitlab/quick_actions/issue_actions.rb10
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb77
-rw-r--r--lib/gitlab/rack_attack/request.rb49
-rw-r--r--lib/gitlab/regex.rb4
-rw-r--r--lib/gitlab/runtime.rb6
-rw-r--r--lib/gitlab/saas.rb2
-rw-r--r--lib/gitlab/search/found_blob.rb4
-rw-r--r--lib/gitlab/security/scan_configuration.rb18
-rw-r--r--lib/gitlab/setup_helper.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/size_limiter/validator.rb2
-rw-r--r--lib/gitlab/sidekiq_queue.rb4
-rw-r--r--lib/gitlab/ssh_public_key.rb58
-rw-r--r--lib/gitlab/subscription_portal.rb4
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb4
-rw-r--r--lib/gitlab/untrusted_regexp/ruby_syntax.rb4
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb2
-rw-r--r--lib/gitlab/usage/service_ping_report.rb36
-rw-r--r--lib/gitlab/usage_data.rb13
-rw-r--r--lib/gitlab/usage_data_counters.rb2
-rw-r--r--lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter.rb28
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml60
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml7
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml6
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml8
-rw-r--r--lib/gitlab/usage_data_counters/web_ide_counter.rb8
-rw-r--r--lib/gitlab/utils.rb7
-rw-r--r--lib/gitlab/web_ide/config/entry/terminal.rb2
-rw-r--r--lib/gitlab_edition.rb10
-rw-r--r--lib/google_api/cloud_platform/client.rb52
-rw-r--r--lib/learn_gitlab/project.rb3
-rw-r--r--lib/security/ci_configuration/base_build_action.rb1
-rw-r--r--lib/security/ci_configuration/container_scanning_build_action.rb30
-rw-r--r--lib/sidebars/concerns/work_item_hierarchy.rb26
-rw-r--r--lib/sidebars/projects/menus/ci_cd_menu.rb6
-rw-r--r--lib/sidebars/projects/menus/project_information_menu.rb3
-rw-r--r--lib/system_check/app/git_config_check.rb44
-rw-r--r--lib/system_check/app/git_version_check.rb31
-rw-r--r--lib/system_check/orphans/repository_check.rb4
-rw-r--r--lib/system_check/rake_task/app_task.rb2
-rw-r--r--lib/tasks/gitlab/assets.rake32
-rw-r--r--lib/tasks/gitlab/backup.rake284
-rw-r--r--lib/tasks/gitlab/banzai.rake20
-rw-r--r--lib/tasks/gitlab/db.rake44
-rw-r--r--lib/tasks/gitlab/dependency_proxy/migrate.rake33
-rw-r--r--lib/tasks/gitlab/docs/compile_deprecations.rake32
-rw-r--r--lib/tasks/gitlab/info.rake4
-rw-r--r--lib/tasks/gitlab/tw/codeowners.rake111
-rw-r--r--lib/tasks/gitlab/usage_data.rake6
-rw-r--r--locale/am_ET/gitlab.po1518
-rw-r--r--locale/ar_SA/gitlab.po1546
-rw-r--r--locale/as_IN/gitlab.po1518
-rw-r--r--locale/az_AZ/gitlab.po1518
-rw-r--r--locale/ba_RU/gitlab.po1511
-rw-r--r--locale/bg/gitlab.po1518
-rw-r--r--locale/bn_BD/gitlab.po1518
-rw-r--r--locale/bn_IN/gitlab.po1518
-rw-r--r--locale/br_FR/gitlab.po1539
-rw-r--r--locale/bs_BA/gitlab.po1525
-rw-r--r--locale/ca_ES/gitlab.po1518
-rw-r--r--locale/cs_CZ/gitlab.po1532
-rw-r--r--locale/cy_GB/gitlab.po1546
-rw-r--r--locale/da_DK/gitlab.po1576
-rw-r--r--locale/de/gitlab.po1570
-rw-r--r--locale/el_GR/gitlab.po1518
-rw-r--r--locale/eo/gitlab.po1518
-rw-r--r--locale/es/gitlab.po2480
-rw-r--r--locale/et_EE/gitlab.po1518
-rw-r--r--locale/fa_IR/gitlab.po1518
-rw-r--r--locale/fi_FI/gitlab.po1518
-rw-r--r--locale/fil_PH/gitlab.po1518
-rw-r--r--locale/fr/gitlab.po1620
-rw-r--r--locale/gitlab.pot1651
-rw-r--r--locale/gl_ES/gitlab.po1518
-rw-r--r--locale/he_IL/gitlab.po1532
-rw-r--r--locale/hi_IN/gitlab.po1518
-rw-r--r--locale/hr_HR/gitlab.po1525
-rw-r--r--locale/hu_HU/gitlab.po1518
-rw-r--r--locale/hy_AM/gitlab.po1518
-rw-r--r--locale/id_ID/gitlab.po1511
-rw-r--r--locale/ig_NG/gitlab.po1511
-rw-r--r--locale/is_IS/gitlab.po1518
-rw-r--r--locale/it/gitlab.po1518
-rw-r--r--locale/ja/gitlab.po1553
-rw-r--r--locale/ka_GE/gitlab.po1518
-rw-r--r--locale/kab/gitlab.po1518
-rw-r--r--locale/ko/gitlab.po2147
-rw-r--r--locale/ku_TR/gitlab.po1518
-rw-r--r--locale/ky_KG/gitlab.po1518
-rw-r--r--locale/lt_LT/gitlab.po1532
-rw-r--r--locale/mk_MK/gitlab.po1518
-rw-r--r--locale/mn_MN/gitlab.po1518
-rw-r--r--locale/nb_NO/gitlab.po1550
-rw-r--r--locale/nl_NL/gitlab.po1518
-rw-r--r--locale/or_IN/gitlab.po43744
-rw-r--r--locale/pa_IN/gitlab.po1518
-rw-r--r--locale/pl_PL/gitlab.po1534
-rw-r--r--locale/pt_BR/gitlab.po2006
-rw-r--r--locale/pt_PT/gitlab.po1518
-rw-r--r--locale/ro_RO/gitlab.po1769
-rw-r--r--locale/ru/gitlab.po3522
-rw-r--r--locale/si_LK/gitlab.po1518
-rw-r--r--locale/sk_SK/gitlab.po1532
-rw-r--r--locale/sl_SI/gitlab.po1532
-rw-r--r--locale/sq_AL/gitlab.po1518
-rw-r--r--locale/sr_CS/gitlab.po1525
-rw-r--r--locale/sr_SP/gitlab.po1525
-rw-r--r--locale/sv_SE/gitlab.po1518
-rw-r--r--locale/sw_KE/gitlab.po1518
-rw-r--r--locale/ta_IN/gitlab.po1518
-rw-r--r--locale/tr_TR/gitlab.po1532
-rw-r--r--locale/uk/gitlab.po1668
-rw-r--r--locale/ur_PK/gitlab.po1518
-rw-r--r--locale/uz_UZ/gitlab.po1518
-rw-r--r--locale/vi_VN/gitlab.po1511
-rw-r--r--locale/zh_CN/gitlab.po1915
-rw-r--r--locale/zh_HK/gitlab.po1511
-rw-r--r--locale/zh_TW/gitlab.po1511
-rw-r--r--metrics_server/dependencies.rb1
-rw-r--r--metrics_server/metrics_server.rb50
-rw-r--r--package.json63
-rw-r--r--qa/Dockerfile1
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock8
-rw-r--r--qa/lib/gitlab/page/admin/subscription.rb31
-rw-r--r--qa/lib/gitlab/page/admin/subscription.stub.rb106
-rw-r--r--qa/qa.rb4
-rw-r--r--qa/qa/fixtures/package_managers/composer/composer.json.erb13
-rw-r--r--qa/qa/fixtures/package_managers/composer/composer_upload_package.yaml.erb13
-rw-r--r--qa/qa/fixtures/package_managers/conan/conan_upload_install_package.yaml.erb12
-rw-r--r--qa/qa/fixtures/package_managers/generic/generic_upload_install_package.yaml.erb18
-rw-r--r--qa/qa/fixtures/package_managers/helm/Chart.yaml.erb6
-rw-r--r--qa/qa/fixtures/package_managers/helm/helm_install_package.yaml.erb11
-rw-r--r--qa/qa/fixtures/package_managers/helm/helm_upload_package.yaml.erb14
-rw-r--r--qa/qa/fixtures/package_managers/maven/build_install.gradle.erb28
-rw-r--r--qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb27
-rw-r--r--qa/qa/fixtures/package_managers/maven/client_pom.xml.erb19
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/package_pom.xml.erb22
-rw-r--r--qa/qa/fixtures/package_managers/maven/settings.xml.erb16
-rw-r--r--qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb16
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb21
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb31
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_upload_package_instance.yaml.erb14
-rw-r--r--qa/qa/fixtures/package_managers/npm/package_instance.json.erb8
-rw-r--r--qa/qa/fixtures/package_managers/npm/package_project.json.erb8
-rw-r--r--qa/qa/fixtures/package_managers/nuget/nuget_install_package.yaml.erb15
-rw-r--r--qa/qa/fixtures/package_managers/nuget/nuget_upload_package.yaml.erb17
-rw-r--r--qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb19
-rw-r--r--qa/qa/fixtures/package_managers/pypi/setup.py.erb16
-rw-r--r--qa/qa/fixtures/package_managers/rubygems/package.gemspec.erb39
-rw-r--r--qa/qa/fixtures/package_managers/rubygems/rubygems_upload_package.yaml.erb15
-rw-r--r--qa/qa/page/component/badges.rb53
-rw-r--r--qa/qa/page/component/blob_content.rb4
-rw-r--r--qa/qa/page/component/design_management.rb2
-rw-r--r--qa/qa/page/component/invite_members_modal.rb6
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb2
-rw-r--r--qa/qa/page/component/members_filter.rb26
-rw-r--r--qa/qa/page/component/namespace_select.rb29
-rw-r--r--qa/qa/page/component/wiki_page_form.rb13
-rw-r--r--qa/qa/page/group/members.rb3
-rw-r--r--qa/qa/page/group/settings/general.rb25
-rw-r--r--qa/qa/page/main/login.rb1
-rw-r--r--qa/qa/page/merge_request/show.rb43
-rw-r--r--qa/qa/page/project/members.rb1
-rw-r--r--qa/qa/page/project/new.rb5
-rw-r--r--qa/qa/page/project/pipeline/index.rb8
-rw-r--r--qa/qa/page/project/pipeline/show.rb25
-rw-r--r--qa/qa/page/project/settings/advanced.rb15
-rw-r--r--qa/qa/page/project/settings/main.rb8
-rw-r--r--qa/qa/page/project/show.rb8
-rw-r--r--qa/qa/page/project/web_ide/edit.rb2
-rw-r--r--qa/qa/page/trials/new.rb1
-rw-r--r--qa/qa/resource/api_fabricator.rb17
-rw-r--r--qa/qa/resource/badge_base.rb25
-rw-r--r--qa/qa/resource/base.rb78
-rw-r--r--qa/qa/resource/clusters/agent.rb1
-rw-r--r--qa/qa/resource/clusters/agent_token.rb1
-rw-r--r--qa/qa/resource/fork.rb2
-rw-r--r--qa/qa/resource/group.rb14
-rw-r--r--qa/qa/resource/group_badge.rb8
-rw-r--r--qa/qa/resource/group_base.rb2
-rw-r--r--qa/qa/resource/group_milestone.rb2
-rw-r--r--qa/qa/resource/project.rb1
-rw-r--r--qa/qa/resource/project_badge.rb21
-rw-r--r--qa/qa/resource/project_web_hook.rb65
-rw-r--r--qa/qa/resource/protected_branch.rb18
-rw-r--r--qa/qa/resource/reusable.rb130
-rw-r--r--qa/qa/resource/reusable_collection.rb56
-rw-r--r--qa/qa/resource/reusable_group.rb51
-rw-r--r--qa/qa/resource/reusable_project.rb42
-rw-r--r--qa/qa/resource/sandbox.rb8
-rw-r--r--qa/qa/runtime/env.rb24
-rw-r--r--qa/qa/runtime/example.rb15
-rw-r--r--qa/qa/runtime/fixtures.rb8
-rw-r--r--qa/qa/runtime/logger.rb10
-rw-r--r--qa/qa/scenario/template.rb3
-rw-r--r--qa/qa/service/cluster_provider/gcloud.rb2
-rw-r--r--qa/qa/service/docker_run/smocker.rb56
-rw-r--r--qa/qa/service/praefect_manager.rb102
-rw-r--r--qa/qa/service/shellout.rb11
-rw-r--r--qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb12
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb22
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb8
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb8
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb5
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb70
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb21
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb57
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb129
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb51
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb37
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb72
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb31
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb8
-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/delete_file_from_snippet_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb98
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb11
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb45
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb43
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb192
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb147
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb214
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb112
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb88
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb62
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb63
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb76
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb8
-rw-r--r--qa/qa/specs/helpers/quarantine.rb4
-rw-r--r--qa/qa/specs/runner.rb35
-rw-r--r--qa/qa/support/api.rb12
-rw-r--r--qa/qa/support/formatters/allure_metadata_formatter.rb32
-rw-r--r--qa/qa/support/formatters/test_stats_formatter.rb111
-rw-r--r--qa/qa/support/page/logging.rb12
-rw-r--r--qa/qa/support/repeater.rb5
-rw-r--r--qa/qa/tools/delete_test_resources.rb87
-rw-r--r--qa/qa/tools/initialize_gitlab_auth.rb2
-rw-r--r--qa/qa/tools/reliable_report.rb2
-rw-r--r--qa/qa/tools/test_resource_data_processor.rb107
-rw-r--r--qa/qa/vendor/smocker/event_payload.rb49
-rw-r--r--qa/qa/vendor/smocker/history_response.rb52
-rw-r--r--qa/qa/vendor/smocker/smocker_api.rb140
-rw-r--r--qa/spec/resource/base_spec.rb100
-rw-r--r--qa/spec/resource/reusable_collection_spec.rb110
-rw-r--r--qa/spec/spec_helper.rb19
-rw-r--r--qa/spec/specs/helpers/quarantine_spec.rb14
-rw-r--r--qa/spec/specs/runner_spec.rb38
-rw-r--r--qa/spec/support/formatters/test_stats_formatter_spec.rb60
-rw-r--r--qa/spec/support/shared_contexts/packages_registry_shared_context.rb2
-rw-r--r--qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb18
-rw-r--r--qa/spec/tools/reliable_report_spec.rb2
-rw-r--r--qa/spec/tools/test_resources_data_processor_spec.rb63
-rw-r--r--rubocop/cop/file_decompression.rb45
-rw-r--r--rubocop/cop/gitlab/event_store_subscriber.rb71
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb4
-rw-r--r--rubocop/cop/migration/schedule_async.rb13
-rw-r--r--rubocop/cop/scalability/bulk_perform_with_context.rb8
-rw-r--r--rubocop/cop/scalability/cron_worker_context.rb2
-rw-r--r--rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication.rb154
-rwxr-xr-xscripts/decomposition/generate-loose-foreign-key405
-rwxr-xr-xscripts/gather-test-memory-data22
-rwxr-xr-xscripts/generate-gems-memory-metrics-static19
-rwxr-xr-xscripts/generate-gems-size-metrics-static31
-rwxr-xr-xscripts/insert-rspec-profiling-data2
-rwxr-xr-xscripts/lint-doc.sh2
-rwxr-xr-xscripts/rspec_bisect_flaky10
-rw-r--r--scripts/rspec_helpers.sh156
-rwxr-xr-xscripts/setup/find-jh-branch.rb2
-rwxr-xr-xscripts/trigger-build.rb (renamed from scripts/trigger-build)100
-rw-r--r--scripts/utils.sh13
-rw-r--r--sidekiq_cluster/cli.rb4
-rw-r--r--spec/bin/feature_flag_spec.rb40
-rw-r--r--spec/channels/application_cable/connection_spec.rb8
-rw-r--r--spec/commands/metrics_server/metrics_server_spec.rb81
-rw-r--r--spec/commands/sidekiq_cluster/cli_spec.rb23
-rw-r--r--spec/controllers/admin/instance_review_controller_spec.rb2
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb7
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb2
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb24
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb18
-rw-r--r--spec/controllers/graphql_controller_spec.rb20
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb7
-rw-r--r--spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb29
-rw-r--r--spec/controllers/groups/releases_controller_spec.rb8
-rw-r--r--spec/controllers/groups/runners_controller_spec.rb4
-rw-r--r--spec/controllers/groups_controller_spec.rb23
-rw-r--r--spec/controllers/metrics_controller_spec.rb6
-rw-r--r--spec/controllers/oauth/authorizations_controller_spec.rb94
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/autocomplete_sources_controller_spec.rb60
-rw-r--r--spec/controllers/projects/avatars_controller_spec.rb4
-rw-r--r--spec/controllers/projects/badges_controller_spec.rb168
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb30
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb7
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb12
-rw-r--r--spec/controllers/projects/commits_controller_spec.rb34
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb25
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb12
-rw-r--r--spec/controllers/projects/group_links_controller_spec.rb2
-rw-r--r--spec/controllers/projects/hooks_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb18
-rw-r--r--spec/controllers/projects/merge_requests/conflicts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests/creations_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests/drafts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb34
-rw-r--r--spec/controllers/projects/mirrors_controller_spec.rb10
-rw-r--r--spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb12
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb2
-rw-r--r--spec/controllers/projects/refs_controller_spec.rb17
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb32
-rw-r--r--spec/controllers/projects/runners_controller_spec.rb4
-rw-r--r--spec/controllers/projects/service_ping_controller_spec.rb29
-rw-r--r--spec/controllers/projects/settings/repository_controller_spec.rb14
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb9
-rw-r--r--spec/controllers/projects_controller_spec.rb20
-rw-r--r--spec/controllers/registrations_controller_spec.rb22
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb4
-rw-r--r--spec/controllers/search_controller_spec.rb3
-rw-r--r--spec/crystalball_env.rb2
-rw-r--r--spec/db/schema_spec.rb2
-rw-r--r--spec/events/projects/project_deleted_event_spec.rb34
-rw-r--r--spec/experiments/application_experiment_spec.rb103
-rw-r--r--spec/experiments/new_project_readme_content_experiment_spec.rb38
-rw-r--r--spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb20
-rw-r--r--spec/factories/ci/build_metadata.rb7
-rw-r--r--spec/factories/ci/runners.rb5
-rw-r--r--spec/factories/container_repositories.rb46
-rw-r--r--spec/factories/gitlab/database/background_migration/batched_jobs.rb16
-rw-r--r--spec/factories/go_module_commits.rb4
-rw-r--r--spec/factories/group_members.rb12
-rw-r--r--spec/factories/issues.rb9
-rw-r--r--spec/factories/keys.rb25
-rw-r--r--spec/factories/labels.rb7
-rw-r--r--spec/factories/namespace_statistics.rb7
-rw-r--r--spec/factories/project_members.rb12
-rw-r--r--spec/factories/projects.rb2
-rw-r--r--spec/factories/usage_data.rb8
-rw-r--r--spec/factories/work_items.rb13
-rw-r--r--spec/features/admin/admin_groups_spec.rb17
-rw-r--r--spec/features/admin/admin_mode/logout_spec.rb2
-rw-r--r--spec/features/admin/admin_runners_spec.rb52
-rw-r--r--spec/features/admin/admin_sees_background_migrations_spec.rb6
-rw-r--r--spec/features/admin/admin_settings_spec.rb56
-rw-r--r--spec/features/admin/integrations/instance_integrations_spec.rb15
-rw-r--r--spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb15
-rw-r--r--spec/features/admin/users/users_spec.rb17
-rw-r--r--spec/features/boards/board_filters_spec.rb13
-rw-r--r--spec/features/boards/boards_spec.rb6
-rw-r--r--spec/features/boards/new_issue_spec.rb19
-rw-r--r--spec/features/breadcrumbs_schema_markup_spec.rb6
-rw-r--r--spec/features/clusters/create_agent_spec.rb1
-rw-r--r--spec/features/contextual_sidebar_spec.rb2
-rw-r--r--spec/features/cycle_analytics_spec.rb4
-rw-r--r--spec/features/dashboard/groups_list_spec.rb65
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb15
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb4
-rw-r--r--spec/features/dashboard/snippets_spec.rb6
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb2
-rw-r--r--spec/features/error_tracking/user_searches_sentry_errors_spec.rb2
-rw-r--r--spec/features/error_tracking/user_sees_error_details_spec.rb2
-rw-r--r--spec/features/error_tracking/user_sees_error_index_spec.rb4
-rw-r--r--spec/features/file_uploads/attachment_spec.rb2
-rw-r--r--spec/features/file_uploads/git_lfs_spec.rb2
-rw-r--r--spec/features/file_uploads/maven_package_spec.rb2
-rw-r--r--spec/features/file_uploads/nuget_package_spec.rb2
-rw-r--r--spec/features/file_uploads/rubygem_package_spec.rb2
-rw-r--r--spec/features/gitlab_experiments_spec.rb4
-rw-r--r--spec/features/groups/group_settings_spec.rb45
-rw-r--r--spec/features/groups/integrations/group_integrations_spec.rb15
-rw-r--r--spec/features/groups/members/leave_group_spec.rb2
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb20
-rw-r--r--spec/features/groups_spec.rb6
-rw-r--r--spec/features/ide/user_commits_changes_spec.rb2
-rw-r--r--spec/features/ide/user_opens_merge_request_spec.rb2
-rw-r--r--spec/features/issuables/markdown_references/internal_references_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/dropdown_base_spec.rb17
-rw-r--r--spec/features/issues/filtered_search/recent_searches_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb778
-rw-r--r--spec/features/issues/keyboard_shortcut_spec.rb4
-rw-r--r--spec/features/issues/todo_spec.rb8
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb1
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb25
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb2
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb3
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb83
-rw-r--r--spec/features/jira_connect/branches_spec.rb4
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb2
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb18
-rw-r--r--spec/features/merge_request/user_awards_emoji_spec.rb1
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb52
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_assignees_sidebar_spec.rb2
-rw-r--r--spec/features/merge_request/user_expands_diff_spec.rb4
-rw-r--r--spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb45
-rw-r--r--spec/features/merge_request/user_merges_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb4
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb60
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb12
-rw-r--r--spec/features/merge_request/user_rebases_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_resolves_wip_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_reviews_image_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb11
-rw-r--r--spec/features/merge_request/user_sees_deleted_target_branch_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb6
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb25
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb22
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb26
-rw-r--r--spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb7
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb10
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb12
-rw-r--r--spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb2
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb26
-rw-r--r--spec/features/merge_requests/user_mass_updates_spec.rb14
-rw-r--r--spec/features/monitor_sidebar_link_spec.rb5
-rw-r--r--spec/features/participants_autocomplete_spec.rb23
-rw-r--r--spec/features/profiles/keys_spec.rb7
-rw-r--r--spec/features/profiles/password_spec.rb2
-rw-r--r--spec/features/projects/active_tabs_spec.rb2
-rw-r--r--spec/features/projects/activity/rss_spec.rb4
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb1583
-rw-r--r--spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb2
-rw-r--r--spec/features/projects/branches/user_views_branches_spec.rb2
-rw-r--r--spec/features/projects/ci/editor_spec.rb61
-rw-r--r--spec/features/projects/cluster_agents_spec.rb7
-rw-r--r--spec/features/projects/clusters_spec.rb3
-rw-r--r--spec/features/projects/environments/environment_spec.rb23
-rw-r--r--spec/features/projects/environments_pod_logs_spec.rb2
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/edit_file_soft_wrap_spec.rb2
-rw-r--r--spec/features/projects/files/editing_a_file_spec.rb2
-rw-r--r--spec/features/projects/files/files_sort_submodules_with_folders_spec.rb2
-rw-r--r--spec/features/projects/files/find_file_keyboard_spec.rb2
-rw-r--r--spec/features/projects/files/gitignore_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/project_owner_creates_license_file_spec.rb2
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb2
-rw-r--r--spec/features/projects/files/template_type_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb29
-rw-r--r--spec/features/projects/files/user_browses_lfs_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_searches_for_files_spec.rb2
-rw-r--r--spec/features/projects/gfm_autocomplete_load_spec.rb2
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb2
-rw-r--r--spec/features/projects/integrations/disable_triggers_spec.rb (renamed from spec/features/projects/services/disable_triggers_spec.rb)12
-rw-r--r--spec/features/projects/integrations/project_integrations_spec.rb15
-rw-r--r--spec/features/projects/integrations/prometheus_external_alerts_spec.rb (renamed from spec/features/projects/services/prometheus_external_alerts_spec.rb)2
-rw-r--r--spec/features/projects/integrations/user_activates_asana_spec.rb4
-rw-r--r--spec/features/projects/integrations/user_activates_assembla_spec.rb4
-rw-r--r--spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb4
-rw-r--r--spec/features/projects/integrations/user_activates_emails_on_push_spec.rb (renamed from spec/features/projects/services/user_activates_emails_on_push_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_flowdock_spec.rb4
-rw-r--r--spec/features/projects/integrations/user_activates_irker_spec.rb (renamed from spec/features/projects/services/user_activates_irker_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_issue_tracker_spec.rb (renamed from spec/features/projects/services/user_activates_issue_tracker_spec.rb)12
-rw-r--r--spec/features/projects/integrations/user_activates_jetbrains_teamcity_ci_spec.rb (renamed from spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_jira_spec.rb14
-rw-r--r--spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb (renamed from spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb)14
-rw-r--r--spec/features/projects/integrations/user_activates_packagist_spec.rb (renamed from spec/features/projects/services/user_activates_packagist_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb4
-rw-r--r--spec/features/projects/integrations/user_activates_prometheus_spec.rb (renamed from spec/features/projects/services/user_activates_prometheus_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_pushover_spec.rb (renamed from spec/features/projects/services/user_activates_pushover_spec.rb)4
-rw-r--r--spec/features/projects/integrations/user_activates_slack_notifications_spec.rb (renamed from spec/features/projects/services/user_activates_slack_notifications_spec.rb)8
-rw-r--r--spec/features/projects/integrations/user_activates_slack_slash_command_spec.rb (renamed from spec/features/projects/services/user_activates_slack_slash_command_spec.rb)2
-rw-r--r--spec/features/projects/integrations/user_uses_inherited_settings_spec.rb2
-rw-r--r--spec/features/projects/integrations/user_views_services_spec.rb (renamed from spec/features/projects/services/user_views_services_spec.rb)6
-rw-r--r--spec/features/projects/issues/design_management/user_uploads_designs_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb2
-rw-r--r--spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb2
-rw-r--r--spec/features/projects/members/invite_group_spec.rb126
-rw-r--r--spec/features/projects/members/member_leaves_project_spec.rb13
-rw-r--r--spec/features/projects/members/owner_cannot_leave_project_spec.rb2
-rw-r--r--spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb2
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb2
-rw-r--r--spec/features/projects/navbar_spec.rb2
-rw-r--r--spec/features/projects/network_graph_spec.rb2
-rw-r--r--spec/features/projects/new_project_spec.rb91
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb120
-rw-r--r--spec/features/projects/settings/monitor_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/packages_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/project_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb2
-rw-r--r--spec/features/projects/show/redirects_spec.rb2
-rw-r--r--spec/features/projects/show/user_manages_notifications_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_deletion_failure_message_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_git_instructions_spec.rb4
-rw-r--r--spec/features/projects/tree/tree_show_spec.rb8
-rw-r--r--spec/features/projects/user_changes_project_visibility_spec.rb10
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb2
-rw-r--r--spec/features/projects/view_on_env_spec.rb1
-rw-r--r--spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb2
-rw-r--r--spec/features/projects_spec.rb12
-rw-r--r--spec/features/protected_tags_spec.rb2
-rw-r--r--spec/features/security/project/snippet/internal_access_spec.rb4
-rw-r--r--spec/features/security/project/snippet/private_access_spec.rb2
-rw-r--r--spec/features/security/project/snippet/public_access_spec.rb6
-rw-r--r--spec/features/snippets_spec.rb2
-rw-r--r--spec/features/triggers_spec.rb6
-rw-r--r--spec/features/user_sorts_things_spec.rb12
-rw-r--r--spec/features/users/bizible_csp_spec.rb15
-rw-r--r--spec/features/users/logout_spec.rb2
-rw-r--r--spec/finders/autocomplete/users_finder_spec.rb56
-rw-r--r--spec/finders/ci/daily_build_group_report_results_finder_spec.rb2
-rw-r--r--spec/finders/ci/jobs_finder_spec.rb37
-rw-r--r--spec/finders/ci/runners_finder_spec.rb32
-rw-r--r--spec/finders/clusters/agents_finder_spec.rb6
-rw-r--r--spec/finders/crm/contacts_finder_spec.rb70
-rw-r--r--spec/finders/deployments_finder_spec.rb6
-rw-r--r--spec/finders/environments/environments_by_deployments_finder_spec.rb16
-rw-r--r--spec/finders/group_descendants_finder_spec.rb92
-rw-r--r--spec/finders/group_projects_finder_spec.rb92
-rw-r--r--spec/finders/issues_finder_spec.rb30
-rw-r--r--spec/finders/merge_request_target_project_finder_spec.rb4
-rw-r--r--spec/finders/merge_requests_finder/params_spec.rb23
-rw-r--r--spec/finders/merge_requests_finder_spec.rb16
-rw-r--r--spec/finders/packages/conan/package_file_finder_spec.rb12
-rw-r--r--spec/finders/packages/package_file_finder_spec.rb10
-rw-r--r--spec/finders/releases_finder_spec.rb72
-rw-r--r--spec/finders/tags_finder_spec.rb15
-rw-r--r--spec/finders/template_finder_spec.rb7
-rw-r--r--spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json3
-rw-r--r--spec/fixtures/api/schemas/entities/member_user.json5
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/deployment.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/merge_request.json221
-rw-r--r--spec/frontend/__helpers__/matchers/to_match_interpolated_text.js15
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js19
-rw-r--r--spec/frontend/__helpers__/test_apollo_link.js5
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js13
-rw-r--r--spec/frontend/actioncable_link_spec.js2
-rw-r--r--spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap1
-rw-r--r--spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js50
-rw-r--r--spec/frontend/admin/users/components/modals/delete_user_modal_spec.js19
-rw-r--r--spec/frontend/admin/users/components/modals/user_modal_manager_spec.js22
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js11
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js3
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js34
-rw-r--r--spec/frontend/alerts_settings/components/mocks/apollo_mock.js6
-rw-r--r--spec/frontend/analytics/shared/components/daterange_spec.js41
-rw-r--r--spec/frontend/analytics/shared/components/metric_popover_spec.js (renamed from spec/frontend/cycle_analytics/metric_popover_spec.js)2
-rw-r--r--spec/frontend/analytics/shared/components/metric_tile_spec.js81
-rw-r--r--spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js31
-rw-r--r--spec/frontend/analytics/shared/utils_spec.js36
-rw-r--r--spec/frontend/analytics/usage_trends/apollo_mock_data.js1
-rw-r--r--spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js15
-rw-r--r--spec/frontend/analytics/usage_trends/components/users_chart_spec.js15
-rw-r--r--spec/frontend/analytics/usage_trends/mock_data.js20
-rw-r--r--spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js11
-rw-r--r--spec/frontend/authentication/webauthn/util_spec.js19
-rw-r--r--spec/frontend/badges/components/badge_form_spec.js16
-rw-r--r--spec/frontend/badges/components/badge_list_row_spec.js16
-rw-r--r--spec/frontend/badges/components/badge_list_spec.js38
-rw-r--r--spec/frontend/badges/components/badge_settings_spec.js9
-rw-r--r--spec/frontend/badges/components/badge_spec.js77
-rw-r--r--spec/frontend/batch_comments/components/diff_file_drafts_spec.js19
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js94
-rw-r--r--spec/frontend/batch_comments/components/drafts_count_spec.js11
-rw-r--r--spec/frontend/batch_comments/components/preview_dropdown_spec.js6
-rw-r--r--spec/frontend/batch_comments/components/publish_button_spec.js11
-rw-r--r--spec/frontend/batch_comments/components/publish_dropdown_spec.js6
-rw-r--r--spec/frontend/behaviors/copy_as_gfm_spec.js37
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js144
-rw-r--r--spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap1
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js8
-rw-r--r--spec/frontend/blob/components/blob_header_default_actions_spec.js43
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js15
-rw-r--r--spec/frontend/blob/components/blob_header_viewer_switcher_spec.js15
-rw-r--r--spec/frontend/blob/components/mock_data.js3
-rw-r--r--spec/frontend/blob/viewer/index_spec.js48
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js62
-rw-r--r--spec/frontend/boards/board_list_helper.js9
-rw-r--r--spec/frontend/boards/board_list_spec.js25
-rw-r--r--spec/frontend/boards/components/board_add_new_column_trigger_spec.js4
-rw-r--r--spec/frontend/boards/components/board_blocked_icon_spec.js4
-rw-r--r--spec/frontend/boards/components/board_card_spec.js6
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js4
-rw-r--r--spec/frontend/boards/components/board_form_spec.js2
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js8
-rw-r--r--spec/frontend/boards/components/board_new_issue_spec.js49
-rw-r--r--spec/frontend/boards/components/board_new_item_spec.js37
-rw-r--r--spec/frontend/boards/components/board_settings_sidebar_spec.js28
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js195
-rw-r--r--spec/frontend/boards/components/sidebar/board_editable_item_spec.js20
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js11
-rw-r--r--spec/frontend/boards/mock_data.js80
-rw-r--r--spec/frontend/boards/project_select_spec.js4
-rw-r--r--spec/frontend/boards/stores/actions_spec.js4
-rw-r--r--spec/frontend/broadcast_notification_spec.js1
-rw-r--r--spec/frontend/captcha/apollo_captcha_link_spec.js2
-rw-r--r--spec/frontend/ci_lint/components/ci_lint_spec.js5
-rw-r--r--spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js5
-rw-r--r--spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js11
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js7
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js7
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_table_spec.js46
-rw-r--r--spec/frontend/clusters/agents/components/activity_events_list_spec.js7
-rw-r--r--spec/frontend/clusters/agents/components/show_spec.js51
-rw-r--r--spec/frontend/clusters/components/new_cluster_spec.js5
-rw-r--r--spec/frontend/clusters/components/remove_cluster_confirmation_spec.js5
-rw-r--r--spec/frontend/clusters/forms/components/integration_form_spec.js45
-rw-r--r--spec/frontend/clusters_list/components/agent_table_spec.js155
-rw-r--r--spec/frontend/clusters_list/components/agents_spec.js116
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js13
-rw-r--r--spec/frontend/clusters_list/components/clusters_actions_spec.js35
-rw-r--r--spec/frontend/clusters_list/components/clusters_spec.js5
-rw-r--r--spec/frontend/clusters_list/components/clusters_view_all_spec.js79
-rw-r--r--spec/frontend/clusters_list/components/delete_agent_button_spec.js (renamed from spec/frontend/clusters_list/components/agent_options_spec.js)77
-rw-r--r--spec/frontend/clusters_list/components/install_agent_modal_spec.js60
-rw-r--r--spec/frontend/clusters_list/components/mock_data.js112
-rw-r--r--spec/frontend/clusters_list/components/node_error_help_text_spec.js5
-rw-r--r--spec/frontend/clusters_list/mocks/apollo.js13
-rw-r--r--spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap1
-rw-r--r--spec/frontend/code_navigation/components/app_spec.js8
-rw-r--r--spec/frontend/code_quality_walkthrough/components/step_spec.js2
-rw-r--r--spec/frontend/commit/commit_pipeline_status_component_spec.js12
-rw-r--r--spec/frontend/commit/pipelines/pipelines_table_spec.js66
-rw-r--r--spec/frontend/confirm_modal_spec.js16
-rw-r--r--spec/frontend/content_editor/test_utils.js2
-rw-r--r--spec/frontend/contributors/component/contributors_spec.js20
-rw-r--r--spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js134
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js7
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js99
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js18
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js22
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js8
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js42
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js8
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js8
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js24
-rw-r--r--spec/frontend/cycle_analytics/base_spec.js2
-rw-r--r--spec/frontend/cycle_analytics/filter_bar_spec.js9
-rw-r--r--spec/frontend/cycle_analytics/stage_table_spec.js3
-rw-r--r--spec/frontend/cycle_analytics/utils_spec.js31
-rw-r--r--spec/frontend/cycle_analytics/value_stream_metrics_spec.js80
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js7
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js11
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js7
-rw-r--r--spec/frontend/deploy_keys/components/action_btn_spec.js15
-rw-r--r--spec/frontend/deploy_keys/components/app_spec.js114
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js14
-rw-r--r--spec/frontend/design_management/components/delete_button_spec.js18
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js64
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js33
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js65
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js149
-rw-r--r--spec/frontend/design_management/components/design_presentation_spec.js117
-rw-r--r--spec/frontend/design_management/components/design_scaler_spec.js9
-rw-r--r--spec/frontend/design_management/components/design_sidebar_spec.js27
-rw-r--r--spec/frontend/design_management/components/design_todo_button_spec.js9
-rw-r--r--spec/frontend/design_management/components/image_spec.js46
-rw-r--r--spec/frontend/design_management/components/list/item_spec.js35
-rw-r--r--spec/frontend/design_management/components/toolbar/design_navigation_spec.js8
-rw-r--r--spec/frontend/design_management/components/toolbar/index_spec.js61
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js59
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js64
-rw-r--r--spec/frontend/design_management/pages/index_spec.js35
-rw-r--r--spec/frontend/design_management/router_spec.js8
-rw-r--r--spec/frontend/design_management/utils/cache_update_spec.js2
-rw-r--r--spec/frontend/diffs/components/app_spec.js23
-rw-r--r--spec/frontend/diffs/components/collapsed_files_warning_spec.js29
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js36
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js7
-rw-r--r--spec/frontend/diffs/components/diff_discussion_reply_spec.js7
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js13
-rw-r--r--spec/frontend/diffs/components/diff_expansion_cell_spec.js8
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js30
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js40
-rw-r--r--spec/frontend/diffs/components/diff_gutter_avatars_spec.js22
-rw-r--r--spec/frontend/diffs/components/diff_view_spec.js5
-rw-r--r--spec/frontend/diffs/components/image_diff_overlay_spec.js4
-rw-r--r--spec/frontend/diffs/components/merge_conflict_warning_spec.js15
-rw-r--r--spec/frontend/diffs/components/no_changes_spec.js7
-rw-r--r--spec/frontend/diffs/components/settings_dropdown_spec.js7
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js39
-rw-r--r--spec/frontend/diffs/store/actions_spec.js14
-rw-r--r--spec/frontend/editor/source_editor_yaml_ext_spec.js102
-rw-r--r--spec/frontend/emoji/awards_app/store/actions_spec.js37
-rw-r--r--spec/frontend/emoji/components/utils_spec.js3
-rw-r--r--spec/frontend/environment.js3
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js27
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js11
-rw-r--r--spec/frontend/environments/commit_spec.js71
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js75
-rw-r--r--spec/frontend/environments/deploy_board_wrapper_spec.js124
-rw-r--r--spec/frontend/environments/deployment_spec.js243
-rw-r--r--spec/frontend/environments/environment_actions_spec.js4
-rw-r--r--spec/frontend/environments/environment_pin_spec.js74
-rw-r--r--spec/frontend/environments/environment_table_spec.js3
-rw-r--r--spec/frontend/environments/environments_app_spec.js8
-rw-r--r--spec/frontend/environments/graphql/mock_data.js66
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js4
-rw-r--r--spec/frontend/environments/new_environment_folder_spec.js1
-rw-r--r--spec/frontend/environments/new_environment_item_spec.js185
-rw-r--r--spec/frontend/environments/new_environments_app_spec.js31
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js160
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_actions_spec.js24
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js52
-rw-r--r--spec/frontend/error_tracking_settings/components/app_spec.js15
-rw-r--r--spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js7
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js19
-rw-r--r--spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js7
-rw-r--r--spec/frontend/feature_flags/components/edit_feature_flag_spec.js14
-rw-r--r--spec/frontend/feature_flags/components/empty_state_spec.js3
-rw-r--r--spec/frontend/feature_flags/components/environments_dropdown_spec.js15
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js29
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_table_spec.js8
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js21
-rw-r--r--spec/frontend/feature_flags/components/new_environments_dropdown_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/new_feature_flag_spec.js18
-rw-r--r--spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js3
-rw-r--r--spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js11
-rw-r--r--spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js3
-rw-r--r--spec/frontend/feature_flags/components/strategy_spec.js140
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_popover_spec.js3
-rw-r--r--spec/frontend/filtered_search/dropdown_user_spec.js2
-rw-r--r--spec/frontend/filtered_search/dropdown_utils_spec.js4
-rw-r--r--spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js9
-rw-r--r--spec/frontend/filtered_search/recent_searches_root_spec.js5
-rw-r--r--spec/frontend/fixtures/application_settings.rb1
-rw-r--r--spec/frontend/fixtures/blob.rb2
-rw-r--r--spec/frontend/fixtures/branches.rb2
-rw-r--r--spec/frontend/fixtures/clusters.rb2
-rw-r--r--spec/frontend/fixtures/commit.rb2
-rw-r--r--spec/frontend/fixtures/freeze_period.rb2
-rw-r--r--spec/frontend/fixtures/issues.rb11
-rw-r--r--spec/frontend/fixtures/jobs.rb2
-rw-r--r--spec/frontend/fixtures/listbox.rb31
-rw-r--r--spec/frontend/fixtures/merge_requests.rb13
-rw-r--r--spec/frontend/fixtures/merge_requests_diffs.rb2
-rw-r--r--spec/frontend/fixtures/pipeline_schedules.rb2
-rw-r--r--spec/frontend/fixtures/projects.rb2
-rw-r--r--spec/frontend/fixtures/prometheus_service.rb2
-rw-r--r--spec/frontend/fixtures/runner.rb44
-rw-r--r--spec/frontend/fixtures/services.rb2
-rw-r--r--spec/frontend/fixtures/snippet.rb2
-rw-r--r--spec/frontend/fixtures/tags.rb2
-rw-r--r--spec/frontend/fixtures/todos.rb2
-rw-r--r--spec/frontend/flash_spec.js8
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js8
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js7
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_spec.js33
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_search_input_spec.js9
-rw-r--r--spec/frontend/gl_form_spec.js15
-rw-r--r--spec/frontend/google_cloud/components/app_spec.js4
-rw-r--r--spec/frontend/google_cloud/components/deployments_service_table_spec.js7
-rw-r--r--spec/frontend/google_cloud/components/home_spec.js4
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_form_spec.js19
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_list_spec.js19
-rw-r--r--spec/frontend/google_tag_manager/index_spec.js178
-rw-r--r--spec/frontend/grafana_integration/components/grafana_integration_spec.js22
-rw-r--r--spec/frontend/group_settings/components/shared_runners_form_spec.js3
-rw-r--r--spec/frontend/groups/components/app_spec.js66
-rw-r--r--spec/frontend/groups/components/group_folder_spec.js6
-rw-r--r--spec/frontend/groups/components/groups_spec.js26
-rw-r--r--spec/frontend/groups/components/invite_members_banner_spec.js4
-rw-r--r--spec/frontend/groups/components/item_actions_spec.js38
-rw-r--r--spec/frontend/groups/components/transfer_group_form_spec.js131
-rw-r--r--spec/frontend/groups/landing_spec.js5
-rw-r--r--spec/frontend/groups/transfer_edit_spec.js31
-rw-r--r--spec/frontend/header_search/components/app_spec.js14
-rw-r--r--spec/frontend/header_search/components/header_search_autocomplete_items_spec.js4
-rw-r--r--spec/frontend/ide/components/activity_bar_spec.js11
-rw-r--r--spec/frontend/ide/components/branches/search_list_spec.js14
-rw-r--r--spec/frontend/ide/components/commit_sidebar/actions_spec.js29
-rw-r--r--spec/frontend/ide/components/commit_sidebar/editor_header_spec.js7
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js47
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_item_spec.js50
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_spec.js7
-rw-r--r--spec/frontend/ide/components/commit_sidebar/message_field_spec.js138
-rw-r--r--spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js52
-rw-r--r--spec/frontend/ide/components/commit_sidebar/radio_group_spec.js45
-rw-r--r--spec/frontend/ide/components/commit_sidebar/success_message_spec.js11
-rw-r--r--spec/frontend/ide/components/error_message_spec.js38
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js74
-rw-r--r--spec/frontend/ide/components/file_templates/bar_spec.js28
-rw-r--r--spec/frontend/ide/components/file_templates/dropdown_spec.js36
-rw-r--r--spec/frontend/ide/components/ide_file_row_spec.js32
-rw-r--r--spec/frontend/ide/components/ide_review_spec.js16
-rw-r--r--spec/frontend/ide/components/ide_side_bar_spec.js19
-rw-r--r--spec/frontend/ide/components/ide_spec.js7
-rw-r--r--spec/frontend/ide/components/ide_status_bar_spec.js14
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js7
-rw-r--r--spec/frontend/ide/components/ide_tree_list_spec.js13
-rw-r--r--spec/frontend/ide/components/ide_tree_spec.js6
-rw-r--r--spec/frontend/ide/components/jobs/detail_spec.js29
-rw-r--r--spec/frontend/ide/components/jobs/item_spec.js11
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js8
-rw-r--r--spec/frontend/ide/components/jobs/stage_spec.js15
-rw-r--r--spec/frontend/ide/components/merge_requests/item_spec.js7
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js75
-rw-r--r--spec/frontend/ide/components/nav_dropdown_button_spec.js32
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js23
-rw-r--r--spec/frontend/ide/components/new_dropdown/button_spec.js20
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js12
-rw-r--r--spec/frontend/ide/components/new_dropdown/modal_spec.js17
-rw-r--r--spec/frontend/ide/components/panes/collapsible_sidebar_spec.js9
-rw-r--r--spec/frontend/ide/components/panes/right_spec.js29
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js60
-rw-r--r--spec/frontend/ide/components/preview/navigator_spec.js120
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js28
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js7
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js22
-rw-r--r--spec/frontend/ide/components/resizable_panel_spec.js14
-rw-r--r--spec/frontend/ide/components/shared/tokened_input_spec.js12
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js25
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js15
-rw-r--r--spec/frontend/ide/components/terminal/view_spec.js8
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js7
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js7
-rw-r--r--spec/frontend/ide/lib/common/model_spec.js7
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions_spec.js17
-rw-r--r--spec/frontend/ide/stores/modules/clientside/actions_spec.js5
-rw-r--r--spec/frontend/ide/stores/plugins/terminal_spec.js5
-rw-r--r--spec/frontend/image_diff/helpers/badge_helper_spec.js9
-rw-r--r--spec/frontend/image_diff/helpers/dom_helper_spec.js12
-rw-r--r--spec/frontend/image_diff/image_diff_spec.js8
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js2
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/fixtures.js1
-rw-r--r--spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js8
-rw-r--r--spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js8
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js11
-rw-r--r--spec/frontend/incidents/mocks/incidents.json4
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap1
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js3
-rw-r--r--spec/frontend/integrations/edit/components/confirmation_modal_spec.js3
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js58
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js363
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js28
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js19
-rw-r--r--spec/frontend/integrations/edit/mock_data.js9
-rw-r--r--spec/frontend/invite_members/components/group_select_spec.js30
-rw-r--r--spec/frontend/invite_members/components/import_a_project_modal_spec.js5
-rw-r--r--spec/frontend/invite_members/components/invite_group_trigger_spec.js2
-rw-r--r--spec/frontend/invite_members/components/invite_groups_modal_spec.js143
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js495
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js1
-rw-r--r--spec/frontend/invite_members/components/invite_modal_base_spec.js103
-rw-r--r--spec/frontend/invite_members/mock_data/group_modal.js11
-rw-r--r--spec/frontend/invite_members/mock_data/member_modal.js36
-rw-r--r--spec/frontend/invite_members/mock_data/modal_base.js11
-rw-r--r--spec/frontend/issuable/components/issue_milestone_spec.js24
-rw-r--r--spec/frontend/issuable/components/related_issuable_item_spec.js9
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js72
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js29
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js30
-rw-r--r--spec/frontend/issues/create_merge_request_dropdown_spec.js4
-rw-r--r--spec/frontend/issues/list/components/issues_list_app_spec.js161
-rw-r--r--spec/frontend/issues/list/components/jira_issues_import_status_app_spec.js9
-rw-r--r--spec/frontend/issues/list/components/new_issue_dropdown_spec.js18
-rw-r--r--spec/frontend/issues/list/mock_data.js21
-rw-r--r--spec/frontend/issues/list/utils_spec.js13
-rw-r--r--spec/frontend/issues/new/components/title_suggestions_spec.js57
-rw-r--r--spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js10
-rw-r--r--spec/frontend/issues/show/components/app_spec.js165
-rw-r--r--spec/frontend/issues/show/components/description_spec.js294
-rw-r--r--spec/frontend/issues/show/components/fields/description_spec.js1
-rw-r--r--spec/frontend/issues/show/components/fields/type_spec.js9
-rw-r--r--spec/frontend/issues/show/components/form_spec.js3
-rw-r--r--spec/frontend/issues/show/components/header_actions_spec.js4
-rw-r--r--spec/frontend/issues/show/components/title_spec.js46
-rw-r--r--spec/frontend/issues/show/mock_data/mock_data.js14
-rw-r--r--spec/frontend/jira_connect/branches/components/new_branch_form_spec.js143
-rw-r--r--spec/frontend/jira_connect/branches/components/project_dropdown_spec.js74
-rw-r--r--spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js19
-rw-r--r--spec/frontend/jira_connect/branches/mock_data.js30
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js3
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js110
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/app_spec.js96
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/compatibility_alert_spec.js56
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js12
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js3
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js62
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/subscriptions_spec.js56
-rw-r--r--spec/frontend/jira_import/components/jira_import_app_spec.js6
-rw-r--r--spec/frontend/jobs/bridge/app_spec.js18
-rw-r--r--spec/frontend/jobs/components/job_app_spec.js18
-rw-r--r--spec/frontend/jobs/components/job_container_item_spec.js3
-rw-r--r--spec/frontend/jobs/components/job_log_controllers_spec.js9
-rw-r--r--spec/frontend/jobs/components/log/collapsible_section_spec.js8
-rw-r--r--spec/frontend/jobs/components/log/line_header_spec.js8
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js11
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js7
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js3
-rw-r--r--spec/frontend/jobs/components/table/cells/actions_cell_spec.js31
-rw-r--r--spec/frontend/jobs/components/table/job_table_app_spec.js53
-rw-r--r--spec/frontend/jobs/mixins/delayed_job_mixin_spec.js11
-rw-r--r--spec/frontend/jobs/mock_data.js97
-rw-r--r--spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js2
-rw-r--r--spec/frontend/lib/utils/apollo_startup_js_link_spec.js2
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js9
-rw-r--r--spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js18
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js16
-rw-r--r--spec/frontend/lib/utils/table_utility_spec.js31
-rw-r--r--spec/frontend/lib/utils/text_markdown_spec.js74
-rw-r--r--spec/frontend/lib/utils/vuex_module_mappers_spec.js10
-rw-r--r--spec/frontend/lib/utils/yaml_spec.js105
-rw-r--r--spec/frontend/listbox/index_spec.js111
-rw-r--r--spec/frontend/listbox/redirect_behavior_spec.js51
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js22
-rw-r--r--spec/frontend/logs/components/log_control_buttons_spec.js31
-rw-r--r--spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js7
-rw-r--r--spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js7
-rw-r--r--spec/frontend/members/components/action_buttons/remove_member_button_spec.js7
-rw-r--r--spec/frontend/members/components/action_buttons/resend_invite_button_spec.js7
-rw-r--r--spec/frontend/members/components/app_spec.js8
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js63
-rw-r--r--spec/frontend/members/components/filter_sort/filter_sort_container_spec.js7
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js7
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js7
-rw-r--r--spec/frontend/members/components/modals/leave_modal_spec.js8
-rw-r--r--spec/frontend/members/components/modals/remove_group_link_modal_spec.js8
-rw-r--r--spec/frontend/members/components/table/expiration_datepicker_spec.js8
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js9
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js11
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js8
-rw-r--r--spec/frontend/members/mock_data.js2
-rw-r--r--spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js10
-rw-r--r--spec/frontend/merge_conflicts/store/actions_spec.js5
-rw-r--r--spec/frontend/merge_request_spec.js67
-rw-r--r--spec/frontend/mocks_spec.js11
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap22
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js25
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js142
-rw-r--r--spec/frontend/monitoring/components/create_dashboard_modal_spec.js10
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js100
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js143
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_builder_spec.js67
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js137
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js341
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js101
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js15
-rw-r--r--spec/frontend/monitoring/components/embeds/metric_embed_spec.js7
-rw-r--r--spec/frontend/monitoring/components/graph_group_spec.js35
-rw-r--r--spec/frontend/monitoring/components/links_section_spec.js20
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js13
-rw-r--r--spec/frontend/monitoring/components/variables/dropdown_field_spec.js8
-rw-r--r--spec/frontend/monitoring/components/variables/text_field_spec.js22
-rw-r--r--spec/frontend/monitoring/components/variables_section_spec.js39
-rw-r--r--spec/frontend/monitoring/router_spec.js7
-rw-r--r--spec/frontend/mr_popover/mr_popover_spec.js29
-rw-r--r--spec/frontend/nav/components/responsive_app_spec.js5
-rw-r--r--spec/frontend/nav/components/top_nav_menu_item_spec.js1
-rw-r--r--spec/frontend/notebook/cells/code_spec.js22
-rw-r--r--spec/frontend/notebook/cells/markdown_spec.js71
-rw-r--r--spec/frontend/notebook/cells/output/index_spec.js36
-rw-r--r--spec/frontend/notebook/cells/prompt_spec.js14
-rw-r--r--spec/frontend/notebook/index_spec.js20
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js13
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js63
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js34
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js56
-rw-r--r--spec/frontend/notes/components/discussion_navigator_spec.js10
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js29
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js17
-rw-r--r--spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js5
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js40
-rw-r--r--spec/frontend/notes/components/note_body_spec.js6
-rw-r--r--spec/frontend/notes/components/note_form_spec.js2
-rw-r--r--spec/frontend/notes/components/note_header_spec.js8
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js24
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js20
-rw-r--r--spec/frontend/notes/components/sort_discussion_spec.js7
-rw-r--r--spec/frontend/notes/components/timeline_toggle_spec.js15
-rw-r--r--spec/frontend/notes/deprecated_notes_spec.js81
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js57
-rw-r--r--spec/frontend/notifications/components/custom_notifications_modal_spec.js7
-rw-r--r--spec/frontend/notifications/components/notifications_dropdown_spec.js8
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js21
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js15
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js21
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js14
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js30
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js13
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js14
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap5
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js39
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js72
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js23
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js3
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap14
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js9
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js24
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js1
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/details_spec.js19
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/list_spec.js24
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js9
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js31
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js15
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/mock_data.js1
-rw-r--r--spec/frontend/pager_spec.js57
-rw-r--r--spec/frontend/pages/admin/projects/components/namespace_select_spec.js7
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js5
-rw-r--r--spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js7
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_form_spec.js11
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js5
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap27
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js38
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js30
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/mock_data.js2
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js13
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js8
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js33
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js2
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js6
-rw-r--r--spec/frontend/performance_bar/components/add_request_spec.js25
-rw-r--r--spec/frontend/persistent_user_callout_spec.js8
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js53
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js46
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js11
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js11
-rw-r--r--spec/frontend/pipeline_editor/components/header/validation_segment_spec.js7
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js13
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js36
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js13
-rw-r--r--spec/frontend/pipeline_wizard/components/commit_spec.js282
-rw-r--r--spec/frontend/pipeline_wizard/components/editor_spec.js69
-rw-r--r--spec/frontend/pipeline_wizard/components/step_nav_spec.js79
-rw-r--r--spec/frontend/pipeline_wizard/components/widgets/text_spec.js152
-rw-r--r--spec/frontend/pipeline_wizard/mock/query_responses.js62
-rw-r--r--spec/frontend/pipelines/__snapshots__/utils_spec.js.snap11
-rw-r--r--spec/frontend/pipelines/components/dag/dag_annotations_spec.js19
-rw-r--r--spec/frontend/pipelines/components/dag/dag_spec.js9
-rw-r--r--spec/frontend/pipelines/components/jobs/jobs_app_spec.js13
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js37
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js23
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js58
-rw-r--r--spec/frontend/pipelines/graph/job_item_spec.js49
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js113
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js30
-rw-r--r--spec/frontend/pipelines/graph/mock_data.js12
-rw-r--r--spec/frontend/pipelines/header_component_spec.js5
-rw-r--r--spec/frontend/pipelines/mock_data.js680
-rw-r--r--spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js146
-rw-r--r--spec/frontend/pipelines/notification/mock_data.js33
-rw-r--r--spec/frontend/pipelines/pipeline_triggerer_spec.js8
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js349
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js20
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js50
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js5
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_table_spec.js7
-rw-r--r--spec/frontend/popovers/components/popovers_spec.js15
-rw-r--r--spec/frontend/popovers/index_spec.js17
-rw-r--r--spec/frontend/profile/account/components/delete_account_modal_spec.js74
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js11
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js4
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js7
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js60
-rw-r--r--spec/frontend/projects/compare/components/app_spec.js7
-rw-r--r--spec/frontend/projects/compare/components/repo_dropdown_spec.js7
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js3
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js3
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap33
-rw-r--r--spec/frontend/projects/components/project_delete_button_spec.js5
-rw-r--r--spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap54
-rw-r--r--spec/frontend/projects/components/shared/delete_button_spec.js30
-rw-r--r--spec/frontend/projects/new/components/deployment_target_select_spec.js82
-rw-r--r--spec/frontend/projects/new/components/new_project_url_select_spec.js9
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js7
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js43
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js12
-rw-r--r--spec/frontend/projects/project_find_file_spec.js5
-rw-r--r--spec/frontend/projects/settings/components/shared_runners_toggle_spec.js3
-rw-r--r--spec/frontend/projects/settings/components/transfer_project_form_spec.js10
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js2
-rw-r--r--spec/frontend/prometheus_alerts/components/reset_key_spec.js44
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js30
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js41
-rw-r--r--spec/frontend/related_issues/components/related_issuable_input_spec.js3
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js3
-rw-r--r--spec/frontend/releases/components/app_index_apollo_client_spec.js14
-rw-r--r--spec/frontend/releases/components/app_show_spec.js13
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js7
-rw-r--r--spec/frontend/releases/components/evidence_block_spec.js8
-rw-r--r--spec/frontend/releases/components/release_block_footer_spec.js5
-rw-r--r--spec/frontend/releases/components/release_block_milestone_info_spec.js30
-rw-r--r--spec/frontend/releases/components/release_block_spec.js5
-rw-r--r--spec/frontend/releases/components/releases_pagination_spec.js7
-rw-r--r--spec/frontend/releases/components/releases_sort_spec.js7
-rw-r--r--spec/frontend/releases/components/tag_field_exsting_spec.js7
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js4
-rw-r--r--spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js14
-rw-r--r--spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js10
-rw-r--r--spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js7
-rw-r--r--spec/frontend/reports/components/report_section_spec.js92
-rw-r--r--spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js7
-rw-r--r--spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js7
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js92
-rw-r--r--spec/frontend/repository/components/blob_controls_spec.js9
-rw-r--r--spec/frontend/repository/components/blob_viewers/download_viewer_spec.js37
-rw-r--r--spec/frontend/repository/components/blob_viewers/image_viewer_spec.js12
-rw-r--r--spec/frontend/repository/components/blob_viewers/lfs_viewer_spec.js41
-rw-r--r--spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js10
-rw-r--r--spec/frontend/repository/components/blob_viewers/video_viewer_spec.js6
-rw-r--r--spec/frontend/repository/components/breadcrumbs_spec.js9
-rw-r--r--spec/frontend/repository/components/last_commit_spec.js25
-rw-r--r--spec/frontend/repository/components/preview/index_spec.js25
-rw-r--r--spec/frontend/repository/components/table/index_spec.js14
-rw-r--r--spec/frontend/repository/components/table/row_spec.js84
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js13
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js5
-rw-r--r--spec/frontend/repository/mock_data.js5
-rw-r--r--spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js14
-rw-r--r--spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js146
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js51
-rw-r--r--spec/frontend/runner/components/cells/link_cell_spec.js72
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js201
-rw-r--r--spec/frontend/runner/components/registration/registration_dropdown_spec.js15
-rw-r--r--spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js15
-rw-r--r--spec/frontend/runner/components/registration/registration_token_spec.js20
-rw-r--r--spec/frontend/runner/components/runner_assigned_item_spec.js53
-rw-r--r--spec/frontend/runner/components/runner_details_spec.js189
-rw-r--r--spec/frontend/runner/components/runner_edit_button_spec.js41
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js41
-rw-r--r--spec/frontend/runner/components/runner_groups_spec.js67
-rw-r--r--spec/frontend/runner/components/runner_header_spec.js44
-rw-r--r--spec/frontend/runner/components/runner_jobs_spec.js156
-rw-r--r--spec/frontend/runner/components/runner_jobs_table_spec.js119
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js50
-rw-r--r--spec/frontend/runner/components/runner_pagination_spec.js1
-rw-r--r--spec/frontend/runner/components/runner_pause_button_spec.js239
-rw-r--r--spec/frontend/runner/components/runner_projects_spec.js193
-rw-r--r--spec/frontend/runner/components/runner_type_tabs_spec.js22
-rw-r--r--spec/frontend/runner/components/runner_update_form_spec.js46
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js79
-rw-r--r--spec/frontend/runner/mock_data.js10
-rw-r--r--spec/frontend/runner/utils_spec.js65
-rw-r--r--spec/frontend/search/sidebar/components/confidentiality_filter_spec.js7
-rw-r--r--spec/frontend/search/sidebar/components/radio_filter_spec.js7
-rw-r--r--spec/frontend/search/sidebar/components/status_filter_spec.js7
-rw-r--r--spec/frontend/search/sort/components/app_spec.js7
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js24
-rw-r--r--spec/frontend/security_configuration/components/feature_card_spec.js1
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js200
-rw-r--r--spec/frontend/security_configuration/components/upgrade_banner_spec.js85
-rw-r--r--spec/frontend/security_configuration/mock_data.js57
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap2
-rw-r--r--spec/frontend/serverless/components/function_details_spec.js11
-rw-r--r--spec/frontend/serverless/components/functions_spec.js52
-rw-r--r--spec/frontend/serverless/survey_banner_spec.js51
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js19
-rw-r--r--spec/frontend/settings_panels_spec.js14
-rw-r--r--spec/frontend/sidebar/assignees_realtime_spec.js7
-rw-r--r--spec/frontend/sidebar/assignees_spec.js8
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js29
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js11
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js5
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js9
-rw-r--r--spec/frontend/sidebar/components/mock_data.js2
-rw-r--r--spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js5
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js8
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js17
-rw-r--r--spec/frontend/sidebar/components/time_tracking/report_spec.js7
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js15
-rw-r--r--spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js10
-rw-r--r--spec/frontend/sidebar/lock/edit_form_buttons_spec.js25
-rw-r--r--spec/frontend/sidebar/lock/issuable_lock_form_spec.js22
-rw-r--r--spec/frontend/sidebar/mock_data.js10
-rw-r--r--spec/frontend/sidebar/participants_spec.js40
-rw-r--r--spec/frontend/sidebar/sidebar_assignees_spec.js8
-rw-r--r--spec/frontend/sidebar/sidebar_move_issue_spec.js54
-rw-r--r--spec/frontend/sidebar/todo_spec.js8
-rw-r--r--spec/frontend/snippets/components/edit_spec.js14
-rw-r--r--spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js3
-rw-r--r--spec/frontend/snippets/components/snippet_blob_view_spec.js38
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js25
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_controls_spec.js5
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_modal_spec.js15
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js28
-rw-r--r--spec/frontend/terraform/components/states_table_actions_spec.js11
-rw-r--r--spec/frontend/terraform/components/states_table_spec.js9
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js8
-rw-r--r--spec/frontend/toggles/index_spec.js149
-rw-r--r--spec/frontend/token_access/token_access_spec.js6
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js35
-rw-r--r--spec/frontend/tooltips/index_spec.js15
-rw-r--r--spec/frontend/user_lists/components/add_user_modal_spec.js5
-rw-r--r--spec/frontend/user_lists/components/edit_user_list_spec.js18
-rw-r--r--spec/frontend/user_lists/components/new_user_list_spec.js14
-rw-r--r--spec/frontend/user_lists/components/user_list_spec.js22
-rw-r--r--spec/frontend/user_lists/components/user_lists_spec.js8
-rw-r--r--spec/frontend/user_lists/components/user_lists_table_spec.js28
-rw-r--r--spec/frontend/vue_alerts_spec.js7
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js5
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js3
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js5
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js32
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js78
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js39
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js32
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js5
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js27
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js25
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js7
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js218
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js7
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js26
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js14
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js64
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js3
-rw-r--r--spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js125
-rw-r--r--spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js137
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_details_spec.js10
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js9
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_metrics_spec.js3
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_status_spec.js23
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js21
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap4
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js32
-rw-r--r--spec/frontend/vue_shared/components/chronic_duration_input_spec.js25
-rw-r--r--spec/frontend/vue_shared/components/confirm_fork_modal_spec.js80
-rw-r--r--spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js258
-rw-r--r--spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js68
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js120
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/expand_button_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/file_finder/index_spec.js152
-rw-r--r--spec/frontend/vue_shared/components/file_finder/item_spec.js53
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js33
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js141
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js35
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap54
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/gfm_autocomplete_spec.js34
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js427
-rw-r--r--spec/frontend/vue_shared/components/gl_countdown_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/gl_modal_vuex_spec.js24
-rw-r--r--spec/frontend/vue_shared/components/help_popover_spec.js110
-rw-r--r--spec/frontend/vue_shared/components/local_storage_sync_spec.js27
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_spec.js111
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js49
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestions_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/modal_copy_button_spec.js21
-rw-r--r--spec/frontend/vue_shared/components/multiselect_dropdown_spec.js35
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/mock_data.js9
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js151
-rw-r--r--spec/frontend/vue_shared/components/notes/noteable_warning_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/pikaday_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/project_avatar/default_spec.js30
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js46
-rw-r--r--spec/frontend/vue_shared/components/registry/list_item_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js68
-rw-r--r--spec/frontend/vue_shared/components/sidebar/date_picker_spec.js125
-rw-r--r--spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js23
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js65
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js68
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js33
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js3
-rw-r--r--spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js (renamed from spec/frontend/vue_shared/components/source_viewer_spec.js)43
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/utils_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/split_button_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap7
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js99
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js51
-rw-r--r--spec/frontend/vue_shared/directives/track_event_spec.js11
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js5
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js33
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js15
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js86
-rw-r--r--spec/frontend/vue_shared/issuable/list/mock_data.js2
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js11
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js6
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js5
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js5
-rw-r--r--spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js8
-rw-r--r--spec/frontend/vue_shared/new_namespace/components/welcome_spec.js5
-rw-r--r--spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js6
-rw-r--r--spec/frontend/vue_shared/security_reports/mock_data.js2
-rw-r--r--spec/frontend/whats_new/components/app_spec.js11
-rw-r--r--spec/frontend/work_items/mock_data.js14
-rw-r--r--spec/frontend/work_items/pages/create_work_item_spec.js146
-rw-r--r--spec/frontend/work_items/pages/work_item_root_spec.js6
-rw-r--r--spec/frontend/work_items/router_spec.js10
-rw-r--r--spec/frontend/work_items_hierarchy/components/app_spec.js63
-rw-r--r--spec/frontend/work_items_hierarchy/components/hierarchy_spec.js118
-rw-r--r--spec/frontend/work_items_hierarchy/hierarchy_util_spec.js16
-rw-r--r--spec/frontend/zen_mode_spec.js2
-rw-r--r--spec/frontend_integration/ide/ide_integration_spec.js7
-rw-r--r--spec/graphql/features/authorization_spec.rb2
-rw-r--r--spec/graphql/graphql_triggers_spec.rb14
-rw-r--r--spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb2
-rw-r--r--spec/graphql/mutations/ci/runner/delete_spec.rb15
-rw-r--r--spec/graphql/mutations/issues/create_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb63
-rw-r--r--spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb49
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb111
-rw-r--r--spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/clusters/agents_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb60
-rw-r--r--spec/graphql/resolvers/package_details_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/package_pipelines_resolver_spec.rb7
-rw-r--r--spec/graphql/resolvers/recent_boards_resolver_spec.rb79
-rw-r--r--spec/graphql/types/ci/pipeline_counts_type_spec.rb87
-rw-r--r--spec/graphql/types/ci/runner_type_spec.rb3
-rw-r--r--spec/graphql/types/clusters/agent_activity_event_type_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agent_token_type_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agent_type_spec.rb2
-rw-r--r--spec/graphql/types/global_id_type_spec.rb2
-rw-r--r--spec/graphql/types/group_type_spec.rb1
-rw-r--r--spec/graphql/types/issuable_type_spec.rb6
-rw-r--r--spec/graphql/types/member_interface_spec.rb13
-rw-r--r--spec/graphql/types/project_type_spec.rb12
-rw-r--r--spec/graphql/types/repository/blob_type_spec.rb5
-rw-r--r--spec/graphql/types/root_storage_statistics_type_spec.rb2
-rw-r--r--spec/graphql/types/subscription_type_spec.rb1
-rw-r--r--spec/graphql/types/user_preferences_type_spec.rb15
-rw-r--r--spec/graphql/types/user_type_spec.rb36
-rw-r--r--spec/helpers/application_helper_spec.rb2
-rw-r--r--spec/helpers/application_settings_helper_spec.rb9
-rw-r--r--spec/helpers/avatars_helper_spec.rb47
-rw-r--r--spec/helpers/bizible_helper_spec.rb47
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb11
-rw-r--r--spec/helpers/clusters_helper_spec.rb8
-rw-r--r--spec/helpers/invite_members_helper_spec.rb40
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb31
-rw-r--r--spec/helpers/issuables_helper_spec.rb10
-rw-r--r--spec/helpers/issues_helper_spec.rb12
-rw-r--r--spec/helpers/listbox_helper_spec.rb75
-rw-r--r--spec/helpers/projects/cluster_agents_helper_spec.rb29
-rw-r--r--spec/helpers/projects_helper_spec.rb30
-rw-r--r--spec/helpers/search_helper_spec.rb148
-rw-r--r--spec/helpers/ssh_keys_helper_spec.rb6
-rw-r--r--spec/helpers/storage_helper_spec.rb83
-rw-r--r--spec/helpers/tab_helper_spec.rb4
-rw-r--r--spec/helpers/users_helper_spec.rb38
-rw-r--r--spec/initializers/google_api_client_spec.rb38
-rw-r--r--spec/initializers/net_http_patch_spec.rb3
-rw-r--r--spec/lib/api/entities/basic_project_details_spec.rb2
-rw-r--r--spec/lib/api/entities/deployment_extended_spec.rb15
-rw-r--r--spec/lib/api/helpers_spec.rb8
-rw-r--r--spec/lib/backup/database_spec.rb9
-rw-r--r--spec/lib/backup/gitaly_backup_spec.rb6
-rw-r--r--spec/lib/backup/gitaly_rpc_backup_spec.rb6
-rw-r--r--spec/lib/backup/manager_spec.rb11
-rw-r--r--spec/lib/backup/repositories_spec.rb72
-rw-r--r--spec/lib/banzai/filter/external_link_filter_spec.rb7
-rw-r--r--spec/lib/banzai/filter/references/issue_reference_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/table_of_contents_filter_spec.rb6
-rw-r--r--spec/lib/banzai/object_renderer_spec.rb2
-rw-r--r--spec/lib/bitbucket_server/representation/repo_spec.rb5
-rw-r--r--spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb15
-rw-r--r--spec/lib/bulk_imports/common/graphql/get_members_query_spec.rb56
-rw-r--r--spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb210
-rw-r--r--spec/lib/bulk_imports/common/pipelines/members_pipeline_spec.rb161
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb27
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb35
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb40
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb119
-rw-r--r--spec/lib/bulk_imports/groups/stage_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb24
-rw-r--r--spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb27
-rw-r--r--spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb32
-rw-r--r--spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb78
-rw-r--r--spec/lib/bulk_imports/projects/stage_spec.rb1
-rw-r--r--spec/lib/container_registry/client_spec.rb110
-rw-r--r--spec/lib/container_registry/gitlab_api_client_spec.rb204
-rw-r--r--spec/lib/container_registry/migration_spec.rb168
-rw-r--r--spec/lib/container_registry/registry_spec.rb10
-rw-r--r--spec/lib/extracts_path_spec.rb21
-rw-r--r--spec/lib/extracts_ref_spec.rb15
-rw-r--r--spec/lib/feature_spec.rb4
-rw-r--r--spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb48
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb15
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb14
-rw-r--r--spec/lib/gitlab/application_context_spec.rb11
-rw-r--r--spec/lib/gitlab/audit/ci_runner_token_author_spec.rb83
-rw-r--r--spec/lib/gitlab/audit/null_author_spec.rb40
-rw-r--r--spec/lib/gitlab/auth/ldap/user_spec.rb28
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb74
-rw-r--r--spec/lib/gitlab/auth/request_authenticator_spec.rb6
-rw-r--r--spec/lib/gitlab/auth/saml/user_spec.rb46
-rw-r--r--spec/lib/gitlab/auth_spec.rb49
-rw-r--r--spec/lib/gitlab/authorized_keys_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb244
-rw-r--r--spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb7
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb50
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb35
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb53
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb8
-rw-r--r--spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb9
-rw-r--r--spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb134
-rw-r--r--spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb20
-rw-r--r--spec/lib/gitlab/background_migration/populate_topics_non_private_projects_count_spec.rb50
-rw-r--r--spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb93
-rw-r--r--spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb28
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb130
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb4
-rw-r--r--spec/lib/gitlab/buffered_io_spec.rb54
-rw-r--r--spec/lib/gitlab/changelog/config_spec.rb14
-rw-r--r--spec/lib/gitlab/changelog/release_spec.rb10
-rw-r--r--spec/lib/gitlab/checks/branch_check_spec.rb9
-rw-r--r--spec/lib/gitlab/ci/badge/release/latest_release_spec.rb42
-rw-r--r--spec/lib/gitlab/ci/badge/release/metadata_spec.rb40
-rw-r--r--spec/lib/gitlab/ci/badge/release/template_spec.rb90
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/expire_in_parser_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb19
-rw-r--r--spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/include/rules_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/include_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/jobs_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/policy_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/entry/script_spec.rb109
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/config/external/rules_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb124
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb148
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/logger_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb165
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_spec.rb28
-rw-r--r--spec/lib/gitlab/ci/reports/security/finding_key_spec.rb61
-rw-r--r--spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/builder/instance_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/builder/project_spec.rb149
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb247
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb58
-rw-r--r--spec/lib/gitlab/cluster/lifecycle_events_spec.rb3
-rw-r--r--spec/lib/gitlab/config/entry/factory_spec.rb6
-rw-r--r--spec/lib/gitlab/console_spec.rb51
-rw-r--r--spec/lib/gitlab/current_settings_spec.rb12
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb7
-rw-r--r--spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb17
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb95
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_transition_log_spec.rb19
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb27
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb27
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb49
-rw-r--r--spec/lib/gitlab/database/dynamic_model_helpers_spec.rb17
-rw-r--r--spec/lib/gitlab/database/each_database_spec.rb100
-rw-r--r--spec/lib/gitlab/database/gitlab_schema_spec.rb2
-rw-r--r--spec/lib/gitlab/database/load_balancing/configuration_spec.rb23
-rw-r--r--spec/lib/gitlab/database/load_balancing/setup_spec.rb31
-rw-r--r--spec/lib/gitlab/database/loose_foreign_keys_spec.rb39
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb102
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb14
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb58
-rw-r--r--spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb18
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_details_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_log_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb2
-rw-r--r--spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb57
-rw-r--r--spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb57
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb29
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_spec.rb2
-rw-r--r--spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb6
-rw-r--r--spec/lib/gitlab/database_spec.rb28
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb6
-rw-r--r--spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/position_tracer_spec.rb2
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb39
-rw-r--r--spec/lib/gitlab/endpoint_attributes_spec.rb5
-rw-r--r--spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb3
-rw-r--r--spec/lib/gitlab/error_tracking/log_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/event_store/store_spec.rb27
-rw-r--r--spec/lib/gitlab/experiment/rollout/feature_spec.rb75
-rw-r--r--spec/lib/gitlab/feature_categories_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb38
-rw-r--r--spec/lib/gitlab/git/wiki_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_design_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_spec.rb5
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb47
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb10
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb167
-rw-r--r--spec/lib/gitlab/github_import/importer/releases_importer_spec.rb24
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_note_spec.rb19
-rw-r--r--spec/lib/gitlab/gl_repository/identifier_spec.rb4
-rw-r--r--spec/lib/gitlab/gl_repository/repo_type_spec.rb4
-rw-r--r--spec/lib/gitlab/gon_helper_spec.rb32
-rw-r--r--spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb2
-rw-r--r--spec/lib/gitlab/graphql/batch_key_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/markdown_field_spec.rb2
-rw-r--r--spec/lib/gitlab/graphql/queries_spec.rb2
-rw-r--r--spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb5
-rw-r--r--spec/lib/gitlab/hook_data/project_builder_spec.rb3
-rw-r--r--spec/lib/gitlab/http_connection_adapter_spec.rb36
-rw-r--r--spec/lib/gitlab/http_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/import_export/command_line_util_spec.rb23
-rw-r--r--spec/lib/gitlab/import_export/config_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/fork_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/group/relation_factory_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/group/tree_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb20
-rw-r--r--spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb34
-rw-r--r--spec/lib/gitlab/import_export/lfs_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/lfs_saver_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/members_mapper_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/project/relation_factory_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb16
-rw-r--r--spec/lib/gitlab/import_export/repo_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/saver_spec.rb48
-rw-r--r--spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/uploads_manager_spec.rb10
-rw-r--r--spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb2
-rw-r--r--spec/lib/gitlab/json_spec.rb42
-rw-r--r--spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb8
-rw-r--r--spec/lib/gitlab/metrics/boot_time_tracker_spec.rb84
-rw-r--r--spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb53
-rw-r--r--spec/lib/gitlab/metrics/rails_slis_spec.rb10
-rw-r--r--spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb14
-rw-r--r--spec/lib/gitlab/metrics/system_spec.rb34
-rw-r--r--spec/lib/gitlab/middleware/memory_report_spec.rb91
-rw-r--r--spec/lib/gitlab/net_http_adapter_spec.rb22
-rw-r--r--spec/lib/gitlab/omniauth_initializer_spec.rb14
-rw-r--r--spec/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns_spec.rb9
-rw-r--r--spec/lib/gitlab/pipeline_scope_counts_spec.rb48
-rw-r--r--spec/lib/gitlab/popen_spec.rb11
-rw-r--r--spec/lib/gitlab/process_memory_cache/helper_spec.rb9
-rw-r--r--spec/lib/gitlab/project_authorizations_spec.rb74
-rw-r--r--spec/lib/gitlab/rack_attack/request_spec.rb266
-rw-r--r--spec/lib/gitlab/regex_spec.rb2
-rw-r--r--spec/lib/gitlab/request_profiler/profile_spec.rb2
-rw-r--r--spec/lib/gitlab/runtime_spec.rb24
-rw-r--r--spec/lib/gitlab/security/scan_configuration_spec.rb33
-rw-r--r--spec/lib/gitlab/ssh_public_key_spec.rb123
-rw-r--r--spec/lib/gitlab/subscription_portal_spec.rb1
-rw-r--r--spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb5
-rw-r--r--spec/lib/gitlab/usage/service_ping_report_spec.rb69
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb3
-rw-r--r--spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb15
-rw-r--r--spec/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter_spec.rb15
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb6
-rw-r--r--spec/lib/gitlab/utils_spec.rb17
-rw-r--r--spec/lib/gitlab/web_ide/config/entry/global_spec.rb2
-rw-r--r--spec/lib/gitlab/web_ide/config_spec.rb2
-rw-r--r--spec/lib/gitlab/webpack/file_loader_spec.rb4
-rw-r--r--spec/lib/gitlab_edition_spec.rb25
-rw-r--r--spec/lib/gitlab_spec.rb7
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb90
-rw-r--r--spec/lib/learn_gitlab/project_spec.rb7
-rw-r--r--spec/lib/peek/views/detailed_view_spec.rb2
-rw-r--r--spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb191
-rw-r--r--spec/lib/security/ci_configuration/sast_build_action_spec.rb9
-rw-r--r--spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb4
-rw-r--r--spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb4
-rw-r--r--spec/lib/serializers/json_spec.rb1
-rw-r--r--spec/lib/serializers/symbolized_json_spec.rb1
-rw-r--r--spec/lib/sidebars/concerns/work_item_hierarchy_spec.rb21
-rw-r--r--spec/lib/sidebars/projects/menus/analytics_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/confluence_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/deployments_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/external_wiki_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/hidden_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/issues_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/monitor_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/project_information_menu_spec.rb8
-rw-r--r--spec/lib/sidebars/projects/menus/repository_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/scope_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/settings_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/shimo_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/snippets_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/wiki_menu_spec.rb2
-rw-r--r--spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb2
-rw-r--r--spec/mailers/notify_spec.rb2
-rw-r--r--spec/metrics_server/metrics_server_spec.rb203
-rw-r--r--spec/migrations/20220106111958_add_insert_or_update_vulnerability_reads_trigger_spec.rb151
-rw-r--r--spec/migrations/20220106112043_add_update_vulnerability_reads_trigger_spec.rb128
-rw-r--r--spec/migrations/20220106112085_add_update_vulnerability_reads_location_trigger_spec.rb136
-rw-r--r--spec/migrations/20220106163326_add_has_issues_on_vulnerability_reads_trigger_spec.rb134
-rw-r--r--spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb107
-rw-r--r--spec/migrations/20220120094340_drop_position_from_security_findings_spec.rb21
-rw-r--r--spec/migrations/20220124130028_dedup_runner_projects_spec.rb65
-rw-r--r--spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb52
-rw-r--r--spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb33
-rw-r--r--spec/migrations/20220202105733_delete_service_template_records_spec.rb42
-rw-r--r--spec/migrations/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe_spec.rb37
-rw-r--r--spec/migrations/backfill_namespace_id_for_namespace_routes_spec.rb29
-rw-r--r--spec/migrations/backfill_project_namespaces_for_group_spec.rb43
-rw-r--r--spec/migrations/populate_audit_event_streaming_verification_token_spec.rb22
-rw-r--r--spec/migrations/schedule_fix_incorrect_max_seats_used2_spec.rb34
-rw-r--r--spec/migrations/schedule_fix_incorrect_max_seats_used_spec.rb26
-rw-r--r--spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb9
-rw-r--r--spec/migrations/start_backfill_ci_queuing_tables_spec.rb48
-rw-r--r--spec/migrations/update_default_scan_method_of_dast_site_profile_spec.rb32
-rw-r--r--spec/models/ability_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb7
-rw-r--r--spec/models/audit_event_spec.rb33
-rw-r--r--spec/models/blob_spec.rb14
-rw-r--r--spec/models/board_spec.rb4
-rw-r--r--spec/models/ci/build_metadata_spec.rb7
-rw-r--r--spec/models/ci/build_spec.rb168
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb2
-rw-r--r--spec/models/ci/job_artifact_spec.rb7
-rw-r--r--spec/models/ci/job_token/project_scope_link_spec.rb14
-rw-r--r--spec/models/ci/namespace_mirror_spec.rb4
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb7
-rw-r--r--spec/models/ci/pipeline_spec.rb120
-rw-r--r--spec/models/ci/ref_spec.rb7
-rw-r--r--spec/models/ci/runner_project_spec.rb7
-rw-r--r--spec/models/ci/runner_spec.rb449
-rw-r--r--spec/models/ci/sources/pipeline_spec.rb14
-rw-r--r--spec/models/ci/stage_spec.rb7
-rw-r--r--spec/models/ci/trigger_spec.rb16
-rw-r--r--spec/models/ci/variable_spec.rb7
-rw-r--r--spec/models/commit_spec.rb18
-rw-r--r--spec/models/commit_status_spec.rb7
-rw-r--r--spec/models/concerns/after_commit_queue_spec.rb4
-rw-r--r--spec/models/concerns/ci/has_variable_spec.rb39
-rw-r--r--spec/models/concerns/cross_database_modification_spec.rb89
-rw-r--r--spec/models/concerns/has_environment_scope_spec.rb32
-rw-r--r--spec/models/concerns/issuable_spec.rb8
-rw-r--r--spec/models/concerns/resolvable_discussion_spec.rb10
-rw-r--r--spec/models/concerns/taskable_spec.rb66
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb138
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb10
-rw-r--r--spec/models/container_repository_spec.rb765
-rw-r--r--spec/models/customer_relations/contact_spec.rb39
-rw-r--r--spec/models/customer_relations/issue_contact_spec.rb8
-rw-r--r--spec/models/deployment_spec.rb38
-rw-r--r--spec/models/design_management/design_action_spec.rb4
-rw-r--r--spec/models/design_management/design_at_version_spec.rb2
-rw-r--r--spec/models/draft_note_spec.rb22
-rw-r--r--spec/models/environment_spec.rb4
-rw-r--r--spec/models/environment_status_spec.rb2
-rw-r--r--spec/models/event_spec.rb32
-rw-r--r--spec/models/external_pull_request_spec.rb7
-rw-r--r--spec/models/group_spec.rb2
-rw-r--r--spec/models/hooks/service_hook_spec.rb2
-rw-r--r--spec/models/hooks/system_hook_spec.rb8
-rw-r--r--spec/models/hooks/web_hook_spec.rb14
-rw-r--r--spec/models/instance_configuration_spec.rb4
-rw-r--r--spec/models/instance_metadata_spec.rb2
-rw-r--r--spec/models/integration_spec.rb19
-rw-r--r--spec/models/integrations/datadog_spec.rb32
-rw-r--r--spec/models/issue_collection_spec.rb4
-rw-r--r--spec/models/issue_spec.rb22
-rw-r--r--spec/models/key_spec.rb28
-rw-r--r--spec/models/label_note_spec.rb18
-rw-r--r--spec/models/loose_foreign_keys/deleted_record_spec.rb37
-rw-r--r--spec/models/member_spec.rb32
-rw-r--r--spec/models/members/project_member_spec.rb11
-rw-r--r--spec/models/merge_request_spec.rb205
-rw-r--r--spec/models/namespace/root_storage_statistics_spec.rb94
-rw-r--r--spec/models/namespace_spec.rb84
-rw-r--r--spec/models/namespace_statistics_spec.rb207
-rw-r--r--spec/models/namespaces/user_namespace_spec.rb9
-rw-r--r--spec/models/note_spec.rb73
-rw-r--r--spec/models/packages/package_file_spec.rb20
-rw-r--r--spec/models/pages_domain_spec.rb5
-rw-r--r--spec/models/personal_access_token_spec.rb10
-rw-r--r--spec/models/preloaders/users_max_access_level_in_projects_preloader_spec.rb51
-rw-r--r--spec/models/project_import_state_spec.rb23
-rw-r--r--spec/models/project_spec.rb279
-rw-r--r--spec/models/project_team_spec.rb32
-rw-r--r--spec/models/state_note_spec.rb4
-rw-r--r--spec/models/user_spec.rb211
-rw-r--r--spec/models/work_item_spec.rb13
-rw-r--r--spec/policies/ci/pipeline_policy_spec.rb6
-rw-r--r--spec/policies/clusters/agent_token_policy_spec.rb11
-rw-r--r--spec/policies/clusters/agents/activity_event_policy_spec.rb11
-rw-r--r--spec/policies/namespaces/project_namespace_policy_spec.rb2
-rw-r--r--spec/policies/project_member_policy_spec.rb2
-rw-r--r--spec/policies/project_policy_spec.rb4
-rw-r--r--spec/presenters/blob_presenter_spec.rb65
-rw-r--r--spec/presenters/blobs/unfold_presenter_spec.rb8
-rw-r--r--spec/presenters/clusterable_presenter_spec.rb24
-rw-r--r--spec/presenters/packages/conan/package_presenter_spec.rb19
-rw-r--r--spec/presenters/packages/detail/package_presenter_spec.rb8
-rw-r--r--spec/presenters/packages/npm/package_presenter_spec.rb11
-rw-r--r--spec/presenters/packages/nuget/package_metadata_presenter_spec.rb8
-rw-r--r--spec/presenters/packages/pypi/package_presenter_spec.rb8
-rw-r--r--spec/presenters/projects/security/configuration_presenter_spec.rb3
-rw-r--r--spec/requests/abuse_reports_controller_spec.rb (renamed from spec/controllers/abuse_reports_controller_spec.rb)16
-rw-r--r--spec/requests/admin/background_migrations_controller_spec.rb2
-rw-r--r--spec/requests/api/api_spec.rb2
-rw-r--r--spec/requests/api/branches_spec.rb18
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb2
-rw-r--r--spec/requests/api/ci/runner/runners_post_spec.rb85
-rw-r--r--spec/requests/api/ci/runner/runners_verify_post_spec.rb24
-rw-r--r--spec/requests/api/ci/runners_reset_registration_token_spec.rb2
-rw-r--r--spec/requests/api/ci/runners_spec.rb171
-rw-r--r--spec/requests/api/ci/secure_files_spec.rb314
-rw-r--r--spec/requests/api/commits_spec.rb16
-rw-r--r--spec/requests/api/features_spec.rb119
-rw-r--r--spec/requests/api/graphql/ci/ci_cd_setting_spec.rb2
-rw-r--r--spec/requests/api/graphql/ci/config_spec.rb7
-rw-r--r--spec/requests/api/graphql/ci/runner_spec.rb103
-rw-r--r--spec/requests/api/graphql/container_repository/container_repository_details_spec.rb2
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb4
-rw-r--r--spec/requests/api/graphql/group/recent_issue_boards_query_spec.rb14
-rw-r--r--spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/create_spec.rb17
-rw-r--r--spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/user_preferences/update_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/work_items/create_spec.rb21
-rw-r--r--spec/requests/api/graphql/mutations/work_items/delete_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb84
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb17
-rw-r--r--spec/requests/api/graphql/project/container_expiration_policy_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/container_repositories_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/grafana_integration_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issue/designs/designs_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issue/designs/notes_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb37
-rw-r--r--spec/requests/api/graphql/project/project_members_spec.rb96
-rw-r--r--spec/requests/api/graphql/project/recent_issue_boards_query_spec.rb14
-rw-r--r--spec/requests/api/graphql/project/repository/blobs_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/repository_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/tree/tree_spec.rb2
-rw-r--r--spec/requests/api/group_clusters_spec.rb16
-rw-r--r--spec/requests/api/groups_spec.rb34
-rw-r--r--spec/requests/api/internal/base_spec.rb48
-rw-r--r--spec/requests/api/internal/container_registry/migration_spec.rb153
-rw-r--r--spec/requests/api/issues/issues_spec.rb48
-rw-r--r--spec/requests/api/lint_spec.rb19
-rw-r--r--spec/requests/api/markdown_spec.rb4
-rw-r--r--spec/requests/api/members_spec.rb2
-rw-r--r--spec/requests/api/merge_requests_spec.rb42
-rw-r--r--spec/requests/api/package_files_spec.rb24
-rw-r--r--spec/requests/api/project_attributes.yml2
-rw-r--r--spec/requests/api/project_clusters_spec.rb32
-rw-r--r--spec/requests/api/project_export_spec.rb2
-rw-r--r--spec/requests/api/project_snapshots_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb5
-rw-r--r--spec/requests/api/repositories_spec.rb11
-rw-r--r--spec/requests/api/rubygem_packages_spec.rb13
-rw-r--r--spec/requests/api/settings_spec.rb45
-rw-r--r--spec/requests/api/tags_spec.rb310
-rw-r--r--spec/requests/api/terraform/modules/v1/packages_spec.rb14
-rw-r--r--spec/requests/api/usage_data_spec.rb26
-rw-r--r--spec/requests/api/users_spec.rb25
-rw-r--r--spec/requests/boards/lists_controller_spec.rb2
-rw-r--r--spec/requests/concerns/planning_hierarchy_spec.rb23
-rw-r--r--spec/requests/git_http_spec.rb26
-rw-r--r--spec/requests/import/gitlab_projects_controller_spec.rb2
-rw-r--r--spec/requests/lfs_http_spec.rb8
-rw-r--r--spec/requests/openid_connect_spec.rb4
-rw-r--r--spec/requests/projects/cluster_agents_controller_spec.rb2
-rw-r--r--spec/requests/projects/clusters/integrations_controller_spec.rb2
-rw-r--r--spec/requests/projects/google_cloud/deployments_controller_spec.rb58
-rw-r--r--spec/requests/projects/google_cloud/service_accounts_controller_spec.rb11
-rw-r--r--spec/requests/projects/merge_requests/creations_spec.rb2
-rw-r--r--spec/requests/projects/merge_requests_discussions_spec.rb2
-rw-r--r--spec/requests/projects/merge_requests_spec.rb2
-rw-r--r--spec/requests/projects/metrics_dashboard_spec.rb2
-rw-r--r--spec/requests/projects/noteable_notes_spec.rb2
-rw-r--r--spec/requests/rack_attack_global_spec.rb32
-rw-r--r--spec/requests/recursive_webhook_detection_spec.rb45
-rw-r--r--spec/requests/users_controller_spec.rb34
-rw-r--r--spec/rubocop/cop/file_decompression_spec.rb48
-rw-r--r--spec/rubocop/cop/gitlab/event_store_subscriber_spec.rb82
-rw-r--r--spec/rubocop/cop/migration/schedule_async_spec.rb51
-rw-r--r--spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb8
-rw-r--r--spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication_spec.rb166
-rw-r--r--spec/serializers/build_details_entity_spec.rb2
-rw-r--r--spec/serializers/ci/lint/result_serializer_spec.rb4
-rw-r--r--spec/serializers/codequality_degradation_entity_spec.rb15
-rw-r--r--spec/serializers/deployment_cluster_entity_spec.rb6
-rw-r--r--spec/serializers/diff_file_base_entity_spec.rb2
-rw-r--r--spec/serializers/environment_serializer_spec.rb15
-rw-r--r--spec/serializers/group_child_entity_spec.rb19
-rw-r--r--spec/serializers/issue_sidebar_basic_entity_spec.rb74
-rw-r--r--spec/serializers/merge_request_poll_cached_widget_entity_spec.rb20
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb10
-rw-r--r--spec/serializers/runner_entity_spec.rb2
-rw-r--r--spec/serializers/test_case_entity_spec.rb12
-rw-r--r--spec/serializers/trigger_variable_entity_spec.rb2
-rw-r--r--spec/services/alert_management/alerts/update_service_spec.rb13
-rw-r--r--spec/services/alert_management/create_alert_issue_service_spec.rb4
-rw-r--r--spec/services/application_settings/update_service_spec.rb18
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb24
-rw-r--r--spec/services/branches/create_service_spec.rb2
-rw-r--r--spec/services/ci/copy_cross_database_associations_service_spec.rb18
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb101
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb16
-rw-r--r--spec/services/ci/pipeline_schedule_service_spec.rb17
-rw-r--r--spec/services/ci/process_sync_events_service_spec.rb76
-rw-r--r--spec/services/ci/register_job_service_spec.rb4
-rw-r--r--spec/services/ci/register_runner_service_spec.rb330
-rw-r--r--spec/services/ci/retry_build_service_spec.rb20
-rw-r--r--spec/services/ci/unregister_runner_service_spec.rb15
-rw-r--r--spec/services/ci/update_build_queue_service_spec.rb32
-rw-r--r--spec/services/ci/update_runner_service_spec.rb14
-rw-r--r--spec/services/concerns/rate_limited_service_spec.rb20
-rw-r--r--spec/services/draft_notes/create_service_spec.rb4
-rw-r--r--spec/services/environments/stop_service_spec.rb8
-rw-r--r--spec/services/feature_flags/update_service_spec.rb2
-rw-r--r--spec/services/google_cloud/create_service_accounts_service_spec.rb16
-rw-r--r--spec/services/google_cloud/enable_cloud_run_service_spec.rb41
-rw-r--r--spec/services/google_cloud/generate_pipeline_service_spec.rb230
-rw-r--r--spec/services/groups/create_service_spec.rb57
-rw-r--r--spec/services/groups/update_statistics_service_spec.rb55
-rw-r--r--spec/services/incident_management/create_incident_label_service_spec.rb7
-rw-r--r--spec/services/incident_management/incidents/create_service_spec.rb36
-rw-r--r--spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb11
-rw-r--r--spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb8
-rw-r--r--spec/services/issues/close_service_spec.rb10
-rw-r--r--spec/services/issues/create_service_spec.rb24
-rw-r--r--spec/services/issues/move_service_spec.rb42
-rw-r--r--spec/services/issues/reorder_service_spec.rb12
-rw-r--r--spec/services/issues/set_crm_contacts_service_spec.rb112
-rw-r--r--spec/services/issues/update_service_spec.rb20
-rw-r--r--spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb78
-rw-r--r--spec/services/members/create_service_spec.rb27
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb32
-rw-r--r--spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb4
-rw-r--r--spec/services/merge_requests/create_service_spec.rb10
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb2
-rw-r--r--spec/services/merge_requests/mergeability_check_service_spec.rb18
-rw-r--r--spec/services/merge_requests/rebase_service_spec.rb2
-rw-r--r--spec/services/merge_requests/squash_service_spec.rb6
-rw-r--r--spec/services/merge_requests/update_service_spec.rb6
-rw-r--r--spec/services/notes/create_service_spec.rb4
-rw-r--r--spec/services/packages/maven/metadata/sync_service_spec.rb19
-rw-r--r--spec/services/packages/nuget/metadata_extraction_service_spec.rb4
-rw-r--r--spec/services/pages/zip_directory_service_spec.rb6
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb26
-rw-r--r--spec/services/projects/container_repository/delete_tags_service_spec.rb18
-rw-r--r--spec/services/projects/create_service_spec.rb98
-rw-r--r--spec/services/projects/destroy_service_spec.rb45
-rw-r--r--spec/services/projects/import_export/export_service_spec.rb15
-rw-r--r--spec/services/projects/import_service_spec.rb2
-rw-r--r--spec/services/projects/overwrite_project_service_spec.rb69
-rw-r--r--spec/services/projects/readme_renderer_service_spec.rb75
-rw-r--r--spec/services/projects/transfer_service_spec.rb31
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb232
-rw-r--r--spec/services/releases/create_service_spec.rb2
-rw-r--r--spec/services/security/ci_configuration/container_scanning_create_service_spec.rb19
-rw-r--r--spec/services/service_ping/submit_service_ping_service_spec.rb39
-rw-r--r--spec/services/system_note_service_spec.rb61
-rw-r--r--spec/services/system_notes/alert_management_service_spec.rb38
-rw-r--r--spec/services/system_notes/incident_service_spec.rb24
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb48
-rw-r--r--spec/services/test_hooks/project_service_spec.rb18
-rw-r--r--spec/services/test_hooks/system_service_spec.rb8
-rw-r--r--spec/services/update_container_registry_info_service_spec.rb15
-rw-r--r--spec/services/web_hook_service_spec.rb65
-rw-r--r--spec/services/work_items/create_service_spec.rb56
-rw-r--r--spec/services/work_items/delete_service_spec.rb50
-rw-r--r--spec/services/work_items/update_service_spec.rb69
-rw-r--r--spec/spec_helper.rb32
-rw-r--r--spec/support/cross_database_modification.rb9
-rw-r--r--spec/support/db_cleaner.rb2
-rw-r--r--spec/support/flaky_tests.rb11
-rw-r--r--spec/support/gitlab_experiment.rb10
-rw-r--r--spec/support/graphql/arguments.rb1
-rw-r--r--spec/support/helpers/fake_blob_helpers.rb5
-rw-r--r--spec/support/helpers/features/invite_members_modal_helper.rb2
-rw-r--r--spec/support/helpers/features/iteration_helpers.rb6
-rw-r--r--spec/support/helpers/gitaly_setup.rb8
-rw-r--r--spec/support/helpers/import_spec_helper.rb2
-rw-r--r--spec/support/helpers/key_generator_helper.rb44
-rw-r--r--spec/support/helpers/login_helpers.rb2
-rw-r--r--spec/support/helpers/memory_usage_helper.rb37
-rw-r--r--spec/support/helpers/merge_request_diff_helpers.rb54
-rw-r--r--spec/support/helpers/note_interaction_helpers.rb4
-rw-r--r--spec/support/helpers/rack_attack_spec_helpers.rb4
-rw-r--r--spec/support/helpers/repo_helpers.rb2
-rw-r--r--spec/support/helpers/session_helpers.rb16
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb2
-rw-r--r--spec/support/helpers/test_env.rb11
-rw-r--r--spec/support/import_export/import_export.yml2
-rw-r--r--spec/support/matchers/event_store.rb12
-rw-r--r--spec/support/matchers/schema_matcher.rb34
-rw-r--r--spec/support/shared_contexts/container_repositories_shared_context.rb27
-rw-r--r--spec/support/shared_contexts/features/integrations/integrations_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb2
-rw-r--r--spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb6
-rw-r--r--spec/support/shared_contexts/graphql/requests/packages_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/lib/container_registry/client_shared_context.rb27
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb1
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb3
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb2
-rw-r--r--spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/features/variable_list_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/graphql/boards_shared_examples.rb58
-rw-r--r--spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb13
-rw-r--r--spec/support/shared_examples/graphql/mutations/security/ci_configuration_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/integrations/integration_settings_form.rb47
-rw-r--r--spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/code_review_extension_request_examples.rb (renamed from spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb)30
-rw-r--r--spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb10
-rw-r--r--spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb18
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb80
-rw-r--r--spec/support/shared_examples/models/note_access_check_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/models/update_project_statistics_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/namespaces/traversal_scope_examples.rb47
-rw-r--r--spec/support/shared_examples/path_extraction_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/policies/clusterable_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb56
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/requests/api/notes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb85
-rw-r--r--spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb93
-rw-r--r--spec/support/shared_examples/services/incident_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/workers/project_export_shared_examples.rb16
-rw-r--r--spec/support/stub_settings_source.rb11
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb79
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb131
-rw-r--r--spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb58
-rw-r--r--spec/tasks/gitlab/info_rake_spec.rb39
-rw-r--r--spec/tooling/danger/project_helper_spec.rb1
-rw-r--r--spec/tooling/docs/deprecation_handling_spec.rb6
-rw-r--r--spec/tooling/lib/tooling/test_map_generator_spec.rb16
-rw-r--r--spec/tooling/quality/test_level_spec.rb4
-rw-r--r--spec/tooling/rspec_flaky/config_spec.rb33
-rw-r--r--spec/tooling/rspec_flaky/listener_spec.rb6
-rw-r--r--spec/uploaders/import_export_uploader_spec.rb28
-rw-r--r--spec/validators/x509_certificate_credentials_validator_spec.rb10
-rw-r--r--spec/views/admin/application_settings/general.html.haml_spec.rb27
-rw-r--r--spec/views/admin/dashboard/index.html.haml_spec.rb29
-rw-r--r--spec/views/devise/shared/_signup_box.html.haml_spec.rb16
-rw-r--r--spec/views/groups/settings/_transfer.html.haml_spec.rb17
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb18
-rw-r--r--spec/views/profiles/keys/_key.html.haml_spec.rb4
-rw-r--r--spec/views/projects/edit.html.haml_spec.rb34
-rw-r--r--spec/views/projects/services/_form.haml_spec.rb52
-rw-r--r--spec/views/shared/_gl_toggle.haml_spec.rb85
-rw-r--r--spec/views/shared/_global_alert.html.haml_spec.rb10
-rw-r--r--spec/views/shared/issuable/_sidebar.html.haml_spec.rb39
-rw-r--r--spec/workers/auto_devops/disable_worker_spec.rb2
-rw-r--r--spec/workers/background_migration/ci_database_worker_spec.rb7
-rw-r--r--spec/workers/background_migration_worker_spec.rb2
-rw-r--r--spec/workers/ci/delete_objects_worker_spec.rb33
-rw-r--r--spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb2
-rw-r--r--spec/workers/cleanup_container_repository_worker_spec.rb2
-rw-r--r--spec/workers/concerns/application_worker_spec.rb39
-rw-r--r--spec/workers/container_expiration_policy_worker_spec.rb5
-rw-r--r--spec/workers/container_registry/migration/enqueuer_worker_spec.rb178
-rw-r--r--spec/workers/container_registry/migration/guard_worker_spec.rb162
-rw-r--r--spec/workers/container_registry/migration/observer_worker_spec.rb57
-rw-r--r--spec/workers/delete_container_repository_worker_spec.rb2
-rw-r--r--spec/workers/delete_merged_branches_worker_spec.rb4
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb6
-rw-r--r--spec/workers/groups/update_statistics_worker_spec.rb29
-rw-r--r--spec/workers/loose_foreign_keys/cleanup_worker_spec.rb10
-rw-r--r--spec/workers/namespaces/process_sync_events_worker_spec.rb12
-rw-r--r--spec/workers/namespaces/update_root_statistics_worker_spec.rb23
-rw-r--r--spec/workers/pages_update_configuration_worker_spec.rb12
-rw-r--r--spec/workers/pipeline_schedule_worker_spec.rb10
-rw-r--r--spec/workers/post_receive_spec.rb16
-rw-r--r--spec/workers/project_destroy_worker_spec.rb4
-rw-r--r--spec/workers/projects/git_garbage_collect_worker_spec.rb15
-rw-r--r--spec/workers/projects/process_sync_events_worker_spec.rb12
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb19
-rw-r--r--spec/workers/web_hook_worker_spec.rb11
-rw-r--r--tooling/danger/project_helper.rb4
-rw-r--r--tooling/lib/tooling/test_map_generator.rb7
-rw-r--r--tooling/quality/test_level.rb1
-rw-r--r--tooling/rspec_flaky/config.rb10
-rw-r--r--vendor/project_templates/cluster_management.tar.gzbin16093 -> 17708 bytes
-rw-r--r--workhorse/.tool-versions2
-rw-r--r--workhorse/Makefile34
-rwxr-xr-xworkhorse/_support/make-gnu-build-id.sh30
-rw-r--r--workhorse/internal/artifacts/artifacts_store_test.go9
-rw-r--r--workhorse/internal/artifacts/artifacts_upload.go2
-rw-r--r--workhorse/internal/dependencyproxy/dependencyproxy_test.go4
-rw-r--r--workhorse/internal/filestore/file_handler_test.go22
-rw-r--r--workhorse/internal/lfs/lfs.go5
-rw-r--r--workhorse/internal/objectstore/object_test.go8
-rw-r--r--workhorse/internal/redis/keywatcher_test.go12
-rw-r--r--workhorse/internal/upload/accelerate.go11
-rw-r--r--workhorse/internal/upload/body_uploader.go35
-rw-r--r--workhorse/internal/upload/body_uploader_test.go12
-rw-r--r--workhorse/internal/upload/rewrite.go14
-rw-r--r--workhorse/internal/upload/rewrite_test.go81
-rw-r--r--workhorse/internal/upload/skip_rails_authorizer.go10
-rw-r--r--workhorse/internal/upload/uploads.go8
-rw-r--r--workhorse/internal/upload/uploads_test.go114
-rw-r--r--workhorse/internal/upstream/routes.go59
-rw-r--r--yarn.lock2549
4783 files changed, 248711 insertions, 74748 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index e80b2e6d9eb..549f1771593 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -95,7 +95,7 @@ rules:
order: ignore
overrides:
- files:
- - '**/spec/**/*'
+ - '{,ee/,jh/}spec/frontend*/**/*'
rules:
'@gitlab/require-i18n-strings': off
'@gitlab/no-runtime-template-compiler': off
@@ -103,6 +103,8 @@ overrides:
- error
- selector: CallExpression[callee.object.name=/(wrapper|vm)/][callee.property.name="setData"]
message: 'Avoid using "setData" on VTU wrapper'
+ - selector: MemberExpression[object.type!='ThisExpression'][property.type='Identifier'][property.name='$nextTick']
+ message: 'Using $nextTick from a component instance is discouraged. Import nextTick directly from the Vue package.'
- files:
- 'config/**/*'
- 'scripts/**/*'
diff --git a/.gitignore b/.gitignore
index 03f77ed89e5..bdd3ac98876 100644
--- a/.gitignore
+++ b/.gitignore
@@ -79,6 +79,7 @@ eslint-report.html
/deprecations/
/knapsack/
/rspec_flaky/
+/rspec/
/locale/**/LC_MESSAGES
/locale/**/*.time_stamp
/.rspec
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 314f99c5f41..1b551967cb3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,7 +16,7 @@ stages:
# in cases where jobs require Docker-in-Docker, the job
# definition must be extended with `.use-docker-in-docker`
default:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36
tags:
- gitlab-org
# All jobs are interruptible by default
@@ -67,12 +67,17 @@ variables:
GIT_DEPTH: "20"
GIT_SUBMODULE_STRATEGY: "none"
GET_SOURCES_ATTEMPTS: "3"
+ DEBIAN_VERSION: "bullseye"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/report-master.json
- FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
+ FLAKY_RSPEC_SUITE_REPORT_PATH: rspec/flaky/report-suite.json
RSPEC_TESTS_MAPPING_PATH: crystalball/mapping.json
RSPEC_PACKED_TESTS_MAPPING_PATH: crystalball/packed-mapping.json
+ RSPEC_PROFILING_FOLDER_PATH: rspec/profiling
FRONTEND_FIXTURES_MAPPING_PATH: crystalball/frontend_fixtures_mapping.json
+ RSPEC_LAST_RUN_RESULTS_FILE: rspec/rspec_last_run_results.txt
+ JUNIT_RESULT_FILE: rspec/junit_rspec.xml
+ JUNIT_RETRY_FILE: rspec/junit_rspec-retry.xml
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
ELASTIC_URL: "http://elastic:changeme@elasticsearch:9200"
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 71e4571b603..ab9805bda7d 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -208,152 +208,588 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
+/doc/administration/application_settings_cache.md @marcia
+/doc/administration/audit_event_streaming.md @eread
+/doc/administration/audit_events.md @eread
+/doc/administration/audit_reports.md @eread
+/doc/administration/auditor_users.md @axil
+/doc/administration/auth/atlassian.md @eread
+/doc/administration/auth/authentiq.md @eread
+/doc/administration/auth/cognito.md @eread
+/doc/administration/auth/crowd.md @eread
+/doc/administration/auth/index.md @eread
+/doc/administration/auth/ldap/google_secure_ldap.md @eread
+/doc/administration/auth/jwt.md @eread
+/doc/administration/auth/ldap/ldap-troubleshooting.md @eread
+/doc/administration/auth/ldap/ldap_synchronization.md @eread
+/doc/administration/auth/ldap/index.md @eread
+/doc/administration/auth/oidc.md @eread
+/doc/administration/auth/smartcard.md @eread
+/doc/administration/cicd.md @marcel.amirault
+/doc/administration/clusters/kas.md @marcia
+/doc/administration/compliance.md @eread
+/doc/administration/configure.md @axil
+/doc/administration/consul.md @axil
+/doc/administration/docs_self_host.md @axil
+/doc/administration/encrypted_configuration.md @axil
+/doc/administration/environment_variables.md @axil
+/doc/administration/external_pipeline_validation.md @marcel.amirault
+/doc/administration/feature_flags.md @axil
+/doc/administration/file_hooks.md @aqualls
/doc/administration/geo/ @axil
+/doc/administration/git_protocol.md @aqualls
/doc/administration/gitaly/ @eread
-/doc/administration/lfs/ @aqualls
+/doc/administration/housekeeping.md @axil
+/doc/administration/incoming_email.md @msedlakjakubowski
+/doc/administration/index.md @axil
+/doc/administration/instance_limits.md @axil
+/doc/administration/instance_review.md @kpaizee
+/doc/administration/integration/kroki.md @kpaizee
+/doc/administration/integration/mailgun.md @kpaizee
+/doc/administration/integration/plantuml.md @aqualls
+/doc/administration/integration/terminal.md @kpaizee
+/doc/administration/invalidate_markdown_cache.md @msedlakjakubowski
+/doc/administration/issue_closing_pattern.md @aqualls
+/doc/administration/job_artifacts.md @eread
+/doc/administration/job_logs.md @sselhorn
+/doc/administration/lfs/index.md @aqualls
+/doc/administration/libravatar.md @axil
+/doc/administration/load_balancer.md @axil
+/doc/administration/logs.md @ngaskill
+/doc/administration/maintenance_mode/index.md @axil
+/doc/administration/merge_request_diffs.md @aqualls
/doc/administration/monitoring/ @ngaskill
-/doc/administration/operations/ @axil @eread @marcia
+/doc/administration/nfs.md @axil
+/doc/administration/object_storage.md @axil
+/doc/administration/operations/ @axil
+/doc/administration/operations/sidekiq_memory_killer.md @marcia
+/doc/administration/package_information/ @axil
/doc/administration/packages/ @ngaskill
-/doc/administration/pages/ @rdickenson @kpaizee
+/doc/administration/pages/ @rdickenson
+/doc/administration/polling.md @axil
/doc/administration/postgresql/ @marcia
-/doc/administration/raketasks/ @axil @eread
+/doc/administration/pseudonymizer.md @axil
+/doc/administration/raketasks/ @axil
+/doc/administration/read_only_gitlab.md @axil
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
-/doc/administration/snippets/ @aqualls
-/doc/administration/troubleshooting @axil @marcia @eread
-/doc/api/graphql/ @msedlakjakubowski @kpaizee
-/doc/api/graphql/reference/ @kpaizee
-/doc/api/group_activity_analytics.md @fneill
-/doc/api/vulnerabilities.md @fneill
-/doc/ci/ @marcel.amirault @sselhorn
-/doc/ci/environments/ @rdickenson
-/doc/ci/services/ @sselhorn
-/doc/ci/test_cases/ @msedlakjakubowski
-/doc/development/ @marcia
-/doc/development/documentation/ @cnorris @dianalogan
-/doc/development/i18n/ @ngaskill
-/doc/development/value_stream_analytics.md @fneill
-/doc/gitlab-basics/ @aqualls
-/doc/install/ @axil
-/doc/operations/ @ngaskill @rdickenson
-/doc/push_rules/ @aqualls
-/doc/security/ @eread
-/doc/ssh/ @eread
-/doc/subscriptions/ @sselhorn
-/doc/topics/autodevops/ @marcia
-/doc/topics/git/ @aqualls
-/doc/update/ @axil @marcia
-/doc/user/analytics/ @fneill @ngaskill
-/doc/user/application_security/ @rdickenson
-/doc/user/application_security/container_scanning/ @ngaskill
-/doc/user/application_security/cluster_image_scanning/ @ngaskill
-/doc/user/application_security/cve_id_request.md @fneill
-/doc/user/application_security/security_dashboard @fneill
-/doc/user/application_security/vulnerabilities @fneill
-/doc/user/application_security/vulnerability_report @fneill
-/doc/user/clusters/ @marcia
-/doc/user/compliance/ @rdickenson @eread
-/doc/user/group/ @msedlakjakubowski
-/doc/user/group/devops_adoption/ @fneill
-/doc/user/group/epics/ @msedlakjakubowski
-/doc/user/group/insights/ @fneill
-/doc/user/group/iterations/ @msedlakjakubowski
-/doc/user/group/roadmap/ @msedlakjakubowski
-/doc/user/group/value_stream_analytics/ @fneill
-/doc/user/infrastructure/ @marcia
-/doc/user/packages/ @ngaskill
-/doc/user/packages/infrastructure_registry/ @marcia
-/doc/user/packages/terraform_module_registry/ @marcia
-/doc/user/profile/ @msedlakjakubowski @eread
-/doc/user/project/ @aqualls @rdickenson @eread @msedlakjakubowski @ngaskill
-/doc/user/project/clusters/ @marcia
-/doc/user/project/import/ @ngaskill @msedlakjakubowski
-/doc/user/project/issues/ @msedlakjakubowski
-/doc/user/project/merge_requests/ @aqualls @eread
-/doc/user/project/milestones/ @msedlakjakubowski
-/doc/user/project/pages/ @rdickenson
-/doc/user/project/repository/ @aqualls
-/doc/user/project/settings/ @aqualls @eread
-/doc/user/project/static_site_editor/index.md @aqualls
-/doc/user/project/web_ide/index.md @aqualls
-/doc/user/project/wiki/index.md @aqualls
-/doc/user/search/ @marcia @aqualls
-/doc/user/workspace/ @fneill
-
-[Docs Create]
-/doc/administration/file_hooks.md @aqualls
-/doc/administration/git_protocol.md @aqualls
-/doc/administration/invalidate_markdown_cache.md @aqualls
-/doc/administration/issue_closing_pattern.md @aqualls
-/doc/administration/merge_request_diffs.md @aqualls
-/doc/administration/repository_checks.md @aqualls
+/doc/administration/reply_by_email_postfix_setup.md @axil
+/doc/administration/reply_by_email.md @msedlakjakubowski
+/doc/administration/repository_checks.md @eread
+/doc/administration/repository_storage_paths.md @eread
+/doc/administration/repository_storage_types.md @eread
+/doc/administration/restart_gitlab.md @axil
+/doc/administration/server_hooks.md @eread
+/doc/administration/sidekiq.md @axil
+/doc/administration/smime_signing_email.md @axil
+/doc/administration/snippets/index.md @aqualls
/doc/administration/static_objects_external_storage.md @aqualls
-/doc/api/access_requests.md @aqualls
+/doc/administration/terraform_state.md @marcia
+/doc/administration/timezone.md @axil
+/doc/administration/troubleshooting/ @axil
+/doc/administration/troubleshooting/group_saml_scim.md @eread
+/doc/administration/troubleshooting/postgresql.md @marcia
+/doc/administration/uploads.md @axil
+/doc/administration/user_settings.md @eread
+/doc/administration/whats-new.md @kpaizee
+/doc/administration/wikis/index.md @aqualls
+/doc/api/access_requests.md @eread
+/doc/api/admin_sidekiq_queues.md @axil
+/doc/api/api_resources.md @kpaizee
+/doc/api/appearance.md @eread
+/doc/api/applications.md @eread
+/doc/api/audit_events.md @eread
+/doc/api/avatar.md @eread
+/doc/api/award_emoji.md @msedlakjakubowski
+/doc/api/boards.md @msedlakjakubowski
/doc/api/branches.md @aqualls
+/doc/api/broadcast_messages.md @kpaizee
+/doc/api/bulk_imports.md @ngaskill
/doc/api/commits.md @aqualls
+/doc/api/container_registry.md @ngaskill
+/doc/api/custom_attributes.md @kpaizee
+/doc/api/dependencies.md @rdickenson
+/doc/api/dependency_proxy.md @ngaskill
+/doc/api/deploy_keys.md @rdickenson
+/doc/api/deploy_tokens.md @rdickenson
+/doc/api/deployments.md @rdickenson
/doc/api/discussions.md @aqualls
+/doc/api/dora/metrics.md @fneill
+/doc/api/dora4_project_analytics.md @fneill
+/doc/api/environments.md @rdickenson
+/doc/api/epic_issues.md @msedlakjakubowski
+/doc/api/epic_links.md @msedlakjakubowski
+/doc/api/epics.md @msedlakjakubowski
+/doc/api/error_tracking.md @ngaskill
+/doc/api/events.md @eread
+/doc/api/experiments.md @kpaizee
+/doc/api/feature_flag_specs.md @rdickenson
+/doc/api/feature_flag_user_lists.md @rdickenson
+/doc/api/feature_flags_legacy.md @rdickenson
+/doc/api/feature_flags.md @rdickenson
+/doc/api/features.md @rdickenson
+/doc/api/freeze_periods.md @rdickenson
+/doc/api/geo_nodes.md @axil
+/doc/api/graphql/ @kpaizee
+/doc/api/graphql/custom_emoji.md @msedlakjakubowski
+/doc/api/graphql/sample_issue_boards.md @msedlakjakubowski
+/doc/api/group_activity_analytics.md @fneill
+/doc/api/group_badges.md @eread
+/doc/api/group_boards.md @msedlakjakubowski
+/doc/api/group_clusters.md @marcia
+/doc/api/group_import_export.md @ngaskill
+/doc/api/group_iterations.md @msedlakjakubowski
+/doc/api/group_labels.md @msedlakjakubowski
+/doc/api/group_level_variables.md @marcel.amirault
+/doc/api/group_milestones.md @msedlakjakubowski
+/doc/api/group_protected_environments.md @rdickenson
+/doc/api/group_relations_export.md @ngaskill
+/doc/api/group_repository_storage_moves.md @aqualls
/doc/api/group_wikis.md @aqualls
+/doc/api/groups.md @eread
+/doc/api/import.md @ngaskill
+/doc/api/index.md @kpaizee
+/doc/api/instance_clusters.md @marcia
+/doc/api/instance_level_ci_variables.md @marcel.amirault
+/doc/api/integrations.md @kpaizee
+/doc/api/invitations.md @kpaizee
+/doc/api/issue_links.md @msedlakjakubowski
+/doc/api/issues_statistics.md @msedlakjakubowski
+/doc/api/issues.md @msedlakjakubowski
+/doc/api/iterations.md @msedlakjakubowski
+/doc/api/job_artifacts.md @eread
+/doc/api/jobs.md @marcel.amirault
/doc/api/keys.md @aqualls
+/doc/api/labels.md @msedlakjakubowski
+/doc/api/license.md @kpaizee
+/doc/api/lint.md @marcel.amirault
+/doc/api/managed_licenses.md @kpaizee
/doc/api/markdown.md @aqualls
+/doc/api/members.md @eread
/doc/api/merge_request_approvals.md @aqualls
/doc/api/merge_request_context_commits.md @aqualls
/doc/api/merge_requests.md @aqualls
+/doc/api/merge_trains.md @marcel.amirault
+/doc/api/metrics_dashboard_annotations.md @ngaskill
+/doc/api/metrics_user_starred_dashboards.md @ngaskill
+/doc/api/milestones.md @msedlakjakubowski
+/doc/api/namespaces.md @eread
+/doc/api/notes.md @msedlakjakubowski
+/doc/api/notification_settings.md @msedlakjakubowski
+/doc/api/oauth2.md @eread
+/doc/api/openapi/openapi_interactive.md @kpaizee
+/doc/api/packages.md @ngaskill
+/doc/api/packages/ @ngaskill
+/doc/api/pages_domains.md @rdickenson
+/doc/api/pages.md @rdickenson
+/doc/api/personal_access_tokens.md @eread
+/doc/api/pipeline_schedules.md @marcel.amirault
+/doc/api/pipeline_triggers.md @marcel.amirault
+/doc/api/pipelines.md @marcel.amirault
+/doc/api/plan_limits.md @eread
/doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls
+/doc/api/project_clusters.md @marcia
/doc/api/project_import_export.md @aqualls
-/doc/api/project_level_variables.md @aqualls
+/doc/api/project_level_variables.md @marcel.amirault
+/doc/api/project_relations_export.md @ngaskill
+/doc/api/project_repository_storage_moves.md @eread
/doc/api/project_snippets.md @aqualls
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
+/doc/api/projects.md @msedlakjakubowski
/doc/api/protected_branches.md @aqualls
+/doc/api/protected_environments.md @rdickenson
/doc/api/protected_tags.md @aqualls
+/doc/api/releases/index.md @rdickenson
+/doc/api/releases/links.md @rdickenson
/doc/api/remote_mirrors.md @aqualls
/doc/api/repositories.md @aqualls
/doc/api/repository_files.md @aqualls
/doc/api/repository_submodules.md @aqualls
+/doc/api/resource_access_tokens.md @eread
+/doc/api/resource_groups.md @rdickenson
+/doc/api/resource_iteration_events.md @msedlakjakubowski
+/doc/api/resource_label_events.md @eread
+/doc/api/resource_milestone_events.md @msedlakjakubowski
+/doc/api/resource_state_events.md @msedlakjakubowski
+/doc/api/resource_weight_events.md @msedlakjakubowski
+/doc/api/runners.md @sselhorn
+/doc/api/scim.md @eread
/doc/api/search.md @aqualls
-/doc/api/services.md @aqualls
+/doc/api/settings.md @eread
+/doc/api/sidekiq_metrics.md @axil
+/doc/api/snippet_repository_storage_moves.md @aqualls
/doc/api/snippets.md @aqualls
+/doc/api/statistics.md @eread
+/doc/api/status_checks.md @eread
/doc/api/suggestions.md @aqualls
+/doc/api/system_hooks.md @kpaizee
/doc/api/tags.md @aqualls
-/doc/api/visual_review_discussions.md @aqualls
+/doc/api/templates/dockerfiles.md @aqualls
+/doc/api/templates/gitignores.md @aqualls
+/doc/api/templates/gitlab_ci_ymls.md @marcel.amirault
+/doc/api/templates/licenses.md @rdickenson
+/doc/api/todos.md @msedlakjakubowski
+/doc/api/topics.md @fneill
+/doc/api/usage_data.md @fneill
+/doc/api/users.md @eread
+/doc/api/v3_to_v4.md @kpaizee
+/doc/api/version.md @kpaizee
+/doc/api/visual_review_discussions.md @eread
+/doc/api/vulnerabilities.md @fneill
+/doc/api/vulnerability_exports.md @fneill
+/doc/api/vulnerability_findings.md @fneill
/doc/api/wikis.md @aqualls
-/doc/intro/index.md @aqualls
+/doc/architecture/blueprints/container_registry_metadata_database/index.md @ngaskill
+/doc/architecture/blueprints/database/scalability/patterns/ @marcia
+/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md @marcia
+/doc/ci/caching/index.md @marcel.amirault
+/doc/ci/chatops/index.md @marcia
+/doc/ci/ci_cd_for_external_repos/ @marcel.amirault
+/doc/ci/cloud_deployment/ecs/quick_start_guide.md @rdickenson
+/doc/ci/cloud_deployment/index.md @rdickenson
+/doc/ci/directed_acyclic_graph/index.md @marcel.amirault
+/doc/ci/docker/index.md @marcel.amirault
+/doc/ci/docker/using_docker_build.md @marcel.amirault
+/doc/ci/docker/using_docker_images.md @sselhorn
+/doc/ci/docker/using_kaniko.md @marcel.amirault
+/doc/ci/enable_or_disable_ci.md @marcel.amirault
+/doc/ci/environments/ @rdickenson
+/doc/ci/examples/authenticating-with-hashicorp-vault/index.md @rdickenson
+/doc/ci/examples/deployment/composer-npm-deploy.md @rdickenson
+/doc/ci/examples/deployment/index.md @rdickenson
+/doc/ci/examples/end_to_end_testing_webdriverio/index.md @eread
+/doc/ci/examples/index.md @marcel.amirault
+/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md @marcel.amirault
+/doc/ci/examples/php.md @marcel.amirault
+/doc/ci/examples/semantic-release.md @ngaskill
+/doc/ci/git_submodules.md @marcel.amirault
+/doc/ci/index.md @marcel.amirault
+/doc/ci/interactive_web_terminal/index.md @sselhorn
+/doc/ci/introduction/index.md @marcel.amirault
+/doc/ci/jobs/ci_job_token.md @marcel.amirault
+/doc/ci/jobs/index.md @marcel.amirault
+/doc/ci/jobs/job_control.md @marcel.amirault
+/doc/ci/large_repositories/index.md @sselhorn
+/doc/ci/lint.md @marcel.amirault
+/doc/ci/metrics_reports.md @eread
+/doc/ci/migration/circleci.md @marcel.amirault
+/doc/ci/migration/jenkins.md @marcel.amirault
+/doc/ci/pipeline_editor/index.md @marcel.amirault
+/doc/ci/pipelines/ @marcel.amirault
+/doc/ci/pipelines/job_artifacts.md @eread
+/doc/ci/pipelines/pipeline_artifacts.md @eread
+/doc/ci/quick_start/index.md @marcel.amirault
+/doc/ci/resource_groups/index.md @rdickenson
+/doc/ci/review_apps/index.md @eread
+/doc/ci/runners/ @sselhorn
+/doc/ci/secrets/index.md @marcia
+/doc/ci/services/ @sselhorn
+/doc/ci/ssh_keys/index.md @marcel.amirault
+/doc/ci/test_cases/index.md @msedlakjakubowski
+/doc/ci/triggers/index.md @marcel.amirault
+/doc/ci/troubleshooting.md @marcel.amirault
+/doc/ci/unit_test_reports.md @eread
+/doc/ci/variables/ @marcel.amirault
+/doc/ci/yaml/ @marcel.amirault
+/doc/ci/yaml/artifacts_reports.md @eread
+/doc/development/adding_database_indexes.md @marcia
+/doc/development/application_limits.md @axil
+/doc/development/approval_rules.md @aqualls
+/doc/development/audit_event_guide/index.md @eread
+/doc/development/auto_devops.md @marcia
+/doc/development/avoiding_downtime_in_migrations.md @marcia
+/doc/development/backend/ruby_style_guide.md @marcia
+/doc/development/background_migrations.md @marcia
+/doc/development/build_test_package.md @axil
+/doc/development/bulk_import.md @ngaskill
+/doc/development/cascading_settings.md @eread
+/doc/development/chatops_on_gitlabcom.md @marcia
+/doc/development/cicd/cicd_reference_documentation_guide.md @marcel.amirault
+/doc/development/cicd/index.md @marcel.amirault
+/doc/development/cicd/templates.md @marcel.amirault
+/doc/development/code_intelligence/index.md @aqualls
+/doc/development/contributing/ @marcia
+/doc/development/creating_enums.md @marcia
+/doc/development/database_debugging.md @marcia
+/doc/development/database_query_comments.md @marcia
+/doc/development/database_review.md @marcia
+/doc/development/database/ @marcia
+/doc/development/db_dump.md @marcia
+/doc/development/developing_with_solargraph.md @aqualls
+/doc/development/distributed_tracing.md @ngaskill
+/doc/development/documentation/feature_flags.md @marcia
+/doc/development/documentation/graphql_styleguide.md @marcia
+/doc/development/documentation/index.md @cnorris
+/doc/development/documentation/redirects.md @cnorris
+/doc/development/documentation/restful_api_styleguide.md @marcia
+/doc/development/documentation/review_apps.md @cnorris
+/doc/development/documentation/structure.md @sselhorn
+/doc/development/documentation/styleguide/index.md @sselhorn
+/doc/development/documentation/styleguide/word_list.md @sselhorn
+/doc/development/documentation/testing.md @cnorris
+/doc/development/elasticsearch.md @marcia
+/doc/development/experiment_guide/ @kpaizee
+/doc/development/export_csv.md @ngaskill
+/doc/development/fe_guide/content_editor.md @aqualls
+/doc/development/fe_guide/dark_mode.md @marcia
+/doc/development/fe_guide/graphql.md @marcia
+/doc/development/fe_guide/source_editor.md @aqualls
+/doc/development/feature_categorization/index.md @marcia
+/doc/development/feature_flags/controls.md @marcia
+/doc/development/feature_flags/index.md @marcia
+/doc/development/filtering_by_label.md @msedlakjakubowski
+/doc/development/foreign_keys.md @marcia
+/doc/development/geo.md @axil
+/doc/development/geo/framework.md @axil
+/doc/development/git_object_deduplication.md @eread
+/doc/development/gitaly.md @eread
+/doc/development/graphql_guide/batchloader.md @marcia
+/doc/development/graphql_guide/graphql_pro.md @kpaizee
+/doc/development/graphql_guide/index.md @kpaizee
+/doc/development/graphql_guide/pagination.md @kpaizee
+/doc/development/hash_indexes.md @marcia
+/doc/development/i18n/ @ngaskill
+/doc/development/image_scaling.md @marcia
+/doc/development/import_export.md @ngaskill
+/doc/development/index.md @marcia
+/doc/development/insert_into_tables_in_batches.md @marcia
+/doc/development/integrations/codesandbox.md @marcia
+/doc/development/integrations/jenkins.md @kpaizee
+/doc/development/integrations/jira_connect.md @kpaizee
+/doc/development/integrations/secure_partner_integration.md @rdickenson
+/doc/development/integrations/secure.md @ngaskill
+/doc/development/internal_api/ @aqualls
+/doc/development/internal_users.md @marcia
+/doc/development/issuable-like-models.md @msedlakjakubowski
+/doc/development/issue_types.md @msedlakjakubowski
+/doc/development/iterating_tables_in_batches.md @marcia
+/doc/development/kubernetes.md @marcia
+/doc/development/lfs.md @aqualls
+/doc/development/licensed_feature_availability.md @sselhorn
+/doc/development/logging.md @ngaskill
+/doc/development/maintenance_mode.md @axil
+/doc/development/new_fe_guide/modules/widget_extensions.md @aqualls
+/doc/development/new_fe_guide/tips.md @marcia
+/doc/development/omnibus.md @axil
+/doc/development/ordering_table_columns.md @marcia
+/doc/development/packages.md @ngaskill
+/doc/development/permissions.md @eread
+/doc/development/policies.md @eread
+/doc/development/prometheus_metrics.md @ngaskill
+/doc/development/query_performance.md @marcia
+/doc/development/real_time.md @msedlakjakubowski
+/doc/development/secure_coding_guidelines.md @marcia
+/doc/development/serializing_data.md @marcia
+/doc/development/service_ping/ @fneill
+/doc/development/snowplow/ @fneill
+/doc/development/sql.md @marcia
+/doc/development/stage_group_dashboards.md @marcia
+/doc/development/swapping_tables.md @marcia
+/doc/development/testing_guide/best_practices.md @marcia
+/doc/development/testing_guide/end_to_end/best_practices.md @marcia
+/doc/development/understanding_explain_plans.md @marcia
+/doc/development/value_stream_analytics.md @fneill
+/doc/development/verifying_database_capabilities.md @marcia
+/doc/development/wikis.md @aqualls
+/doc/development/work_items.md @msedlakjakubowski
+/doc/development/work_items_widgets.md @msedlakjakubowski
+/doc/downgrade_ee_to_ce/index.md @axil
+/doc/gitlab-basics/add-file.md @aqualls
+/doc/gitlab-basics/command-line-commands.md @aqualls
+/doc/gitlab-basics/create-branch.md @aqualls
+/doc/gitlab-basics/feature_branch_workflow.md @aqualls
+/doc/gitlab-basics/index.md @aqualls
+/doc/gitlab-basics/start-using-git.md @aqualls
+/doc/install/ @axil
+/doc/integration/ @kpaizee
+/doc/integration/elasticsearch.md @marcia
+/doc/integration/gitpod.md @aqualls
+/doc/integration/kerberos.md @eread
+/doc/integration/mattermost/index.md @axil
+/doc/integration/oauth_provider.md @eread
+/doc/integration/saml.md @eread
+/doc/integration/security_partners/index.md @rdickenson
+/doc/integration/sourcegraph.md @aqualls
+/doc/integration/vault.md @rdickenson
+/doc/operations/ @ngaskill
+/doc/operations/feature_flags.md @rdickenson
+/doc/operations/product_analytics.md @fneill
+/doc/policy/ @axil
+/doc/public_access/public_access.md @fneill
+/doc/raketasks/ @axil
+/doc/raketasks/generate_sample_prometheus_data.md @ngaskill
+/doc/raketasks/migrate_snippets.md @aqualls
+/doc/raketasks/spdx.md @rdickenson
+/doc/raketasks/x509_signatures.md @aqualls
+/doc/security/ @eread
+/doc/ssh/index.md @eread
+/doc/subscriptions/ @sselhorn
+/doc/system_hooks/system_hooks.md @kpaizee
+/doc/topics/authentication/index.md @eread
+/doc/topics/autodevops/customize.md @marcia
+/doc/topics/autodevops/ @marcia
+/doc/topics/git/ @aqualls
/doc/topics/gitlab_flow.md @aqualls
+/doc/topics/offline/ @axil
+/doc/topics/plan_and_track.md @msedlakjakubowski
+/doc/update/ @axil
+/doc/update/mysql_to_postgresql.md @marcia
+/doc/update/upgrading_postgresql_using_slony.md @marcia
+/doc/user/admin_area/analytics/ @fneill
+/doc/user/admin_area/broadcast_messages.md @kpaizee
+/doc/user/admin_area/credentials_inventory.md @eread
+/doc/user/admin_area/custom_project_templates.md @ngaskill
+/doc/user/admin_area/diff_limits.md @aqualls
+/doc/user/admin_area/geo_nodes.md @axil
+/doc/user/admin_area/labels.md @msedlakjakubowski
+/doc/user/admin_area/license.md @kpaizee
+/doc/user/admin_area/merge_requests_approvals.md @aqualls
+/doc/user/admin_area/moderate_users.md @eread
+/doc/user/admin_area/monitoring/background_migrations.md @marcia
+/doc/user/admin_area/monitoring/health_check.md @ngaskill
+/doc/user/admin_area/review_abuse_reports.md @eread
/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
+/doc/user/admin_area/settings/continuous_integration.md @marcel.amirault
+/doc/user/admin_area/settings/deprecated_api_rate_limits.md @aqualls
+/doc/user/admin_area/settings/email.md @msedlakjakubowski
+/doc/user/admin_area/settings/external_authorization.md @eread
+/doc/user/admin_area/settings/files_api_rate_limits.md @aqualls
+/doc/user/admin_area/settings/git_lfs_rate_limits.md @aqualls
+/doc/user/admin_area/settings/gitaly_timeouts.md @eread
+/doc/user/admin_area/settings/import_export_rate_limits.md @ngaskill
+/doc/user/admin_area/settings/index.md @aqualls
/doc/user/admin_area/settings/instance_template_repository.md @aqualls
-/doc/user/admin_area/settings/project_integration_management.md @aqualls
+/doc/user/admin_area/settings/package_registry_rate_limits.md @ngaskill
+/doc/user/admin_area/settings/project_integration_management.md @kpaizee
/doc/user/admin_area/settings/push_event_activities_limit.md @aqualls
+/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @msedlakjakubowski
+/doc/user/admin_area/settings/rate_limit_on_notes_creation.md @msedlakjakubowski
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
+/doc/user/analytics/ci_cd_analytics.md @rdickenson
+/doc/user/analytics/ @fneill
+/doc/user/application_security/ @rdickenson
+/doc/user/application_security/cluster_image_scanning/index.md @ngaskill
+/doc/user/application_security/container_scanning/index.md @ngaskill
+/doc/user/application_security/cve_id_request.md @fneill
+/doc/user/application_security/policies/index.md @ngaskill
+/doc/user/application_security/security_dashboard/index.md @fneill
+/doc/user/application_security/threat_monitoring/index.md @ngaskill
+/doc/user/application_security/vulnerabilities/ @fneill
+/doc/user/application_security/vulnerability_report/index.md @fneill
/doc/user/asciidoc.md @aqualls
-/doc/user/index.md @aqualls
+/doc/user/award_emojis.md @msedlakjakubowski
+/doc/user/clusters/ @marcia
+/doc/user/compliance/compliance_report/index.md @eread
+/doc/user/compliance/index.md @eread
+/doc/user/compliance/license_compliance/index.md @rdickenson
+/doc/user/discussions/index.md @aqualls
+/doc/user/feature_flags.md @marcia
+/doc/user/group/clusters/index.md @marcia
+/doc/user/group/contribution_analytics/index.md @fneill
+/doc/user/group/custom_project_templates.md @ngaskill
+/doc/user/group/devops_adoption/index.md @fneill
+/doc/user/group/epics/epic_boards.md @msedlakjakubowski
+/doc/user/group/epics/index.md @msedlakjakubowski
+/doc/user/group/epics/manage_epics.md @msedlakjakubowski
+/doc/user/group/import/index.md @ngaskill
+/doc/user/group/index.md @eread
+/doc/user/group/insights/index.md @fneill
+/doc/user/group/issues_analytics/index.md @msedlakjakubowski
+/doc/user/group/iterations/index.md @msedlakjakubowski
+/doc/user/group/repositories_analytics/index.md @eread
+/doc/user/group/roadmap/index.md @msedlakjakubowski
+/doc/user/group/saml_sso/group_managed_accounts.md @eread
+/doc/user/group/saml_sso/index.md @eread
+/doc/user/group/saml_sso/scim_setup.md @eread
+/doc/user/group/settings/import_export.md @ngaskill
+/doc/user/group/subgroups/index.md @eread
+/doc/user/group/value_stream_analytics/index.md @fneill
+/doc/user/infrastructure/clusters/ @marcia
+/doc/user/infrastructure/clusters/manage/clusters_health.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md @sselhorn
+/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md @marcia
+/doc/user/infrastructure/iac/ @marcia
+/doc/user/infrastructure/index.md @marcia
/doc/user/markdown.md @aqualls
+/doc/user/packages/ @ngaskill
+/doc/user/packages/infrastructure_registry/index.md @marcia
+/doc/user/packages/terraform_module_registry/index.md @marcia
+/doc/user/permissions.md @eread
+/doc/user/profile/ @eread
+/doc/user/profile/notifications.md @msedlakjakubowski
/doc/user/project/autocomplete_characters.md @aqualls
/doc/user/project/badges.md @aqualls
+/doc/user/project/clusters/ @marcia
+/doc/user/project/clusters/kubernetes_pod_logs.md @ngaskill
+/doc/user/project/clusters/protect/ @ngaskill
/doc/user/project/code_intelligence.md @aqualls
/doc/user/project/code_owners.md @aqualls
+/doc/user/project/deploy_boards.md @rdickenson
+/doc/user/project/deploy_keys/index.md @rdickenson
+/doc/user/project/deploy_tokens/index.md @rdickenson
+/doc/user/project/description_templates.md @msedlakjakubowski
/doc/user/project/file_lock.md @aqualls
/doc/user/project/git_attributes.md @aqualls
/doc/user/project/highlighting.md @aqualls
-/doc/user/project/index.md @aqualls
+/doc/user/project/import/ @ngaskill
+/doc/user/project/import/jira.md @msedlakjakubowski
+/doc/user/project/index.md @fneill
+/doc/user/project/integrations/ @kpaizee
+/doc/user/project/integrations/prometheus_library/ @ngaskill
+/doc/user/project/integrations/prometheus.md @ngaskill
+/doc/user/project/issue_board.md @msedlakjakubowski
+/doc/user/project/issues/ @msedlakjakubowski
+/doc/user/project/labels.md @msedlakjakubowski
+/doc/user/project/members/index.md @eread
+/doc/user/project/members/share_project_with_groups.md @fneill
+/doc/user/project/merge_requests/ @aqualls
+/doc/user/project/merge_requests/accessibility_testing.md @eread
+/doc/user/project/merge_requests/browser_performance_testing.md @eread
+/doc/user/project/merge_requests/code_quality.md @rdickenson
+/doc/user/project/merge_requests/csv_export.md @eread
+/doc/user/project/merge_requests/fail_fast_testing.md @eread
+/doc/user/project/merge_requests/load_performance_testing.md @eread
+/doc/user/project/merge_requests/status_checks.md @eread
+/doc/user/project/merge_requests/test_coverage_visualization.md @eread
+/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md @eread
+/doc/user/project/milestones/ @msedlakjakubowski
+/doc/user/project/pages/ @rdickenson
/doc/user/project/protected_branches.md @aqualls
/doc/user/project/protected_tags.md @aqualls
/doc/user/project/push_options.md @aqualls
-/doc/user/project/settings/import_export.md @aqualls
+/doc/user/project/quick_actions.md @msedlakjakubowski
+/doc/user/project/releases/index.md @rdickenson
+/doc/user/project/releases/release_cli.md @rdickenson
+/doc/user/project/repository/ @aqualls
+/doc/user/project/repository/reducing_the_repo_size_using_git.md @eread
+/doc/user/project/requirements/index.md @msedlakjakubowski
+/doc/user/project/service_desk.md @msedlakjakubowski
+/doc/user/project/settings/import_export.md @ngaskill
+/doc/user/project/settings/index.md @fneill
+/doc/user/project/settings/project_access_tokens.md @eread
+/doc/user/project/static_site_editor/index.md @aqualls
+/doc/user/project/time_tracking.md @msedlakjakubowski
+/doc/user/project/web_ide/index.md @aqualls
+/doc/user/project/wiki/group.md @aqualls
+/doc/user/project/wiki/index.md @aqualls
+/doc/user/project/working_with_projects.md @fneill
+/doc/user/reserved_names.md @fneill
+/doc/user/search/advanced_search.md @marcia
+/doc/user/search/index.md @aqualls
/doc/user/snippets.md @aqualls
-
-[Docs Ecosystem]
-/doc/administration/integration/ @kpaizee
-/doc/integration/ @kpaizee
-/doc/user/project/integrations/ @kpaizee
-/doc/user/project/integrations/prometheus_library/ @ngaskill
-
-[Docs Growth]
-/doc/administration/instance_review.md @kpaizee
-/doc/api/invitations.md @kpaizee
-/doc/api/experiments.md @kpaizee
-/doc/development/experiment_guide/ @kpaizee
-/doc/development/snowplow/ @fneill
-/doc/development/service_ping/ @fneill
-/doc/user/admin_area/license.md @kpaizee
+/doc/user/tasks.md @msedlakjakubowski
+/doc/user/todos.md @msedlakjakubowski
+/doc/user/usage_quotas.md @sselhorn
+/doc/user/workspace/index.md @fneill
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index bf439288be2..d720ec5ae45 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -1,10 +1,51 @@
+cloud-native-image-env:
+ extends:
+ - .default-retry
+ - .cng:rules
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine3.13
+ stage: post-test
+ before_script:
+ - source ./scripts/utils.sh
+ - install_gitlab_gem
+ script:
+ - 'ruby -r./scripts/trigger-build.rb -e "puts Trigger.variables_for_env_file(Trigger::CNG.new.variables)" > build.env'
+ - cat build.env
+ artifacts:
+ reports:
+ dotenv: build.env
+ paths:
+ - build.env
+ expire_in: 7 days
+ when: always
+
cloud-native-image:
extends: .cng:rules
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
- dependencies: []
stage: post-test
+ needs: ["cloud-native-image-env"]
+ inherit:
+ variables: false
variables:
- GIT_DEPTH: "1"
- script:
- - install_gitlab_gem
- - ./scripts/trigger-build cng
+ TOP_UPSTREAM_SOURCE_PROJECT: "${TOP_UPSTREAM_SOURCE_PROJECT}"
+ TOP_UPSTREAM_SOURCE_REF: "${TOP_UPSTREAM_SOURCE_REF}"
+ TOP_UPSTREAM_SOURCE_JOB: "${TOP_UPSTREAM_SOURCE_JOB}"
+ TOP_UPSTREAM_SOURCE_SHA: "${TOP_UPSTREAM_SOURCE_SHA}"
+ TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID: "${TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID}"
+ TOP_UPSTREAM_MERGE_REQUEST_IID: "${TOP_UPSTREAM_MERGE_REQUEST_IID}"
+ GITLAB_REF_SLUG: "${GITLAB_REF_SLUG}"
+ # CNG pipeline specific variables
+ GITLAB_VERSION: "${GITLAB_VERSION}"
+ GITLAB_TAG: "${GITLAB_TAG}"
+ GITLAB_ASSETS_TAG: "${GITLAB_ASSETS_TAG}"
+ FORCE_RAILS_IMAGE_BUILDS: "${FORCE_RAILS_IMAGE_BUILDS}"
+ CE_PIPELINE: "${CE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$CE_PIPELINE'` will evaluate to `false` when this variable is empty
+ EE_PIPELINE: "${EE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$EE_PIPELINE'` will evaluate to `false` when this variable is empty
+ GITLAB_SHELL_VERSION: "${GITLAB_SHELL_VERSION}"
+ GITLAB_ELASTICSEARCH_INDEXER_VERSION: "${GITLAB_ELASTICSEARCH_INDEXER_VERSION}"
+ GITLAB_KAS_VERSION: "${GITLAB_KAS_VERSION}"
+ GITLAB_WORKHORSE_VERSION: "${GITLAB_WORKHORSE_VERSION}"
+ GITLAB_PAGES_VERSION: "${GITLAB_PAGES_VERSION}"
+ GITALY_SERVER_VERSION: "${GITALY_SERVER_VERSION}"
+ trigger:
+ project: gitlab-org/build/CNG
+ branch: $TRIGGER_BRANCH
+ strategy: depend
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index c439e9a7c80..8b7691045cb 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -28,7 +28,7 @@
review-docs-deploy:
extends: .review-docs
script:
- - ./scripts/trigger-build docs deploy
+ - ./scripts/trigger-build.rb docs deploy
# Cleanup remote environment of gitlab-docs
review-docs-cleanup:
@@ -37,14 +37,14 @@ review-docs-cleanup:
name: review-docs/mr-${CI_MERGE_REQUEST_IID}
action: stop
script:
- - ./scripts/trigger-build docs cleanup
+ - ./scripts/trigger-build.rb docs cleanup
docs-lint markdown:
extends:
- .default-retry
- .docs:rules:docs-lint
# When updating the image version here, update it in /scripts/lint-doc.sh too.
- image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.14.0-markdownlint-0.30.0
+ image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.15.0-markdownlint-0.31.0
stage: lint
needs: []
script:
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 1dd5285e0ae..ef5af342544 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -11,7 +11,7 @@
- .default-retry
- .default-before_script
- .assets-compile-cache
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-git-2.33-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7-git-2.33-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
variables:
SETUP_DB: "false"
WEBPACK_VENDOR_DLL: "true"
@@ -306,11 +306,6 @@ qa-frontend-node:latest:
- .qa-frontend-node
- .frontend:rules:qa-frontend-node-latest
image: ${GITLAB_DEPENDENCY_PROXY}node:latest
- # This is a workaround for https://github.com/webpack/webpack/issues/14532 until
- # we can upgrade to Webpack 5 and switch to SHA256: https://gitlab.com/gitlab-org/gitlab/-/issues/350120
- script:
- - *yarn-install
- - run_timed_command "retry yarn run webpack-prod-node-latest"
webpack-dev-server:
extends:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 73e4712cc89..33b04faf731 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -18,7 +18,7 @@
- source scripts/prepare_build.sh
.ruby-gems-cache: &ruby-gems-cache
- key: "ruby-gems-v1"
+ key: "ruby-gems-${DEBIAN_VERSION}"
paths:
- vendor/ruby/
policy: pull
@@ -28,7 +28,7 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.gitaly-ruby-gems-cache: &gitaly-ruby-gems-cache
- key: "gitaly-ruby-gems-v1"
+ key: "gitaly-ruby-gems-${DEBIAN_VERSION}"
paths:
- vendor/gitaly-ruby/
policy: pull
@@ -41,7 +41,7 @@
key:
files:
- GITALY_SERVER_VERSION
- prefix: "gitaly-binaries"
+ prefix: "gitaly-binaries-${DEBIAN-VERSION}"
paths:
- tmp/tests/gitaly/_build/bin/
- tmp/tests/gitaly/_build/deps/git/install/
@@ -56,7 +56,7 @@
policy: pull
.go-pkg-cache: &go-pkg-cache
- key: "go-pkg-v1"
+ key: "go-pkg-${DEBIAN_VERSION}"
paths:
- .go/pkg/mod/
policy: pull
@@ -66,7 +66,7 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.node-modules-cache: &node-modules-cache
- key: "node-modules-${NODE_ENV}-v1"
+ key: "node-modules-${DEBIAN_VERSION}-${NODE_ENV}"
paths:
- node_modules/
- tmp/cache/webpack-dlls/
@@ -77,7 +77,7 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.assets-cache: &assets-cache
- key: "assets-${NODE_ENV}-v2"
+ key: "assets-${DEBIAN_VERSION}-${NODE_ENV}"
paths:
- assets-hash.txt
- public/assets/webpack/
@@ -91,7 +91,7 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.storybook-node-modules-cache: &storybook-node-modules-cache
- key: "storybook-node-modules-${NODE_ENV}-v1"
+ key: "storybook-node-modules-${DEBIAN_VERSION}-${NODE_ENV}"
paths:
- storybook/node_modules/
policy: pull
@@ -101,7 +101,7 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.rubocop-cache: &rubocop-cache
- key: "rubocop-v1"
+ key: "rubocop-${DEBIAN_VERSION}"
paths:
- tmp/rubocop_cache/
policy: pull
@@ -113,7 +113,7 @@
policy: push
.qa-ruby-gems-cache: &qa-ruby-gems-cache
- key: "qa-ruby-gems-v1-debian-buster"
+ key: "qa-ruby-gems-${DEBIAN_VERSION}"
paths:
- qa/vendor/ruby/
policy: pull
@@ -213,7 +213,7 @@
- *storybook-node-modules-cache-push
.use-pg11:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-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"]
@@ -222,7 +222,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-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"]
@@ -231,7 +231,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -240,7 +240,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-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"]
@@ -251,7 +251,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-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"]
@@ -262,7 +262,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13-ee:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-97-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
diff --git a/.gitlab/ci/memory.gitlab-ci.yml b/.gitlab/ci/memory.gitlab-ci.yml
index 9234b116ff8..c6572d9709c 100644
--- a/.gitlab/ci/memory.gitlab-ci.yml
+++ b/.gitlab/ci/memory.gitlab-ci.yml
@@ -11,34 +11,9 @@
metrics: "${METRICS_FILE}"
expire_in: 31d
-memory-static:
- extends: .only-code-memory-job-base
- stage: test
- needs: ["setup-test-env"]
- variables:
- SETUP_DB: "false"
- MEMORY_BUNDLE_MEM_FILE: "tmp/memory_bundle_mem.txt"
- MEMORY_BUNDLE_OBJECTS_FILE: "tmp/memory_bundle_objects.txt"
- script:
- # Uses two different reports from the 'derailed_benchmars' gem.
-
- # Loads each of gems in the Gemfile and checks how much memory they consume when they are required.
- # 'derailed_benchmarks' internally uses 'get_process_mem'
- - bundle exec derailed bundle:mem > "${MEMORY_BUNDLE_MEM_FILE}"
- - scripts/generate-gems-size-metrics-static "${MEMORY_BUNDLE_MEM_FILE}" >> "${METRICS_FILE}"
-
- # Outputs detailed information about objects created while gems are loaded.
- # 'derailed_benchmarks' internally uses 'memory_profiler'
- - bundle exec derailed bundle:objects > "${MEMORY_BUNDLE_OBJECTS_FILE}"
- - scripts/generate-gems-memory-metrics-static "${MEMORY_BUNDLE_OBJECTS_FILE}" >> "${METRICS_FILE}"
- artifacts:
- paths:
- - "${METRICS_FILE}"
- - "${MEMORY_BUNDLE_MEM_FILE}"
- - "${MEMORY_BUNDLE_OBJECTS_FILE}"
# Show memory usage caused by invoking require per gem.
-# Unlike `memory-static`, it hits the app with one request to ensure that any last minute require-s have been called.
+# Hits the app with one request to ensure that any last minute require-s have been called.
# The application is booted in `production` environment.
# All tests are run without a webserver (directly using Rack::Mock by default).
memory-on-boot:
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index b12f76f2823..77d12a3e848 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -73,7 +73,7 @@ update-qa-cache:
- echo $exit_code
- |
if [ $exit_code -eq 0 ]; then
- ./scripts/trigger-build omnibus
+ ./scripts/trigger-build.rb omnibus
elif [ $exit_code -eq 1 ]; then
exit 1
else
@@ -108,7 +108,7 @@ update-qa-cache:
if [[ $feature_flags ]]; then
export GITLAB_QA_OPTIONS="--set-feature-flags $feature_flags"
echo $GITLAB_QA_OPTIONS
- ./scripts/trigger-build omnibus
+ ./scripts/trigger-build.rb omnibus
else
echo "No changed feature flag found to test. The tests are skipped if the flag was removed."
fi
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 1d2f94b616d..8a4ea690c60 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -29,7 +29,9 @@
GITLAB_USE_MODEL_LOAD_BALANCING: "true"
.rspec-base:
- extends: .rails-job-base
+ extends:
+ - .rails-job-base
+ - .base-artifacts
stage: test
variables:
RUBY_GC_MALLOC_LIMIT: 67108864
@@ -40,6 +42,8 @@
script:
- !reference [.base-script, script]
- rspec_paralellized_job "--tag ~quarantine --tag ~geo --tag ~level:migration"
+
+.base-artifacts:
artifacts:
expire_in: 31d
when: always
@@ -48,16 +52,16 @@
- crystalball/
- deprecations/
- knapsack/
- - rspec_flaky/
- - rspec_profiling/
+ - rspec/
- tmp/capybara/
- - tmp/memory_test/
- log/*.log
reports:
- junit: junit_rspec.xml
+ junit: ${JUNIT_RESULT_FILE}
.rspec-base-migration:
- extends: .rails:rules:ee-and-foss-migration
+ extends:
+ - .base-artifacts
+ - .rails:rules:ee-and-foss-migration
script:
- !reference [.base-script, script]
- rspec_paralellized_job "--tag ~quarantine --tag ~geo --tag level:migration"
@@ -307,6 +311,8 @@ rspec system pg12:
- .rspec-base-pg12
- .rails:rules:ee-and-foss-system
- .rspec-system-parallel
+ variables:
+ DEBUG_GITLAB_TRANSACTION_STACK: "true"
rspec system pg12 minimal:
extends:
@@ -335,13 +341,9 @@ rspec fast_spec_helper:
- .rspec-base-pg12
- .rails:rules:ee-and-foss-fast_spec_helper
script:
- - bin/rspec spec/fast_spec_helper.rb
-
-rspec fast_spec_helper minimal:
- extends:
- - rspec fast_spec_helper
- - .minimal-rspec-tests
- - .rails:rules:ee-and-foss-fast_spec_helper:minimal
+ - fast_spec_helper_specs=$(git grep -l -E '^require.*fast_spec_helper')
+ # Load fast_spec_helper as well just in case there are no specs available.
+ - bin/rspec --dry-run spec/fast_spec_helper.rb $fast_spec_helper_specs
db:rollback:
extends: .db-job-base
@@ -427,6 +429,13 @@ db:check-migrations-decomposed:
- .decomposed-database
- .rails:rules:decomposed-databases
+db:migrate-non-superuser:
+ extends:
+ - .db-job-base
+ - .rails:rules:ee-and-foss-mr-with-migration
+ script:
+ - bundle exec rake gitlab:db:reset_as_non_superuser
+
db:gitlabcom-database-testing:
extends: .rails:rules:db:gitlabcom-database-testing
stage: test
@@ -436,7 +445,7 @@ db:gitlabcom-database-testing:
script:
- source scripts/utils.sh
- install_gitlab_gem
- - ./scripts/trigger-build gitlab-com-database-testing
+ - ./scripts/trigger-build.rb gitlab-com-database-testing
gitlab:setup:
extends: .db-job-base
@@ -554,7 +563,6 @@ rspec:coverage:
- rspec-ee integration pg12 geo minimal
- rspec-ee system pg12 geo minimal
# Memory jobs
- - memory-static
- memory-on-boot
# As-if-FOSS jobs
- rspec migration pg12-as-if-foss
@@ -571,7 +579,6 @@ rspec:coverage:
- rspec system pg12-as-if-foss decomposed
script:
- run_timed_command "bundle exec scripts/merge-simplecov"
- - run_timed_command "bundle exec scripts/gather-test-memory-data"
coverage: '/LOC \((\d+\.\d+%)\) covered.$/'
artifacts:
name: coverage
@@ -580,7 +587,6 @@ rspec:coverage:
- coverage/index.html
- coverage/assets/
- coverage/lcov/
- - tmp/memory_test/
reports:
cobertura: coverage/coverage.xml
@@ -621,54 +627,26 @@ rspec:feature-flags:
run_timed_command "bundle exec scripts/used-feature-flags";
fi
-rspec:skipped-flaky-tests-report:
+rspec:flaky-tests-report:
extends:
- .default-retry
- - .rails:rules:skipped-flaky-tests-report
- image: ruby:2.7-alpine
+ - .rails:rules:flaky-tests-report
stage: post-test
# We cannot use needs since it would mean needing 84 jobs (since most are parallelized)
# so we use `dependencies` here.
- dependencies:
- # FOSS/EE jobs
- - rspec migration pg12
- - rspec unit pg12
- - rspec integration pg12
- - rspec system pg12
- # FOSS/EE minimal jobs
- - rspec migration pg12 minimal
- - rspec unit pg12 minimal
- - rspec integration pg12 minimal
- - rspec system pg12 minimal
- # EE jobs
- - rspec-ee migration pg12
- - rspec-ee unit pg12
- - rspec-ee integration pg12
- - rspec-ee system pg12
- # EE minimal jobs
- - rspec-ee migration pg12 minimal
- - rspec-ee unit pg12 minimal
- - rspec-ee integration pg12 minimal
- - rspec-ee system pg12 minimal
- # Geo jobs
- - rspec-ee unit pg12 geo
- - rspec-ee integration pg12 geo
- - rspec-ee system pg12 geo
- # Geo minimal jobs
- - rspec-ee unit pg12 geo minimal
- - rspec-ee integration pg12 geo minimal
- - rspec-ee system pg12 geo minimal
+ dependencies: !reference ["rspec:coverage", "dependencies"]
variables:
- SKIPPED_FLAKY_TESTS_REPORT: skipped_flaky_tests_report.txt
+ SKIPPED_FLAKY_TESTS_REPORT_PATH: rspec/flaky/skipped_flaky_tests_report.txt
+ RETRIED_TESTS_REPORT_PATH: rspec/flaky/retried_tests_report.txt
before_script:
- - 'echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: $SKIP_FLAKY_TESTS_AUTOMATICALLY"'
- - mkdir -p rspec_flaky
+ - source scripts/utils.sh
+ - source scripts/rspec_helpers.sh
script:
- - find rspec_flaky/ -type f -name 'skipped_flaky_tests_*_report.txt' -exec cat {} + >> "${SKIPPED_FLAKY_TESTS_REPORT}"
+ - generate_flaky_tests_reports
artifacts:
expire_in: 31d
paths:
- - ${SKIPPED_FLAKY_TESTS_REPORT}
+ - rspec/
# EE/FOSS: default refs (MRs, default branch, schedules) jobs #
#######################################################
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 6d58bbf9682..b9d2e31191a 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -112,7 +112,6 @@ yarn-audit-dependency_scanning:
name: registry.gitlab.com/gitlab-com/gl-security/security-research/package-hunter-cli:1.1.0
entrypoint: [""]
variables:
- DEBUG: '*'
HTR_user: '$PACKAGE_HUNTER_USER'
HTR_pass: '$PACKAGE_HUNTER_PASS'
needs: []
@@ -121,7 +120,7 @@ yarn-audit-dependency_scanning:
- rm -r spec locale .git app/assets/images doc/
- cd .. && tar -I "gzip --best" -cf gitlab.tgz gitlab/
script:
- - node /usr/src/app/cli.js analyze --format gitlab --manager ${PACKAGE_MANAGER} gitlab.tgz | tee ${CI_PROJECT_DIR}/gl-dependency-scanning-report.json
+ - DEBUG=* node /usr/src/app/cli.js analyze --format gitlab --manager ${PACKAGE_MANAGER} gitlab.tgz | tee ${CI_PROJECT_DIR}/gl-dependency-scanning-report.json
artifacts:
paths:
- gl-dependency-scanning-report.json
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index 16ef3c82cda..d083f876b03 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -16,20 +16,58 @@ include:
- source ./scripts/review_apps/review-apps.sh
- install_api_client_dependencies_with_apk
-review-build-cng:
+review-build-cng-env:
extends:
- .default-retry
- .review:rules:review-build-cng
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine3.13
stage: prepare
- variables:
- CNG_PROJECT_ACCESS_TOKEN: "${CNG_MIRROR_PROJECT_ACCESS_TOKEN}" # "Multi-pipeline (from 'gitlab-org/gitlab' 'review-build-cng' job)" at https://gitlab.com/gitlab-org/build/CNG-mirror/-/settings/access_tokens
- CNG_PROJECT_PATH: "gitlab-org/build/CNG-mirror"
+ needs: []
before_script:
- source ./scripts/utils.sh
- install_gitlab_gem
script:
- - ./scripts/trigger-build cng
+ - 'ruby -r./scripts/trigger-build.rb -e "puts Trigger.variables_for_env_file(Trigger::CNG.new.variables)" > build.env'
+ - cat build.env
+ artifacts:
+ reports:
+ dotenv: build.env
+ paths:
+ - build.env
+ expire_in: 7 days
+ when: always
+
+review-build-cng:
+ extends: .review:rules:review-build-cng
+ stage: prepare
+ needs: ["review-build-cng-env"]
+ inherit:
+ variables: false
+ variables:
+ TOP_UPSTREAM_SOURCE_PROJECT: "${TOP_UPSTREAM_SOURCE_PROJECT}"
+ TOP_UPSTREAM_SOURCE_REF: "${TOP_UPSTREAM_SOURCE_REF}"
+ TOP_UPSTREAM_SOURCE_JOB: "${TOP_UPSTREAM_SOURCE_JOB}"
+ TOP_UPSTREAM_SOURCE_SHA: "${TOP_UPSTREAM_SOURCE_SHA}"
+ TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID: "${TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID}"
+ TOP_UPSTREAM_MERGE_REQUEST_IID: "${TOP_UPSTREAM_MERGE_REQUEST_IID}"
+ GITLAB_REF_SLUG: "${GITLAB_REF_SLUG}"
+ # CNG pipeline specific variables
+ GITLAB_VERSION: "${GITLAB_VERSION}"
+ GITLAB_TAG: "${GITLAB_TAG}"
+ GITLAB_ASSETS_TAG: "${GITLAB_ASSETS_TAG}"
+ FORCE_RAILS_IMAGE_BUILDS: "${FORCE_RAILS_IMAGE_BUILDS}"
+ CE_PIPELINE: "${CE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$CE_PIPELINE'` will evaluate to `false` when this variable is empty
+ EE_PIPELINE: "${EE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$EE_PIPELINE'` will evaluate to `false` when this variable is empty
+ GITLAB_SHELL_VERSION: "${GITLAB_SHELL_VERSION}"
+ GITLAB_ELASTICSEARCH_INDEXER_VERSION: "${GITLAB_ELASTICSEARCH_INDEXER_VERSION}"
+ GITLAB_KAS_VERSION: "${GITLAB_KAS_VERSION}"
+ GITLAB_WORKHORSE_VERSION: "${GITLAB_WORKHORSE_VERSION}"
+ GITLAB_PAGES_VERSION: "${GITLAB_PAGES_VERSION}"
+ GITALY_SERVER_VERSION: "${GITALY_SERVER_VERSION}"
+ trigger:
+ project: gitlab-org/build/CNG-mirror
+ branch: $TRIGGER_BRANCH
+ strategy: depend
.review-workflow-base:
extends:
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index 4ef6efa2604..eaf6429ad58 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -27,11 +27,13 @@
- echo "${CI_ENVIRONMENT_URL}"
- cd qa
script:
- - |
- bin/test "${QA_SCENARIO}" "${CI_ENVIRONMENT_URL}" \
- -- \
- --color --format documentation \
- --format RspecJunitFormatter --out tmp/rspec.xml
+ - qa_run_status=0
+ - bin/test "${QA_SCENARIO}" "${CI_ENVIRONMENT_URL}" -- --color --format documentation --format RspecJunitFormatter --out tmp/rspec.xml || qa_run_status=$?
+ - if [ ${qa_run_status} -ne 0 ]; then
+ release_sha=$(echo "${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-${CI_COMMIT_SHA}}" | cut -c1-11);
+ echo "Errors can be found at https://sentry.gitlab.net/gitlab/gitlab-review-apps/releases/${release_sha}/all-events/.";
+ fi
+ - exit ${qa_run_status}
artifacts:
paths:
- qa/tmp
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 008b62f6a0f..a4bb99c49ad 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -73,6 +73,9 @@
.if-security-merge-request: &if-security-merge-request
if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_MERGE_REQUEST_IID'
+.if-fork-merge-request: &if-fork-merge-request
+ if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/ && $CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-all-rspec/'
+
.if-default-branch-schedule-2-hourly: &if-default-branch-schedule-2-hourly
if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $FREQUENCY == "2-hourly"'
@@ -121,15 +124,13 @@
.if-security-pipeline-merge-result: &if-security-pipeline-merge-result
if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH && $CI_PROJECT_NAMESPACE == "gitlab-org/security" && $GITLAB_USER_LOGIN == "gitlab-release-tools-bot"'
-.if-skip-flaky-tests-automatically: &if-skip-flaky-tests-automatically
- if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true"'
-
####################
# Changes patterns #
####################
.ci-patterns: &ci-patterns
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
+ - "scripts/rspec_helpers.sh"
.ci-build-images-patterns: &ci-build-images-patterns
- ".gitlab-ci.yml"
@@ -143,7 +144,7 @@
- ".gitlab/ci/review-apps/**/*"
- "scripts/review_apps/base-config.yaml"
- "scripts/review_apps/review-apps.sh"
- - "scripts/trigger-build"
+ - "scripts/trigger-build.rb"
- "{,ee/,jh/}{bin,config}/**/*.rb"
.ci-qa-patterns: &ci-qa-patterns
@@ -232,6 +233,9 @@
.controllers-patterns: &controllers-patterns
- "{,ee/,jh/}{app/controllers}/**/*"
+.models-patterns: &models-patterns
+ - "{,ee/,jh/}{app/models}/**/*"
+
.startup-css-patterns: &startup-css-patterns
- "{,ee/,jh/}app/assets/stylesheets/startup/**/*"
@@ -248,6 +252,7 @@
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
- "*_VERSION"
+ - "scripts/rspec_helpers.sh"
# DB patterns + .ci-patterns
.db-patterns: &db-patterns
@@ -456,6 +461,106 @@
.feature-flag-development-config-patterns: &feature-flag-development-config-patterns
- "{,ee/}config/feature_flags/{development,ops}/*.yml"
+##################
+# Conditions set #
+##################
+.strict-ee-only-rules:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-jh
+ when: never
+
+.as-if-jh-default-exclusion-rules:
+ rules:
+ - <<: *if-security-merge-request
+ when: never
+ - <<: *if-merge-request-targeting-stable-branch
+ when: never
+ - <<: *if-stable-branch-refs
+ when: never
+ - <<: *if-merge-request-labels-as-if-jh
+ allow_failure: true
+
+.rails:rules:minimal-default-rules:
+ rules:
+ - <<: *if-merge-request-approved
+ when: never
+ - <<: *if-automated-merge-request
+ when: never
+ - <<: *if-security-merge-request
+ when: never
+
+
+.rails:rules:ee-and-foss-default-rules:
+ rules:
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *core-backend-patterns
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ - <<: *if-automated-merge-request
+ changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *backend-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
+
+.rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules:
+ rules:
+ - <<: *if-merge-request
+ changes: *core-backend-patterns
+ when: never
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ when: never
+
+.rails:rules:unit-integration:minimal-default-rules:
+ rules:
+ - <<: *if-merge-request-labels-run-all-rspec
+ when: never
+ - !reference [".rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules", rules]
+
+.rails:rules:system-default-rules:
+ rules:
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *core-backend-patterns
+ - <<: *if-merge-request
+ changes: *workhorse-patterns
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ - <<: *if-automated-merge-request
+ changes: *code-backstage-patterns
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
+
+.rails:rules:system:minimal-default-rules:
+ rules:
+ - <<: *if-merge-request-labels-run-all-rspec
+ when: never
+ - <<: *if-merge-request
+ changes: *core-backend-patterns
+ when: never
+ - <<: *if-merge-request
+ changes: *workhorse-patterns
+ when: never
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ when: never
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
+
+.rails:rules:previous-failed-tests-default-rules:
+ rules:
+ - <<: *if-security-merge-request
+ when: never
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
+
################
# Shared rules #
################
@@ -519,7 +624,6 @@
rules:
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
.dev-fixtures:rules:ee-only:
rules:
@@ -527,7 +631,6 @@
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
##############
# Docs rules #
@@ -543,7 +646,6 @@
rules:
- <<: *if-default-refs
changes: *docs-patterns
- when: on_success
.docs:rules:deprecations-and-removals:
rules:
@@ -553,14 +655,12 @@
##################
# GraphQL rules #
##################
-
.graphql:rules:graphql-verify:
rules:
- <<: *if-not-ee
when: never
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- when: on_success
##################
# Frontend rules #
@@ -572,11 +672,13 @@
- <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
- changes: *code-qa-patterns
+ - changes: *workhorse-patterns
.frontend:rules:compile-test-assets:
rules:
- - changes: *code-backstage-qa-patterns
- <<: *if-merge-request-labels-run-all-rspec
+ - changes: *code-backstage-qa-patterns
+ - changes: *workhorse-patterns
.frontend:rules:compile-test-assets-as-if-foss:
rules:
@@ -586,23 +688,19 @@
- <<: *if-merge-request-labels-run-all-rspec
- changes: *code-backstage-qa-patterns
- changes: *startup-css-patterns
+ - changes: *workhorse-patterns
.frontend:rules:compile-test-assets-as-if-jh:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-targeting-stable-branch
- when: never
- - <<: *if-stable-branch-refs
- when: never
- - <<: *if-merge-request-labels-as-if-jh
+ - !reference [".strict-ee-only-rules", rules]
+ - !reference [".as-if-jh-default-exclusion-rules", rules]
- <<: *if-merge-request-labels-run-all-rspec
+ allow_failure: true
- changes: *code-backstage-qa-patterns
+ allow_failure: true
- changes: *startup-css-patterns
+ allow_failure: true
+ - changes: *workhorse-patterns
.frontend:rules:default-frontend-jobs:
rules:
@@ -611,10 +709,7 @@
.frontend:rules:default-frontend-jobs-as-if-foss:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
+ - !reference [".strict-ee-only-rules", rules]
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-labels-as-if-foss
@@ -626,25 +721,21 @@
.frontend:rules:default-frontend-jobs-as-if-jh:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-targeting-stable-branch
- when: never
- - <<: *if-stable-branch-refs
- when: never
- - <<: *if-merge-request-labels-as-if-jh
+ - !reference [".strict-ee-only-rules", rules]
+ - !reference [".as-if-jh-default-exclusion-rules", rules]
- <<: *if-merge-request-labels-run-all-rspec
+ allow_failure: true
- <<: *if-merge-request
changes: *startup-css-patterns
+ allow_failure: true
- <<: *if-merge-request
changes: *ci-patterns
+ allow_failure: true
.frontend:rules:jest:
rules:
+ - <<: *if-fork-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-jest
- <<: *if-default-refs
changes: *core-frontend-patterns
@@ -661,16 +752,12 @@
.frontend:rules:jest:minimal:
rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
+ - <<: *if-fork-merge-request
+ changes: *code-backstage-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
- <<: *if-merge-request-labels-run-all-jest
when: never
- - <<: *if-default-refs
- changes: *core-frontend-patterns
+ - changes: *core-frontend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
@@ -680,10 +767,7 @@
.frontend:rules:eslint-as-if-foss:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
+ - !reference [".strict-ee-only-rules", rules]
# We already have `static-analysis as-if-foss` which already runs `lint:eslint:all` if the `pipeline:run-as-if-foss` label is set.
- <<: *if-merge-request-labels-as-if-foss
when: never
@@ -731,7 +815,6 @@
rules:
- <<: *if-default-refs
changes: *code-patterns
- when: on_success
###############
# Pages rules #
@@ -747,14 +830,10 @@
rules:
- <<: *if-default-refs
changes: *code-qa-patterns
- when: on_success
.qa:rules:as-if-foss:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
+ - !reference [".strict-ee-only-rules", rules]
- <<: *if-security-merge-request
changes: *code-qa-patterns
- <<: *if-merge-request-labels-as-if-foss
@@ -809,11 +888,15 @@
.rails:rules:ee-and-foss-migration:
rules:
+ - <<: *if-fork-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *core-backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
changes: *db-patterns
- <<: *if-automated-merge-request
@@ -826,20 +909,12 @@
.rails:rules:ee-and-foss-migration:minimal:
rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - <<: *if-fork-merge-request
+ changes: *db-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
changes: *db-patterns
when: never
@@ -860,105 +935,49 @@
.rails:rules:ee-and-foss-unit:
rules:
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
.rails:rules:ee-and-foss-unit:minimal:
rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - <<: *if-fork-merge-request
+ changes: *backend-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request
changes: *backend-patterns
.rails:rules:ee-and-foss-integration:
rules:
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
.rails:rules:ee-and-foss-integration:minimal:
rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - <<: *if-fork-merge-request
+ changes: *backend-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request
changes: *backend-patterns
.rails:rules:ee-and-foss-system:
rules:
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *code-backstage-patterns
- - <<: *if-security-merge-request
- changes: *code-backstage-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:system-default-rules", rules]
- changes: *code-backstage-patterns
.rails:rules:ee-and-foss-system:minimal:
rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
- - <<: *if-merge-request
+ - <<: *if-fork-merge-request
changes: *code-backstage-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:system:minimal-default-rules", rules]
.rails:rules:ee-and-foss-fast_spec_helper:
rules:
@@ -967,33 +986,8 @@
changes: *core-backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: ["config/**/*"]
- - <<: *if-security-merge-request
- changes: ["config/**/*"]
- - <<: *if-merge-request-not-approved
- when: never
- changes: ["config/**/*"]
-.rails:rules:ee-and-foss-fast_spec_helper:minimal:
- rules:
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
- - <<: *if-merge-request
- changes: ["config/**/*"]
-
.rails:rules:code-backstage-qa:
rules:
- changes: *code-backstage-qa-patterns
@@ -1008,6 +1002,8 @@
changes: *core-backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
changes: *db-patterns
- <<: *if-automated-merge-request
@@ -1022,20 +1018,10 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
changes: *db-patterns
when: never
@@ -1044,37 +1030,19 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
.rails:rules:ee-only-unit:minimal:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - <<: *if-fork-merge-request
+ changes: *backend-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request
changes: *backend-patterns
@@ -1082,37 +1050,19 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
.rails:rules:ee-only-integration:minimal:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - <<: *if-fork-merge-request
+ changes: *backend-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request
changes: *backend-patterns
@@ -1120,39 +1070,19 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *code-backstage-patterns
- - <<: *if-security-merge-request
- changes: *code-backstage-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:system-default-rules", rules]
- changes: *code-backstage-patterns
.rails:rules:ee-only-system:minimal:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
- - <<: *if-merge-request
+ - <<: *if-fork-merge-request
changes: *code-backstage-patterns
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:system:minimal-default-rules", rules]
.rails:rules:as-if-foss-migration:
rules:
@@ -1163,8 +1093,8 @@
changes: *core-backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
- - <<: *if-security-merge-request
- changes: *db-patterns
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request-labels-as-if-foss
changes: *db-patterns
- <<: *if-automated-merge-request
@@ -1178,18 +1108,10 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
- when: never
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules", rules]
+ # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request-labels-as-if-foss
changes: *db-patterns
when: never
@@ -1198,17 +1120,9 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1216,18 +1130,10 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1235,17 +1141,9 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *backend-patterns
- - <<: *if-security-merge-request
- changes: *backend-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:ee-and-foss-default-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1253,18 +1151,10 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request
- changes: *core-backend-patterns
- when: never
- - <<: *if-merge-request
- changes: *ci-patterns
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:minimal-default-rules", rules]
+ - !reference [".rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1272,17 +1162,9 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- - <<: *if-automated-merge-request
- changes: *code-backstage-patterns
- - <<: *if-security-merge-request
- changes: *code-backstage-patterns
- - <<: *if-merge-request-not-approved
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:system-default-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
@@ -1290,16 +1172,16 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-merge-request-approved
- when: never
- - <<: *if-automated-merge-request
- when: never
- - <<: *if-security-merge-request
+ - <<: *if-fork-merge-request
when: never
+ - !reference [".rails:rules:minimal-default-rules", rules]
- <<: *if-merge-request
changes: *core-backend-patterns
when: never
- <<: *if-merge-request
+ changes: *workhorse-patterns
+ when: never
+ - <<: *if-merge-request
changes: *ci-patterns
when: never
- <<: *if-merge-request-labels-as-if-foss
@@ -1307,18 +1189,8 @@
.rails:rules:as-if-jh-rspec:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-targeting-stable-branch
- when: never
- - <<: *if-stable-branch-refs
- when: never
- - <<: *if-merge-request-labels-as-if-jh
- allow_failure: true
+ - !reference [".strict-ee-only-rules", rules]
+ - !reference [".as-if-jh-default-exclusion-rules", rules]
- <<: *if-merge-request
changes: *ci-patterns
allow_failure: true
@@ -1340,24 +1212,17 @@
.rails:rules:detect-tests:
rules:
- - changes: *code-backstage-qa-patterns
- <<: *if-merge-request-labels-run-all-rspec
+ - changes: *code-backstage-qa-patterns
+ - changes: *workhorse-patterns
.rails:rules:detect-previous-failed-tests:
rules:
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *code-backstage-patterns
+ - !reference [".rails:rules:previous-failed-tests-default-rules", rules]
.rails:rules:rerun-previous-failed-tests:
rules:
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *code-backstage-patterns
+ - !reference [".rails:rules:previous-failed-tests-default-rules", rules]
.rails:rules:rspec-foss-impact:
rules:
@@ -1418,19 +1283,21 @@
- <<: *if-merge-request
changes: *backend-patterns
-.rails:rules:default-branch-schedule-nightly--code-backstage:
+.rails:rules:default-branch-schedule-nightly--code-backstage-default-rules:
rules:
- <<: *if-default-branch-schedule-nightly
- <<: *if-merge-request
changes: [".gitlab/ci/rails.gitlab-ci.yml"]
+.rails:rules:default-branch-schedule-nightly--code-backstage:
+ rules:
+ - !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-default-rules", rules]
+
.rails:rules:default-branch-schedule-nightly--code-backstage-ee-only:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-default-branch-schedule-nightly
- - <<: *if-merge-request
- changes: [".gitlab/ci/rails.gitlab-ci.yml"]
+ - !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-default-rules", rules]
.rails:rules:rspec-feature-flags:
rules:
@@ -1438,13 +1305,16 @@
when: never
- changes: *code-backstage-patterns
-.rails:rules:skipped-flaky-tests-report:
+.rails:rules:flaky-tests-report:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-skip-flaky-tests-automatically
+ - if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true" || $RETRY_FAILED_TESTS_IN_NEW_PROCESS == "true"'
changes: *code-backstage-patterns
- - changes: *ci-patterns
+ when: always
+ - if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true" || $RETRY_FAILED_TESTS_IN_NEW_PROCESS == "true"'
+ changes: *ci-patterns
+ when: always
#########################
# Static analysis rules #
@@ -1619,6 +1489,8 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *controllers-patterns
- <<: *if-dot-com-gitlab-org-merge-request
+ changes: *models-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-patterns
@@ -1734,7 +1606,6 @@
when: never
- <<: *if-default-branch-or-tag
changes: *code-backstage-qa-patterns
- when: on_success
.setup:rules:dont-interrupt-me:
rules:
@@ -1749,7 +1620,6 @@
rules:
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
.setup:rules:no-ee-check:
rules:
@@ -1757,7 +1627,6 @@
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
.setup:rules:no-jh-check:
rules:
@@ -1765,7 +1634,6 @@
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
.setup:rules:verify-tests-yml:
rules:
@@ -1773,7 +1641,6 @@
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
- when: on_success
.setup:rules:generate-frontend-fixtures-mapping:
rules:
@@ -1787,20 +1654,16 @@
.setup:rules:add-jh-folder:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-jh
- when: never
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-targeting-stable-branch
- when: never
- - <<: *if-stable-branch-refs
- when: never
- - <<: *if-merge-request-labels-as-if-jh
+ - !reference [".strict-ee-only-rules", rules]
+ - !reference [".as-if-jh-default-exclusion-rules", rules]
- <<: *if-merge-request-labels-run-all-rspec
+ allow_failure: true
- changes: *code-backstage-qa-patterns
+ allow_failure: true
- changes: *startup-css-patterns
+ allow_failure: true
+ - changes: *workhorse-patterns
+ allow_failure: true
#######################
# Test metadata rules #
@@ -1808,7 +1671,7 @@
.test-metadata:rules:retrieve-tests-metadata:
rules:
- changes: *code-backstage-patterns
- when: on_success
+ - changes: *workhorse-patterns
- <<: *if-merge-request-labels-run-all-rspec
.test-metadata:rules:update-tests-metadata:
@@ -1825,8 +1688,7 @@
###################
.workhorse:rules:workhorse:
rules:
- - <<: *if-default-refs
- changes: *workhorse-patterns
+ - changes: *workhorse-patterns
###################
# yaml-lint rules #
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 13108ba289a..1aeccfcb212 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -159,7 +159,7 @@ add-jh-folder:
script:
- JH_BRANCH=$(./scripts/setup/find-jh-branch.rb)
- 'echo "JH_BRANCH: ${JH_BRANCH}"'
- - curl --location -o "jh-folder.tar.gz" "https://gitlab.com/gitlab-jh/gitlab/-/archive/${JH_BRANCH}/gitlab-${JH_BRANCH}.tar.gz?path=jh"
+ - curl --location -o "jh-folder.tar.gz" "https://gitlab.com/gitlab-org/gitlab-jh/gitlab/-/archive/${JH_BRANCH}/gitlab-${JH_BRANCH}.tar.gz?path=jh"
- tar -xf "jh-folder.tar.gz"
- mv "gitlab-${JH_BRANCH}-jh/jh/" ./
- cp Gemfile.lock jh/
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index d0d45cb9294..20cbd759ac6 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -6,9 +6,9 @@
expire_in: 31d
paths:
- knapsack/
- - rspec_flaky/
- - rspec_profiling/
+ - rspec/
- crystalball/
+ when: always
retrieve-tests-metadata:
extends:
@@ -44,6 +44,6 @@ update-tests-metadata:
script:
- run_timed_command "retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document"
- source ./scripts/rspec_helpers.sh
- - test -f rspec_flaky/report-suite.json || echo -e "\e[31m" 'Consider add ~"pipeline:run-all-rspec" to run full rspec jobs' "\e[0m"
+ - test -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo -e "\e[31m" 'Consider add ~"pipeline:run-all-rspec" to run full rspec jobs' "\e[0m"
- update_tests_metadata
- update_tests_mapping
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index aab077e575b..01e059b8a60 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -22,8 +22,8 @@ workhorse:verify:
workhorse:test using go 1.16:
extends: .workhorse:test
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-golang-1.16-git-2.31
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7-golang-1.16-git-2.31
workhorse:test using go 1.17:
extends: .workhorse:test
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-golang-1.17-git-2.31
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-2.7-golang-1.17-git-2.31
diff --git a/.gitlab/issue_templates/Actionable Insight.md b/.gitlab/issue_templates/Actionable Insight - Exploration needed.md
index f4724d66a1b..76316fc626d 100644
--- a/.gitlab/issue_templates/Actionable Insight.md
+++ b/.gitlab/issue_templates/Actionable Insight - Exploration needed.md
@@ -1,13 +1,15 @@
-<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights -->
+<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights
+
+This issue template is for an actionable insight that requires further exploration.-->
### Insight
-<!-- Describe the insight itself: often the problem, finding, or observation. -->
+<!-- Describe the insight itself: often the problem, finding, or observation.-->
### Supporting evidence
<!-- Describe why the problem is happening, or more details behind the finding or observation. Try to include quotes or specific data collected. Feel free to link the Actionable insight from Dovetail here if applicable instead of retyping details. -->
### Action
-<!--Describe the next step or action that needs to take place as a result of the research. The action should be clearly defined, achievable, and directly tied back to the insight. Make sure to use directive terminology, such as: conduct, explore, redesign, etc. -->
+<!--Since this is an actionable insight that requires further exploration, ensure the action is algned to that. Describe the next step or action that needs to take place as a result of the research. The action should be clearly defined, achievable, and directly tied back to the insight. Make sure to use directive terminology, such as: conduct, explore, redesign, etc. -->
### Resources
<!--Add resources as links below or as related issues. -->
@@ -26,5 +28,5 @@
/confidential
-/label ~"Actionable Insight"
+/label ~"Actionable Insight::Exploration needed"
diff --git a/.gitlab/issue_templates/Actionable Insight - Product change.md b/.gitlab/issue_templates/Actionable Insight - Product change.md
new file mode 100644
index 00000000000..6c030220636
--- /dev/null
+++ b/.gitlab/issue_templates/Actionable Insight - Product change.md
@@ -0,0 +1,33 @@
+<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights
+
+This issue template is for an actionable insight that requires a change in the product.-->
+
+### Insight
+<!-- Describe the insight itself: often the problem, finding, or observation.-->
+
+### Supporting evidence
+<!-- Describe why the problem is happening, or more details behind the finding or observation. Try to include quotes or specific data collected. Feel free to link the Actionable insight from Dovetail here if applicable instead of retyping details. -->
+
+### Action
+<!--Since this is an actionable insight that requires a change in the product, ensure the action is algned to that. Describe the next step or action that needs to take place as a result of the research. The action should be clearly defined, achievable, and directly tied back to the insight. Make sure to use directive terminology, such as: change, update, add/remove, etc. -->
+
+### Resources
+ <!--Add resources as links below or as related issues. -->
+
+- :dove: [Dovetail project](Paste URL for Dovetail project here)
+- :mag: [Research issue](Paste URL for research issue here)
+- :footprints: [Follow-up issue or epic](Paste URL for follow-up issue or epic here)
+
+### Tasks
+ <!--Fill out these tasks in order to consider an Actionable Insight complete. Actionable Insights are created as confidential by default, but can be made non-confidential if the insight does not include information about competitors from a Competitor Evaluation or any other confidential information. -->
+- [ ] Assign this issue to the appropriate Product Manager, Product Designer, or UX Researcher.
+- [ ] Add the appropriate `Group` (such as `~"group::source code"`) label to the issue. This helps identify and track actionable insights at the group level.
+- [ ] Link this issue back to the original research issue in the GitLab UX Research project and the Dovetail project.
+- [ ] Adjust confidentiality of this issue if applicable
+
+
+
+/confidential
+/label ~"Actionable Insight::Product change"
+/label ~"SUS"
+
diff --git a/.gitlab/issue_templates/Deprecations.md b/.gitlab/issue_templates/Deprecations.md
index 85db4314233..cea010153bb 100644
--- a/.gitlab/issue_templates/Deprecations.md
+++ b/.gitlab/issue_templates/Deprecations.md
@@ -1,3 +1,5 @@
+For guidance on the overall deprecations, removals and breaking changes workflow, please visit https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features
+
<!-- Use this template as a starting point for deprecations. -->
### Deprecation Summary
@@ -37,23 +39,27 @@ Which tier is this feature available in?
- [ ] @mention your stage's stable counterparts on this issue. For example, Customer Support, Customer Success (Technical Account Manager), Product Marketing Manager.
- To see who the stable counterparts are for a product team visit [product categories](https://about.gitlab.com/handbook/product/categories/)
- If there is no stable counterpart listed for Sales/CS please mention `@timtams`
- - If there is no stable counterpart listed for Support please @mention `@gitlab-com/support/managers`
- - If there is no stable counterpart listed for Marketing please mention `@williamchia`
+ - If there is no stable counterpart listed for Support please mention `@gitlab-com/support/managers`
+ - If there is no stable counterpart listed for Marketing please mention `@cfoster3`
-- [ ] @mention your GPM so that they are aware of planned deprecations. The goal is to have reviews happen at least two releases before the final removal of the feature or introduction of a breaking change.
+- [ ] `@mention` your GPM so that they are aware of planned deprecations. The goal is to have reviews happen at least two releases before the final removal of the feature or introduction of a breaking change.
### Deprecation Milestone
<!-- In which milestone will this deprecation be announced ? -->
-### Planned Removal Milestone
+### Planned Removal Milestone
<!-- In which milestone will the feature or functionality be removed and announced? -->
### Links
<!--
-Add links to any relevant documentation or code that will provide additional details or clarity regarding the planned change. Also, include a link to the removal issue if relevant.
+Add links to any relevant documentation or code that will provide additional details or clarity regarding the planned change.
+
+This issue is the main SSOT for the deprecations and removals process. Be sure to link all
+issues and MRs related to this deprecation/removal to this issue. This can include removal
+issues that were created ahead of time, and the MRs doing the actual deprecation/removal work.
-->
<!-- Label reminders - you should have one of each of the following labels.
@@ -71,4 +77,4 @@ Use the following resources to find the appropriate labels:
<!-- Identifies that this Issue is related to deprecating a feature -->
/label ~"type::deprecation"
-<!-- Add the ~"breaking change" label to this issue if necessary --> \ No newline at end of file
+<!-- Add the ~"breaking change" label to this issue if necessary -->
diff --git a/.gitlab/issue_templates/Feature Flag Cleanup.md b/.gitlab/issue_templates/Feature Flag Cleanup.md
new file mode 100644
index 00000000000..eedb35a4b5f
--- /dev/null
+++ b/.gitlab/issue_templates/Feature Flag Cleanup.md
@@ -0,0 +1,52 @@
+<!-- Title suggestion: [Feature flag] Cleanup <feature-flag-name> -->
+
+## Summary
+
+This issue is to cleanup the `<feature-flag-name>` feature flag, after the feature flag has been enabled by default for an appropriate amount of time in production.
+
+<!-- Short description of what the feature is about and link to relevant other issues. -->
+
+## Owners
+
+- Team: NAME_OF_TEAM
+- Most appropriate slack channel to reach out to: `#g_TEAM_NAME`
+- Best individual to reach out to: NAME
+- PM: NAME
+
+## Stakeholders
+
+<!--
+Are there any other stages or teams involved that need to be kept in the loop?
+
+- Name of a PM
+- The Support Team
+- The Delivery Team
+-->
+
+## Expectations
+
+### What might happen if this goes wrong?
+
+<!-- Any MRs that need to be rolled back? Communication that needs to happen? What are some things you can think of that could go wrong - data loss or broken pages? -->
+
+### Cleaning up the feature flag
+
+<!-- The checklist here is to help stakeholders keep track of the feature flag status -->
+- [ ] Create a merge request to remove `<feature-flag-name>` feature flag. Ask for review and merge it.
+ - [ ] Remove all references to the feature flag from the codebase.
+ - [ ] Remove the YAML definitions for the feature from the repository.
+ - [ ] Create [a changelog entry](https://docs.gitlab.com/ee/development/feature_flags/#changelog).
+- [ ] Ensure that the cleanup MR has been deployed to both production and canary.
+ If the merge request was deployed before [the code cutoff](https://about.gitlab.com/handbook/engineering/releases/#self-managed-releases-1),
+ the feature can be officially announced in a release blog post.
+ - [ ] `/chatops run auto_deploy status <merge-commit-of-cleanup-mr>`
+- [ ] Close [the feature issue](ISSUE LINK) to indicate the feature will be released in the current milestone.
+- [ ] Clean up the feature flag from all environments by running these chatops command in `#production` channel:
+ - [ ] `/chatops run feature delete <feature-flag-name> --dev`
+ - [ ] `/chatops run feature delete <feature-flag-name> --staging`
+ - [ ] `/chatops run feature delete <feature-flag-name>`
+- [ ] Close this rollout issue.
+
+
+/label ~"feature flag" ~"type::feature" ~"feature::addition"
+/assign DRI
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index 86f356daf90..590e627df75 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -121,7 +121,7 @@ To do so, follow these steps:
- [ ] `/chatops run auto_deploy status <merge-commit-of-default-enabling-mr>`
- [ ] 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).
+- [ ] (Optional) You can [create a separate issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20Flag%20Cleanup) 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.
@@ -141,6 +141,8 @@ the [clean up](https://docs.gitlab.com/ee/development/feature_flags/controls.htm
should be done as soon as possible to permanently enable the feature and reduce complexity in the
codebase.
+You can either [create a follow-up issue for Feature Flag Cleanup](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20Flag%20Cleanup) or use the checklist below in this same issue.
+
<!-- The checklist here is to help stakeholders keep track of the feature flag status -->
- [ ] Create a merge request to remove `<feature-flag-name>` feature flag. Ask for review and merge it.
- [ ] Remove all references to the feature flag from the codebase.
diff --git a/.gitlab/issue_templates/Feature Proposal - lean.md b/.gitlab/issue_templates/Feature Proposal - lean.md
index c826abe7e10..53ad17bbf39 100644
--- a/.gitlab/issue_templates/Feature Proposal - lean.md
+++ b/.gitlab/issue_templates/Feature Proposal - lean.md
@@ -38,7 +38,7 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
-->
-### Metrics
+### Feature Usage Metrics
<!-- How are you going to track usage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
diff --git a/.gitlab/issue_templates/Feature proposal - detailed.md b/.gitlab/issue_templates/Feature proposal - detailed.md
index f7d0567f806..78faf146fbe 100644
--- a/.gitlab/issue_templates/Feature proposal - detailed.md
+++ b/.gitlab/issue_templates/Feature proposal - detailed.md
@@ -31,14 +31,6 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
-->
-### Metrics
-
-<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
-
-Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
-
--->
-
### User experience goal
<!-- What is the single user experience workflow this problem addresses?
@@ -63,7 +55,12 @@ Consider adding checkboxes and expectations of users with certain levels of memb
* [ ] Add expected impact to Reporter (20) members
* [ ] Add expected impact to Developer (30) members
* [ ] Add expected impact to Maintainer (40) members
-* [ ] Add expected impact to Owner (50) members -->
+* [ ] Add expected impact to Owner (50) members
+
+Please consider performing a threat model for the code changes that are introduced as part of this feature. To get started, refer to our Threat Modeling handbook page https://about.gitlab.com/handbook/security/threat_modeling/#threat-modeling.
+
+Don't hesitate to reach out to the Application Security Team (`@gitlab-com/gl-security/appsec`) to discuss any security concerns.
+-->
### Documentation
@@ -94,6 +91,14 @@ See the test engineering planning process and reach out to your counterpart Soft
* Ultimate/Gold
-->
+### Feature Usage Metrics
+
+<!-- How are you going to track usage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
+
+Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
+
+-->
+
### What does success look like, and how can we measure that?
<!--
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 256bddcbdab..6d37fc678af 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
@@ -130,25 +130,23 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
FAILED_VERIFICATION_INDEX_NAME = "index_cool_widget_states_failed_verification"
NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widget_states_needs_verification"
- disable_ddl_transaction!
+ enable_lock_retries!
def up
- with_lock_retries do
- create_table :cool_widget_states, id: false do |t|
- t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure, limit: 255
-
- t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
+ create_table :cool_widget_states, id: false do |t|
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure, limit: 255
+
+ t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
end
end
@@ -489,7 +487,7 @@ That's all of the required database changes.
module Geo
class CoolWidgetState < ApplicationRecord
include EachBatch
-
+
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
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 44b80158e51..35bb28ad170 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -132,25 +132,23 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
FAILED_VERIFICATION_INDEX_NAME = "index_cool_widget_states_failed_verification"
NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widget_states_needs_verification"
- disable_ddl_transaction!
+ enable_lock_retries!
def up
- with_lock_retries do
- create_table :cool_widget_states, id: false do |t|
- t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure, limit: 255
-
- t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
+ create_table :cool_widget_states, id: false do |t|
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure, limit: 255
+
+ t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
end
end
@@ -453,7 +451,7 @@ That's all of the required database changes.
module Geo
class CoolWidgetState < ApplicationRecord
include EachBatch
-
+
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
diff --git a/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md b/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md
new file mode 100644
index 00000000000..4544e675256
--- /dev/null
+++ b/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md
@@ -0,0 +1,38 @@
+<!--
+## Implementation Issue To-Do list
+(_NOTE: This section can be removed when the issue is ready for creation_)
+- [ ] Ensure that issue title is concise yet descriptive
+- [ ] Add `Frontend :` or `Backend: ` per group [naming conventions](https://about.gitlab.com/handbook/engineering/development/ops/verify/pipeline-authoring/#splitting-issues)
+- [ ] Ensure the issue containing the feature or change proposal and related discussions is linked as related to this implementation issue.
+- [ ] Aside from default labeling, please make sure to include relevant labels for `type::`, `workflow::`, and `~frontend`/`~backend` labeling.
+- [ ] Issues with user-facing changes should include the `~UX` label.
+-->
+
+## Summary
+
+## Proposal
+
+## Implementation Table
+
+<!--
+_NOTE: If the issue is not part of an epic, the implementation table can be removed. If it is part of an epic, make sure that the implementation table below mirrors the corresponding epic's implementation table content._
+-->
+
+
+| Group | Issue Link |
+| ------ | ------ |
+| ~backend | :point_left: You are here |
+| ~frontend | [#123123](url) |
+
+<!--
+## Documentation
+
+_NOTE: This section is optional, but can be used for easy access to any relevant documentation URLs._
+-->
+
+## Links/References
+
+
+
+
+/label ~"group::pipeline authoring" ~"Category:Pipeline Authoring" ~"section::ops" ~"devops::verify" ~"workflow::planning breakdown"
diff --git a/.gitlab/issue_templates/Problem Validation.md b/.gitlab/issue_templates/Problem Validation.md
index 3f92510b6af..dee026ee752 100644
--- a/.gitlab/issue_templates/Problem Validation.md
+++ b/.gitlab/issue_templates/Problem Validation.md
@@ -1,4 +1,4 @@
-<!-- This template is used as a starting point for understing and articulating a customer problem.
+<!-- This template is used as a starting point for understanding and articulating a customer problem.
Learn more about it in the handbook: https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation
-->
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index e63727fe484..5c1b669a88f 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -9,14 +9,13 @@ Set the title to: `Description of the original issue`
## Prior to starting the security release work
- [ ] Read the [security process for developers] if you are not familiar with it.
-- [ ] Make sure the issue really needs to follow the security release workflow.
- - Verify if the issue you're working on `gitlab-org/gitlab` is confidential, if it's public fix should be placed on GitLab canonical and no backports are required.
- - If the issue you're fixing doesn't appear to be something that can be exploited by a malicious person and is instead simply a security enhancement do not hesitate to ping `@gitlab-com/gl-security/appsec` to discuss if the issue can be fixed in the canonical repository.
+- [ ] Make sure the [issue really needs to follow the security release workflow].
- [ ] **IMPORTANT**: Mark this [issue as linked] to the Security Release Tracking Issue. You can find it [here](https://gitlab.com/gitlab-org/gitlab/-/issues?sort=created_date&state=opened&label_name[]=upcoming+security+release). This issue
MUST be linked for the release bot to know that the associated merge requests should be merged for this security release.
- Fill out the [Links section](#links):
- [ ] Next to **Issue on GitLab**, add a link to the `gitlab-org/gitlab` issue that describes the security vulnerability.
- [ ] Add one of the `~severity::x` labels to the issue and all associated merge requests.
+- [ ] If this change affects the public interface (public API or UI) of the product, post in the `#support_gitlab-com` Slack channel to explain the impact and discuss a mitigation plan for users that might be affected. If you need Support feedback or approval, reach out in `#spt_managers` Slack channel or mention `@gitlab-com/support/managers`.
## Development
@@ -71,5 +70,6 @@ After your merge request has been approved according to our [approval guidelines
[security Release merge request template]: https://gitlab.com/gitlab-org/security/gitlab/blob/master/.gitlab/merge_request_templates/Security%20Release.md
[approval guidelines]: https://docs.gitlab.com/ee/development/code_review.html#approval-guidelines
[issue as linked]: https://docs.gitlab.com/ee/user/project/issues/related_issues.html#add-a-linked-issue
+[issue really needs to follow the security release workflow]: https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/developer.md#making-sure-the-issue-needs-to-follow-the-security-release-workflow
/label ~security
diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md
index e0b4f127e4a..fc803152efb 100644
--- a/.gitlab/merge_request_templates/Deprecations.md
+++ b/.gitlab/merge_request_templates/Deprecations.md
@@ -1,12 +1,18 @@
<!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. -->
-/label ~"release post" ~"release post item" ~"Technical Writing" ~"devops::" ~"group::" ~"release post item::deprecation"
+/label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::deprecation"
+/label ~"type::maintenance"
/milestone %
/assign `@EM/PM` (choose the DRI; remove backticks here, and below)
**Be sure to link this MR to the relevant deprecation issue(s).**
-If the MR does not have a deprecation issue, hit pause and review [this handbook documentation](https://about.gitlab.com/handbook/product/gitlab-the-product/#process-for-deprecating-and-removing-a-feature) and connect with the Product Manager DRI.
+- Deprecation Issue:
+
+If there is no relevant deprecation issue, hit pause and:
+
+- Review the [process for deprecating and removing features](https://about.gitlab.com/handbook/product/gitlab-the-product/#process-for-deprecating-and-removing-a-feature).
+- Connect with the Product Manager DRI.
Deprecation announcements can and should be created and merged into Docs at any time, to optimize user awareness and planning. We encourage confirmed deprecations to be merged as soon as the required reviews are complete, even if weeks ahead of the target milestone's release post. For the announcement to be included in a specific release post and that release's documentation packages, this MR must be reviewed/merged per the due dates below:
@@ -28,18 +34,13 @@ Please review the [guidelines for deprecations](https://about.gitlab.com/handboo
as well as the process for [creating a deprecation entry](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry).
They are frequently updated, and everyone should make sure they are aware of the current standards (PM, PMM, EM, and TW).
-## Links
-
-- Deprecation Issue:
-- Deprecation MR (optional):
-
## EM/PM release post item checklist
- [ ] Set yourself as the Assignee, meaning you are the DRI.
- [ ] If the deprecation is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`.
- [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry).
- [ ] Add reviewers by the 10th.
-- [ ] When ready to be merged and not later than the 15th, add the ~ready label and @ message the TW for final review and merge.
+- [ ] When ready to be merged and not later than the 15th, add the `~ready` label and @ message the TW for final review and merge.
## Reviewers
@@ -68,7 +69,7 @@ yourself as a reviewer if it's not ready for merge yet.
- [ ] Title:
- Length limit: 7 words (not including articles or prepositions).
- Capitalization: ensure the title is [sentence cased](https://design.gitlab.com/content/punctuation#case).
- - No Markdown `` `code` `` formatting in the title, as it doesn't render correctly in the release post.
+ - Rewrite to exclude the words `deprecation`, `deprecate`, `removal`, and `remove` if necessary.
- [ ] Consistency:
- Ensure that all resources (docs, deprecation, etc.) refer to the feature with the same term / feature name.
- [ ] Content:
@@ -98,4 +99,4 @@ must be updated before this MR is merged:
1. Commit the updated file and push the changes.
1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete).
-If you have trouble running the rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
+If you have trouble running the Rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
diff --git a/.gitlab/merge_request_templates/Removals.md b/.gitlab/merge_request_templates/Removals.md
index 398714826b9..9d3738f63b5 100644
--- a/.gitlab/merge_request_templates/Removals.md
+++ b/.gitlab/merge_request_templates/Removals.md
@@ -1,13 +1,24 @@
<!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. -->
-**Be sure to link this MR to the relevant deprecation issue(s).**
+/label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::removal"
+/label ~"type::maintenance"
+/milestone %
+/assign `@EM/PM` (choose the DRI; remove backticks here, and below)
+
+**Be sure to link this MR to the relevant issue(s).**
+
+- Deprecation issue:
+- Removal issue:
+- MR that removes the feature (optional):
+
+If there is no relevant deprecation issue, hit pause and:
-If the MR does not have a deprecation issue, hit pause and:
+- Review the [process for deprecating and removing features](https://about.gitlab.com/handbook/product/gitlab-the-product/#process-for-deprecating-and-removing-a-feature).
+- Connect with the Product Manager DRI.
-- Review [this handbook documentation](https://about.gitlab.com/handbook/product/gitlab-the-product/#process-for-deprecating-and-removing-a-feature).
-- Connect with the Product Manager DRI.
+Removals must be [announced as deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations) at least 2 milestones in advance of the planned removal date.
-Removals must be [announced as Deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations) at least 2 milestones in advance of the planned removal date. Removals can only be removed in a XX.0 major release if it creates a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features).
+If the removal creates a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features), it can only be removed in a major "XX.0" release.
**By the 10th**: Assign this MR to these team members as reviewers, and for approval:
@@ -27,11 +38,6 @@ Removals must be [announced as Deprecations](https://about.gitlab.com/handbook/m
Please review the [guidelines for removals](https://about.gitlab.com/handbook/marketing/blog/release-posts/#removals).
-## Links
-
-- Removal Issue:
-- Removal MR (optional):
-
## EM/PM release post item checklist
- [ ] Set yourself as the Assignee, meaning you are the DRI.
@@ -97,7 +103,3 @@ must be updated before this MR is merged:
1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete).
If you have trouble running the rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
-
-/label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::removal"
-/milestone %
-/assign `@EM/PM` (choose the DRI; remove backticks here, and below)
diff --git a/.markdownlint.yml b/.markdownlint.yml
index e1e2b246314..9d83bd2e1da 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -22,6 +22,8 @@ no-emphasis-as-heading: false
first-line-h1: false
code-block-style:
style: "fenced"
+emphasis-style: false
+strong-style: false
proper-names:
names: [
"Akismet",
@@ -139,6 +141,8 @@ proper-names:
"unicorn-worker-killer",
"URL",
"WebdriverIO",
+ "Workload Identity Pool",
+ "Workload Identity Provider",
"YAML",
"YouTrack"
]
diff --git a/.projections.json.example b/.projections.json.example
index 19ded7eba98..eff09c73140 100644
--- a/.projections.json.example
+++ b/.projections.json.example
@@ -31,6 +31,14 @@
"alternate": "lib/api/{}.rb",
"type": "test"
},
+ "rubocop/cop/*.rb": {
+ "alternate": "spec/rubocop/cop/{}_spec.rb",
+ "type": "source"
+ },
+ "spec/rubocop/cop/*_spec.rb": {
+ "alternate": "rubocop/cop/{}.rb",
+ "type": "test"
+ },
"ee/lib/api/*.rb": {
"alternate": "ee/spec/requests/api/{}_spec.rb",
"type": "source"
diff --git a/.rubocop.yml b/.rubocop.yml
index 2280fe222ea..8416653d677 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -97,14 +97,8 @@ RSpec/FilePath:
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
- Max: 28
+ Max: 25
AllowSubject: true
- Exclude:
- - 'spec/migrations/**/*.rb'
- - 'spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb'
- - 'ee/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb'
Naming/FileName:
ExpectMatchingDefinition: true
@@ -174,6 +168,7 @@ Naming/FileName:
- GitLab
- JavaScript
- VSCode
+ - JetBrains
# default ones:
- CLI
- DSL
@@ -296,6 +291,12 @@ Gitlab/AvoidUploadedFileFromParams:
- 'spec/**/*'
- 'ee/spec/**/*'
+Gitlab/EventStoreSubscriber:
+ Enabled: true
+ Exclude:
+ - 'spec/**/*'
+ - 'ee/spec/**/*'
+
GitlabSecurity/PublicSend:
Enabled: true
Exclude:
@@ -517,24 +518,6 @@ Graphql/Descriptions:
RSpec/ImplicitSubject:
Enabled: false
-# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/211580
-RSpec/LeakyConstantDeclaration:
- Enabled: true
- Exclude:
- - 'spec/db/schema_spec.rb'
- - 'spec/lib/feature_spec.rb'
- - 'spec/lib/gitlab/config/entry/simplifiable_spec.rb'
- - 'spec/lib/gitlab/quick_actions/dsl_spec.rb'
- - 'spec/lib/marginalia_spec.rb'
- - 'spec/mailers/notify_spec.rb'
- - 'spec/models/concerns/batch_destroy_dependent_associations_spec.rb'
- - 'spec/models/concerns/bulk_insert_safe_spec.rb'
- - 'spec/models/concerns/bulk_insertable_associations_spec.rb'
- - 'spec/models/concerns/triggerable_hooks_spec.rb'
- - 'spec/models/repository_spec.rb'
- - 'spec/services/clusters/applications/check_installation_progress_service_spec.rb'
- - 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb'
-
RSpec/EmptyLineAfterHook:
Enabled: false
@@ -689,6 +672,7 @@ Gitlab/NamespacedClass:
- 'ee/elastic/**/*.rb'
- 'scripts/**/*'
- 'spec/migrations/**/*.rb'
+ - 'app/experiments/**/*_experiment.rb'
Lint/HashCompareByIdentity:
Enabled: true
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 300706a4d8e..ac8afd5c00c 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -231,7 +231,6 @@ Naming/HeredocDelimiterNaming:
Naming/MethodParameterName:
Exclude:
- 'lib/gitlab/diff/inline_diff.rb'
- - 'spec/support/helpers/key_generator_helper.rb'
# Offense count: 218
# Cop supports --auto-correct.
diff --git a/.rubocop_todo/database/multiple_databases.yml b/.rubocop_todo/database/multiple_databases.yml
index 7329d178dc1..69bc0b64a30 100644
--- a/.rubocop_todo/database/multiple_databases.yml
+++ b/.rubocop_todo/database/multiple_databases.yml
@@ -11,7 +11,6 @@ Database/MultipleDatabases:
- ee/spec/services/ee/merge_requests/update_service_spec.rb
- lib/backup/database.rb
- lib/backup/manager.rb
- - lib/gitlab/current_settings.rb
- lib/gitlab/database/load_balancing/load_balancer.rb
- lib/gitlab/database/load_balancing.rb
- lib/gitlab/database/load_balancing/sticking.rb
@@ -19,18 +18,15 @@ Database/MultipleDatabases:
- lib/gitlab/database/migrations/observers/query_log.rb
- lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
- lib/gitlab/database.rb
- - lib/gitlab/database/with_lock_retries.rb
- lib/gitlab/gitlab_import/importer.rb
- lib/gitlab/health_checks/db_check.rb
- lib/gitlab/import_export/base/relation_factory.rb
- lib/gitlab/import_export/group/relation_tree_restorer.rb
- lib/gitlab/legacy_github_import/importer.rb
- lib/gitlab/seeder.rb
- - lib/system_check/orphans/repository_check.rb
- spec/db/schema_spec.rb
- spec/initializers/database_config_spec.rb
- spec/lib/backup/manager_spec.rb
- - spec/lib/gitlab/current_settings_spec.rb
- spec/lib/gitlab/database_spec.rb
- spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
- spec/lib/gitlab/profiler_spec.rb
diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml
index f13325378d3..7d0f69c9300 100644
--- a/.rubocop_todo/gitlab/namespaced_class.yml
+++ b/.rubocop_todo/gitlab/namespaced_class.yml
@@ -428,6 +428,7 @@ Gitlab/NamespacedClass:
- app/policies/user_policy.rb
- app/policies/wiki_page_policy.rb
- app/policies/wiki_policy.rb
+ - app/policies/work_item_policy.rb
- app/presenters/award_emoji_presenter.rb
- app/presenters/blob_presenter.rb
- app/presenters/board_presenter.rb
@@ -836,7 +837,6 @@ Gitlab/NamespacedClass:
- app/workers/pages_domain_verification_cron_worker.rb
- app/workers/pages_domain_verification_worker.rb
- app/workers/pages_transfer_worker.rb
- - app/workers/pages_update_configuration_worker.rb
- app/workers/pages_worker.rb
- app/workers/partition_creation_worker.rb
- app/workers/pipeline_hooks_worker.rb
diff --git a/.rubocop_todo/graphql/field_definitions.yml b/.rubocop_todo/graphql/field_definitions.yml
index 35ed870fa41..e1245a53409 100644
--- a/.rubocop_todo/graphql/field_definitions.yml
+++ b/.rubocop_todo/graphql/field_definitions.yml
@@ -1,10 +1,6 @@
---
GraphQL/FieldDefinitions:
Exclude:
- - app/graphql/types/commit_type.rb
- - app/graphql/types/group_type.rb
- - app/graphql/types/issue_type.rb
- - app/graphql/types/label_type.rb
- ee/app/graphql/types/ci/code_quality_degradation_type.rb
- ee/app/graphql/types/epic_type.rb
- ee/app/graphql/types/group_release_stats_type.rb
diff --git a/.rubocop_todo/graphql/ordered_arguments.yml b/.rubocop_todo/graphql/ordered_arguments.yml
index 3a4e805948d..def1b0085e4 100644
--- a/.rubocop_todo/graphql/ordered_arguments.yml
+++ b/.rubocop_todo/graphql/ordered_arguments.yml
@@ -4,10 +4,6 @@ GraphQL/OrderedArguments:
- app/graphql/resolvers/base_issues_resolver.rb
- app/graphql/resolvers/design_management/designs_resolver.rb
- app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
- - app/graphql/resolvers/merge_requests_resolver.rb
- - app/graphql/resolvers/paginated_tree_resolver.rb
- - app/graphql/resolvers/tree_resolver.rb
- - app/graphql/resolvers/users/groups_resolver.rb
- app/graphql/types/commit_action_type.rb
- app/graphql/types/diff_paths_input_type.rb
- app/graphql/types/issues/negated_issue_filter_input_type.rb
diff --git a/.rubocop_todo/rails/save_bang.yml b/.rubocop_todo/rails/save_bang.yml
index 15361fd6743..e1698a83682 100644
--- a/.rubocop_todo/rails/save_bang.yml
+++ b/.rubocop_todo/rails/save_bang.yml
@@ -2,44 +2,3 @@
Rails/SaveBang:
Exclude:
- ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb
- - ee/spec/models/protected_environment_spec.rb
- - ee/spec/models/repository_spec.rb
- - ee/spec/models/scim_identity_spec.rb
- - ee/spec/models/scim_oauth_access_token_spec.rb
- - ee/spec/models/upload_spec.rb
- - ee/spec/models/user_preference_spec.rb
- - ee/spec/models/visible_approvable_spec.rb
- - ee/spec/models/vulnerabilities/feedback_spec.rb
- - ee/spec/models/vulnerabilities/issue_link_spec.rb
- - spec/lib/backup/manager_spec.rb
- - spec/lib/gitlab/alerting/alert_spec.rb
- - spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
- - spec/lib/gitlab/auth/ldap/user_spec.rb
- - spec/lib/gitlab/auth/o_auth/user_spec.rb
- - spec/lib/gitlab/auth/saml/user_spec.rb
- - spec/lib/gitlab/auth_spec.rb
- - spec/lib/gitlab/authorized_keys_spec.rb
- - spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
- - spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
- - spec/lib/gitlab/database/custom_structure_spec.rb
- - spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
- - spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
- - spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
- - spec/lib/gitlab/import_export/fork_spec.rb
- - spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
- - spec/lib/gitlab/import_export/group/relation_factory_spec.rb
- - spec/lib/gitlab/import_export/group/tree_saver_spec.rb
- - spec/lib/gitlab/import_export/importer_spec.rb
- - spec/lib/gitlab/import_export/lfs_restorer_spec.rb
- - spec/lib/gitlab/import_export/lfs_saver_spec.rb
- - spec/lib/gitlab/import_export/members_mapper_spec.rb
- - spec/lib/gitlab/import_export/project/relation_factory_spec.rb
- - spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
- - spec/lib/gitlab/import_export/project/tree_saver_spec.rb
- - spec/lib/gitlab/import_export/repo_restorer_spec.rb
- - spec/lib/gitlab/import_export/saver_spec.rb
- - spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
- - spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
- - spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
- - spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
- - spec/lib/gitlab/import_export/uploads_manager_spec.rb
diff --git a/.rubocop_todo/rspec/any_instance_of.yml b/.rubocop_todo/rspec/any_instance_of.yml
index f7a8cfb3968..bf1bc408b66 100644
--- a/.rubocop_todo/rspec/any_instance_of.yml
+++ b/.rubocop_todo/rspec/any_instance_of.yml
@@ -29,7 +29,6 @@ RSpec/AnyInstanceOf:
- ee/spec/features/security/project/internal_access_spec.rb
- ee/spec/features/security/project/private_access_spec.rb
- ee/spec/features/security/project/public_access_spec.rb
- - ee/spec/features/trials/capture_lead_spec.rb
- ee/spec/features/trials/select_namespace_spec.rb
- ee/spec/features/users/login_spec.rb
- ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb
diff --git a/.rubocop_todo/rspec/leaky_constant_declaration.yml b/.rubocop_todo/rspec/leaky_constant_declaration.yml
new file mode 100644
index 00000000000..b8b3980ef4f
--- /dev/null
+++ b/.rubocop_todo/rspec/leaky_constant_declaration.yml
@@ -0,0 +1,15 @@
+---
+RSpec/LeakyConstantDeclaration:
+ Exclude:
+ - spec/db/schema_spec.rb
+ - spec/lib/gitlab/config/entry/simplifiable_spec.rb
+ - spec/lib/gitlab/quick_actions/dsl_spec.rb
+ - spec/lib/marginalia_spec.rb
+ - spec/mailers/notify_spec.rb
+ - spec/models/concerns/batch_destroy_dependent_associations_spec.rb
+ - spec/models/concerns/bulk_insert_safe_spec.rb
+ - spec/models/concerns/bulk_insertable_associations_spec.rb
+ - spec/models/concerns/triggerable_hooks_spec.rb
+ - spec/models/repository_spec.rb
+ - spec/services/clusters/applications/check_installation_progress_service_spec.rb
+ - spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb
diff --git a/.rubocop_todo/rspec/multiple_memoized_helpers.yml b/.rubocop_todo/rspec/multiple_memoized_helpers.yml
new file mode 100644
index 00000000000..2f6d390bec2
--- /dev/null
+++ b/.rubocop_todo/rspec/multiple_memoized_helpers.yml
@@ -0,0 +1,11 @@
+---
+RSpec/MultipleMemoizedHelpers:
+ Exclude:
+ - spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
+ - spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
+ - spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
+ - spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+ - ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb
+ - ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb
+ - ee/spec/services/ee/boards/issues/move_service_spec.rb
+ - ee/spec/services/security/store_report_service_spec.rb
diff --git a/.rubocop_todo/rspec/timecop_freeze.yml b/.rubocop_todo/rspec/timecop_freeze.yml
index 8deefee1164..2967793e42a 100644
--- a/.rubocop_todo/rspec/timecop_freeze.yml
+++ b/.rubocop_todo/rspec/timecop_freeze.yml
@@ -1,8 +1,6 @@
---
RSpec/TimecopFreeze:
Exclude:
- - ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb
- - ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb
- ee/spec/models/merge_train_spec.rb
- ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb
- qa/spec/support/repeater_spec.rb
diff --git a/.rubocop_todo/style/open_struct_use.yml b/.rubocop_todo/style/open_struct_use.yml
index ed4a53f2894..80239770db0 100644
--- a/.rubocop_todo/style/open_struct_use.yml
+++ b/.rubocop_todo/style/open_struct_use.yml
@@ -12,12 +12,8 @@ Style/OpenStructUse:
- lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
- lib/gitlab/testing/request_inspector_middleware.rb
- lib/mattermost/session.rb
- - spec/controllers/groups/clusters_controller_spec.rb
- - spec/controllers/projects/clusters_controller_spec.rb
- spec/factories/go_module_versions.rb
- spec/factories/wiki_pages.rb
- - spec/features/projects/clusters_spec.rb
- - spec/finders/template_finder_spec.rb
- spec/graphql/mutations/branches/create_spec.rb
- spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
- spec/graphql/mutations/clusters/agents/create_spec.rb
@@ -30,11 +26,5 @@ Style/OpenStructUse:
- spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
- spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
- spec/lib/gitlab/quick_actions/command_definition_spec.rb
- - spec/models/design_management/design_action_spec.rb
- - spec/models/design_management/design_at_version_spec.rb
- - spec/services/packages/nuget/metadata_extraction_service_spec.rb
- - spec/services/projects/import_service_spec.rb
- spec/services/system_note_service_spec.rb
- - spec/support/helpers/import_spec_helper.rb
- - spec/support/helpers/login_helpers.rb
- spec/support/helpers/repo_helpers.rb
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a29b06eea6e..8bd24e50e14 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,7 +36,9 @@ entry.
## 14.7.1 (2022-02-03)
-No changes.
+### Security
+
+See https://about.gitlab.com/releases/2022/02/03/security-release-gitlab-14-7-1-released/
## 14.7.0 (2022-01-21)
@@ -475,6 +477,12 @@ No changes.
- [Fix Gitlab/DelegatePredicateMethods offenses](gitlab-org/gitlab@518700a11025b0000ff3ce011638417a882612b0) by @edith007 ([merge request](gitlab-org/gitlab!76001))
- [Fix Rails/SaveBang offenses](gitlab-org/gitlab@513b0e1dbdf95ea595e7548ff26929e0be30ce29) by @edith007 ([merge request](gitlab-org/gitlab!75894)) **GitLab Enterprise Edition**
+## 14.6.4 (2022-02-03)
+
+### Security
+
+See https://about.gitlab.com/releases/2022/02/03/security-release-gitlab-14-7-1-released/
+
## 14.6.3 (2022-01-18)
### Fixed (4 changes)
@@ -873,6 +881,12 @@ No changes.
- [Fix OpenStruct use](gitlab-org/gitlab@f8466f5943a1afeabaf9cf781f7804a8df515a0e) by @mehulsharma ([merge request](gitlab-org/gitlab!74702))
- [Update Sidekiq to 6.3.1](gitlab-org/gitlab@22e8bc0af656717e56428a7227c467fe08021c66) ([merge request](gitlab-org/gitlab!73973))
+## 14.5.4 (2022-02-03)
+
+### Security
+
+See https://about.gitlab.com/releases/2022/02/03/security-release-gitlab-14-7-1-released/
+
## 14.5.3 (2022-01-11)
No changes.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 1f4bff5c623..363e7aebbbc 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-14.7.3 \ No newline at end of file
+5f39869b69abb55d5472140f0b730016f78887ed
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index d18453764c3..6ebe0c0b057 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-14.5.0
+14.8.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index ba0a719118c..b7921ae87bc 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.51.0
+1.54.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 35d41ddb27d..bb133229025 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.22.2
+13.23.2
diff --git a/Gemfile b/Gemfile
index 334e7df7681..518c6d8cc53 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@
source 'https://rubygems.org'
-gem 'rails', '~> 6.1.4.4'
+gem 'rails', '~> 6.1.4.6'
gem 'bootsnap', '~> 1.9.1', require: false
@@ -72,7 +72,7 @@ gem 'u2f', '~> 0.2.1'
# GitLab Pages
gem 'validates_hostname', '~> 1.0.11'
-gem 'rubyzip', '~> 2.0.0', require: 'zip'
+gem 'rubyzip', '~> 2.3.2', require: 'zip'
# GitLab Pages letsencrypt support
gem 'acme-client', '~> 2.0', '>= 2.0.9'
@@ -183,7 +183,7 @@ gem 'rack', '~> 2.2.3'
gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
group :puma do
- gem 'puma', '~> 5.5.2', require: false
+ gem 'puma', '~> 5.6.2', require: false
gem 'puma_worker_killer', '~> 0.3.1', require: false
gem 'sd_notify', '~> 0.1.0', require: false
end
@@ -195,7 +195,7 @@ gem 'state_machines-activerecord', '~> 0.8.0'
gem 'acts-as-taggable-on', '~> 9.0'
# Background jobs
-gem 'sidekiq', '~> 6.3'
+gem 'sidekiq', '~> 6.4'
gem 'sidekiq-cron', '~> 1.2'
gem 'redis-namespace', '~> 1.8.1'
gem 'gitlab-sidekiq-fetcher', '0.8.0', require: 'sidekiq-reliable-fetch'
@@ -295,7 +295,7 @@ gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
-gem 'gitlab-license', '~> 2.0'
+gem 'gitlab-license', '~> 2.1.0'
# Protect against bruteforcing
gem 'rack-attack', '~> 6.3.0'
@@ -310,7 +310,7 @@ gem 'pg_query', '~> 2.1'
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '~> 0.21.3'
+gem 'gitlab-labkit', '~> 0.22.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'
@@ -396,7 +396,7 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 2.6.1', require: false
+ gem 'gitlab-dangerfiles', '~> 2.8.0', require: false
end
group :development, :test, :coverage do
@@ -466,21 +466,14 @@ gem 'sys-filesystem', '~> 1.4.3'
# NTP client
gem 'net-ntp'
-# SSH host key support
-gem 'net-ssh', '~> 6.0'
-gem 'sshkey', '~> 2.0'
-
-# Required for ED25519 SSH host key support
-group :ed25519 do
- gem 'ed25519', '~> 1.2'
- gem 'bcrypt_pbkdf', '~> 1.1'
-end
+# SSH keys support
+gem 'ssh_data', '~> 1.2'
# Spamcheck GRPC protocol definitions
gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 14.6.0.pre.rc1'
+gem 'gitaly', '~> 14.8.0.pre.rc1'
# KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2'
@@ -496,7 +489,7 @@ gem 'flipper', '~> 0.21.0'
gem 'flipper-active_record', '~> 0.21.0'
gem 'flipper-active_support_cache_store', '~> 0.21.0'
gem 'unleash', '~> 3.2.2'
-gem 'gitlab-experiment', '~> 0.6.5'
+gem 'gitlab-experiment', '~> 0.7.0'
# Structured logging
gem 'lograge', '~> 0.5'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4fd0bf053c4..71fe578b921 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -11,63 +11,63 @@ GEM
RedCloth (4.3.2)
acme-client (2.0.9)
faraday (>= 0.17, < 2.0.0)
- actioncable (6.1.4.4)
- actionpack (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ actioncable (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.1.4.4)
- actionpack (= 6.1.4.4)
- activejob (= 6.1.4.4)
- activerecord (= 6.1.4.4)
- activestorage (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ actionmailbox (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ activejob (= 6.1.4.6)
+ activerecord (= 6.1.4.6)
+ activestorage (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
mail (>= 2.7.1)
- actionmailer (6.1.4.4)
- actionpack (= 6.1.4.4)
- actionview (= 6.1.4.4)
- activejob (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ actionmailer (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ actionview (= 6.1.4.6)
+ activejob (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.1.4.4)
- actionview (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ actionpack (6.1.4.6)
+ actionview (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
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.1.4.4)
- actionpack (= 6.1.4.4)
- activerecord (= 6.1.4.4)
- activestorage (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ actiontext (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ activerecord (= 6.1.4.6)
+ activestorage (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
nokogiri (>= 1.8.5)
- actionview (6.1.4.4)
- activesupport (= 6.1.4.4)
+ actionview (6.1.4.6)
+ activesupport (= 6.1.4.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.1.4.4)
- activesupport (= 6.1.4.4)
+ activejob (6.1.4.6)
+ activesupport (= 6.1.4.6)
globalid (>= 0.3.6)
- activemodel (6.1.4.4)
- activesupport (= 6.1.4.4)
- activerecord (6.1.4.4)
- activemodel (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ activemodel (6.1.4.6)
+ activesupport (= 6.1.4.6)
+ activerecord (6.1.4.6)
+ activemodel (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (6.1.4.4)
- actionpack (= 6.1.4.4)
- activejob (= 6.1.4.4)
- activerecord (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ activestorage (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ activejob (= 6.1.4.6)
+ activerecord (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
marcel (~> 1.0.0)
mini_mime (>= 1.1.0)
- activesupport (6.1.4.4)
+ activesupport (6.1.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@@ -137,7 +137,6 @@ GEM
base32 (0.3.2)
batch-loader (2.0.1)
bcrypt (3.1.16)
- bcrypt_pbkdf (1.1.0)
benchmark (0.1.1)
benchmark-ips (2.3.0)
benchmark-memory (0.1.2)
@@ -193,7 +192,7 @@ GEM
childprocess (3.0.0)
chunky_png (1.3.5)
citrus (3.0.2)
- claide (1.0.3)
+ claide (1.1.0)
claide-plugins (0.9.2)
cork
nap
@@ -202,7 +201,7 @@ GEM
colored2 (3.1.2)
commonmarker (0.23.2)
concurrent-ruby (1.1.9)
- connection_pool (2.2.2)
+ connection_pool (2.2.5)
contracts (0.11.0)
cork (0.3.0)
colored2 (~> 3.1)
@@ -308,7 +307,6 @@ GEM
e2mmap (0.1.0)
ecma-re-validator (0.3.0)
regexp_parser (~> 2.0)
- ed25519 (1.2.4)
elasticsearch (6.8.2)
elasticsearch-api (= 6.8.2)
elasticsearch-transport (= 6.8.2)
@@ -451,7 +449,7 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (14.6.0.pre.rc1)
+ gitaly (14.8.0.pre.rc1)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab (4.16.1)
@@ -459,13 +457,12 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (2.6.1)
+ gitlab-dangerfiles (2.8.0)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
- gitlab-experiment (0.6.5)
+ gitlab-experiment (0.7.0)
activesupport (>= 3.0)
request_store (>= 1.0)
- scientist (~> 1.6, >= 1.6.0)
gitlab-fog-azure-rm (1.2.0)
azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
@@ -473,15 +470,15 @@ GEM
fog-json (~> 1.2.0)
mime-types
ms_rest_azure (~> 0.12.0)
- gitlab-labkit (0.21.3)
+ gitlab-labkit (0.22.0)
actionpack (>= 5.0.0, < 7.0.0)
activesupport (>= 5.0.0, < 7.0.0)
grpc (>= 1.37)
- jaeger-client (~> 1.1)
+ jaeger-client (~> 1.1.0)
opentracing (~> 0.4)
pg_query (~> 2.1)
redis (> 3.0.0, < 5.0.0)
- gitlab-license (2.0.0)
+ gitlab-license (2.1.0)
gitlab-license_finder (6.14.2.1)
bundler
rubyzip (>= 1, < 3)
@@ -633,7 +630,7 @@ GEM
http-form_data (~> 2.2)
http-parser (~> 1.2.0)
http-accept (1.7.0)
- http-cookie (1.0.3)
+ http-cookie (1.0.4)
domain_name (~> 0.5)
http-form_data (2.3.0)
http-parser (1.2.3)
@@ -642,7 +639,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.8.11)
+ i18n (1.9.1)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
@@ -944,7 +941,7 @@ GEM
tty-markdown
tty-prompt
public_suffix (4.0.6)
- puma (5.5.2)
+ puma (5.6.2)
nio4r (~> 2.0)
puma_worker_killer (0.3.1)
get_process_mem (~> 0.2)
@@ -970,20 +967,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.2)
- rails (6.1.4.4)
- actioncable (= 6.1.4.4)
- actionmailbox (= 6.1.4.4)
- actionmailer (= 6.1.4.4)
- actionpack (= 6.1.4.4)
- actiontext (= 6.1.4.4)
- actionview (= 6.1.4.4)
- activejob (= 6.1.4.4)
- activemodel (= 6.1.4.4)
- activerecord (= 6.1.4.4)
- activestorage (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ rails (6.1.4.6)
+ actioncable (= 6.1.4.6)
+ actionmailbox (= 6.1.4.6)
+ actionmailer (= 6.1.4.6)
+ actionpack (= 6.1.4.6)
+ actiontext (= 6.1.4.6)
+ actionview (= 6.1.4.6)
+ activejob (= 6.1.4.6)
+ activemodel (= 6.1.4.6)
+ activerecord (= 6.1.4.6)
+ activestorage (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
bundler (>= 1.15.0)
- railties (= 6.1.4.4)
+ railties (= 6.1.4.6)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -997,9 +994,9 @@ GEM
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
- railties (6.1.4.4)
- actionpack (= 6.1.4.4)
- activesupport (= 6.1.4.4)
+ railties (6.1.4.6)
+ actionpack (= 6.1.4.6)
+ activesupport (= 6.1.4.6)
method_source
rake (>= 0.13)
thor (~> 1.0)
@@ -1031,13 +1028,13 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.9.0)
redis (>= 4, < 5)
- regexp_parser (2.1.1)
+ regexp_parser (2.2.1)
regexp_property_values (1.0.0)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
- request_store (1.5.0)
+ request_store (1.5.1)
rack (>= 1.4)
responders (3.0.0)
actionpack (>= 5.0)
@@ -1134,7 +1131,7 @@ GEM
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
- rubyzip (2.0.0)
+ rubyzip (2.3.2)
rugged (1.2.0)
safe_yaml (1.0.4)
safety_net_attestation (0.4.0)
@@ -1147,9 +1144,8 @@ GEM
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
- sassc (2.0.1)
+ sassc (2.4.0)
ffi (~> 1.9)
- rake
sassc-rails (2.1.0)
railties (>= 4.0.0)
sassc (>= 2.0)
@@ -1159,7 +1155,6 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
- scientist (1.6.2)
sd_notify (0.1.0)
securecompare (1.0.0)
seed-fu (2.3.7)
@@ -1176,7 +1171,7 @@ GEM
shellany (0.0.1)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
- sidekiq (6.3.1)
+ sidekiq (6.4.0)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
@@ -1232,7 +1227,7 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
- sshkey (2.0.0)
+ ssh_data (1.2.0)
ssrf_filter (1.0.7)
stackprof (0.2.15)
state_machines (0.5.0)
@@ -1319,7 +1314,7 @@ GEM
rugged (>= 0.27, < 1.3)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.7)
+ unf_ext (0.0.8)
unicode-display_width (1.7.0)
unicode_utils (1.4.0)
uniform_notifier (1.13.0)
@@ -1379,7 +1374,7 @@ GEM
nokogiri (~> 1.8)
yajl-ruby (1.4.1)
yard (0.9.26)
- zeitwerk (2.5.3)
+ zeitwerk (2.5.4)
PLATFORMS
ruby
@@ -1408,7 +1403,6 @@ DEPENDENCIES
base32 (~> 0.3.0)
batch-loader (~> 2.0.1)
bcrypt (~> 3.1, >= 3.1.14)
- bcrypt_pbkdf (~> 1.1)
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.0)
@@ -1441,7 +1435,6 @@ DEPENDENCIES
discordrb-webhooks (~> 3.4)
doorkeeper (~> 5.5.0.rc2)
doorkeeper-openid_connect (~> 1.7.5)
- ed25519 (~> 1.2)
elasticsearch-api (~> 6.8.2)
elasticsearch-model (~> 6.1)
elasticsearch-rails (~> 6.1)
@@ -1470,14 +1463,14 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 14.6.0.pre.rc1)
+ gitaly (~> 14.8.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 2.6.1)
- gitlab-experiment (~> 0.6.5)
+ gitlab-dangerfiles (~> 2.8.0)
+ gitlab-experiment (~> 0.7.0)
gitlab-fog-azure-rm (~> 1.2.0)
- gitlab-labkit (~> 0.21.3)
- gitlab-license (~> 2.0)
+ gitlab-labkit (~> 0.22.0)
+ gitlab-license (~> 2.1.0)
gitlab-license_finder (~> 6.0)
gitlab-mail_room (~> 0.0.9)
gitlab-markup (~> 1.8.0)
@@ -1542,7 +1535,6 @@ DEPENDENCIES
multi_json (~> 1.14.1)
net-ldap (~> 0.16.3)
net-ntp
- net-ssh (~> 6.0)
nokogiri (~> 1.12)
oauth2 (~> 1.4)
octokit (~> 4.15)
@@ -1579,7 +1571,7 @@ DEPENDENCIES
pry-byebug
pry-rails (~> 0.3.9)
pry-shell (~> 0.5.0)
- puma (~> 5.5.2)
+ puma (~> 5.6.2)
puma_worker_killer (~> 0.3.1)
rack (~> 2.2.3)
rack-attack (~> 6.3.0)
@@ -1587,7 +1579,7 @@ DEPENDENCIES
rack-oauth2 (~> 1.16.0)
rack-proxy (~> 0.6.0)
rack-timeout (~> 0.5.1)
- rails (~> 6.1.4.4)
+ rails (~> 6.1.4.6)
rails-controller-testing
rails-i18n (~> 6.0)
rainbow (~> 3.0)
@@ -1615,7 +1607,7 @@ DEPENDENCIES
ruby-progressbar (~> 1.10)
ruby-saml (~> 1.13.0)
ruby_parser (~> 3.15)
- rubyzip (~> 2.0.0)
+ rubyzip (~> 2.3.2)
rugged (~> 1.2)
sanitize (~> 6.0)
sassc-rails (~> 2.1.0)
@@ -1625,7 +1617,7 @@ DEPENDENCIES
sentry-raven (~> 3.1)
settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1)
- sidekiq (~> 6.3)
+ sidekiq (~> 6.4)
sidekiq-cron (~> 1.2)
simple_po_parser (~> 1.1.2)
simplecov (~> 0.18.5)
@@ -1639,7 +1631,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4)
sprite-factory (~> 1.7)
sprockets (~> 3.7.0)
- sshkey (~> 2.0)
+ ssh_data (~> 1.2)
stackprof (~> 0.2.15)
state_machines-activerecord (~> 0.8.0)
sys-filesystem (~> 1.4.3)
@@ -1669,4 +1661,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.1)
BUNDLED WITH
- 2.1.4
+ 2.3.6
diff --git a/PROCESS.md b/PROCESS.md
index 67abe2f0a98..2757075e354 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -22,7 +22,7 @@
- [Code format](#code-format)
- [Issue fixed in newer version](#issue-fixed-in-newer-version)
- [Improperly formatted merge request](#improperly-formatted-merge-request)
- - [Accepting merge requests](#accepting-merge-requests)
+ - [Seeking community contributions](#seeking-community-contributions)
- [Only accepting merge requests with green tests](#only-accepting-merge-requests-with-green-tests)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -195,14 +195,14 @@ Thanks for your interest in improving the GitLab codebase!
Please update your merge request according to the [contributing guidelines](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/contributing/merge_request_workflow.md#merge-request-guidelines).
```
-### Accepting merge requests
+### Seeking community contributions
```
Is there an issue on the
[issue tracker](https://gitlab.com/gitlab-org/gitlab/issues) that is
similar to this? Could you please link it here?
Please be aware that new functionality that is not marked
-[`Accepting merge requests`](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#label-for-community-contributors)
+[`Seeking community contributions`](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#label-for-community-contributors)
might not make it into GitLab.
```
diff --git a/app/assets/images/auth_buttons/atlassian_64.png b/app/assets/images/auth_buttons/atlassian_64.png
index 548f1c93318..63169b9a81b 100644
--- a/app/assets/images/auth_buttons/atlassian_64.png
+++ b/app/assets/images/auth_buttons/atlassian_64.png
Binary files differ
diff --git a/app/assets/images/auth_buttons/auth0_64.png b/app/assets/images/auth_buttons/auth0_64.png
index 5ad59659380..3b2d8562d9d 100644
--- a/app/assets/images/auth_buttons/auth0_64.png
+++ b/app/assets/images/auth_buttons/auth0_64.png
Binary files differ
diff --git a/app/assets/images/auth_buttons/bitbucket_64.png b/app/assets/images/auth_buttons/bitbucket_64.png
index 0edf7f52a11..06a68b9bf55 100644
--- a/app/assets/images/auth_buttons/bitbucket_64.png
+++ b/app/assets/images/auth_buttons/bitbucket_64.png
Binary files differ
diff --git a/app/assets/images/auth_buttons/facebook_64.png b/app/assets/images/auth_buttons/facebook_64.png
index 71ffb1c6a1f..34b75de4498 100644
--- a/app/assets/images/auth_buttons/facebook_64.png
+++ b/app/assets/images/auth_buttons/facebook_64.png
Binary files differ
diff --git a/app/assets/images/auth_buttons/twitter_64.png b/app/assets/images/auth_buttons/twitter_64.png
index a4f14de57ae..15596b0f30a 100644
--- a/app/assets/images/auth_buttons/twitter_64.png
+++ b/app/assets/images/auth_buttons/twitter_64.png
Binary files differ
diff --git a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
index 09278e1776a..cdc8a952ead 100644
--- a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
+++ b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
@@ -22,6 +22,7 @@ query accessTokensGetProjects(
avatarUrl
}
pageInfo {
+ __typename
...PageInfo
}
}
diff --git a/app/assets/javascripts/actioncable_link.js b/app/assets/javascripts/actioncable_link.js
index 895a34ba157..cf53d9e21b4 100644
--- a/app/assets/javascripts/actioncable_link.js
+++ b/app/assets/javascripts/actioncable_link.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
import { print } from 'graphql';
import cable from '~/actioncable_consumer';
import { uuids } from '~/lib/utils/uuids';
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index f45af5fe08e..74e0e1b6225 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import { localTimeAgo } from './lib/utils/datetime_utility';
@@ -55,7 +55,7 @@ export default class Activities {
const filter = $sender.attr('id').split('_')[0];
$('.event-filter .active').removeClass('active');
- Cookies.set('event_filter', filter);
+ setCookie('event_filter', filter);
$sender.closest('li').toggleClass('active');
}
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 90c9113e0e1..96584080d0f 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
@@ -1,5 +1,5 @@
<script>
-import { GlModal, GlTabs, GlTab, GlSearchBoxByType, GlSprintf } from '@gitlab/ui';
+import { GlModal, GlTabs, GlTab, GlSearchBoxByType, GlSprintf, GlBadge } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import ReviewTabContainer from '~/add_context_commits_modal/components/review_tab_container.vue';
import createFlash from '~/flash';
@@ -21,6 +21,7 @@ export default {
ReviewTabContainer,
GlSearchBoxByType,
GlSprintf,
+ GlBadge,
},
props: {
contextCommitsPath: {
@@ -239,7 +240,7 @@ export default {
<template #title>
<gl-sprintf :message="__(`Commits in %{codeStart}${targetBranch}%{codeEnd}`)">
<template #code="{ content }">
- <code>{{ content }}</code>
+ <code class="gl-ml-2">{{ content }}</code>
</template>
</gl-sprintf>
</template>
@@ -262,7 +263,7 @@ export default {
<gl-tab>
<template #title>
{{ __('Selected commits') }}
- <span class="badge badge-pill">{{ selectedCommitsCount }}</span>
+ <gl-badge size="sm" class="gl-ml-2">{{ selectedCommitsCount }}</gl-badge>
</template>
<review-tab-container
:is-loading="isLoadingContextCommits"
diff --git a/app/assets/javascripts/admin/application_settings/setup_service_usage_data.js b/app/assets/javascripts/admin/application_settings/setup_service_usage_data.js
new file mode 100644
index 00000000000..a88efbd89a8
--- /dev/null
+++ b/app/assets/javascripts/admin/application_settings/setup_service_usage_data.js
@@ -0,0 +1,15 @@
+import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer';
+import PayloadDownloader from '~/pages/admin/application_settings/payload_downloader';
+
+export default () => {
+ const payloadPreviewTrigger = document.querySelector('.js-payload-preview-trigger');
+ const payloadDownloadTrigger = document.querySelector('.js-payload-download-trigger');
+
+ if (payloadPreviewTrigger) {
+ new PayloadPreviewer(payloadPreviewTrigger).init();
+ }
+
+ if (payloadDownloadTrigger) {
+ new PayloadDownloader(payloadDownloadTrigger).init();
+ }
+};
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 79a6bac3ba7..84c2b216859 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -15,7 +15,7 @@ import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
import { fetchPolicies } from '~/lib/graphql';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
-import { s__, __ } from '~/locale';
+import { s__, __, n__ } from '~/locale';
import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import {
tdClass,
@@ -32,8 +32,11 @@ const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
const TWELVE_HOURS_IN_MS = 12 * 60 * 60 * 1000;
+const MAX_VISIBLE_ASSIGNEES = 4;
+
export default {
trackAlertListViewsOptions,
+ MAX_VISIBLE_ASSIGNEES,
i18n: {
noAlertsMsg: s__(
'AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list.',
@@ -258,6 +261,13 @@ export default {
this.serverErrorMessage = '';
this.isErrorAlertDismissed = true;
},
+ assigneesBadgeSrOnlyText(item) {
+ return n__(
+ '%d additional assignee',
+ '%d additional assignees',
+ item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
+ );
+ },
},
};
</script>
@@ -365,10 +375,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
- :max-visible="4"
+ :max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
+ :badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link
diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js
index b23f8a8eba4..42cbeef56bf 100644
--- a/app/assets/javascripts/alert_management/list.js
+++ b/app/assets/javascripts/alert_management/list.js
@@ -1,4 +1,4 @@
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import { defaultDataIdFromObject } from '@apollo/client/core';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
index b64e2e3eefa..36a98145457 100644
--- a/app/assets/javascripts/alerts_settings/graphql.js
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -1,15 +1,9 @@
-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 = {
@@ -55,9 +49,5 @@ const resolvers = {
};
export default new VueApollo({
- defaultClient: createDefaultClient(resolvers, {
- cacheConfig: {
- fragmentMatcher,
- },
- }),
+ defaultClient: createDefaultClient(resolvers),
});
diff --git a/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json b/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json
deleted file mode 100644
index 07dfc43aa6c..00000000000
--- a/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"UNION","name":"AlertManagementIntegration","possibleTypes":[{"name":"AlertManagementHttpIntegration"},{"name":"AlertManagementPrometheusIntegration"}]}]}}
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
index 3cd3f2d92f8..ac9304391f9 100644
--- a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
@@ -5,6 +5,7 @@ query getIntegrations($projectPath: ID!) {
id
alertManagementIntegrations {
nodes {
+ __typename
...IntegrationItem
}
}
diff --git a/app/assets/javascripts/analytics/shared/components/daterange.vue b/app/assets/javascripts/analytics/shared/components/daterange.vue
index a5b9c40b9c9..7df66d1b2be 100644
--- a/app/assets/javascripts/analytics/shared/components/daterange.vue
+++ b/app/assets/javascripts/analytics/shared/components/daterange.vue
@@ -1,5 +1,5 @@
<script>
-import { GlDaterangePicker, GlSprintf, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlDaterangePicker, GlSprintf } from '@gitlab/ui';
import { getDayDifference } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import { OFFSET_DATE_BY_ONE } from '../constants';
@@ -8,10 +8,6 @@ export default {
components: {
GlDaterangePicker,
GlSprintf,
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
},
props: {
show: {
@@ -56,7 +52,7 @@ export default {
return {
maxDateRangeTooltip: sprintf(
__(
- 'Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days.',
+ 'Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days.',
),
{
maxDateRange: this.maxDateRange,
@@ -94,28 +90,15 @@ export default {
:max-date-range="maxDateRange"
:default-max-date="maxDate"
:same-day-selection="includeSelectedDate"
+ :tooltip="maxDateRangeTooltip"
theme="animate-picker"
start-picker-class="js-daterange-picker-from gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-lg-mr-3 gl-mb-2 gl-lg-mb-0"
- end-picker-class="js-daterange-picker-to d-flex flex-column flex-lg-row align-items-lg-center"
+ end-picker-class="js-daterange-picker-to d-flex flex-column flex-lg-row align-items-lg-center gl-mb-2 gl-lg-mb-0"
label-class="gl-mb-2 gl-lg-mb-0"
- />
- <div
- v-if="maxDateRange"
- class="daterange-indicator d-flex flex-row flex-lg-row align-items-flex-start align-items-lg-center"
>
- <span class="number-of-days pl-2 pr-1">
- <gl-sprintf :message="n__('1 day selected', '%d days selected', numberOfDays)">
- <template #numberOfDays>{{ numberOfDays }}</template>
- </gl-sprintf>
- </span>
- <gl-icon
- v-gl-tooltip
- data-testid="helper-icon"
- :title="maxDateRangeTooltip"
- name="question"
- :size="14"
- class="text-secondary"
- />
- </div>
+ <gl-sprintf :message="n__('1 day selected', '%d days selected', numberOfDays)">
+ <template #numberOfDays>{{ numberOfDays }}</template>
+ </gl-sprintf>
+ </gl-daterange-picker>
</div>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/metric_popover.vue b/app/assets/javascripts/analytics/shared/components/metric_popover.vue
index 8d90e7b2392..8d90e7b2392 100644
--- a/app/assets/javascripts/cycle_analytics/components/metric_popover.vue
+++ b/app/assets/javascripts/analytics/shared/components/metric_popover.vue
diff --git a/app/assets/javascripts/analytics/shared/components/metric_tile.vue b/app/assets/javascripts/analytics/shared/components/metric_tile.vue
new file mode 100644
index 00000000000..845a3386f6c
--- /dev/null
+++ b/app/assets/javascripts/analytics/shared/components/metric_tile.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { redirectTo } from '~/lib/utils/url_utility';
+import MetricPopover from './metric_popover.vue';
+
+export default {
+ name: 'MetricTile',
+ components: {
+ GlSingleStat,
+ MetricPopover,
+ },
+ props: {
+ metric: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ decimalPlaces() {
+ const parsedFloat = parseFloat(this.metric.value);
+ return Number.isNaN(parsedFloat) || Number.isInteger(parsedFloat) ? 0 : 1;
+ },
+ hasLinks() {
+ return this.metric.links?.length && this.metric.links[0].url;
+ },
+ },
+ methods: {
+ clickHandler({ links }) {
+ if (this.hasLinks) {
+ redirectTo(links[0].url);
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div v-bind="$attrs">
+ <gl-single-stat
+ :id="metric.identifier"
+ :value="`${metric.value}`"
+ :title="metric.label"
+ :unit="metric.unit || ''"
+ :should-animate="true"
+ :animation-decimal-places="decimalPlaces"
+ :class="{ 'gl-hover-cursor-pointer': hasLinks }"
+ tabindex="0"
+ @click="clickHandler(metric)"
+ />
+ <metric-popover :metric="metric" :target="metric.identifier" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue b/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue
index 9671742e564..1a3544e7677 100644
--- a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
+++ b/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue
@@ -1,13 +1,11 @@
<script>
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import { flatten } from 'lodash';
+import { flatten, isEqual } from 'lodash';
import createFlash from '~/flash';
import { sprintf, s__ } from '~/locale';
-import { redirectTo } from '~/lib/utils/url_utility';
import { METRICS_POPOVER_CONTENT } from '../constants';
import { removeFlash, prepareTimeMetricsData } from '../utils';
-import MetricPopover from './metric_popover.vue';
+import MetricTile from './metric_tile.vue';
const requestData = ({ request, endpoint, path, params, name }) => {
return request({ endpoint, params, requestPath: path })
@@ -33,9 +31,8 @@ const fetchMetricsData = (reqs = [], path, params) => {
export default {
name: 'ValueStreamMetrics',
components: {
- GlSingleStat,
GlSkeletonLoading,
- MetricPopover,
+ MetricTile,
},
props: {
requestPath: {
@@ -50,6 +47,11 @@ export default {
type: Array,
required: true,
},
+ filterFn: {
+ type: Function,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -58,8 +60,10 @@ export default {
};
},
watch: {
- requestParams() {
- this.fetchData();
+ requestParams(newVal, oldVal) {
+ if (!isEqual(newVal, oldVal)) {
+ this.fetchData();
+ }
},
},
mounted() {
@@ -71,40 +75,25 @@ export default {
this.isLoading = true;
return fetchMetricsData(this.requests, this.requestPath, this.requestParams)
.then((data) => {
- this.metrics = data;
+ this.metrics = this.filterFn ? this.filterFn(data) : data;
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
});
},
- hasLinks(links) {
- return links?.length && links[0].url;
- },
- clickHandler({ links }) {
- if (this.hasLinks(links)) {
- redirectTo(links[0].url);
- }
- },
},
};
</script>
<template>
- <div class="gl-display-flex gl-flex-wrap" data-testid="vsa-time-metrics">
+ <div class="gl-display-flex gl-flex-wrap" data-testid="vsa-metrics">
<gl-skeleton-loading v-if="isLoading" class="gl-h-auto gl-py-3 gl-pr-9 gl-my-6" />
- <div v-for="metric in metrics" v-show="!isLoading" :key="metric.key" class="gl-my-6 gl-pr-9">
- <gl-single-stat
- :id="metric.key"
- :value="`${metric.value}`"
- :title="metric.label"
- :unit="metric.unit || ''"
- :should-animate="true"
- :animation-decimal-places="1"
- :class="{ 'gl-hover-cursor-pointer': hasLinks(metric.links) }"
- tabindex="0"
- @click="clickHandler(metric)"
- />
- <metric-popover :metric="metric" :target="metric.key" />
- </div>
+ <metric-tile
+ v-for="metric in metrics"
+ v-show="!isLoading"
+ :key="metric.identifier"
+ :metric="metric"
+ class="gl-my-6 gl-pr-9"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js
index c06bd34f86f..2ac144ceb5e 100644
--- a/app/assets/javascripts/analytics/shared/constants.js
+++ b/app/assets/javascripts/analytics/shared/constants.js
@@ -1,4 +1,5 @@
import { masks } from 'dateformat';
+import { s__ } from '~/locale';
export const DATE_RANGE_LIMIT = 180;
export const OFFSET_DATE_BY_ONE = 1;
@@ -11,3 +12,47 @@ export const dateFormats = {
defaultDateTime: 'mmm d, yyyy h:MMtt',
month: 'mmmm',
};
+
+// Some content is duplicated due to backward compatibility.
+// It will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/350614 in 14.9
+export const METRICS_POPOVER_CONTENT = {
+ 'lead-time': {
+ description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),
+ },
+ lead_time: {
+ description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),
+ },
+ 'cycle-time': {
+ description: s__(
+ "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.",
+ ),
+ },
+ cycle_time: {
+ description: s__(
+ "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.",
+ ),
+ },
+ 'lead-time-for-changes': {
+ description: s__(
+ 'ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period.',
+ ),
+ },
+ lead_time_for_changes: {
+ description: s__(
+ 'ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period.',
+ ),
+ },
+ issues: { description: s__('ValueStreamAnalytics|Number of new issues created.') },
+ 'new-issue': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
+ 'new-issues': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
+ deploys: { description: s__('ValueStreamAnalytics|Total number of deploys to production.') },
+ 'deployment-frequency': {
+ description: s__('ValueStreamAnalytics|Average number of deployments to production per day.'),
+ },
+ deployment_frequency: {
+ description: s__('ValueStreamAnalytics|Average number of deployments to production per day.'),
+ },
+ commits: {
+ description: s__('ValueStreamAnalytics|Number of commits pushed to the default branch'),
+ },
+};
diff --git a/app/assets/javascripts/analytics/shared/utils.js b/app/assets/javascripts/analytics/shared/utils.js
index f55ef99964e..dde429ab278 100644
--- a/app/assets/javascripts/analytics/shared/utils.js
+++ b/app/assets/javascripts/analytics/shared/utils.js
@@ -1,4 +1,6 @@
import dateFormat from 'dateformat';
+import { hideFlash } from '~/flash';
+import { slugify } from '~/lib/utils/text_utility';
import { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import { dateFormats } from './constants';
@@ -69,3 +71,28 @@ export const getDataZoomOption = ({
};
});
};
+
+export const removeFlash = (type = 'alert') => {
+ const flashEl = document.querySelector(`.flash-${type}`);
+ if (flashEl) {
+ hideFlash(flashEl);
+ }
+};
+
+/**
+ * Prepares metric data to be rendered in the metric_card component
+ *
+ * @param {MetricData[]} data - The metric data to be rendered
+ * @param {Object} popoverContent - Key value pair of data to display in the popover
+ * @returns {TransformedMetricData[]} An array of metrics ready to render in the metric_card
+ */
+export const prepareTimeMetricsData = (data = [], popoverContent = {}) =>
+ data.map(({ title: label, identifier, ...rest }) => {
+ const metricIdentifier = identifier || slugify(label);
+ return {
+ ...rest,
+ label,
+ identifier: metricIdentifier,
+ description: popoverContent[metricIdentifier]?.description || '',
+ };
+ });
diff --git a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
index 2bde5973600..b353bcdfd0e 100644
--- a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
+++ b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
@@ -1,4 +1,5 @@
fragment Count on UsageTrendsMeasurement {
+ __typename
count
recordedAt
}
diff --git a/app/assets/javascripts/authentication/webauthn/util.js b/app/assets/javascripts/authentication/webauthn/util.js
index 5f06c000afe..eeda2bfaeaf 100644
--- a/app/assets/javascripts/authentication/webauthn/util.js
+++ b/app/assets/javascripts/authentication/webauthn/util.js
@@ -14,31 +14,36 @@ export function isHTTPS() {
export const FLOW_AUTHENTICATE = 'authenticate';
export const FLOW_REGISTER = 'register';
-// adapted from https://stackoverflow.com/a/21797381/8204697
-function base64ToBuffer(base64) {
- const binaryString = window.atob(base64);
- const len = binaryString.length;
- const bytes = new Uint8Array(len);
- for (let i = 0; i < len; i += 1) {
- bytes[i] = binaryString.charCodeAt(i);
- }
- return bytes.buffer;
-}
-
-// adapted from https://stackoverflow.com/a/9458996/8204697
-function bufferToBase64(buffer) {
- if (typeof buffer === 'string') {
- return buffer;
+/**
+ * Converts a base64 string to an ArrayBuffer
+ *
+ * @param {String} str - A base64 encoded string
+ * @returns {ArrayBuffer}
+ */
+export const base64ToBuffer = (str) => {
+ const rawStr = atob(str);
+ const buffer = new ArrayBuffer(rawStr.length);
+ const arr = new Uint8Array(buffer);
+ for (let i = 0; i < rawStr.length; i += 1) {
+ arr[i] = rawStr.charCodeAt(i);
}
+ return arr.buffer;
+};
- let binary = '';
- const bytes = new Uint8Array(buffer);
- const len = bytes.byteLength;
- for (let i = 0; i < len; i += 1) {
- binary += String.fromCharCode(bytes[i]);
+/**
+ * Converts ArrayBuffer to a base64-encoded string
+ *
+ * @param {ArrayBuffer, String} str -
+ * @returns {String} - ArrayBuffer to a base64-encoded string.
+ * When input is a string, returns the input as-is.
+ */
+export const bufferToBase64 = (input) => {
+ if (typeof input === 'string') {
+ return input;
}
- return window.btoa(binary);
-}
+ const arr = new Uint8Array(input);
+ return btoa(String.fromCharCode(...arr));
+};
/**
* Returns a copy of the given object with the id property converted to buffer
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 43ca5b5cf89..aa735df7da5 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -2,10 +2,10 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import Cookies from 'js-cookie';
import { uniq } from 'lodash';
+import { getCookie, setCookie, scrollToElement } from '~/lib/utils/common_utils';
import * as Emoji from '~/emoji';
-import { scrollToElement } from '~/lib/utils/common_utils';
+
import { dispose, fixTitle } from '~/tooltips';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
@@ -506,7 +506,7 @@ export class AwardsHandler {
addEmojiToFrequentlyUsedList(emoji) {
if (this.emoji.isEmojiNameValid(emoji)) {
this.frequentlyUsedEmojis = uniq(this.getFrequentlyUsedEmojis().concat(emoji));
- Cookies.set('frequently_used_emojis', this.frequentlyUsedEmojis.join(','), { expires: 365 });
+ setCookie('frequently_used_emojis', this.frequentlyUsedEmojis.join(','));
}
}
@@ -514,7 +514,7 @@ export class AwardsHandler {
return (
this.frequentlyUsedEmojis ||
(() => {
- const frequentlyUsedEmojis = uniq((Cookies.get('frequently_used_emojis') || '').split(','));
+ const frequentlyUsedEmojis = uniq((getCookie('frequently_used_emojis') || '').split(','));
this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter((inputName) =>
this.emoji.isEmojiNameValid(inputName),
);
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 53469ac8999..8bef972cc58 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -74,7 +74,14 @@ export default {
<template>
<div>
- <a v-show="!isLoading && !hasError" :href="linkUrl" target="_blank" rel="noopener noreferrer">
+ <a
+ v-show="!isLoading && !hasError"
+ :href="linkUrl"
+ target="_blank"
+ rel="noopener noreferrer"
+ data-qa-selector="badge_image_link"
+ :data-qa-link-url="linkUrl"
+ >
<img
:src="imageUrlWithRetries"
class="project-badge"
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 2c7e878f044..d1570e16639 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -182,7 +182,7 @@ export default {
@submit.prevent.stop="onSubmit"
>
<gl-form-group :label="s__('Badges|Name')" label-for="badge-name">
- <gl-form-input id="badge-name" v-model="name" />
+ <gl-form-input id="badge-name" v-model="name" data-qa-selector="badge_name_field" />
</gl-form-group>
<div class="form-group">
@@ -191,6 +191,7 @@ export default {
<input
id="badge-link-url"
v-model="linkUrl"
+ data-qa-selector="badge_link_url_field"
type="URL"
class="form-control gl-form-input"
required
@@ -206,6 +207,7 @@ export default {
<input
id="badge-image-url"
v-model="imageUrl"
+ data-qa-selector="badge_image_url_field"
type="URL"
class="form-control gl-form-input"
required
@@ -246,7 +248,13 @@ export default {
</gl-button>
</div>
<div v-else class="form-group">
- <gl-button :loading="isSaving" type="submit" variant="confirm" category="primary">
+ <gl-button
+ :loading="isSaving"
+ type="submit"
+ variant="confirm"
+ category="primary"
+ data-qa-selector="add_badge_button"
+ >
{{ s__('Badges|Add badge') }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
index 86c7b4c7a6e..76625fe9a60 100644
--- a/app/assets/javascripts/badges/components/badge_list.vue
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -34,8 +34,14 @@ export default {
<span v-if="isGroupBadge">{{ s__('Badges|This group has no badges') }}</span>
<span v-else>{{ s__('Badges|This project has no badges') }}</span>
</div>
- <div v-else class="card-body">
- <badge-list-row v-for="badge in badges" :key="badge.id" :badge="badge" />
+ <div v-else class="card-body" data-qa-selector="badge_list_content">
+ <badge-list-row
+ v-for="badge in badges"
+ :key="badge.id"
+ :badge="badge"
+ data-qa-selector="badge_list_row"
+ :data-qa-badge-name="badge.name"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index d8525c15087..4c2b700c7ff 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon, GlButton, GlModalDirective } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlModalDirective, GlBadge } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import { PROJECT_BADGE } from '../constants';
@@ -11,6 +11,7 @@ export default {
Badge,
GlLoadingIcon,
GlButton,
+ GlBadge,
},
directives: {
GlModal: GlModalDirective,
@@ -49,7 +50,7 @@ export default {
/>
<div class="table-section section-30">
<label class="label-bold str-truncated mb-0">{{ badge.name }}</label>
- <span class="badge badge-pill">{{ badgeKindText }}</span>
+ <gl-badge size="sm">{{ badgeKindText }}</gl-badge>
</div>
<span class="table-section section-30 str-truncated">{{ badge.linkUrl }}</span>
<div class="table-section section-10 table-button-footer">
diff --git a/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue b/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
index 570954c7200..2ebde10c229 100644
--- a/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
+++ b/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
@@ -1,11 +1,13 @@
<script>
import { mapGetters } from 'vuex';
import imageDiff from '~/diffs/mixins/image_diff';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
import DraftNote from './draft_note.vue';
export default {
components: {
DraftNote,
+ DesignNotePin,
},
mixins: [imageDiff],
props: {
@@ -31,9 +33,12 @@ export default {
class="discussion-notes diff-discussions position-relative"
>
<div class="notes">
- <span class="d-block btn-transparent badge badge-pill is-draft js-diff-notes-index">
- {{ toggleText(draft, index) }}
- </span>
+ <design-note-pin
+ :label="toggleText(draft, index)"
+ is-draft
+ class="js-diff-notes-index gl-translate-x-n50"
+ size="sm"
+ />
<draft-note :draft="draft" />
</div>
</div>
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index a218624f2d4..c8130c47f5b 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlSafeHtmlDirective } from '@gitlab/ui';
+import { GlButton, GlSafeHtmlDirective, GlBadge } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import NoteableNote from '~/notes/components/noteable_note.vue';
import PublishButton from './publish_button.vue';
@@ -9,6 +9,7 @@ export default {
NoteableNote,
PublishButton,
GlButton,
+ GlBadge,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
@@ -100,9 +101,7 @@ export default {
@toggleResolveStatus="toggleResolveDiscussion(draft.id)"
>
<template #note-header-info>
- <strong class="badge draft-pending-label gl-mr-2">
- {{ __('Pending') }}
- </strong>
+ <gl-badge variant="warning" class="gl-mr-2">{{ __('Pending') }}</gl-badge>
</template>
</noteable-note>
</ul>
@@ -115,10 +114,15 @@ export default {
></div>
<p class="draft-note-actions d-flex">
- <publish-button :show-count="true" :should-publish="false" category="secondary" />
+ <publish-button
+ :show-count="true"
+ :should-publish="false"
+ category="secondary"
+ :disabled="isPublishingDraft(draft.id)"
+ />
<gl-button
- ref="publishNowButton"
- :loading="isPublishingDraft(draft.id) || isPublishing"
+ :disabled="isPublishing"
+ :loading="isPublishingDraft(draft.id)"
class="gl-ml-3"
@click="publishNow"
>
diff --git a/app/assets/javascripts/behaviors/markdown/marks/bold.js b/app/assets/javascripts/behaviors/markdown/marks/bold.js
index d307edd9fd3..89e373220af 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/bold.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/bold.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Bold as BaseBold } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Bold extends BaseBold {
diff --git a/app/assets/javascripts/behaviors/markdown/marks/code.js b/app/assets/javascripts/behaviors/markdown/marks/code.js
index ccfe2cf5b8d..68368dec676 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/code.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/code.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Code as BaseCode } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Code extends BaseCode {
diff --git a/app/assets/javascripts/behaviors/markdown/marks/italic.js b/app/assets/javascripts/behaviors/markdown/marks/italic.js
index dbef10536ab..7dc86102f18 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/italic.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/italic.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Italic as BaseItalic } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Italic extends BaseItalic {
diff --git a/app/assets/javascripts/behaviors/markdown/marks/link.js b/app/assets/javascripts/behaviors/markdown/marks/link.js
index 1111c51805d..b5e09017d83 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/link.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/link.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Link as BaseLink } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Link extends BaseLink {
diff --git a/app/assets/javascripts/behaviors/markdown/marks/math.js b/app/assets/javascripts/behaviors/markdown/marks/math.js
index 382bf5c9b5b..ca25ff7d07d 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/math.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/math.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Mark } from 'tiptap';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::MathFilter
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js
index bd5868e5524..8b14a04e2fe 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Blockquote as BaseBlockquote } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Blockquote extends BaseBlockquote {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js
index 209e7239998..ef1eafaa419 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { BulletList as BaseBulletList } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class BulletList extends BaseBulletList {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/heading.js b/app/assets/javascripts/behaviors/markdown/nodes/heading.js
index 708da053a2f..29967e61ffa 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/heading.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/heading.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Heading as BaseHeading } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Heading extends BaseHeading {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js
index 47a24eae1e8..ee3aa145dc3 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class HorizontalRule extends BaseHorizontalRule {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/image.js b/app/assets/javascripts/behaviors/markdown/nodes/image.js
index 4cc28c45739..16647d2f96e 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/image.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/image.js
@@ -1,8 +1,8 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Image as BaseImage } from 'tiptap-extensions';
import { placeholderImage } from '~/lazy_loader';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
export default class Image extends BaseImage {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
index 0f56e89dca6..7204b7c09ba 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { ListItem as BaseListItem } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class ListItem extends BaseListItem {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js
index 93d00f27868..5fd098cd46f 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class Paragraph extends Node {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/playable.js b/app/assets/javascripts/behaviors/markdown/nodes/playable.js
index 2b667aba2d6..90cbaf9ef4c 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/playable.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/playable.js
@@ -1,8 +1,8 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable @gitlab/require-i18n-strings */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
/**
* Abstract base class for playable media, like video and audio.
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/text.js b/app/assets/javascripts/behaviors/markdown/nodes/text.js
index 4eab10c9d98..0dc77a12f5c 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/text.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/text.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
export default class Text extends Node {
get name() {
diff --git a/app/assets/javascripts/behaviors/markdown/serializer.js b/app/assets/javascripts/behaviors/markdown/serializer.js
index b4adf1a413f..a5f97d7748a 100644
--- a/app/assets/javascripts/behaviors/markdown/serializer.js
+++ b/app/assets/javascripts/behaviors/markdown/serializer.js
@@ -1,4 +1,4 @@
-import { MarkdownSerializer } from 'prosemirror-markdown';
+import { MarkdownSerializer } from '~/lib/prosemirror_markdown_serializer';
import editorExtensions from './editor_extensions';
const nodes = editorExtensions
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index ac2a4184176..9297b14aac9 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
-import Cookies from 'js-cookie';
import { flatten } from 'lodash';
import Mousetrap from 'mousetrap';
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
+
import findAndFollowLink from '~/lib/utils/navigation_utility';
import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility';
import {
@@ -161,10 +161,10 @@ export default class Shortcuts {
static onTogglePerfBar(e) {
e.preventDefault();
const performanceBarCookieName = 'perf_bar_enabled';
- if (parseBoolean(Cookies.get(performanceBarCookieName))) {
- Cookies.set(performanceBarCookieName, 'false', { expires: 365, path: '/' });
+ if (parseBoolean(getCookie(performanceBarCookieName))) {
+ setCookie(performanceBarCookieName, 'false', { path: '/' });
} else {
- Cookies.set(performanceBarCookieName, 'true', { expires: 365, path: '/' });
+ setCookie(performanceBarCookieName, 'true', { path: '/' });
}
refreshCurrentPage();
}
@@ -172,8 +172,13 @@ export default class Shortcuts {
static onToggleCanary(e) {
e.preventDefault();
const canaryCookieName = 'gitlab_canary';
- const currentValue = parseBoolean(Cookies.get(canaryCookieName));
- Cookies.set(canaryCookieName, (!currentValue).toString(), { expires: 365, path: '/' });
+ const currentValue = parseBoolean(getCookie(canaryCookieName));
+ setCookie(canaryCookieName, (!currentValue).toString(), {
+ expires: 365,
+ path: '/',
+ // next.gitlab.com uses a leading period. See https://gitlab.com/gitlab-org/gitlab/-/issues/350186
+ domain: `.${window.location.hostname}`,
+ });
refreshCurrentPage();
}
diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue
index 1645469a218..c5ab28e6ec5 100644
--- a/app/assets/javascripts/blob/components/blob_header.vue
+++ b/app/assets/javascripts/blob/components/blob_header.vue
@@ -42,6 +42,11 @@ export default {
required: false,
default: false,
},
+ showPath: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
return {
@@ -55,6 +60,9 @@ export default {
showDefaultActions() {
return !this.hideDefaultActions;
},
+ isEmpty() {
+ return this.blob.rawSize === 0;
+ },
},
watch: {
viewer(newVal, oldVal) {
@@ -74,7 +82,7 @@ export default {
<div class="js-file-title file-title-flex-parent">
<div class="gl-display-flex">
<table-of-contents class="gl-pr-2" />
- <blob-filepath :blob="blob">
+ <blob-filepath :blob="blob" :show-path="showPath">
<template #filepath-prepend>
<slot name="prepend"></slot>
</template>
@@ -88,10 +96,13 @@ export default {
<default-actions
v-if="showDefaultActions"
- :raw-path="blob.rawPath"
+ :raw-path="blob.externalStorageUrl || blob.rawPath"
:active-viewer="viewer"
:has-render-error="hasRenderError"
:is-binary="isBinary"
+ :environment-name="blob.environmentFormattedExternalUrl"
+ :environment-path="blob.environmentExternalUrlForRouteMap"
+ :is-empty="isEmpty"
@copy="proxyCopyRequest"
/>
</div>
diff --git a/app/assets/javascripts/blob/components/blob_header_default_actions.vue b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
index 2798a918b15..12bcb24b0cc 100644
--- a/app/assets/javascripts/blob/components/blob_header_default_actions.vue
+++ b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
@@ -1,5 +1,6 @@
<script>
import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
import {
BTN_COPY_CONTENTS_TITLE,
BTN_DOWNLOAD_TITLE,
@@ -37,6 +38,21 @@ export default {
required: false,
default: false,
},
+ environmentName: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ environmentPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ isEmpty: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
downloadUrl() {
@@ -51,6 +67,11 @@ export default {
showCopyButton() {
return !this.hasRenderError && !this.isBinary;
},
+ environmentTitle() {
+ return sprintf(s__('BlobViewer|View on %{environmentName}'), {
+ environmentName: this.environmentName,
+ });
+ },
},
BTN_COPY_CONTENTS_TITLE,
BTN_DOWNLOAD_TITLE,
@@ -71,6 +92,7 @@ export default {
icon="copy-to-clipboard"
category="primary"
variant="default"
+ class="js-copy-blob-source-btn"
/>
<gl-button
v-if="!isBinary"
@@ -84,6 +106,7 @@ export default {
variant="default"
/>
<gl-button
+ v-if="!isEmpty"
v-gl-tooltip.hover
:aria-label="$options.BTN_DOWNLOAD_TITLE"
:title="$options.BTN_DOWNLOAD_TITLE"
@@ -93,5 +116,17 @@ export default {
category="primary"
variant="default"
/>
+ <gl-button
+ v-if="environmentName && environmentPath"
+ v-gl-tooltip.hover
+ :aria-label="environmentTitle"
+ :title="environmentTitle"
+ :href="environmentPath"
+ data-testid="environment"
+ target="_blank"
+ icon="external-link"
+ category="primary"
+ variant="default"
+ />
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/blob/components/blob_header_filepath.vue b/app/assets/javascripts/blob/components/blob_header_filepath.vue
index 90d01358451..62355306655 100644
--- a/app/assets/javascripts/blob/components/blob_header_filepath.vue
+++ b/app/assets/javascripts/blob/components/blob_header_filepath.vue
@@ -15,6 +15,11 @@ export default {
type: Object,
required: true,
},
+ showPath: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
blobSize() {
@@ -26,6 +31,13 @@ export default {
showLfsBadge() {
return this.blob.storedExternally && this.blob.externalStorage === 'lfs';
},
+ fileName() {
+ if (this.showPath) {
+ return this.blob.path;
+ }
+
+ return this.blob.name;
+ },
},
};
</script>
@@ -33,12 +45,12 @@ export default {
<div class="file-header-content d-flex align-items-center lh-100">
<slot name="filepath-prepend"></slot>
- <template v-if="blob.path">
- <file-icon :file-name="blob.path" :size="16" aria-hidden="true" css-classes="mr-2" />
+ <template v-if="fileName">
+ <file-icon :file-name="fileName" :size="16" aria-hidden="true" css-classes="mr-2" />
<strong
class="file-title-name mr-1 js-blob-header-filepath"
data-qa-selector="file_title_content"
- >{{ blob.path }}</strong
+ >{{ fileName }}</strong
>
</template>
diff --git a/app/assets/javascripts/blob/components/constants.js b/app/assets/javascripts/blob/components/constants.js
index a129c537fa5..adac4d6408d 100644
--- a/app/assets/javascripts/blob/components/constants.js
+++ b/app/assets/javascripts/blob/components/constants.js
@@ -42,7 +42,7 @@ export const BLOB_RENDER_ERRORS = {
id: 'load',
text: __('load it anyway'),
conjunction: __('or'),
- href: '#',
+ href: '?expanded=true&viewer=simple',
target: '',
event: BLOB_RENDER_EVENT_LOAD,
},
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index 47a0c4ba2d1..b4ca29114cb 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
-import Cookies from 'js-cookie';
+import { getCookie, removeCookie } from '~/lib/utils/common_utils';
import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
@@ -62,7 +62,7 @@ export default {
return this.commitCookiePath || this.projectMergeRequestsPath;
},
commitCookiePath() {
- const cookieVal = Cookies.get(this.commitCookie);
+ const cookieVal = getCookie(this.commitCookie);
if (cookieVal !== 'true') return cookieVal;
return '';
@@ -85,7 +85,7 @@ export default {
},
methods: {
disableModalFromRenderingAgain() {
- Cookies.remove(this.commitCookie);
+ removeCookie(this.commitCookie);
},
},
};
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index ea80496c3f5..aee61a5b2a5 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -11,12 +11,10 @@ import { sortBy } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
import { isScopedLabel } from '~/lib/utils/common_utils';
-import { updateHistory } from '~/lib/utils/url_utility';
import { sprintf, __, n__ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { ListType } from '../constants';
-import eventHub from '../eventhub';
import BoardBlockedIcon from './board_blocked_icon.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
@@ -176,18 +174,10 @@ export default {
)
);
},
- filterByLabel(label) {
- if (!this.updateFilters) return;
+ labelTarget(label) {
const filterPath = window.location.search ? `${window.location.search}&` : '?';
- const filter = `label_name[]=${encodeURIComponent(label.title)}`;
-
- if (!filterPath.includes(filter)) {
- updateHistory({
- url: `${filterPath}${filter}`,
- });
- this.performSearch();
- eventHub.$emit('updateTokens');
- }
+ const value = encodeURIComponent(label.title);
+ return `${filterPath}label_name[]=${value}`;
},
showScopedLabel(label) {
return this.scopedLabelsAvailable && isScopedLabel(label);
@@ -242,7 +232,7 @@ export default {
:description="label.description"
size="sm"
:scoped="showScopedLabel(label)"
- @click="filterByLabel(label)"
+ :target="labelTarget(label)"
/>
</template>
</div>
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index 156029b62b0..0320b4d925e 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -184,29 +184,15 @@ export default {
:issuable-type="issuableType"
data-testid="sidebar-milestones"
/>
- <template v-if="!glFeatures.iterationCadences">
- <sidebar-dropdown-widget
- v-if="iterationFeatureAvailable && !isIncidentSidebar"
- :iid="activeBoardItem.iid"
- issuable-attribute="iteration"
- :workspace-path="projectPathForActiveIssue"
- :attr-workspace-path="groupPathForActiveIssue"
- :issuable-type="issuableType"
- class="gl-mt-5"
- data-testid="iteration-edit"
- />
- </template>
- <template v-else>
- <iteration-sidebar-dropdown-widget
- v-if="iterationFeatureAvailable && !isIncidentSidebar"
- :iid="activeBoardItem.iid"
- :workspace-path="projectPathForActiveIssue"
- :attr-workspace-path="groupPathForActiveIssue"
- :issuable-type="issuableType"
- class="gl-mt-5"
- data-testid="iteration-edit"
- />
- </template>
+ <iteration-sidebar-dropdown-widget
+ v-if="iterationFeatureAvailable && !isIncidentSidebar"
+ :iid="activeBoardItem.iid"
+ :workspace-path="projectPathForActiveIssue"
+ :attr-workspace-path="groupPathForActiveIssue"
+ :issuable-type="issuableType"
+ class="gl-mt-5"
+ data-testid="iteration-edit"
+ />
</div>
<board-sidebar-time-tracker />
<sidebar-date-widget
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index 2599d1c80b8..45192b5304a 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -1,5 +1,5 @@
<script>
-import { pickBy, isEmpty } from 'lodash';
+import { pickBy, isEmpty, mapValues } from 'lodash';
import { mapActions } from 'vuex';
import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
@@ -251,22 +251,36 @@ export default {
);
}
- return {
- ...notParams,
- author_username: authorUsername,
- 'label_name[]': labelName,
- assignee_username: assigneeUsername,
- assignee_id: assigneeId,
- milestone_title: milestoneTitle,
- iteration_id: iterationId,
- search,
- types,
- weight,
- epic_id: isGid(epicId) ? getIdFromGraphQLId(epicId) : epicId,
- my_reaction_emoji: myReactionEmoji,
- release_tag: releaseTag,
- confidential,
- };
+ return mapValues(
+ {
+ ...notParams,
+ author_username: authorUsername,
+ 'label_name[]': labelName,
+ assignee_username: assigneeUsername,
+ assignee_id: assigneeId,
+ milestone_title: milestoneTitle,
+ iteration_id: iterationId,
+ search,
+ types,
+ weight,
+ epic_id: isGid(epicId) ? getIdFromGraphQLId(epicId) : epicId,
+ my_reaction_emoji: myReactionEmoji,
+ release_tag: releaseTag,
+ confidential,
+ },
+ (value) => {
+ if (value || value === false) {
+ // note: need to check array for labels.
+ if (Array.isArray(value)) {
+ return value.map((valueItem) => encodeURIComponent(valueItem));
+ }
+
+ return encodeURIComponent(value);
+ }
+
+ return value;
+ },
+ );
},
},
created() {
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 6ad57fd8985..cc048e2af1a 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -98,9 +98,6 @@ export default {
return this.$options.i18n[this.currentPage].btnText;
},
buttonKind() {
- if (this.isNewForm) {
- return 'success';
- }
if (this.isDeleteForm) {
return 'danger';
}
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index e4c3c3206a8..1024be61359 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -60,6 +60,9 @@ export default {
filters: this.filterParams,
};
},
+ skip() {
+ return this.isEpicBoard;
+ },
},
},
computed: {
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 84c9191975e..8db366e4995 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -25,7 +25,7 @@ export default {
},
computed: {
...mapState(['selectedProject', 'fullPath']),
- ...mapGetters(['isGroupBoard']),
+ ...mapGetters(['isGroupBoard', 'getBoardItemsByList']),
formEventPrefix() {
return toggleFormEventPrefix.issue;
},
@@ -42,6 +42,7 @@ export default {
const labels = this.list.label ? [this.list.label] : [];
const assignees = this.list.assignee ? [this.list.assignee] : [];
const milestone = getMilestone(this.list);
+ const firstItemId = this.getBoardItemsByList(this.list.id)[0]?.id;
return this.addListNewIssue({
list: this.list,
@@ -51,6 +52,7 @@ export default {
assigneeIds: assignees?.map((a) => a?.id),
milestoneId: milestone?.id,
projectPath: this.projectPath,
+ moveAfterId: firstItemId,
},
}).then(() => {
this.cancel();
diff --git a/app/assets/javascripts/boards/components/board_new_item.vue b/app/assets/javascripts/boards/components/board_new_item.vue
index 44574de17d7..600917683cd 100644
--- a/app/assets/javascripts/boards/components/board_new_item.vue
+++ b/app/assets/javascripts/boards/components/board_new_item.vue
@@ -43,6 +43,12 @@ export default {
// eslint-disable-next-line @gitlab/require-i18n-strings
return `${this.list.id}-title`;
},
+ isIssueTitleEmpty() {
+ return this.title.trim() === '';
+ },
+ isCreatingIssueDisabled() {
+ return this.isIssueTitleEmpty || this.disableSubmit;
+ },
},
methods: {
handleFormCancel() {
@@ -54,7 +60,7 @@ export default {
eventHub.$emit(`scroll-board-list-${this.list.id}`);
this.$emit('form-submit', {
- title,
+ title: title.trim(),
list,
});
},
@@ -69,7 +75,7 @@ export default {
<label :for="inputFieldId" class="gl-font-weight-bold">{{ __('Title') }}</label>
<gl-form-input
:id="inputFieldId"
- v-model.trim="title"
+ v-model="title"
:autofocus="true"
autocomplete="off"
type="text"
@@ -78,7 +84,8 @@ export default {
<slot></slot>
<div class="gl-clearfix gl-mt-4">
<gl-button
- :disabled="!title || disableSubmit"
+ data-testid="create-button"
+ :disabled="isCreatingIssueDisabled"
class="gl-float-left js-no-auto-disable"
variant="confirm"
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 6b7c08d05a5..24071c6f0b4 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlDrawer, GlLabel } from '@gitlab/ui';
+import { GlButton, GlDrawer, GlLabel, GlModal, GlModalDirective } from '@gitlab/ui';
import { MountingPortal } from 'portal-vue';
import { mapActions, mapState, mapGetters } from 'vuex';
import { LIST, ListType, ListTypeTitles } from '~/boards/constants';
@@ -11,8 +11,14 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
listSettingsText: __('List settings'),
+ i18n: {
+ modalAction: __('Remove list'),
+ modalCopy: __('Are you sure you want to remove this list?'),
+ modalCancel: __('Cancel'),
+ },
components: {
GlButton,
+ GlModal,
GlDrawer,
GlLabel,
MountingPortal,
@@ -21,6 +27,9 @@ export default {
BoardSettingsListTypes: () =>
import('ee_component/boards/components/board_settings_list_types.vue'),
},
+ directives: {
+ GlModal: GlModalDirective,
+ },
mixins: [glFeatureFlagMixin(), Tracking.mixin()],
inject: ['canAdminList', 'scopedLabelsAvailable'],
inheritAttrs: false,
@@ -29,6 +38,7 @@ export default {
ListType,
};
},
+ modalId: 'board-settings-sidebar-modal',
computed: {
...mapGetters(['isSidebarOpen', 'isEpicBoard']),
...mapState(['activeId', 'sidebarType', 'boardLists']),
@@ -59,16 +69,16 @@ export default {
},
methods: {
...mapActions(['unsetActiveId', 'removeList']),
+ handleModalPrimary() {
+ this.deleteBoard();
+ },
showScopedLabels(label) {
return this.scopedLabelsAvailable && isScopedLabel(label);
},
deleteBoard() {
- // eslint-disable-next-line no-alert
- if (window.confirm(__('Are you sure you want to remove this list?'))) {
- this.track('click_button', { label: 'remove_list' });
- this.removeList(this.activeId);
- this.unsetActiveId();
- }
+ this.track('click_button', { label: 'remove_list' });
+ this.removeList(this.activeId);
+ this.unsetActiveId();
},
},
};
@@ -92,11 +102,10 @@ export default {
<template #header>
<div v-if="canAdminList && activeList.id" class="gl-mt-3">
<gl-button
+ v-gl-modal="$options.modalId"
variant="danger"
category="secondary"
size="small"
- data-testid="remove-list"
- @click.stop="deleteBoard"
>{{ __('Remove list') }}
</gl-button>
</div>
@@ -122,5 +131,21 @@ export default {
/>
</template>
</gl-drawer>
+ <gl-modal
+ :modal-id="$options.modalId"
+ :title="$options.i18n.modalAction"
+ size="sm"
+ :action-primary="{
+ text: $options.i18n.modalAction,
+ attributes: [{ variant: 'danger' }],
+ }"
+ :action-secondary="{
+ text: $options.i18n.modalCancel,
+ attributes: [{ variant: 'default' }],
+ }"
+ @primary="handleModalPrimary"
+ >
+ <p>{{ $options.i18n.modalCopy }}</p>
+ </gl-modal>
</mounting-portal>
</template>
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 69343cd78d8..6dbb1ea0050 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -14,8 +14,6 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import BoardForm from 'ee_else_ce/boards/components/board_form.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
import { s__ } from '~/locale';
import eventHub from '../eventhub';
@@ -23,6 +21,8 @@ import groupBoardsQuery from '../graphql/group_boards.query.graphql';
import projectBoardsQuery from '../graphql/project_boards.query.graphql';
import groupBoardQuery from '../graphql/group_board.query.graphql';
import projectBoardQuery from '../graphql/project_board.query.graphql';
+import groupRecentBoardsQuery from '../graphql/group_recent_boards.query.graphql';
+import projectRecentBoardsQuery from '../graphql/project_recent_boards.query.graphql';
const MIN_BOARDS_TO_VIEW_RECENT = 10;
@@ -40,7 +40,7 @@ export default {
directives: {
GlModalDirective,
},
- inject: ['fullPath', 'recentBoardsEndpoint'],
+ inject: ['fullPath'],
props: {
throttleDuration: {
type: Number,
@@ -158,6 +158,10 @@ export default {
this.scrollFadeInitialized = false;
this.$nextTick(this.setScrollFade);
},
+ recentBoards() {
+ this.scrollFadeInitialized = false;
+ this.$nextTick(this.setScrollFade);
+ },
},
created() {
eventHub.$on('showBoardModal', this.showPage);
@@ -173,11 +177,11 @@ export default {
cancel() {
this.showPage('');
},
- boardUpdate(data) {
+ boardUpdate(data, boardType) {
if (!data?.[this.parentType]) {
return [];
}
- return data[this.parentType].boards.edges.map(({ node }) => ({
+ return data[this.parentType][boardType].edges.map(({ node }) => ({
id: getIdFromGraphQLId(node.id),
name: node.name,
}));
@@ -185,6 +189,9 @@ export default {
boardQuery() {
return this.isGroupBoard ? groupBoardsQuery : projectBoardsQuery;
},
+ recentBoardsQuery() {
+ return this.isGroupBoard ? groupRecentBoardsQuery : projectRecentBoardsQuery;
+ },
loadBoards(toggleDropdown = true) {
if (toggleDropdown && this.boards.length > 0) {
return;
@@ -196,39 +203,20 @@ export default {
},
query: this.boardQuery,
loadingKey: 'loadingBoards',
- update: this.boardUpdate,
+ update: (data) => this.boardUpdate(data, 'boards'),
});
this.loadRecentBoards();
},
loadRecentBoards() {
- this.loadingRecentBoards = true;
- // Follow up to fetch recent boards using GraphQL
- // https://gitlab.com/gitlab-org/gitlab/-/issues/300985
- axios
- .get(this.recentBoardsEndpoint)
- .then((res) => {
- this.recentBoards = res.data;
- })
- .catch((err) => {
- /**
- * If user is unauthorized we'd still want to resolve the
- * request to display all boards.
- */
- if (err?.response?.status === httpStatusCodes.UNAUTHORIZED) {
- this.recentBoards = []; // recent boards are empty
- return;
- }
- throw err;
- })
- .then(() => this.$nextTick()) // Wait for boards list in DOM
- .then(() => {
- this.setScrollFade();
- })
- .catch(() => {})
- .finally(() => {
- this.loadingRecentBoards = false;
- });
+ this.$apollo.addSmartQuery('recentBoards', {
+ variables() {
+ return { fullPath: this.fullPath };
+ },
+ query: this.recentBoardsQuery,
+ loadingKey: 'loadingRecentBoards',
+ update: (data) => this.boardUpdate(data, 'recentIssueBoards'),
+ });
},
isScrolledUp() {
const { content } = this.$refs;
diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
index 7fc87f9f672..6bfdbb674a2 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -157,6 +157,7 @@ export default {
symbol: '%',
token: MilestoneToken,
unique: true,
+ shouldSkipSort: true,
fetchMilestones: this.fetchMilestones,
},
{
diff --git a/app/assets/javascripts/boards/config_toggle.js b/app/assets/javascripts/boards/config_toggle.js
index 945a508c55d..1e54c2511b8 100644
--- a/app/assets/javascripts/boards/config_toggle.js
+++ b/app/assets/javascripts/boards/config_toggle.js
@@ -12,6 +12,7 @@ export default () => {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'ConfigToggleRoot',
render(h) {
return h(ConfigToggle, {
props: {
diff --git a/app/assets/javascripts/boards/graphql.js b/app/assets/javascripts/boards/graphql.js
index 64938cb42ed..95863d4d5ac 100644
--- a/app/assets/javascripts/boards/graphql.js
+++ b/app/assets/javascripts/boards/graphql.js
@@ -1,10 +1,5 @@
-import { IntrospectionFragmentMatcher, defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import { defaultDataIdFromObject } from '@apollo/client/core';
import createDefaultClient from '~/lib/graphql';
-import introspectionQueryResultData from '~/sidebar/fragmentTypes.json';
-
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
export const gqlClient = createDefaultClient(
{},
@@ -14,8 +9,6 @@ export const gqlClient = createDefaultClient(
// eslint-disable-next-line no-underscore-dangle
return object.__typename === 'BoardList' ? object.iid : defaultDataIdFromObject(object);
},
-
- fragmentMatcher,
},
},
);
diff --git a/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql b/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
index 6fe8bb799d6..9e6c26063e9 100644
--- a/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
@@ -1,7 +1,12 @@
query GroupBoardMilestones($fullPath: ID!, $searchTerm: String, $state: MilestoneStateEnum) {
group(fullPath: $fullPath) {
id
- milestones(includeAncestors: true, searchTitle: $searchTerm, state: $state) {
+ milestones(
+ includeAncestors: true
+ searchTitle: $searchTerm
+ state: $state
+ sort: EXPIRED_LAST_DUE_DATE_ASC
+ ) {
nodes {
id
title
diff --git a/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql b/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql
new file mode 100644
index 00000000000..827c08486b1
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql
@@ -0,0 +1,14 @@
+#import "ee_else_ce/boards/graphql/board.fragment.graphql"
+
+query group_recent_boards($fullPath: ID!) {
+ group(fullPath: $fullPath) {
+ id
+ recentIssueBoards {
+ edges {
+ node {
+ ...BoardFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql b/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
index d917c7e809d..02aa08f90ef 100644
--- a/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
@@ -1,7 +1,12 @@
query ProjectBoardMilestones($fullPath: ID!, $searchTerm: String, $state: MilestoneStateEnum) {
project(fullPath: $fullPath) {
id
- milestones(searchTitle: $searchTerm, includeAncestors: true, state: $state) {
+ milestones(
+ searchTitle: $searchTerm
+ includeAncestors: true
+ state: $state
+ sort: EXPIRED_LAST_DUE_DATE_ASC
+ ) {
nodes {
id
title
diff --git a/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql b/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql
new file mode 100644
index 00000000000..4d38e9b0498
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql
@@ -0,0 +1,14 @@
+#import "ee_else_ce/boards/graphql/board.fragment.graphql"
+
+query project_recent_boards($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ id
+ recentIssueBoards {
+ edges {
+ node {
+ ...BoardFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index ded3bfded86..f6073f9d981 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -64,6 +64,7 @@ function mountBoardApp(el) {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'BoardAppRoot',
store,
apolloProvider,
provide: {
@@ -121,6 +122,7 @@ export default () => {
// eslint-disable-next-line no-new
new Vue({
el: createColumnTriggerEl,
+ name: 'BoardAddNewColumnTriggerRoot',
components: {
BoardAddNewColumnTrigger,
},
@@ -144,7 +146,6 @@ export default () => {
mountMultipleBoardsSwitcher({
fullPath: $boardApp.dataset.fullPath,
rootPath: $boardApp.dataset.boardsEndpoint,
- recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
allowScopedLabels: $boardApp.dataset.scopedLabels,
labelsManagePath: $boardApp.dataset.labelsManagePath,
});
diff --git a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
index a8ade58e316..327fb9ba8d7 100644
--- a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
+++ b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
@@ -18,6 +18,7 @@ export default (apolloProvider, isSignedIn, releasesFetchPath) => {
return new Vue({
el,
+ name: 'BoardFilteredSearchRoot',
provide: {
initialFilterParams,
isSignedIn,
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index ed32579a9c3..0bc9cfbd867 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -1,27 +1,14 @@
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
import store from '~/boards/stores';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
-import introspectionQueryResultData from '~/sidebar/fragmentTypes.json';
Vue.use(VueApollo);
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
-
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- cacheConfig: {
- fragmentMatcher,
- },
- },
- ),
+ defaultClient: createDefaultClient(),
});
export default (params = {}) => {
@@ -29,6 +16,7 @@ export default (params = {}) => {
const { dataset } = boardsSwitcherElement;
return new Vue({
el: boardsSwitcherElement,
+ name: 'BoardsSelectorRoot',
components: {
BoardsSelector,
},
@@ -37,7 +25,6 @@ export default (params = {}) => {
provide: {
fullPath: params.fullPath,
rootPath: params.rootPath,
- recentBoardsEndpoint: params.recentBoardsEndpoint,
allowScopedLabels: params.allowScopedLabels,
labelsManagePath: params.labelsManagePath,
allowLabelCreate: parseBoolean(dataset.canAdminBoard),
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 48ca3239cfd..1ebfcfc331b 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -15,7 +15,6 @@ import {
FilterFields,
ListTypeTitles,
DraggableItemTypes,
- active,
} from 'ee_else_ce/boards/constants';
import {
formatIssueInput,
@@ -210,7 +209,6 @@ export default {
const variables = {
fullPath,
searchTerm,
- state: active,
};
let query;
diff --git a/app/assets/javascripts/boards/toggle_focus.js b/app/assets/javascripts/boards/toggle_focus.js
index 0a230f72dcc..8f057e192dd 100644
--- a/app/assets/javascripts/boards/toggle_focus.js
+++ b/app/assets/javascripts/boards/toggle_focus.js
@@ -6,6 +6,7 @@ export default () => {
return new Vue({
el: '#js-toggle-focus-btn',
+ name: 'ToggleFocusRoot',
render(h) {
return h(ToggleFocus, {
props: {
diff --git a/app/assets/javascripts/broadcast_notification.js b/app/assets/javascripts/broadcast_notification.js
index 2cf2e922f68..34282c6932e 100644
--- a/app/assets/javascripts/broadcast_notification.js
+++ b/app/assets/javascripts/broadcast_notification.js
@@ -1,4 +1,4 @@
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
const handleOnDismiss = ({ currentTarget }) => {
currentTarget.removeEventListener('click', handleOnDismiss);
@@ -6,7 +6,7 @@ const handleOnDismiss = ({ currentTarget }) => {
dataset: { id, expireDate },
} = currentTarget;
- Cookies.set(`hide_broadcast_message_${id}`, true, { expires: new Date(expireDate) });
+ setCookie(`hide_broadcast_message_${id}`, true, { expires: new Date(expireDate) });
const notification = document.querySelector(`.js-broadcast-notification-${id}`);
notification.parentNode.removeChild(notification);
diff --git a/app/assets/javascripts/captcha/apollo_captcha_link.js b/app/assets/javascripts/captcha/apollo_captcha_link.js
index e49abc10b29..d63ffaf5f1a 100644
--- a/app/assets/javascripts/captcha/apollo_captcha_link.js
+++ b/app/assets/javascripts/captcha/apollo_captcha_link.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
export const apolloCaptchaLink = new ApolloLink((operation, forward) =>
forward(operation).flatMap((result) => {
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
index e630ce71bd3..2e198c59926 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
@@ -14,8 +14,8 @@ import {
GlModal,
GlSprintf,
} from '@gitlab/ui';
-import Cookies from 'js-cookie';
import { mapActions, mapState } from 'vuex';
+import { getCookie, setCookie } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -59,7 +59,7 @@ export default {
mixins: [glFeatureFlagsMixin(), trackingMixin],
data() {
return {
- isTipDismissed: Cookies.get(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
+ isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
validationErrorEventProperty: '',
};
},
@@ -176,7 +176,7 @@ export default {
'setVariableProtected',
]),
dismissTip() {
- Cookies.set(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
+ setCookie(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
this.isTipDismissed = true;
},
deleteVarAndClose() {
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
index 9c0ffab7f6b..61636b389da 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -3,6 +3,7 @@ import { GlTable, GlButton, GlModalDirective, GlIcon, GlTooltipDirective } from
import { mapState, mapActions } from 'vuex';
import { s__, __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { ADD_CI_VARIABLE_MODAL_ID } from '../constants';
import CiVariablePopover from './ci_variable_popover.vue';
@@ -52,10 +53,11 @@ export default {
},
],
components: {
- GlTable,
+ CiVariablePopover,
GlButton,
GlIcon,
- CiVariablePopover,
+ GlTable,
+ TooltipOnTruncate,
},
directives: {
GlModalDirective,
@@ -67,8 +69,8 @@ export default {
valuesButtonText() {
return this.valuesHidden ? __('Reveal values') : __('Hide values');
},
- tableIsNotEmpty() {
- return this.variables && this.variables.length > 0;
+ isTableEmpty() {
+ return !this.variables || this.variables.length === 0;
},
fields() {
return this.$options.fields;
@@ -103,12 +105,14 @@ export default {
<col v-for="field in scope.fields" :key="field.key" :style="field.customStyle" />
</template>
<template #cell(key)="{ item }">
- <div class="gl-display-flex truncated-container gl-align-items-center">
- <span
- :id="`ci-variable-key-${item.id}`"
- class="gl-display-inline-block gl-max-w-full gl-text-truncate"
- >{{ item.key }}</span
- >
+ <div class="gl-display-flex gl-align-items-center">
+ <tooltip-on-truncate :title="item.key" truncate-target="child">
+ <span
+ :id="`ci-variable-key-${item.id}`"
+ class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ >{{ item.key }}</span
+ >
+ </tooltip-on-truncate>
<gl-button
v-gl-tooltip
category="tertiary"
@@ -120,7 +124,7 @@ export default {
</div>
</template>
<template #cell(value)="{ item }">
- <div class="gl-display-flex gl-align-items-center truncated-container">
+ <div class="gl-display-flex gl-align-items-center">
<span v-if="valuesHidden">*********************</span>
<span
v-else
@@ -147,10 +151,12 @@ export default {
<gl-icon v-else :size="$options.iconSize" :name="$options.falseIcon" />
</template>
<template #cell(environment_scope)="{ item }">
- <div class="d-flex truncated-container">
- <span :id="`ci-variable-env-${item.id}`" class="d-inline-block mw-100 text-truncate">{{
- item.environment_scope
- }}</span>
+ <div class="gl-display-flex">
+ <span
+ :id="`ci-variable-env-${item.id}`"
+ class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ >{{ item.environment_scope }}</span
+ >
<ci-variable-popover
:target="`ci-variable-env-${item.id}`"
:value="item.environment_scope"
@@ -160,7 +166,6 @@ export default {
</template>
<template #cell(actions)="{ item }">
<gl-button
- ref="edit-ci-variable"
v-gl-modal-directive="$options.modalId"
icon="pencil"
:aria-label="__('Edit')"
@@ -169,17 +174,16 @@ export default {
/>
</template>
<template #empty>
- <p ref="empty-variables" class="text-center empty-variables text-plain">
+ <p class="gl-text-center gl-py-6 gl-text-black-normal gl-mb-0">
{{ __('There are no variables yet.') }}
</p>
</template>
</gl-table>
<div
class="ci-variable-actions gl-display-flex"
- :class="{ 'justify-content-center': !tableIsNotEmpty }"
+ :class="{ 'gl-justify-content-center': isTableEmpty }"
>
<gl-button
- ref="add-ci-variable"
v-gl-modal-directive="$options.modalId"
class="gl-mr-3"
data-qa-selector="add_ci_variable_button"
@@ -188,8 +192,7 @@ export default {
>{{ __('Add variable') }}</gl-button
>
<gl-button
- v-if="tableIsNotEmpty"
- ref="secret-value-reveal-button"
+ v-if="!isTableEmpty"
data-qa-selector="reveal_ci_variable_value_button"
@click="toggleValues(!valuesHidden)"
>{{ valuesButtonText }}</gl-button
diff --git a/app/assets/javascripts/clusters/agents/components/show.vue b/app/assets/javascripts/clusters/agents/components/show.vue
index a53bba6992d..63f068a9327 100644
--- a/app/assets/javascripts/clusters/agents/components/show.vue
+++ b/app/assets/javascripts/clusters/agents/components/show.vue
@@ -10,7 +10,7 @@ import {
} from '@gitlab/ui';
import { s__, __ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { MAX_LIST_COUNT } from '../constants';
+import { MAX_LIST_COUNT, TOKEN_STATUS_ACTIVE } from '../constants';
import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
import TokenTable from './token_table.vue';
import ActivityEvents from './activity_events_list.vue';
@@ -30,6 +30,7 @@ export default {
return {
agentName: this.agentName,
projectPath: this.projectPath,
+ tokenStatus: TOKEN_STATUS_ACTIVE,
...this.cursor,
};
},
diff --git a/app/assets/javascripts/clusters/agents/constants.js b/app/assets/javascripts/clusters/agents/constants.js
index 315c7662755..98d4707b4de 100644
--- a/app/assets/javascripts/clusters/agents/constants.js
+++ b/app/assets/javascripts/clusters/agents/constants.js
@@ -36,3 +36,4 @@ export const EVENT_DETAILS = {
};
export const DEFAULT_ICON = 'token';
+export const TOKEN_STATUS_ACTIVE = 'ACTIVE';
diff --git a/app/assets/javascripts/clusters/agents/graphql/provider.js b/app/assets/javascripts/clusters/agents/graphql/provider.js
index 8b068fa1eee..9153c5252b3 100644
--- a/app/assets/javascripts/clusters/agents/graphql/provider.js
+++ b/app/assets/javascripts/clusters/agents/graphql/provider.js
@@ -1,25 +1,10 @@
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import { vulnerabilityLocationTypes } from '~/graphql_shared/fragment_types/vulnerability_location_types';
Vue.use(VueApollo);
-// We create a fragment matcher so that we can create a fragment from an interface
-// Without this, Apollo throws a heuristic fragment matcher warning
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData: vulnerabilityLocationTypes,
-});
-
-const defaultClient = createDefaultClient(
- {},
- {
- cacheConfig: {
- fragmentMatcher,
- },
- },
-);
+const defaultClient = createDefaultClient();
export default new VueApollo({
defaultClient,
diff --git a/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql b/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
index 3662e925261..3610662afc0 100644
--- a/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
+++ b/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
@@ -4,6 +4,7 @@
query getClusterAgent(
$projectPath: ID!
$agentName: String!
+ $tokenStatus: AgentTokenStatus!
$first: Int
$last: Int
$afterToken: String
@@ -20,7 +21,13 @@ query getClusterAgent(
name
}
- tokens(first: $first, last: $last, before: $beforeToken, after: $afterToken) {
+ tokens(
+ status: $tokenStatus
+ first: $first
+ last: $last
+ before: $beforeToken
+ after: $afterToken
+ ) {
count
nodes {
diff --git a/app/assets/javascripts/clusters/agents/index.js b/app/assets/javascripts/clusters/agents/index.js
index 6c7fae274f8..ba7b3edba72 100644
--- a/app/assets/javascripts/clusters/agents/index.js
+++ b/app/assets/javascripts/clusters/agents/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import AgentShowPage from 'ee_else_ce/clusters/agents/components/show.vue';
import apolloProvider from './graphql/provider';
+import createRouter from './router';
export default () => {
const el = document.querySelector('#js-cluster-agent-details');
@@ -9,14 +10,22 @@ export default () => {
return null;
}
- const { activityEmptyStateImage, agentName, emptyStateSvgPath, projectPath } = el.dataset;
+ const {
+ activityEmptyStateImage,
+ agentName,
+ canAdminVulnerability,
+ emptyStateSvgPath,
+ projectPath,
+ } = el.dataset;
return new Vue({
el,
apolloProvider,
+ router: createRouter(),
provide: {
activityEmptyStateImage,
agentName,
+ canAdminVulnerability,
emptyStateSvgPath,
projectPath,
},
diff --git a/app/assets/javascripts/clusters/agents/router.js b/app/assets/javascripts/clusters/agents/router.js
new file mode 100644
index 00000000000..162a91dc300
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/router.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+
+Vue.use(VueRouter);
+
+// Vue Router requires a component to render if the route matches, but since we're only using it for
+// querystring handling, we'll create an empty component.
+const EmptyRouterComponent = {
+ render(createElement) {
+ return createElement('div');
+ },
+};
+
+export default () => {
+ // Name and path here don't really matter since we're not rendering anything if the route matches.
+ const routes = [{ path: '/', name: 'cluster_agents', component: EmptyRouterComponent }];
+ return new VueRouter({
+ mode: 'history',
+ base: window.location.pathname,
+ routes,
+ });
+};
diff --git a/app/assets/javascripts/clusters_list/components/agent_table.vue b/app/assets/javascripts/clusters_list/components/agent_table.vue
index 695e16b7b4b..61c4904aacf 100644
--- a/app/assets/javascripts/clusters_list/components/agent_table.vue
+++ b/app/assets/javascripts/clusters_list/components/agent_table.vue
@@ -1,23 +1,14 @@
<script>
import { GlLink, GlTable, GlIcon, GlSprintf, GlTooltip, GlPopover } from '@gitlab/ui';
-import { s__, __ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { AGENT_STATUSES } from '../constants';
+import { AGENT_STATUSES, I18N_AGENT_TABLE } from '../constants';
import { getAgentConfigPath } from '../clusters_util';
-import AgentOptions from './agent_options.vue';
+import DeleteAgentButton from './delete_agent_button.vue';
export default {
- i18n: {
- nameLabel: s__('ClusterAgents|Name'),
- statusLabel: s__('ClusterAgents|Connection status'),
- lastContactLabel: s__('ClusterAgents|Last contact'),
- configurationLabel: s__('ClusterAgents|Configuration'),
- optionsLabel: __('Options'),
- troubleshootingText: s__('ClusterAgents|Learn how to troubleshoot'),
- neverConnectedText: s__('ClusterAgents|Never'),
- },
+ i18n: I18N_AGENT_TABLE,
components: {
GlLink,
GlTable,
@@ -26,13 +17,15 @@ export default {
GlTooltip,
GlPopover,
TimeAgoTooltip,
- AgentOptions,
+ DeleteAgentButton,
},
mixins: [timeagoMixin],
AGENT_STATUSES,
- troubleshooting_link: helpPagePath('user/clusters/agent/index', {
- anchor: 'troubleshooting',
+ troubleshootingLink: helpPagePath('user/clusters/agent/troubleshooting'),
+ versionUpdateLink: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'update-the-agent-version',
}),
+ inject: ['gitlabVersion'],
props: {
agents: {
required: true,
@@ -69,30 +62,93 @@ export default {
tdClass,
},
{
+ key: 'version',
+ label: this.$options.i18n.versionLabel,
+ tdClass,
+ },
+ {
key: 'configuration',
label: this.$options.i18n.configurationLabel,
tdClass,
},
{
key: 'options',
- label: this.$options.i18n.optionsLabel,
+ label: '',
tdClass,
},
];
},
+ agentsList() {
+ if (!this.agents.length) {
+ return [];
+ }
+
+ return this.agents.map((agent) => {
+ const versions = this.getAgentVersions(agent);
+ return { ...agent, versions };
+ });
+ },
},
methods: {
- getCellId(item) {
+ getStatusCellId(item) {
return `connection-status-${item.name}`;
},
+ getVersionCellId(item) {
+ return `version-${item.name}`;
+ },
+ getPopoverTestId(item) {
+ return `popover-${item.name}`;
+ },
getAgentConfigPath,
+ getAgentVersions(agent) {
+ const agentConnections = agent.connections?.nodes || [];
+
+ const agentVersions = agentConnections.map((agentConnection) =>
+ agentConnection.metadata.version.replace('v', ''),
+ );
+
+ const uniqueAgentVersions = [...new Set(agentVersions)];
+
+ return uniqueAgentVersions.sort((a, b) => a.localeCompare(b));
+ },
+ getAgentVersionString(agent) {
+ return agent.versions[0] || '';
+ },
+ isVersionMismatch(agent) {
+ return agent.versions.length > 1;
+ },
+ isVersionOutdated(agent) {
+ if (!agent.versions.length) return false;
+
+ const [agentMajorVersion, agentMinorVersion] = this.getAgentVersionString(agent).split('.');
+ const [gitlabMajorVersion, gitlabMinorVersion] = this.gitlabVersion.split('.');
+
+ const majorVersionMismatch = agentMajorVersion !== gitlabMajorVersion;
+
+ // We should warn user if their current GitLab and agent versions are more than 1 minor version apart:
+ const minorVersionMismatch = Math.abs(agentMinorVersion - gitlabMinorVersion) > 1;
+
+ return majorVersionMismatch || minorVersionMismatch;
+ },
+
+ getVersionPopoverTitle(agent) {
+ if (this.isVersionMismatch(agent) && this.isVersionOutdated(agent)) {
+ return this.$options.i18n.versionMismatchOutdatedTitle;
+ } else if (this.isVersionMismatch(agent)) {
+ return this.$options.i18n.versionMismatchTitle;
+ } else if (this.isVersionOutdated(agent)) {
+ return this.$options.i18n.versionOutdatedTitle;
+ }
+
+ return null;
+ },
},
};
</script>
<template>
<gl-table
- :items="agents"
+ :items="agentsList"
:fields="fields"
stacked="md"
head-variant="white"
@@ -107,19 +163,23 @@ export default {
</template>
<template #cell(status)="{ item }">
- <span :id="getCellId(item)" class="gl-md-pr-5" data-testid="cluster-agent-connection-status">
+ <span
+ :id="getStatusCellId(item)"
+ class="gl-md-pr-5"
+ data-testid="cluster-agent-connection-status"
+ >
<span :class="$options.AGENT_STATUSES[item.status].class" class="gl-mr-3">
<gl-icon :name="$options.AGENT_STATUSES[item.status].icon" :size="12" /></span
>{{ $options.AGENT_STATUSES[item.status].name }}
</span>
- <gl-tooltip v-if="item.status === 'active'" :target="getCellId(item)" placement="right">
+ <gl-tooltip v-if="item.status === 'active'" :target="getStatusCellId(item)" placement="right">
<gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.title"
><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template>
</gl-sprintf>
</gl-tooltip>
<gl-popover
v-else
- :target="getCellId(item)"
+ :target="getStatusCellId(item)"
:title="$options.AGENT_STATUSES[item.status].tooltip.title"
placement="right"
container="viewport"
@@ -130,7 +190,7 @@ export default {
>
</p>
<p class="gl-mb-0">
- <gl-link :href="$options.troubleshooting_link" target="_blank" class="gl-font-sm">
+ <gl-link :href="$options.troubleshootingLink" target="_blank" class="gl-font-sm">
{{ $options.i18n.troubleshootingText }}</gl-link
>
</p>
@@ -144,6 +204,52 @@ export default {
</span>
</template>
+ <template #cell(version)="{ item }">
+ <span :id="getVersionCellId(item)" data-testid="cluster-agent-version">
+ {{ getAgentVersionString(item) }}
+
+ <gl-icon
+ v-if="isVersionMismatch(item) || isVersionOutdated(item)"
+ name="warning"
+ class="gl-text-orange-500 gl-ml-2"
+ />
+ </span>
+
+ <gl-popover
+ v-if="isVersionMismatch(item) || isVersionOutdated(item)"
+ :target="getVersionCellId(item)"
+ :title="getVersionPopoverTitle(item)"
+ :data-testid="getPopoverTestId(item)"
+ placement="right"
+ container="viewport"
+ >
+ <div v-if="isVersionMismatch(item) && isVersionOutdated(item)">
+ <p>{{ $options.i18n.versionMismatchText }}</p>
+
+ <p class="gl-mb-0">
+ <gl-sprintf :message="$options.i18n.versionOutdatedText">
+ <template #version>{{ gitlabVersion }}</template>
+ </gl-sprintf>
+ <gl-link :href="$options.versionUpdateLink" class="gl-font-sm">
+ {{ $options.i18n.viewDocsText }}</gl-link
+ >
+ </p>
+ </div>
+ <p v-else-if="isVersionMismatch(item)" class="gl-mb-0">
+ {{ $options.i18n.versionMismatchText }}
+ </p>
+
+ <p v-else-if="isVersionOutdated(item)" class="gl-mb-0">
+ <gl-sprintf :message="$options.i18n.versionOutdatedText">
+ <template #version>{{ gitlabVersion }}</template>
+ </gl-sprintf>
+ <gl-link :href="$options.versionUpdateLink" class="gl-font-sm">
+ {{ $options.i18n.viewDocsText }}</gl-link
+ >
+ </p>
+ </gl-popover>
+ </template>
+
<template #cell(configuration)="{ item }">
<span data-testid="cluster-agent-configuration-link">
<gl-link v-if="item.configFolder" :href="item.configFolder.webPath">
@@ -155,7 +261,7 @@ export default {
</template>
<template #cell(options)="{ item }">
- <agent-options
+ <delete-agent-button
:agent="item"
:default-branch-name="defaultBranchName"
:max-agents="maxAgents"
diff --git a/app/assets/javascripts/clusters_list/components/agents.vue b/app/assets/javascripts/clusters_list/components/agents.vue
index 4fc421e7c31..bf096f53e9d 100644
--- a/app/assets/javascripts/clusters_list/components/agents.vue
+++ b/app/assets/javascripts/clusters_list/components/agents.vue
@@ -1,11 +1,29 @@
<script>
-import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
-import { MAX_LIST_COUNT, ACTIVE_CONNECTION_TIME } from '../constants';
+import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import {
+ MAX_LIST_COUNT,
+ ACTIVE_CONNECTION_TIME,
+ AGENT_FEEDBACK_ISSUE,
+ AGENT_FEEDBACK_KEY,
+} from '../constants';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue';
export default {
+ i18n: {
+ feedbackBannerTitle: s__('ClusterAgents|Tell us what you think'),
+ feedbackBannerText: s__(
+ 'ClusterAgents|We would love to learn more about your experience with the GitLab Agent.',
+ ),
+ feedbackBannerButton: s__('ClusterAgents|Give feedback'),
+ error: s__('ClusterAgents|An error occurred while loading your Agents'),
+ },
+ AGENT_FEEDBACK_ISSUE,
+ AGENT_FEEDBACK_KEY,
apollo: {
agents: {
query: getAgentsQuery,
@@ -31,7 +49,10 @@ export default {
GlAlert,
GlKeysetPagination,
GlLoadingIcon,
+ GlBanner,
+ LocalStorageSync,
},
+ mixins: [glFeatureFlagMixin()],
inject: ['projectPath'],
props: {
defaultBranchName: {
@@ -57,6 +78,7 @@ export default {
last: null,
},
folderList: {},
+ feedbackBannerDismissed: false,
};
},
computed: {
@@ -86,6 +108,12 @@ export default {
treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
},
+ feedbackBannerEnabled() {
+ return this.glFeatures.showGitlabAgentFeedback;
+ },
+ feedbackBannerClasses() {
+ return this.isChildComponent ? 'gl-my-2' : 'gl-mb-4';
+ },
},
methods: {
reloadAgents() {
@@ -142,6 +170,9 @@ export default {
const count = this.agents?.project?.clusterAgents?.count;
this.$emit('onAgentsLoad', count);
},
+ handleBannerClose() {
+ this.feedbackBannerDismissed = true;
+ },
},
};
</script>
@@ -151,6 +182,24 @@ export default {
<section v-else-if="agentList">
<div v-if="agentList.length">
+ <local-storage-sync
+ v-if="feedbackBannerEnabled"
+ v-model="feedbackBannerDismissed"
+ :storage-key="$options.AGENT_FEEDBACK_KEY"
+ >
+ <gl-banner
+ v-if="!feedbackBannerDismissed"
+ variant="introduction"
+ :class="feedbackBannerClasses"
+ :title="$options.i18n.feedbackBannerTitle"
+ :button-text="$options.i18n.feedbackBannerButton"
+ :button-link="$options.AGENT_FEEDBACK_ISSUE"
+ @close="handleBannerClose"
+ >
+ <p>{{ $options.i18n.feedbackBannerText }}</p>
+ </gl-banner>
+ </local-storage-sync>
+
<agent-table
:agents="agentList"
:default-branch-name="defaultBranchName"
@@ -166,6 +215,6 @@ export default {
</section>
<gl-alert v-else variant="danger" :dismissible="false">
- {{ s__('ClusterAgents|An error occurred while loading your GitLab Agents') }}
+ {{ $options.i18n.error }}
</gl-alert>
</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 9c330045596..7fb3aa3ff7e 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -57,7 +57,7 @@ export default {
'totalClusters',
]),
contentAlignClasses() {
- return 'gl-display-flex gl-align-items-center gl-justify-content-end gl-justify-content-md-start';
+ return 'gl-display-flex gl-align-items-center gl-justify-content-end gl-md-justify-content-start';
},
currentPage: {
get() {
diff --git a/app/assets/javascripts/clusters_list/components/clusters_actions.vue b/app/assets/javascripts/clusters_list/components/clusters_actions.vue
index 25f67462223..5b8dc74b84f 100644
--- a/app/assets/javascripts/clusters_list/components/clusters_actions.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters_actions.vue
@@ -1,5 +1,13 @@
<script>
-import { GlDropdown, GlDropdownItem, GlModalDirective } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlModalDirective,
+ GlTooltipDirective,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+} from '@gitlab/ui';
+
import { INSTALL_AGENT_MODAL_ID, CLUSTERS_ACTIONS } from '../constants';
export default {
@@ -8,11 +16,20 @@ export default {
components: {
GlDropdown,
GlDropdownItem,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
},
directives: {
GlModalDirective,
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: ['newClusterPath', 'addClusterPath', 'canAddCluster'],
+ computed: {
+ tooltip() {
+ const { connectWithAgent, dropdownDisabledHint } = this.$options.i18n;
+ return this.canAddCluster ? connectWithAgent : dropdownDisabledHint;
+ },
},
- inject: ['newClusterPath', 'addClusterPath'],
};
</script>
@@ -20,22 +37,27 @@ export default {
<div class="nav-controls gl-ml-auto">
<gl-dropdown
ref="dropdown"
- v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
+ v-gl-modal-directive="canAddCluster && $options.INSTALL_AGENT_MODAL_ID"
+ v-gl-tooltip="tooltip"
category="primary"
variant="confirm"
:text="$options.i18n.actionsButton"
+ :disabled="!canAddCluster"
split
right
>
- <gl-dropdown-item :href="newClusterPath" data-testid="new-cluster-link" @click.stop>
- {{ $options.i18n.createNewCluster }}
- </gl-dropdown-item>
+ <gl-dropdown-section-header>{{ $options.i18n.agent }}</gl-dropdown-section-header>
<gl-dropdown-item
v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
data-testid="connect-new-agent-link"
>
{{ $options.i18n.connectWithAgent }}
</gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-section-header>{{ $options.i18n.certificate }}</gl-dropdown-section-header>
+ <gl-dropdown-item :href="newClusterPath" data-testid="new-cluster-link" @click.stop>
+ {{ $options.i18n.createNewCluster }}
+ </gl-dropdown-item>
<gl-dropdown-item :href="addClusterPath" data-testid="connect-cluster-link" @click.stop>
{{ $options.i18n.connectExistingCluster }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
index 0e312d21e4e..b730c0adfa2 100644
--- a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
@@ -8,6 +8,7 @@ import {
GlBadge,
GlLoadingIcon,
GlModalDirective,
+ GlTooltipDirective,
} from '@gitlab/ui';
import { mapState } from 'vuex';
import {
@@ -33,6 +34,7 @@ export default {
},
directives: {
GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
MAX_CLUSTERS_LIST,
INSTALL_AGENT_MODAL_ID,
@@ -40,7 +42,7 @@ export default {
agent: AGENT_CARD_INFO,
certificate: CERTIFICATE_BASED_CARD_INFO,
},
- inject: ['addClusterPath'],
+ inject: ['addClusterPath', 'canAddCluster'],
props: {
defaultBranchName: {
default: '.noBranch',
@@ -91,6 +93,14 @@ export default {
return cardTitle;
},
+ installAgentTooltip() {
+ return this.canAddCluster ? '' : this.$options.i18n.agent.installAgentDisabledHint;
+ },
+ connectExistingClusterTooltip() {
+ return this.canAddCluster
+ ? ''
+ : this.$options.i18n.certificate.connectExistingClusterDisabledHint;
+ },
},
methods: {
cardFooterNumber(number) {
@@ -113,7 +123,7 @@ export default {
<div v-show="!isLoading" data-testid="clusters-cards-container">
<gl-card
header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between gl-py-4"
- body-class="gl-pb-0"
+ body-class="gl-pb-0 cluster-card-item"
footer-class="gl-text-right"
>
<template #header>
@@ -166,20 +176,29 @@ export default {
><gl-sprintf :message="$options.i18n.agent.footerText"
><template #number>{{ cardFooterNumber(totalAgents) }}</template></gl-sprintf
></gl-link
- ><gl-button
- v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
- class="gl-ml-4"
- category="secondary"
- variant="confirm"
- >{{ $options.i18n.agent.actionText }}</gl-button
>
+ <div
+ v-gl-tooltip="installAgentTooltip"
+ class="gl-display-inline-block"
+ tabindex="-1"
+ data-testid="install-agent-button-tooltip"
+ >
+ <gl-button
+ v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
+ class="gl-ml-4"
+ category="secondary"
+ variant="confirm"
+ :disabled="!canAddCluster"
+ >{{ $options.i18n.agent.actionText }}</gl-button
+ >
+ </div>
</template>
</gl-card>
<gl-card
class="gl-mt-6"
header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between"
- body-class="gl-pb-0"
+ body-class="gl-pb-0 cluster-card-item"
footer-class="gl-text-right"
>
<template #header>
@@ -206,14 +225,23 @@ export default {
><gl-sprintf :message="$options.i18n.certificate.footerText"
><template #number>{{ cardFooterNumber(totalClusters) }}</template></gl-sprintf
></gl-link
- ><gl-button
- category="secondary"
- data-qa-selector="connect_existing_cluster_button"
- variant="confirm"
- class="gl-ml-4"
- :href="addClusterPath"
- >{{ $options.i18n.certificate.actionText }}</gl-button
>
+ <div
+ v-gl-tooltip="connectExistingClusterTooltip"
+ class="gl-display-inline-block"
+ tabindex="-1"
+ data-testid="connect-existing-cluster-button-tooltip"
+ >
+ <gl-button
+ category="secondary"
+ data-qa-selector="connect_existing_cluster_button"
+ variant="confirm"
+ class="gl-ml-4"
+ :href="addClusterPath"
+ :disabled="!canAddCluster"
+ >{{ $options.i18n.certificate.actionText }}</gl-button
+ >
+ </div>
</template>
</gl-card>
</div>
diff --git a/app/assets/javascripts/clusters_list/components/agent_options.vue b/app/assets/javascripts/clusters_list/components/delete_agent_button.vue
index a364122ba56..6588d304d5c 100644
--- a/app/assets/javascripts/clusters_list/components/agent_options.vue
+++ b/app/assets/javascripts/clusters_list/components/delete_agent_button.vue
@@ -1,36 +1,23 @@
<script>
import {
- GlDropdown,
- GlDropdownItem,
+ GlButton,
GlModal,
GlModalDirective,
GlSprintf,
GlFormGroup,
GlFormInput,
+ GlTooltipDirective,
} from '@gitlab/ui';
-import { s__, __, sprintf } from '~/locale';
-import { DELETE_AGENT_MODAL_ID } from '../constants';
+import { sprintf } from '~/locale';
+import { DELETE_AGENT_BUTTON, DELETE_AGENT_MODAL_ID } from '../constants';
import deleteAgent from '../graphql/mutations/delete_agent.mutation.graphql';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import { removeAgentFromStore } from '../graphql/cache_update';
export default {
- i18n: {
- dropdownText: __('More options'),
- deleteButton: s__('ClusterAgents|Delete agent'),
- modalTitle: __('Are you sure?'),
- modalBody: s__(
- 'ClusterAgents|Are you sure you want to delete this agent? You cannot undo this.',
- ),
- modalInputLabel: s__('ClusterAgents|To delete the agent, type %{name} to confirm:'),
- modalAction: s__('ClusterAgents|Delete'),
- modalCancel: __('Cancel'),
- successMessage: s__('ClusterAgents|%{name} successfully deleted'),
- defaultError: __('An error occurred. Please try again.'),
- },
+ i18n: DELETE_AGENT_BUTTON,
components: {
- GlDropdown,
- GlDropdownItem,
+ GlButton,
GlModal,
GlSprintf,
GlFormGroup,
@@ -38,8 +25,9 @@ export default {
},
directives: {
GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
- inject: ['projectPath'],
+ inject: ['projectPath', 'canAdminCluster'],
props: {
agent: {
required: true,
@@ -66,6 +54,13 @@ export default {
};
},
computed: {
+ deleteButtonDisabled() {
+ return this.loading || !this.canAdminCluster;
+ },
+ deleteButtonTooltip() {
+ const { deleteButton, disabledHint } = this.$options.i18n;
+ return this.deleteButtonDisabled ? disabledHint : deleteButton;
+ },
getAgentsQueryVariables() {
return {
defaultBranchName: this.defaultBranchName,
@@ -159,19 +154,22 @@ export default {
<template>
<div>
- <gl-dropdown
- icon="ellipsis_v"
- right
- :disabled="loading"
- :text="$options.i18n.dropdownText"
- text-sr-only
- category="tertiary"
- no-caret
+ <div
+ v-gl-tooltip="deleteButtonTooltip"
+ class="gl-display-inline-block"
+ tabindex="-1"
+ data-testid="delete-agent-button-tooltip"
>
- <gl-dropdown-item v-gl-modal-directive="modalId">
- {{ $options.i18n.deleteButton }}
- </gl-dropdown-item>
- </gl-dropdown>
+ <gl-button
+ ref="deleteAgentButton"
+ v-gl-modal-directive="modalId"
+ icon="remove"
+ category="secondary"
+ variant="danger"
+ :disabled="deleteButtonDisabled"
+ :aria-label="$options.i18n.deleteButton"
+ />
+ </div>
<gl-modal
ref="modal"
diff --git a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
index 5eef76252bd..8fc0a66cd7e 100644
--- a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
+++ b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
@@ -111,6 +111,9 @@ export default {
canCancel() {
return !this.registered && !this.registering && this.isAgentRegistrationModal;
},
+ canRegister() {
+ return !this.registered && this.isAgentRegistrationModal;
+ },
agentRegistrationCommand() {
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
},
@@ -142,6 +145,9 @@ export default {
isAgentRegistrationModal() {
return this.modalType === MODAL_TYPE_REGISTER;
},
+ isKasEnabledInEmptyStateModal() {
+ return this.isEmptyStateModal && !this.kasDisabled;
+ },
},
methods: {
setAgentName(name) {
@@ -350,18 +356,18 @@ export default {
<img :alt="i18n.altText" :src="emptyStateImage" height="100" />
</div>
- <p>
- <gl-sprintf :message="i18n.modalBody">
+ <p v-if="kasDisabled">
+ <gl-sprintf :message="i18n.enableKasText">
<template #link="{ content }">
- <gl-link :href="$options.installAgentPath"> {{ content }}</gl-link>
+ <gl-link :href="$options.enableKasPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
- <p v-if="kasDisabled">
- <gl-sprintf :message="i18n.enableKasText">
+ <p v-else>
+ <gl-sprintf :message="i18n.modalBody">
<template #link="{ content }">
- <gl-link :href="$options.enableKasPath"> {{ content }}</gl-link>
+ <gl-link :href="$options.installAgentPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
@@ -380,7 +386,16 @@ export default {
</gl-button>
<gl-button
- v-else-if="isAgentRegistrationModal"
+ v-if="canCancel"
+ :data-track-action="$options.EVENT_ACTIONS_CLICK"
+ :data-track-label="$options.EVENT_LABEL_MODAL"
+ data-track-property="cancel"
+ @click="closeModal"
+ >{{ i18n.cancel }}
+ </gl-button>
+
+ <gl-button
+ v-if="canRegister"
:disabled="!nextButtonDisabled"
variant="confirm"
category="primary"
@@ -392,32 +407,21 @@ export default {
</gl-button>
<gl-button
- v-if="canCancel"
+ v-if="isEmptyStateModal"
:data-track-action="$options.EVENT_ACTIONS_CLICK"
:data-track-label="$options.EVENT_LABEL_MODAL"
- data-track-property="cancel"
+ data-track-property="done"
@click="closeModal"
- >{{ i18n.cancel }}
+ >{{ i18n.done }}
</gl-button>
<gl-button
- v-if="isEmptyStateModal"
+ v-if="isKasEnabledInEmptyStateModal"
:href="repositoryPath"
variant="confirm"
- category="secondary"
- data-testid="agent-secondary-button"
- >{{ i18n.secondaryButton }}
- </gl-button>
-
- <gl-button
- v-if="isEmptyStateModal"
- variant="confirm"
category="primary"
- :data-track-action="$options.EVENT_ACTIONS_CLICK"
- :data-track-label="$options.EVENT_LABEL_MODAL"
- data-track-property="done"
- @click="closeModal"
- >{{ i18n.done }}
+ data-testid="agent-primary-button"
+ >{{ i18n.primaryButton }}
</gl-button>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js
index 380a5d0aada..5cf6fd050a1 100644
--- a/app/assets/javascripts/clusters_list/constants.js
+++ b/app/assets/javascripts/clusters_list/constants.js
@@ -64,6 +64,27 @@ export const STATUSES = {
creating: { title: __('Creating') },
};
+export const I18N_AGENT_TABLE = {
+ nameLabel: s__('ClusterAgents|Name'),
+ statusLabel: s__('ClusterAgents|Connection status'),
+ lastContactLabel: s__('ClusterAgents|Last contact'),
+ versionLabel: __('Version'),
+ configurationLabel: s__('ClusterAgents|Configuration'),
+ optionsLabel: __('Options'),
+ troubleshootingText: s__('ClusterAgents|Learn how to troubleshoot'),
+ neverConnectedText: s__('ClusterAgents|Never'),
+ versionMismatchTitle: s__('ClusterAgents|Agent version mismatch'),
+ versionMismatchText: s__(
+ "ClusterAgents|The Agent version do not match each other across your cluster's pods. This can happen when a new Agent version was just deployed and Kubernetes is shutting down the old pods.",
+ ),
+ versionOutdatedTitle: s__('ClusterAgents|Agent version update required'),
+ versionOutdatedText: s__(
+ 'ClusterAgents|Your Agent version is out of sync with your GitLab version (v%{version}), which might cause compatibility problems. Update the Agent installed on your cluster to the most recent version.',
+ ),
+ versionMismatchOutdatedTitle: s__('ClusterAgents|Agent version mismatch and update'),
+ viewDocsText: s__('ClusterAgents|How to update the Agent?'),
+};
+
export const I18N_AGENT_MODAL = {
agent_registration: {
registerAgentButton: s__('ClusterAgents|Register'),
@@ -112,7 +133,7 @@ export const I18N_AGENT_MODAL = {
"ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it.",
),
altText: s__('ClusterAgents|GitLab Agent for Kubernetes'),
- secondaryButton: s__('ClusterAgents|Go to the repository files'),
+ primaryButton: s__('ClusterAgents|Go to the repository files'),
done: __('Cancel'),
},
};
@@ -176,8 +197,8 @@ export const I18N_CLUSTERS_EMPTY_STATE = {
export const AGENT_CARD_INFO = {
tabName: 'agent',
- title: sprintf(s__('ClusterAgents|%{number} of %{total} agents')),
- emptyTitle: s__('ClusterAgents|No agents'),
+ title: sprintf(s__('ClusterAgents|%{number} of %{total} Agents')),
+ emptyTitle: s__('ClusterAgents|No Agents'),
tooltip: {
label: s__('ClusterAgents|Recommended'),
title: s__('ClusterAgents|GitLab Agent'),
@@ -188,8 +209,11 @@ export const AGENT_CARD_INFO = {
),
link: helpPagePath('user/clusters/agent/index'),
},
- actionText: s__('ClusterAgents|Install a new agent'),
+ actionText: s__('ClusterAgents|Install new Agent'),
footerText: sprintf(s__('ClusterAgents|View all %{number} agents')),
+ installAgentDisabledHint: s__(
+ 'ClusterAgents|Requires a Maintainer or greater role to install new agents',
+ ),
};
export const CERTIFICATE_BASED_CARD_INFO = {
@@ -201,6 +225,9 @@ export const CERTIFICATE_BASED_CARD_INFO = {
actionText: s__('ClusterAgents|Connect existing cluster'),
footerText: sprintf(s__('ClusterAgents|View all %{number} clusters')),
badgeText: s__('ClusterAgents|Deprecated'),
+ connectExistingClusterDisabledHint: s__(
+ 'ClusterAgents|Requires a maintainer or greater role to connect existing clusters',
+ ),
};
export const MAX_CLUSTERS_LIST = 6;
@@ -226,8 +253,25 @@ export const CLUSTERS_TABS = [
export const CLUSTERS_ACTIONS = {
actionsButton: s__('ClusterAgents|Actions'),
createNewCluster: s__('ClusterAgents|Create a new cluster'),
- connectWithAgent: s__('ClusterAgents|Connect with the Agent'),
+ connectWithAgent: s__('ClusterAgents|Connect with Agent'),
connectExistingCluster: s__('ClusterAgents|Connect with a certificate'),
+ agent: s__('ClusterAgents|Agent'),
+ certificate: s__('ClusterAgents|Certificate'),
+ dropdownDisabledHint: s__(
+ 'ClusterAgents|Requires a Maintainer or greater role to perform these actions',
+ ),
+};
+
+export const DELETE_AGENT_BUTTON = {
+ deleteButton: s__('ClusterAgents|Delete agent'),
+ disabledHint: s__('ClusterAgents|Requires a Maintainer or greater role to delete agents'),
+ modalTitle: __('Are you sure?'),
+ modalBody: s__('ClusterAgents|Are you sure you want to delete this agent? You cannot undo this.'),
+ modalInputLabel: s__('ClusterAgents|To delete the agent, type %{name} to confirm:'),
+ modalAction: s__('ClusterAgents|Delete'),
+ modalCancel: __('Cancel'),
+ successMessage: s__('ClusterAgents|%{name} successfully deleted'),
+ defaultError: __('An error occurred. Please try again.'),
};
export const AGENT = 'agent';
@@ -244,3 +288,6 @@ export const MODAL_TYPE_EMPTY = 'empty_state';
export const MODAL_TYPE_REGISTER = 'agent_registration';
export const DELETE_AGENT_MODAL_ID = 'delete-agent-modal-%{agentName}';
+
+export const AGENT_FEEDBACK_ISSUE = 'https://gitlab.com/gitlab-org/gitlab/-/issues/342696';
+export const AGENT_FEEDBACK_KEY = 'agent_feedback_banner';
diff --git a/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
index cd46dfee170..05d2525ab98 100644
--- a/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
@@ -2,6 +2,13 @@ fragment ClusterAgentFragment on ClusterAgent {
id
name
webPath
+ connections {
+ nodes {
+ metadata {
+ version
+ }
+ }
+ }
tokens {
nodes {
id
diff --git a/app/assets/javascripts/clusters_list/load_main_view.js b/app/assets/javascripts/clusters_list/load_main_view.js
index 08c99b46e16..d52b1d4a64d 100644
--- a/app/assets/javascripts/clusters_list/load_main_view.js
+++ b/app/assets/javascripts/clusters_list/load_main_view.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import { parseBoolean } from '~/lib/utils/common_utils';
import createDefaultClient from '~/lib/graphql';
import ClustersMainView from './components/clusters_main_view.vue';
import { createStore } from './store';
@@ -24,6 +25,9 @@ export default () => {
addClusterPath,
emptyStateHelpText,
clustersEmptyStateImage,
+ canAddCluster,
+ canAdminCluster,
+ gitlabVersion,
} = el.dataset;
return new Vue({
@@ -37,6 +41,9 @@ export default () => {
addClusterPath,
emptyStateHelpText,
clustersEmptyStateImage,
+ canAddCluster: parseBoolean(canAddCluster),
+ canAdminCluster: parseBoolean(canAdminCluster),
+ gitlabVersion,
},
store: createStore(el.dataset),
render(createElement) {
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index d54fb7cded2..925b411e51c 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -1,8 +1,8 @@
+import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
import {
MarkdownSerializer as ProseMirrorMarkdownSerializer,
defaultMarkdownSerializer,
-} from 'prosemirror-markdown/src/to_markdown';
-import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
+} from '~/lib/prosemirror_markdown_serializer';
import Audio from '../extensions/audio';
import Blockquote from '../extensions/blockquote';
import Bold from '../extensions/bold';
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 08942374120..d1a68e80608 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -1,10 +1,9 @@
import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import Cookies from 'js-cookie';
import { debounce } from 'lodash';
+import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
-import { parseBoolean } from '~/lib/utils/common_utils';
export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed';
@@ -59,7 +58,7 @@ export default class ContextualSidebar {
if (!ContextualSidebar.isDesktopBreakpoint()) {
return;
}
- Cookies.set('sidebar_collapsed', value, { expires: 365 * 10 });
+ setCookie('sidebar_collapsed', value, { expires: 365 * 10 });
}
toggleSidebarNav(show) {
@@ -111,7 +110,7 @@ export default class ContextualSidebar {
if (!ContextualSidebar.isDesktopBreakpoint()) {
this.toggleSidebarNav(false);
} else {
- const collapse = parseBoolean(Cookies.get('sidebar_collapsed'));
+ const collapse = parseBoolean(getCookie('sidebar_collapsed'));
this.toggleCollapsedSidebar(collapse, true);
}
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index bdfabb8e846..3d7a34581b3 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -1,12 +1,12 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import Cookies from 'js-cookie';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { getCookie, setCookie } from '~/lib/utils/common_utils';
+import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
import { toYmd } from '~/analytics/shared/utils';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import StageTable from '~/cycle_analytics/components/stage_table.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
-import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { __ } from '~/locale';
import { SUMMARY_METRICS_REQUEST, METRICS_REQUESTS } from '../constants';
@@ -35,7 +35,7 @@ export default {
},
data() {
return {
- isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE),
+ isOverviewDialogDismissed: getCookie(OVERVIEW_DIALOG_COOKIE),
};
},
computed: {
@@ -134,7 +134,7 @@ export default {
},
dismissOverviewDialog() {
this.isOverviewDialogDismissed = true;
- Cookies.set(OVERVIEW_DIALOG_COOKIE, '1', { expires: 365 });
+ setCookie(OVERVIEW_DIALOG_COOKIE, '1');
},
isUserAllowed(id) {
const { permissions } = this;
diff --git a/app/assets/javascripts/cycle_analytics/components/metric_tile.vue b/app/assets/javascripts/cycle_analytics/components/metric_tile.vue
new file mode 100644
index 00000000000..a5c20b237b3
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/components/metric_tile.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { redirectTo } from '~/lib/utils/url_utility';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
+
+export default {
+ name: 'MetricTile',
+ components: {
+ GlSingleStat,
+ MetricPopover,
+ },
+ props: {
+ metric: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ decimalPlaces() {
+ const parsedFloat = parseFloat(this.metric.value);
+ return Number.isNaN(parsedFloat) || Number.isInteger(parsedFloat) ? 0 : 1;
+ },
+ hasLinks() {
+ return this.metric.links?.length && this.metric.links[0].url;
+ },
+ },
+ methods: {
+ clickHandler({ links }) {
+ if (this.hasLinks) {
+ redirectTo(links[0].url);
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div v-bind="$attrs">
+ <gl-single-stat
+ :id="metric.identifier"
+ :value="`${metric.value}`"
+ :title="metric.label"
+ :unit="metric.unit || ''"
+ :should-animate="true"
+ :animation-decimal-places="decimalPlaces"
+ :class="{ 'gl-hover-cursor-pointer': hasLinks }"
+ tabindex="0"
+ @click="clickHandler(metric)"
+ />
+ <metric-popover :metric="metric" :target="metric.identifier" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_table.vue b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
index 8f7a3f99bab..ea5a1291a17 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_table.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
@@ -266,7 +266,7 @@ export default {
>
<span class="gl-font-lg">&middot;</span>
<span data-testid="vsa-stage-event-date">
- {{ s__('OpenedNDaysAgo|Opened') }}
+ {{ s__('OpenedNDaysAgo|Created') }}
<gl-link class="gl-text-black-normal" :href="item.url">{{
item.createdAt
}}</gl-link>
diff --git a/app/assets/javascripts/cycle_analytics/constants.js b/app/assets/javascripts/cycle_analytics/constants.js
index 7d5822b0824..f0b2bd9dc5b 100644
--- a/app/assets/javascripts/cycle_analytics/constants.js
+++ b/app/assets/javascripts/cycle_analytics/constants.js
@@ -36,31 +36,6 @@ export const OVERVIEW_METRICS = {
RECENT_ACTIVITY: 'RECENT_ACTIVITY',
};
-export const METRICS_POPOVER_CONTENT = {
- 'lead-time': {
- description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),
- },
- 'cycle-time': {
- description: s__(
- "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.",
- ),
- },
- 'lead-time-for-changes': {
- description: s__(
- 'ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period.',
- ),
- },
- 'new-issue': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
- 'new-issues': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
- deploys: { description: s__('ValueStreamAnalytics|Total number of deploys to production.') },
- 'deployment-frequency': {
- description: s__('ValueStreamAnalytics|Average number of deployments to production per day.'),
- },
- commits: {
- description: s__('ValueStreamAnalytics|Number of commits pushed to the default branch'),
- },
-};
-
export const SUMMARY_METRICS_REQUEST = [
{ endpoint: METRIC_TYPE_SUMMARY, name: __('recent activity'), request: getValueStreamMetrics },
];
diff --git a/app/assets/javascripts/cycle_analytics/utils.js b/app/assets/javascripts/cycle_analytics/utils.js
index 9af63f5f9cc..428bb11b950 100644
--- a/app/assets/javascripts/cycle_analytics/utils.js
+++ b/app/assets/javascripts/cycle_analytics/utils.js
@@ -1,14 +1,5 @@
-import { hideFlash } from '~/flash';
import { parseSeconds } from '~/lib/utils/datetime_utility';
import { formatTimeAsSummary } from '~/lib/utils/datetime/date_format_utility';
-import { slugify } from '~/lib/utils/text_utility';
-
-export const removeFlash = (type = 'alert') => {
- const flashEl = document.querySelector(`.flash-${type}`);
- if (flashEl) {
- hideFlash(flashEl);
- }
-};
/**
* Takes the stages and median data, combined with the selected stage, to build an
@@ -80,30 +71,11 @@ export const filterStagesByHiddenStatus = (stages = [], isHidden = true) =>
* @typedef {Object} TransformedMetricData
* @property {String} label - Title of the metric measured
* @property {String} value - String representing the decimal point value, e.g '1.5'
- * @property {String} key - Slugified string based on the 'title'
+ * @property {String} identifier - Slugified string based on the 'title' or the provided 'identifier' attribute
* @property {String} description - String to display for a description
* @property {String} unit - String representing the decimal point value, e.g '1.5'
*/
-/**
- * Prepares metric data to be rendered in the metric_card component
- *
- * @param {MetricData[]} data - The metric data to be rendered
- * @param {Object} popoverContent - Key value pair of data to display in the popover
- * @returns {TransformedMetricData[]} An array of metrics ready to render in the metric_card
- */
-
-export const prepareTimeMetricsData = (data = [], popoverContent = {}) =>
- data.map(({ title: label, ...rest }) => {
- const key = slugify(label);
- return {
- ...rest,
- label,
- key,
- description: popoverContent[key]?.description || '',
- };
- });
-
const extractFeatures = (gon) => ({
cycleAnalyticsForGroups: Boolean(gon?.licensed_features?.cycleAnalyticsForGroups),
});
diff --git a/app/assets/javascripts/deprecated_notes.js b/app/assets/javascripts/deprecated_notes.js
index 4ab3f140b61..82bbbe891e2 100644
--- a/app/assets/javascripts/deprecated_notes.js
+++ b/app/assets/javascripts/deprecated_notes.js
@@ -13,7 +13,6 @@ deprecated_notes_spec.js is the spec for the legacy, jQuery notes application. I
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import Autosize from 'autosize';
import $ from 'jquery';
-import Cookies from 'js-cookie';
import { escape, uniqueId } from 'lodash';
import Vue from 'vue';
import '~/lib/utils/jquery_at_who';
@@ -28,6 +27,7 @@ import { defaultAutocompleteConfig } from './gfm_auto_complete';
import GLForm from './gl_form';
import axios from './lib/utils/axios_utils';
import {
+ getCookie,
isInViewport,
getPagePath,
scrollToElement,
@@ -121,7 +121,7 @@ export default class Notes {
}
setViewType(view) {
- this.view = Cookies.get('diff_view') || view;
+ this.view = getCookie('diff_view') || view;
}
addBinding() {
@@ -473,7 +473,7 @@ export default class Notes {
}
isParallelView() {
- return Cookies.get('diff_view') === 'parallel';
+ return getCookie('diff_view') === 'parallel';
}
/**
@@ -694,7 +694,7 @@ export default class Notes {
// Convert returned HTML to a jQuery object so we can modify it further
const $noteEntityEl = $(noteEntity.html);
const $noteAvatar = $noteEntityEl.find('.image-diff-avatar-link');
- const $targetNoteBadge = $targetNote.find('.badge');
+ const $targetNoteBadge = $targetNote.find('.design-note-pin');
$noteAvatar.append($targetNoteBadge);
this.revertNoteEditForm($targetNote);
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index b058709b316..674415ec449 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -286,6 +286,7 @@ export default {
"
:is-inactive="isNoteInactive(note)"
:is-resolved="note.resolved"
+ is-on-image
@mousedown.stop="onNoteMousedown($event, note)"
@mouseup.stop="onNoteMouseup(note)"
/>
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index 6d0ed3b08a3..81d0b6d0df4 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -1,7 +1,7 @@
<script>
import { GlCollapse, GlButton, GlPopover } from '@gitlab/ui';
-import Cookies from 'js-cookie';
-import { parseBoolean, isLoggedIn } from '~/lib/utils/common_utils';
+import { getCookie, setCookie, parseBoolean, isLoggedIn } from '~/lib/utils/common_utils';
+
import { s__ } from '~/locale';
import Participants from '~/sidebar/components/participants/participants.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -53,7 +53,7 @@ export default {
},
data() {
return {
- isResolvedCommentsPopoverHidden: parseBoolean(Cookies.get(this.$options.cookieKey)),
+ isResolvedCommentsPopoverHidden: parseBoolean(getCookie(this.$options.cookieKey)),
discussionWithOpenForm: '',
isLoggedIn: isLoggedIn(),
};
@@ -96,7 +96,7 @@ export default {
methods: {
handleSidebarClick() {
this.isResolvedCommentsPopoverHidden = true;
- Cookies.set(this.$options.cookieKey, 'true', { expires: 365 * 10 });
+ setCookie(this.$options.cookieKey, 'true', { expires: 365 * 10 });
this.updateActiveDiscussion();
},
updateActiveDiscussion(id) {
diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js
index 5cf32cb7fe3..8c44c5a5d0a 100644
--- a/app/assets/javascripts/design_management/graphql.js
+++ b/app/assets/javascripts/design_management/graphql.js
@@ -1,11 +1,10 @@
-import { defaultDataIdFromObject, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
+import { defaultDataIdFromObject } from '@apollo/client/core';
import produce from 'immer';
import { uniqueId } from 'lodash';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
-import introspectionQueryResultData from './graphql/fragmentTypes.json';
import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
import getDesignQuery from './graphql/queries/get_design.query.graphql';
import typeDefs from './graphql/typedefs.graphql';
@@ -13,10 +12,6 @@ import { addPendingTodoToStore } from './utils/cache_update';
import { extractTodoIdFromDeletePath, createPendingTodo } from './utils/design_management_utils';
import { CREATE_DESIGN_TODO_EXISTS_ERROR } from './utils/error_messages';
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
-
Vue.use(VueApollo);
const resolvers = {
@@ -85,7 +80,6 @@ const defaultClient = createDefaultClient(
}
return defaultDataIdFromObject(object);
},
- fragmentMatcher,
},
typeDefs,
},
diff --git a/app/assets/javascripts/design_management/graphql/fragmentTypes.json b/app/assets/javascripts/design_management/graphql/fragmentTypes.json
deleted file mode 100644
index 0953231ea4c..00000000000
--- a/app/assets/javascripts/design_management/graphql/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"INTERFACE","name":"User","possibleTypes":[{"name":"UserCore"}]},{"kind":"UNION","name":"NoteableType","possibleTypes":[{"name":"Design"},{"name":"Issue"},{"name":"MergeRequest"}]}]}}
diff --git a/app/assets/javascripts/design_management/index.js b/app/assets/javascripts/design_management/index.js
index 4ae76050aa5..b856ac6c627 100644
--- a/app/assets/javascripts/design_management/index.js
+++ b/app/assets/javascripts/design_management/index.js
@@ -24,6 +24,7 @@ export default () => {
return new Vue({
el,
+ name: 'DesignRoot',
router,
apolloProvider,
provide: {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 66d06a3a1b6..5707e4d67f9 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -26,10 +26,8 @@ import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
MIN_TREE_WIDTH,
- MAX_TREE_WIDTH,
TREE_HIDE_STATS_WIDTH,
MR_TREE_SHOW_KEY,
- CENTERED_LIMITED_CONTAINER_CLASSES,
ALERT_OVERFLOW_HIDDEN,
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
@@ -55,6 +53,7 @@ import DiffFile from './diff_file.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
import NoChanges from './no_changes.vue';
import TreeList from './tree_list.vue';
+import VirtualScrollerScrollSync from './virtual_scroller_scroll_sync';
export default {
name: 'DiffsApp',
@@ -64,8 +63,7 @@ export default {
DynamicScrollerItem: () =>
import('vendor/vue-virtual-scroller').then(({ DynamicScrollerItem }) => DynamicScrollerItem),
PreRenderer: () => import('./pre_renderer.vue').then((PreRenderer) => PreRenderer),
- VirtualScrollerScrollSync: () =>
- import('./virtual_scroller_scroll_sync').then((VSSSync) => VSSSync),
+ VirtualScrollerScrollSync,
CompareVersions,
DiffFile,
NoChanges,
@@ -253,13 +251,6 @@ export default {
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
- isLimitedContainer() {
- if (this.glFeatures.mrChangesFluidLayout) {
- return false;
- }
-
- return !this.renderFileTree && !this.isParallelView && !this.isFluidLayout;
- },
isFullChangeset() {
return this.startVersion === null && this.latestDiff;
},
@@ -395,8 +386,6 @@ export default {
this.adjustView();
this.subscribeToEvents();
- this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
-
this.unwatchDiscussions = this.$watch(
() => `${this.diffFiles.length}:${this.$store.state.notes.discussions.length}`,
() => this.setDiscussions(),
@@ -417,10 +406,8 @@ export default {
this.unsubscribeFromEvents();
this.removeEventListeners();
- if (window.gon?.features?.diffsVirtualScrolling) {
- diffsEventHub.$off('scrollToFileHash', this.scrollVirtualScrollerToFileHash);
- diffsEventHub.$off('scrollToIndex', this.scrollVirtualScrollerToIndex);
- }
+ diffsEventHub.$off('scrollToFileHash', this.scrollVirtualScrollerToFileHash);
+ diffsEventHub.$off('scrollToIndex', this.scrollVirtualScrollerToIndex);
},
methods: {
...mapActions(['startTaskList']),
@@ -533,32 +520,27 @@ export default {
);
}
- if (
- window.gon?.features?.diffsVirtualScrolling ||
- window.gon?.features?.diffSearchingUsageData
- ) {
- let keydownTime;
- Mousetrap.bind(['mod+f', 'mod+g'], () => {
- keydownTime = new Date().getTime();
- });
+ let keydownTime;
+ Mousetrap.bind(['mod+f', 'mod+g'], () => {
+ keydownTime = new Date().getTime();
+ });
- window.addEventListener('blur', () => {
- if (keydownTime) {
- const delta = new Date().getTime() - keydownTime;
+ window.addEventListener('blur', () => {
+ if (keydownTime) {
+ const delta = new Date().getTime() - keydownTime;
- // To make sure the user is using the find function we need to wait for blur
- // and max 1000ms to be sure it the search box is filtered
- if (delta >= 0 && delta < 1000) {
- this.disableVirtualScroller();
+ // To make sure the user is using the find function we need to wait for blur
+ // and max 1000ms to be sure it the search box is filtered
+ if (delta >= 0 && delta < 1000) {
+ this.disableVirtualScroller();
- if (window.gon?.features?.diffSearchingUsageData) {
- api.trackRedisHllUserEvent('i_code_review_user_searches_diff');
- api.trackRedisCounterEvent('diff_searches');
- }
+ if (window.gon?.features?.usageDataDiffSearches) {
+ api.trackRedisHllUserEvent('i_code_review_user_searches_diff');
+ api.trackRedisCounterEvent('diff_searches');
}
}
- });
- }
+ }
+ });
},
removeEventListeners() {
Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF));
@@ -600,8 +582,6 @@ export default {
this.virtualScrollCurrentIndex = -1;
},
scrollVirtualScrollerToDiffNote() {
- if (!window.gon?.features?.diffsVirtualScrolling) return;
-
const id = window?.location?.hash;
if (id.startsWith('#note_')) {
@@ -616,11 +596,7 @@ export default {
}
},
subscribeToVirtualScrollingEvents() {
- if (
- window.gon?.features?.diffsVirtualScrolling &&
- this.shouldShow &&
- !this.subscribedToVirtualScrollingEvents
- ) {
+ if (this.shouldShow && !this.subscribedToVirtualScrollingEvents) {
diffsEventHub.$on('scrollToFileHash', this.scrollVirtualScrollerToFileHash);
diffsEventHub.$on('scrollToIndex', this.scrollVirtualScrollerToIndex);
@@ -632,7 +608,7 @@ export default {
},
},
minTreeWidth: MIN_TREE_WIDTH,
- maxTreeWidth: MAX_TREE_WIDTH,
+ maxTreeWidth: window.innerWidth / 2,
howToMergeDocsPath: helpPagePath('user/project/merge_requests/reviews/index.md', {
anchor: 'checkout-merge-requests-locally-through-the-head-ref',
}),
@@ -643,10 +619,7 @@ export default {
<div v-show="shouldShow">
<div v-if="isLoading || !isTreeLoaded" class="loading"><gl-loading-icon size="lg" /></div>
<div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
- <compare-versions
- :is-limited-container="isLimitedContainer"
- :diff-files-count-text="numTotalFiles"
- />
+ <compare-versions :diff-files-count-text="numTotalFiles" />
<template v-if="!isBatchLoadingError">
<hidden-files-warning
@@ -656,10 +629,7 @@ export default {
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
- <collapsed-files-warning
- v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES"
- :limited="isLimitedContainer"
- />
+ <collapsed-files-warning v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES" />
</template>
<div
@@ -669,7 +639,7 @@ export default {
<div
v-if="renderFileTree"
:style="{ width: `${treeWidth}px` }"
- class="diff-tree-list js-diff-tree-list px-3 pr-md-0"
+ class="diff-tree-list js-diff-tree-list gl-px-5"
>
<panel-resizer
:size.sync="treeWidth"
@@ -681,12 +651,7 @@ export default {
/>
<tree-list :hide-file-stats="hideFileStats" />
</div>
- <div
- class="col-12 col-md-auto diff-files-holder"
- :class="{
- [CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
- }"
- >
+ <div class="col-12 col-md-auto diff-files-holder">
<commit-widget v-if="commit" :commit="commit" :collapsible="false" />
<gl-alert
v-if="isBatchLoadingError"
diff --git a/app/assets/javascripts/diffs/components/collapsed_files_warning.vue b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
index 240f102e600..b7eea32e699 100644
--- a/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
@@ -2,7 +2,7 @@
import { GlAlert, GlButton } from '@gitlab/ui';
import { mapState } from 'vuex';
-import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
+import { EVT_EXPAND_ALL_FILES } from '../constants';
import eventHub from '../event_hub';
export default {
@@ -11,11 +11,6 @@ export default {
GlButton,
},
props: {
- limited: {
- type: Boolean,
- required: false,
- default: false,
- },
dismissed: {
type: Boolean,
required: false,
@@ -29,11 +24,6 @@ export default {
},
computed: {
...mapState('diffs', ['diffFiles']),
- containerClasses() {
- return {
- [CENTERED_LIMITED_CONTAINER_CLASSES]: this.limited,
- };
- },
shouldDisplay() {
return !this.isDismissed && this.diffFiles.length > 1;
},
@@ -53,7 +43,7 @@ export default {
</script>
<template>
- <div v-if="shouldDisplay" data-testid="root" :class="containerClasses" class="col-12">
+ <div v-if="shouldDisplay" data-testid="root" class="col-12">
<gl-alert
:dismissible="true"
:title="__('Some changes are not shown')"
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index e54fde72847..df7cf83b3f0 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -155,9 +155,11 @@ export default {
<gl-button
v-if="commit.description_html && collapsible"
+ v-gl-tooltip
class="js-toggle-button"
size="small"
icon="ellipsis_h"
+ :title="__('Toggle commit description')"
:aria-label="__('Toggle commit description')"
/>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 442807587d5..2b871680d5e 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -3,7 +3,7 @@ import { GlTooltipDirective, GlIcon, GlLink, GlButtonGroup, GlButton, GlSprintf
import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
import { setUrlParams } from '../../lib/utils/url_utility';
-import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
+import { EVT_EXPAND_ALL_FILES } from '../constants';
import eventHub from '../event_hub';
import CompareDropdownLayout from './compare_dropdown_layout.vue';
import DiffStats from './diff_stats.vue';
@@ -24,11 +24,6 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
- isLimitedContainer: {
- type: Boolean,
- required: false,
- default: false,
- },
diffFilesCountText: {
type: String,
required: false,
@@ -73,9 +68,6 @@ export default {
return this.commit && (this.commit.next_commit_id || this.commit.prev_commit_id);
},
},
- created() {
- this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
- },
methods: {
...mapActions('diffs', ['setInlineDiffViewType', 'setParallelDiffViewType', 'setShowTreeList']),
expandAllFiles() {
@@ -88,12 +80,7 @@ export default {
<template>
<div class="mr-version-controls border-top">
- <div
- class="mr-version-menus-container content-block"
- :class="{
- [CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
- }"
- >
+ <div class="mr-version-menus-container content-block">
<gl-button
v-if="hasChanges"
v-gl-tooltip.hover
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index 5e05ec87f84..47a05ce11cc 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -1,12 +1,14 @@
<script>
import { GlIcon } from '@gitlab/ui';
import { mapActions } from 'vuex';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
import noteableDiscussion from '../../notes/components/noteable_discussion.vue';
export default {
components: {
noteableDiscussion,
GlIcon,
+ DesignNotePin,
},
props: {
discussions: {
@@ -62,20 +64,22 @@ export default {
<ul :data-discussion-id="discussion.id" class="notes">
<template v-if="shouldCollapseDiscussions">
<button
- :class="{
- 'diff-notes-collapse': discussion.expanded,
- 'btn-transparent badge badge-pill': !discussion.expanded,
- }"
+ v-if="discussion.expanded"
+ class="diff-notes-collapse js-diff-notes-toggle"
type="button"
- class="js-diff-notes-toggle"
:aria-label="__('Show comments')"
@click="toggleDiscussion({ discussionId: discussion.id })"
>
- <gl-icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
- <template v-else>
- {{ index + 1 }}
- </template>
+ <gl-icon name="collapse" class="collapse-icon" />
</button>
+ <design-note-pin
+ v-else
+ :label="index + 1"
+ :is-resolved="discussion.resolved"
+ size="sm"
+ class="js-diff-notes-toggle gl-translate-x-n50"
+ @click="toggleDiscussion({ discussionId: discussion.id })"
+ />
</template>
<noteable-discussion
v-show="isExpanded(discussion)"
@@ -87,9 +91,12 @@ export default {
@noteDeleted="deleteNoteHandler"
>
<template v-if="renderAvatarBadge" #avatar-badge>
- <span class="badge badge-pill">
- {{ index + 1 }}
- </span>
+ <design-note-pin
+ :label="index + 1"
+ class="user-avatar"
+ :is-resolved="discussion.resolved"
+ size="sm"
+ />
</template>
</noteable-discussion>
</ul>
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index edff2e67b20..4c7b8e8f667 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -223,25 +223,31 @@ export default {
<template>
<div class="content js-line-expansion-content">
- <a
- v-if="canExpandDown"
- class="gl-mx-2 gl-cursor-pointer js-unfold-down gl-display-inline-block gl-py-4"
+ <button
+ type="button"
+ :disabled="!canExpandDown"
+ class="js-unfold-down gl-mx-2 gl-py-4 gl-cursor-pointer"
@click="handleExpandLines(EXPAND_DOWN)"
>
<gl-icon :size="12" name="expand-down" />
<span>{{ $options.i18n.showMore }}</span>
- </a>
- <a class="gl-mx-2 cursor-pointer js-unfold-all" @click="handleExpandLines()">
+ </button>
+ <button
+ type="button"
+ class="js-unfold-all gl-mx-2 gl-py-4 gl-cursor-pointer"
+ @click="handleExpandLines()"
+ >
<gl-icon :size="12" name="expand" />
<span>{{ $options.i18n.showAll }}</span>
- </a>
- <a
- v-if="canExpandUp"
- class="gl-mx-2 gl-cursor-pointer js-unfold gl-display-inline-block gl-py-4"
+ </button>
+ <button
+ type="button"
+ :disabled="!canExpandUp"
+ class="js-unfold gl-mx-2 gl-py-4 gl-cursor-pointer"
@click="handleExpandLines(EXPAND_UP)"
>
<gl-icon :size="12" name="expand-up" />
<span>{{ $options.i18n.showMore }}</span>
- </a>
+ </button>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 238f07ac22c..3cf1f69b08c 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -3,6 +3,7 @@ import {
GlTooltipDirective,
GlSafeHtmlDirective,
GlIcon,
+ GlBadge,
GlButton,
GlButtonGroup,
GlDropdown,
@@ -34,6 +35,7 @@ export default {
GlIcon,
FileIcon,
DiffStats,
+ GlBadge,
GlButton,
GlButtonGroup,
GlDropdown,
@@ -207,7 +209,7 @@ export default {
handler(val) {
const el = this.$el.closest('.vue-recycle-scroller__item-view');
- if (this.glFeatures.diffsVirtualScrolling && el) {
+ if (el) {
// We can't add a style with Vue because of the way the virtual
// scroller library renders the diff files
el.style.zIndex = val ? '1' : null;
@@ -349,7 +351,9 @@ export default {
{{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
- <span v-if="isUsingLfs" class="badge label label-lfs gl-mr-2"> {{ __('LFS') }} </span>
+ <gl-badge v-if="isUsingLfs" variant="neutral" class="gl-mr-2" data-testid="label-lfs">{{
+ __('LFS')
+ }}</gl-badge>
</div>
<div
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 8562a1d44e7..333bf1b356c 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -153,21 +153,38 @@ export default {
@mousedown="handleParallelLineMouseDown"
>
<template v-for="(line, index) in diffLines">
- <div
- v-if="line.isMatchLineLeft || line.isMatchLineRight"
- :key="`expand-${index}`"
- class="diff-tr line_expansion match"
- >
- <div class="diff-td text-center gl-font-regular">
- <diff-expansion-cell
- :file-hash="diffFile.file_hash"
- :context-lines-path="diffFile.context_lines_path"
- :line="line.left"
- :is-top="index === 0"
- :is-bottom="index + 1 === diffLinesLength"
- />
+ <template v-if="line.isMatchLineLeft || line.isMatchLineRight">
+ <div :key="`expand-${index}`" class="diff-tr line_expansion match">
+ <div class="diff-td text-center gl-font-regular">
+ <diff-expansion-cell
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
+ </div>
</div>
- </div>
+ <div
+ v-if="line.left.rich_text"
+ :key="`expand-definition-${index}`"
+ class="diff-grid-row diff-tr line_holder match"
+ >
+ <div class="diff-grid-left diff-grid-3-col left-side">
+ <div class="diff-td diff-line-num"></div>
+ <div v-if="inline" class="diff-td diff-line-num"></div>
+ <div class="diff-td line_content left-side gl-white-space-normal!">
+ {{ line.left.rich_text }}
+ </div>
+ </div>
+ <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side">
+ <div class="diff-td diff-line-num"></div>
+ <div class="diff-td line_content right-side gl-white-space-normal!">
+ {{ line.left.rich_text }}
+ </div>
+ </div>
+ </div>
+ </template>
<diff-row
v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
:key="line.line_code"
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index eede8e52292..8871be1f9af 100644
--- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -1,8 +1,8 @@
<script>
-import { GlIcon } from '@gitlab/ui';
import { isArray } from 'lodash';
import { mapActions, mapGetters } from 'vuex';
import imageDiffMixin from 'ee_else_ce/diffs/mixins/image_diff';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
function calcPercent(pos, renderedSize) {
return (100 * pos) / renderedSize;
@@ -11,7 +11,7 @@ function calcPercent(pos, renderedSize) {
export default {
name: 'ImageDiffOverlay',
components: {
- GlIcon,
+ DesignNotePin,
},
mixins: [imageDiffMixin],
props: {
@@ -36,7 +36,7 @@ export default {
badgeClass: {
type: String,
required: false,
- default: 'badge badge-pill',
+ default: '',
},
shouldToggleDiscussion: {
type: Boolean,
@@ -114,30 +114,28 @@ export default {
>
<span class="sr-only"> {{ __('Add image comment') }} </span>
</button>
- <button
+
+ <design-note-pin
v-for="(discussion, index) in allDiscussions"
:key="discussion.id"
- :style="getPosition(discussion)"
- :class="[badgeClass, { 'is-draft': discussion.isDraft }]"
- :disabled="!shouldToggleDiscussion"
- class="js-image-badge"
- type="button"
+ :label="showCommentIcon ? null : toggleText(discussion, index)"
+ :position="getPosition(discussion)"
:aria-label="__('Show comments')"
+ class="js-image-badge"
+ :class="badgeClass"
+ :is-draft="discussion.isDraft"
+ :is-resolved="discussion.resolved"
+ is-on-image
+ :disabled="!shouldToggleDiscussion"
@click="clickedToggle(discussion)"
- >
- <gl-icon v-if="showCommentIcon" name="image-comment-dark" :size="24" />
- <template v-else>
- {{ toggleText(discussion, index) }}
- </template>
- </button>
- <button
+ />
+
+ <design-note-pin
v-if="canComment && currentCommentForm"
- :style="{ left: `${currentCommentForm.xPercent}%`, top: `${currentCommentForm.yPercent}%` }"
- :aria-label="__('Comment form position')"
- class="btn-transparent comment-indicator position-absolute"
- type="button"
- >
- <gl-icon name="image-comment-dark" :size="24" />
- </button>
+ :position="{
+ left: `${currentCommentForm.xPercent}%`,
+ top: `${currentCommentForm.yPercent}%`,
+ }"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/merge_conflict_warning.vue b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
index 587efd6ed41..6e1e6f5c2d0 100644
--- a/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
+++ b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
@@ -1,6 +1,5 @@
<script>
import { GlButton, GlAlert, GlModalDirective } from '@gitlab/ui';
-import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
export default {
components: {
@@ -11,10 +10,6 @@ export default {
GlModalDirective,
},
props: {
- limited: {
- type: Boolean,
- required: true,
- },
mergeable: {
type: Boolean,
required: true,
@@ -24,18 +19,11 @@ export default {
required: true,
},
},
- computed: {
- containerClasses() {
- return {
- [CENTERED_LIMITED_CONTAINER_CLASSES]: this.limited,
- };
- },
- },
};
</script>
<template>
- <div :class="containerClasses">
+ <div>
<gl-alert
:dismissible="false"
:title="__('There are merge conflicts')"
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 93961b07e2e..bbe27c0dbd6 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -29,8 +29,6 @@ export const UNFOLD_COUNT = 20;
export const COUNT_OF_AVATARS_IN_GUTTER = 3;
export const LENGTH_OF_AVATAR_TOOLTIP = 17;
-export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
-
export const DIFF_FILE_SYMLINK_MODE = '120000';
export const DIFF_FILE_DELETED_MODE = '0';
@@ -42,7 +40,6 @@ export const TREE_LIST_WIDTH_STORAGE_KEY = 'mr_tree_list_width';
export const INITIAL_TREE_WIDTH = 320;
export const MIN_TREE_WIDTH = 240;
-export const MAX_TREE_WIDTH = 400;
export const TREE_HIDE_STATS_WIDTH = 260;
export const OLD_LINE_KEY = 'old_line';
@@ -50,9 +47,6 @@ export const NEW_LINE_KEY = 'new_line';
export const TYPE_KEY = 'type';
export const LEFT_LINE_KEY = 'left';
-export const CENTERED_LIMITED_CONTAINER_CLASSES =
- 'container-limited limit-container-width mx-lg-auto px-3';
-
export const MAX_RENDERING_DIFF_LINES = 500;
export const MAX_RENDERING_BULK_ROWS = 30;
export const MIN_RENDERING_MS = 2;
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 260ebdf2141..1691da34c6d 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -1,8 +1,7 @@
-import Cookies from 'js-cookie';
import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import { getParameterValues } from '~/lib/utils/url_utility';
+import { getCookie, parseBoolean, removeCookie } from '~/lib/utils/common_utils';
+
import eventHub from '../notes/event_hub';
import diffsApp from './components/app.vue';
@@ -58,14 +57,14 @@ export default function initDiffsApp(store) {
// 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);
+ if (getCookie(DIFF_WHITESPACE_COOKIE_NAME)) {
+ const hideWhitespace = getCookie(DIFF_WHITESPACE_COOKIE_NAME);
this.setShowWhitespace({
url: this.endpointUpdateUser,
showWhitespace: hideWhitespace !== '1',
trackClick: false,
});
- Cookies.remove(DIFF_WHITESPACE_COOKIE_NAME);
+ removeCookie(DIFF_WHITESPACE_COOKIE_NAME);
} else {
// This is only to set the the user preference in Vuex for use later
this.setShowWhitespace({
@@ -74,11 +73,6 @@ export default function initDiffsApp(store) {
trackClick: false,
});
}
-
- const vScrollingParam = getParameterValues('virtual_scrolling')[0];
- if (vScrollingParam === 'false' || vScrollingParam === 'true') {
- Cookies.set('diffs_virtual_scrolling', vScrollingParam);
- }
},
methods: {
...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']),
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 692cb913a57..e967be23f42 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -1,9 +1,14 @@
-import Cookies from 'js-cookie';
import Vue from 'vue';
+import {
+ setCookie,
+ handleLocationHash,
+ historyPushState,
+ scrollToElement,
+} from '~/lib/utils/common_utils';
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';
+
import httpStatusCodes from '~/lib/utils/http_status';
import Poll from '~/lib/utils/poll';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
@@ -120,7 +125,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
commit(types.SET_DIFF_DATA_BATCH, { diff_files });
commit(types.SET_BATCH_LOADING_STATE, 'loaded');
- if (window.gon?.features?.diffsVirtualScrolling && !scrolledVirtualScroller) {
+ if (!scrolledVirtualScroller) {
const index = state.diffFiles.findIndex(
(f) =>
f.file_hash === hash || f[INLINE_DIFF_LINES_KEY].find((l) => l.line_code === hash),
@@ -190,9 +195,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
commit(types.SET_BATCH_LOADING_STATE, 'error');
});
- return getBatch().then(
- () => !window.gon?.features?.diffsVirtualScrolling && handleLocationHash(),
- );
+ return getBatch();
};
export const fetchDiffFilesMeta = ({ commit, state }) => {
@@ -369,7 +372,7 @@ export const setRenderIt = ({ commit }, file) => commit(types.RENDER_FILE, file)
export const setInlineDiffViewType = ({ commit }) => {
commit(types.SET_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE);
- Cookies.set(DIFF_VIEW_COOKIE_NAME, INLINE_DIFF_VIEW_TYPE);
+ setCookie(DIFF_VIEW_COOKIE_NAME, INLINE_DIFF_VIEW_TYPE);
const url = mergeUrlParams({ view: INLINE_DIFF_VIEW_TYPE }, window.location.href);
historyPushState(url);
@@ -381,7 +384,7 @@ export const setInlineDiffViewType = ({ commit }) => {
export const setParallelDiffViewType = ({ commit }) => {
commit(types.SET_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE);
- Cookies.set(DIFF_VIEW_COOKIE_NAME, PARALLEL_DIFF_VIEW_TYPE);
+ setCookie(DIFF_VIEW_COOKIE_NAME, PARALLEL_DIFF_VIEW_TYPE);
const url = mergeUrlParams({ view: PARALLEL_DIFF_VIEW_TYPE }, window.location.href);
historyPushState(url);
@@ -524,7 +527,7 @@ export const setCurrentFileHash = ({ commit }, hash) => {
commit(types.SET_CURRENT_DIFF_FILE, hash);
};
-export const scrollToFile = ({ state, commit, getters }, { path, setHash = true }) => {
+export const scrollToFile = ({ state, commit, getters }, { path }) => {
if (!state.treeEntries[path]) return;
const { fileHash } = state.treeEntries[path];
@@ -534,11 +537,9 @@ export const scrollToFile = ({ state, commit, getters }, { path, setHash = true
if (getters.isVirtualScrollingEnabled) {
eventHub.$emit('scrollToFileHash', fileHash);
- if (setHash) {
- setTimeout(() => {
- window.history.replaceState(null, null, `#${fileHash}`);
- });
- }
+ setTimeout(() => {
+ window.history.replaceState(null, null, `#${fileHash}`);
+ });
} else {
document.location.hash = fileHash;
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index ca85be5d829..3a85c1a9fe1 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,6 +1,5 @@
-import Cookies from 'js-cookie';
-import { getParameterValues } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
+import { getParameterValues } from '~/lib/utils/url_utility';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
@@ -175,21 +174,11 @@ export function suggestionCommitMessage(state, _, rootState) {
}
export const isVirtualScrollingEnabled = (state) => {
- const vSrollerCookie = Cookies.get('diffs_virtual_scrolling');
-
- if (state.disableVirtualScroller) {
+ if (state.disableVirtualScroller || getParameterValues('virtual_scrolling')[0] === 'false') {
return false;
}
- if (vSrollerCookie) {
- return vSrollerCookie === 'true';
- }
-
- return (
- !state.viewDiffsFileByFile &&
- (window.gon?.features?.diffsVirtualScrolling ||
- getParameterValues('virtual_scrolling')[0] === 'true')
- );
+ return !state.viewDiffsFileByFile;
};
export const isBatchLoading = (state) => state.batchLoadingState === 'loading';
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 5f66360a040..329db1fe2cf 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -1,10 +1,10 @@
-import Cookies from 'js-cookie';
+import { getCookie } from '~/lib/utils/common_utils';
import { getParameterValues } from '~/lib/utils/url_utility';
import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME } from '../../constants';
const getViewTypeFromQueryString = () => getParameterValues('view')[0];
-const viewTypeFromCookie = Cookies.get(DIFF_VIEW_COOKIE_NAME);
+const viewTypeFromCookie = getCookie(DIFF_VIEW_COOKIE_NAME);
const defaultViewType = INLINE_DIFF_VIEW_TYPE;
export default () => ({
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 3f1af68e37a..f2028892a5f 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -9,7 +9,6 @@ import {
NEW_LINE_TYPE,
OLD_LINE_TYPE,
MATCH_LINE_TYPE,
- LINES_TO_BE_RENDERED_DIRECTLY,
INLINE_DIFF_LINES_KEY,
CONFLICT_OUR,
CONFLICT_THEIR,
@@ -380,16 +379,9 @@ function prepareDiffFileLines(file) {
return file;
}
-function finalizeDiffFile(file, index) {
- let renderIt = Boolean(window.gon?.features?.diffsVirtualScrolling);
-
- if (!window.gon?.features?.diffsVirtualScrolling) {
- renderIt =
- index < 3 ? file[INLINE_DIFF_LINES_KEY].length < LINES_TO_BE_RENDERED_DIRECTLY : false;
- }
-
+function finalizeDiffFile(file) {
Object.assign(file, {
- renderIt,
+ renderIt: true,
isShowingFullFile: false,
isLoadingFullFile: false,
discussions: [],
@@ -417,15 +409,13 @@ export function prepareDiffData({ diff, priorFiles = [], meta = false }) {
.map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta }))
.map(ensureBasicDiffFileLines)
.map(prepareDiffFileLines)
- .map((file, index) => finalizeDiffFile(file, priorFiles.length + index));
+ .map((file) => finalizeDiffFile(file));
return deduplicateFilesList([...priorFiles, ...cleanedFiles]);
}
export function getDiffPositionByLineCode(diffFiles) {
- let lines = [];
-
- lines = diffFiles.reduce((acc, diffFile) => {
+ const lines = diffFiles.reduce((acc, diffFile) => {
diffFile[INLINE_DIFF_LINES_KEY].forEach((line) => {
acc.push({ file: diffFile, line });
});
diff --git a/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
index 05ce617ca7c..2fba02f212b 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
@@ -20,33 +20,6 @@ export class YamlEditorExtension {
}
/**
- * Extends the source editor with capabilities for yaml files.
- *
- * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
- * @param {YamlEditorExtensionOptions} setupOptions
- */
- onSetup(instance, setupOptions = {}) {
- const { enableComments = false, highlightPath = null, model = null } = setupOptions;
- this.enableComments = enableComments;
- this.highlightPath = highlightPath;
- this.model = model;
-
- if (model) {
- this.initFromModel(instance, model);
- }
-
- instance.onDidChangeModelContent(() => instance.onUpdate());
- }
-
- initFromModel(instance, model) {
- const doc = new Document(model);
- if (this.enableComments) {
- YamlEditorExtension.transformComments(doc);
- }
- instance.setValue(doc.toString());
- }
-
- /**
* @private
* This wraps long comments to a maximum line length of 80 chars.
*
@@ -164,10 +137,10 @@ export class YamlEditorExtension {
if (!path) throw Error(`No path provided.`);
const blob = instance.getValue();
const doc = parseDocument(blob);
- const pathArray = toPath(path);
+ const pathArray = Array.isArray(path) ? path : toPath(path);
if (!doc.getIn(pathArray)) {
- throw Error(`The node ${path} could not be found inside the document.`);
+ return [null, null];
}
const parentNode = doc.getIn(pathArray.slice(0, pathArray.length - 1));
@@ -190,6 +163,33 @@ export class YamlEditorExtension {
return [startLine, endLine];
}
+ /**
+ * Extends the source editor with capabilities for yaml files.
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param {YamlEditorExtensionOptions} setupOptions
+ */
+ onSetup(instance, setupOptions = {}) {
+ const { enableComments = false, highlightPath = null, model = null } = setupOptions;
+ this.enableComments = enableComments;
+ this.highlightPath = highlightPath;
+ this.model = model;
+
+ if (model) {
+ this.initFromModel(instance, model);
+ }
+
+ instance.onDidChangeModelContent(() => instance.onUpdate());
+ }
+
+ initFromModel(instance, model) {
+ const doc = new Document(model);
+ if (this.enableComments) {
+ YamlEditorExtension.transformComments(doc);
+ }
+ instance.setValue(doc.toString());
+ }
+
setDoc(instance, doc) {
if (this.enableComments) {
YamlEditorExtension.transformComments(doc);
@@ -202,18 +202,31 @@ export class YamlEditorExtension {
}
}
- highlight(instance, path) {
+ highlight(instance, path, keepOnNotFound = false) {
// IMPORTANT
// removeHighlight and highlightLines both come from
// SourceEditorExtension. So it has to be installed prior to this extension
if (this.highlightPath === path) return;
- if (!path) {
+
+ if (!path || !path.length) {
instance.removeHighlights();
- } else {
- const res = YamlEditorExtension.locate(instance, path);
- instance.highlightLines(res);
+ this.highlightPath = null;
+ return;
}
- this.highlightPath = path || null;
+
+ const [startLine, endLine] = YamlEditorExtension.locate(instance, path);
+
+ if (startLine === null) {
+ // Path could not be found.
+ if (!keepOnNotFound) {
+ instance.removeHighlights();
+ this.highlightPath = null;
+ }
+ return;
+ }
+
+ instance.highlightLines([startLine, endLine]);
+ this.highlightPath = path;
}
provides() {
@@ -283,18 +296,23 @@ export class YamlEditorExtension {
* Add a line highlight style to the node specified by the path.
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
- * @param {string|null|false} path A path to a node of the Editor's value,
+ * @param {string|(string|number)[]|null|false} path A path to a node
+ * of the Editor's
+ * value,
* e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
* highlights.
+ * @param {boolean} [keepOnNotFound=false] If the passed path cannot
+ * be located, keep the previous highlight state
*/
- highlight: (instance, path) => this.highlight(instance, path),
+ highlight: (instance, path, keepOnNotFound) => this.highlight(instance, path, keepOnNotFound),
/**
* Return the line numbers of a certain node identified by `path` within
* the yaml.
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
- * @param {string} path A path to a node, eg. `foo.bar[0]`
+ * @param {string|(string|number)[]} path A path to a node, eg.
+ * `foo.bar[0]`
* @returns {number[]} Array following the schema `[firstLine, lastLine]`
* (both inclusive)
*
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index f0db3e5594b..4d9fe6ff851 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -765,6 +765,9 @@
"filter": {
"oneOf": [
{
+ "type": "null"
+ },
+ {
"$ref": "#/definitions/filter_refs"
},
{
diff --git a/app/assets/javascripts/emoji/awards_app/index.js b/app/assets/javascripts/emoji/awards_app/index.js
index 1a084d37762..0986533dcd1 100644
--- a/app/assets/javascripts/emoji/awards_app/index.js
+++ b/app/assets/javascripts/emoji/awards_app/index.js
@@ -12,6 +12,7 @@ export default (el) => {
return new Vue({
el,
+ name: 'AwardsListRoot',
store: createstore(),
computed: {
...mapState(['currentUserId', 'canAwardEmoji', 'awards']),
diff --git a/app/assets/javascripts/emoji/awards_app/store/actions.js b/app/assets/javascripts/emoji/awards_app/store/actions.js
index f0340209248..f83bfe614dd 100644
--- a/app/assets/javascripts/emoji/awards_app/store/actions.js
+++ b/app/assets/javascripts/emoji/awards_app/store/actions.js
@@ -33,20 +33,51 @@ export const fetchAwards = async ({ commit, dispatch, state }, page = '1') => {
}
};
+/**
+ * Creates an intermediary award, used for display
+ * until the real award is loaded from the backend.
+ */
+const newOptimisticAward = (name, state) => {
+ const freeId = Math.min(...state.awards.map((a) => a.id), Number.MAX_SAFE_INTEGER) - 1;
+ return {
+ id: freeId,
+ name,
+ user: {
+ id: window.gon.current_user_id,
+ name: window.gon.current_user_fullname,
+ username: window.gon.current_username,
+ },
+ };
+};
+
export const toggleAward = async ({ commit, state }, name) => {
const award = state.awards.find((a) => a.name === name && a.user.id === state.currentUserId);
try {
if (award) {
- await axios.delete(joinPaths(gon.relative_url_root || '', `${state.path}/${award.id}`));
-
commit(REMOVE_AWARD, award.id);
+ await axios
+ .delete(joinPaths(gon.relative_url_root || '', `${state.path}/${award.id}`))
+ .catch((err) => {
+ commit(ADD_NEW_AWARD, award);
+
+ throw err;
+ });
+
showToast(__('Award removed'));
} else {
- const { data } = await axios.post(joinPaths(gon.relative_url_root || '', state.path), {
- name,
- });
+ const optimisticAward = newOptimisticAward(name, state);
+
+ commit(ADD_NEW_AWARD, optimisticAward);
+
+ const { data } = await axios
+ .post(joinPaths(gon.relative_url_root || '', state.path), {
+ name,
+ })
+ .finally(() => {
+ commit(REMOVE_AWARD, optimisticAward.id);
+ });
commit(ADD_NEW_AWARD, data);
diff --git a/app/assets/javascripts/emoji/components/utils.js b/app/assets/javascripts/emoji/components/utils.js
index 3465a8ae7e6..5eec0992896 100644
--- a/app/assets/javascripts/emoji/components/utils.js
+++ b/app/assets/javascripts/emoji/components/utils.js
@@ -1,5 +1,5 @@
-import Cookies from 'js-cookie';
import { chunk, memoize, uniq } from 'lodash';
+import { getCookie, setCookie } from '~/lib/utils/common_utils';
import { initEmojiMap, getEmojiCategoryMap } from '~/emoji';
import {
EMOJIS_PER_ROW,
@@ -13,7 +13,7 @@ export const generateCategoryHeight = (emojisLength) =>
emojisLength * EMOJI_ROW_HEIGHT + CATEGORY_ROW_HEIGHT;
export const getFrequentlyUsedEmojis = () => {
- const savedEmojis = Cookies.get(FREQUENTLY_USED_COOKIE_KEY);
+ const savedEmojis = getCookie(FREQUENTLY_USED_COOKIE_KEY);
if (!savedEmojis) return null;
@@ -30,13 +30,13 @@ export const getFrequentlyUsedEmojis = () => {
export const addToFrequentlyUsed = (emoji) => {
const frequentlyUsedEmojis = uniq(
- (Cookies.get(FREQUENTLY_USED_COOKIE_KEY) || '')
+ (getCookie(FREQUENTLY_USED_COOKIE_KEY) || '')
.split(',')
.filter((e) => e)
.concat(emoji),
);
- Cookies.set(FREQUENTLY_USED_COOKIE_KEY, frequentlyUsedEmojis.join(','), { expires: 365 });
+ setCookie(FREQUENTLY_USED_COOKIE_KEY, frequentlyUsedEmojis.join(','));
};
export const hasFrequentlyUsedEmojis = () => getFrequentlyUsedEmojis() !== null;
diff --git a/app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js b/app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js
new file mode 100644
index 00000000000..012cf949c96
--- /dev/null
+++ b/app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js
@@ -0,0 +1,3 @@
+import { initRedirectListboxBehavior } from '~/listbox/redirect_behavior';
+
+initRedirectListboxBehavior();
diff --git a/app/assets/javascripts/environments/components/canary_ingress.vue b/app/assets/javascripts/environments/components/canary_ingress.vue
index 02d660a91c1..30f3f9dfc75 100644
--- a/app/assets/javascripts/environments/components/canary_ingress.vue
+++ b/app/assets/javascripts/environments/components/canary_ingress.vue
@@ -17,6 +17,11 @@ export default {
required: true,
type: Object,
},
+ graphql: {
+ required: false,
+ type: Boolean,
+ default: false,
+ },
},
ingressOptions: Array(100 / 5 + 1)
.fill(0)
@@ -47,11 +52,17 @@ export default {
canaryWeightId() {
return uniqueId('canary-weight-');
},
+ weight() {
+ if (this.graphql) {
+ return this.canaryIngress.canaryWeight;
+ }
+ return this.canaryIngress.canary_weight;
+ },
stableWeight() {
- return (100 - this.canaryIngress.canary_weight).toString();
+ return (100 - this.weight).toString();
},
canaryWeight() {
- return this.canaryIngress.canary_weight.toString();
+ return this.weight.toString();
},
},
methods: {
diff --git a/app/assets/javascripts/environments/components/canary_update_modal.vue b/app/assets/javascripts/environments/components/canary_update_modal.vue
index 8b1121c7158..fd4885a9dbd 100644
--- a/app/assets/javascripts/environments/components/canary_update_modal.vue
+++ b/app/assets/javascripts/environments/components/canary_update_modal.vue
@@ -71,7 +71,7 @@ export default {
mutation: updateCanaryIngress,
variables: {
input: {
- id: this.environment.global_id,
+ id: this.environment.global_id || this.environment.globalId,
weight: this.weight,
},
},
diff --git a/app/assets/javascripts/environments/components/commit.vue b/app/assets/javascripts/environments/components/commit.vue
new file mode 100644
index 00000000000..54b94480685
--- /dev/null
+++ b/app/assets/javascripts/environments/components/commit.vue
@@ -0,0 +1,54 @@
+<script>
+import { GlAvatar, GlAvatarLink, GlLink, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
+import { escape } from 'lodash';
+
+export default {
+ components: {
+ GlAvatar,
+ GlAvatarLink,
+ GlLink,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ commit: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ commitMessage() {
+ return this.commit?.message;
+ },
+ commitAuthorPath() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return this.commit?.author?.path || `mailto:${escape(this.commit?.authorEmail)}`;
+ },
+ commitAuthorAvatar() {
+ return this.commit?.author?.avatarUrl || this.commit?.authorGravatarUrl;
+ },
+ commitAuthor() {
+ return this.commit?.author?.name || this.commit?.authorName;
+ },
+ commitPath() {
+ return this.commit?.commitPath;
+ },
+ },
+};
+</script>
+<template>
+ <div data-testid="deployment-commit" class="gl-display-flex gl-align-items-center">
+ <gl-avatar-link v-gl-tooltip :title="commitAuthor" :href="commitAuthorPath">
+ <gl-avatar :size="16" :src="commitAuthorAvatar" />
+ </gl-avatar-link>
+ <gl-link
+ v-gl-tooltip
+ :title="commitMessage"
+ :href="commitPath"
+ class="gl-ml-3 gl-str-truncated"
+ >
+ {{ commitMessage }}
+ </gl-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/deploy_board.vue b/app/assets/javascripts/environments/components/deploy_board.vue
index c642a07fd1e..8a379ebdf66 100644
--- a/app/assets/javascripts/environments/components/deploy_board.vue
+++ b/app/assets/javascripts/environments/components/deploy_board.vue
@@ -1,5 +1,4 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
/**
* Renders a deploy board.
*
@@ -17,11 +16,11 @@ import {
GlTooltip,
GlTooltipDirective,
GlSafeHtmlDirective as SafeHtml,
+ GlSprintf,
} from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import { n__ } from '~/locale';
+import { s__, n__ } from '~/locale';
import instanceComponent from '~/vue_shared/components/deployment_instance.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { STATUS_MAP, CANARY_STATUS } from '../constants';
import CanaryIngress from './canary_ingress.vue';
@@ -32,13 +31,13 @@ export default {
GlIcon,
GlLoadingIcon,
GlLink,
+ GlSprintf,
GlTooltip,
},
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
- mixins: [glFeatureFlagsMixin()],
props: {
deployBoardData: {
type: Object,
@@ -57,6 +56,11 @@ export default {
required: false,
default: '',
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
canRenderDeployBoard() {
@@ -65,8 +69,15 @@ export default {
canRenderEmptyState() {
return this.isEmpty;
},
+ canaryIngress() {
+ if (this.graphql) {
+ return this.deployBoardData.canaryIngress;
+ }
+
+ return this.deployBoardData.canary_ingress;
+ },
canRenderCanaryWeight() {
- return !isEmpty(this.deployBoardData.canary_ingress);
+ return !isEmpty(this.canaryIngress);
},
instanceCount() {
const { instances } = this.deployBoardData;
@@ -90,8 +101,20 @@ export default {
deployBoardSvg() {
return deployBoardSvg;
},
+ rollbackUrl() {
+ if (this.graphql) {
+ return this.deployBoardData.rollbackUrl;
+ }
+ return this.deployBoardData.rollback_url;
+ },
+ abortUrl() {
+ if (this.graphql) {
+ return this.deployBoardData.abortUrl;
+ }
+ return this.deployBoardData.abort_url;
+ },
deployBoardActions() {
- return this.deployBoardData.rollback_url || this.deployBoardData.abort_url;
+ return this.rollbackUrl || this.abortUrl;
},
statuses() {
// Canary is not a pod status but it needs to be in the legend.
@@ -106,7 +129,17 @@ export default {
changeCanaryWeight(weight) {
this.$emit('changeCanaryWeight', weight);
},
+ podName(instance) {
+ if (this.graphql) {
+ return instance.podName;
+ }
+
+ return instance.pod_name;
+ },
},
+ emptyStateText: s__(
+ 'DeployBoards|To see deployment progress for your environments, make sure you are deploying to %{codeStart}$KUBE_NAMESPACE%{codeEnd} and annotating with %{codeStart}app.gitlab.com/app=$CI_PROJECT_PATH_SLUG%{codeEnd} and %{codeStart}app.gitlab.com/env=$CI_ENVIRONMENT_SLUG%{codeEnd}.',
+ ),
};
</script>
<template>
@@ -152,7 +185,7 @@ export default {
:key="i"
:status="instance.status"
:tooltip-text="instance.tooltip"
- :pod-name="instance.pod_name"
+ :pod-name="podName(instance)"
:logs-path="logsPath"
:stable="instance.stable"
/>
@@ -163,22 +196,23 @@ export default {
<canary-ingress
v-if="canRenderCanaryWeight"
class="deploy-board-canary-ingress"
- :canary-ingress="deployBoardData.canary_ingress"
+ :canary-ingress="canaryIngress"
+ :graphql="graphql"
@change="changeCanaryWeight"
/>
<section v-if="deployBoardActions" class="deploy-board-actions">
<gl-link
- v-if="deployBoardData.rollback_url"
- :href="deployBoardData.rollback_url"
+ v-if="rollbackUrl"
+ :href="rollbackUrl"
class="btn"
data-method="post"
rel="nofollow"
>{{ __('Rollback') }}</gl-link
>
<gl-link
- v-if="deployBoardData.abort_url"
- :href="deployBoardData.abort_url"
+ v-if="abortUrl"
+ :href="abortUrl"
class="btn btn-danger btn-inverted"
data-method="post"
rel="nofollow"
@@ -196,11 +230,11 @@ export default {
__('Kubernetes deployment not found')
}}</span>
<span>
- To see deployment progress for your environments, make sure you are deploying to
- <code>$KUBE_NAMESPACE</code> and annotating with
- <code>app.gitlab.com/app=$CI_PROJECT_PATH_SLUG</code>
- and
- <code>app.gitlab.com/env=$CI_ENVIRONMENT_SLUG</code>.
+ <gl-sprintf :message="$options.emptyStateText">
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
</span>
</section>
</div>
diff --git a/app/assets/javascripts/environments/components/deploy_board_wrapper.vue b/app/assets/javascripts/environments/components/deploy_board_wrapper.vue
new file mode 100644
index 00000000000..d9d77088ad3
--- /dev/null
+++ b/app/assets/javascripts/environments/components/deploy_board_wrapper.vue
@@ -0,0 +1,86 @@
+<script>
+import { GlCollapse, GlButton } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import setEnvironmentToChangeCanaryMutation from '../graphql/mutations/set_environment_to_change_canary.mutation.graphql';
+import DeployBoard from './deploy_board.vue';
+
+export default {
+ components: {
+ DeployBoard,
+ GlButton,
+ GlCollapse,
+ },
+ props: {
+ rolloutStatus: {
+ required: true,
+ type: Object,
+ },
+ environment: {
+ required: true,
+ type: Object,
+ },
+ },
+ data() {
+ return { visible: false };
+ },
+ computed: {
+ icon() {
+ return this.visible ? 'angle-down' : 'angle-right';
+ },
+ label() {
+ return this.visible ? this.$options.i18n.collapse : this.$options.i18n.expand;
+ },
+ isLoading() {
+ return this.rolloutStatus.status === 'loading';
+ },
+ isEmpty() {
+ return this.rolloutStatus.status === 'not_found';
+ },
+ },
+ methods: {
+ toggleCollapse() {
+ this.visible = !this.visible;
+ },
+ changeCanaryWeight(weight) {
+ this.$apollo.mutate({
+ mutation: setEnvironmentToChangeCanaryMutation,
+ variables: {
+ environment: this.environment,
+ weight,
+ },
+ });
+ },
+ },
+ i18n: {
+ collapse: __('Collapse'),
+ expand: __('Expand'),
+ pods: s__('DeployBoard|Kubernetes Pods'),
+ },
+};
+</script>
+<template>
+ <div>
+ <div>
+ <gl-button
+ class="gl-mr-4 gl-min-w-fit-content"
+ :icon="icon"
+ :aria-label="label"
+ size="small"
+ category="tertiary"
+ @click="toggleCollapse"
+ />
+ <span>{{ $options.i18n.pods }}</span>
+ </div>
+ <gl-collapse :visible="visible">
+ <deploy-board
+ :deploy-board-data="rolloutStatus"
+ :is-loading="isLoading"
+ :is-empty="isEmpty"
+ :environment="environment"
+ graphql
+ class="gl-reset-bg!"
+ @changeCanaryWeight="changeCanaryWeight"
+ />
+ </gl-collapse>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/deployment.vue b/app/assets/javascripts/environments/components/deployment.vue
index ef43ca6bc33..f98edb6bb7d 100644
--- a/app/assets/javascripts/environments/components/deployment.vue
+++ b/app/assets/javascripts/environments/components/deployment.vue
@@ -1,25 +1,240 @@
<script>
+import {
+ GlBadge,
+ GlButton,
+ GlCollapse,
+ GlIcon,
+ GlLink,
+ GlTooltipDirective as GlTooltip,
+ GlTruncate,
+} from '@gitlab/ui';
+import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
+import { __, s__ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DeploymentStatusBadge from './deployment_status_badge.vue';
+import Commit from './commit.vue';
export default {
components: {
+ ClipboardButton,
+ Commit,
DeploymentStatusBadge,
+ GlBadge,
+ GlButton,
+ GlCollapse,
+ GlIcon,
+ GlLink,
+ GlTruncate,
+ TimeAgoTooltip,
+ },
+ directives: {
+ GlTooltip,
},
props: {
deployment: {
type: Object,
required: true,
},
+ latest: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ },
+ data() {
+ return { visible: false };
},
computed: {
status() {
return this.deployment?.status;
},
+ iid() {
+ return this.deployment?.iid;
+ },
+ shortSha() {
+ return this.commit?.shortId;
+ },
+ createdAt() {
+ return this.deployment?.createdAt;
+ },
+ isMobile() {
+ return !GlBreakpointInstance.isDesktop();
+ },
+ detailsButton() {
+ return this.visible
+ ? { text: this.$options.i18n.hideDetails, icon: 'expand-up' }
+ : { text: this.$options.i18n.showDetails, icon: 'expand-down' };
+ },
+ detailsButtonClasses() {
+ return this.isMobile ? 'gl-sr-only' : '';
+ },
+ commit() {
+ return this.deployment?.commit;
+ },
+ user() {
+ return this.deployment?.user;
+ },
+ username() {
+ return `@${this.user.username}`;
+ },
+ userPath() {
+ return this.user?.path;
+ },
+ deployable() {
+ return this.deployment?.deployable;
+ },
+ jobName() {
+ return this.deployable?.name;
+ },
+ jobPath() {
+ return this.deployable?.buildPath;
+ },
+ refLabel() {
+ return this.deployment?.tag ? this.$options.i18n.tag : this.$options.i18n.branch;
+ },
+ ref() {
+ return this.deployment?.ref;
+ },
+ refName() {
+ return this.ref?.name;
+ },
+ refPath() {
+ return this.ref?.refPath;
+ },
+ },
+ methods: {
+ toggleCollapse() {
+ this.visible = !this.visible;
+ },
+ },
+ i18n: {
+ latestBadge: s__('Deployment|Latest Deployed'),
+ deploymentId: s__('Deployment|Deployment ID'),
+ copyButton: __('Copy commit SHA'),
+ commitSha: __('Commit SHA'),
+ showDetails: __('Show details'),
+ hideDetails: __('Hide details'),
+ triggerer: s__('Deployment|Triggerer'),
+ job: __('Job'),
+ api: __('API'),
+ branch: __('Branch'),
+ tag: __('Tag'),
},
+ headerClasses: [
+ 'gl-display-flex',
+ 'gl-align-items-flex-start',
+ 'gl-md-align-items-center',
+ 'gl-justify-content-space-between',
+ 'gl-pr-6',
+ ],
+ headerDetailsClasses: [
+ 'gl-display-flex',
+ 'gl-flex-direction-column',
+ 'gl-md-flex-direction-row',
+ 'gl-align-items-flex-start',
+ 'gl-md-align-items-center',
+ 'gl-font-sm',
+ 'gl-text-gray-700',
+ ],
+ deploymentStatusClasses: [
+ 'gl-display-flex',
+ 'gl-gap-x-3',
+ 'gl-mr-0',
+ 'gl-md-mr-5',
+ 'gl-mb-3',
+ 'gl-md-mb-0',
+ ],
};
</script>
<template>
<div>
- <deployment-status-badge v-if="status" :status="status" />
+ <div :class="$options.headerClasses">
+ <div :class="$options.headerDetailsClasses">
+ <div :class="$options.deploymentStatusClasses">
+ <deployment-status-badge v-if="status" :status="status" />
+ <gl-badge v-if="latest" variant="info">{{ $options.i18n.latestBadge }}</gl-badge>
+ </div>
+ <div class="gl-display-flex gl-align-items-center gl-gap-x-5">
+ <div
+ v-if="iid"
+ v-gl-tooltip
+ class="gl-display-flex"
+ :title="$options.i18n.deploymentId"
+ :aria-label="$options.i18n.deploymentId"
+ >
+ <gl-icon ref="deployment-iid-icon" name="deployments" />
+ <span class="gl-ml-2">#{{ iid }}</span>
+ </div>
+ <div
+ v-if="shortSha"
+ data-testid="deployment-commit-sha"
+ class="gl-font-monospace gl-display-flex gl-align-items-center"
+ >
+ <gl-icon ref="deployment-commit-icon" name="commit" class="gl-mr-2" />
+ <span v-gl-tooltip :title="$options.i18n.commitSha">{{ shortSha }}</span>
+ <clipboard-button
+ :text="shortSha"
+ category="tertiary"
+ :title="$options.i18n.copyButton"
+ size="small"
+ />
+ </div>
+ <time-ago-tooltip v-if="createdAt" :time="createdAt" class="gl-display-flex">
+ <template #default="{ timeAgo }">
+ <gl-icon name="calendar" />
+ <span class="gl-mr-2 gl-white-space-nowrap">{{ timeAgo }}</span>
+ </template>
+ </time-ago-tooltip>
+ </div>
+ </div>
+ <gl-button
+ ref="details-toggle"
+ category="tertiary"
+ :icon="detailsButton.icon"
+ :button-text-classes="detailsButtonClasses"
+ @click="toggleCollapse"
+ >
+ {{ detailsButton.text }}
+ </gl-button>
+ </div>
+ <commit v-if="commit" :commit="commit" class="gl-mt-3" />
+ <gl-collapse :visible="visible">
+ <div
+ class="gl-display-flex gl-md-align-items-center gl-mt-5 gl-flex-direction-column gl-md-flex-direction-row gl-pr-4 gl-md-pr-0"
+ >
+ <div v-if="user" class="gl-display-flex gl-flex-direction-column gl-md-max-w-15p">
+ <span class="gl-text-gray-500">{{ $options.i18n.triggerer }}</span>
+ <gl-link :href="userPath" class="gl-font-monospace gl-mt-3">
+ <gl-truncate :text="username" with-tooltip />
+ </gl-link>
+ </div>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-md-pl-7 gl-md-max-w-15p gl-mt-4 gl-md-mt-0"
+ >
+ <span class="gl-text-gray-500" :class="{ 'gl-ml-3': !deployable }">
+ {{ $options.i18n.job }}
+ </span>
+ <gl-link v-if="jobPath" :href="jobPath" class="gl-font-monospace gl-mt-3">
+ <gl-truncate :text="jobName" with-tooltip position="middle" />
+ </gl-link>
+ <span v-else-if="jobName" class="gl-font-monospace gl-mt-3">
+ <gl-truncate :text="jobName" with-tooltip position="middle" />
+ </span>
+ <gl-badge v-else class="gl-font-monospace gl-mt-3" variant="info">
+ {{ $options.i18n.api }}
+ </gl-badge>
+ </div>
+ <div
+ v-if="ref"
+ class="gl-display-flex gl-flex-direction-column gl-md-pl-7 gl-md-max-w-15p gl-mt-4 gl-md-mt-0"
+ >
+ <span class="gl-text-gray-500">{{ refLabel }}</span>
+ <gl-link :href="refPath" class="gl-font-monospace gl-mt-3">
+ <gl-truncate :text="refName" with-tooltip />
+ </gl-link>
+ </div>
+ </div>
+ </gl-collapse>
</div>
</template>
diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue
index 977da12e8a9..36b9b647af7 100644
--- a/app/assets/javascripts/environments/components/empty_state.vue
+++ b/app/assets/javascripts/environments/components/empty_state.vue
@@ -12,10 +12,10 @@ export default {
<template>
<div class="empty-state">
<div class="text-content">
- <h4 class="blank-state-title js-blank-state-title">
+ <h4 class="js-blank-state-title">
{{ s__("Environments|You don't have any environments right now") }}
</h4>
- <p class="blank-state-text">
+ <p>
{{
s__(`Environments|Environments are places where
code gets deployed, such as staging or production.`)
diff --git a/app/assets/javascripts/environments/components/environment_pin.vue b/app/assets/javascripts/environments/components/environment_pin.vue
index 0b753d53ee3..f5a83b97552 100644
--- a/app/assets/javascripts/environments/components/environment_pin.vue
+++ b/app/assets/javascripts/environments/components/environment_pin.vue
@@ -6,6 +6,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { __ } from '~/locale';
import eventHub from '../event_hub';
+import cancelAutoStopMutation from '../graphql/mutations/cancel_auto_stop.mutation.graphql';
export default {
components: {
@@ -16,10 +17,22 @@ export default {
type: String,
required: true,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
methods: {
onPinClick() {
- eventHub.$emit('cancelAutoStop', this.autoStopUrl);
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: cancelAutoStopMutation,
+ variables: { autoStopUrl: this.autoStopUrl },
+ });
+ } else {
+ eventHub.$emit('cancelAutoStop', this.autoStopUrl);
+ }
},
},
title: __('Prevent auto-stopping'),
diff --git a/app/assets/javascripts/environments/components/new_environment_item.vue b/app/assets/javascripts/environments/components/new_environment_item.vue
index d3624103c13..27a763fb9c4 100644
--- a/app/assets/javascripts/environments/components/new_environment_item.vue
+++ b/app/assets/javascripts/environments/components/new_environment_item.vue
@@ -4,10 +4,12 @@ import {
GlDropdown,
GlButton,
GlLink,
+ GlSprintf,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import { truncate } from '~/lib/utils/text_utility';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import isLastDeployment from '../graphql/queries/is_last_deployment.query.graphql';
import ExternalUrl from './environment_external_url.vue';
import Actions from './environment_actions.vue';
@@ -18,6 +20,7 @@ import Monitoring from './environment_monitoring.vue';
import Terminal from './environment_terminal_button.vue';
import Delete from './environment_delete.vue';
import Deployment from './deployment.vue';
+import DeployBoardWrapper from './deploy_board_wrapper.vue';
export default {
components: {
@@ -25,19 +28,23 @@ export default {
GlDropdown,
GlButton,
GlLink,
+ GlSprintf,
Actions,
Deployment,
+ DeployBoardWrapper,
ExternalUrl,
StopComponent,
Rollback,
Monitoring,
Pin,
Terminal,
+ TimeAgoTooltip,
Delete,
},
directives: {
GlTooltip,
},
+ inject: ['helpPagePath'],
props: {
environment: {
required: true,
@@ -60,6 +67,10 @@ export default {
i18n: {
collapse: __('Collapse'),
expand: __('Expand'),
+ emptyState: s__(
+ 'Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}',
+ ),
+ autoStopIn: s__('Environment|Auto stop %{time}'),
},
data() {
return { visible: false };
@@ -83,12 +94,15 @@ export default {
upcomingDeployment() {
return this.environment?.upcomingDeployment;
},
+ hasDeployment() {
+ return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
+ },
actions() {
if (!this.lastDeployment) {
return [];
}
- const { manualActions = [], scheduledActions = [] } = this.lastDeployment;
- const combinedActions = [...manualActions, ...scheduledActions];
+ const { manualActions, scheduledActions } = this.lastDeployment;
+ const combinedActions = [...(manualActions ?? []), ...(scheduledActions ?? [])];
return combinedActions.map((action) => ({
...action,
}));
@@ -133,6 +147,9 @@ export default {
displayName() {
return truncate(this.name, 80);
},
+ rolloutStatus() {
+ return this.environment?.rolloutStatus;
+ },
},
methods: {
toggleCollapse() {
@@ -144,7 +161,15 @@ export default {
'gl-border-t-solid',
'gl-border-1',
'gl-py-5',
- 'gl-pl-7',
+ 'gl-md-pl-7',
+ 'gl-bg-gray-10',
+ ],
+ deployBoardClasses: [
+ 'gl-border-gray-100',
+ 'gl-border-t-solid',
+ 'gl-border-1',
+ 'gl-py-4',
+ 'gl-md-pl-7',
'gl-bg-gray-10',
],
};
@@ -176,7 +201,14 @@ export default {
{{ displayName }}
</gl-link>
</div>
- <div>
+ <div class="gl-display-flex gl-align-items-center">
+ <p v-if="canShowAutoStopDate" class="gl-font-sm gl-text-gray-700 gl-mr-5 gl-mb-0">
+ <gl-sprintf :message="$options.i18n.autoStopIn">
+ <template #time>
+ <time-ago-tooltip :time="environment.autoStopAt" css-class="gl-font-weight-bold" />
+ </template>
+ </gl-sprintf>
+ </p>
<div class="btn-group table-action-buttons" role="group">
<external-url
v-if="externalUrl"
@@ -224,6 +256,7 @@ export default {
<pin
v-if="canShowAutoStopDate"
:auto-stop-url="autoStopPath"
+ graphql
data-track-action="click_button"
data-track-label="environment_pin"
/>
@@ -254,11 +287,37 @@ export default {
</div>
</div>
<gl-collapse :visible="visible">
- <div v-if="lastDeployment" :class="$options.deploymentClasses">
- <deployment :deployment="lastDeployment" :class="{ 'gl-ml-7': inFolder }" />
+ <template v-if="hasDeployment">
+ <div v-if="lastDeployment" :class="$options.deploymentClasses">
+ <deployment
+ :deployment="lastDeployment"
+ :class="{ 'gl-ml-7': inFolder }"
+ latest
+ class="gl-pl-4"
+ />
+ </div>
+ <div v-if="upcomingDeployment" :class="$options.deploymentClasses">
+ <deployment
+ :deployment="upcomingDeployment"
+ :class="{ 'gl-ml-7': inFolder }"
+ class="gl-pl-4"
+ />
+ </div>
+ </template>
+ <div v-else :class="$options.deploymentClasses">
+ <gl-sprintf :message="$options.i18n.emptyState">
+ <template #link="{ content }">
+ <gl-link :href="helpPagePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
</div>
- <div v-if="upcomingDeployment" :class="$options.deploymentClasses">
- <deployment :deployment="upcomingDeployment" :class="{ 'gl-ml-7': inFolder }" />
+ <div v-if="rolloutStatus" :class="$options.deployBoardClasses">
+ <deploy-board-wrapper
+ :rollout-status="rolloutStatus"
+ :environment="environment"
+ :class="{ 'gl-ml-7': inFolder }"
+ class="gl-pl-4"
+ />
</div>
</gl-collapse>
</div>
diff --git a/app/assets/javascripts/environments/components/new_environments_app.vue b/app/assets/javascripts/environments/components/new_environments_app.vue
index cb36e226d0e..3699f39b611 100644
--- a/app/assets/javascripts/environments/components/new_environments_app.vue
+++ b/app/assets/javascripts/environments/components/new_environments_app.vue
@@ -8,16 +8,19 @@ import pageInfoQuery from '../graphql/queries/page_info.query.graphql';
import environmentToDeleteQuery from '../graphql/queries/environment_to_delete.query.graphql';
import environmentToRollbackQuery from '../graphql/queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from '../graphql/queries/environment_to_stop.query.graphql';
+import environmentToChangeCanaryQuery from '../graphql/queries/environment_to_change_canary.query.graphql';
import EnvironmentFolder from './new_environment_folder.vue';
import EnableReviewAppModal from './enable_review_app_modal.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
import EnvironmentItem from './new_environment_item.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import DeleteEnvironmentModal from './delete_environment_modal.vue';
+import CanaryUpdateModal from './canary_update_modal.vue';
export default {
components: {
DeleteEnvironmentModal,
+ CanaryUpdateModal,
ConfirmRollbackModal,
EnvironmentFolder,
EnableReviewAppModal,
@@ -56,6 +59,12 @@ export default {
environmentToStop: {
query: environmentToStopQuery,
},
+ environmentToChangeCanary: {
+ query: environmentToChangeCanaryQuery,
+ },
+ weight: {
+ query: environmentToChangeCanaryQuery,
+ },
},
inject: ['newEnvironmentPath', 'canCreateEnvironment'],
i18n: {
@@ -80,6 +89,8 @@ export default {
environmentToDelete: {},
environmentToRollback: {},
environmentToStop: {},
+ environmentToChangeCanary: {},
+ weight: 0,
};
},
computed: {
@@ -186,6 +197,7 @@ export default {
<delete-environment-modal :environment="environmentToDelete" graphql />
<stop-environment-modal :environment="environmentToStop" graphql />
<confirm-rollback-modal :environment="environmentToRollback" graphql />
+ <canary-update-modal :environment="environmentToChangeCanary" :weight="weight" />
<gl-tabs
:action-secondary="addEnvironment"
:action-primary="openReviewAppModal"
diff --git a/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql
index 22dfb8a7a89..0b473495710 100644
--- a/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql
+++ b/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql
@@ -1,5 +1,5 @@
-mutation cancelAutoStop($environment: LocalEnvironment) {
- cancelAutoStop(environment: $environment) @client {
+mutation cancelAutoStop($autoStopUrl: String!) {
+ cancelAutoStop(autoStopUrl: $autoStopUrl) @client {
errors
}
}
diff --git a/app/assets/javascripts/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql
new file mode 100644
index 00000000000..0f48c1f5c05
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql
@@ -0,0 +1,3 @@
+mutation SetEnvironmentToChangeCanary($environment: LocalEnvironmentInput, $weight: Int!) {
+ setEnvironmentToChangeCanary(environment: $environment, weight: $weight) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_to_change_canary.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_to_change_canary.query.graphql
new file mode 100644
index 00000000000..b582ae55ba1
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environment_to_change_canary.query.graphql
@@ -0,0 +1,4 @@
+query environmentToChangeCanary {
+ environmentToChangeCanary @client
+ weight @client
+}
diff --git a/app/assets/javascripts/environments/graphql/resolvers.js b/app/assets/javascripts/environments/graphql/resolvers.js
index 812fa0c81f0..dc763b77157 100644
--- a/app/assets/javascripts/environments/graphql/resolvers.js
+++ b/app/assets/javascripts/environments/graphql/resolvers.js
@@ -10,6 +10,7 @@ import pollIntervalQuery from './queries/poll_interval.query.graphql';
import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from './queries/environment_to_stop.query.graphql';
import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
+import environmentToChangeCanaryQuery from './queries/environment_to_change_canary.query.graphql';
import pageInfoQuery from './queries/page_info.query.graphql';
const buildErrors = (errors = []) => ({
@@ -134,9 +135,15 @@ export const resolvers = (endpoint) => ({
data: { environmentToRollback: environment },
});
},
- cancelAutoStop(_, { environment: { autoStopPath } }) {
+ setEnvironmentToChangeCanary(_, { environment, weight }, { client }) {
+ client.writeQuery({
+ query: environmentToChangeCanaryQuery,
+ data: { environmentToChangeCanary: environment, weight },
+ });
+ },
+ cancelAutoStop(_, { autoStopUrl }) {
return axios
- .post(autoStopPath)
+ .post(autoStopUrl)
.then(() => buildErrors())
.catch((err) =>
buildErrors([
diff --git a/app/assets/javascripts/environments/graphql/typedefs.graphql b/app/assets/javascripts/environments/graphql/typedefs.graphql
index c02f6b2838a..b4d1f7326f6 100644
--- a/app/assets/javascripts/environments/graphql/typedefs.graphql
+++ b/app/assets/javascripts/environments/graphql/typedefs.graphql
@@ -77,9 +77,10 @@ extend type Mutation {
stopEnvironment(environment: LocalEnvironmentInput): LocalErrors
deleteEnvironment(environment: LocalEnvironmentInput): LocalErrors
rollbackEnvironment(environment: LocalEnvironmentInput): LocalErrors
- cancelAutoStop(environment: LocalEnvironmentInput): LocalErrors
+ cancelAutoStop(autoStopUrl: String!): LocalErrors
setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToStop(environment: LocalEnvironmentInput): LocalErrors
+ setEnvironmentToChangeCanary(environment: LocalEnvironmentInput, weight: Int): LocalErrors
action(environment: LocalEnvironmentInput): LocalErrors
}
diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js
index 0d7a475eb8e..071c95b8f0a 100644
--- a/app/assets/javascripts/files_comment_button.js
+++ b/app/assets/javascripts/files_comment_button.js
@@ -4,7 +4,7 @@
* causes reflows, visit https://gist.github.com/paulirish/5d52fb081b3570c81e3a
*/
-import Cookies from 'js-cookie';
+import { getCookie } from '~/lib/utils/common_utils';
const LINE_NUMBER_CLASS = 'diff-line-num';
const UNFOLDABLE_LINE_CLASS = 'js-unfold';
@@ -29,7 +29,7 @@ export default {
$diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
}
- this.isParallelView = Cookies.get('diff_view') === 'parallel';
+ this.isParallelView = getCookie('diff_view') === 'parallel';
if (this.userCanCreateNote) {
$diffFile
diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
index d00e6e59cf5..28a3c54cc8f 100644
--- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -13,6 +13,21 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
IssuableTokenKeys.tokenKeys.splice(2, 0, reviewerToken);
IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, reviewerToken);
+ if (window.gon?.features?.mrAttentionRequests) {
+ const attentionRequestedToken = {
+ formattedKey: __('Attention'),
+ key: 'attention',
+ type: 'string',
+ param: '',
+ symbol: '@',
+ icon: 'user',
+ tag: '@attention',
+ hideNotEqual: true,
+ };
+ IssuableTokenKeys.tokenKeys.splice(2, 0, attentionRequestedToken);
+ IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, attentionRequestedToken);
+ }
+
const draftToken = {
token: {
formattedKey: __('Draft'),
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index 3cd4d48a4a3..09cef74477c 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -77,6 +77,11 @@ export default class AvailableDropdownMappings {
gl: DropdownUser,
element: this.container.querySelector('#js-dropdown-reviewer'),
},
+ attention: {
+ reference: null,
+ gl: DropdownUser,
+ element: this.container.getElementById('js-dropdown-attention-requested'),
+ },
'approved-by': {
reference: null,
gl: DropdownUser,
diff --git a/app/assets/javascripts/filtered_search/constants.js b/app/assets/javascripts/filtered_search/constants.js
index e2d6936acbd..f8b5910de9e 100644
--- a/app/assets/javascripts/filtered_search/constants.js
+++ b/app/assets/javascripts/filtered_search/constants.js
@@ -1,4 +1,4 @@
-export const USER_TOKEN_TYPES = ['author', 'assignee', 'approved-by', 'reviewer'];
+export const USER_TOKEN_TYPES = ['author', 'assignee', 'approved-by', 'reviewer', 'attention'];
export const DROPDOWN_TYPE = {
hint: 'hint',
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index d9c2e55cffe..fa605f8c056 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -18,6 +18,13 @@ const VARIANT_DANGER = 'danger';
const VARIANT_INFO = 'info';
const VARIANT_TIP = 'tip';
+const TYPE_TO_VARIANT = {
+ [FLASH_TYPES.ALERT]: VARIANT_DANGER,
+ [FLASH_TYPES.NOTICE]: VARIANT_INFO,
+ [FLASH_TYPES.SUCCESS]: VARIANT_SUCCESS,
+ [FLASH_TYPES.WARNING]: VARIANT_WARNING,
+};
+
const FLASH_CLOSED_EVENT = 'flashClosed';
const getCloseEl = (flashEl) => {
@@ -61,7 +68,7 @@ const createAction = (config) => `
`;
const createFlashEl = (message, type) => `
- <div class="flash-${type}">
+ <div class="flash-${type}" data-testid="alert-${TYPE_TO_VARIANT[type]}">
<div class="flash-text">
${escape(message)}
<div class="close-icon-wrapper js-close-icon">
@@ -189,6 +196,9 @@ const createAlert = function createAlert({
secondaryButtonLink: secondaryButton?.link,
secondaryButtonText: secondaryButton?.text,
},
+ attrs: {
+ 'data-testid': `alert-${variant}`,
+ },
on,
},
message,
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 69331ff1a06..bf29a356abd 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -86,6 +86,7 @@ export const defaultAutocompleteConfig = {
labels: true,
snippets: true,
vulnerabilities: true,
+ contacts: true,
};
class GfmAutoComplete {
@@ -127,6 +128,7 @@ class GfmAutoComplete {
if (this.enableMap.mergeRequests) this.setupMergeRequests($input);
if (this.enableMap.labels) this.setupLabels($input);
if (this.enableMap.snippets) this.setupSnippets($input);
+ if (this.enableMap.contacts) this.setupContacts($input);
$input.filter('[data-supports-quick-actions="true"]').atwho({
at: '/',
@@ -174,9 +176,16 @@ class GfmAutoComplete {
let tpl = '/${name} ';
let referencePrefix = null;
if (value.params.length > 0) {
- [[referencePrefix]] = value.params;
- if (/^[@%~]/.test(referencePrefix)) {
+ const regexp = /\[[a-z]+:/;
+ const match = regexp.exec(value.params);
+ if (match) {
+ [referencePrefix] = match;
tpl += '<%- referencePrefix %>';
+ } else {
+ [[referencePrefix]] = value.params;
+ if (/^[@%~]/.test(referencePrefix)) {
+ tpl += '<%- referencePrefix %>';
+ }
}
}
return template(tpl, { interpolate: /<%=([\s\S]+?)%>/g })({ referencePrefix });
@@ -266,6 +275,8 @@ class GfmAutoComplete {
UNASSIGN_REVIEWER: '/unassign_reviewer',
REASSIGN: '/reassign',
CC: '/cc',
+ ATTENTION: '/attention',
+ REMOVE_ATTENTION: '/remove_attention',
};
let assignees = [];
let reviewers = [];
@@ -344,6 +355,23 @@ class GfmAutoComplete {
} else if (command === MEMBER_COMMAND.UNASSIGN_REVIEWER) {
// Only include members which are not assigned as a reviewer to Issuable currently
return data.filter((member) => reviewers.includes(member.search));
+ } else if (
+ command === MEMBER_COMMAND.ATTENTION ||
+ command === MEMBER_COMMAND.REMOVE_ATTENTION
+ ) {
+ const attentionUsers = [
+ ...(SidebarMediator.singleton?.store?.assignees || []),
+ ...(SidebarMediator.singleton?.store?.reviewers || []),
+ ];
+ const attentionRequested = command === MEMBER_COMMAND.REMOVE_ATTENTION;
+
+ return data.filter((member) =>
+ attentionUsers.find(
+ (u) =>
+ createMemberSearchString(u).includes(member.search) &&
+ u.attention_requested === attentionRequested,
+ ),
+ );
}
return data;
@@ -619,6 +647,42 @@ class GfmAutoComplete {
});
}
+ setupContacts($input) {
+ $input.atwho({
+ at: '[contact:',
+ suffix: ']',
+ alias: 'contacts',
+ searchKey: 'search',
+ displayTpl(value) {
+ let tmpl = GfmAutoComplete.Loading.template;
+ if (value.email != null) {
+ tmpl = GfmAutoComplete.Contacts.templateFunction(value);
+ }
+ return tmpl;
+ },
+ data: GfmAutoComplete.defaultLoadingData,
+ // eslint-disable-next-line no-template-curly-in-string
+ insertTpl: '${atwho-at}${email}',
+ callbacks: {
+ ...this.getDefaultCallbacks(),
+ beforeSave(contacts) {
+ return $.map(contacts, (m) => {
+ if (m.email == null) {
+ return m;
+ }
+ return {
+ id: m.id,
+ email: m.email,
+ firstName: m.first_name,
+ lastName: m.last_name,
+ search: `${m.email}`,
+ };
+ });
+ },
+ },
+ });
+ }
+
getDefaultCallbacks() {
const self = this;
@@ -790,6 +854,7 @@ GfmAutoComplete.atTypeMap = {
'/': 'commands',
'[vulnerability:': 'vulnerabilities',
$: 'snippets',
+ '[contact:': 'contacts',
};
GfmAutoComplete.typesWithBackendFiltering = ['vulnerabilities'];
@@ -883,6 +948,11 @@ GfmAutoComplete.Milestones = {
return `<li>${escape(title)}</li>`;
},
};
+GfmAutoComplete.Contacts = {
+ templateFunction({ email, firstName, lastName }) {
+ return `<li><small>${firstName} ${lastName}</small> ${escape(email)}</li>`;
+ },
+};
GfmAutoComplete.Loading = {
template:
'<li style="pointer-events: none;"><span class="spinner align-text-bottom mr-1"></span>Loading...</li>',
diff --git a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue b/app/assets/javascripts/google_cloud/components/deployments_service_table.vue
index 7d27d7cf6b2..26c9fd14dc6 100644
--- a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue
+++ b/app/assets/javascripts/google_cloud/components/deployments_service_table.vue
@@ -2,6 +2,9 @@
import { GlButton, GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
+const cloudRun = 'cloudRun';
+const cloudStorage = 'cloudStorage';
+
const i18n = {
cloudRun: __('Cloud Run'),
cloudRunDescription: __('Deploy container based web apps on Google managed clusters'),
@@ -28,6 +31,13 @@ export default {
required: true,
},
},
+ methods: {
+ actionUrl(key) {
+ if (key === cloudRun) return this.cloudRunUrl;
+ else if (key === cloudStorage) return this.cloudStorageUrl;
+ return '#';
+ },
+ },
fields: [
{ key: 'title', label: i18n.service },
{ key: 'description', label: i18n.description },
@@ -37,12 +47,19 @@ export default {
{
title: i18n.cloudRun,
description: i18n.cloudRunDescription,
- action: { title: i18n.configureViaMergeRequest, disabled: true },
+ action: {
+ key: cloudRun,
+ title: i18n.configureViaMergeRequest,
+ },
},
{
title: i18n.cloudStorage,
description: i18n.cloudStorageDescription,
- action: { title: i18n.configureViaMergeRequest, disabled: true },
+ action: {
+ key: cloudStorage,
+ title: i18n.configureViaMergeRequest,
+ disabled: true,
+ },
},
],
i18n,
@@ -54,7 +71,9 @@ export default {
<p>{{ $options.i18n.deploymentsDescription }}</p>
<gl-table :fields="$options.fields" :items="$options.items">
<template #cell(action)="{ value }">
- <gl-button :disabled="value.disabled">{{ value.title }}</gl-button>
+ <gl-button :disabled="value.disabled" :href="actionUrl(value.key)">
+ {{ value.title }}
+ </gl-button>
</template>
</gl-table>
</div>
diff --git a/app/assets/javascripts/google_cloud/components/home.vue b/app/assets/javascripts/google_cloud/components/home.vue
index 8ef110dcf22..c08d8bb7c51 100644
--- a/app/assets/javascripts/google_cloud/components/home.vue
+++ b/app/assets/javascripts/google_cloud/components/home.vue
@@ -23,11 +23,11 @@ export default {
type: String,
required: true,
},
- deploymentsCloudRunUrl: {
+ enableCloudRunUrl: {
type: String,
required: true,
},
- deploymentsCloudStorageUrl: {
+ enableCloudStorageUrl: {
type: String,
required: true,
},
@@ -47,8 +47,8 @@ export default {
</gl-tab>
<gl-tab :title="__('Deployments')">
<deployments-service-table
- :cloud-run-url="deploymentsCloudRunUrl"
- :cloud-storage-url="deploymentsCloudStorageUrl"
+ :cloud-run-url="enableCloudRunUrl"
+ :cloud-storage-url="enableCloudStorageUrl"
/>
</gl-tab>
<gl-tab :title="__('Services')" disabled />
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
index e7a09668473..551783e6c50 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
@@ -1,9 +1,9 @@
<script>
-import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
- components: { GlButton, GlFormGroup, GlFormSelect },
+ components: { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox },
props: {
gcpProjects: { required: true, type: Array },
environments: { required: true, type: Array },
@@ -19,6 +19,9 @@ export default {
environmentDescription: __('Generated service account is linked to the selected environment'),
submitLabel: __('Create service account'),
cancelLabel: __('Cancel'),
+ checkboxLabel: __(
+ 'I understand the responsibilities involved with managing service account keys',
+ ),
},
};
</script>
@@ -59,6 +62,11 @@ export default {
</option>
</gl-form-select>
</gl-form-group>
+ <gl-form-group>
+ <gl-form-checkbox name="confirmation" required>
+ {{ $options.i18n.checkboxLabel }}
+ </gl-form-checkbox>
+ </gl-form-group>
<div class="form-actions row">
<gl-button type="submit" category="primary" variant="confirm">
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
index b70b25a5dc3..4db84746482 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
@@ -1,9 +1,9 @@
<script>
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
- components: { GlButton, GlEmptyState, GlTable },
+ components: { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf, GlTable },
props: {
list: {
type: Array,
@@ -28,6 +28,22 @@ export default {
],
};
},
+ i18n: {
+ createServiceAccount: __('Create service account'),
+ found: __('✔'),
+ notFound: __('Not found'),
+ noServiceAccountsTitle: __('No service accounts'),
+ noServiceAccountsDescription: __(
+ 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+ ),
+ serviceAccountsTitle: __('Service accounts'),
+ serviceAccountsDescription: __(
+ 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+ ),
+ secretManagersDescription: __(
+ 'Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}',
+ ),
+ },
};
</script>
@@ -35,31 +51,39 @@ export default {
<div>
<gl-empty-state
v-if="list.length === 0"
- :title="__('No service accounts')"
- :description="
- __('Service Accounts keys authorize GitLab to deploy your Google Cloud project')
- "
+ :title="$options.i18n.noServiceAccountsTitle"
+ :description="$options.i18n.noServiceAccountsDescription"
:primary-button-link="createUrl"
- :primary-button-text="__('Create service account')"
+ :primary-button-text="$options.i18n.createServiceAccount"
:svg-path="emptyIllustrationUrl"
/>
<div v-else>
- <h2 class="gl-font-size-h2">{{ __('Service Accounts') }}</h2>
- <p>{{ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project') }}</p>
+ <h2 class="gl-font-size-h2">{{ $options.i18n.serviceAccountsTitle }}</h2>
+ <p>{{ $options.i18n.serviceAccountsDescription }}</p>
<gl-table :items="list" :fields="tableFields">
<template #cell(service_account_exists)="{ value }">
- {{ value ? '✔' : __('Not found') }}
+ {{ value ? $options.i18n.found : $options.i18n.notFound }}
</template>
<template #cell(service_account_key_exists)="{ value }">
- {{ value ? '✔' : __('Not found') }}
+ {{ value ? $options.i18n.found : $options.i18n.notFound }}
</template>
</gl-table>
<gl-button :href="createUrl" category="primary" variant="info">
- {{ __('Create service account') }}
+ {{ $options.i18n.createServiceAccount }}
</gl-button>
+
+ <gl-alert class="gl-mt-5" :dismissible="false" variant="tip">
+ <gl-sprintf :message="$options.i18n.secretManagersDescription">
+ <template #docLink="{ content }">
+ <gl-link href="https://docs.gitlab.com/ee/ci/secrets/">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/google_tag_manager/index.js b/app/assets/javascripts/google_tag_manager/index.js
index ab80e15c2ec..55987ce64e6 100644
--- a/app/assets/javascripts/google_tag_manager/index.js
+++ b/app/assets/javascripts/google_tag_manager/index.js
@@ -1,5 +1,43 @@
+import { v4 as uuidv4 } from 'uuid';
import { logError } from '~/lib/logger';
+const SKU_PREMIUM = '2c92a00d76f0d5060176f2fb0a5029ff';
+const SKU_ULTIMATE = '2c92a0ff76f0d5250176f2f8c86f305a';
+const PRODUCT_INFO = {
+ [SKU_PREMIUM]: {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ name: 'Premium',
+ id: '0002',
+ price: '228',
+ variant: 'SaaS',
+ },
+ [SKU_ULTIMATE]: {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ name: 'Ultimate',
+ id: '0001',
+ price: '1188',
+ variant: 'SaaS',
+ },
+};
+
+const generateProductInfo = (sku, quantity) => {
+ const product = PRODUCT_INFO[sku];
+
+ if (!product) {
+ logError('Unexpected product sku provided to generateProductInfo');
+ return {};
+ }
+
+ const productInfo = {
+ ...product,
+ brand: 'GitLab',
+ category: 'DevOps',
+ quantity,
+ };
+
+ return productInfo;
+};
+
const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer;
const pushEvent = (event, args = {}) => {
@@ -17,6 +55,22 @@ const pushEvent = (event, args = {}) => {
}
};
+const pushEnhancedEcommerceEvent = (event, args = {}) => {
+ if (!window.dataLayer) {
+ return;
+ }
+
+ try {
+ window.dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object
+ window.dataLayer.push({
+ event,
+ ...args,
+ });
+ } catch (e) {
+ logError('Unexpected error while pushing to dataLayer', e);
+ }
+};
+
const pushAccountSubmit = (accountType, accountMethod) =>
pushEvent('accountSubmit', { accountType, accountMethod });
@@ -120,3 +174,60 @@ export const trackSaasTrialGetStarted = () => {
pushEvent('saasTrialGetStarted');
});
};
+
+export const trackCheckout = (selectedPlan, quantity) => {
+ if (!isSupported()) {
+ return;
+ }
+
+ const product = generateProductInfo(selectedPlan, quantity);
+
+ if (Object.keys(product).length === 0) {
+ return;
+ }
+
+ const eventData = {
+ ecommerce: {
+ currencyCode: 'USD',
+ checkout: {
+ actionField: { step: 1 },
+ products: [product],
+ },
+ },
+ };
+
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ pushEnhancedEcommerceEvent('EECCheckout', eventData);
+};
+
+export const trackTransaction = (transactionDetails) => {
+ if (!isSupported()) {
+ return;
+ }
+
+ const transactionId = uuidv4();
+ const { paymentOption, revenue, tax, selectedPlan, quantity } = transactionDetails;
+ const product = generateProductInfo(selectedPlan, quantity);
+
+ if (Object.keys(product).length === 0) {
+ return;
+ }
+
+ const eventData = {
+ ecommerce: {
+ currencyCode: 'USD',
+ purchase: {
+ actionField: {
+ id: transactionId,
+ affiliation: 'GitLab',
+ option: paymentOption,
+ revenue: revenue.toString(),
+ tax: tax.toString(),
+ },
+ products: [product],
+ },
+ },
+ };
+
+ pushEnhancedEcommerceEvent('EECtransactionSuccess', eventData);
+};
diff --git a/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js b/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js
deleted file mode 100644
index 30888e20a46..00000000000
--- a/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export const vulnerabilityLocationTypes = {
- __schema: {
- types: [
- {
- kind: 'UNION',
- name: 'VulnerabilityLocation',
- possibleTypes: [
- { name: 'VulnerabilityLocationContainerScanning' },
- { name: 'VulnerabilityLocationDast' },
- { name: 'VulnerabilityLocationDependencyScanning' },
- { name: 'VulnerabilityLocationSast' },
- { name: 'VulnerabilityLocationSecretDetection' },
- ],
- },
- ],
- },
-};
diff --git a/app/assets/javascripts/graphql_shared/possibleTypes.json b/app/assets/javascripts/graphql_shared/possibleTypes.json
new file mode 100644
index 00000000000..9a24d2a3afc
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/possibleTypes.json
@@ -0,0 +1 @@
+{"AlertManagementIntegration":["AlertManagementHttpIntegration","AlertManagementPrometheusIntegration"],"CurrentUserTodos":["BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest"],"DependencyLinkMetadata":["NugetDependencyLinkMetadata"],"DesignFields":["Design","DesignAtVersion"],"Entry":["Blob","Submodule","TreeEntry"],"Eventable":["BoardEpic","Epic"],"Issuable":["Epic","Issue","MergeRequest"],"JobNeedUnion":["CiBuildNeed","CiJob"],"MemberInterface":["GroupMember","ProjectMember"],"NoteableInterface":["AlertManagementAlert","BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest","Snippet","Vulnerability"],"NoteableType":["Design","Issue","MergeRequest"],"OrchestrationPolicy":["ScanExecutionPolicy","ScanResultPolicy"],"PackageFileMetadata":["ConanFileMetadata","HelmFileMetadata"],"PackageMetadata":["ComposerMetadata","ConanMetadata","MavenMetadata","NugetMetadata","PypiMetadata"],"ResolvableInterface":["Discussion","Note"],"Service":["BaseService","JiraService"],"TimeboxReportInterface":["Iteration","Milestone"],"User":["MergeRequestAssignee","MergeRequestReviewer","UserCore"],"VulnerabilityDetail":["VulnerabilityDetailBase","VulnerabilityDetailBoolean","VulnerabilityDetailCode","VulnerabilityDetailCommit","VulnerabilityDetailDiff","VulnerabilityDetailFileLocation","VulnerabilityDetailInt","VulnerabilityDetailList","VulnerabilityDetailMarkdown","VulnerabilityDetailModuleLocation","VulnerabilityDetailTable","VulnerabilityDetailText","VulnerabilityDetailUrl"],"VulnerabilityLocation":["VulnerabilityLocationClusterImageScanning","VulnerabilityLocationContainerScanning","VulnerabilityLocationCoverageFuzzing","VulnerabilityLocationDast","VulnerabilityLocationDependencyScanning","VulnerabilityLocationGeneric","VulnerabilityLocationSast","VulnerabilityLocationSecretDetection"]}
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index a1ec5942d64..e3147065d5c 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -41,6 +41,7 @@ export default {
},
data() {
return {
+ isModalVisible: false,
isLoading: true,
isSearchEmpty: false,
searchEmptyMessage: '',
@@ -101,6 +102,12 @@ export default {
eventHub.$off(`${this.action}updateGroups`, this.updateGroups);
},
methods: {
+ hideModal() {
+ this.isModalVisible = false;
+ },
+ showModal() {
+ this.isModalVisible = true;
+ },
fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) {
return this.service
.getGroups(parentId, page, filterGroupsBy, sortBy, archived)
@@ -185,6 +192,7 @@ export default {
showLeaveGroupModal(group, parentGroup) {
this.targetGroup = group;
this.targetParentGroup = parentGroup;
+ this.showModal();
},
leaveGroup() {
this.targetGroup.isBeingRemoved = true;
@@ -256,10 +264,12 @@ export default {
/>
<gl-modal
modal-id="leave-group-modal"
+ :visible="isModalVisible"
:title="__('Are you sure?')"
:action-primary="primaryProps"
:action-cancel="cancelProps"
@primary="leaveGroup"
+ @hide="hideModal"
>
{{ groupLeaveConfirmationMessage }}
</gl-modal>
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 10c45abbfa2..707008ec493 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -34,8 +34,8 @@ export default {
),
itemCaret,
itemTypeIcon,
- itemStats,
itemActions,
+ itemStats,
},
props: {
parentGroup: {
@@ -92,6 +92,9 @@ export default {
complianceFramework() {
return this.group.complianceFramework;
},
+ showActionsMenu() {
+ return this.isGroup && (this.group.canEdit || this.group.canRemove || this.group.canLeave);
+ },
},
methods: {
onClickRowGroup(e) {
@@ -197,17 +200,19 @@ export default {
<div v-if="isGroupPendingRemoval">
<gl-badge variant="warning">{{ __('pending deletion') }}</gl-badge>
</div>
- <div class="metadata d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between">
+ <div
+ class="metadata gl-display-flex gl-flex-grow-1 gl-flex-shrink-0 gl-flex-wrap justify-content-md-between"
+ >
+ <item-stats
+ :item="group"
+ class="group-stats gl-mt-2 gl-display-none gl-md-display-flex gl-align-items-center"
+ />
<item-actions
- v-if="isGroup"
+ v-if="showActionsMenu"
: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"
- />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/groups/components/invite_members_banner.vue b/app/assets/javascripts/groups/components/invite_members_banner.vue
index dfc1549fb4a..7afea815197 100644
--- a/app/assets/javascripts/groups/components/invite_members_banner.vue
+++ b/app/assets/javascripts/groups/components/invite_members_banner.vue
@@ -46,7 +46,6 @@ export default {
},
openModal() {
eventHub.$emit('openModal', {
- inviteeType: 'members',
source: this.$options.openModalSource,
});
this.track(this.$options.buttonClickEvent);
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index df751a3f37e..fc7cfffc22c 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -1,15 +1,17 @@
<script>
-import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { COMMON_STR } from '../constants';
import eventHub from '../event_hub';
+const { LEAVE_BTN_TITLE, EDIT_BTN_TITLE, REMOVE_BTN_TITLE, OPTIONS_DROPDOWN_TITLE } = COMMON_STR;
+
export default {
components: {
- GlButton,
+ GlDropdown,
+ GlDropdownItem,
},
directives: {
GlTooltip: GlTooltipDirective,
- GlModal: GlModalDirective,
},
props: {
parentGroup: {
@@ -28,11 +30,8 @@ export default {
},
},
computed: {
- leaveBtnTitle() {
- return COMMON_STR.LEAVE_BTN_TITLE;
- },
- editBtnTitle() {
- return COMMON_STR.EDIT_BTN_TITLE;
+ removeButtonHref() {
+ return `${this.group.editPath}#js-remove-group-form`;
},
},
methods: {
@@ -40,33 +39,51 @@ export default {
eventHub.$emit(`${this.action}showLeaveGroupModal`, this.group, this.parentGroup);
},
},
+ i18n: {
+ leaveBtnTitle: LEAVE_BTN_TITLE,
+ editBtnTitle: EDIT_BTN_TITLE,
+ removeBtnTitle: REMOVE_BTN_TITLE,
+ optionsDropdownTitle: OPTIONS_DROPDOWN_TITLE,
+ },
};
</script>
<template>
- <div class="controls d-flex justify-content-end">
- <gl-button
- v-if="group.canLeave"
- v-gl-tooltip.top
- v-gl-modal.leave-group-modal
- :title="leaveBtnTitle"
- :aria-label="leaveBtnTitle"
- data-testid="leave-group-btn"
- size="small"
- icon="leave"
- class="leave-group gl-ml-3"
- @click.stop="onLeaveGroup"
- />
- <gl-button
- v-if="group.canEdit"
- v-gl-tooltip.top
- :href="group.editPath"
- :title="editBtnTitle"
- :aria-label="editBtnTitle"
- data-testid="edit-group-btn"
- size="small"
- icon="pencil"
- class="edit-group gl-ml-3"
- />
+ <div class="gl-display-flex gl-justify-content-end gl-ml-5">
+ <gl-dropdown
+ v-gl-tooltip.hover.focus="$options.i18n.optionsDropdownTitle"
+ right
+ category="tertiary"
+ icon="ellipsis_v"
+ no-caret
+ :data-testid="`group-${group.id}-dropdown-button`"
+ data-qa-selector="group_dropdown_button"
+ :data-qa-group-id="group.id"
+ >
+ <gl-dropdown-item
+ v-if="group.canEdit"
+ :data-testid="`edit-group-${group.id}-btn`"
+ :href="group.editPath"
+ @click.stop
+ >
+ {{ $options.i18n.editBtnTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="group.canLeave"
+ :data-testid="`leave-group-${group.id}-btn`"
+ @click.stop="onLeaveGroup"
+ >
+ {{ $options.i18n.leaveBtnTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="group.canRemove"
+ :href="removeButtonHref"
+ :data-testid="`remove-group-${group.id}-btn`"
+ variant="danger"
+ @click.stop
+ >
+ {{ $options.i18n.removeBtnTitle }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/transfer_group_form.vue b/app/assets/javascripts/groups/components/transfer_group_form.vue
new file mode 100644
index 00000000000..e848f10352d
--- /dev/null
+++ b/app/assets/javascripts/groups/components/transfer_group_form.vue
@@ -0,0 +1,80 @@
+<script>
+import { GlFormGroup } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+
+export const i18n = {
+ confirmationMessage: __(
+ 'You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?',
+ ),
+ emptyNamespaceTitle: __('No parent group'),
+ dropdownTitle: s__('GroupSettings|Select parent group'),
+};
+
+export default {
+ name: 'TransferGroupForm',
+ components: {
+ ConfirmDanger,
+ GlFormGroup,
+ NamespaceSelect,
+ },
+ props: {
+ groupNamespaces: {
+ type: Array,
+ required: true,
+ },
+ isPaidGroup: {
+ type: Boolean,
+ required: true,
+ },
+ confirmationPhrase: {
+ type: String,
+ required: true,
+ },
+ confirmButtonText: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedId: null,
+ };
+ },
+ computed: {
+ disableSubmitButton() {
+ return this.isPaidGroup || !this.selectedId;
+ },
+ },
+ methods: {
+ handleSelected({ id }) {
+ this.selectedId = id;
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <div>
+ <gl-form-group v-if="!isPaidGroup">
+ <namespace-select
+ :default-text="$options.i18n.dropdownTitle"
+ :group-namespaces="groupNamespaces"
+ :empty-namespace-title="$options.i18n.emptyNamespaceTitle"
+ :include-headers="false"
+ include-empty-namespace
+ data-testid="transfer-group-namespace-select"
+ @select="handleSelected"
+ />
+ <input type="hidden" name="new_parent_group_id" :value="selectedId" />
+ </gl-form-group>
+ <confirm-danger
+ button-class="qa-transfer-button"
+ :disabled="disableSubmitButton"
+ :phrase="confirmationPhrase"
+ :button-text="confirmButtonText"
+ @confirm="$emit('confirm')"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index e2722d780dc..005bac1e7b5 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -15,8 +15,10 @@ export const COMMON_STR = {
LEAVE_FORBIDDEN: s__(
'GroupsTree|Failed to leave the group. Please make sure you are not the only owner.',
),
- LEAVE_BTN_TITLE: s__('GroupsTree|Leave this group'),
- EDIT_BTN_TITLE: s__('GroupsTree|Edit group'),
+ LEAVE_BTN_TITLE: s__('GroupsTree|Leave group'),
+ EDIT_BTN_TITLE: s__('GroupsTree|Edit'),
+ REMOVE_BTN_TITLE: s__('GroupsTree|Delete'),
+ OPTIONS_DROPDOWN_TITLE: s__('GroupsTree|Options'),
GROUP_SEARCH_EMPTY: s__('GroupsTree|No groups matched your search'),
GROUP_PROJECT_SEARCH_EMPTY: s__('GroupsTree|No groups or projects matched your search'),
};
diff --git a/app/assets/javascripts/groups/init_transfer_group_form.js b/app/assets/javascripts/groups/init_transfer_group_form.js
new file mode 100644
index 00000000000..f055b926918
--- /dev/null
+++ b/app/assets/javascripts/groups/init_transfer_group_form.js
@@ -0,0 +1,52 @@
+import Vue from 'vue';
+import { sprintf } from '~/locale';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import TransferGroupForm, { i18n } from './components/transfer_group_form.vue';
+
+const prepareGroups = (rawGroups) => {
+ if (!rawGroups) {
+ return [];
+ }
+
+ return JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
+ id,
+ humanName,
+ }));
+};
+
+export default () => {
+ const el = document.querySelector('.js-transfer-group-form');
+ if (!el) {
+ return false;
+ }
+
+ const {
+ targetFormId = null,
+ buttonText: confirmButtonText = '',
+ groupName = '',
+ parentGroups,
+ isPaidGroup,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ confirmDangerMessage: sprintf(i18n.confirmationMessage, { group_name: groupName }),
+ },
+ render(createElement) {
+ return createElement(TransferGroupForm, {
+ props: {
+ groupNamespaces: prepareGroups(parentGroups),
+ isPaidGroup: parseBoolean(isPaidGroup),
+ confirmButtonText,
+ confirmationPhrase: groupName,
+ },
+ on: {
+ confirm: () => {
+ document.getElementById(targetFormId)?.submit();
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/groups/landing.js b/app/assets/javascripts/groups/landing.js
index bfb4d9ce67b..ed76bebf843 100644
--- a/app/assets/javascripts/groups/landing.js
+++ b/app/assets/javascripts/groups/landing.js
@@ -1,5 +1,4 @@
-import Cookies from 'js-cookie';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
class Landing {
constructor(landingElement, dismissButton, cookieName) {
@@ -27,11 +26,11 @@ class Landing {
dismissLanding() {
this.landingElement.classList.add('hidden');
- Cookies.set(this.cookieName, 'true', { expires: 365 });
+ setCookie(this.cookieName, 'true');
}
isDismissed() {
- return parseBoolean(Cookies.get(this.cookieName));
+ return parseBoolean(getCookie(this.cookieName));
}
}
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index d3600bd223a..0917b9ceccf 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -83,6 +83,7 @@ export default class GroupsStore {
leavePath: rawGroupItem.leave_path,
canEdit: rawGroupItem.can_edit,
canLeave: rawGroupItem.can_leave,
+ canRemove: rawGroupItem.can_remove,
type: rawGroupItem.type,
permission: rawGroupItem.permission,
children: groupChildren,
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
deleted file mode 100644
index d6343f698c0..00000000000
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import $ from 'jquery';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __ } from '~/locale';
-
-export default class TransferDropdown {
- constructor() {
- this.groupDropdown = $('.js-groups-dropdown');
- this.parentInput = $('#new_parent_group_id');
- this.data = this.groupDropdown.data('data');
- this.init();
- }
-
- init() {
- this.buildDropdown();
- }
-
- buildDropdown() {
- const extraOptions = [{ id: '-1', text: __('No parent group') }, { type: 'divider' }];
-
- initDeprecatedJQueryDropdown(this.groupDropdown, {
- selectable: true,
- filterable: true,
- toggleLabel: (item) => item.text,
- search: { fields: ['text'] },
- data: extraOptions.concat(this.data),
- text: (item) => item.text,
- clicked: (options) => {
- const { e } = options;
- e.preventDefault();
- this.assignSelected(options.selectedObj);
- },
- });
- }
-
- assignSelected(selected) {
- this.parentInput.val(selected.id);
- this.parentInput.change();
- }
-}
diff --git a/app/assets/javascripts/groups/transfer_edit.js b/app/assets/javascripts/groups/transfer_edit.js
deleted file mode 100644
index bb15e11fd4c..00000000000
--- a/app/assets/javascripts/groups/transfer_edit.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import $ from 'jquery';
-
-export default function setupTransferEdit(formSelector, targetSelector) {
- const $transferForm = $(formSelector);
- const $selectNamespace = $transferForm.find(targetSelector);
-
- $selectNamespace.on('change', () => {
- $transferForm.find(':submit').prop('disabled', !$selectNamespace.val());
- });
- $selectNamespace.trigger('change');
-}
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index bd71c5ebc11..64bba91eb4d 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -28,6 +28,7 @@ const groupsSelect = () => {
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
const groupsFilter = $select.data('groupsFilter');
+ const minAccessLevel = $select.data('minAccessLevel');
$select.select2({
placeholder: __('Search for a group'),
@@ -45,6 +46,7 @@ const groupsSelect = () => {
page,
per_page: window.GROUP_SELECT_PER_PAGE,
all_available: allAvailable,
+ min_access_level: minAccessLevel,
};
},
results(data, page) {
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index 846b4d92724..92dacf8c94a 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective, GlBadge } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { leftSidebarViews } from '../constants';
@@ -7,6 +7,7 @@ import { leftSidebarViews } from '../constants';
export default {
components: {
GlIcon,
+ GlBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -82,9 +83,13 @@ export default {
@click.prevent="changedActivityView($event, $options.leftSidebarViews.commit.name)"
>
<gl-icon name="commit" />
- <div v-if="stagedFiles.length > 0" class="ide-commit-badge badge badge-pill">
+ <gl-badge
+ v-if="stagedFiles.length"
+ class="gl-absolute gl-px-2 gl-top-3 gl-right-3 gl-font-weight-bold gl-bg-gray-900! gl-text-white!"
+ size="sm"
+ >
{{ stagedFiles.length }}
- </div>
+ </gl-badge>
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index 9ec4a07a3d0..44f543d9a76 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -187,7 +187,7 @@ export default {
class="qa-commit-button"
category="primary"
variant="confirm"
- @click="commit"
+ type="submit"
>
{{ __('Commit') }}
</gl-button>
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index 13f2e775fc3..b1f6f2c87b9 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -4,7 +4,12 @@ import { listen } from 'codesandbox-api';
import { isEmpty, debounce } from 'lodash';
import { Manager } from 'smooshpack';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { packageJsonPath, LIVE_PREVIEW_DEBOUNCE } from '../../constants';
+import {
+ packageJsonPath,
+ LIVE_PREVIEW_DEBOUNCE,
+ PING_USAGE_PREVIEW_KEY,
+ PING_USAGE_PREVIEW_SUCCESS_KEY,
+} from '../../constants';
import eventHub from '../../eventhub';
import { createPathWithExt } from '../../utils';
import Navigator from './navigator.vue';
@@ -62,6 +67,15 @@ export default {
};
},
},
+ watch: {
+ sandpackReady: {
+ handler(val) {
+ if (val) {
+ this.pingUsage(PING_USAGE_PREVIEW_SUCCESS_KEY);
+ }
+ },
+ },
+ },
mounted() {
this.onFilesChangeCallback = debounce(() => this.update(), LIVE_PREVIEW_DEBOUNCE);
eventHub.$on('ide.files.change', this.onFilesChangeCallback);
@@ -101,7 +115,7 @@ export default {
initPreview() {
if (!this.mainEntry) return null;
- this.pingUsage();
+ this.pingUsage(PING_USAGE_PREVIEW_KEY);
return this.loadFileContent(this.mainEntry)
.then(() => this.$nextTick())
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 775b6906498..bfe4c3ac271 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -114,3 +114,7 @@ export const LIVE_PREVIEW_DEBOUNCE = 2000;
export const MAX_MR_FILES_AUTO_OPEN = 10;
export const DEFAULT_BRANCH = 'main';
+
+// Ping Usage Metrics Keys
+export const PING_USAGE_PREVIEW_KEY = 'web_ide_clientside_preview';
+export const PING_USAGE_PREVIEW_SUCCESS_KEY = 'web_ide_clientside_preview_success';
diff --git a/app/assets/javascripts/ide/stores/modules/clientside/actions.js b/app/assets/javascripts/ide/stores/modules/clientside/actions.js
index e36419cd7eb..1a8e665867f 100644
--- a/app/assets/javascripts/ide/stores/modules/clientside/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/clientside/actions.js
@@ -1,9 +1,9 @@
import axios from '~/lib/utils/axios_utils';
-export const pingUsage = ({ rootGetters }) => {
+export const pingUsage = ({ rootGetters }, metricName) => {
const { web_url: projectUrl } = rootGetters.currentProject;
- const url = `${projectUrl}/service_ping/web_ide_clientside_preview`;
+ const url = `${projectUrl}/service_ping/${metricName}`;
return axios.post(url);
};
diff --git a/app/assets/javascripts/image_diff/helpers/badge_helper.js b/app/assets/javascripts/image_diff/helpers/badge_helper.js
index 8ee72235a23..5ff00394e3b 100644
--- a/app/assets/javascripts/image_diff/helpers/badge_helper.js
+++ b/app/assets/javascripts/image_diff/helpers/badge_helper.js
@@ -14,7 +14,15 @@ export function createImageBadge(noteId, { x, y }, classNames = []) {
}
export function addImageBadge(containerEl, { coordinate, badgeText, noteId }) {
- const buttonEl = createImageBadge(noteId, coordinate, ['badge', 'badge-pill']);
+ const buttonEl = createImageBadge(noteId, coordinate, [
+ 'gl-display-flex',
+ 'gl-align-items-center',
+ 'gl-justify-content-center',
+ 'gl-font-sm',
+ 'design-note-pin',
+ 'on-image',
+ 'gl-absolute',
+ ]);
buttonEl.textContent = badgeText;
containerEl.appendChild(buttonEl);
@@ -30,8 +38,8 @@ export function addImageCommentBadge(containerEl, { coordinate, noteId }) {
export function addAvatarBadge(el, event) {
const { noteId, badgeNumber } = event.detail;
- // Add badge to new comment
- const avatarBadgeEl = el.querySelector(`#${noteId} .badge`);
+ // Add design pin to new comment
+ const avatarBadgeEl = el.querySelector(`#${noteId} .design-note-pin`);
avatarBadgeEl.textContent = badgeNumber;
avatarBadgeEl.classList.remove('hidden');
}
diff --git a/app/assets/javascripts/image_diff/helpers/dom_helper.js b/app/assets/javascripts/image_diff/helpers/dom_helper.js
index a61e5f01f9b..3468a629f5a 100644
--- a/app/assets/javascripts/image_diff/helpers/dom_helper.js
+++ b/app/assets/javascripts/image_diff/helpers/dom_helper.js
@@ -10,12 +10,12 @@ export function setPositionDataAttribute(el, options) {
}
export function updateDiscussionAvatarBadgeNumber(discussionEl, newBadgeNumber) {
- const avatarBadgeEl = discussionEl.querySelector('.image-diff-avatar-link .badge');
+ const avatarBadgeEl = discussionEl.querySelector('.image-diff-avatar-link .design-note-pin');
avatarBadgeEl.textContent = newBadgeNumber;
}
export function updateDiscussionBadgeNumber(discussionEl, newBadgeNumber) {
- const discussionBadgeEl = discussionEl.querySelector('.badge');
+ const discussionBadgeEl = discussionEl.querySelector('.design-note-pin');
discussionBadgeEl.textContent = newBadgeNumber;
}
diff --git a/app/assets/javascripts/image_diff/image_diff.js b/app/assets/javascripts/image_diff/image_diff.js
index a0dd8e6f894..e3ca4327efe 100644
--- a/app/assets/javascripts/image_diff/image_diff.js
+++ b/app/assets/javascripts/image_diff/image_diff.js
@@ -118,7 +118,7 @@ export default class ImageDiff {
removeBadge(event) {
const { badgeNumber } = event.detail;
const indexToRemove = badgeNumber - 1;
- const imageBadgeEls = this.imageFrameEl.querySelectorAll('.badge');
+ const imageBadgeEls = this.imageFrameEl.querySelectorAll('.design-note-pin');
if (this.imageBadges.length !== badgeNumber) {
// Cascade badges count numbers for (avatar badges + image badges)
diff --git a/app/assets/javascripts/image_diff/replaced_image_diff.js b/app/assets/javascripts/image_diff/replaced_image_diff.js
index a3d9b8a138a..8b84cc45c21 100644
--- a/app/assets/javascripts/image_diff/replaced_image_diff.js
+++ b/app/assets/javascripts/image_diff/replaced_image_diff.js
@@ -61,7 +61,7 @@ export default class ReplacedImageDiff extends ImageDiff {
this.currentView = newView;
// Clear existing badges on new view
- const existingBadges = this.imageFrameEl.querySelectorAll('.badge');
+ const existingBadges = this.imageFrameEl.querySelectorAll('.design-note-pin');
[...existingBadges].map((badge) => badge.remove());
// Remove existing references to old view image badges
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 37597da3c8e..7a904bdb6ad 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -12,7 +12,7 @@ import {
} 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 { s__, n__ } from '~/locale';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import Tracking from '~/tracking';
@@ -38,6 +38,8 @@ import {
import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
+const MAX_VISIBLE_ASSIGNEES = 4;
+
export default {
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
@@ -94,6 +96,7 @@ export default {
thAttr: TH_PUBLISHED_TEST_ID,
},
],
+ MAX_VISIBLE_ASSIGNEES,
components: {
GlLoadingIcon,
GlTable,
@@ -295,6 +298,13 @@ export default {
errorAlertDismissed() {
this.isErrorAlertDismissed = true;
},
+ assigneesBadgeSrOnlyText(item) {
+ return n__(
+ '%d additional assignee',
+ '%d additional assignees',
+ item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
+ );
+ },
isValidSlaDueAt,
},
};
@@ -391,10 +401,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
- :max-visible="4"
+ :max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
+ :badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link
diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js
index b90658fb13c..004601bc0a3 100644
--- a/app/assets/javascripts/integrations/constants.js
+++ b/app/assets/javascripts/integrations/constants.js
@@ -1,7 +1,5 @@
import { s__, __ } from '~/locale';
-export const VALIDATE_INTEGRATION_FORM_EVENT = 'validateIntegrationForm';
-
export const integrationLevels = {
GROUP: 'group',
INSTANCE: 'instance',
@@ -26,5 +24,3 @@ export const I18N_SUCCESSFUL_CONNECTION_MESSAGE = s__('Integrations|Connection s
export const settingsTabTitle = __('Settings');
export const overridesTabTitle = s__('Integrations|Projects using custom settings');
-
-export const INTEGRATION_FORM_SELECTOR = '.js-integration-settings-form';
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index 4b0579a5beb..b4ceec22822 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -9,8 +9,6 @@ import {
} from '@gitlab/ui';
import { capitalize, lowerCase, isEmpty } from 'lodash';
import { mapGetters } from 'vuex';
-import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
-import eventHub from '../event_hub';
export default {
name: 'DynamicField',
@@ -70,11 +68,15 @@ export default {
required: false,
default: null,
},
+ isValidated: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
model: this.value,
- validated: false,
};
},
computed: {
@@ -123,22 +125,13 @@ export default {
};
},
valid() {
- return !this.required || !isEmpty(this.model) || this.isNonEmptyPassword || !this.validated;
+ return !this.required || !isEmpty(this.model) || this.isNonEmptyPassword || !this.isValidated;
},
},
created() {
if (this.isNonEmptyPassword) {
this.model = null;
}
- eventHub.$on(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
- beforeDestroy() {
- eventHub.$off(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
- methods: {
- validateForm() {
- this.validated = true;
- },
},
helpHtmlConfig: {
ADD_ATTR: ['target'], // allow external links, can be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1427 is implemented
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index c3cc35adfa5..007a384f41e 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -5,16 +5,13 @@ import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
- VALIDATE_INTEGRATION_FORM_EVENT,
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
- INTEGRATION_FORM_SELECTOR,
integrationLevels,
} from '~/integrations/constants';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import csrf from '~/lib/utils/csrf';
-import eventHub from '../event_hub';
import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue';
import ConfirmationModal from './confirmation_modal.vue';
@@ -57,6 +54,7 @@ export default {
isTesting: false,
isSaving: false,
isResetting: false,
+ isValidated: false,
};
},
computed: {
@@ -83,54 +81,38 @@ export default {
disableButtons() {
return Boolean(this.isSaving || this.isResetting || this.isTesting);
},
- useVueForm() {
- return this.glFeatures?.vueIntegrationForm;
+ form() {
+ return this.$refs.integrationForm.$el;
},
- formContainerProps() {
- return this.useVueForm
- ? {
- ref: 'integrationForm',
- method: 'post',
- class: 'gl-mb-3 gl-show-field-errors integration-settings-form',
- action: this.propsSource.formPath,
- novalidate: !this.integrationActive,
- }
- : {};
- },
- formContainer() {
- return this.useVueForm ? GlForm : 'div';
- },
- },
- mounted() {
- this.form = this.useVueForm
- ? this.$refs.integrationForm.$el
- : document.querySelector(INTEGRATION_FORM_SELECTOR);
},
methods: {
- ...mapActions(['setOverride', 'fetchResetIntegration', 'requestJiraIssueTypes']),
+ ...mapActions(['setOverride', 'requestJiraIssueTypes']),
+ setIsValidated() {
+ this.isValidated = true;
+ },
onSaveClick() {
this.isSaving = true;
if (this.integrationActive && !this.form.checkValidity()) {
this.isSaving = false;
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ this.setIsValidated();
return;
}
this.form.submit();
},
onTestClick() {
- this.isTesting = true;
-
if (!this.form.checkValidity()) {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ this.setIsValidated();
return;
}
+ this.isTesting = true;
+
testIntegrationSettings(this.propsSource.testPath, this.getFormData())
.then(({ data: { error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } }) => {
if (error) {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ this.setIsValidated();
this.$toast.show(message);
return;
}
@@ -169,16 +151,6 @@ export default {
},
onToggleIntegrationState(integrationActive) {
this.integrationActive = integrationActive;
- if (!this.form || this.useVueForm) {
- return;
- }
-
- // If integration will be active, enable form validation.
- if (integrationActive) {
- this.form.removeAttribute('novalidate');
- } else {
- this.form.setAttribute('novalidate', true);
- }
},
},
helpHtmlConfig: {
@@ -191,17 +163,21 @@ export default {
</script>
<template>
- <component :is="formContainer" v-bind="formContainerProps">
- <template v-if="useVueForm">
- <input type="hidden" name="_method" value="put" />
- <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
- <input
- type="hidden"
- name="redirect_to"
- :value="propsSource.redirectTo"
- data-testid="redirect-to-field"
- />
- </template>
+ <gl-form
+ ref="integrationForm"
+ method="post"
+ class="gl-mb-3 gl-show-field-errors integration-settings-form"
+ :action="propsSource.formPath"
+ :novalidate="!integrationActive"
+ >
+ <input type="hidden" name="_method" value="put" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ <input
+ type="hidden"
+ name="redirect_to"
+ :value="propsSource.redirectTo"
+ data-testid="redirect-to-field"
+ />
<override-dropdown
v-if="defaultState !== null"
@@ -227,6 +203,7 @@ export default {
v-if="isJira"
:key="`${currentKey}-jira-trigger-fields`"
v-bind="propsSource.triggerFieldsProps"
+ :is-validated="isValidated"
/>
<trigger-fields
v-else-if="propsSource.triggerEvents.length"
@@ -238,11 +215,13 @@ export default {
v-for="field in propsSource.fields"
:key="`${currentKey}-${field.name}`"
v-bind="field"
+ :is-validated="isValidated"
/>
<jira-issues-fields
v-if="isJira && !isInstanceOrGroupLevel"
:key="`${currentKey}-jira-issues-fields`"
v-bind="propsSource.jiraIssuesProps"
+ :is-validated="isValidated"
@request-jira-issue-types="onRequestJiraIssueTypes"
/>
@@ -311,5 +290,5 @@ export default {
</div>
</div>
</div>
- </component>
+ </gl-form>
</template>
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 99498501f6c..7f2f7620a86 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -1,9 +1,7 @@
<script>
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import { mapGetters } from 'vuex';
-import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
import { s__, __ } from '~/locale';
-import eventHub from '../event_hub';
import JiraUpgradeCta from './jira_upgrade_cta.vue';
export default {
@@ -64,29 +62,22 @@ export default {
required: false,
default: '',
},
+ isValidated: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
enableJiraIssues: this.initialEnableJiraIssues,
projectKey: this.initialProjectKey,
- validated: false,
};
},
computed: {
...mapGetters(['isInheriting']),
validProjectKey() {
- return !this.enableJiraIssues || Boolean(this.projectKey) || !this.validated;
- },
- },
- created() {
- eventHub.$on(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
- beforeDestroy() {
- eventHub.$off(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
- methods: {
- validateForm() {
- this.validated = true;
+ return !this.enableJiraIssues || Boolean(this.projectKey) || !this.isValidated;
},
},
i18n: {
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 249a3e105b1..df5946b814a 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -9,9 +9,7 @@ import {
} from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
import { s__ } from '~/locale';
-import eventHub from '../event_hub';
const commentDetailOptions = [
{
@@ -92,10 +90,14 @@ export default {
required: false,
default: '',
},
+ isValidated: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
- validated: false,
triggerCommit: this.initialTriggerCommit,
triggerMergeRequest: this.initialTriggerMergeRequest,
enableComments: this.initialEnableComments,
@@ -115,19 +117,10 @@ export default {
return this.triggerCommit || this.triggerMergeRequest;
},
validIssueTransitionId() {
- return !this.validated || Boolean(this.jiraIssueTransitionId);
+ return !this.isValidated || Boolean(this.jiraIssueTransitionId);
},
},
- created() {
- eventHub.$on(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
- beforeDestroy() {
- eventHub.$off(VALIDATE_INTEGRATION_FORM_EVENT, this.validateForm);
- },
methods: {
- validateForm() {
- this.validated = true;
- },
showCustomIssueTransitions(currentOption) {
return (
this.jiraIssueTransitionAutomatic === ISSUE_TRANSITION_CUSTOM &&
diff --git a/app/assets/javascripts/integrations/edit/event_hub.js b/app/assets/javascripts/integrations/edit/event_hub.js
deleted file mode 100644
index e31806ad199..00000000000
--- a/app/assets/javascripts/integrations/edit/event_hub.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import createEventHub from '~/helpers/event_hub_factory';
-
-export default createEventHub();
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 1398b710d1d..d31d3eb9d82 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -1,10 +1,8 @@
import {
- VALIDATE_INTEGRATION_FORM_EVENT,
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
} from '~/integrations/constants';
import { testIntegrationSettings } from '../api';
-import eventHub from '../event_hub';
import * as types from './mutation_types';
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
@@ -19,7 +17,6 @@ export const requestJiraIssueTypes = ({ commit, dispatch, getters }, formData) =
data: { issuetypes, error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE },
}) => {
if (error || !issuetypes?.length) {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
throw new Error(message);
}
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index ddf6bef7554..eb74b0b1c73 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -1,9 +1,5 @@
export const SET_OVERRIDE = 'SET_OVERRIDE';
-export const SET_IS_RESETTING = 'SET_IS_RESETTING';
export const SET_IS_LOADING_JIRA_ISSUE_TYPES = 'SET_IS_LOADING_JIRA_ISSUE_TYPES';
export const SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE = 'SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE';
export const SET_JIRA_ISSUE_TYPES = 'SET_JIRA_ISSUE_TYPES';
-
-export const REQUEST_RESET_INTEGRATION = 'REQUEST_RESET_INTEGRATION';
-export const RECEIVE_RESET_INTEGRATION_ERROR = 'RECEIVE_RESET_INTEGRATION_ERROR';
diff --git a/app/assets/javascripts/invite_members/components/group_select.vue b/app/assets/javascripts/invite_members/components/group_select.vue
index 216078ed35e..04a8ec3400f 100644
--- a/app/assets/javascripts/invite_members/components/group_select.vue
+++ b/app/assets/javascripts/invite_members/components/group_select.vue
@@ -24,6 +24,10 @@ export default {
prop: 'selectedGroup',
},
props: {
+ accessLevels: {
+ type: Object,
+ required: true,
+ },
groupsFilter: {
type: String,
required: false,
@@ -34,6 +38,10 @@ export default {
required: false,
default: null,
},
+ invalidGroups: {
+ type: Array,
+ required: true,
+ },
},
data() {
return {
@@ -50,6 +58,13 @@ export default {
isFetchResultEmpty() {
return this.groups.length === 0;
},
+ defaultFetchOptions() {
+ return {
+ exclude_internal: true,
+ active: true,
+ min_access_level: this.accessLevels.Guest,
+ };
+ },
},
watch: {
searchTerm() {
@@ -64,18 +79,26 @@ export default {
this.isFetching = true;
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.groups = this.processGroups(response);
this.isFetching = false;
})
.catch(() => {
this.isFetching = false;
});
}, SEARCH_DELAY),
+ processGroups(response) {
+ const rawGroups = response.map((group) => ({
+ id: group.id,
+ name: group.full_name,
+ path: group.path,
+ avatarUrl: group.avatar_url,
+ }));
+
+ return this.filterOutInvalidGroups(rawGroups);
+ },
+ filterOutInvalidGroups(groups) {
+ return groups.filter((group) => this.invalidGroups.indexOf(group.id) === -1);
+ },
selectGroup(group) {
this.selectedGroup = group;
@@ -84,13 +107,9 @@ export default {
fetchGroups() {
switch (this.groupsFilter) {
case GROUP_FILTERS.DESCENDANT_GROUPS:
- return getDescendentGroups(
- this.parentGroupId,
- this.searchTerm,
- this.$options.defaultFetchOptions,
- );
+ return getDescendentGroups(this.parentGroupId, this.searchTerm, this.defaultFetchOptions);
default:
- return getGroups(this.searchTerm, this.$options.defaultFetchOptions);
+ return getGroups(this.searchTerm, this.defaultFetchOptions);
}
},
},
@@ -99,10 +118,6 @@ export default {
searchPlaceholder: s__('GroupSelect|Search groups'),
emptySearchResult: s__('GroupSelect|No matching results'),
},
- defaultFetchOptions: {
- exclude_internal: true,
- active: true,
- },
};
</script>
<template>
diff --git a/app/assets/javascripts/invite_members/components/invite_group_trigger.vue b/app/assets/javascripts/invite_members/components/invite_group_trigger.vue
index c9de078319a..c08a4d75c59 100644
--- a/app/assets/javascripts/invite_members/components/invite_group_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_group_trigger.vue
@@ -21,7 +21,7 @@ export default {
},
methods: {
openModal() {
- eventHub.$emit('openModal', { inviteeType: 'group' });
+ eventHub.$emit('openGroupModal');
},
},
};
diff --git a/app/assets/javascripts/invite_members/components/invite_groups_modal.vue b/app/assets/javascripts/invite_members/components/invite_groups_modal.vue
new file mode 100644
index 00000000000..6598000c464
--- /dev/null
+++ b/app/assets/javascripts/invite_members/components/invite_groups_modal.vue
@@ -0,0 +1,146 @@
+<script>
+import { uniqueId } from 'lodash';
+import Api from '~/api';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
+import { GROUP_FILTERS, GROUP_MODAL_LABELS } from '../constants';
+import eventHub from '../event_hub';
+import GroupSelect from './group_select.vue';
+import InviteModalBase from './invite_modal_base.vue';
+
+export default {
+ name: 'InviteMembersModal',
+ components: {
+ GroupSelect,
+ InviteModalBase,
+ },
+ props: {
+ id: {
+ type: String,
+ required: true,
+ },
+ isProject: {
+ type: Boolean,
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ accessLevels: {
+ type: Object,
+ required: true,
+ },
+ defaultAccessLevel: {
+ type: Number,
+ required: true,
+ },
+ helpLink: {
+ type: String,
+ required: true,
+ },
+ groupSelectFilter: {
+ type: String,
+ required: false,
+ default: GROUP_FILTERS.ALL,
+ },
+ groupSelectParentId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ invalidGroups: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ modalId: uniqueId('invite-groups-modal-'),
+ groupToBeSharedWith: {},
+ };
+ },
+ computed: {
+ labelIntroText() {
+ return this.$options.labels[this.inviteTo].introText;
+ },
+ inviteTo() {
+ return this.isProject ? 'toProject' : 'toGroup';
+ },
+ toastOptions() {
+ return {
+ onComplete: () => {
+ this.groupToBeSharedWith = {};
+ },
+ };
+ },
+ inviteDisabled() {
+ return Object.keys(this.groupToBeSharedWith).length === 0;
+ },
+ },
+ mounted() {
+ eventHub.$on('openGroupModal', () => {
+ this.openModal();
+ });
+ },
+ methods: {
+ openModal() {
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
+ },
+ closeModal() {
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
+ },
+ sendInvite({ onError, onSuccess, data: { accessLevel, expiresAt } }) {
+ const apiShareWithGroup = this.isProject
+ ? Api.projectShareWithGroup.bind(Api)
+ : Api.groupShareWithGroup.bind(Api);
+
+ apiShareWithGroup(this.id, {
+ format: 'json',
+ group_id: this.groupToBeSharedWith.id,
+ group_access: accessLevel,
+ expires_at: expiresAt,
+ })
+ .then(() => {
+ onSuccess();
+ this.showSuccessMessage();
+ })
+ .catch(onError);
+ },
+ resetFields() {
+ this.groupToBeSharedWith = {};
+ },
+ showSuccessMessage() {
+ this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
+ this.closeModal();
+ },
+ },
+ labels: GROUP_MODAL_LABELS,
+};
+</script>
+<template>
+ <invite-modal-base
+ :modal-id="modalId"
+ :modal-title="$options.labels.title"
+ :name="name"
+ :access-levels="accessLevels"
+ :default-access-level="defaultAccessLevel"
+ :help-link="helpLink"
+ v-bind="$attrs"
+ :label-intro-text="labelIntroText"
+ :label-search-field="$options.labels.searchField"
+ :submit-disabled="inviteDisabled"
+ @reset="resetFields"
+ @submit="sendInvite"
+ >
+ <template #select="{ clearValidation }">
+ <group-select
+ v-model="groupToBeSharedWith"
+ :access-levels="accessLevels"
+ :groups-filter="groupSelectFilter"
+ :parent-group-id="groupSelectParentId"
+ :invalid-groups="invalidGroups"
+ @input="clearValidation"
+ />
+ </template>
+ </invite-modal-base>
+</template>
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 91a139a5105..6c0fc5caf26 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -1,56 +1,40 @@
<script>
import {
GlAlert,
- GlFormGroup,
- GlModal,
GlDropdown,
GlDropdownItem,
- GlDatepicker,
GlLink,
GlSprintf,
- GlButton,
- GlFormInput,
GlFormCheckboxGroup,
} from '@gitlab/ui';
-import { partition, isString, unescape, uniqueId } from 'lodash';
+import { partition, isString, uniqueId } from 'lodash';
+import InviteModalBase from 'ee_else_ce/invite_members/components/invite_modal_base.vue';
import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
-import { sanitize } from '~/lib/dompurify';
-import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { getParameterValues } from '~/lib/utils/url_utility';
-import { sprintf } from '~/locale';
import {
- GROUP_FILTERS,
USERS_FILTER_ALL,
INVITE_MEMBERS_FOR_TASK,
- MODAL_LABELS,
+ MEMBER_MODAL_LABELS,
LEARN_GITLAB,
} from '../constants';
import eventHub from '../event_hub';
-import {
- responseMessageFromError,
- responseMessageFromSuccess,
-} from '../utils/response_message_parser';
+import { responseMessageFromSuccess } from '../utils/response_message_parser';
import ModalConfetti from './confetti.vue';
-import GroupSelect from './group_select.vue';
import MembersTokenSelect from './members_token_select.vue';
export default {
name: 'InviteMembersModal',
components: {
GlAlert,
- GlFormGroup,
- GlDatepicker,
GlLink,
- GlModal,
GlDropdown,
GlDropdownItem,
GlSprintf,
- GlButton,
- GlFormInput,
GlFormCheckboxGroup,
+ InviteModalBase,
MembersTokenSelect,
- GroupSelect,
ModalConfetti,
},
inject: ['newProjectPath'],
@@ -75,15 +59,9 @@ export default {
type: Number,
required: true,
},
- groupSelectFilter: {
+ helpLink: {
type: String,
- required: false,
- default: GROUP_FILTERS.ALL,
- },
- groupSelectParentId: {
- type: Number,
- required: false,
- default: null,
+ required: true,
},
usersFilter: {
type: String,
@@ -95,10 +73,6 @@ export default {
required: false,
default: null,
},
- helpLink: {
- type: String,
- required: true,
- },
tasksToBeDoneOptions: {
type: Array,
required: true,
@@ -110,73 +84,31 @@ export default {
},
data() {
return {
- visible: true,
modalId: uniqueId('invite-members-modal-'),
- selectedAccessLevel: this.defaultAccessLevel,
- inviteeType: 'members',
newUsersToInvite: [],
- selectedDate: undefined,
selectedTasksToBeDone: [],
selectedTaskProject: this.projects[0],
- groupToBeSharedWith: {},
source: 'unknown',
- invalidFeedbackMessage: '',
- isLoading: false,
mode: 'default',
+ // Kept in sync with "base"
+ selectedAccessLevel: undefined,
};
},
computed: {
isCelebration() {
return this.mode === 'celebrate';
},
- validationState() {
- return this.invalidFeedbackMessage === '' ? null : false;
- },
- isInviteGroup() {
- return this.inviteeType === 'group';
- },
modalTitle() {
- return this.$options.labels[this.inviteeType].modal[this.mode].title;
- },
- introText() {
- return sprintf(this.$options.labels[this.inviteeType][this.inviteTo][this.mode].introText, {
- name: this.name,
- });
+ return this.$options.labels.modal[this.mode].title;
},
inviteTo() {
return this.isProject ? 'toProject' : 'toGroup';
},
- toastOptions() {
- return {
- onComplete: () => {
- this.selectedAccessLevel = this.defaultAccessLevel;
- this.newUsersToInvite = [];
- this.groupToBeSharedWith = {};
- },
- };
- },
- basePostData() {
- return {
- expires_at: this.selectedDate,
- format: 'json',
- };
- },
- selectedRoleName() {
- return Object.keys(this.accessLevels).find(
- (key) => this.accessLevels[key] === Number(this.selectedAccessLevel),
- );
+ labelIntroText() {
+ return this.$options.labels[this.inviteTo][this.mode].introText;
},
inviteDisabled() {
- return (
- this.newUsersToInvite.length === 0 && Object.keys(this.groupToBeSharedWith).length === 0
- );
- },
- errorFieldDescription() {
- if (this.inviteeType === 'group') {
- return '';
- }
-
- return this.$options.labels[this.inviteeType].placeHolder;
+ return this.newUsersToInvite.length === 0;
},
tasksToBeDoneEnabled() {
return (
@@ -215,7 +147,7 @@ export default {
});
if (this.tasksToBeDoneEnabled) {
- this.openModal({ inviteeType: 'members', source: 'in_product_marketing_email' });
+ this.openModal({ source: 'in_product_marketing_email' });
this.trackEvent(INVITE_MEMBERS_FOR_TASK.name, INVITE_MEMBERS_FOR_TASK.view);
}
},
@@ -231,72 +163,42 @@ export default {
usersToAddById.map((user) => user.id).join(','),
];
},
- openModal({ mode = 'default', inviteeType, source }) {
+ openModal({ mode = 'default', source }) {
this.mode = mode;
- this.inviteeType = inviteeType;
this.source = source;
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
+ closeModal() {
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
+ },
trackEvent(experimentName, eventName) {
const tracking = new ExperimentTracking(experimentName);
tracking.event(eventName);
},
- closeModal() {
- this.resetFields();
- this.$refs.modal.hide();
- },
- sendInvite() {
- if (this.isInviteGroup) {
- this.submitShareWithGroup();
- } else {
- this.submitInviteMembers();
- }
- },
- trackinviteMembersForTask() {
- const label = 'selected_tasks_to_be_done';
- const property = this.selectedTasksToBeDone.join(',');
- const tracking = new ExperimentTracking(INVITE_MEMBERS_FOR_TASK.name, { label, property });
- tracking.event(INVITE_MEMBERS_FOR_TASK.submit);
- },
- resetFields() {
- this.isLoading = false;
- this.selectedAccessLevel = this.defaultAccessLevel;
- this.selectedDate = undefined;
- this.newUsersToInvite = [];
- this.groupToBeSharedWith = {};
- this.invalidFeedbackMessage = '';
- this.selectedTasksToBeDone = [];
- [this.selectedTaskProject] = this.projects;
- },
- changeSelectedItem(item) {
- this.selectedAccessLevel = item;
- },
- changeSelectedTaskProject(project) {
- this.selectedTaskProject = project;
- },
- submitShareWithGroup() {
- const apiShareWithGroup = this.isProject
- ? Api.projectShareWithGroup.bind(Api)
- : Api.groupShareWithGroup.bind(Api);
-
- apiShareWithGroup(this.id, this.shareWithGroupPostData(this.groupToBeSharedWith.id))
- .then(this.showSuccessMessage)
- .catch(this.showInvalidFeedbackMessage);
- },
- submitInviteMembers() {
- this.invalidFeedbackMessage = '';
- this.isLoading = true;
-
+ sendInvite({ onError, onSuccess, data: { accessLevel, expiresAt } }) {
const [usersToInviteByEmail, usersToAddById] = this.partitionNewUsersToInvite();
const promises = [];
+ const baseData = {
+ format: 'json',
+ expires_at: expiresAt,
+ access_level: accessLevel,
+ invite_source: this.source,
+ tasks_to_be_done: this.tasksToBeDoneForPost,
+ tasks_project_id: this.tasksProjectForPost,
+ };
if (usersToInviteByEmail !== '') {
const apiInviteByEmail = this.isProject
? Api.inviteProjectMembersByEmail.bind(Api)
: Api.inviteGroupMembersByEmail.bind(Api);
- promises.push(apiInviteByEmail(this.id, this.inviteByEmailPostData(usersToInviteByEmail)));
+ promises.push(
+ apiInviteByEmail(this.id, {
+ ...baseData,
+ email: usersToInviteByEmail,
+ }),
+ );
}
if (usersToAddById !== '') {
@@ -304,188 +206,103 @@ export default {
? Api.addProjectMembersByUserId.bind(Api)
: Api.addGroupMembersByUserId.bind(Api);
- promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
+ promises.push(
+ apiAddByUserId(this.id, {
+ ...baseData,
+ user_id: usersToAddById,
+ }),
+ );
}
this.trackinviteMembersForTask();
Promise.all(promises)
- .then(this.conditionallyShowSuccessMessage)
- .catch(this.showInvalidFeedbackMessage);
- },
- inviteByEmailPostData(usersToInviteByEmail) {
- return {
- ...this.basePostData,
- email: usersToInviteByEmail,
- access_level: this.selectedAccessLevel,
- invite_source: this.source,
- tasks_to_be_done: this.tasksToBeDoneForPost,
- tasks_project_id: this.tasksProjectForPost,
- };
+ .then((responses) => {
+ const message = responseMessageFromSuccess(responses);
+
+ if (message) {
+ onError({
+ response: {
+ data: {
+ message,
+ },
+ },
+ });
+ } else {
+ onSuccess();
+ this.showSuccessMessage();
+ }
+ })
+ .catch(onError);
},
- addByUserIdPostData(usersToAddById) {
- return {
- ...this.basePostData,
- user_id: usersToAddById,
- access_level: this.selectedAccessLevel,
- invite_source: this.source,
- tasks_to_be_done: this.tasksToBeDoneForPost,
- tasks_project_id: this.tasksProjectForPost,
- };
+ trackinviteMembersForTask() {
+ const label = 'selected_tasks_to_be_done';
+ const property = this.selectedTasksToBeDone.join(',');
+ const tracking = new ExperimentTracking(INVITE_MEMBERS_FOR_TASK.name, { label, property });
+ tracking.event(INVITE_MEMBERS_FOR_TASK.submit);
},
- shareWithGroupPostData(groupToBeSharedWith) {
- return {
- ...this.basePostData,
- group_id: groupToBeSharedWith,
- group_access: this.selectedAccessLevel,
- };
+ resetFields() {
+ this.newUsersToInvite = [];
+ this.selectedTasksToBeDone = [];
+ [this.selectedTaskProject] = this.projects;
},
- conditionallyShowSuccessMessage(response) {
- const message = this.unescapeMsg(responseMessageFromSuccess(response));
-
- if (message === '') {
- this.showSuccessMessage();
-
- return;
- }
-
- this.invalidFeedbackMessage = message;
- this.isLoading = false;
+ changeSelectedTaskProject(project) {
+ this.selectedTaskProject = project;
},
showSuccessMessage() {
if (this.isOnLearnGitlab) {
eventHub.$emit('showSuccessfulInvitationsAlert');
} else {
- this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
+ this.$toast.show(this.$options.labels.toastMessageSuccessful);
}
- this.closeModal();
- },
- showInvalidFeedbackMessage(response) {
- const message = this.unescapeMsg(responseMessageFromError(response));
- this.isLoading = false;
- this.invalidFeedbackMessage = message || this.$options.labels.invalidFeedbackMessageDefault;
- },
- handleMembersTokenSelectClear() {
- this.invalidFeedbackMessage = '';
+ this.closeModal();
},
- unescapeMsg(message) {
- return unescape(sanitize(message, { ALLOWED_TAGS: [] }));
+ onAccessLevelUpdate(val) {
+ this.selectedAccessLevel = val;
},
},
- labels: MODAL_LABELS,
- membersTokenSelectLabelId: 'invite-members-input',
+ labels: MEMBER_MODAL_LABELS,
};
</script>
<template>
- <gl-modal
- ref="modal"
+ <invite-modal-base
:modal-id="modalId"
- size="sm"
- data-qa-selector="invite_members_modal_content"
- data-testid="invite-members-modal"
- :title="modalTitle"
- :header-close-label="$options.labels.headerCloseLabel"
- @hidden="resetFields"
- @close="resetFields"
- @hide="resetFields"
+ :modal-title="modalTitle"
+ :name="name"
+ :access-levels="accessLevels"
+ :default-access-level="defaultAccessLevel"
+ :help-link="helpLink"
+ :label-intro-text="labelIntroText"
+ :label-search-field="$options.labels.searchField"
+ :form-group-description="$options.labels.placeHolder"
+ :submit-disabled="inviteDisabled"
+ @reset="resetFields"
+ @submit="sendInvite"
+ @access-level="onAccessLevelUpdate"
>
- <div>
- <div class="gl-display-flex">
- <div v-if="isCelebration" class="gl-p-4 gl-font-size-h1"><gl-emoji data-name="tada" /></div>
- <div>
- <p ref="introText">
- <gl-sprintf :message="introText">
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- <br />
- <span v-if="isCelebration">{{ $options.labels.members.modal.celebrate.intro }} </span>
- <modal-confetti v-if="isCelebration" />
- </p>
- </div>
- </div>
-
- <gl-form-group
- :invalid-feedback="invalidFeedbackMessage"
- :state="validationState"
- :description="errorFieldDescription"
- data-testid="members-form-group"
- >
- <label :id="$options.membersTokenSelectLabelId" class="col-form-label">{{
- $options.labels[inviteeType].searchField
- }}</label>
- <members-token-select
- v-if="!isInviteGroup"
- v-model="newUsersToInvite"
- class="gl-mb-2"
- :validation-state="validationState"
- :aria-labelledby="$options.membersTokenSelectLabelId"
- :users-filter="usersFilter"
- :filter-id="filterId"
- @clear="handleMembersTokenSelectClear"
- />
- <group-select
- v-if="isInviteGroup"
- v-model="groupToBeSharedWith"
- :groups-filter="groupSelectFilter"
- :parent-group-id="groupSelectParentId"
- @input="handleMembersTokenSelectClear"
- />
- </gl-form-group>
-
- <label class="gl-font-weight-bold">{{ $options.labels.accessLevel }}</label>
- <div class="gl-mt-2 gl-w-half gl-xs-w-full">
- <gl-dropdown
- class="gl-shadow-none gl-w-full"
- data-qa-selector="access_level_dropdown"
- v-bind="$attrs"
- :text="selectedRoleName"
- >
- <template v-for="(key, item) in accessLevels">
- <gl-dropdown-item
- :key="key"
- active-class="is-active"
- is-check-item
- :is-checked="key === selectedAccessLevel"
- @click="changeSelectedItem(key)"
- >
- <div>{{ item }}</div>
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
- </div>
-
- <div class="gl-mt-2 gl-w-half gl-xs-w-full">
- <gl-sprintf :message="$options.labels.readMoreText">
- <template #link="{ content }">
- <gl-link :href="helpLink" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
-
- <label class="gl-mt-5 gl-display-block" for="expires_at">{{
- $options.labels.accessExpireDate
- }}</label>
- <div class="gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block">
- <gl-datepicker
- v-model="selectedDate"
- class="gl-display-inline!"
- :min-date="new Date()"
- :target="null"
- >
- <template #default="{ formattedDate }">
- <gl-form-input
- class="gl-w-full"
- :value="formattedDate"
- :placeholder="__(`YYYY-MM-DD`)"
- />
- </template>
- </gl-datepicker>
- </div>
+ <template #intro-text-before>
+ <div v-if="isCelebration" class="gl-p-4 gl-font-size-h1"><gl-emoji data-name="tada" /></div>
+ </template>
+ <template #intro-text-after>
+ <br />
+ <span v-if="isCelebration">{{ $options.labels.modal.celebrate.intro }} </span>
+ <modal-confetti v-if="isCelebration" />
+ </template>
+ <template #select="{ clearValidation, validationState, labelId }">
+ <members-token-select
+ v-model="newUsersToInvite"
+ class="gl-mb-2"
+ :validation-state="validationState"
+ :aria-labelledby="labelId"
+ :users-filter="usersFilter"
+ :filter-id="filterId"
+ @clear="clearValidation"
+ />
+ </template>
+ <template #form-after>
<div v-if="showTasksToBeDone" data-testid="invite-members-modal-tasks-to-be-done">
<label class="gl-mt-5">
- {{ $options.labels.members.tasksToBeDone.title }}
+ {{ $options.labels.tasksToBeDone.title }}
</label>
<template v-if="projects.length">
<gl-form-checkbox-group
@@ -495,7 +312,7 @@ export default {
/>
<template v-if="showTaskProjects">
<label class="gl-mt-5 gl-display-block">
- {{ $options.labels.members.tasksProject.title }}
+ {{ $options.labels.tasksProject.title }}
</label>
<gl-dropdown
class="gl-w-half gl-xs-w-full"
@@ -522,7 +339,7 @@ export default {
:dismissible="false"
data-testid="invite-members-modal-no-projects-alert"
>
- <gl-sprintf :message="$options.labels.members.tasksToBeDone.noProjects">
+ <gl-sprintf :message="$options.labels.tasksToBeDone.noProjects">
<template #link="{ content }">
<gl-link :href="newProjectPath" target="_blank" class="gl-label-link">
{{ content }}
@@ -531,22 +348,6 @@ export default {
</gl-sprintf>
</gl-alert>
</div>
- </div>
-
- <template #modal-footer>
- <gl-button data-testid="cancel-button" @click="closeModal">
- {{ $options.labels.cancelButtonText }}
- </gl-button>
- <gl-button
- :disabled="inviteDisabled"
- :loading="isLoading"
- variant="success"
- data-qa-selector="invite_button"
- data-testid="invite-button"
- @click="sendInvite"
- >
- {{ $options.labels.inviteButtonText }}
- </gl-button>
</template>
- </gl-modal>
+ </invite-modal-base>
</template>
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 7dd74f8803a..79b192e2495 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -71,7 +71,7 @@ export default {
return this.triggerElement === targetTriggerElement;
},
openModal() {
- eventHub.$emit('openModal', { inviteeType: 'members', source: this.triggerSource });
+ eventHub.$emit('openModal', { source: this.triggerSource });
},
},
TRIGGER_ELEMENT_BUTTON,
diff --git a/app/assets/javascripts/invite_members/components/invite_modal_base.vue b/app/assets/javascripts/invite_members/components/invite_modal_base.vue
new file mode 100644
index 00000000000..fc00f5b9343
--- /dev/null
+++ b/app/assets/javascripts/invite_members/components/invite_modal_base.vue
@@ -0,0 +1,276 @@
+<script>
+import {
+ GlFormGroup,
+ GlModal,
+ GlDropdown,
+ GlDropdownItem,
+ GlDatepicker,
+ GlLink,
+ GlSprintf,
+ GlButton,
+ GlFormInput,
+} from '@gitlab/ui';
+import { unescape } from 'lodash';
+import { sanitize } from '~/lib/dompurify';
+import { sprintf } from '~/locale';
+import {
+ ACCESS_LEVEL,
+ ACCESS_EXPIRE_DATE,
+ INVALID_FEEDBACK_MESSAGE_DEFAULT,
+ READ_MORE_TEXT,
+ INVITE_BUTTON_TEXT,
+ CANCEL_BUTTON_TEXT,
+ HEADER_CLOSE_LABEL,
+} from '../constants';
+import { responseMessageFromError } from '../utils/response_message_parser';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlDatepicker,
+ GlLink,
+ GlModal,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ GlButton,
+ GlFormInput,
+ },
+ inheritAttrs: false,
+ props: {
+ modalTitle: {
+ type: String,
+ required: true,
+ },
+ modalId: {
+ type: String,
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ accessLevels: {
+ type: Object,
+ required: true,
+ },
+ defaultAccessLevel: {
+ type: Number,
+ required: true,
+ },
+ helpLink: {
+ type: String,
+ required: true,
+ },
+ labelIntroText: {
+ type: String,
+ required: true,
+ },
+ labelSearchField: {
+ type: String,
+ required: true,
+ },
+ formGroupDescription: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ submitDisabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ // Be sure to check out reset!
+ return {
+ invalidFeedbackMessage: '',
+ selectedAccessLevel: this.defaultAccessLevel,
+ selectedDate: undefined,
+ isLoading: false,
+ minDate: new Date(),
+ };
+ },
+ computed: {
+ introText() {
+ return sprintf(this.labelIntroText, { name: this.name });
+ },
+ validationState() {
+ return this.invalidFeedbackMessage ? false : null;
+ },
+ selectLabelId() {
+ return `${this.modalId}_select`;
+ },
+ selectedRoleName() {
+ return Object.keys(this.accessLevels).find(
+ (key) => this.accessLevels[key] === Number(this.selectedAccessLevel),
+ );
+ },
+ },
+ watch: {
+ selectedAccessLevel: {
+ immediate: true,
+ handler(val) {
+ this.$emit('access-level', val);
+ },
+ },
+ },
+ methods: {
+ showInvalidFeedbackMessage(response) {
+ const message = this.unescapeMsg(responseMessageFromError(response));
+
+ this.invalidFeedbackMessage = message || INVALID_FEEDBACK_MESSAGE_DEFAULT;
+ },
+ reset() {
+ // This component isn't necessarily disposed,
+ // so we might need to reset it's state.
+ this.isLoading = false;
+ this.invalidFeedbackMessage = '';
+ this.selectedAccessLevel = this.defaultAccessLevel;
+ this.selectedDate = undefined;
+
+ this.$emit('reset');
+ },
+ closeModal() {
+ this.reset();
+ this.$refs.modal.hide();
+ },
+ clearValidation() {
+ this.invalidFeedbackMessage = '';
+ },
+ changeSelectedItem(item) {
+ this.selectedAccessLevel = item;
+ },
+ submit() {
+ this.isLoading = true;
+ this.invalidFeedbackMessage = '';
+
+ this.$emit('submit', {
+ onSuccess: () => {
+ this.isLoading = false;
+ },
+ onError: (...args) => {
+ this.isLoading = false;
+ this.showInvalidFeedbackMessage(...args);
+ },
+ data: {
+ accessLevel: this.selectedAccessLevel,
+ expiresAt: this.selectedDate,
+ },
+ });
+ },
+ unescapeMsg(message) {
+ return unescape(sanitize(message, { ALLOWED_TAGS: [] }));
+ },
+ },
+ HEADER_CLOSE_LABEL,
+ ACCESS_EXPIRE_DATE,
+ ACCESS_LEVEL,
+ READ_MORE_TEXT,
+ INVITE_BUTTON_TEXT,
+ CANCEL_BUTTON_TEXT,
+};
+</script>
+
+<template>
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ data-qa-selector="invite_members_modal_content"
+ data-testid="invite-modal"
+ size="sm"
+ :title="modalTitle"
+ :header-close-label="$options.HEADER_CLOSE_LABEL"
+ @hidden="reset"
+ @close="reset"
+ @hide="reset"
+ >
+ <div class="gl-display-flex" data-testid="modal-base-intro-text">
+ <slot name="intro-text-before"></slot>
+ <p>
+ <gl-sprintf :message="introText">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
+ <slot name="intro-text-after"></slot>
+ </div>
+
+ <gl-form-group
+ :invalid-feedback="invalidFeedbackMessage"
+ :state="validationState"
+ :description="formGroupDescription"
+ data-testid="members-form-group"
+ >
+ <label :id="selectLabelId" class="col-form-label">{{ labelSearchField }}</label>
+ <slot
+ name="select"
+ v-bind="{ clearValidation, validationState, labelId: selectLabelId }"
+ ></slot>
+ </gl-form-group>
+
+ <label class="gl-font-weight-bold">{{ $options.ACCESS_LEVEL }}</label>
+ <div class="gl-mt-2 gl-w-half gl-xs-w-full">
+ <gl-dropdown
+ class="gl-shadow-none gl-w-full"
+ data-qa-selector="access_level_dropdown"
+ v-bind="$attrs"
+ :text="selectedRoleName"
+ >
+ <template v-for="(key, item) in accessLevels">
+ <gl-dropdown-item
+ :key="key"
+ active-class="is-active"
+ is-check-item
+ :is-checked="key === selectedAccessLevel"
+ @click="changeSelectedItem(key)"
+ >
+ <div>{{ item }}</div>
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+ </div>
+
+ <div class="gl-mt-2 gl-w-half gl-xs-w-full">
+ <gl-sprintf :message="$options.READ_MORE_TEXT">
+ <template #link="{ content }">
+ <gl-link :href="helpLink" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+
+ <label class="gl-mt-5 gl-display-block" for="expires_at">{{
+ $options.ACCESS_EXPIRE_DATE
+ }}</label>
+ <div class="gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block">
+ <gl-datepicker
+ v-model="selectedDate"
+ class="gl-display-inline!"
+ :min-date="minDate"
+ :target="null"
+ >
+ <template #default="{ formattedDate }">
+ <gl-form-input class="gl-w-full" :value="formattedDate" :placeholder="__(`YYYY-MM-DD`)" />
+ </template>
+ </gl-datepicker>
+ </div>
+ <slot name="form-after"></slot>
+
+ <template #modal-footer>
+ <gl-button data-testid="cancel-button" @click="closeModal">
+ {{ $options.CANCEL_BUTTON_TEXT }}
+ </gl-button>
+ <gl-button
+ :disabled="submitDisabled"
+ :loading="isLoading"
+ variant="success"
+ data-qa-selector="invite_button"
+ data-testid="invite-button"
+ @click="submit"
+ >
+ {{ $options.INVITE_BUTTON_TEXT }}
+ </gl-button>
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index ec59b3909fe..cf2ee508184 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -72,67 +72,52 @@ export const INVITE_BUTTON_TEXT = s__('InviteMembersModal|Invite');
export const CANCEL_BUTTON_TEXT = s__('InviteMembersModal|Cancel');
export const HEADER_CLOSE_LABEL = s__('InviteMembersModal|Close invite team members');
-export const MODAL_LABELS = {
- members: {
- modal: {
- default: {
- title: MEMBERS_MODAL_DEFAULT_TITLE,
- },
- celebrate: {
- title: MEMBERS_MODAL_CELEBRATE_TITLE,
- intro: MEMBERS_MODAL_CELEBRATE_INTRO,
- },
+export const MEMBER_MODAL_LABELS = {
+ modal: {
+ default: {
+ title: MEMBERS_MODAL_DEFAULT_TITLE,
},
- toGroup: {
- default: {
- introText: MEMBERS_TO_GROUP_DEFAULT_INTRO_TEXT,
- },
- },
- toProject: {
- default: {
- introText: MEMBERS_TO_PROJECT_DEFAULT_INTRO_TEXT,
- },
- celebrate: {
- introText: MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
- },
- },
- searchField: MEMBERS_SEARCH_FIELD,
- placeHolder: MEMBERS_PLACEHOLDER,
- tasksToBeDone: {
- title: MEMBERS_TASKS_TO_BE_DONE_TITLE,
- noProjects: MEMBERS_TASKS_TO_BE_DONE_NO_PROJECTS,
- },
- tasksProject: {
- title: MEMBERS_TASKS_PROJECTS_TITLE,
+ celebrate: {
+ title: MEMBERS_MODAL_CELEBRATE_TITLE,
+ intro: MEMBERS_MODAL_CELEBRATE_INTRO,
},
},
- group: {
- modal: {
- default: {
- title: GROUP_MODAL_DEFAULT_TITLE,
- },
+ toGroup: {
+ default: {
+ introText: MEMBERS_TO_GROUP_DEFAULT_INTRO_TEXT,
},
- toGroup: {
- default: {
- introText: GROUP_MODAL_TO_GROUP_DEFAULT_INTRO_TEXT,
- },
+ },
+ toProject: {
+ default: {
+ introText: MEMBERS_TO_PROJECT_DEFAULT_INTRO_TEXT,
},
- toProject: {
- default: {
- introText: GROUP_MODAL_TO_PROJECT_DEFAULT_INTRO_TEXT,
- },
+ celebrate: {
+ introText: MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
},
- searchField: GROUP_SEARCH_FIELD,
- placeHolder: GROUP_PLACEHOLDER,
},
- accessLevel: ACCESS_LEVEL,
- accessExpireDate: ACCESS_EXPIRE_DATE,
+ searchField: MEMBERS_SEARCH_FIELD,
+ placeHolder: MEMBERS_PLACEHOLDER,
+ tasksToBeDone: {
+ title: MEMBERS_TASKS_TO_BE_DONE_TITLE,
+ noProjects: MEMBERS_TASKS_TO_BE_DONE_NO_PROJECTS,
+ },
+ tasksProject: {
+ title: MEMBERS_TASKS_PROJECTS_TITLE,
+ },
+ toastMessageSuccessful: TOAST_MESSAGE_SUCCESSFUL,
+};
+
+export const GROUP_MODAL_LABELS = {
+ title: GROUP_MODAL_DEFAULT_TITLE,
+ toGroup: {
+ introText: GROUP_MODAL_TO_GROUP_DEFAULT_INTRO_TEXT,
+ },
+ toProject: {
+ introText: GROUP_MODAL_TO_PROJECT_DEFAULT_INTRO_TEXT,
+ },
+ searchField: GROUP_SEARCH_FIELD,
+ placeHolder: GROUP_PLACEHOLDER,
toastMessageSuccessful: TOAST_MESSAGE_SUCCESSFUL,
- invalidFeedbackMessageDefault: INVALID_FEEDBACK_MESSAGE_DEFAULT,
- readMoreText: READ_MORE_TEXT,
- inviteButtonText: INVITE_BUTTON_TEXT,
- cancelButtonText: CANCEL_BUTTON_TEXT,
- headerCloseLabel: HEADER_CLOSE_LABEL,
};
export const LEARN_GITLAB = 'learn_gitlab';
diff --git a/app/assets/javascripts/invite_members/init_invite_groups_modal.js b/app/assets/javascripts/invite_members/init_invite_groups_modal.js
new file mode 100644
index 00000000000..be1576ad0b0
--- /dev/null
+++ b/app/assets/javascripts/invite_members/init_invite_groups_modal.js
@@ -0,0 +1,44 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import InviteGroupsModal from '~/invite_members/components/invite_groups_modal.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+Vue.use(GlToast);
+
+let initedInviteGroupsModal;
+
+export default function initInviteGroupsModal() {
+ if (initedInviteGroupsModal) {
+ // if we already loaded this in another part of the dom, we don't want to do it again
+ // else we will stack the modals
+ return false;
+ }
+
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/344955
+ // bug lying in wait here for someone to put group and project invite in same screen
+ // once that happens we'll need to mount these differently, perhaps split
+ // group/project to each mount one, with many ways to open it.
+ const el = document.querySelector('.js-invite-groups-modal');
+
+ if (!el) {
+ return false;
+ }
+
+ initedInviteGroupsModal = true;
+
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(InviteGroupsModal, {
+ props: {
+ ...el.dataset,
+ 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),
+ invalidGroups: JSON.parse(el.dataset.invalidGroups || '[]'),
+ },
+ }),
+ });
+}
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 2cc056f2ddb..e9d620cedf0 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -28,6 +28,7 @@ export default function initInviteMembersModal() {
return new Vue({
el,
+ name: 'InviteMembersModalRoot',
provide: {
newProjectPath: el.dataset.newProjectPath,
},
@@ -38,8 +39,6 @@ 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),
tasksToBeDoneOptions: JSON.parse(el.dataset.tasksToBeDoneOptions || '[]'),
projects: JSON.parse(el.dataset.projects || '[]'),
usersFilter: el.dataset.usersFilter,
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 935edb35349..54a5eab2e4b 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_trigger.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
@@ -11,6 +11,7 @@ export default function initInviteMembersTrigger() {
return triggers.forEach((el) => {
return new Vue({
el,
+ name: 'InviteMembersTriggerRoot',
render: (createElement) =>
createElement(InviteMembersTrigger, {
props: {
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js b/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
index dca606556d0..967996b859e 100644
--- a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
@@ -23,6 +23,7 @@ export function initIssueStatusSelect() {
return new Vue({
el,
+ name: 'StatusSelectRoot',
render: (createElement) => createElement(StatusSelect),
});
}
diff --git a/app/assets/javascripts/issuable/index.js b/app/assets/javascripts/issuable/index.js
index 57bad5182e7..10dbefce503 100644
--- a/app/assets/javascripts/issuable/index.js
+++ b/app/assets/javascripts/issuable/index.js
@@ -32,6 +32,7 @@ export function initCsvImportExportButtons() {
return new Vue({
el,
+ name: 'CsvImportExportButtonsRoot',
provide: {
showExportButton: parseBoolean(showExportButton),
showImportButton: parseBoolean(showImportButton),
@@ -74,6 +75,7 @@ export function initIssuableByEmail() {
return new Vue({
el,
+ name: 'IssuableByEmailRoot',
provide: {
initialEmail,
issuableType,
@@ -97,6 +99,7 @@ export function initIssuableHeaderWarnings(store) {
return new Vue({
el,
+ name: 'IssuableHeaderWarningsRoot',
store,
provide: { hidden: parseBoolean(hidden) },
render: (createElement) => createElement(IssuableHeaderWarnings),
diff --git a/app/assets/javascripts/issuable/issuable_context.js b/app/assets/javascripts/issuable/issuable_context.js
index 453305dd6e0..37001d00a27 100644
--- a/app/assets/javascripts/issuable/issuable_context.js
+++ b/app/assets/javascripts/issuable/issuable_context.js
@@ -1,6 +1,6 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import { loadCSSFile } from '~/lib/utils/css_utils';
import UsersSelect from '~/users_select';
@@ -62,7 +62,7 @@ export default class IssuableContext {
const supportedSizes = ['xs', 'sm', 'md'];
if (supportedSizes.includes(bpBreakpoint)) {
- Cookies.set('collapsed_gutter', true);
+ setCookie('collapsed_gutter', true);
}
});
}
diff --git a/app/assets/javascripts/issuable/issuable_form.js b/app/assets/javascripts/issuable/issuable_form.js
index 91f47a86cb7..88c1748db0b 100644
--- a/app/assets/javascripts/issuable/issuable_form.js
+++ b/app/assets/javascripts/issuable/issuable_form.js
@@ -77,6 +77,7 @@ export default class IssuableForm {
this.initAutosave();
this.form.on('submit', this.handleSubmit);
this.form.on('click', '.btn-cancel', this.resetAutosave);
+ this.form.find('.js-unwrap-on-load').unwrap();
this.initWip();
const $issuableDueDate = $('#issuable-due-date');
diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js
index 5d36396bc6e..a3752c7043c 100644
--- a/app/assets/javascripts/issues/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js
@@ -69,11 +69,11 @@ export default class CreateMergeRequestDropdown {
this.regexps = {
branch: {
createBranchPath: new RegExp('(branch_name=)(.+?)(?=&issue)'),
- createMrPath: new RegExp('(branch_name=)(.+?)(?=&ref)'),
+ createMrPath: new RegExp('(source_branch%5D=)(.+?)(?=&)'),
},
ref: {
createBranchPath: new RegExp('(ref=)(.+?)$'),
- createMrPath: new RegExp('(ref=)(.+?)$'),
+ createMrPath: new RegExp('(target_branch%5D=)(.+?)$'),
},
};
@@ -167,23 +167,18 @@ export default class CreateMergeRequestDropdown {
}
createMergeRequest() {
- this.isCreatingMergeRequest = true;
-
- return axios
- .post(this.createMrPath, {
- target_project_id: canCreateConfidentialMergeRequest()
- ? confidentialMergeRequestState.selectedProject.id
- : null,
- })
- .then(({ data }) => {
- this.mergeRequestCreated = true;
- window.location.href = data.url;
- })
- .catch(() =>
- createFlash({
- message: __('Failed to create merge request. Please try again.'),
- }),
- );
+ return new Promise(() => {
+ this.isCreatingMergeRequest = true;
+
+ return this.createBranch().then(() => {
+ window.location.href = canCreateConfidentialMergeRequest()
+ ? this.createMrPath.replace(
+ this.projectPath,
+ confidentialMergeRequestState.selectedProject.pathWithNamespace,
+ )
+ : this.createMrPath;
+ });
+ });
}
disable() {
@@ -562,5 +557,7 @@ export default class CreateMergeRequestDropdown {
this.regexps[target].createMrPath,
pathReplacement,
);
+
+ this.wrapperEl.dataset.createMrPath = this.createMrPath;
}
}
diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue
index 8b15e801f02..3866a7b3305 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -10,16 +10,30 @@ import {
} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import { orderBy } from 'lodash';
+import IssueCardTimeInfo from 'ee_else_ce/issues/list/components/issue_card_time_info.vue';
import getIssuesQuery from 'ee_else_ce/issues/list/queries/get_issues.query.graphql';
import getIssuesCountsQuery from 'ee_else_ce/issues/list/queries/get_issues_counts.query.graphql';
-import IssueCardTimeInfo from 'ee_else_ce/issues/list/components/issue_card_time_info.vue';
import createFlash, { FLASH_TYPES } from '~/flash';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { ITEM_TYPE } from '~/groups/constants';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
+import axios from '~/lib/utils/axios_utils';
+import { scrollUp } from '~/lib/utils/scroll_utils';
+import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
+import {
+ DEFAULT_NONE_ANY,
+ OPERATOR_IS_ONLY,
+ TOKEN_TITLE_ASSIGNEE,
+ TOKEN_TITLE_AUTHOR,
+ TOKEN_TITLE_CONFIDENTIAL,
+ TOKEN_TITLE_LABEL,
+ TOKEN_TITLE_MILESTONE,
+ TOKEN_TITLE_MY_REACTION,
+ TOKEN_TITLE_RELEASE,
+ TOKEN_TITLE_TYPE,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
import {
@@ -27,8 +41,6 @@ import {
i18n,
MAX_LIST_SIZE,
PAGE_SIZE,
- PARAM_DUE_DATE,
- PARAM_SORT,
PARAM_STATE,
RELATIVE_POSITION_ASC,
TOKEN_TYPE_ASSIGNEE,
@@ -41,37 +53,23 @@ import {
TOKEN_TYPE_TYPE,
UPDATED_DESC,
urlSortParams,
-} from '~/issues/list/constants';
+} from '../constants';
+import eventHub from '../eventhub';
+import reorderIssuesMutation from '../queries/reorder_issues.mutation.graphql';
+import searchLabelsQuery from '../queries/search_labels.query.graphql';
+import searchMilestonesQuery from '../queries/search_milestones.query.graphql';
+import searchUsersQuery from '../queries/search_users.query.graphql';
+import setSortPreferenceMutation from '../queries/set_sort_preference.mutation.graphql';
import {
convertToApiParams,
convertToSearchQuery,
convertToUrlParams,
- getDueDateValue,
getFilterTokens,
getInitialPageParams,
getSortKey,
getSortOptions,
-} from '~/issues/list/utils';
-import axios from '~/lib/utils/axios_utils';
-import { scrollUp } from '~/lib/utils/scroll_utils';
-import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
-import {
- DEFAULT_NONE_ANY,
- OPERATOR_IS_ONLY,
- TOKEN_TITLE_ASSIGNEE,
- TOKEN_TITLE_AUTHOR,
- TOKEN_TITLE_CONFIDENTIAL,
- TOKEN_TITLE_LABEL,
- TOKEN_TITLE_MILESTONE,
- TOKEN_TITLE_MY_REACTION,
- TOKEN_TITLE_RELEASE,
- TOKEN_TITLE_TYPE,
-} from '~/vue_shared/components/filtered_search_bar/constants';
-import eventHub from '../eventhub';
-import reorderIssuesMutation from '../queries/reorder_issues.mutation.graphql';
-import searchLabelsQuery from '../queries/search_labels.query.graphql';
-import searchMilestonesQuery from '../queries/search_milestones.query.graphql';
-import searchUsersQuery from '../queries/search_users.query.graphql';
+ isSortKey,
+} from '../utils';
import NewIssueDropdown from './new_issue_dropdown.vue';
const AuthorToken = () =>
@@ -103,74 +101,31 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- inject: {
- autocompleteAwardEmojisPath: {
- default: '',
- },
- calendarPath: {
- default: '',
- },
- canBulkUpdate: {
- default: false,
- },
- emptyStateSvgPath: {
- default: '',
- },
- exportCsvPath: {
- default: '',
- },
- fullPath: {
- default: '',
- },
- hasAnyIssues: {
- default: false,
- },
- hasAnyProjects: {
- default: false,
- },
- hasBlockedIssuesFeature: {
- default: false,
- },
- hasIssueWeightsFeature: {
- default: false,
- },
- hasMultipleIssueAssigneesFeature: {
- default: false,
- },
- initialEmail: {
- default: '',
- },
- isAnonymousSearchDisabled: {
- default: false,
- },
- isIssueRepositioningDisabled: {
- default: false,
- },
- isProject: {
- default: false,
- },
- isSignedIn: {
- default: false,
- },
- jiraIntegrationPath: {
- default: '',
- },
- newIssuePath: {
- default: '',
- },
- releasesPath: {
- default: '',
- },
- rssPath: {
- default: '',
- },
- showNewIssueLink: {
- default: false,
- },
- signInPath: {
- default: '',
- },
- },
+ inject: [
+ 'autocompleteAwardEmojisPath',
+ 'calendarPath',
+ 'canBulkUpdate',
+ 'emptyStateSvgPath',
+ 'exportCsvPath',
+ 'fullPath',
+ 'hasAnyIssues',
+ 'hasAnyProjects',
+ 'hasBlockedIssuesFeature',
+ 'hasIssueWeightsFeature',
+ 'hasMultipleIssueAssigneesFeature',
+ 'initialEmail',
+ 'initialSort',
+ 'isAnonymousSearchDisabled',
+ 'isIssueRepositioningDisabled',
+ 'isProject',
+ 'isSignedIn',
+ 'jiraIntegrationPath',
+ 'newIssuePath',
+ 'releasesPath',
+ 'rssPath',
+ 'showNewIssueLink',
+ 'signInPath',
+ ],
props: {
eeSearchTokens: {
type: Array,
@@ -181,7 +136,13 @@ export default {
data() {
const state = getParameterByName(PARAM_STATE);
const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
- let sortKey = getSortKey(getParameterByName(PARAM_SORT)) || defaultSortKey;
+ const dashboardSortKey = getSortKey(this.initialSort);
+ const graphQLSortKey =
+ isSortKey(this.initialSort?.toUpperCase()) && this.initialSort.toUpperCase();
+
+ // The initial sort is an old enum value when it is saved on the dashboard issues page.
+ // The initial sort is a GraphQL enum value when it is saved on the Vue issues list page.
+ let sortKey = dashboardSortKey || graphQLSortKey || defaultSortKey;
if (this.isIssueRepositioningDisabled && sortKey === RELATIVE_POSITION_ASC) {
this.showIssueRepositioningMessage();
@@ -198,7 +159,6 @@ export default {
}
return {
- dueDateFilter: getDueDateValue(getParameterByName(PARAM_DUE_DATE)),
exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
filterTokens: isSearchDisabled ? [] : getFilterTokens(window.location.search),
issues: [],
@@ -221,6 +181,9 @@ export default {
return data[this.namespace]?.issues.nodes ?? [];
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.pageInfo = data[this.namespace]?.issues.pageInfo ?? {};
this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery();
},
@@ -341,6 +304,7 @@ export default {
token: MilestoneToken,
fetchMilestones: this.fetchMilestones,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-milestone`,
+ shouldSkipSort: true,
},
{
type: TOKEN_TYPE_LABEL,
@@ -406,7 +370,7 @@ export default {
tokens.sort((a, b) => a.title.localeCompare(b.title));
- return orderBy(tokens, ['title']);
+ return tokens;
},
showPaginationControls() {
return this.issues.length > 0 && (this.pageInfo.hasNextPage || this.pageInfo.hasPreviousPage);
@@ -427,7 +391,6 @@ export default {
},
urlParams() {
return {
- due_date: this.dueDateFilter,
search: this.searchQuery,
sort: urlSortParams[this.sortKey],
state: this.state,
@@ -584,7 +547,6 @@ export default {
.put(joinPaths(issueToMove.webPath, 'reorder'), {
move_before_id: isMovingToBeginning ? null : getIdFromGraphQLId(moveBeforeId),
move_after_id: isMovingToEnd ? null : getIdFromGraphQLId(moveAfterId),
- group_full_path: this.isProject ? undefined : this.fullPath,
})
.then(() => {
const serializedVariables = JSON.stringify(this.queryVariables);
@@ -608,6 +570,25 @@ export default {
this.pageParams = getInitialPageParams(sortKey);
}
this.sortKey = sortKey;
+
+ if (this.isSignedIn) {
+ this.saveSortPreference(sortKey);
+ }
+ },
+ saveSortPreference(sortKey) {
+ this.$apollo
+ .mutate({
+ mutation: setSortPreferenceMutation,
+ variables: { input: { issuesSort: sortKey } },
+ })
+ .then(({ data }) => {
+ if (data.userPreferencesUpdate.errors.length) {
+ throw new Error(data.userPreferencesUpdate.errors);
+ }
+ })
+ .catch((error) => {
+ Sentry.captureException(error);
+ });
},
showAnonymousSearchingMessage() {
createFlash({
@@ -644,6 +625,7 @@ export default {
:tabs="$options.IssuableListTabs"
:current-tab="state"
:tab-counts="tabCounts"
+ :truncate-counts="!isProject"
:issuables-loading="$apollo.queries.issues.loading"
:is-manual-ordering="isManualOrdering"
:show-bulk-edit-sidebar="showBulkEditSidebar"
diff --git a/app/assets/javascripts/issues/list/components/new_issue_dropdown.vue b/app/assets/javascripts/issues/list/components/new_issue_dropdown.vue
index 71f84050ba8..666e80dfd4b 100644
--- a/app/assets/javascripts/issues/list/components/new_issue_dropdown.vue
+++ b/app/assets/javascripts/issues/list/components/new_issue_dropdown.vue
@@ -7,10 +7,10 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import createFlash from '~/flash';
-import searchProjectsQuery from '~/issues/list/queries/search_projects.query.graphql';
import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
+import searchProjectsQuery from '../queries/search_projects.query.graphql';
export default {
i18n: {
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index 4a380848b4f..284167a933f 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -55,8 +55,6 @@ export const i18n = {
export const MAX_LIST_SIZE = 10;
export const PAGE_SIZE = 20;
export const PAGE_SIZE_MANUAL = 100;
-export const PARAM_DUE_DATE = 'due_date';
-export const PARAM_SORT = 'sort';
export const PARAM_STATE = 'state';
export const RELATIVE_POSITION = 'relative_position';
@@ -68,21 +66,6 @@ export const largePageSizeParams = {
firstPageSize: PAGE_SIZE_MANUAL,
};
-export const DUE_DATE_NONE = '0';
-export const DUE_DATE_ANY = '';
-export const DUE_DATE_OVERDUE = 'overdue';
-export const DUE_DATE_WEEK = 'week';
-export const DUE_DATE_MONTH = 'month';
-export const DUE_DATE_NEXT_MONTH_AND_PREVIOUS_TWO_WEEKS = 'next_month_and_previous_two_weeks';
-export const DUE_DATE_VALUES = [
- DUE_DATE_NONE,
- DUE_DATE_ANY,
- DUE_DATE_OVERDUE,
- DUE_DATE_WEEK,
- DUE_DATE_MONTH,
- DUE_DATE_NEXT_MONTH_AND_PREVIOUS_TWO_WEEKS,
-];
-
export const BLOCKING_ISSUES_ASC = 'BLOCKING_ISSUES_ASC';
export const BLOCKING_ISSUES_DESC = 'BLOCKING_ISSUES_DESC';
export const CREATED_ASC = 'CREATED_ASC';
diff --git a/app/assets/javascripts/issues/list/index.js b/app/assets/javascripts/issues/list/index.js
index 01cc82ed8fd..3b2d37eab74 100644
--- a/app/assets/javascripts/issues/list/index.js
+++ b/app/assets/javascripts/issues/list/index.js
@@ -30,6 +30,7 @@ export function mountJiraIssuesListApp() {
return new Vue({
el,
+ name: 'JiraIssuesImportStatusRoot',
apolloProvider,
render(createComponent) {
return createComponent(JiraIssuesImportStatusRoot, {
@@ -99,6 +100,7 @@ export function mountIssuesListApp() {
hasMultipleIssueAssigneesFeature,
importCsvIssuesPath,
initialEmail,
+ initialSort,
isAnonymousSearchDisabled,
isIssueRepositioningDisabled,
isProject,
@@ -118,6 +120,7 @@ export function mountIssuesListApp() {
return new Vue({
el,
+ name: 'IssuesListRoot',
apolloProvider,
provide: {
autocompleteAwardEmojisPath,
@@ -133,6 +136,7 @@ export function mountIssuesListApp() {
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
hasIterationsFeature: parseBoolean(hasIterationsFeature),
hasMultipleIssueAssigneesFeature: parseBoolean(hasMultipleIssueAssigneesFeature),
+ initialSort,
isAnonymousSearchDisabled: parseBoolean(isAnonymousSearchDisabled),
isIssueRepositioningDisabled: parseBoolean(isIssueRepositioningDisabled),
isProject: parseBoolean(isProject),
diff --git a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
index 07dae3fd756..430d494deab 100644
--- a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
+++ b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
@@ -1,4 +1,5 @@
fragment IssueFragment on Issue {
+ __typename
id
iid
closedAt
@@ -18,6 +19,7 @@ fragment IssueFragment on Issue {
webUrl
assignees {
nodes {
+ __typename
id
avatarUrl
name
@@ -26,6 +28,7 @@ fragment IssueFragment on Issue {
}
}
author {
+ __typename
id
avatarUrl
name
diff --git a/app/assets/javascripts/issues/list/queries/search_milestones.query.graphql b/app/assets/javascripts/issues/list/queries/search_milestones.query.graphql
index e7eb08104a6..040240cde99 100644
--- a/app/assets/javascripts/issues/list/queries/search_milestones.query.graphql
+++ b/app/assets/javascripts/issues/list/queries/search_milestones.query.graphql
@@ -3,7 +3,13 @@
query searchMilestones($fullPath: ID!, $search: String, $isProject: Boolean = false) {
group(fullPath: $fullPath) @skip(if: $isProject) {
id
- milestones(searchTitle: $search, includeAncestors: true, includeDescendants: true) {
+ milestones(
+ searchTitle: $search
+ includeAncestors: true
+ includeDescendants: true
+ sort: EXPIRED_LAST_DUE_DATE_ASC
+ state: active
+ ) {
nodes {
...Milestone
}
@@ -11,7 +17,12 @@ query searchMilestones($fullPath: ID!, $search: String, $isProject: Boolean = fa
}
project(fullPath: $fullPath) @include(if: $isProject) {
id
- milestones(searchTitle: $search, includeAncestors: true) {
+ milestones(
+ searchTitle: $search
+ includeAncestors: true
+ sort: EXPIRED_LAST_DUE_DATE_ASC
+ state: active
+ ) {
nodes {
...Milestone
}
diff --git a/app/assets/javascripts/issues/list/queries/set_sort_preference.mutation.graphql b/app/assets/javascripts/issues/list/queries/set_sort_preference.mutation.graphql
new file mode 100644
index 00000000000..ed7b5193c9b
--- /dev/null
+++ b/app/assets/javascripts/issues/list/queries/set_sort_preference.mutation.graphql
@@ -0,0 +1,5 @@
+mutation setSortPreference($input: UserPreferencesUpdateInput!) {
+ userPreferencesUpdate(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/issues/list/utils.js b/app/assets/javascripts/issues/list/utils.js
index 2919bbbfef8..6322968b3f0 100644
--- a/app/assets/javascripts/issues/list/utils.js
+++ b/app/assets/javascripts/issues/list/utils.js
@@ -1,3 +1,9 @@
+import { isPositiveInteger } from '~/lib/utils/number_utils';
+import { __ } from '~/locale';
+import {
+ FILTERED_SEARCH_TERM,
+ OPERATOR_IS_NOT,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import {
API_PARAM,
BLOCKING_ISSUES_ASC,
@@ -7,7 +13,6 @@ import {
defaultPageSizeParams,
DUE_DATE_ASC,
DUE_DATE_DESC,
- DUE_DATE_VALUES,
filters,
LABEL_PRIORITY_ASC,
LABEL_PRIORITY_DESC,
@@ -36,13 +41,7 @@ import {
urlSortParams,
WEIGHT_ASC,
WEIGHT_DESC,
-} from '~/issues/list/constants';
-import { isPositiveInteger } from '~/lib/utils/number_utils';
-import { __ } from '~/locale';
-import {
- FILTERED_SEARCH_TERM,
- OPERATOR_IS_NOT,
-} from '~/vue_shared/components/filtered_search_bar/constants';
+} from './constants';
export const getInitialPageParams = (sortKey) =>
sortKey === RELATIVE_POSITION_ASC ? largePageSizeParams : defaultPageSizeParams;
@@ -50,7 +49,7 @@ export const getInitialPageParams = (sortKey) =>
export const getSortKey = (sort) =>
Object.keys(urlSortParams).find((key) => urlSortParams[key] === sort);
-export const getDueDateValue = (value) => (DUE_DATE_VALUES.includes(value) ? value : undefined);
+export const isSortKey = (sort) => Object.keys(urlSortParams).includes(sort);
export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) => {
const sortOptions = [
diff --git a/app/assets/javascripts/issues/manual_ordering.js b/app/assets/javascripts/issues/manual_ordering.js
index c78505d0610..8fb891f62f7 100644
--- a/app/assets/javascripts/issues/manual_ordering.js
+++ b/app/assets/javascripts/issues/manual_ordering.js
@@ -7,12 +7,11 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
-const updateIssue = (url, issueList, { move_before_id, move_after_id }) =>
+const updateIssue = (url, { move_before_id, move_after_id }) =>
axios
.put(`${url}/reorder`, {
move_before_id,
move_after_id,
- group_full_path: issueList.dataset.groupFullPath,
})
.catch(() => {
createFlash({
@@ -52,7 +51,7 @@ const initManualOrdering = () => {
const beforeId = prev && parseInt(prev.dataset.id, 10);
const afterId = next && parseInt(next.dataset.id, 10);
- updateIssue(url, issueList, { move_after_id: afterId, move_before_id: beforeId });
+ updateIssue(url, { move_after_id: afterId, move_before_id: beforeId });
},
}),
);
diff --git a/app/assets/javascripts/issues/new/index.js b/app/assets/javascripts/issues/new/index.js
index f96cacf2595..91599502996 100644
--- a/app/assets/javascripts/issues/new/index.js
+++ b/app/assets/javascripts/issues/new/index.js
@@ -20,6 +20,7 @@ export function initTitleSuggestions() {
return new Vue({
el,
+ name: 'TitleSuggestionsRoot',
apolloProvider,
data() {
return {
@@ -51,6 +52,7 @@ export function initTypePopover() {
return new Vue({
el,
+ name: 'TypePopoverRoot',
render: (createElement) => createElement(TypePopover),
});
}
diff --git a/app/assets/javascripts/issues/related_merge_requests/index.js b/app/assets/javascripts/issues/related_merge_requests/index.js
index 5045f7e1a2a..196084093c8 100644
--- a/app/assets/javascripts/issues/related_merge_requests/index.js
+++ b/app/assets/javascripts/issues/related_merge_requests/index.js
@@ -13,6 +13,7 @@ export function initRelatedMergeRequests() {
return new Vue({
el,
+ name: 'RelatedMergeRequestsRoot',
store: createStore(),
render: (createElement) =>
createElement(RelatedMergeRequests, {
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
index 7be4c13f544..eeccf886b65 100644
--- a/app/assets/javascripts/issues/show/components/description.vue
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -1,18 +1,31 @@
<script>
-import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import {
+ GlSafeHtmlDirective as SafeHtml,
+ GlModal,
+ GlModalDirective,
+ GlPopover,
+ GlButton,
+} from '@gitlab/ui';
import $ from 'jquery';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
import TaskList from '~/task_list';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
import animateMixin from '../mixins/animate';
export default {
directives: {
SafeHtml,
+ GlModal: GlModalDirective,
},
-
- mixins: [animateMixin],
-
+ components: {
+ GlModal,
+ GlPopover,
+ CreateWorkItem,
+ GlButton,
+ },
+ mixins: [animateMixin, glFeatureFlagMixin()],
props: {
canUpdate: {
type: Boolean,
@@ -53,8 +66,15 @@ export default {
preAnimation: false,
pulseAnimation: false,
initialUpdate: true,
+ taskButtons: [],
+ activeTask: {},
};
},
+ computed: {
+ workItemsEnabled() {
+ return this.glFeatures.workItems;
+ },
+ },
watch: {
descriptionHtml(newDescription, oldDescription) {
if (!this.initialUpdate && newDescription !== oldDescription) {
@@ -74,6 +94,10 @@ export default {
mounted() {
this.renderGFM();
this.updateTaskStatusText();
+
+ if (this.workItemsEnabled) {
+ this.renderTaskActions();
+ }
},
methods: {
renderGFM() {
@@ -132,6 +156,63 @@ export default {
$tasksShort.text('');
}
},
+ renderTaskActions() {
+ if (!this.$el?.querySelectorAll) {
+ return;
+ }
+
+ const taskListFields = this.$el.querySelectorAll('.task-list-item');
+
+ taskListFields.forEach((item, index) => {
+ const button = document.createElement('button');
+ button.classList.add(
+ 'btn',
+ 'btn-default',
+ 'btn-md',
+ 'gl-button',
+ 'btn-default-tertiary',
+ 'gl-left-0',
+ 'gl-p-0!',
+ 'gl-top-2',
+ 'gl-absolute',
+ 'js-add-task',
+ );
+ button.id = `js-task-button-${index}`;
+ this.taskButtons.push(button.id);
+ button.innerHTML = `
+ <svg data-testid="ellipsis_v-icon" role="img" aria-hidden="true" class="dropdown-icon gl-icon s14">
+ <use href="${gon.sprite_icons}#ellipsis_v"></use>
+ </svg>
+ `;
+ item.prepend(button);
+ });
+ },
+ openCreateTaskModal(id) {
+ this.activeTask = { id, title: this.$el.querySelector(`#${id}`).parentElement.innerText };
+ this.$refs.modal.show();
+ },
+ closeCreateTaskModal() {
+ this.$refs.modal.hide();
+ },
+ handleCreateTask(title) {
+ const listItem = this.$el.querySelector(`#${this.activeTask.id}`).parentElement;
+ const taskBadge = document.createElement('span');
+ taskBadge.innerHTML = `
+ <svg data-testid="issue-open-m-icon" role="img" aria-hidden="true" class="gl-icon gl-fill-green-500 s12">
+ <use href="${gon.sprite_icons}#issue-open-m"></use>
+ </svg>
+ <span class="badge badge-info badge-pill gl-badge sm gl-mr-1">
+ ${__('Task')}
+ </span>
+ <a href="#">${title}</a>
+ `;
+ listItem.insertBefore(taskBadge, listItem.lastChild);
+ listItem.removeChild(listItem.lastChild);
+ this.closeCreateTaskModal();
+ },
+ focusButton() {
+ this.$refs.convertButton[0].$el.focus();
+ },
},
safeHtmlConfig: { ADD_TAGS: ['gl-emoji', 'copy-code'] },
};
@@ -142,12 +223,14 @@ export default {
v-if="descriptionHtml"
:class="{
'js-task-list-container': canUpdate,
+ 'work-items-enabled': workItemsEnabled,
}"
class="description"
>
<div
ref="gfm-content"
v-safe-html:[$options.safeHtmlConfig]="descriptionHtml"
+ data-testid="gfm-content"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
@@ -157,13 +240,46 @@ export default {
<!-- eslint-disable vue/no-mutating-props -->
<textarea
v-if="descriptionText"
- ref="textarea"
v-model="descriptionText"
:data-update-url="updateUrl"
class="hidden js-task-list-field"
dir="auto"
+ data-testid="textarea"
>
</textarea>
<!-- eslint-enable vue/no-mutating-props -->
+ <gl-modal
+ ref="modal"
+ modal-id="create-task-modal"
+ :title="s__('WorkItem|New Task')"
+ hide-footer
+ body-class="gl-p-0!"
+ >
+ <create-work-item
+ :is-modal="true"
+ :initial-title="activeTask.title"
+ @closeModal="closeCreateTaskModal"
+ @onCreate="handleCreateTask"
+ />
+ </gl-modal>
+ <template v-if="workItemsEnabled">
+ <gl-popover
+ v-for="item in taskButtons"
+ :key="item"
+ :target="item"
+ placement="top"
+ triggers="focus"
+ @shown="focusButton"
+ >
+ <gl-button
+ ref="convertButton"
+ variant="link"
+ data-testid="convert-to-task"
+ class="gl-text-gray-900! gl-text-decoration-none! gl-outline-0!"
+ @click="openCreateTaskModal(item)"
+ >{{ s__('WorkItem|Convert to work item') }}</gl-button
+ >
+ </gl-popover>
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/issues/show/components/fields/description.vue b/app/assets/javascripts/issues/show/components/fields/description.vue
index 5476a1ef897..d5ac7b28afc 100644
--- a/app/assets/javascripts/issues/show/components/fields/description.vue
+++ b/app/assets/javascripts/issues/show/components/fields/description.vue
@@ -1,13 +1,12 @@
<script>
import markdownField from '~/vue_shared/components/markdown/field.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import updateMixin from '../../mixins/update';
export default {
components: {
markdownField,
},
- mixins: [glFeatureFlagsMixin(), updateMixin],
+ mixins: [updateMixin],
props: {
formState: {
type: Object,
@@ -56,7 +55,7 @@ export default {
v-model="formState.description"
class="note-textarea js-gfm-input js-autosize markdown-area qa-description-textarea"
dir="auto"
- :data-supports-quick-actions="!glFeatures.tributeAutocomplete"
+ data-supports-quick-actions="true"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@keydown.meta.enter="updateIssuable"
diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js
index 7f5a0e32f72..f5c71f9691f 100644
--- a/app/assets/javascripts/issues/show/index.js
+++ b/app/assets/javascripts/issues/show/index.js
@@ -44,6 +44,7 @@ export function initIncidentApp(issueData = {}) {
return new Vue({
el,
+ name: 'DescriptionRoot',
apolloProvider,
provide: {
issueType: INCIDENT_TYPE,
@@ -74,6 +75,8 @@ export function initIssueApp(issueData, store) {
return undefined;
}
+ const { fullPath } = el.dataset;
+
if (gon?.features?.fixCommentScroll) {
scrollToTargetOnResize();
}
@@ -84,10 +87,12 @@ export function initIssueApp(issueData, store) {
return new Vue({
el,
+ name: 'DescriptionRoot',
apolloProvider,
store,
provide: {
canCreateIncident,
+ fullPath,
},
computed: {
...mapGetters(['getNoteableData']),
@@ -120,6 +125,7 @@ export function initHeaderActions(store, type = '') {
return new Vue({
el,
+ name: 'HeaderActionsRoot',
apolloProvider,
store,
provide: {
@@ -154,6 +160,7 @@ export function initSentryErrorStackTrace() {
return new Vue({
el,
+ name: 'SentryErrorStackTraceRoot',
store: errorTrackingStore,
render: (createElement) =>
createElement(SentryErrorStackTrace, { props: { issueStackTracePath } }),
diff --git a/app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue b/app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue
index 66fcb8e10eb..46c27c33f56 100644
--- a/app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue
+++ b/app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue
@@ -1,5 +1,6 @@
<script>
-import { GlFormGroup, GlButton, GlFormInput, GlForm, GlAlert } from '@gitlab/ui';
+import { GlFormGroup, GlButton, GlFormInput, GlForm, GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
import {
CREATE_BRANCH_ERROR_GENERIC,
CREATE_BRANCH_ERROR_WITH_CONTEXT,
@@ -7,6 +8,7 @@ import {
I18N_NEW_BRANCH_LABEL_BRANCH,
I18N_NEW_BRANCH_LABEL_SOURCE,
I18N_NEW_BRANCH_SUBMIT_BUTTON_TEXT,
+ I18N_NEW_BRANCH_PERMISSION_ALERT,
} from '../constants';
import createBranchMutation from '../graphql/mutations/create_branch.mutation.graphql';
import ProjectDropdown from './project_dropdown.vue';
@@ -17,6 +19,8 @@ const DEFAULT_ALERT_PARAMS = {
title: '',
message: '',
variant: DEFAULT_ALERT_VARIANT,
+ link: undefined,
+ dismissible: true,
};
export default {
@@ -27,10 +31,16 @@ export default {
GlFormInput,
GlForm,
GlAlert,
+ GlSprintf,
+ GlLink,
ProjectDropdown,
SourceBranchDropdown,
},
- inject: ['initialBranchName'],
+ inject: {
+ initialBranchName: {
+ default: '',
+ },
+ },
data() {
return {
selectedProject: null,
@@ -40,6 +50,7 @@ export default {
alertParams: {
...DEFAULT_ALERT_PARAMS,
},
+ hasPermission: false,
};
},
computed: {
@@ -49,19 +60,38 @@ export default {
showAlert() {
return Boolean(this.alertParams?.message);
},
+ isBranchNameValid() {
+ return (this.branchName ?? '').trim().length > 0;
+ },
disableSubmitButton() {
- return !(this.selectedProject && this.selectedSourceBranchName && this.branchName);
+ return !(this.selectedProject && this.selectedSourceBranchName && this.isBranchNameValid);
},
},
methods: {
- displayAlert({ title, message, variant = DEFAULT_ALERT_VARIANT } = {}) {
+ displayAlert({
+ title,
+ message,
+ variant = DEFAULT_ALERT_VARIANT,
+ link,
+ dismissible = true,
+ } = {}) {
this.alertParams = {
title,
message,
variant,
+ link,
+ dismissible,
};
},
- onAlertDismiss() {
+ setPermissionAlert() {
+ this.displayAlert({
+ message: I18N_NEW_BRANCH_PERMISSION_ALERT,
+ variant: 'warning',
+ link: helpPagePath('user/permissions', { anchor: 'project-members-permissions' }),
+ dismissible: false,
+ });
+ },
+ dismissAlert() {
this.alertParams = {
...DEFAULT_ALERT_PARAMS,
};
@@ -69,6 +99,14 @@ export default {
onProjectSelect(project) {
this.selectedProject = project;
this.selectedSourceBranchName = null; // reset branch selection
+ this.hasPermission = this.selectedProject.userPermissions.pushCode;
+
+ if (!this.hasPermission) {
+ this.setPermissionAlert();
+ } else {
+ // clear alert if the user has permissions for the newly-selected project.
+ this.dismissAlert();
+ }
},
onSourceBranchSelect(branchName) {
this.selectedSourceBranchName = branchName;
@@ -127,10 +165,18 @@ export default {
class="gl-mb-5"
:variant="alertParams.variant"
:title="alertParams.title"
- @dismiss="onAlertDismiss"
+ :dismissible="alertParams.dismissible"
+ @dismiss="dismissAlert"
>
- {{ alertParams.message }}
+ <gl-sprintf :message="alertParams.message">
+ <template #link="{ content }">
+ <gl-link :href="alertParams.link" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
</gl-alert>
+
<gl-form-group :label="$options.i18n.I18N_NEW_BRANCH_LABEL_DROPDOWN" label-for="project-select">
<project-dropdown
id="project-select"
@@ -140,25 +186,28 @@ export default {
/>
</gl-form-group>
- <gl-form-group
- :label="$options.i18n.I18N_NEW_BRANCH_LABEL_BRANCH"
- label-for="branch-name-input"
- >
- <gl-form-input id="branch-name-input" v-model="branchName" type="text" required />
- </gl-form-group>
+ <template v-if="selectedProject && hasPermission">
+ <gl-form-group
+ :label="$options.i18n.I18N_NEW_BRANCH_LABEL_SOURCE"
+ label-for="source-branch-select"
+ >
+ <source-branch-dropdown
+ id="source-branch-select"
+ :selected-project="selectedProject"
+ :selected-branch-name="selectedSourceBranchName"
+ @change="onSourceBranchSelect"
+ @error="onError"
+ />
+ </gl-form-group>
- <gl-form-group
- :label="$options.i18n.I18N_NEW_BRANCH_LABEL_SOURCE"
- label-for="source-branch-select"
- >
- <source-branch-dropdown
- id="source-branch-select"
- :selected-project="selectedProject"
- :selected-branch-name="selectedSourceBranchName"
- @change="onSourceBranchSelect"
- @error="onError"
- />
- </gl-form-group>
+ <gl-form-group
+ :label="$options.i18n.I18N_NEW_BRANCH_LABEL_BRANCH"
+ label-for="branch-name-input"
+ class="gl-max-w-62"
+ >
+ <gl-form-input id="branch-name-input" v-model="branchName" type="text" required />
+ </gl-form-group>
+ </template>
<div class="form-actions">
<gl-button
diff --git a/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue b/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue
index 751f3e9639d..88005cccd89 100644
--- a/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue
+++ b/app/assets/javascripts/jira_connect/branches/components/project_dropdown.vue
@@ -1,5 +1,11 @@
<script>
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ GlDropdownItem,
+ GlAvatarLabeled,
+} from '@gitlab/ui';
import { __ } from '~/locale';
import { PROJECTS_PER_PAGE } from '../constants';
import getProjectsQuery from '../graphql/queries/get_projects.query.graphql';
@@ -14,6 +20,7 @@ export default {
GlDropdownItem,
GlSearchBoxByType,
GlLoadingIcon,
+ GlAvatarLabeled,
},
props: {
selectedProject: {
@@ -56,7 +63,7 @@ export default {
return Boolean(this.$apollo.queries.projects.loading);
},
projectDropdownText() {
- return this.selectedProject?.nameWithNamespace || __('Select a project');
+ return this.selectedProject?.nameWithNamespace || this.$options.i18n.selectProjectText;
},
},
methods: {
@@ -70,11 +77,19 @@ export default {
return project.id === this.selectedProject?.id;
},
},
+ i18n: {
+ selectProjectText: __('Select a project'),
+ },
};
</script>
<template>
- <gl-dropdown :text="projectDropdownText" :loading="initialProjectsLoading">
+ <gl-dropdown
+ :text="projectDropdownText"
+ :loading="initialProjectsLoading"
+ menu-class="gl-w-auto!"
+ :header-text="$options.i18n.selectProjectText"
+ >
<template #header>
<gl-search-box-by-type v-model.trim="projectSearchQuery" :debounce="250" />
</template>
@@ -85,10 +100,20 @@ export default {
v-for="project in projects"
:key="project.id"
is-check-item
+ is-check-centered
:is-checked="isProjectSelected(project)"
+ :data-testid="`test-project-${project.id}`"
@click="onProjectSelect(project)"
>
- {{ project.nameWithNamespace }}
+ <gl-avatar-labeled
+ class="gl-text-truncate"
+ shape="rect"
+ :size="32"
+ :src="project.avatarUrl"
+ :label="project.name"
+ :entity-name="project.name"
+ :sub-label="project.nameWithNamespace"
+ />
</gl-dropdown-item>
</template>
</gl-dropdown>
diff --git a/app/assets/javascripts/jira_connect/branches/constants.js b/app/assets/javascripts/jira_connect/branches/constants.js
index ab9d3b2c110..43be774ce7c 100644
--- a/app/assets/javascripts/jira_connect/branches/constants.js
+++ b/app/assets/javascripts/jira_connect/branches/constants.js
@@ -23,3 +23,6 @@ export const I18N_NEW_BRANCH_SUCCESS_TITLE = s__(
export const I18N_NEW_BRANCH_SUCCESS_MESSAGE = s__(
'JiraConnect|You can now close this window and return to Jira.',
);
+export const I18N_NEW_BRANCH_PERMISSION_ALERT = s__(
+ "JiraConnect|You don't have permission to create branches for this project. Select a different project or contact the project owner for access. %{linkStart}Learn more.%{linkEnd}",
+);
diff --git a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
index 32fbc1113bc..03e8e3e986b 100644
--- a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
+++ b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
@@ -26,6 +26,9 @@ query jiraGetProjects(
repository {
empty
}
+ userPermissions {
+ pushCode
+ }
}
pageInfo {
...PageInfo
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue
index 5a49d7c1a90..7f035dddafe 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue
@@ -30,7 +30,8 @@ export default {
page: 1,
totalItems: 0,
errorMessage: null,
- searchTerm: '',
+ userSearchTerm: '',
+ searchValue: '',
};
},
computed: {
@@ -45,16 +46,11 @@ export default {
},
methods: {
loadGroups() {
- // fetchGroups returns no results for search terms 0 < {length} < 3.
- // The desired UX is to return the unfiltered results for searches {length} < 3.
- // Here, we set the search to an empty string if {length} < 3
- const search = this.searchTerm?.length < MINIMUM_SEARCH_TERM_LENGTH ? '' : this.searchTerm;
-
this.isLoadingMore = true;
return fetchGroups(this.groupsPath, {
page: this.page,
perPage: this.$options.DEFAULT_GROUPS_PER_PAGE,
- search,
+ search: this.searchValue,
})
.then((response) => {
const { page, total } = parseIntPagination(normalizeHeaders(response.headers));
@@ -69,12 +65,24 @@ export default {
this.isLoadingMore = false;
});
},
- onGroupSearch(searchTerm) {
- // keep a copy of the search term for pagination
- this.searchTerm = searchTerm;
- // reset the current page
+ onGroupSearch(userSearchTerm = '') {
+ this.userSearchTerm = userSearchTerm;
+
+ // fetchGroups returns no results for search terms 0 < {length} < 3.
+ // The desired UX is to return the unfiltered results for searches {length} < 3.
+ // Here, we set the search to an empty string '' if {length} < 3
+ const newSearchValue =
+ this.userSearchTerm.length < MINIMUM_SEARCH_TERM_LENGTH ? '' : this.userSearchTerm;
+
+ // don't fetch new results if the search value didn't change.
+ if (newSearchValue === this.searchValue) {
+ return;
+ }
+
+ // reset the page.
this.page = 1;
- return this.loadGroups();
+ this.searchValue = newSearchValue;
+ this.loadGroups();
},
},
DEFAULT_GROUPS_PER_PAGE,
@@ -92,7 +100,7 @@ export default {
debounce="500"
:placeholder="__('Search by name')"
:is-loading="isLoadingMore"
- :value="searchTerm"
+ :value="userSearchTerm"
@input="onGroupSearch"
/>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
index 7fd4cc38f11..905e242e977 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
@@ -1,13 +1,13 @@
<script>
-import { GlAlert, GlLink, GlSprintf, GlEmptyState } from '@gitlab/ui';
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapState, mapMutations } from 'vuex';
import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
import { SET_ALERT } from '../store/mutation_types';
-import SubscriptionsList from './subscriptions_list.vue';
-import AddNamespaceButton from './add_namespace_button.vue';
-import SignInButton from './sign_in_button.vue';
+import SignInPage from '../pages/sign_in.vue';
+import SubscriptionsPage from '../pages/subscriptions.vue';
import UserLink from './user_link.vue';
+import CompatibilityAlert from './compatibility_alert.vue';
export default {
name: 'JiraConnectApp',
@@ -15,11 +15,10 @@ export default {
GlAlert,
GlLink,
GlSprintf,
- GlEmptyState,
- SubscriptionsList,
- AddNamespaceButton,
- SignInButton,
UserLink,
+ CompatibilityAlert,
+ SignInPage,
+ SubscriptionsPage,
},
inject: {
usersPath: {
@@ -58,11 +57,14 @@ export default {
<template>
<div>
+ <compatibility-alert />
+
<gl-alert
v-if="shouldShowAlert"
class="gl-mb-7"
:variant="alert.variant"
:title="alert.title"
+ data-testid="jira-connect-persisted-alert"
@dismiss="setAlert"
>
<gl-sprintf v-if="alert.linkUrl" :message="alert.message">
@@ -79,43 +81,9 @@ export default {
<user-link :user-signed-in="userSignedIn" :has-subscriptions="hasSubscriptions" />
<h2 class="gl-text-center gl-mb-7">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
- <div class="jira-connect-app-body gl-mx-auto gl-px-5 gl-mb-7">
- <template v-if="hasSubscriptions">
- <div class="gl-display-flex gl-justify-content-end">
- <sign-in-button v-if="!userSignedIn" :users-path="usersPath" />
- <add-namespace-button v-else />
- </div>
-
- <subscriptions-list />
- </template>
- <template v-else>
- <div v-if="!userSignedIn" class="gl-text-center">
- <p class="gl-mb-7">{{ s__('JiraService|Sign in to GitLab.com to get started.') }}</p>
- <sign-in-button class="gl-mb-7" :users-path="usersPath">
- {{ __('Sign in to GitLab') }}
- </sign-in-button>
- <p>
- {{
- s__(
- 'Integrations|Note: this integration only works with accounts on GitLab.com (SaaS).',
- )
- }}
- </p>
- </div>
- <gl-empty-state
- v-else
- :title="s__('Integrations|No linked namespaces')"
- :description="
- s__(
- 'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
- )
- "
- >
- <template #actions>
- <add-namespace-button />
- </template>
- </gl-empty-state>
- </template>
+ <div class="gl-layout-w-limited gl-mx-auto gl-px-5 gl-mb-7">
+ <sign-in-page v-if="!userSignedIn" :has-subscriptions="hasSubscriptions" />
+ <subscriptions-page v-else :has-subscriptions="hasSubscriptions" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue b/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue
new file mode 100644
index 00000000000..3cfbd87ac53
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+
+const COMPATIBILITY_ALERT_STATE_KEY = 'compatibility_alert_dismissed';
+
+export default {
+ name: 'CompatibilityAlert',
+ components: {
+ GlAlert,
+ GlSprintf,
+ GlLink,
+ LocalStorageSync,
+ },
+ data() {
+ return {
+ alertDismissed: false,
+ };
+ },
+ computed: {
+ shouldShowAlert() {
+ return !this.alertDismissed;
+ },
+ },
+ methods: {
+ dismissAlert() {
+ this.alertDismissed = true;
+ },
+ },
+ i18n: {
+ title: s__('Integrations|Known limitations'),
+ body: s__(
+ 'Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}.',
+ ),
+ },
+ DOCS_LINK_URL: helpPagePath('integration/jira/connect-app'),
+ COMPATIBILITY_ALERT_STATE_KEY,
+};
+</script>
+<template>
+ <local-storage-sync
+ v-model="alertDismissed"
+ :storage-key="$options.COMPATIBILITY_ALERT_STATE_KEY"
+ >
+ <gl-alert
+ v-if="shouldShowAlert"
+ class="gl-mb-7"
+ variant="info"
+ :title="$options.i18n.title"
+ @dismiss="dismissAlert"
+ >
+ <gl-sprintf :message="$options.i18n.body">
+ <template #link="{ content }">
+ <gl-link :href="$options.DOCS_LINK_URL" target="_blank" rel="noopener noreferrer">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </local-storage-sync>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
index dc0a77e99c2..627abcdd4a0 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
@@ -1,6 +1,7 @@
<script>
import { GlButton } from '@gitlab/ui';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
+import { s__ } from '~/locale';
export default {
components: {
@@ -25,12 +26,15 @@ export default {
this.signInURL = await getGitlabSignInURL(this.usersPath);
},
},
+ i18n: {
+ defaultButtonText: s__('Integrations|Sign in to GitLab'),
+ },
};
</script>
<template>
<gl-button category="primary" variant="info" :href="signInURL" target="_blank">
<slot>
- {{ s__('Integrations|Sign in to add namespaces') }}
+ {{ $options.i18n.defaultButtonText }}
</slot>
</gl-button>
</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in.vue
new file mode 100644
index 00000000000..2bce5afc72b
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in.vue
@@ -0,0 +1,40 @@
+<script>
+import { s__ } from '~/locale';
+import SubscriptionsList from '../components/subscriptions_list.vue';
+import SignInButton from '../components/sign_in_button.vue';
+
+export default {
+ name: 'SignInPage',
+ components: {
+ SubscriptionsList,
+ SignInButton,
+ },
+ inject: ['usersPath'],
+ props: {
+ hasSubscriptions: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ i18n: {
+ signinButtonTextWithSubscriptions: s__('Integrations|Sign in to add namespaces'),
+ signInText: s__('JiraService|Sign in to GitLab.com to get started.'),
+ },
+};
+</script>
+
+<template>
+ <div v-if="hasSubscriptions">
+ <div class="gl-display-flex gl-justify-content-end">
+ <sign-in-button :users-path="usersPath">
+ {{ $options.i18n.signinButtonTextWithSubscriptions }}
+ </sign-in-button>
+ </div>
+
+ <subscriptions-list />
+ </div>
+ <div v-else class="gl-text-center">
+ <p class="gl-mb-7">{{ $options.i18n.signInText }}</p>
+ <sign-in-button class="gl-mb-7" :users-path="usersPath" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/subscriptions.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/subscriptions.vue
new file mode 100644
index 00000000000..426f2999370
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/pages/subscriptions.vue
@@ -0,0 +1,43 @@
+<script>
+import { GlEmptyState } from '@gitlab/ui';
+import SubscriptionsList from '../components/subscriptions_list.vue';
+import AddNamespaceButton from '../components/add_namespace_button.vue';
+
+export default {
+ name: 'SubscriptionsPage',
+ components: {
+ GlEmptyState,
+ SubscriptionsList,
+ AddNamespaceButton,
+ },
+ props: {
+ hasSubscriptions: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="hasSubscriptions">
+ <div class="gl-display-flex gl-justify-content-end">
+ <add-namespace-button />
+ </div>
+
+ <subscriptions-list />
+ </div>
+ <gl-empty-state
+ v-else
+ :title="s__('Integrations|No linked namespaces')"
+ :description="
+ s__(
+ 'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
+ )
+ "
+ >
+ <template #actions>
+ <add-namespace-button />
+ </template>
+ </gl-empty-state>
+</template>
diff --git a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
index 7dfa963a857..753a15871ab 100644
--- a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
+++ b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
@@ -58,6 +58,14 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ retryBtnDisabled: false,
+ cancelBtnDisabled: false,
+ playManualBtnDisabled: false,
+ unscheduleBtnDisabled: false,
+ };
+ },
computed: {
hasArtifacts() {
return this.job.artifacts.nodes.find((artifact) => artifact.fileType === FILE_TYPE_ARCHIVE);
@@ -132,15 +140,23 @@ export default {
});
},
cancelJob() {
+ this.cancelBtnDisabled = true;
+
this.postJobAction(this.$options.jobCancel, cancelJobMutation);
},
retryJob() {
+ this.retryBtnDisabled = true;
+
this.postJobAction(this.$options.jobRetry, retryJobMutation);
},
playJob() {
+ this.playManualBtnDisabled = true;
+
this.postJobAction(this.$options.jobPlay, playJobMutation);
},
unscheduleJob() {
+ this.unscheduleBtnDisabled = true;
+
this.postJobAction(this.$options.jobUnschedule, unscheduleJobMutation);
},
},
@@ -155,6 +171,7 @@ export default {
data-testid="cancel-button"
icon="cancel"
:title="$options.CANCEL"
+ :disabled="cancelBtnDisabled"
@click="cancelJob()"
/>
<template v-else-if="isScheduled">
@@ -179,6 +196,7 @@ export default {
<gl-button
icon="time-out"
:title="$options.ACTIONS_UNSCHEDULE"
+ :disabled="unscheduleBtnDisabled"
data-testid="unschedule"
@click="unscheduleJob()"
/>
@@ -189,6 +207,7 @@ export default {
v-if="manualJobPlayable"
icon="play"
:title="$options.ACTIONS_PLAY"
+ :disabled="playManualBtnDisabled"
data-testid="play"
@click="playJob()"
/>
@@ -197,6 +216,7 @@ export default {
icon="repeat"
:title="$options.ACTIONS_RETRY"
:method="currentJobMethod"
+ :disabled="retryBtnDisabled"
data-testid="retry"
@click="retryJob()"
/>
diff --git a/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue b/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue
index ba5732d3d43..19594c4955d 100644
--- a/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue
+++ b/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue
@@ -39,6 +39,7 @@ export default {
<time
v-gl-tooltip
:title="tooltipTitle(finishedTime)"
+ :datetime="finishedTime"
data-placement="top"
data-container="body"
>
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 c786d35ac68..81f42c1e293 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
@@ -51,7 +51,9 @@ export default {
},
data() {
return {
- jobs: {},
+ jobs: {
+ list: [],
+ },
hasError: false,
isAlertDismissed: false,
scope: null,
diff --git a/app/assets/javascripts/labels/index.js b/app/assets/javascripts/labels/index.js
index e87ad8d9a06..0d4113bba4c 100644
--- a/app/assets/javascripts/labels/index.js
+++ b/app/assets/javascripts/labels/index.js
@@ -11,6 +11,7 @@ import ProjectLabelSubscription from './project_label_subscription';
export function initDeleteLabelModal(optionalProps = {}) {
new Vue({
+ name: 'DeleteLabelModalRoot',
render(h) {
return h(DeleteLabelModal, {
props: {
@@ -65,6 +66,7 @@ export function initLabelIndex() {
return new Vue({
el: '#js-promote-label-modal',
+ name: 'PromoteLabelModal',
data() {
return {
modalProps: {
diff --git a/app/assets/javascripts/lib/apollo/instrumentation_link.js b/app/assets/javascripts/lib/apollo/instrumentation_link.js
index 2ab364557b8..bbe16d260e7 100644
--- a/app/assets/javascripts/lib/apollo/instrumentation_link.js
+++ b/app/assets/javascripts/lib/apollo/instrumentation_link.js
@@ -1,4 +1,4 @@
-import { ApolloLink } from 'apollo-link';
+import { ApolloLink } from '@apollo/client/core';
import { memoize } from 'lodash';
export const FEATURE_CATEGORY_HEADER = 'x-gitlab-feature-category';
diff --git a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
index 9b7901685b6..b2a86ac257b 100644
--- a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
+++ b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
@@ -1,5 +1,5 @@
-import { Observable } from 'apollo-link';
-import { onError } from 'apollo-link-error';
+import { Observable } from '@apollo/client/core';
+import { onError } from '@apollo/client/link/error';
import { isNavigatingAway } from '~/lib/utils/is_navigating_away';
/**
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index df2e85afe24..f533ba3671c 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -1,11 +1,9 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
-import { ApolloClient } from 'apollo-client';
-import { ApolloLink } from 'apollo-link';
-import { BatchHttpLink } from 'apollo-link-batch-http';
-import { HttpLink } from 'apollo-link-http';
+import { ApolloClient, InMemoryCache, ApolloLink, HttpLink } from '@apollo/client/core';
+import { BatchHttpLink } from '@apollo/client/link/batch-http';
import { createUploadLink } from 'apollo-upload-client';
import ActionCableLink from '~/actioncable_link';
import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link';
+import possibleTypes from '~/graphql_shared/possibleTypes.json';
import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
import csrf from '~/lib/utils/csrf';
import { objectToQuery, queryToObject } from '~/lib/utils/url_utility';
@@ -21,6 +19,36 @@ export const fetchPolicies = {
CACHE_ONLY: 'cache-only',
};
+export const typePolicies = {
+ Repository: {
+ merge: true,
+ },
+ UserPermissions: {
+ merge: true,
+ },
+ MergeRequestPermissions: {
+ merge: true,
+ },
+ ContainerRepositoryConnection: {
+ merge: true,
+ },
+ TimelogConnection: {
+ merge: true,
+ },
+ BranchList: {
+ merge: true,
+ },
+ InstanceSecurityDashboard: {
+ merge: true,
+ },
+ PipelinePermissions: {
+ merge: true,
+ },
+ DesignCollection: {
+ merge: true,
+ },
+};
+
export const stripWhitespaceFromQuery = (url, path) => {
/* eslint-disable-next-line no-unused-vars */
const [_, params] = url.split(path);
@@ -46,6 +74,30 @@ export const stripWhitespaceFromQuery = (url, path) => {
return `${path}?${reassembled}`;
};
+const acs = [];
+
+let pendingApolloMutations = 0;
+
+// ### Why track pendingApolloMutations, but calculate pendingApolloRequests?
+//
+// In Apollo 2, we had a single link for counting operations.
+//
+// With Apollo 3, the `forward().map(...)` of deduped queries is never called.
+// So, we resorted to calculating the sum of `inFlightLinkObservables?.size`.
+// However! Mutations don't use `inFLightLinkObservables`, but since they are likely
+// not deduped we can count them...
+//
+// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55062#note_838943715
+// https://www.apollographql.com/docs/react/v2/networking/network-layer/#query-deduplication
+Object.defineProperty(window, 'pendingApolloRequests', {
+ get() {
+ return acs.reduce(
+ (sum, ac) => sum + (ac?.queryManager?.inFlightLinkObservables?.size || 0),
+ pendingApolloMutations,
+ );
+ },
+});
+
export default (resolvers = {}, config = {}) => {
const {
baseUrl,
@@ -56,6 +108,7 @@ export default (resolvers = {}, config = {}) => {
path = '/api/graphql',
useGet = false,
} = config;
+ let ac = null;
let uri = `${gon.relative_url_root || ''}${path}`;
if (baseUrl) {
@@ -75,16 +128,6 @@ export default (resolvers = {}, config = {}) => {
batchMax,
};
- const requestCounterLink = new ApolloLink((operation, forward) => {
- window.pendingApolloRequests = window.pendingApolloRequests || 0;
- window.pendingApolloRequests += 1;
-
- return forward(operation).map((response) => {
- window.pendingApolloRequests -= 1;
- return response;
- });
- });
-
/*
This custom fetcher intervention is to deal with an issue where we are using GET to access
eTag polling, but Apollo Client adds excessive whitespace, which causes the
@@ -138,6 +181,22 @@ export default (resolvers = {}, config = {}) => {
);
};
+ const hasMutation = (operation) =>
+ (operation?.query?.definitions || []).some((x) => x.operation === 'mutation');
+
+ const requestCounterLink = new ApolloLink((operation, forward) => {
+ if (hasMutation(operation)) {
+ pendingApolloMutations += 1;
+ }
+
+ return forward(operation).map((response) => {
+ if (hasMutation(operation)) {
+ pendingApolloMutations -= 1;
+ }
+ return response;
+ });
+ });
+
const appLink = ApolloLink.split(
hasSubscriptionOperation,
new ActionCableLink(),
@@ -155,19 +214,23 @@ export default (resolvers = {}, config = {}) => {
),
);
- return new ApolloClient({
+ ac = new ApolloClient({
typeDefs,
link: appLink,
cache: new InMemoryCache({
+ typePolicies,
+ possibleTypes,
...cacheConfig,
- freezeResults: true,
}),
resolvers,
- assumeImmutableResults: true,
defaultOptions: {
query: {
fetchPolicy,
},
},
});
+
+ acs.push(ac);
+
+ return ac;
};
diff --git a/app/assets/javascripts/lib/prosemirror_markdown_serializer.js b/app/assets/javascripts/lib/prosemirror_markdown_serializer.js
new file mode 100644
index 00000000000..6473683c3af
--- /dev/null
+++ b/app/assets/javascripts/lib/prosemirror_markdown_serializer.js
@@ -0,0 +1,3 @@
+// Import from `src/to_markdown` to avoid unnecessary bundling of unused libs
+// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79859
+export * from 'prosemirror-markdown/src/to_markdown';
diff --git a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
index 014823f3831..f240226e991 100644
--- a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
+++ b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
import { parse } from 'graphql';
import { isEqual, pickBy } from 'lodash';
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index eff00dff7a7..cf6ce2c4889 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -705,7 +705,10 @@ export const scopedLabelKey = ({ title = '' }) => {
};
// Methods to set and get Cookie
-export const setCookie = (name, value) => Cookies.set(name, value, { expires: 365 });
+export const setCookie = (name, value, attributes) => {
+ const defaults = { expires: 365, secure: Boolean(window.gon?.secure) };
+ Cookies.set(name, value, { ...defaults, ...attributes });
+};
export const getCookie = (name) => Cookies.get(name);
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
index 733d0f69f5d..f3380b7b4ba 100644
--- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
@@ -1,13 +1,21 @@
<script>
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
cancelAction: { text: __('Cancel') },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
components: {
GlModal,
},
props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
primaryText: {
type: String,
required: false,
@@ -18,11 +26,27 @@ export default {
required: false,
default: 'confirm',
},
+ modalHtmlMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ hideCancel: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
primaryAction() {
return { text: this.primaryText, attributes: { variant: this.primaryVariant } };
},
+ cancelAction() {
+ return this.hideCancel ? null : this.$options.cancelAction;
+ },
+ shouldShowHeader() {
+ return Boolean(this.title?.length);
+ },
},
mounted() {
this.$refs.modal.show();
@@ -36,12 +60,14 @@ export default {
size="sm"
modal-id="confirmationModal"
body-class="gl-display-flex"
+ :title="title"
:action-primary="primaryAction"
- :action-cancel="$options.cancelAction"
- hide-header
+ :action-cancel="cancelAction"
+ :hide-header="!shouldShowHeader"
@primary="$emit('confirmed')"
@hidden="$emit('closed')"
>
- <div class="gl-align-self-center"><slot></slot></div>
+ <div v-if="!modalHtmlMessage" class="gl-align-self-center"><slot></slot></div>
+ <div v-else v-safe-html="modalHtmlMessage" class="gl-align-self-center"></div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
index fdd0e045d07..a8a89d0644a 100644
--- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
@@ -1,6 +1,9 @@
import Vue from 'vue';
-export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {}) {
+export function confirmAction(
+ message,
+ { primaryBtnVariant, primaryBtnText, modalHtmlMessage, title, hideCancel } = {},
+) {
return new Promise((resolve) => {
let confirmed = false;
@@ -15,6 +18,9 @@ export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {
props: {
primaryVariant: primaryBtnVariant,
primaryText: primaryBtnText,
+ title,
+ modalHtmlMessage,
+ hideCancel,
},
on: {
confirmed() {
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 36c6545164e..379c57f3945 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -1,6 +1,7 @@
export const BYTES_IN_KIB = 1024;
export const DEFAULT_DEBOUNCE_AND_THROTTLE_MS = 250;
export const HIDDEN_CLASS = 'hidden';
+export const THOUSAND = 1000;
export const TRUNCATE_WIDTH_DEFAULT_WIDTH = 80;
export const TRUNCATE_WIDTH_DEFAULT_FONT_SIZE = 12;
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index f46263c0e4d..b0e31fe729b 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -1,5 +1,5 @@
import { sprintf, __ } from '~/locale';
-import { BYTES_IN_KIB } from './constants';
+import { BYTES_IN_KIB, THOUSAND } from './constants';
/**
* Function that allows a number with an X amount of decimals
@@ -86,6 +86,27 @@ export function numberToHumanSize(size, digits = 2) {
}
/**
+ * Converts a number to kilos or megas.
+ *
+ * For example:
+ * - 123 becomes 123
+ * - 123456 becomes 123.4k
+ * - 123456789 becomes 123.4m
+ *
+ * @param number Number to format
+ * @param digits The number of digits to appear after the decimal point
+ * @return {string} Formatted number
+ */
+export function numberToMetricPrefix(number, digits = 1) {
+ if (number < THOUSAND) {
+ return number.toString();
+ }
+ if (number < THOUSAND ** 2) {
+ return `${(number / THOUSAND).toFixed(digits)}k`;
+ }
+ return `${(number / THOUSAND ** 2).toFixed(digits)}m`;
+}
+/**
* A simple method that returns the value of a + b
* It seems unessesary, but when combined with a reducer it
* adds up all the values in an array.
diff --git a/app/assets/javascripts/lib/utils/table_utility.js b/app/assets/javascripts/lib/utils/table_utility.js
index 33db7686e0f..6d66335b832 100644
--- a/app/assets/javascripts/lib/utils/table_utility.js
+++ b/app/assets/javascripts/lib/utils/table_utility.js
@@ -1,3 +1,4 @@
+import { convertToSnakeCase, convertToCamelCase } from '~/lib/utils/text_utility';
import { DEFAULT_TH_CLASSES } from './constants';
/**
@@ -7,3 +8,37 @@ import { DEFAULT_TH_CLASSES } from './constants';
* @returns {String} The classes to be used in GlTable fields object.
*/
export const thWidthClass = (width) => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`;
+
+/**
+ * Converts a GlTable sort-changed event object into string format.
+ * This string can be used as a sort argument on GraphQL queries.
+ *
+ * @param {Object} - The table state context object.
+ * @returns {String} A string with the sort key and direction, for example 'NAME_DESC'.
+ */
+export const sortObjectToString = ({ sortBy, sortDesc }) => {
+ const sortingDirection = sortDesc ? 'DESC' : 'ASC';
+ const sortingColumn = convertToSnakeCase(sortBy).toUpperCase();
+
+ return `${sortingColumn}_${sortingDirection}`;
+};
+
+/**
+ * Converts a sort string into a sort state object that can be used to
+ * set the sort order on GlTable.
+ *
+ * @param {String} - The string with the sort key and direction, for example 'NAME_DESC'.
+ * @returns {Object} An object with the sortBy and sortDesc properties.
+ */
+export const sortStringToObject = (sortString) => {
+ let sortBy = null;
+ let sortDesc = null;
+
+ if (sortString && sortString.includes('_')) {
+ const [key, direction] = sortString.split(/_(ASC|DESC)$/);
+ sortBy = convertToCamelCase(key.toLowerCase());
+ sortDesc = direction === 'DESC';
+ }
+
+ return { sortBy, sortDesc };
+};
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 40dd29bea76..ec6789d81ec 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -5,6 +5,12 @@ import { insertText } from '~/lib/utils/common_utils';
const LINK_TAG_PATTERN = '[{text}](url)';
+// at the start of a line, find any amount of whitespace followed by
+// a bullet point character (*+-) and an optional checkbox ([ ] [x])
+// OR a number with a . after it and an optional checkbox ([ ] [x])
+// followed by one or more whitespace characters
+const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isOl>[*+-])|(?<isUl>\d+\.))( \[([x ])\])?\s)(?<content>.)?/;
+
function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
}
@@ -13,8 +19,15 @@ function addBlockTags(blockTag, selected) {
return `${blockTag}\n${selected}\n${blockTag}`;
}
-function lineBefore(text, textarea) {
- const split = text.substring(0, textarea.selectionStart).trim().split('\n');
+function lineBefore(text, textarea, trimNewlines = true) {
+ let split = text.substring(0, textarea.selectionStart);
+
+ if (trimNewlines) {
+ split = split.trim();
+ }
+
+ split = split.split('\n');
+
return split[split.length - 1];
}
@@ -284,9 +297,9 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo
}
/* eslint-disable @gitlab/require-i18n-strings */
-export function keypressNoteText(e) {
+function handleSurroundSelectedText(e, textArea) {
if (!gon.markdown_surround_selection) return;
- if (this.selectionStart === this.selectionEnd) return;
+ if (textArea.selectionStart === textArea.selectionEnd) return;
const keys = {
'*': '**{text}**', // wraps with bold character
@@ -306,7 +319,7 @@ export function keypressNoteText(e) {
updateText({
tag,
- textArea: this,
+ textArea,
blockTag: '',
wrap: true,
select: '',
@@ -316,6 +329,48 @@ export function keypressNoteText(e) {
}
/* eslint-enable @gitlab/require-i18n-strings */
+function handleContinueList(e, textArea) {
+ if (!gon.features?.markdownContinueLists) return;
+ if (!(e.key === 'Enter')) return;
+ if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
+ if (textArea.selectionStart !== textArea.selectionEnd) return;
+
+ const currentLine = lineBefore(textArea.value, textArea, false);
+ const result = currentLine.match(LIST_LINE_HEAD_PATTERN);
+
+ if (result) {
+ const { indent, content, leader } = result.groups;
+ const prevLineEmpty = !content;
+
+ if (prevLineEmpty) {
+ // erase previous empty list item - select the text and allow the
+ // natural line feed erase the text
+ textArea.selectionStart = textArea.selectionStart - result[0].length;
+ return;
+ }
+
+ const itemInsert = `${indent}${leader}`;
+
+ e.preventDefault();
+
+ updateText({
+ tag: itemInsert,
+ textArea,
+ blockTag: '',
+ wrap: false,
+ select: '',
+ tagContent: '',
+ });
+ }
+}
+
+export function keypressNoteText(e) {
+ const textArea = this;
+
+ handleContinueList(e, textArea);
+ handleSurroundSelectedText(e, textArea);
+}
+
export function updateTextForToolbarBtn($toolbarBtn) {
return updateText({
textArea: $toolbarBtn.closest('.md-area').find('textarea'),
diff --git a/app/assets/javascripts/lib/utils/yaml.js b/app/assets/javascripts/lib/utils/yaml.js
new file mode 100644
index 00000000000..9270d388342
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/yaml.js
@@ -0,0 +1,121 @@
+/**
+ * This file adds a merge function to be used with a yaml Document as defined by
+ * the yaml@2.x package: https://eemeli.org/yaml/#yaml
+ *
+ * Ultimately, this functionality should be merged upstream into the package,
+ * track the progress of that effort at https://github.com/eemeli/yaml/pull/347
+ * */
+
+import { visit, Scalar, isCollection, isDocument, isScalar, isNode, isMap, isSeq } from 'yaml';
+
+function getPath(ancestry) {
+ return ancestry.reduce((p, { key }) => {
+ return key !== undefined ? [...p, key.value] : p;
+ }, []);
+}
+
+function getFirstChildNode(collection) {
+ let firstChildKey;
+ let type;
+ switch (collection.constructor.name) {
+ case 'YAMLSeq': // eslint-disable-line @gitlab/require-i18n-strings
+ return collection.items.find((i) => isNode(i));
+ case 'YAMLMap': // eslint-disable-line @gitlab/require-i18n-strings
+ firstChildKey = collection.items[0]?.key;
+ if (!firstChildKey) return undefined;
+ return isScalar(firstChildKey) ? firstChildKey : new Scalar(firstChildKey);
+ default:
+ type = collection.constructor?.name || typeof collection;
+ throw Error(`Cannot identify a child Node for type ${type}`);
+ }
+}
+
+function moveMetaPropsToFirstChildNode(collection) {
+ const firstChildNode = getFirstChildNode(collection);
+ const { comment, commentBefore, spaceBefore } = collection;
+ if (!(comment || commentBefore || spaceBefore)) return;
+ if (!firstChildNode)
+ throw new Error('Cannot move meta properties to a child of an empty Collection'); // eslint-disable-line @gitlab/require-i18n-strings
+ Object.assign(firstChildNode, { comment, commentBefore, spaceBefore });
+ Object.assign(collection, {
+ comment: undefined,
+ commentBefore: undefined,
+ spaceBefore: undefined,
+ });
+}
+
+function assert(isTypeFn, node, path) {
+ if (![isSeq, isMap].includes(isTypeFn)) {
+ throw new Error('assert() can only be used with isSeq() and isMap()');
+ }
+ const expectedTypeName = isTypeFn === isSeq ? 'YAMLSeq' : 'YAMLMap'; // eslint-disable-line @gitlab/require-i18n-strings
+ if (!isTypeFn(node)) {
+ const type = node?.constructor?.name || typeof node;
+ throw new Error(
+ `Type conflict at "${path.join(
+ '.',
+ )}": Destination node is of type ${type}, the node to be merged is of type ${expectedTypeName}.`,
+ );
+ }
+}
+
+function mergeCollection(target, node, path) {
+ // In case both the source and the target node have comments or spaces
+ // We'll move them to their first child so they do not conflict
+ moveMetaPropsToFirstChildNode(node);
+ if (target.hasIn(path)) {
+ const targetNode = target.getIn(path, true);
+ assert(isSeq(node) ? isSeq : isMap, targetNode, path);
+ moveMetaPropsToFirstChildNode(targetNode);
+ }
+}
+
+function mergePair(target, node, path) {
+ if (!isScalar(node.value)) return undefined;
+ if (target.hasIn([...path, node.key.value])) {
+ target.setIn(path, node);
+ } else {
+ target.addIn(path, node);
+ }
+ return visit.SKIP;
+}
+
+function getVisitorFn(target, options) {
+ return {
+ Map: (_, node, ancestors) => {
+ mergeCollection(target, node, getPath(ancestors));
+ },
+ Pair: (_, node, ancestors) => {
+ mergePair(target, node, getPath(ancestors));
+ },
+ Seq: (_, node, ancestors) => {
+ const path = getPath(ancestors);
+ mergeCollection(target, node, path);
+ if (options.onSequence === 'replace') {
+ target.setIn(path, node);
+ return visit.SKIP;
+ }
+ node.items.forEach((item) => target.addIn(path, item));
+ return visit.SKIP;
+ },
+ };
+}
+
+/** Merge another collection into this */
+export function merge(target, source, options = {}) {
+ const opt = {
+ onSequence: 'replace',
+ ...options,
+ };
+ const sourceNode = target.createNode(isDocument(source) ? source.contents : source);
+ if (!isCollection(sourceNode)) {
+ const type = source?.constructor?.name || typeof source;
+ throw new Error(`Cannot merge type "${type}", expected a Collection`);
+ }
+ if (!isCollection(target.contents)) {
+ // If the target doc is empty add the source to it directly
+ Object.assign(target, { contents: sourceNode });
+ return;
+ }
+ visit(sourceNode, getVisitorFn(target, opt));
+}
diff --git a/app/assets/javascripts/listbox/index.js b/app/assets/javascripts/listbox/index.js
new file mode 100644
index 00000000000..f63171e2785
--- /dev/null
+++ b/app/assets/javascripts/listbox/index.js
@@ -0,0 +1,67 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+export function parseAttributes(el) {
+ const { items: itemsString, selected, right: rightString } = el.dataset;
+
+ const items = JSON.parse(itemsString);
+ const right = parseBoolean(rightString);
+
+ const { className } = el;
+
+ return { items, selected, right, className };
+}
+
+export function initListbox(el, { onChange } = {}) {
+ if (!el) return null;
+
+ const { items, selected, right, className } = parseAttributes(el);
+
+ return new Vue({
+ el,
+ data() {
+ return {
+ selected,
+ };
+ },
+ computed: {
+ text() {
+ return items.find(({ value }) => value === this.selected)?.text;
+ },
+ },
+ render(h) {
+ return h(
+ GlDropdown,
+ {
+ props: {
+ text: this.text,
+ right,
+ },
+ class: className,
+ },
+ items.map((item) =>
+ h(
+ GlDropdownItem,
+ {
+ props: {
+ isCheckItem: true,
+ isChecked: this.selected === item.value,
+ },
+ on: {
+ click: () => {
+ this.selected = item.value;
+
+ if (typeof onChange === 'function') {
+ onChange(item);
+ }
+ },
+ },
+ },
+ item.text,
+ ),
+ ),
+ );
+ },
+ });
+}
diff --git a/app/assets/javascripts/listbox/redirect_behavior.js b/app/assets/javascripts/listbox/redirect_behavior.js
new file mode 100644
index 00000000000..7e0ea2c4dfd
--- /dev/null
+++ b/app/assets/javascripts/listbox/redirect_behavior.js
@@ -0,0 +1,22 @@
+import { initListbox } from '~/listbox';
+import { redirectTo } from '~/lib/utils/url_utility';
+
+/**
+ * Instantiates GlListbox components with redirect behavior for tags created
+ * with the `gl_redirect_listbox_tag` HAML helper.
+ *
+ * NOTE: Do not import this script explicitly. Using `gl_redirect_listbox_tag`
+ * automatically injects the `redirect_listbox` bundle, which calls this
+ * function.
+ */
+export function initRedirectListboxBehavior() {
+ const elements = Array.from(document.querySelectorAll('.js-redirect-listbox'));
+
+ return elements.map((el) =>
+ initListbox(el, {
+ onChange({ href }) {
+ redirectTo(href);
+ },
+ }),
+ );
+}
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index c9e7b034950..b0d31ca315e 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -2,6 +2,7 @@
import {
GlSprintf,
GlAlert,
+ GlLink,
GlDropdown,
GlDropdownSectionHeader,
GlDropdownItem,
@@ -20,6 +21,7 @@ import LogSimpleFilters from './log_simple_filters.vue';
export default {
components: {
GlSprintf,
+ GlLink,
GlAlert,
GlDropdown,
GlDropdownSectionHeader,
@@ -58,6 +60,7 @@ export default {
return {
isElasticStackCalloutDismissed: false,
scrollDownButtonDisabled: true,
+ isDeprecationNoticeDismissed: false,
};
},
computed: {
@@ -151,6 +154,41 @@ export default {
{{ s__('Metrics|Invalid time range, please verify.') }}
</gl-alert>
<gl-alert
+ v-if="!isDeprecationNoticeDismissed"
+ :title="s__('Deprecations|Feature deprecation and removal')"
+ class="mb-3"
+ variant="danger"
+ @dismiss="isDeprecationNoticeDismissed = true"
+ >
+ <gl-sprintf
+ :message="
+ s__(
+ 'Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0.',
+ )
+ "
+ >
+ <template #epic="{ content }">
+ <gl-link href="https://gitlab.com/groups/gitlab-org/-/epics/7188" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+
+ <gl-sprintf
+ :message="
+ s__(
+ 'Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}.',
+ )
+ "
+ >
+ <template #epic="{ content }">
+ <gl-link href="https://gitlab.com/groups/gitlab-org/-/epics/6976" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ <gl-alert
v-if="logs.fetchError"
class="mb-3"
variant="danger"
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 376134afef0..f78b4da181e 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -15,11 +15,11 @@ import { initRails } from '~/lib/utils/rails_ujs';
import * as popovers from '~/popovers';
import * as tooltips from '~/tooltips';
import { initPrefetchLinks } from '~/lib/utils/navigation_utility';
+import { logHelloDeferred } from 'jh_else_ce/lib/logger/hello_deferred';
import initAlertHandler from './alert_handler';
import { addDismissFlashClickListener } from './flash';
import initTodoToggle from './header';
import initLayoutNav from './layout_nav';
-import { logHelloDeferred } from './lib/logger/hello_deferred';
import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
import { localTimeAgo } from './lib/utils/datetime/timeago_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue
index 9687eacb036..ec59f0f681c 100644
--- a/app/assets/javascripts/members/components/avatars/user_avatar.vue
+++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue
@@ -8,10 +8,14 @@ import {
import { generateBadges } from 'ee_else_ce/members/utils';
import { glEmojiTag } from '~/emoji';
import { __ } from '~/locale';
+import { isUserBusy } from '~/set_status_modal/utils';
import { AVATAR_SIZE } from '../../constants';
export default {
name: 'UserAvatar',
+ i18n: {
+ busy: __('Busy'),
+ },
avatarSize: AVATAR_SIZE,
orphanedUserLabel: __('Orphaned member'),
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
@@ -46,7 +50,10 @@ export default {
}).filter((badge) => badge.show);
},
statusEmoji() {
- return this.user?.status?.emoji;
+ return this.user?.showStatus && this.user?.status?.emoji;
+ },
+ isUserBusy() {
+ return isUserBusy(this.user?.availability || '');
},
},
methods: {
@@ -73,6 +80,11 @@ export default {
:entity-id="user.id"
>
<template #meta>
+ <div v-if="isUserBusy" class="gl-p-1">
+ <span class="gl-text-gray-500 gl-font-sm gl-font-weight-normal"
+ >({{ $options.i18n.busy }})</span
+ >
+ </div>
<div v-if="statusEmoji" class="gl-p-1">
<span
v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)"
diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
index e9329fb1d88..633dee75237 100644
--- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
+++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
@@ -151,6 +151,7 @@ export default {
:search-input-placeholder="filteredSearchBar.placeholder"
:initial-filter-value="initialFilterValue"
data-testid="members-filtered-search-bar"
+ data-qa-selector="members_filtered_search_bar_content"
@onFilter="handleFilter"
/>
</template>
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index e09d16cf680..b4ba9aa36e7 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -11,7 +11,9 @@ import {
ACTIVE_TAB_QUERY_PARAM_NAME,
TAB_QUERY_PARAM_VALUES,
MEMBER_STATE_AWAITING,
+ MEMBER_STATE_ACTIVE,
USER_STATE_BLOCKED_PENDING_APPROVAL,
+ BADGE_LABELS_AWAITING_USER_SIGNUP,
BADGE_LABELS_PENDING_OWNER_APPROVAL,
} from '../../constants';
import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue';
@@ -154,8 +156,12 @@ export default {
* @see {@link ~/app/serializers/member_entity.rb}
* @returns {boolean}
*/
- isNewUser(memberInviteMetadata) {
- return memberInviteMetadata && !memberInviteMetadata.userState;
+ isNewUser(memberInviteMetadata, memberState) {
+ return (
+ memberInviteMetadata &&
+ !memberInviteMetadata.userState &&
+ memberState !== MEMBER_STATE_ACTIVE
+ );
},
/**
* Returns whether the user is awaiting root approval
@@ -204,6 +210,10 @@ export default {
* @returns {string}
*/
inviteBadge(memberInviteMetadata, memberState) {
+ if (this.isNewUser(memberInviteMetadata, memberState)) {
+ return BADGE_LABELS_AWAITING_USER_SIGNUP;
+ }
+
if (this.shouldAddPendingOwnerApprovalBadge(memberInviteMetadata, memberState)) {
return BADGE_LABELS_PENDING_OWNER_APPROVAL;
}
diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js
index 62241eaed04..273f1acebc7 100644
--- a/app/assets/javascripts/members/constants.js
+++ b/app/assets/javascripts/members/constants.js
@@ -111,6 +111,7 @@ export const MEMBER_STATE_CREATED = 0;
export const MEMBER_STATE_AWAITING = 1;
export const MEMBER_STATE_ACTIVE = 2;
+export const BADGE_LABELS_AWAITING_USER_SIGNUP = __('Awaiting user signup');
export const BADGE_LABELS_PENDING_OWNER_APPROVAL = __('Pending owner approval');
export const DAYS_TO_EXPIRE_SOON = 7;
diff --git a/app/assets/javascripts/merge_conflicts/store/actions.js b/app/assets/javascripts/merge_conflicts/store/actions.js
index df515c4ac1a..9c101da52f5 100644
--- a/app/assets/javascripts/merge_conflicts/store/actions.js
+++ b/app/assets/javascripts/merge_conflicts/store/actions.js
@@ -1,4 +1,4 @@
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -51,7 +51,7 @@ export const setFailedRequest = ({ commit }, message) => {
export const setViewType = ({ commit }, viewType) => {
commit(types.SET_VIEW_TYPE, viewType);
- Cookies.set('diff_view', viewType);
+ setCookie('diff_view', viewType);
};
export const setSubmitState = ({ commit }, isSubmitting) => {
diff --git a/app/assets/javascripts/merge_conflicts/store/state.js b/app/assets/javascripts/merge_conflicts/store/state.js
index 8f700f58e54..7a2e28183a7 100644
--- a/app/assets/javascripts/merge_conflicts/store/state.js
+++ b/app/assets/javascripts/merge_conflicts/store/state.js
@@ -1,7 +1,7 @@
-import Cookies from 'js-cookie';
+import { getCookie } from '~/lib/utils/common_utils';
import { VIEW_TYPES } from '../constants';
-const diffViewType = Cookies.get('diff_view');
+const diffViewType = getCookie('diff_view');
export default () => ({
isLoading: true,
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index a40caea1223..ad0117844cd 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,20 +1,21 @@
/* eslint-disable no-new, class-methods-use-this */
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import Cookies from 'js-cookie';
import Vue from 'vue';
+import {
+ getCookie,
+ parseUrlPathname,
+ isMetaClick,
+ parseBoolean,
+ scrollToElement,
+} from '~/lib/utils/common_utils';
import createEventHub from '~/helpers/event_hub_factory';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import Diff from './diff';
import createFlash from './flash';
import { initDiffStatsDropdown } from './init_diff_stats_dropdown';
import axios from './lib/utils/axios_utils';
-import {
- parseUrlPathname,
- isMetaClick,
- parseBoolean,
- scrollToElement,
-} from './lib/utils/common_utils';
+
import { localTimeAgo } from './lib/utils/datetime_utility';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { __ } from './locale';
@@ -514,7 +515,7 @@ export default class MergeRequestTabs {
// Expand the issuable sidebar unless the user explicitly collapsed it
expandView() {
- if (parseBoolean(Cookies.get('collapsed_gutter'))) {
+ if (parseBoolean(getCookie('collapsed_gutter'))) {
return;
}
const $gutterBtn = $('.js-sidebar-toggle');
diff --git a/app/assets/javascripts/milestones/index.js b/app/assets/javascripts/milestones/index.js
index 2ca5f104b4f..f90fdb04923 100644
--- a/app/assets/javascripts/milestones/index.js
+++ b/app/assets/javascripts/milestones/index.js
@@ -46,6 +46,7 @@ export function initPromoteMilestoneModal() {
return new Vue({
el: promoteMilestoneModal,
+ name: 'PromoteMilestoneModalRoot',
render(createElement) {
return createElement(PromoteMilestoneModal);
},
@@ -80,6 +81,7 @@ export function initDeleteMilestoneModal() {
return new Vue({
el: '#js-delete-milestone-modal',
+ name: 'DeleteMilestoneModalRoot',
data() {
return {
modalProps: {
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index c9767330b73..6467d953500 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,5 +1,13 @@
<script>
-import { GlButton, GlModalDirective, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import {
+ GlButton,
+ GlModalDirective,
+ GlTooltipDirective,
+ GlIcon,
+ GlAlert,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import VueDraggable from 'vuedraggable';
import { mapActions, mapState, mapGetters } from 'vuex';
@@ -38,6 +46,9 @@ export default {
GroupEmptyState,
VariablesSection,
LinksSection,
+ GlAlert,
+ GlSprintf,
+ GlLink,
},
directives: {
GlModal: GlModalDirective,
@@ -143,6 +154,7 @@ export default {
isRearrangingPanels: false,
originalDocumentTitle: document.title,
hoveredPanel: '',
+ isDeprecationNoticeDismissed: false,
};
},
computed: {
@@ -392,9 +404,44 @@ export default {
},
};
</script>
-
<template>
<div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
+ <div>
+ <gl-alert
+ v-if="!isDeprecationNoticeDismissed"
+ :title="__('Feature deprecation and removal')"
+ class="mb-3"
+ variant="danger"
+ @dismiss="isDeprecationNoticeDismissed = true"
+ >
+ <gl-sprintf
+ :message="
+ s__(
+ 'Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0.',
+ )
+ "
+ >
+ <template #epic="{ content }">
+ <gl-link href="https://gitlab.com/groups/gitlab-org/-/epics/7188" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ <gl-sprintf
+ :message="
+ s__(
+ 'Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}.',
+ )
+ "
+ >
+ <template #epic="{ content }">
+ <gl-link href="https://gitlab.com/groups/gitlab-org/-/epics/6976" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </div>
<dashboard-header
v-if="showHeader"
ref="prometheusGraphsHeader"
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 07c6fa7773a..bf1fd691ca8 100644
--- a/app/assets/javascripts/nav/components/top_nav_menu_item.vue
+++ b/app/assets/javascripts/nav/components/top_nav_menu_item.vue
@@ -35,7 +35,7 @@ export default {
<gl-button
category="tertiary"
:href="menuItem.href"
- class="top-nav-menu-item gl-display-block"
+ class="top-nav-menu-item gl-display-block gl-pr-3!"
:class="[menuItem.css_class, { [$options.ACTIVE_CLASS]: menuItem.active }]"
:aria-label="menuItem.title"
v-bind="dataAttrs"
diff --git a/app/assets/javascripts/nav/mount.js b/app/assets/javascripts/nav/mount.js
index 51b6a31b8cb..7b0cc977107 100644
--- a/app/assets/javascripts/nav/mount.js
+++ b/app/assets/javascripts/nav/mount.js
@@ -12,6 +12,7 @@ const mount = (el, Component) => {
return new Vue({
el,
+ name: 'TopNavRoot',
store,
render(h) {
return h(Component, {
diff --git a/app/assets/javascripts/network/raphael.js b/app/assets/javascripts/network/raphael.js
index 22e06a35d91..e13471c0e51 100644
--- a/app/assets/javascripts/network/raphael.js
+++ b/app/assets/javascripts/network/raphael.js
@@ -1,12 +1,14 @@
import Raphael from 'raphael/raphael';
+import { formatDate } from '~/lib/utils/datetime_utility';
Raphael.prototype.commitTooltip = function commitTooltip(x, y, commit) {
const boxWidth = 300;
const icon = this.image(gon.relative_url_root + commit.author.icon, x, y, 20, 20);
const nameText = this.text(x + 25, y + 10, commit.author.name);
- const idText = this.text(x, y + 35, commit.id);
- const messageText = this.text(x, y + 50, commit.message.replace(/\r?\n/g, ' \n '));
- const textSet = this.set(icon, nameText, idText, messageText).attr({
+ const dateText = this.text(x, y + 35, formatDate(commit.date));
+ const idText = this.text(x, y + 55, commit.id);
+ const messageText = this.text(x, y + 70, commit.message.replace(/\r?\n/g, ' \n '));
+ const textSet = this.set(icon, nameText, dateText, idText, messageText).attr({
'text-anchor': 'start',
font: '12px Monaco, monospace',
});
@@ -14,6 +16,9 @@ Raphael.prototype.commitTooltip = function commitTooltip(x, y, commit) {
font: '14px Arial',
'font-weight': 'bold',
});
+ dateText.attr({
+ fill: '#666',
+ });
idText.attr({
fill: '#AAA',
});
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 996c008b881..a9948fed3b6 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -369,7 +369,7 @@ export default {
class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
data-qa-selector="comment_field"
data-testid="comment-field"
- :data-supports-quick-actions="!glFeatures.tributeAutocomplete"
+ data-supports-quick-actions="true"
:aria-label="$options.i18n.comment"
:placeholder="$options.i18n.bodyPlaceholder"
@keydown.up="editCurrentUserLastNote()"
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index b2d5910fd3f..b4f7ba5f960 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -107,7 +107,7 @@ export default {
<td v-if="error" class="js-error-lazy-load-diff diff-loading-error-block">
{{ __('Unable to load the diff') }}
<button
- class="btn-link btn-link-retry btn-no-padding js-toggle-lazy-diff-retry-button"
+ class="btn-link btn-link-retry gl-p-0 js-toggle-lazy-diff-retry-button"
@click="fetchDiff"
>
{{ __('Try again') }}
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index d6b65ed0e8b..ee22c118e11 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -5,7 +5,6 @@ import { getDraft, updateDraft } from '~/lib/utils/autosave';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import markdownField from '~/vue_shared/components/markdown/field.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../event_hub';
import issuableStateMixin from '../mixins/issuable_state';
import resolvable from '../mixins/resolvable';
@@ -20,7 +19,7 @@ export default {
GlSprintf,
GlLink,
},
- mixins: [glFeatureFlagsMixin(), issuableStateMixin, resolvable],
+ mixins: [issuableStateMixin, resolvable],
props: {
noteBody: {
type: String,
@@ -349,7 +348,7 @@ export default {
ref="textarea"
v-model="updatedNoteBody"
:disabled="isSubmitting"
- :data-supports-quick-actions="!isEditing && !glFeatures.tributeAutocomplete"
+ :data-supports-quick-actions="!isEditing"
name="note[note]"
class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
data-qa-selector="reply_field"
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 8e32c3b3073..ddf72587ba3 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -5,6 +5,7 @@ import DraftNote from '~/batch_comments/components/draft_note.vue';
import createFlash from '~/flash';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
import { isLoggedIn } from '~/lib/utils/common_utils';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { s__, __ } from '~/locale';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
@@ -170,12 +171,13 @@ export default {
this.expandDiscussion({ discussionId: this.discussion.id });
}
},
- cancelReplyForm(shouldConfirm, isDirty) {
+ async cancelReplyForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
- // eslint-disable-next-line no-alert
- if (!window.confirm(msg)) {
+ const confirmed = await confirmAction(msg);
+
+ if (!confirmed) {
return;
}
}
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 3250a4818c7..7bad10616cc 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -3,6 +3,7 @@ import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import $ from 'jquery';
import { escape, isEmpty } from 'lodash';
import { mapGetters, mapActions } from 'vuex';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -243,14 +244,18 @@ export default {
this.setSelectedCommentPositionHover();
this.$emit('handleEdit');
},
- deleteHandler() {
+ async deleteHandler() {
const typeOfComment = this.note.isDraft ? __('pending comment') : __('comment');
- if (
- // eslint-disable-next-line no-alert
- window.confirm(
- sprintf(__('Are you sure you want to delete this %{typeOfComment}?'), { typeOfComment }),
- )
- ) {
+
+ const msg = sprintf(__('Are you sure you want to delete this %{typeOfComment}?'), {
+ typeOfComment,
+ });
+ const confirmed = await confirmAction(msg, {
+ primaryBtnVariant: 'danger',
+ primaryBtnText: __('Delete Comment'),
+ });
+
+ if (confirmed) {
this.isDeleting = true;
this.$emit('handleDeleteNote', this.note);
@@ -345,10 +350,11 @@ export default {
parent: this.$el,
});
},
- formCancelHandler({ shouldConfirm, isDirty }) {
+ async formCancelHandler({ shouldConfirm, isDirty }) {
if (shouldConfirm && isDirty) {
- // eslint-disable-next-line no-alert
- if (!window.confirm(__('Are you sure you want to cancel editing this comment?'))) return;
+ const msg = __('Are you sure you want to cancel editing this comment?');
+ const confirmed = await confirmAction(msg);
+ if (!confirmed) return;
}
this.$refs.noteBody.resetAutoSave();
if (this.oldContent) {
diff --git a/app/assets/javascripts/notes/discussion_filters.js b/app/assets/javascripts/notes/discussion_filters.js
index 7c9e7703d59..104e9d4183a 100644
--- a/app/assets/javascripts/notes/discussion_filters.js
+++ b/app/assets/javascripts/notes/discussion_filters.js
@@ -19,7 +19,7 @@ export default (store) => {
return new Vue({
el: discussionFilterEl,
- name: 'DiscussionFilter',
+ name: 'DiscussionFilterRoot',
components: {
DiscussionFilter,
},
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 2ce60976adb..19fa484d659 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -14,6 +14,7 @@ export default () => {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'NotesRoot',
components: {
notesApp,
},
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js
index ad529eb99b6..93236b05100 100644
--- a/app/assets/javascripts/notes/mixins/discussion_navigation.js
+++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js
@@ -3,8 +3,6 @@ import { scrollToElementWithContext, scrollToElement } from '~/lib/utils/common_
import { updateHistory } from '../../lib/utils/url_utility';
import eventHub from '../event_hub';
-const isDiffsVirtualScrollingEnabled = () => window.gon?.features?.diffsVirtualScrolling;
-
/**
* @param {string} selector
* @returns {boolean}
@@ -15,7 +13,7 @@ function scrollTo(selector, { withoutContext = false } = {}) {
if (el) {
scrollFunction(el, {
- behavior: isDiffsVirtualScrollingEnabled() ? 'auto' : 'smooth',
+ behavior: 'auto',
});
return true;
}
@@ -31,7 +29,7 @@ function updateUrlWithNoteId(noteId) {
replace: true,
};
- if (noteId && isDiffsVirtualScrollingEnabled()) {
+ if (noteId) {
// Temporarily mask the ID to avoid the browser default
// scrolling taking over which is broken with virtual
// scrolling enabled.
@@ -115,17 +113,13 @@ function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId)
const isDiffView = window.mrTabs.currentAction === 'diffs';
const targetId = fn(discussionId, isDiffView);
const discussion = self.getDiscussion(targetId);
- const setHash = !isDiffView && !isDiffsVirtualScrollingEnabled();
const discussionFilePath = discussion?.diff_file?.file_path;
- if (isDiffsVirtualScrollingEnabled()) {
- window.location.hash = '';
- }
+ window.location.hash = '';
if (discussionFilePath) {
self.scrollToFile({
path: discussionFilePath,
- setHash,
});
}
diff --git a/app/assets/javascripts/notes/sort_discussions.js b/app/assets/javascripts/notes/sort_discussions.js
index ecfa3223039..ca8df880fe4 100644
--- a/app/assets/javascripts/notes/sort_discussions.js
+++ b/app/assets/javascripts/notes/sort_discussions.js
@@ -8,6 +8,7 @@ export default (store) => {
return new Vue({
el,
+ name: 'SortDiscussionRoot',
store,
render(createElement) {
return createElement(SortDiscussion);
diff --git a/app/assets/javascripts/notifications/components/notifications_dropdown.vue b/app/assets/javascripts/notifications/components/notifications_dropdown.vue
index 69eb2115bf4..6b450c2b5fd 100644
--- a/app/assets/javascripts/notifications/components/notifications_dropdown.vue
+++ b/app/assets/javascripts/notifications/components/notifications_dropdown.vue
@@ -42,6 +42,9 @@ export default {
showLabel: {
default: false,
},
+ noFlip: {
+ default: false,
+ },
},
data() {
return {
@@ -127,6 +130,7 @@ export default {
:disabled="disabled"
:split="isCustomNotification"
:text="buttonText"
+ :no-flip="noFlip"
@click="openNotificationsModal"
>
<notifications-dropdown-item
diff --git a/app/assets/javascripts/notifications/index.js b/app/assets/javascripts/notifications/index.js
index d60a368703c..a81f2c2590b 100644
--- a/app/assets/javascripts/notifications/index.js
+++ b/app/assets/javascripts/notifications/index.js
@@ -21,6 +21,7 @@ export default () => {
projectId,
groupId,
showLabel,
+ noFlip,
} = el.dataset;
return new Vue({
@@ -35,6 +36,7 @@ export default () => {
projectId,
groupId,
showLabel: parseBoolean(showLabel),
+ noFlip: parseBoolean(noFlip),
},
render(h) {
return h(NotificationsDropdown);
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
index 4fda4058711..7659ba5f9ea 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
@@ -7,6 +7,7 @@ import RegistryList from '~/packages_and_registries/shared/components/registry_l
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import {
REMOVE_TAGS_BUTTON_TITLE,
TAGS_LIST_TITLE,
@@ -20,7 +21,6 @@ import {
} from '../../constants/index';
import getContainerRepositoryTagsQuery from '../../graphql/queries/get_container_repository_tags.query.graphql';
import TagsListRow from './tags_list_row.vue';
-import TagsLoader from './tags_loader.vue';
export default {
name: 'TagsList',
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
index bb687ffdb89..931849c9918 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
@@ -5,6 +5,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
+import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import DeleteImage from '../components/delete_image.vue';
import DeleteAlert from '../components/details_page/delete_alert.vue';
import DeleteModal from '../components/details_page/delete_modal.vue';
@@ -12,7 +13,6 @@ import DetailsHeader from '../components/details_page/details_header.vue';
import PartialCleanupAlert from '../components/details_page/partial_cleanup_alert.vue';
import StatusAlert from '../components/details_page/status_alert.vue';
import TagsList from '../components/details_page/tags_list.vue';
-import TagsLoader from '../components/details_page/tags_loader.vue';
import {
ALERT_SUCCESS_TAG,
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
index 3274de05803..e2acebf39d6 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
@@ -52,7 +52,7 @@ export default {
),
CliCommands: () =>
import(
- /* webpackChunkName: 'container_registry_components' */ '../components/list_page/cli_commands.vue'
+ /* webpackChunkName: 'container_registry_components' */ '~/packages_and_registries/shared/components/cli_commands.vue'
),
GlModal,
GlSprintf,
@@ -68,7 +68,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
- inject: ['config'],
+ inject: ['config', 'dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand'],
loader: {
repeat: 10,
width: 1000,
@@ -96,6 +96,9 @@ export default {
return data[this.graphqlResource]?.containerRepositories.nodes;
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.pageInfo = data[this.graphqlResource]?.containerRepositories?.pageInfo;
this.containerRepositoriesCount = data[this.graphqlResource]?.containerRepositoriesCount;
},
@@ -321,7 +324,12 @@ export default {
:hide-expiration-policy-data="config.isGroupPage"
>
<template #commands>
- <cli-commands v-if="showCommands" />
+ <cli-commands
+ v-if="showCommands"
+ :docker-build-command="dockerBuildCommand"
+ :docker-push-command="dockerPushCommand"
+ :docker-login-command="dockerLoginCommand"
+ />
</template>
</registry-header>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue
index 2a479c65d0c..9bab08b8548 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue
@@ -21,13 +21,17 @@ export default {
},
},
computed: {
- showModuleCount() {
- return Number.isInteger(this.count);
+ hasModules() {
+ return Number.isInteger(this.count) && this.count > 0;
},
moduleAmountText() {
return n__(`%d Module`, `%d Modules`, this.count);
},
infoMessages() {
+ if (!this.hasModules) {
+ return [];
+ }
+
return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
@@ -43,11 +47,7 @@ export default {
<template>
<title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
<template #metadata-amount>
- <metadata-item
- v-if="showModuleCount"
- icon="infrastructure-registry"
- :text="moduleAmountText"
- />
+ <metadata-item v-if="hasModules" icon="infrastructure-registry" :text="moduleAmountText" />
</template>
</title-area>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue
index 462618a7f12..184a24047eb 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue
@@ -99,7 +99,7 @@ export default {
<template>
<div>
<infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
- <infrastructure-search @update="requestPackagesList" />
+ <infrastructure-search v-if="packagesCount > 0" @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
index 1afd1b69db0..57ff3cd2a83 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
@@ -61,11 +61,13 @@ export default {
</template>
<template #right-secondary>
- <gl-sprintf :message="__('Created %{timestamp}')">
- <template #timestamp>
- <time-ago-tooltip :time="packageEntity.createdAt" />
- </template>
- </gl-sprintf>
+ <span>
+ <gl-sprintf :message="__('Created %{timestamp}')">
+ <template #timestamp>
+ <time-ago-tooltip :time="packageEntity.createdAt" />
+ </template>
+ </gl-sprintf>
+ </span>
</template>
</list-item>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
index 3483d23e251..c27083261b5 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
@@ -9,6 +9,8 @@ import {
FILTERED_SEARCH_TERM,
FILTERED_SEARCH_TYPE,
} from '~/packages_and_registries/shared/constants';
+import { LIST_KEY_CREATED_AT } from '~/packages_and_registries/package_registry/constants';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import PackageTypeToken from './tokens/package_type_token.vue';
export default {
@@ -22,13 +24,13 @@ export default {
operators: OPERATOR_IS_ONLY,
},
],
- components: { RegistrySearch, UrlSync },
+ components: { RegistrySearch, UrlSync, LocalStorageSync },
inject: ['isGroupPage'],
data() {
return {
filters: [],
sorting: {
- orderBy: 'name',
+ orderBy: LIST_KEY_CREATED_AT,
sort: 'desc',
},
mountRegistrySearch: false,
@@ -94,19 +96,26 @@ export default {
</script>
<template>
- <url-sync>
- <template #default="{ updateQuery }">
- <registry-search
- v-if="mountRegistrySearch"
- :filter="filters"
- :sorting="sorting"
- :tokens="$options.tokens"
- :sortable-fields="sortableFields"
- @sorting:changed="updateSortingAndEmitUpdate"
- @filter:changed="updateFilters"
- @filter:submit="emitUpdate"
- @query:changed="updateQuery"
- />
- </template>
- </url-sync>
+ <local-storage-sync
+ storage-key="package_registry_list_sorting"
+ :value="sorting"
+ as-json
+ @input="updateSorting"
+ >
+ <url-sync>
+ <template #default="{ updateQuery }">
+ <registry-search
+ v-if="mountRegistrySearch"
+ :filter="filters"
+ :sorting="sorting"
+ :tokens="$options.tokens"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSortingAndEmitUpdate"
+ @filter:changed="updateFilters"
+ @filter:submit="emitUpdate"
+ @query:changed="updateQuery"
+ />
+ </template>
+ </url-sync>
+ </local-storage-sync>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json
deleted file mode 100644
index c61a653d10b..00000000000
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "__schema": {
- "types": [
- {
- "kind": "UNION",
- "name": "PackageMetadata",
- "possibleTypes": [
- { "name": "ComposerMetadata" },
- { "name": "ConanMetadata" },
- { "name": "MavenMetadata" },
- { "name": "NugetMetadata" },
- { "name": "PypiMetadata" }
- ]
- }
- ]
- }
-}
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
index 21d6fbc9e1f..56f95fa2c1f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
@@ -1,22 +1,9 @@
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import introspectionQueryResultData from './fragmentTypes.json';
-
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
Vue.use(VueApollo);
export const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- cacheConfig: {
- fragmentMatcher,
- },
- },
- ),
+ defaultClient: createDefaultClient(),
});
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue b/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue
index 07ee3c6083b..de7ab3e6d7b 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue
@@ -10,7 +10,7 @@ import {
COPY_BUILD_TITLE,
PUSH_COMMAND_LABEL,
COPY_PUSH_TITLE,
-} from '../../constants/index';
+} from '../constants';
const trackingLabel = 'quickstart_dropdown';
@@ -20,7 +20,20 @@ export default {
CodeInstruction,
},
mixins: [Tracking.mixin({ label: trackingLabel })],
- inject: ['config', 'dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand'],
+ props: {
+ dockerBuildCommand: {
+ type: String,
+ required: true,
+ },
+ dockerPushCommand: {
+ type: String,
+ required: true,
+ },
+ dockerLoginCommand: {
+ type: String,
+ required: true,
+ },
+ },
trackingLabel,
i18n: {
QUICK_START,
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue b/app/assets/javascripts/packages_and_registries/shared/components/tags_loader.vue
index b7afa5fba33..b7afa5fba33 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/tags_loader.vue
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants/index.js b/app/assets/javascripts/packages_and_registries/shared/constants/index.js
new file mode 100644
index 00000000000..7659781d96e
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/constants/index.js
@@ -0,0 +1,2 @@
+export * from './package_registry';
+export * from './quick_start';
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants.js b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
index afc72a2c627..afc72a2c627 100644
--- a/app/assets/javascripts/packages_and_registries/shared/constants.js
+++ b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants/quick_start.js b/app/assets/javascripts/packages_and_registries/shared/constants/quick_start.js
new file mode 100644
index 00000000000..6a39c07eba2
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/constants/quick_start.js
@@ -0,0 +1,9 @@
+import { s__ } from '~/locale';
+
+export const QUICK_START = s__('ContainerRegistry|CLI Commands');
+export const LOGIN_COMMAND_LABEL = s__('ContainerRegistry|Login');
+export const COPY_LOGIN_TITLE = s__('ContainerRegistry|Copy login command');
+export const BUILD_COMMAND_LABEL = s__('ContainerRegistry|Build an image');
+export const COPY_BUILD_TITLE = s__('ContainerRegistry|Copy build command');
+export const PUSH_COMMAND_LABEL = s__('ContainerRegistry|Push an image');
+export const COPY_PUSH_TITLE = s__('ContainerRegistry|Copy push command');
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
index c2510a16d2f..3ef75b3ef0e 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
+++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
@@ -140,8 +140,8 @@ export default {
return {
id: 'signup-settings-modal',
text: n__(
- 'ApplicationSettings|By making this change, you will automatically approve %d user with the pending approval status.',
- 'ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status.',
+ 'ApplicationSettings|By making this change, you will automatically approve %d user who is pending approval.',
+ 'ApplicationSettings|By making this change, you will automatically approve %d users who are pending approval.',
pendingUserCount,
),
actionPrimary: {
@@ -157,7 +157,7 @@ export default {
actionCancel: {
text: __('Cancel'),
},
- title: s__('ApplicationSettings|Approve users in the pending approval status?'),
+ title: s__('ApplicationSettings|Approve users who are pending approval?'),
};
},
},
diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js
new file mode 100644
index 00000000000..67eee2c3209
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js
@@ -0,0 +1,52 @@
+import createFlash from '~/flash';
+import axios from '../../../lib/utils/axios_utils';
+import { __ } from '../../../locale';
+
+export default class PayloadDownloader {
+ constructor(trigger) {
+ this.trigger = trigger;
+ }
+
+ init() {
+ this.spinner = this.trigger.querySelector('.js-spinner');
+ this.text = this.trigger.querySelector('.js-text');
+
+ this.trigger.addEventListener('click', (event) => {
+ event.preventDefault();
+
+ return this.requestPayload();
+ });
+ }
+
+ requestPayload() {
+ this.spinner.classList.add('d-inline-flex');
+
+ return axios
+ .get(this.trigger.dataset.endpoint, {
+ responseType: 'json',
+ })
+ .then(({ data }) => {
+ PayloadDownloader.downloadFile(data);
+ })
+ .catch(() => {
+ createFlash({
+ message: __('Error fetching payload data.'),
+ });
+ })
+ .finally(() => {
+ this.spinner.classList.remove('d-inline-flex');
+ });
+ }
+
+ static downloadFile(data) {
+ const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
+
+ const link = document.createElement('a');
+ link.href = window.URL.createObjectURL(blob);
+ link.download = `${data.recorded_at.slice(0, 10)} payload.json`;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ window.URL.revokeObjectURL(link.href);
+ }
+}
diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
index 08f6633f424..c017cf0afa2 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
@@ -5,7 +5,6 @@ import { __ } from '../../../locale';
export default class PayloadPreviewer {
constructor(trigger) {
this.trigger = trigger;
- this.container = document.querySelector(trigger.dataset.payloadSelector);
this.isVisible = false;
this.isInserted = false;
}
@@ -23,21 +22,27 @@ export default class PayloadPreviewer {
});
}
+ getContainer() {
+ return document.querySelector(this.trigger.dataset.payloadSelector);
+ }
+
requestPayload() {
if (this.isInserted) return this.showPayload();
- this.spinner.classList.add('d-inline-flex');
+ this.spinner.classList.add('gl-display-inline-flex');
+
+ const container = this.getContainer();
return axios
- .get(this.container.dataset.endpoint, {
+ .get(container.dataset.endpoint, {
responseType: 'text',
})
.then(({ data }) => {
- this.spinner.classList.remove('d-inline-flex');
+ this.spinner.classList.remove('gl-display-inline-flex');
this.insertPayload(data);
})
.catch(() => {
- this.spinner.classList.remove('d-inline-flex');
+ this.spinner.classList.remove('gl-display-inline-flex');
createFlash({
message: __('Error fetching payload data.'),
});
@@ -46,19 +51,19 @@ export default class PayloadPreviewer {
hidePayload() {
this.isVisible = false;
- this.container.classList.add('d-none');
+ this.getContainer().classList.add('gl-display-none');
this.text.textContent = __('Preview payload');
}
showPayload() {
this.isVisible = true;
- this.container.classList.remove('d-none');
+ this.getContainer().classList.remove('gl-display-none');
this.text.textContent = __('Hide payload');
}
insertPayload(data) {
this.isInserted = true;
- this.container.innerHTML = data;
+ this.getContainer().innerHTML = data;
this.showPayload();
}
}
diff --git a/app/assets/javascripts/pages/admin/application_settings/service_usage_data/index.js b/app/assets/javascripts/pages/admin/application_settings/service_usage_data/index.js
new file mode 100644
index 00000000000..8a12e753847
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/service_usage_data/index.js
@@ -0,0 +1,3 @@
+import initServiceUsageData from '~/admin/application_settings/setup_service_usage_data';
+
+initServiceUsageData();
diff --git a/app/assets/javascripts/pages/admin/runners/show/index.js b/app/assets/javascripts/pages/admin/runners/show/index.js
new file mode 100644
index 00000000000..f76f3a2430d
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/runners/show/index.js
@@ -0,0 +1,3 @@
+import { initAdminRunnerShow } from '~/runner/admin_runner_show';
+
+initAdminRunnerShow();
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index f6155b2ab2f..96487e14e30 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -1,8 +1,7 @@
import { GROUP_BADGE } from '~/badges/constants';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
-import TransferDropdown from '~/groups/transfer_dropdown';
-import setupTransferEdit from '~/groups/transfer_edit';
+import initTransferGroupForm from '~/groups/init_transfer_group_form';
import groupsSelect from '~/groups_select';
import { initCascadingSettingsLockPopovers } from '~/namespaces/cascading_settings';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
@@ -15,11 +14,11 @@ document.addEventListener('DOMContentLoaded', () => {
initFilePickers();
initConfirmDanger();
initSettingsPanels();
+ initTransferGroupForm();
dirtySubmitFactory(
document.querySelectorAll('.js-general-settings-form, .js-general-permissions-form'),
);
mountBadgeSettings(GROUP_BADGE);
- setupTransferEdit('.js-group-transfer-form', '#new_parent_group_id');
// Initialize Subgroups selector
groupsSelect();
@@ -28,6 +27,4 @@ document.addEventListener('DOMContentLoaded', () => {
initSearchSettings();
initCascadingSettingsLockPopovers();
-
- return new TransferDropdown();
});
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index 01a371920f8..14ce3f775b1 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -1,6 +1,7 @@
import { groupMemberRequestFormatter } from '~/groups/members/utils';
import groupsSelect from '~/groups_select';
import initInviteGroupTrigger from '~/invite_members/init_invite_group_trigger';
+import initInviteGroupsModal from '~/invite_members/init_invite_groups_modal';
import initInviteMembersForm from '~/invite_members/init_invite_members_form';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
@@ -56,6 +57,7 @@ groupsSelect();
memberExpirationDate();
memberExpirationDate('.js-access-expiration-date-groups');
initInviteMembersModal();
+initInviteGroupsModal();
initInviteMembersTrigger();
initInviteGroupTrigger();
diff --git a/app/assets/javascripts/pages/projects/imports/new/index.js b/app/assets/javascripts/pages/projects/imports/new/index.js
new file mode 100644
index 00000000000..4acfc5265ac
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/imports/new/index.js
@@ -0,0 +1,3 @@
+import initProjectNew from '~/projects/project_new';
+
+initProjectNew.bindEvents();
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
index 42c40cda601..adae97c6b6f 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
@@ -2,7 +2,8 @@
import { GlProgressBar, GlSprintf, GlAlert } from '@gitlab/ui';
import eventHub from '~/invite_members/event_hub';
import { s__ } from '~/locale';
-import { ACTION_LABELS, ACTION_SECTIONS } from '../constants';
+import { getCookie, removeCookie, parseBoolean } from '~/lib/utils/common_utils';
+import { ACTION_LABELS, ACTION_SECTIONS, INVITE_MODAL_OPEN_COOKIE } from '../constants';
import LearnGitlabSectionCard from './learn_gitlab_section_card.vue';
export default {
@@ -26,7 +27,7 @@ export default {
required: true,
type: Object,
},
- inviteMembersOpen: {
+ inviteMembers: {
type: Boolean,
required: false,
default: false,
@@ -53,7 +54,7 @@ export default {
},
},
mounted() {
- if (this.inviteMembersOpen) {
+ if (this.inviteMembers && this.getCookieForInviteMembers()) {
this.openInviteMembersModal('celebrate');
}
@@ -63,8 +64,15 @@ export default {
eventHub.$off('showSuccessfulInvitationsAlert', this.handleShowSuccessfulInvitationsAlert);
},
methods: {
+ getCookieForInviteMembers() {
+ const value = parseBoolean(getCookie(INVITE_MODAL_OPEN_COOKIE));
+
+ removeCookie(INVITE_MODAL_OPEN_COOKIE);
+
+ return value;
+ },
openInviteMembersModal(mode) {
- eventHub.$emit('openModal', { mode, inviteeType: 'members', source: 'learn-gitlab' });
+ eventHub.$emit('openModal', { mode, source: 'learn-gitlab' });
},
handleShowSuccessfulInvitationsAlert() {
this.showSuccessfulInvitationsAlert = true;
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
index 3a401f5cb31..d0ec02bbd0c 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
@@ -31,14 +31,13 @@ export default {
this.action === 'userAdded' && isExperimentVariant('invite_for_help_continuous_onboarding')
);
},
+ openInNewTab() {
+ return ACTION_LABELS[this.action]?.openInNewTab === true;
+ },
},
methods: {
openModal() {
- eventHub.$emit('openModal', {
- inviteeType: 'members',
- source: 'learn_gitlab',
- tasksToBeDoneEnabled: true,
- });
+ eventHub.$emit('openModal', { source: 'learn_gitlab' });
},
},
};
@@ -61,8 +60,9 @@ export default {
</gl-link>
<gl-link
v-else
- target="_blank"
+ :target="openInNewTab ? '_blank' : '_self'"
:href="value.url"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
:data-track-label="$options.i18n.ACTION_LABELS[action].title"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
index 9e204aa6746..880cf699e5e 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
@@ -62,6 +62,7 @@ export const ACTION_LABELS = {
description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'),
section: 'deploy',
position: 1,
+ openInNewTab: true,
},
issueCreated: {
title: s__('LearnGitLab|Create an issue'),
@@ -94,3 +95,5 @@ export const ACTION_SECTIONS = {
),
},
};
+
+export const INVITE_MODAL_OPEN_COOKIE = 'confetti_post_signup';
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
index 1f91cc46946..c62cab1a425 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
import LearnGitlab from '../components/learn_gitlab.vue';
function initLearnGitlab() {
@@ -13,13 +13,13 @@ function initLearnGitlab() {
const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions));
const sections = convertObjectPropsToCamelCase(JSON.parse(el.dataset.sections));
const project = convertObjectPropsToCamelCase(JSON.parse(el.dataset.project));
- const { inviteMembersOpen } = el.dataset;
+ const { inviteMembers } = el.dataset;
return new Vue({
el,
render(createElement) {
return createElement(LearnGitlab, {
- props: { actions, sections, project, inviteMembersOpen },
+ props: { actions, sections, project, inviteMembers: parseBoolean(inviteMembers) },
});
},
});
diff --git a/app/assets/javascripts/pages/projects/new/index.js b/app/assets/javascripts/pages/projects/new/index.js
index 5d830872ed9..50733d8a145 100644
--- a/app/assets/javascripts/pages/projects/new/index.js
+++ b/app/assets/javascripts/pages/projects/new/index.js
@@ -1,4 +1,8 @@
-import { initNewProjectCreation, initNewProjectUrlSelect } from '~/projects/new';
+import {
+ initNewProjectCreation,
+ initNewProjectUrlSelect,
+ initDeploymentTargetSelect,
+} from '~/projects/new';
import initProjectVisibilitySelector from '~/projects/project_visibility';
import initProjectNew from '~/projects/project_new';
@@ -6,3 +10,4 @@ initProjectVisibilitySelector();
initProjectNew.bindEvents();
initNewProjectCreation();
initNewProjectUrlSelect();
+initDeploymentTargetSelect();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
index 42b08bcaa7b..ee70ff858be 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton } from '@gitlab/ui';
-import Cookies from 'js-cookie';
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
+
import Translate from '../../../../../vue_shared/translate';
Vue.use(Translate);
@@ -17,13 +17,13 @@ export default {
inject: ['docsUrl', 'illustrationUrl'],
data() {
return {
- calloutDismissed: parseBoolean(Cookies.get(cookieKey)),
+ calloutDismissed: parseBoolean(getCookie(cookieKey)),
};
},
methods: {
dismissCallout() {
this.calloutDismissed = true;
- Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
+ setCookie(cookieKey, this.calloutDismissed);
},
},
};
diff --git a/app/assets/javascripts/pages/projects/planning_hierarchy/index.js b/app/assets/javascripts/pages/projects/planning_hierarchy/index.js
new file mode 100644
index 00000000000..d5dfe2d5f37
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/planning_hierarchy/index.js
@@ -0,0 +1,3 @@
+import { initWorkItemsHierarchy } from '~/work_items_hierarchy/work_items_hierarchy_bundle';
+
+initWorkItemsHierarchy();
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index a26aeeb6db4..0c17bf2f344 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, no-return-assign */
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import initClonePanel from '~/clone_panel';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import createFlash from '~/flash';
@@ -24,19 +24,19 @@ export default class Project {
}
$('.js-hide-no-ssh-message').on('click', function (e) {
- Cookies.set('hide_no_ssh_message', 'false');
+ setCookie('hide_no_ssh_message', 'false');
$(this).parents('.js-no-ssh-key-message').remove();
return e.preventDefault();
});
$('.js-hide-no-password-message').on('click', function (e) {
- Cookies.set('hide_no_password_message', 'false');
+ setCookie('hide_no_password_message', 'false');
$(this).parents('.js-no-password-message').remove();
return e.preventDefault();
});
$('.hide-auto-devops-implicitly-enabled-banner').on('click', function (e) {
const projectId = $(this).data('project-id');
const cookieKey = `hide_auto_devops_implicitly_enabled_banner_${projectId}`;
- Cookies.set(cookieKey, 'false');
+ setCookie(cookieKey, 'false');
$(this).parents('.auto-devops-implicitly-enabled-banner').remove();
return e.preventDefault();
});
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index 947bbdacf2c..26c42247cf7 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -3,6 +3,7 @@ import initImportAProjectModal from '~/invite_members/init_import_a_project_moda
import initInviteGroupTrigger from '~/invite_members/init_invite_group_trigger';
import initInviteMembersForm from '~/invite_members/init_invite_members_form';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteGroupsModal from '~/invite_members/init_invite_groups_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { s__ } from '~/locale';
import memberExpirationDate from '~/member_expiration_date';
@@ -17,6 +18,7 @@ memberExpirationDate();
memberExpirationDate('.js-access-expiration-date-groups');
initImportAProjectModal();
initInviteMembersModal();
+initInviteGroupsModal();
initInviteMembersTrigger();
initInviteGroupTrigger();
diff --git a/app/assets/javascripts/pages/projects/security/configuration/index.js b/app/assets/javascripts/pages/projects/security/configuration/index.js
index 5f801501b2f..f13a48c1224 100644
--- a/app/assets/javascripts/pages/projects/security/configuration/index.js
+++ b/app/assets/javascripts/pages/projects/security/configuration/index.js
@@ -1,3 +1,3 @@
import { initSecurityConfiguration } from '~/security_configuration';
-initSecurityConfiguration(document.querySelector('#js-security-configuration-static'));
+initSecurityConfiguration(document.querySelector('#js-security-configuration'));
diff --git a/app/assets/javascripts/pages/projects/serverless/index.js b/app/assets/javascripts/pages/projects/serverless/index.js
index 640301dd478..9ae81b327b1 100644
--- a/app/assets/javascripts/pages/projects/serverless/index.js
+++ b/app/assets/javascripts/pages/projects/serverless/index.js
@@ -1,5 +1,3 @@
import ServerlessBundle from '~/serverless/serverless_bundle';
-import initServerlessSurveyBanner from '~/serverless/survey_banner';
-initServerlessSurveyBanner();
new ServerlessBundle(); // eslint-disable-line no-new
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 d5e00f54e91..184bda4410f 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
@@ -280,7 +280,7 @@ export default {
}
return s__(
- 'ProjectSettings|View and edit files in this project. Non-project members will only have read access.',
+ 'ProjectSettings|View and edit files in this project. Non-project members have only read access.',
);
},
cveIdRequestIsDisabled() {
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
index 58ceb524360..5cbb7a06bc1 100644
--- a/app/assets/javascripts/pages/users/index.js
+++ b/app/assets/javascripts/pages/users/index.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import UserCallout from '~/user_callout';
import UserTabs from './user_tabs';
@@ -10,7 +10,7 @@ function initUserProfile(action) {
// hide project limit message
$('.hide-project-limit-message').on('click', (e) => {
e.preventDefault();
- Cookies.set('hide_project_limit_message', 'false');
+ setCookie('hide_project_limit_message', 'false');
$(this).parents('.project-limit-message').remove();
});
}
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 ed30198244f..710f49b833c 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -124,6 +124,9 @@ export default {
const fileName = this.requests[0].truncatedUrl;
return `${fileName}_perf_bar_${Date.now()}.json`;
},
+ memoryReportPath() {
+ return mergeUrlParams({ performance_bar: 'memory' }, window.location.href);
+ },
},
mounted() {
this.currentRequest = this.requestId;
@@ -182,6 +185,15 @@ export default {
s__('PerformanceBar|Download')
}}</a>
</div>
+ <div
+ v-if="currentRequest.details && env === 'development'"
+ id="peek-memory-report"
+ class="view"
+ >
+ <a class="gl-text-blue-200" :href="memoryReportPath">{{
+ s__('PerformanceBar|Memory report')
+ }}</a>
+ </div>
<div v-if="currentRequest.details" id="peek-flamegraph" class="view">
<span class="gl-text-white-200">{{ s__('PerformanceBar|Flamegraph with mode:') }}</span>
<a class="gl-text-blue-200" :href="flamegraphPath('wall')">{{
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index 66e999ca43b..eb5b50dd1ec 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -20,6 +20,7 @@ const initPerformanceBar = (el) => {
return new Vue({
el,
+ name: 'PerformanceBarRoot',
components: {
PerformanceBarApp: () => import('./components/performance_bar_app.vue'),
},
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index bc83844b8b9..b003302ec8e 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -7,10 +7,11 @@ const DEFERRED_LINK_CLASS = 'deferred-link';
export default class PersistentUserCallout {
constructor(container, options = container.dataset) {
- const { dismissEndpoint, featureId, deferLinks } = options;
+ const { dismissEndpoint, featureId, groupId, deferLinks } = options;
this.container = container;
this.dismissEndpoint = dismissEndpoint;
this.featureId = featureId;
+ this.groupId = groupId;
this.deferLinks = parseBoolean(deferLinks);
this.init();
@@ -52,6 +53,7 @@ export default class PersistentUserCallout {
axios
.post(this.dismissEndpoint, {
feature_name: this.featureId,
+ group_id: this.groupId,
})
.then(() => {
this.container.remove();
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index a7f8704b559..337c204c36a 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -10,6 +10,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-new-user-signups-cap-reached',
'.js-eoa-bronze-plan-banner',
'.js-security-newsletter-callout',
+ '.js-approaching-seats-count-threshold',
];
const initCallouts = () => {
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 54c9688d88f..8ff1aea020f 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -1,11 +1,11 @@
<script>
-import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
import {
COMMIT_ACTION_CREATE,
COMMIT_ACTION_UPDATE,
COMMIT_FAILURE,
COMMIT_SUCCESS,
+ COMMIT_SUCCESS_WITH_REDIRECT,
} from '../../constants';
import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
import updateCurrentBranchMutation from '../../graphql/mutations/client/update_current_branch.mutation.graphql';
@@ -15,9 +15,6 @@ import getCurrentBranch from '../../graphql/queries/client/current_branch.query.
import CommitForm from './commit_form.vue';
-const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
-const MR_TARGET_BRANCH = 'merge_request[target_branch]';
-
export default {
alertTexts: {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
@@ -29,7 +26,7 @@ export default {
components: {
CommitForm,
},
- inject: ['projectFullPath', 'ciConfigPath', 'newMergeRequestPath'],
+ inject: ['projectFullPath', 'ciConfigPath'],
props: {
ciFileContent: {
type: String,
@@ -74,16 +71,6 @@ export default {
},
},
methods: {
- redirectToNewMergeRequest(sourceBranch) {
- const url = mergeUrlParams(
- {
- [MR_SOURCE_BRANCH]: sourceBranch,
- [MR_TARGET_BRANCH]: this.currentBranch,
- },
- this.newMergeRequestPath,
- );
- redirectTo(url);
- },
async onCommitSubmit({ message, targetBranch, openMergeRequest }) {
this.isSaving = true;
@@ -112,12 +99,25 @@ export default {
if (errors?.length) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
- } else if (openMergeRequest) {
- this.redirectToNewMergeRequest(targetBranch);
} else {
- this.$emit('commit', { type: COMMIT_SUCCESS });
+ const commitBranch = targetBranch;
+ const params = openMergeRequest
+ ? {
+ type: COMMIT_SUCCESS_WITH_REDIRECT,
+ params: {
+ sourceBranch: commitBranch,
+ targetBranch: this.currentBranch,
+ },
+ }
+ : { type: COMMIT_SUCCESS };
+
+ this.$emit('commit', {
+ ...params,
+ });
+
this.updateLastCommitBranch(targetBranch);
this.updateCurrentBranch(targetBranch);
+
if (this.currentBranch === targetBranch) {
this.$emit('updateCommitSha');
}
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 bfbf24c6b13..5177cea900c 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -5,6 +5,11 @@ import SourceEditor from '~/vue_shared/components/source_editor.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
+ editorOptions: {
+ // Quick suggestions is so that monaco can provide
+ // autocomplete for keywords
+ quickSuggestions: true,
+ },
components: {
SourceEditor,
},
@@ -29,6 +34,7 @@ export default {
<div class="gl-border-solid gl-border-gray-100 gl-border-1 gl-border-t-none!">
<source-editor
ref="editor"
+ :editor-options="$options.editorOptions"
:file-name="ciConfigPath"
v-bind="$attrs"
@[$options.readyEvent]="registerCiSchema($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 4f79a81d539..ead2076ec3b 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
@@ -9,7 +9,6 @@ import {
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 { __ } from '~/locale';
@@ -63,8 +62,6 @@ export default {
return {
availableBranches: [],
branchSelected: null,
- filteredBranches: [],
- isSearchingBranches: false,
pageLimit: this.paginationLimit,
pageCounter: 0,
searchTerm: '',
@@ -76,10 +73,9 @@ export default {
query: getAvailableBranchesQuery,
variables() {
return {
- limit: this.paginationLimit,
offset: 0,
projectFullPath: this.projectFullPath,
- searchPattern: '*',
+ ...this.availableBranchesVariables,
};
},
update(data) {
@@ -116,14 +112,24 @@ export default {
},
},
computed: {
- branches() {
- return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches;
+ availableBranchesVariables() {
+ if (this.searchTerm.length > 0) {
+ return {
+ limit: this.totalBranches,
+ searchPattern: `*${this.searchTerm}*`,
+ };
+ }
+
+ return {
+ limit: this.paginationLimit,
+ searchPattern: '*',
+ };
},
enableBranchSwitcher() {
- return this.branches.length > 0 || this.searchTerm.length > 0;
+ return this.availableBranches.length > 0 || this.searchTerm.length > 0;
},
isBranchesLoading() {
- return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
+ return this.$apollo.queries.availableBranches.loading;
},
},
watch: {
@@ -134,38 +140,21 @@ export default {
},
},
methods: {
- availableBranchesQueryVars(varsOverride = {}) {
- if (this.searchTerm.length > 0) {
- return {
- limit: this.totalBranches,
- offset: 0,
- projectFullPath: this.projectFullPath,
- searchPattern: `*${this.searchTerm}*`,
- ...varsOverride,
- };
- }
-
- return {
- limit: this.paginationLimit,
- offset: this.pageCounter * this.paginationLimit,
- projectFullPath: this.projectFullPath,
- searchPattern: '*',
- ...varsOverride,
- };
- },
// if there is no searchPattern, paginate by {paginationLimit} branches
fetchNextBranches() {
if (
this.isBranchesLoading ||
this.searchTerm.length > 0 ||
- this.branches.length >= this.totalBranches
+ this.availableBranches.length >= this.totalBranches
) {
return;
}
this.$apollo.queries.availableBranches
.fetchMore({
- variables: this.availableBranchesQueryVars(),
+ variables: {
+ offset: this.pageCounter * this.paginationLimit,
+ },
updateQuery(previousResult, { fetchMoreResult }) {
const previousBranches = previousResult.project.repository.branchNames;
const newBranches = fetchMoreResult.project.repository.branchNames;
@@ -204,23 +193,6 @@ export default {
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', {
@@ -255,14 +227,14 @@ export default {
</gl-dropdown-section-header>
<gl-infinite-scroll
- :fetched-items="branches.length"
+ :fetched-items="availableBranches.length"
:max-list-height="250"
data-qa-selector="branch_menu_container"
@bottomReached="fetchNextBranches"
>
<template #items>
<gl-dropdown-item
- v-for="branch in branches"
+ v-for="branch in availableBranches"
:key="branch"
:is-checked="currentBranch === branch"
:is-check-item="true"
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
index 72b492a5877..4b9c98135ec 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -49,7 +49,7 @@ export default {
pipelineEtag: {
query: getPipelineEtag,
update(data) {
- return data.etags.pipeline;
+ return data.etags?.pipeline;
},
},
pipeline: {
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
index 7206f19d060..c72cff4c6f8 100644
--- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
+++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
@@ -5,6 +5,7 @@ import { __, s__ } from '~/locale';
import {
COMMIT_FAILURE,
COMMIT_SUCCESS,
+ COMMIT_SUCCESS_WITH_REDIRECT,
DEFAULT_FAILURE,
DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN,
@@ -21,14 +22,18 @@ export default {
GlAlert,
CodeSnippetAlert,
},
- errorTexts: {
+
+ errors: {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
[PIPELINE_FAILURE]: s__('Pipelines|There was a problem with loading the pipeline data.'),
},
- successTexts: {
+ success: {
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
+ [COMMIT_SUCCESS_WITH_REDIRECT]: s__(
+ 'Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page.',
+ ),
[DEFAULT_SUCCESS]: __('Your action succeeded.'),
},
props: {
@@ -65,42 +70,20 @@ export default {
},
computed: {
failure() {
- switch (this.failureType) {
- case LOAD_FAILURE_UNKNOWN:
- return {
- text: this.$options.errorTexts[LOAD_FAILURE_UNKNOWN],
- variant: 'danger',
- };
- case COMMIT_FAILURE:
- return {
- text: this.$options.errorTexts[COMMIT_FAILURE],
- variant: 'danger',
- };
- case PIPELINE_FAILURE:
- return {
- text: this.$options.errorTexts[PIPELINE_FAILURE],
- variant: 'danger',
- };
- default:
- return {
- text: this.$options.errorTexts[DEFAULT_FAILURE],
- variant: 'danger',
- };
- }
+ const { errors } = this.$options;
+
+ return {
+ text: errors[this.failureType] ?? errors[DEFAULT_FAILURE],
+ variant: 'danger',
+ };
},
success() {
- switch (this.successType) {
- case COMMIT_SUCCESS:
- return {
- text: this.$options.successTexts[COMMIT_SUCCESS],
- variant: 'info',
- };
- default:
- return {
- text: this.$options.successTexts[DEFAULT_SUCCESS],
- variant: 'info',
- };
- }
+ const { success } = this.$options;
+
+ return {
+ text: success[this.successType] ?? success[DEFAULT_SUCCESS],
+ variant: 'info',
+ };
},
},
created() {
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index bc79b0742e7..a65463d02aa 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -20,6 +20,7 @@ export const EDITOR_APP_VALID_STATUSES = [
export const COMMIT_FAILURE = 'COMMIT_FAILURE';
export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
+export const COMMIT_SUCCESS_WITH_REDIRECT = 'COMMIT_SUCCESS_WITH_REDIRECT';
export const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
export const DEFAULT_SUCCESS = 'DEFAULT_SUCCESS';
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 90f48195c5e..1da50c55a68 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon, GlModal } from '@gitlab/ui';
import { fetchPolicies } from '~/lib/graphql';
-import { queryToObject } from '~/lib/utils/url_utility';
+import { mergeUrlParams, queryToObject, redirectTo } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
@@ -11,6 +11,7 @@ import PipelineEditorEmptyState from './components/ui/pipeline_editor_empty_stat
import PipelineEditorMessages from './components/ui/pipeline_editor_messages.vue';
import {
COMMIT_SHA_POLL_INTERVAL,
+ COMMIT_SUCCESS_WITH_REDIRECT,
EDITOR_APP_STATUS_EMPTY,
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_LINT_UNAVAILABLE,
@@ -27,6 +28,9 @@ import getTemplate from './graphql/queries/get_starter_template.query.graphql';
import getLatestCommitShaQuery from './graphql/queries/latest_commit_sha.query.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
+const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
+const MR_TARGET_BRANCH = 'merge_request[target_branch]';
+
export default {
components: {
ConfirmUnsavedChangesDialog,
@@ -36,14 +40,7 @@ export default {
PipelineEditorHome,
PipelineEditorMessages,
},
- inject: {
- ciConfigPath: {
- default: '',
- },
- projectFullPath: {
- default: '',
- },
- },
+ inject: ['ciConfigPath', 'newMergeRequestPath', 'projectFullPath'],
data() {
return {
ciConfigData: {},
@@ -57,7 +54,7 @@ export default {
lastCommittedContent: '',
shouldSkipStartScreen: false,
showFailure: false,
- showResetComfirmationModal: false,
+ showResetConfirmationModal: false,
showStartScreen: false,
showSuccess: false,
starterTemplate: '',
@@ -199,7 +196,7 @@ export default {
currentBranch: {
query: getCurrentBranch,
update(data) {
- return data.workBranches.current.name;
+ return data.workBranches?.current?.name;
},
},
starterTemplate: {
@@ -217,7 +214,7 @@ export default {
return data.project?.ciTemplate?.content || '';
},
result({ data }) {
- this.updateCiConfig(data.project?.ciTemplate?.content || '');
+ this.updateCiConfig(data?.project?.ciTemplate?.content || '');
},
error() {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
@@ -271,17 +268,39 @@ export default {
this.checkShouldSkipStartScreen();
},
methods: {
+ checkShouldSkipStartScreen() {
+ const params = queryToObject(window.location.search);
+ this.shouldSkipStartScreen = Boolean(params?.add_new_config_file);
+ },
+ confirmReset() {
+ if (this.hasUnsavedChanges) {
+ this.showResetConfirmationModal = true;
+ }
+ },
hideFailure() {
this.showFailure = false;
},
hideSuccess() {
this.showSuccess = false;
},
- confirmReset() {
- if (this.hasUnsavedChanges) {
- this.showResetComfirmationModal = true;
+ loadTemplateFromURL() {
+ const templateName = queryToObject(window.location.search)?.template;
+
+ if (templateName) {
+ this.starterTemplateName = templateName;
+ this.setNewEmptyCiConfigFile();
}
},
+ redirectToNewMergeRequest(sourceBranch, targetBranch) {
+ const url = mergeUrlParams(
+ {
+ [MR_SOURCE_BRANCH]: sourceBranch,
+ [MR_TARGET_BRANCH]: targetBranch,
+ },
+ this.newMergeRequestPath,
+ );
+ redirectTo(url);
+ },
async refetchContent() {
this.$apollo.queries.initialCiFileContent.skip = false;
await this.$apollo.queries.initialCiFileContent.refetch();
@@ -298,7 +317,7 @@ export default {
this.successType = type;
},
resetContent() {
- this.showResetComfirmationModal = false;
+ this.showResetConfirmationModal = false;
this.currentCiFileContent = this.lastCommittedContent;
},
setAppStatus(appStatus) {
@@ -323,7 +342,7 @@ export default {
this.isFetchingCommitSha = true;
this.$apollo.queries.commitSha.refetch();
},
- updateOnCommit({ type }) {
+ async updateOnCommit({ type, params = {} }) {
this.reportSuccess(type);
if (this.isNewCiConfigFile) {
@@ -333,19 +352,17 @@ export default {
// 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;
- },
- loadTemplateFromURL() {
- const templateName = queryToObject(window.location.search)?.template;
- if (templateName) {
- this.starterTemplateName = templateName;
- this.setNewEmptyCiConfigFile();
+ if (type === COMMIT_SUCCESS_WITH_REDIRECT) {
+ const { sourceBranch, targetBranch } = params;
+ // This force update does 2 things for us:
+ // 1. It make sure `hasUnsavedChanges` is updated so
+ // we don't show a modal when the user creates an MR
+ // 2. Ensure the commit success banner is visible.
+ await this.$forceUpdate();
+ this.redirectToNewMergeRequest(sourceBranch, targetBranch);
}
},
- checkShouldSkipStartScreen() {
- const params = queryToObject(window.location.search);
- this.shouldSkipStartScreen = Boolean(params?.add_new_config_file);
- },
},
};
</script>
@@ -358,7 +375,7 @@ export default {
@createEmptyConfigFile="setNewEmptyCiConfigFile"
@refetchContent="refetchContent"
/>
- <div v-else>
+ <div v-else class="gl-pr-10">
<pipeline-editor-messages
:failure-type="failureType"
:failure-reasons="failureReasons"
@@ -382,7 +399,7 @@ export default {
@updateCommitSha="updateCommitSha"
/>
<gl-modal
- v-model="showResetComfirmationModal"
+ v-model="showResetConfirmationModal"
modal-id="reset-content"
:title="$options.i18n.resetModal.title"
:action-cancel="$options.i18n.resetModal.actionCancel"
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
index 96680080f0c..bb759477e1e 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -90,7 +90,7 @@ export default {
</script>
<template>
- <div class="gl-pr-10 gl-transition-medium gl-w-full">
+ <div class="gl-transition-medium gl-w-full">
<gl-modal
v-if="showSwitchBranchModal"
visible
diff --git a/app/assets/javascripts/pipeline_new/constants.js b/app/assets/javascripts/pipeline_new/constants.js
index a6c9f3cb746..43f7634083b 100644
--- a/app/assets/javascripts/pipeline_new/constants.js
+++ b/app/assets/javascripts/pipeline_new/constants.js
@@ -1,3 +1,4 @@
+import { __ } from '~/locale';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
export const VARIABLE_TYPE = 'env_var';
@@ -7,5 +8,7 @@ export const CONFIG_VARIABLES_TIMEOUT = 5000;
export const BRANCH_REF_TYPE = 'branch';
export const TAG_REF_TYPE = 'tag';
-export const CC_VALIDATION_REQUIRED_ERROR =
- 'Credit card required to be on file in order to create a pipeline';
+// must match pipeline/chain/validate/after_config.rb
+export const CC_VALIDATION_REQUIRED_ERROR = __(
+ 'Credit card required to be on file in order to create a pipeline',
+);
diff --git a/app/assets/javascripts/pipeline_wizard/components/commit.vue b/app/assets/javascripts/pipeline_wizard/components/commit.vue
new file mode 100644
index 00000000000..518b41c66b1
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/components/commit.vue
@@ -0,0 +1,224 @@
+<script>
+import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormTextarea } from '@gitlab/ui';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { __, s__, sprintf } from '~/locale';
+import createCommitMutation from '../queries/create_commit.graphql';
+import getFileMetaDataQuery from '../queries/get_file_meta.graphql';
+import StepNav from './step_nav.vue';
+
+export const i18n = {
+ updateFileHeading: s__('PipelineWizard|Commit changes to your file'),
+ createFileHeading: s__('PipelineWizard|Commit your new file'),
+ fieldRequiredFeedback: __('This field is required'),
+ commitMessageLabel: s__('PipelineWizard|Commit Message'),
+ branchSelectorLabel: s__('PipelineWizard|Commit file to Branch'),
+ defaultUpdateCommitMessage: s__('PipelineWizardDefaultCommitMessage|Update %{filename}'),
+ defaultCreateCommitMessage: s__('PipelineWizardDefaultCommitMessage|Add %{filename}'),
+ commitButtonLabel: s__('PipelineWizard|Commit'),
+ commitSuccessMessage: s__('PipelineWizard|The file has been committed.'),
+ errors: {
+ loadError: s__(
+ 'PipelineWizard|There was a problem while checking whether your file already exists in the specified branch.',
+ ),
+ commitError: s__('PipelineWizard|There was a problem committing the changes.'),
+ },
+};
+
+const COMMIT_ACTION = {
+ CREATE: 'CREATE',
+ UPDATE: 'UPDATE',
+};
+
+export default {
+ i18n,
+ name: 'PipelineWizardCommitStep',
+ components: {
+ RefSelector,
+ GlAlert,
+ GlButton,
+ GlForm,
+ GlFormGroup,
+ GlFormTextarea,
+ StepNav,
+ },
+ props: {
+ prev: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ defaultBranch: {
+ type: String,
+ required: true,
+ },
+ fileContent: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ filename: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ branch: this.defaultBranch,
+ loading: false,
+ loadError: null,
+ commitError: null,
+ message: null,
+ };
+ },
+ computed: {
+ fileExistsInRepo() {
+ return this.project?.repository?.blobs.nodes.length > 0;
+ },
+ commitAction() {
+ return this.fileExistsInRepo ? COMMIT_ACTION.UPDATE : COMMIT_ACTION.CREATE;
+ },
+ defaultMessage() {
+ return sprintf(
+ this.fileExistsInRepo
+ ? this.$options.i18n.defaultUpdateCommitMessage
+ : this.$options.i18n.defaultCreateCommitMessage,
+ { filename: this.filename },
+ );
+ },
+ isCommitButtonEnabled() {
+ return this.fileExistsCheckInProgress;
+ },
+ fileExistsCheckInProgress() {
+ return this.$apollo.queries.project.loading;
+ },
+ mutationPayload() {
+ return {
+ mutation: createCommitMutation,
+ variables: {
+ input: {
+ projectPath: this.projectPath,
+ branch: this.branch,
+ message: this.message || this.defaultMessage,
+ actions: [
+ {
+ action: this.commitAction,
+ filePath: `/${this.filename}`,
+ content: this.fileContent,
+ },
+ ],
+ },
+ },
+ };
+ },
+ },
+ apollo: {
+ project: {
+ query: getFileMetaDataQuery,
+ variables() {
+ this.loadError = null;
+ return {
+ fullPath: this.projectPath,
+ filePath: this.filename,
+ ref: this.branch,
+ };
+ },
+ error() {
+ this.loadError = this.$options.i18n.errors.loadError;
+ },
+ },
+ },
+ methods: {
+ async commit() {
+ this.loading = true;
+ try {
+ const { data } = await this.$apollo.mutate(this.mutationPayload);
+ const hasError = Boolean(data.commitCreate.errors?.length);
+ if (hasError) {
+ this.commitError = this.$options.i18n.errors.commitError;
+ } else {
+ this.handleCommitSuccess();
+ }
+ } catch (e) {
+ this.commitError = this.$options.i18n.errors.commitError;
+ } finally {
+ this.loading = false;
+ }
+ },
+ handleCommitSuccess() {
+ this.$toast.show(this.$options.i18n.commitSuccessMessage);
+ this.$emit('done');
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h4 v-if="fileExistsInRepo" key="create-heading">
+ {{ $options.i18n.updateFileHeading }}
+ </h4>
+ <h4 v-else key="update-heading">
+ {{ $options.i18n.createFileHeading }}
+ </h4>
+ <gl-alert
+ v-if="!!loadError"
+ :dismissible="false"
+ class="gl-mb-5"
+ data-testid="load-error"
+ variant="danger"
+ >
+ {{ loadError }}
+ </gl-alert>
+ <gl-form class="gl-max-w-48">
+ <gl-form-group
+ :invalid-feedback="$options.i18n.fieldRequiredFeedback"
+ :label="$options.i18n.commitMessageLabel"
+ data-testid="commit_message_group"
+ label-for="commit_message"
+ >
+ <gl-form-textarea
+ id="commit_message"
+ v-model="message"
+ :placeholder="defaultMessage"
+ data-testid="commit_message"
+ size="md"
+ @input="(v) => $emit('update:message', v)"
+ />
+ </gl-form-group>
+ <gl-form-group
+ :invalid-feedback="$options.i18n.fieldRequiredFeedback"
+ :label="$options.i18n.branchSelectorLabel"
+ data-testid="branch_selector_group"
+ label-for="branch"
+ >
+ <ref-selector id="branch" v-model="branch" data-testid="branch" :project-id="projectPath" />
+ </gl-form-group>
+ <gl-alert
+ v-if="!!commitError"
+ :dismissible="false"
+ class="gl-mb-5"
+ data-testid="commit-error"
+ variant="danger"
+ >
+ {{ commitError }}
+ </gl-alert>
+ <step-nav show-back-button v-bind="$props" @back="$emit('go-back')">
+ <template #after>
+ <gl-button
+ :disabled="isCommitButtonEnabled"
+ :loading="fileExistsCheckInProgress || loading"
+ category="primary"
+ variant="confirm"
+ @click="commit"
+ >
+ {{ $options.i18n.commitButtonLabel }}
+ </gl-button>
+ </template>
+ </step-nav>
+ </gl-form>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_wizard/components/editor.vue b/app/assets/javascripts/pipeline_wizard/components/editor.vue
new file mode 100644
index 00000000000..41611233f71
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/components/editor.vue
@@ -0,0 +1,94 @@
+<script>
+import { debounce } from 'lodash';
+import { isDocument } from 'yaml';
+import { CONTENT_UPDATE_DEBOUNCE } from '~/editor/constants';
+import SourceEditor from '~/editor/source_editor';
+import { YamlEditorExtension } from '~/editor/extensions/source_editor_yaml_ext';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
+
+export default {
+ name: 'YamlEditor',
+ props: {
+ doc: {
+ type: Object,
+ required: true,
+ validator: (d) => isDocument(d),
+ },
+ highlight: {
+ type: [String, Array],
+ required: false,
+ default: null,
+ },
+ filename: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ editor: null,
+ isUpdating: false,
+ yamlEditorExtension: null,
+ };
+ },
+ watch: {
+ doc: {
+ handler() {
+ this.updateEditorContent();
+ },
+ deep: true,
+ },
+ highlight(v) {
+ this.requestHighlight(v);
+ },
+ },
+ mounted() {
+ this.editor = new SourceEditor().createInstance({
+ el: this.$el,
+ blobPath: this.filename,
+ language: 'yaml',
+ });
+ [, this.yamlEditorExtension] = this.editor.use([
+ { definition: SourceEditorExtension },
+ {
+ definition: YamlEditorExtension,
+ setupOptions: {
+ highlightPath: this.highlight,
+ },
+ },
+ ]);
+ this.editor.onDidChangeModelContent(
+ debounce(() => this.handleChange(), CONTENT_UPDATE_DEBOUNCE),
+ );
+ this.updateEditorContent();
+ this.emitValue();
+ },
+ methods: {
+ async updateEditorContent() {
+ this.isUpdating = true;
+ this.editor.setDoc(this.doc);
+ this.isUpdating = false;
+ this.requestHighlight(this.highlight);
+ },
+ handleChange() {
+ this.emitValue();
+ if (!this.isUpdating) {
+ this.handleTouch();
+ }
+ },
+ emitValue() {
+ this.$emit('update:yaml', this.editor.getValue());
+ },
+ handleTouch() {
+ this.$emit('touch');
+ },
+ requestHighlight(path) {
+ this.editor.highlight(path, true);
+ },
+ },
+};
+</script>
+
+<template>
+ <div id="source-editor-yaml-editor"></div>
+</template>
diff --git a/app/assets/javascripts/pipeline_wizard/components/step_nav.vue b/app/assets/javascripts/pipeline_wizard/components/step_nav.vue
new file mode 100644
index 00000000000..8f9198855c6
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/components/step_nav.vue
@@ -0,0 +1,54 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+
+export default {
+ name: 'StepNav',
+ components: {
+ GlButton,
+ },
+ props: {
+ showBackButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showNextButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ nextButtonEnabled: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <slot name="before"></slot>
+ <gl-button
+ v-if="showBackButton"
+ category="secondary"
+ data-testid="back-button"
+ @click="$emit('back')"
+ >
+ {{ __('Back') }}
+ </gl-button>
+ <gl-button
+ v-if="showNextButton"
+ :disabled="!nextButtonEnabled"
+ category="primary"
+ data-testid="next-button"
+ variant="confirm"
+ @click="$emit('next')"
+ >
+ {{ __('Next') }}
+ </gl-button>
+ <slot name="after"></slot>
+ </div>
+</template>
+
+<style scoped></style>
diff --git a/app/assets/javascripts/pipeline_wizard/components/widgets/text.vue b/app/assets/javascripts/pipeline_wizard/components/widgets/text.vue
new file mode 100644
index 00000000000..26235b20ce9
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/components/widgets/text.vue
@@ -0,0 +1,126 @@
+<script>
+import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { s__ } from '~/locale';
+
+const VALIDATION_STATE = {
+ NO_VALIDATION: null,
+ INVALID: false,
+ VALID: true,
+};
+
+export default {
+ name: 'TextWidget',
+ components: {
+ GlFormGroup,
+ GlFormInput,
+ },
+ props: {
+ label: {
+ type: String,
+ required: true,
+ },
+ description: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ placeholder: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ invalidFeedback: {
+ type: String,
+ required: false,
+ default: s__('PipelineWizardInputValidation|This value is not valid'),
+ },
+ id: {
+ type: String,
+ required: false,
+ default: () => uniqueId('textWidget-'),
+ },
+ pattern: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ validate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ required: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ default: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ touched: false,
+ value: this.default,
+ };
+ },
+ computed: {
+ validationState() {
+ if (!this.showValidationState) return VALIDATION_STATE.NO_VALIDATION;
+ if (this.isRequiredButEmpty) return VALIDATION_STATE.INVALID;
+ return this.needsValidationAndPasses ? VALIDATION_STATE.VALID : VALIDATION_STATE.INVALID;
+ },
+ showValidationState() {
+ return this.touched || this.validate;
+ },
+ isRequiredButEmpty() {
+ return this.required && !this.value;
+ },
+ needsValidationAndPasses() {
+ return !this.pattern || new RegExp(this.pattern).test(this.value);
+ },
+ invalidFeedbackMessage() {
+ return this.isRequiredButEmpty
+ ? s__('PipelineWizardInputValidation|This field is required')
+ : this.invalidFeedback;
+ },
+ },
+ watch: {
+ validationState(v) {
+ this.$emit('update:valid', v);
+ },
+ value(v) {
+ this.$emit('input', v.trim());
+ },
+ },
+ created() {
+ if (this.default) {
+ this.$emit('input', this.value);
+ }
+ },
+};
+</script>
+
+<template>
+ <div data-testid="text-widget">
+ <gl-form-group
+ :description="description"
+ :invalid-feedback="invalidFeedbackMessage"
+ :label="label"
+ :label-for="id"
+ :state="validationState"
+ >
+ <gl-form-input
+ :id="id"
+ v-model="value"
+ :placeholder="placeholder"
+ :state="validationState"
+ type="text"
+ @blur="touched = true"
+ />
+ </gl-form-group>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_wizard/queries/create_commit.graphql b/app/assets/javascripts/pipeline_wizard/queries/create_commit.graphql
new file mode 100644
index 00000000000..9abf8eff587
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/queries/create_commit.graphql
@@ -0,0 +1,9 @@
+mutation CreateCommit($input: CommitCreateInput!) {
+ commitCreate(input: $input) {
+ commit {
+ id
+ }
+ content
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipeline_wizard/queries/get_file_meta.graphql b/app/assets/javascripts/pipeline_wizard/queries/get_file_meta.graphql
new file mode 100644
index 00000000000..87f014fade6
--- /dev/null
+++ b/app/assets/javascripts/pipeline_wizard/queries/get_file_meta.graphql
@@ -0,0 +1,12 @@
+query GetFileMetadata($fullPath: ID!, $filePath: String!, $ref: String) {
+ project(fullPath: $fullPath) {
+ id
+ repository {
+ blobs(paths: [$filePath], ref: $ref) {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index 12c3f9a7f40..795ba91a164 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -59,7 +59,11 @@ export default {
</script>
<template>
<!-- eslint-disable @gitlab/vue-no-data-toggle -->
- <div :id="computedJobId" class="ci-job-dropdown-container dropdown dropright">
+ <div
+ :id="computedJobId"
+ class="ci-job-dropdown-container dropdown dropright"
+ data-qa-selector="job_dropdown_container"
+ >
<button
type="button"
data-toggle="dropdown"
@@ -79,7 +83,10 @@ export default {
</div>
</button>
- <ul class="dropdown-menu big-pipeline-graph-dropdown-menu js-grouped-pipeline-dropdown">
+ <ul
+ class="dropdown-menu big-pipeline-graph-dropdown-menu js-grouped-pipeline-dropdown"
+ data-qa-selector="jobs_dropdown_menu"
+ >
<li class="scrollable-menu">
<ul>
<li v-for="job in group.jobs" :key="job.id">
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index ee58dcc4882..795b95421c7 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -2,7 +2,7 @@
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
-import { sprintf } from '~/locale';
+import { sprintf, __ } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { reportToSentry } from '../../utils';
import ActionComponent from '../jobs_shared/action_component.vue';
@@ -160,6 +160,21 @@ export default {
hasAction() {
return this.job.status && this.job.status.action && this.job.status.action.path;
},
+ hasUnauthorizedManualAction() {
+ return (
+ !this.hasAction &&
+ this.job.status?.group === 'manual' &&
+ this.job.status?.label?.includes('(not allowed)')
+ );
+ },
+ unauthorizedManualActionIcon() {
+ /*
+ The action object is not available when the user cannot run the action.
+ So we can show the correct icon, extract the action name from the label instead:
+ "manual play action (not allowed)" or "manual stop action (not allowed)"
+ */
+ return this.job.status?.label?.split(' ')[1];
+ },
relatedDownstreamHovered() {
return this.job.name === this.sourceJobHovered;
},
@@ -198,6 +213,9 @@ export default {
this.$emit('pipelineActionRequestComplete');
},
},
+ i18n: {
+ unauthorizedTooltip: __('You are not authorized to run this manual job'),
+ },
};
</script>
<template>
@@ -242,8 +260,16 @@ export default {
:link="status.action.path"
:action-icon="status.action.icon"
class="gl-mr-1"
- data-qa-selector="action_button"
+ data-qa-selector="job_action_button"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
+ <action-component
+ v-if="hasUnauthorizedManualAction"
+ disabled
+ :tooltip-text="$options.i18n.unauthorizedTooltip"
+ :action-icon="unauthorizedManualActionIcon"
+ :link="`unauthorized-${computedJobId}`"
+ class="gl-mr-1"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index e0c1dcc5be5..c59f56fc68f 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon, GlBadge } from '@gitlab/ui';
+import { GlBadge, GlButton, GlLink, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
@@ -12,10 +12,10 @@ export default {
},
components: {
CiStatus,
+ GlBadge,
GlButton,
GlLink,
GlLoadingIcon,
- GlBadge,
},
props: {
columnTitle: {
@@ -26,6 +26,10 @@ export default {
type: Boolean,
required: true,
},
+ isLoading: {
+ type: Boolean,
+ required: true,
+ },
pipeline: {
type: Object,
required: true,
@@ -34,33 +38,40 @@ export default {
type: String,
required: true,
},
- isLoading: {
- type: Boolean,
- required: true,
- },
},
computed: {
- tooltipText() {
- return `${this.downstreamTitle} #${this.pipeline.id} - ${this.pipelineStatus.label} -
- ${this.sourceJobInfo}`;
+ buttonBorderClass() {
+ return this.isUpstream ? 'gl-border-r-1!' : 'gl-border-l-1!';
},
buttonId() {
return `js-linked-pipeline-${this.pipeline.id}`;
},
- pipelineStatus() {
- return this.pipeline.status;
+ cardSpacingClass() {
+ return this.isDownstream ? 'gl-pr-0' : '';
},
- projectName() {
- return this.pipeline.project.name;
+ expandedIcon() {
+ if (this.isUpstream) {
+ return this.expanded ? 'angle-right' : 'angle-left';
+ }
+ return this.expanded ? 'angle-left' : 'angle-right';
+ },
+ childPipeline() {
+ return this.isDownstream && this.isSameProject;
},
downstreamTitle() {
return this.childPipeline ? this.sourceJobName : this.pipeline.project.name;
},
- parentPipeline() {
- return this.isUpstream && this.isSameProject;
+ flexDirection() {
+ return this.isUpstream ? 'gl-flex-direction-row-reverse' : 'gl-flex-direction-row';
},
- childPipeline() {
- return this.isDownstream && this.isSameProject;
+ isDownstream() {
+ return this.type === DOWNSTREAM;
+ },
+ isSameProject() {
+ return !this.pipeline.multiproject;
+ },
+ isUpstream() {
+ return this.type === UPSTREAM;
},
label() {
if (this.parentPipeline) {
@@ -70,17 +81,17 @@ export default {
}
return __('Multi-project');
},
+ parentPipeline() {
+ return this.isUpstream && this.isSameProject;
+ },
pipelineIsLoading() {
return Boolean(this.isLoading || this.pipeline.isLoading);
},
- isDownstream() {
- return this.type === DOWNSTREAM;
- },
- isUpstream() {
- return this.type === UPSTREAM;
+ pipelineStatus() {
+ return this.pipeline.status;
},
- isSameProject() {
- return !this.pipeline.multiproject;
+ projectName() {
+ return this.pipeline.project.name;
},
sourceJobName() {
return this.pipeline.sourceJob?.name ?? '';
@@ -88,28 +99,23 @@ export default {
sourceJobInfo() {
return this.isDownstream ? sprintf(__('Created by %{job}'), { job: this.sourceJobName }) : '';
},
- expandedIcon() {
- if (this.isUpstream) {
- return this.expanded ? 'angle-right' : 'angle-left';
- }
- return this.expanded ? 'angle-left' : 'angle-right';
- },
- expandButtonPosition() {
- return this.isUpstream ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!';
+ tooltipText() {
+ return `${this.downstreamTitle} #${this.pipeline.id} - ${this.pipelineStatus.label} -
+ ${this.sourceJobInfo}`;
},
},
errorCaptured(err, _vm, info) {
reportToSentry('linked_pipeline', `error: ${err}, info: ${info}`);
},
methods: {
+ hideTooltips() {
+ this.$root.$emit(BV_HIDE_TOOLTIP);
+ },
onClickLinkedPipeline() {
this.hideTooltips();
this.$emit('pipelineClicked', this.$refs.linkedPipeline);
this.$emit('pipelineExpandToggle', this.sourceJobName, !this.expanded);
},
- hideTooltips() {
- this.$root.$emit(BV_HIDE_TOOLTIP);
- },
onDownstreamHovered() {
this.$emit('downstreamHovered', this.sourceJobName);
},
@@ -124,27 +130,23 @@ export default {
<div
ref="linkedPipeline"
v-gl-tooltip
- class="gl-downstream-pipeline-job-width"
+ class="gl-h-full gl-display-flex! gl-border-solid gl-border-gray-100 gl-border-1"
+ :class="flexDirection"
:title="tooltipText"
data-qa-selector="child_pipeline"
@mouseover="onDownstreamHovered"
@mouseleave="onDownstreamHoverLeave"
>
- <div
- class="gl-relative gl-bg-white gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1"
- :class="{ 'gl-pl-9': isUpstream }"
- >
- <div class="gl-display-flex gl-pr-7 gl-pipeline-job-width">
+ <div class="gl-w-full gl-bg-white gl-p-3" :class="cardSpacingClass">
+ <div class="gl-display-flex gl-pr-3">
<ci-status
v-if="!pipelineIsLoading"
:status="pipelineStatus"
:size="24"
css-classes="gl-top-0 gl-pr-2"
/>
- <div v-else class="gl-pr-2"><gl-loading-icon size="sm" inline /></div>
- <div
- class="gl-display-flex gl-flex-direction-column gl-pipeline-job-width gl-text-truncate"
- >
+ <div v-else class="gl-pr-3"><gl-loading-icon size="sm" inline /></div>
+ <div class="gl-display-flex gl-flex-direction-column gl-downstream-pipeline-job-width">
<span class="gl-text-truncate" data-testid="downstream-title">
{{ downstreamTitle }}
</span>
@@ -160,10 +162,12 @@ export default {
{{ label }}
</gl-badge>
</div>
+ </div>
+ <div class="gl-display-flex">
<gl-button
:id="buttonId"
- class="gl-absolute gl-top-0 gl-bottom-0 gl-shadow-none! gl-rounded-0!"
- :class="`js-pipeline-expand-${pipeline.id} ${expandButtonPosition}`"
+ class="gl-shadow-none! gl-rounded-0!"
+ :class="`js-pipeline-expand-${pipeline.id} ${buttonBorderClass}`"
:icon="expandedIcon"
:aria-label="__('Expand pipeline')"
data-testid="expand-pipeline-button"
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index 8088858f381..6a4d1bb44f2 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -1,9 +1,22 @@
<script>
-import { GlAlert, GlButton, GlLoadingIcon, GlModal, GlModalDirective } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlButton,
+ GlLoadingIcon,
+ GlModal,
+ GlModalDirective,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import ciHeader from '~/vue_shared/components/header_ci_component.vue';
-import { LOAD_FAILURE, POST_FAILURE, DELETE_FAILURE, DEFAULT } from '../constants';
+import {
+ LOAD_FAILURE,
+ POST_FAILURE,
+ DELETE_FAILURE,
+ DEFAULT,
+ BUTTON_TOOLTIP_RETRY,
+} from '../constants';
import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutation.graphql';
import deletePipelineMutation from '../graphql/mutations/delete_pipeline.mutation.graphql';
import retryPipelineMutation from '../graphql/mutations/retry_pipeline.mutation.graphql';
@@ -15,6 +28,7 @@ const POLL_INTERVAL = 10000;
export default {
name: 'PipelineHeaderSection',
+ BUTTON_TOOLTIP_RETRY,
pipelineCancel: 'pipelineCancel',
pipelineRetry: 'pipelineRetry',
finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
@@ -27,6 +41,7 @@ export default {
},
directives: {
GlModal: GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
errorTexts: {
[LOAD_FAILURE]: __('We are currently unable to fetch data for the pipeline header.'),
@@ -225,6 +240,9 @@ export default {
>
<gl-button
v-if="canRetryPipeline"
+ v-gl-tooltip
+ :aria-label="$options.BUTTON_TOOLTIP_RETRY"
+ :title="$options.BUTTON_TOOLTIP_RETRY"
:loading="isRetrying"
:disabled="isRetrying"
category="secondary"
diff --git a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
index e11073aee33..99fb5c146ba 100644
--- a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
+++ b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
@@ -36,10 +36,13 @@ export default {
return data.project?.pipeline?.jobs?.nodes || [];
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.jobsPageInfo = data.project?.pipeline?.jobs?.pageInfo || {};
},
error() {
- createFlash({ message: __('An error occured while fetching the pipelines jobs.') });
+ createFlash({ message: __('An error occurred while fetching the pipelines jobs.') });
},
},
},
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 efad43ddd4f..ca2537ca4f4 100644
--- a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
@@ -92,14 +92,20 @@ export default {
<template>
<gl-button
:id="`js-ci-action-${link}`"
- v-gl-tooltip="{ boundary: 'viewport' }"
- :title="tooltipText"
:class="cssClass"
:disabled="isDisabled"
class="js-ci-action gl-ci-action-icon-container ci-action-icon-container ci-action-icon-wrapper gl-display-flex gl-align-items-center gl-justify-content-center"
+ data-testid="ci-action-component"
@click.stop="onClickAction"
>
- <gl-loading-icon v-if="isLoading" size="sm" class="js-action-icon-loading" />
- <gl-icon v-else :name="actionIcon" class="gl-mr-0!" :aria-label="actionIcon" />
+ <div
+ v-gl-tooltip.viewport
+ :title="tooltipText"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-h-full"
+ data-testid="ci-action-icon-tooltip-wrapper"
+ >
+ <gl-loading-icon v-if="isLoading" size="sm" class="js-action-icon-loading" />
+ <gl-icon v-else :name="actionIcon" class="gl-mr-0!" :aria-label="actionIcon" />
+ </div>
</gl-button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/notification/deprecated_type_keyword_notification.vue b/app/assets/javascripts/pipelines/components/notification/deprecated_type_keyword_notification.vue
new file mode 100644
index 00000000000..b8f9f84c217
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/notification/deprecated_type_keyword_notification.vue
@@ -0,0 +1,102 @@
+<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import getPipelineWarnings from '../../graphql/queries/get_pipeline_warnings.query.graphql';
+
+export default {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ expectedMessage: 'will be removed in',
+ i18n: {
+ title: __('Found warning in your .gitlab-ci.yml'),
+ rootTypesWarning: __(
+ '%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}',
+ ),
+ typeWarning: __(
+ '%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}',
+ ),
+ },
+ components: {
+ GlAlert,
+ GlLink,
+ GlSprintf,
+ },
+ inject: ['deprecatedKeywordsDocPath', 'fullPath', 'pipelineIid'],
+ apollo: {
+ warnings: {
+ query: getPipelineWarnings,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.pipelineIid,
+ };
+ },
+ update(data) {
+ return data?.project?.pipeline?.warningMessages || [];
+ },
+ error() {
+ this.hasError = true;
+ },
+ },
+ },
+ data() {
+ return {
+ warnings: [],
+ hasError: false,
+ };
+ },
+ computed: {
+ deprecationWarnings() {
+ return this.warnings.filter(({ content }) => {
+ return content.includes(this.$options.expectedMessage);
+ });
+ },
+ formattedWarnings() {
+ // The API doesn't have a mechanism currently to return a
+ // type instead of just the error message. To work around this,
+ // we check if the deprecation message is found within the warnings
+ // and show a FE version of that message with the link to the documentation
+ // and translated. We can have only 2 types of warnings: root types and individual
+ // type. If the word `root` is present, then we know it's the root type deprecation
+ // and if not, it's the normal type. This has to be deleted in 15.0.
+ // Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/350810
+ return this.deprecationWarnings.map(({ content }) => {
+ if (content.includes('root')) {
+ return this.$options.i18n.rootTypesWarning;
+ }
+ return this.$options.i18n.typeWarning;
+ });
+ },
+ hasDeprecationWarning() {
+ return this.formattedWarnings.length > 0;
+ },
+ showWarning() {
+ return (
+ !this.$apollo.queries.warnings?.loading && !this.hasError && this.hasDeprecationWarning
+ );
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-alert
+ v-if="showWarning"
+ :title="$options.i18n.title"
+ variant="warning"
+ :dismissible="false"
+ >
+ <ul class="gl-mb-0">
+ <li v-for="warning in formattedWarnings" :key="warning">
+ <gl-sprintf :message="warning">
+ <template #code="{ content }">
+ <code> {{ content }}</code>
+ </template>
+ <template #link="{ content }">
+ <gl-link :href="deprecatedKeywordsDocPath" target="_blank"> {{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </li>
+ </ul>
+ </gl-alert>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
index b6c178d20b0..fa0e153b2af 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
@@ -1,15 +1,13 @@
<script>
import { GlButton, GlTooltipDirective, GlModalDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
import eventHub from '../../event_hub';
+import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL } from '../../constants';
import PipelineMultiActions from './pipeline_multi_actions.vue';
import PipelinesManualActions from './pipelines_manual_actions.vue';
export default {
- i18n: {
- cancelTitle: __('Cancel'),
- redeployTitle: __('Retry'),
- },
+ BUTTON_TOOLTIP_RETRY,
+ BUTTON_TOOLTIP_CANCEL,
directives: {
GlTooltip: GlTooltipDirective,
GlModalDirective,
@@ -75,12 +73,13 @@ export default {
<gl-button
v-if="pipeline.flags.retryable"
v-gl-tooltip.hover
- :aria-label="$options.i18n.redeployTitle"
- :title="$options.i18n.redeployTitle"
+ :aria-label="$options.BUTTON_TOOLTIP_RETRY"
+ :title="$options.BUTTON_TOOLTIP_RETRY"
:disabled="isRetrying"
:loading="isRetrying"
class="js-pipelines-retry-button"
data-qa-selector="pipeline_retry_button"
+ data-testid="pipelines-retry-button"
icon="repeat"
variant="default"
category="secondary"
@@ -91,14 +90,15 @@ export default {
v-if="pipeline.flags.cancelable"
v-gl-tooltip.hover
v-gl-modal-directive="'confirmation-modal'"
- :aria-label="$options.i18n.cancelTitle"
- :title="$options.i18n.cancelTitle"
+ :aria-label="$options.BUTTON_TOOLTIP_CANCEL"
+ :title="$options.BUTTON_TOOLTIP_CANCEL"
:loading="isCancelling"
:disabled="isCancelling"
icon="cancel"
variant="danger"
category="primary"
class="js-pipelines-cancel-button gl-ml-1"
+ data-testid="pipelines-cancel-button"
@click="handleCancelClick"
/>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
index 0528e4c147c..b29c8426301 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
@@ -26,7 +26,7 @@ export default {
v-if="user"
:link-href="user.path"
:img-src="user.avatar_url"
- :img-size="26"
+ :img-size="32"
:tooltip-text="user.name"
class="gl-ml-3 js-pipeline-url-user"
/>
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 e2f30d5a8e6..52da4d01468 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -1,15 +1,19 @@
<script>
-import { GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
+import { GlIcon, GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { SCHEDULE_ORIGIN } from '../../constants';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import { SCHEDULE_ORIGIN, ICONS } from '../../constants';
export default {
components: {
+ GlIcon,
GlLink,
GlPopover,
GlSprintf,
GlBadge,
+ TooltipOnTruncate,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -33,11 +37,12 @@ export default {
type: String,
required: true,
},
+ viewType: {
+ type: String,
+ required: true,
+ },
},
computed: {
- user() {
- return this.pipeline.user;
- },
isScheduled() {
return this.pipeline.source === SCHEDULE_ORIGIN;
},
@@ -53,12 +58,160 @@ export default {
autoDevopsHelpPath() {
return helpPagePath('topics/autodevops/index.md');
},
+ mergeRequestRef() {
+ return this.pipeline?.merge_request;
+ },
+ commitRef() {
+ return this.pipeline?.ref;
+ },
+ commitTag() {
+ return this.commitRef?.tag;
+ },
+ commitUrl() {
+ return this.pipeline?.commit?.commit_path;
+ },
+ commitShortSha() {
+ return this.pipeline?.commit?.short_id;
+ },
+ refUrl() {
+ return this.commitRef?.ref_url || this.commitRef?.path;
+ },
+ tooltipTitle() {
+ return this.mergeRequestRef?.title || this.commitRef?.name;
+ },
+ commitAuthor() {
+ let commitAuthorInformation;
+ const pipelineCommit = this.pipeline?.commit;
+ const pipelineCommitAuthor = pipelineCommit?.author;
+
+ if (!pipelineCommit) {
+ return null;
+ }
+
+ // 1. person who is an author of a commit might be a GitLab user
+ if (pipelineCommitAuthor) {
+ // 2. if person who is an author of a commit is a GitLab user
+ // they can have a GitLab avatar
+ if (pipelineCommitAuthor?.avatar_url) {
+ commitAuthorInformation = pipelineCommitAuthor;
+
+ // 3. If GitLab user does not have avatar, they might have a Gravatar
+ } else if (pipelineCommit.author_gravatar_url) {
+ commitAuthorInformation = {
+ ...pipelineCommitAuthor,
+ avatar_url: pipelineCommit.author_gravatar_url,
+ };
+ }
+ // 4. If committer is not a GitLab User, they can have a Gravatar
+ } else {
+ commitAuthorInformation = {
+ avatar_url: pipelineCommit.author_gravatar_url,
+ path: `mailto:${pipelineCommit.author_email}`,
+ username: pipelineCommit.author_name,
+ };
+ }
+
+ return commitAuthorInformation;
+ },
+ commitIcon() {
+ let name = '';
+
+ if (this.commitTag) {
+ name = ICONS.TAG;
+ } else if (this.mergeRequestRef) {
+ name = ICONS.MR;
+ } else {
+ name = ICONS.BRANCH;
+ }
+
+ return name;
+ },
+ commitIconTooltipTitle() {
+ switch (this.commitIcon) {
+ case ICONS.TAG:
+ return __('Tag');
+ case ICONS.MR:
+ return __('Merge Request');
+ default:
+ return __('Branch');
+ }
+ },
+ commitTitleText() {
+ return this.pipeline?.commit?.title || __("Can't find HEAD commit for this branch");
+ },
+ hasAuthor() {
+ return (
+ this.commitAuthor?.avatar_url && this.commitAuthor?.path && this.commitAuthor?.username
+ );
+ },
+ userImageAltDescription() {
+ return this.commitAuthor?.username
+ ? sprintf(__("%{username}'s avatar"), { username: this.commitAuthor.username })
+ : null;
+ },
+ rearrangePipelinesTable() {
+ return this.glFeatures?.rearrangePipelinesTable;
+ },
},
};
</script>
<template>
<div class="pipeline-tags" data-testid="pipeline-url-table-cell">
+ <template v-if="rearrangePipelinesTable">
+ <div class="commit-title gl-mb-2" data-testid="commit-title-container">
+ <span class="gl-display-flex">
+ <tooltip-on-truncate :title="commitTitleText" class="flex-truncate-child gl-flex-grow-1">
+ <gl-link
+ :href="pipeline.path"
+ class="commit-row-message gl-text-blue-600!"
+ data-testid="commit-title"
+ data-qa-selector="pipeline_url_link"
+ >{{ commitTitleText }}</gl-link
+ >
+ </tooltip-on-truncate>
+ </span>
+ </div>
+ <div class="gl-mb-2">
+ <span class="gl-font-weight-bold gl-text-gray-500" data-testid="pipeline-identifier">
+ #{{ pipeline[pipelineKey] }}
+ </span>
+ <!--Commit row-->
+ <div class="icon-container gl-display-inline-block">
+ <gl-icon
+ v-gl-tooltip
+ :name="commitIcon"
+ :title="commitIconTooltipTitle"
+ data-testid="commit-icon-type"
+ />
+ </div>
+ <tooltip-on-truncate :title="tooltipTitle" truncate-target="child" placement="top">
+ <gl-link
+ v-if="mergeRequestRef"
+ :href="mergeRequestRef.path"
+ class="ref-name"
+ data-testid="merge-request-ref"
+ >{{ mergeRequestRef.iid }}</gl-link
+ >
+ <gl-link v-else :href="refUrl" class="ref-name" data-testid="commit-ref-name">{{
+ commitRef.name
+ }}</gl-link>
+ </tooltip-on-truncate>
+ <gl-icon
+ v-gl-tooltip
+ name="commit"
+ class="commit-icon"
+ :title="__('Commit')"
+ data-testid="commit-icon"
+ />
+
+ <gl-link :href="commitUrl" class="commit-sha mr-0" data-testid="commit-short-sha">{{
+ commitShortSha
+ }}</gl-link>
+ <!--End of commit row-->
+ </div>
+ </template>
<gl-link
+ v-if="!rearrangePipelinesTable"
:href="pipeline.path"
class="gl-text-decoration-underline"
data-testid="pipeline-url-link"
@@ -66,7 +219,7 @@ export default {
>
#{{ pipeline[pipelineKey] }}
</gl-link>
- <div class="label-container">
+ <div class="label-container gl-mt-1">
<gl-badge
v-if="isScheduled"
v-gl-tooltip
@@ -163,7 +316,7 @@ export default {
v-gl-tooltip
:title="
__(
- 'Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.',
+ 'Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines.',
)
"
variant="info"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
index b94f1a42039..47fffa8a6b2 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
@@ -2,6 +2,7 @@
import { GlDropdown, GlDropdownItem, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { s__, __, sprintf } from '~/locale';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import eventHub from '../../event_hub';
@@ -28,7 +29,7 @@ export default {
};
},
methods: {
- onClickAction(action) {
+ async onClickAction(action) {
if (action.scheduled_at) {
const confirmationMessage = sprintf(
s__(
@@ -36,9 +37,10 @@ export default {
),
{ jobName: action.name },
);
- // https://gitlab.com/gitlab-org/gitlab-foss/issues/52156
- // eslint-disable-next-line no-alert
- if (!window.confirm(confirmationMessage)) {
+
+ const confirmed = await confirmAction(confirmationMessage);
+
+ if (!confirmed) {
return;
}
}
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
index f56457a4162..54901c2d13f 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
@@ -3,12 +3,16 @@ import CodeQualityWalkthrough from '~/code_quality_walkthrough/components/step.v
import { PIPELINE_STATUSES } from '~/code_quality_walkthrough/constants';
import { CHILD_VIEW } from '~/pipelines/constants';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import PipelinesTimeago from './time_ago.vue';
export default {
components: {
CodeQualityWalkthrough,
CiBadge,
+ PipelinesTimeago,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
pipeline: {
type: Object,
@@ -40,6 +44,9 @@ export default {
codeQualityBuildPath() {
return this.pipeline?.details?.code_quality_build_path;
},
+ rearrangePipelinesTable() {
+ return this.glFeatures?.rearrangePipelinesTable;
+ },
},
};
</script>
@@ -48,11 +55,13 @@ export default {
<div>
<ci-badge
id="js-code-quality-walkthrough"
+ class="gl-mb-3"
:status="pipelineStatus"
:show-text="!isChildView"
:icon-classes="'gl-vertical-align-middle!'"
data-qa-selector="pipeline_commit_status"
/>
+ <pipelines-timeago v-if="rearrangePipelinesTable" class="gl-mt-3" :pipeline="pipeline" />
<code-quality-walkthrough
v-if="shouldRenderCodeQualityWalkthrough"
:step="codeQualityStep"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
index d64decc81ec..9919a18cb99 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -1,6 +1,7 @@
<script>
import { GlTableLite, GlTooltipDirective } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
import PipelineMiniGraph from './pipeline_mini_graph.vue';
import PipelineOperations from './pipeline_operations.vue';
@@ -33,6 +34,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagMixin()],
props: {
pipelines: {
type: Array,
@@ -72,16 +74,18 @@ export default {
key: 'status',
label: s__('Pipeline|Status'),
thClass: DEFAULT_TH_CLASSES,
- columnClass: 'gl-w-10p',
+ columnClass: this.rearrangePipelinesTable ? 'gl-w-15p' : 'gl-w-10p',
tdClass: DEFAULT_TD_CLASS,
thAttr: { 'data-testid': 'status-th' },
},
{
key: 'pipeline',
- label: this.pipelineKeyOption.label,
+ label: this.rearrangePipelinesTable ? __('Pipeline') : this.pipelineKeyOption.label,
thClass: DEFAULT_TH_CLASSES,
- tdClass: `${DEFAULT_TD_CLASS} ${HIDE_TD_ON_MOBILE}`,
- columnClass: 'gl-w-10p',
+ tdClass: this.rearrangePipelinesTable
+ ? `${DEFAULT_TD_CLASS}`
+ : `${DEFAULT_TD_CLASS} ${HIDE_TD_ON_MOBILE}`,
+ columnClass: this.rearrangePipelinesTable ? 'gl-w-30p' : 'gl-w-10p',
thAttr: { 'data-testid': 'pipeline-th' },
},
{
@@ -113,7 +117,7 @@ export default {
label: s__('Pipeline|Duration'),
thClass: DEFAULT_TH_CLASSES,
tdClass: DEFAULT_TD_CLASS,
- columnClass: 'gl-w-15p',
+ columnClass: this.rearrangePipelinesTable ? 'gl-w-5p' : 'gl-w-15p',
thAttr: { 'data-testid': 'timeago-th' },
},
{
@@ -124,7 +128,13 @@ export default {
thAttr: { 'data-testid': 'actions-th' },
},
];
- return fields;
+
+ return !this.rearrangePipelinesTable
+ ? fields
+ : fields.filter((field) => !['commit', 'timeago'].includes(field.key));
+ },
+ rearrangePipelinesTable() {
+ return this.glFeatures?.rearrangePipelinesTable;
},
},
watch: {
@@ -182,6 +192,7 @@ export default {
:pipeline="item"
:pipeline-schedule-url="pipelineScheduleUrl"
:pipeline-key="pipelineKeyOption.key"
+ :view-type="viewType"
/>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
index e6b03751350..c45e3f24567 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -54,11 +54,14 @@ export default {
showSkipped() {
return !this.duration && !this.finishedTime && this.skipped;
},
+ shouldDisplayAsBlock() {
+ return this.glFeatures?.rearrangePipelinesTable;
+ },
},
};
</script>
<template>
- <div>
+ <div class="{ 'gl-display-block': shouldDisplayAsBlock }">
<span v-if="showInProgress" data-testid="pipeline-in-progress">
<gl-icon v-if="stuck" name="warning" class="gl-mr-2" :size="12" data-testid="warning-icon" />
<gl-icon
@@ -87,6 +90,7 @@ export default {
<time
v-gl-tooltip
:title="tooltipTitle(finishedTime)"
+ :datetime="finishedTime"
data-placement="top"
data-container="body"
>
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 410fc7b82cd..36f708ff2af 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -10,6 +10,12 @@ export const SCHEDULE_ORIGIN = 'schedule';
export const NEEDS_PROPERTY = 'needs';
export const EXPLICIT_NEEDS_PROPERTY = 'previousStageJobsOrNeeds';
+export const ICONS = {
+ TAG: 'tag',
+ MR: 'git-merge',
+ BRANCH: 'branch',
+};
+
export const TestStatus = {
FAILED: 'failed',
SKIPPED: 'skipped',
@@ -53,3 +59,6 @@ export const PipelineKeyOptions = [
];
export const TOAST_MESSAGE = s__('Pipeline|Creating pipeline.');
+
+export const BUTTON_TOOLTIP_RETRY = __('Retry failed jobs');
+export const BUTTON_TOOLTIP_CANCEL = __('Cancel');
diff --git a/app/assets/javascripts/pipelines/graphql/fragmentTypes.json b/app/assets/javascripts/pipelines/graphql/fragmentTypes.json
deleted file mode 100644
index 4601b74b5c1..00000000000
--- a/app/assets/javascripts/pipelines/graphql/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"UNION","name":"JobNeedUnion","possibleTypes":[{"name":"CiBuildNeed"},{"name":"CiJob"}]}]}} \ No newline at end of file
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_warnings.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_warnings.query.graphql
new file mode 100644
index 00000000000..cd1d2b62a3d
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_warnings.query.graphql
@@ -0,0 +1,12 @@
+query getPipelineWarnings($fullPath: ID!, $iid: ID!) {
+ project(fullPath: $fullPath) {
+ id
+ pipeline(iid: $iid) {
+ id
+ warningMessages {
+ content
+ id
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index 3201f88a9e3..c4f7665c91d 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -1,6 +1,7 @@
import Visibility from 'visibilityjs';
import createFlash from '~/flash';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import { validateParams } from '~/pipelines/utils';
@@ -195,11 +196,20 @@ export default {
this.$toast.show(TOAST_MESSAGE);
this.updateTable();
})
- .catch(() => {
+ .catch((e) => {
+ const unauthorized = e.response.status === httpStatusCodes.UNAUTHORIZED;
+ const badRequest = e.response.status === httpStatusCodes.BAD_REQUEST;
+
+ let errorMessage = __(
+ 'An error occurred while trying to run a new pipeline for this merge request.',
+ );
+
+ if (unauthorized || badRequest) {
+ errorMessage = __('You do not have permission to run a pipeline on this branch.');
+ }
+
createFlash({
- message: __(
- 'An error occurred while trying to run a new pipeline for this merge request.',
- ),
+ message: errorMessage,
});
})
.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 ae8b2503c79..bfb95e5ab0c 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -3,6 +3,7 @@ import { __ } from '~/locale';
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 { createPipelineJobsApp } from './pipeline_details_jobs';
import { apolloProvider } from './pipeline_shared_client';
import { createTestDetails } from './pipeline_test_details';
@@ -11,6 +12,7 @@ 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',
PIPELINE_JOBS: '#js-pipeline-jobs-vue',
};
@@ -43,6 +45,14 @@ export default async function initPipelineDetailsBundle() {
}
try {
+ createPipelineNotificationApp(SELECTORS.PIPELINE_NOTIFICATION, apolloProvider);
+ } catch {
+ createFlash({
+ message: __('An error occurred while loading a section of this page.'),
+ });
+ }
+
+ try {
createDagApp(apolloProvider);
} catch {
createFlash({
diff --git a/app/assets/javascripts/pipelines/pipeline_details_notification.js b/app/assets/javascripts/pipelines/pipeline_details_notification.js
new file mode 100644
index 00000000000..0061be843c5
--- /dev/null
+++ b/app/assets/javascripts/pipelines/pipeline_details_notification.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import DeprecatedKeywordNotification from './components/notification/deprecated_type_keyword_notification.vue';
+
+Vue.use(VueApollo);
+
+export const createPipelineNotificationApp = (elSelector, apolloProvider) => {
+ const el = document.querySelector(elSelector);
+
+ if (!el) {
+ return;
+ }
+
+ const { deprecatedKeywordsDocPath, fullPath, pipelineIid } = el?.dataset;
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ components: {
+ DeprecatedKeywordNotification,
+ },
+ provide: {
+ deprecatedKeywordsDocPath,
+ fullPath,
+ pipelineIid,
+ },
+ apolloProvider,
+ render(createElement) {
+ return createElement('deprecated-keyword-notification');
+ },
+ });
+};
diff --git a/app/assets/javascripts/pipelines/pipeline_shared_client.js b/app/assets/javascripts/pipelines/pipeline_shared_client.js
index 84276588d6a..c3be487caae 100644
--- a/app/assets/javascripts/pipelines/pipeline_shared_client.js
+++ b/app/assets/javascripts/pipelines/pipeline_shared_client.js
@@ -1,19 +1,10 @@
import VueApollo from 'vue-apollo';
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql';
-import introspectionQueryResultData from './graphql/fragmentTypes.json';
-
-export const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
export const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
- cacheConfig: {
- fragmentMatcher,
- },
useGet: true,
},
),
diff --git a/app/assets/javascripts/popovers/index.js b/app/assets/javascripts/popovers/index.js
index 7db669b8c52..94340ae16a0 100644
--- a/app/assets/javascripts/popovers/index.js
+++ b/app/assets/javascripts/popovers/index.js
@@ -13,7 +13,7 @@ const getPopoversApp = () => {
document.body.appendChild(container);
const Popovers = Vue.extend(PopoversComponent);
- app = new Popovers();
+ app = new Popovers({ name: 'PopoversRoot' });
app.$mount(`#${APP_ELEMENT_ID}`);
}
diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue
index eaf93e2da4f..924b6f55db4 100644
--- a/app/assets/javascripts/projects/components/project_delete_button.vue
+++ b/app/assets/javascripts/projects/components/project_delete_button.vue
@@ -1,12 +1,8 @@
<script>
-import { GlAlert, GlSprintf } from '@gitlab/ui';
-import { __ } from '~/locale';
import SharedDeleteButton from './shared/delete_button.vue';
export default {
components: {
- GlSprintf,
- GlAlert,
SharedDeleteButton,
},
props: {
@@ -39,66 +35,17 @@ export default {
required: true,
},
},
- strings: {
- alertTitle: __('You are about to permanently delete this project'),
- alertBody: __(
- 'After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc.',
- ),
- isNotForkMessage: __(
- 'This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:',
- ),
- isForkMessage: __('This forked project has the following:'),
- },
};
</script>
<template>
- <shared-delete-button v-bind="{ confirmPhrase, formPath }">
- <template #modal-body>
- <gl-alert
- class="gl-mb-5"
- variant="danger"
- :title="$options.strings.alertTitle"
- :dismissible="false"
- >
- <p>
- <gl-sprintf v-if="isFork" :message="$options.strings.isForkMessage" />
- <gl-sprintf v-else :message="$options.strings.isNotForkMessage">
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </p>
- <ul>
- <li>
- <gl-sprintf :message="n__('%d issue', '%d issues', issuesCount)">
- <template #issuesCount>{{ issuesCount }}</template>
- </gl-sprintf>
- </li>
- <li>
- <gl-sprintf
- :message="n__('%d merge requests', '%d merge requests', mergeRequestsCount)"
- >
- <template #mergeRequestsCount>{{ mergeRequestsCount }}</template>
- </gl-sprintf>
- </li>
- <li>
- <gl-sprintf :message="n__('%d fork', '%d forks', forksCount)">
- <template #forksCount>{{ forksCount }}</template>
- </gl-sprintf>
- </li>
- <li>
- <gl-sprintf :message="n__('%d star', '%d stars', starsCount)">
- <template #starsCount>{{ starsCount }}</template>
- </gl-sprintf>
- </li>
- </ul>
- <gl-sprintf :message="$options.strings.alertBody">
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </gl-alert>
- </template>
- </shared-delete-button>
+ <shared-delete-button
+ :confirm-phrase="confirmPhrase"
+ :form-path="formPath"
+ :is-fork="isFork"
+ :issues-count="issuesCount"
+ :merge-requests-count="mergeRequestsCount"
+ :forks-count="forksCount"
+ :stars-count="starsCount"
+ />
</template>
diff --git a/app/assets/javascripts/projects/components/shared/delete_button.vue b/app/assets/javascripts/projects/components/shared/delete_button.vue
index 2e46f437ace..fd71a246a26 100644
--- a/app/assets/javascripts/projects/components/shared/delete_button.vue
+++ b/app/assets/javascripts/projects/components/shared/delete_button.vue
@@ -1,14 +1,16 @@
<script>
-import { GlModal, GlModalDirective, GlFormInput, GlButton } from '@gitlab/ui';
+import { GlModal, GlModalDirective, GlFormInput, GlButton, GlAlert, GlSprintf } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
export default {
components: {
+ GlAlert,
GlModal,
GlFormInput,
GlButton,
+ GlSprintf,
},
directives: {
GlModal: GlModalDirective,
@@ -22,6 +24,26 @@ export default {
type: String,
required: true,
},
+ isFork: {
+ type: Boolean,
+ required: true,
+ },
+ issuesCount: {
+ type: Number,
+ required: true,
+ },
+ mergeRequestsCount: {
+ type: Number,
+ required: true,
+ },
+ forksCount: {
+ type: Number,
+ required: true,
+ },
+ starsCount: {
+ type: Number,
+ required: true,
+ },
},
data() {
return {
@@ -55,8 +77,17 @@ export default {
},
strings: {
deleteProject: __('Delete project'),
- title: __('Delete project. Are you ABSOLUTELY SURE?'),
- confirmText: __('Please type the following to confirm:'),
+ title: __('Are you absolutely sure?'),
+ confirmText: __('Enter the following to confirm:'),
+ isForkAlertTitle: __('You are about to delete this forked project containing:'),
+ isNotForkAlertTitle: __('You are about to delete this project containing:'),
+ isForkAlertBody: __('This process deletes the project repository and all related resources.'),
+ isNotForkAlertBody: __(
+ 'This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources.',
+ ),
+ isNotForkMessage: __(
+ 'This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:',
+ ),
},
};
</script>
@@ -83,7 +114,52 @@ export default {
>
<template #modal-title>{{ $options.strings.title }}</template>
<div>
- <slot name="modal-body"></slot>
+ <gl-alert class="gl-mb-5" variant="danger" :dismissible="false">
+ <h4 v-if="isFork" data-testid="delete-alert-title" class="gl-alert-title">
+ {{ $options.strings.isForkAlertTitle }}
+ </h4>
+ <h4 v-else data-testid="delete-alert-title" class="gl-alert-title">
+ {{ $options.strings.isNotForkAlertTitle }}
+ </h4>
+ <ul>
+ <li>
+ <gl-sprintf :message="n__('%d issue', '%d issues', issuesCount)">
+ <template #issuesCount>{{ issuesCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf
+ :message="n__('%d merge requests', '%d merge requests', mergeRequestsCount)"
+ >
+ <template #mergeRequestsCount>{{ mergeRequestsCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf :message="n__('%d fork', '%d forks', forksCount)">
+ <template #forksCount>{{ forksCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf :message="n__('%d star', '%d stars', starsCount)">
+ <template #starsCount>{{ starsCount }}</template>
+ </gl-sprintf>
+ </li>
+ </ul>
+ <gl-sprintf
+ v-if="isFork"
+ data-testid="delete-alert-body"
+ :message="$options.strings.isForkAlertBody"
+ />
+ <gl-sprintf
+ v-else
+ data-testid="delete-alert-body"
+ :message="$options.strings.isNotForkAlertBody"
+ >
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
<p class="gl-mb-1">{{ $options.strings.confirmText }}</p>
<p>
<code class="gl-white-space-pre-wrap">{{ confirmPhrase }}</code>
diff --git a/app/assets/javascripts/projects/new/components/deployment_target_select.vue b/app/assets/javascripts/projects/new/components/deployment_target_select.vue
new file mode 100644
index 00000000000..f3b7e39f148
--- /dev/null
+++ b/app/assets/javascripts/projects/new/components/deployment_target_select.vue
@@ -0,0 +1,61 @@
+<script>
+import { GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+import {
+ DEPLOYMENT_TARGET_SELECTIONS,
+ DEPLOYMENT_TARGET_LABEL,
+ DEPLOYMENT_TARGET_EVENT,
+ NEW_PROJECT_FORM,
+} from '../constants';
+
+const trackingMixin = Tracking.mixin({ label: DEPLOYMENT_TARGET_LABEL });
+
+export default {
+ i18n: {
+ deploymentTargetLabel: s__('Deployment Target|Project deployment target (optional)'),
+ defaultOption: s__('Deployment Target|Select the deployment target'),
+ },
+ deploymentTargets: DEPLOYMENT_TARGET_SELECTIONS,
+ selectId: 'deployment-target-select',
+ components: {
+ GlFormGroup,
+ GlFormSelect,
+ },
+ mixins: [trackingMixin],
+ data() {
+ return {
+ selectedTarget: null,
+ formSubmitted: false,
+ };
+ },
+ mounted() {
+ const form = document.getElementById(NEW_PROJECT_FORM);
+ form.addEventListener('submit', () => {
+ this.formSubmitted = true;
+ this.trackSelection();
+ });
+ },
+ methods: {
+ trackSelection() {
+ if (this.formSubmitted && this.selectedTarget) {
+ this.track(DEPLOYMENT_TARGET_EVENT, { property: this.selectedTarget });
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group :label="$options.i18n.deploymentTargetLabel" :label-for="$options.selectId">
+ <gl-form-select
+ :id="$options.selectId"
+ v-model="selectedTarget"
+ :options="$options.deploymentTargets"
+ >
+ <template #first>
+ <option :value="null" disabled>{{ $options.i18n.defaultOption }}</option>
+ </template>
+ </gl-form-select>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/projects/new/constants.js b/app/assets/javascripts/projects/new/constants.js
new file mode 100644
index 00000000000..c5e6722981b
--- /dev/null
+++ b/app/assets/javascripts/projects/new/constants.js
@@ -0,0 +1,20 @@
+import { s__ } from '~/locale';
+
+export const DEPLOYMENT_TARGET_SELECTIONS = [
+ s__('DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)'),
+ s__('DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)'),
+ s__('DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)'),
+ s__('DeploymentTarget|Heroku'),
+ s__('DeploymentTarget|Virtual machine (for example, EC2)'),
+ s__('DeploymentTarget|Mobile app store'),
+ s__('DeploymentTarget|Registry (package or container)'),
+ s__('DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)'),
+ s__('DeploymentTarget|Serverless backend (Lambda, Cloud functions)'),
+ s__('DeploymentTarget|GitLab Pages'),
+ s__('DeploymentTarget|Other hosting service'),
+ s__('DeploymentTarget|No deployment planned'),
+];
+
+export const NEW_PROJECT_FORM = 'new_project';
+export const DEPLOYMENT_TARGET_LABEL = 'new_project_deployment_target';
+export const DEPLOYMENT_TARGET_EVENT = 'select_deployment_target';
diff --git a/app/assets/javascripts/projects/new/index.js b/app/assets/javascripts/projects/new/index.js
index 010c6a29ae3..4de9b8a6f47 100644
--- a/app/assets/javascripts/projects/new/index.js
+++ b/app/assets/javascripts/projects/new/index.js
@@ -4,6 +4,7 @@ import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import NewProjectCreationApp from './components/app.vue';
import NewProjectUrlSelect from './components/new_project_url_select.vue';
+import DeploymentTargetSelect from './components/deployment_target_select.vue';
export function initNewProjectCreation() {
const el = document.querySelector('.js-new-project-creation');
@@ -64,3 +65,16 @@ export function initNewProjectUrlSelect() {
}),
);
}
+
+export function initDeploymentTargetSelect() {
+ const el = document.querySelector('.js-deployment-target-select');
+
+ if (!el) {
+ return null;
+ }
+
+ return new Vue({
+ el,
+ render: (createElement) => createElement(DeploymentTargetSelect),
+ });
+}
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index 8d71a3dab68..62e2cec874a 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -1,6 +1,8 @@
import $ from 'jquery';
import { debounce } from 'lodash';
import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../lib/utils/constants';
import axios from '../lib/utils/axios_utils';
import {
convertToTitleCase,
@@ -13,20 +15,26 @@ let hasUserDefinedProjectPath = false;
let hasUserDefinedProjectName = false;
const invalidInputClass = 'gl-field-error-outline';
+const cancelSource = axios.CancelToken.source();
+const endpoint = `${gon.relative_url_root}/import/url/validate`;
+let importCredentialsValidationPromise = null;
const validateImportCredentials = (url, user, password) => {
- const endpoint = `${gon.relative_url_root}/import/url/validate`;
- return axios
- .post(endpoint, {
- url,
- user,
- password,
- })
+ cancelSource.cancel();
+ importCredentialsValidationPromise = axios
+ .post(endpoint, { url, user, password }, { cancelToken: cancelSource.cancel() })
.then(({ data }) => data)
- .catch(() => ({
- // intentionally reporting success in case of validation error
- // we do not want to block users from trying import in case of validation exception
- success: true,
- }));
+ .catch((thrown) =>
+ axios.isCancel(thrown)
+ ? {
+ cancelled: true,
+ }
+ : {
+ // intentionally reporting success in case of validation error
+ // we do not want to block users from trying import in case of validation exception
+ success: true,
+ },
+ );
+ return importCredentialsValidationPromise;
};
const onProjectNameChange = ($projectNameInput, $projectPathInput) => {
@@ -72,7 +80,7 @@ const deriveProjectPathFromUrl = ($projectImportUrl) => {
.parents('.toggle-import-form')
.find('#project_path');
- if (hasUserDefinedProjectPath) {
+ if (hasUserDefinedProjectPath || $currentProjectPath.length === 0) {
return;
}
@@ -98,6 +106,21 @@ const deriveProjectPathFromUrl = ($projectImportUrl) => {
};
const bindHowToImport = () => {
+ const importLinks = document.querySelectorAll('.js-how-to-import-link');
+
+ importLinks.forEach((link) => {
+ const { modalTitle: title, modalMessage: modalHtmlMessage } = link.dataset;
+
+ link.addEventListener('click', (e) => {
+ e.preventDefault();
+ confirmAction('', {
+ modalHtmlMessage,
+ title,
+ hideCancel: true,
+ });
+ });
+ });
+
$('.how_to_import_link').on('click', (e) => {
e.preventDefault();
$(e.currentTarget).next('.modal').show();
@@ -114,7 +137,7 @@ const bindEvents = () => {
const $projectImportUrlUser = $('#project_import_url_user');
const $projectImportUrlPassword = $('#project_import_url_password');
const $projectImportUrlError = $('.js-import-url-error');
- const $projectImportForm = $('.project-import form');
+ const $projectImportForm = $('form.js-project-import');
const $projectPath = $('.tab-pane.active #project_path');
const $useTemplateBtn = $('.template-button > input');
const $projectFieldsForm = $('.project-fields-form');
@@ -124,7 +147,7 @@ const bindEvents = () => {
const $projectTemplateButtons = $('.project-templates-buttons');
const $projectName = $('.tab-pane.active #project_name');
- if ($newProjectForm.length !== 1) {
+ if ($newProjectForm.length !== 1 && $projectImportForm.length !== 1) {
return;
}
@@ -168,20 +191,28 @@ const bindEvents = () => {
$projectPath.val($projectPath.val().trim());
});
- const updateUrlPathWarningVisibility = debounce(async () => {
- const { success: isUrlValid } = await validateImportCredentials(
+ const updateUrlPathWarningVisibility = async () => {
+ const { success: isUrlValid, cancelled } = await validateImportCredentials(
$projectImportUrl.val(),
$projectImportUrlUser.val(),
$projectImportUrlPassword.val(),
);
+ if (cancelled) {
+ return;
+ }
+
$projectImportUrl.toggleClass(invalidInputClass, !isUrlValid);
$projectImportUrlError.toggleClass('hide', isUrlValid);
- }, 500);
+ };
+ const debouncedUpdateUrlPathWarningVisibility = debounce(
+ updateUrlPathWarningVisibility,
+ DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
+ );
let isProjectImportUrlDirty = false;
$projectImportUrl.on('blur', () => {
isProjectImportUrlDirty = true;
- updateUrlPathWarningVisibility();
+ debouncedUpdateUrlPathWarningVisibility();
});
$projectImportUrl.on('keyup', () => {
deriveProjectPathFromUrl($projectImportUrl);
@@ -190,17 +221,33 @@ const bindEvents = () => {
[$projectImportUrl, $projectImportUrlUser, $projectImportUrlPassword].forEach(($f) => {
$f.on('input', () => {
if (isProjectImportUrlDirty) {
- updateUrlPathWarningVisibility();
+ debouncedUpdateUrlPathWarningVisibility();
}
});
});
- $projectImportForm.on('submit', (e) => {
+ $projectImportForm.on('submit', async (e) => {
+ e.preventDefault();
+
+ if (importCredentialsValidationPromise === null) {
+ // we didn't validate credentials yet
+ debouncedUpdateUrlPathWarningVisibility.cancel();
+ updateUrlPathWarningVisibility();
+ }
+
+ const submitBtn = $projectImportForm.find('input[type="submit"]');
+
+ submitBtn.disable();
+ await importCredentialsValidationPromise;
+ submitBtn.enable();
+
const $invalidFields = $projectImportForm.find(`.${invalidInputClass}`);
if ($invalidFields.length > 0) {
$invalidFields[0].focus();
- e.preventDefault();
- e.stopPropagation();
+ } else {
+ // calling .submit() on HTMLFormElement does not trigger 'submit' event
+ // We are using this behavior to bypass this handler and avoid infinite loop
+ $projectImportForm[0].submit();
}
});
diff --git a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
index 91d8fca0487..aa3235b1515 100644
--- a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
+++ b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
@@ -2,6 +2,7 @@
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { __, s__ } from '~/locale';
+import { CC_VALIDATION_REQUIRED_ERROR } from '../constants';
const DEFAULT_ERROR_MESSAGE = __('An error occurred while updating the configuration.');
const REQUIRES_VALIDATION_TEXT = s__(
@@ -47,11 +48,13 @@ export default {
};
},
computed: {
- showCreditCardValidation() {
+ ccRequiredError() {
+ return this.errorMessage === CC_VALIDATION_REQUIRED_ERROR && !this.ccAlertDismissed;
+ },
+ genericError() {
return (
- this.isCreditCardValidationRequired &&
- !this.isSharedRunnerEnabled &&
- !this.successfulValidation &&
+ this.errorMessage &&
+ this.errorMessage !== CC_VALIDATION_REQUIRED_ERROR &&
!this.ccAlertDismissed
);
},
@@ -62,6 +65,7 @@ export default {
},
toggleSharedRunners() {
this.isLoading = true;
+ this.ccAlertDismissed = false;
this.errorMessage = null;
axios
@@ -82,20 +86,19 @@ export default {
<template>
<div>
<section class="gl-mt-5">
- <gl-alert v-if="errorMessage" class="gl-mb-3" variant="danger" :dismissible="false">
- {{ errorMessage }}
- </gl-alert>
-
<cc-validation-required-alert
- v-if="showCreditCardValidation"
+ v-if="ccRequiredError"
class="gl-pb-5"
:custom-message="$options.i18n.REQUIRES_VALIDATION_TEXT"
@verifiedCreditCard="creditCardValidated"
@dismiss="ccAlertDismissed = true"
/>
+ <gl-alert v-if="genericError" class="gl-mb-3" variant="danger" :dismissible="false">
+ {{ errorMessage }}
+ </gl-alert>
+
<gl-toggle
- v-else
ref="sharedRunnersToggle"
:disabled="isDisabledAndUnoverridable"
:is-loading="isLoading"
diff --git a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
index b98e1101884..fe968e74c6d 100644
--- a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
+++ b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
@@ -11,8 +11,12 @@ export default {
ConfirmDanger,
},
props: {
- namespaces: {
- type: Object,
+ groupNamespaces: {
+ type: Array,
+ required: true,
+ },
+ userNamespaces: {
+ type: Array,
required: true,
},
confirmationPhrase: {
@@ -44,10 +48,10 @@ export default {
<div>
<gl-form-group>
<namespace-select
- class="qa-namespaces-list"
data-testid="transfer-project-namespace"
:full-width="true"
- :data="namespaces"
+ :group-namespaces="groupNamespaces"
+ :user-namespaces="userNamespaces"
:selected-namespace="selectedNamespace"
@select="handleSelect"
/>
diff --git a/app/assets/javascripts/projects/settings/constants.js b/app/assets/javascripts/projects/settings/constants.js
index f5591c43dc4..9cf1afd334f 100644
--- a/app/assets/javascripts/projects/settings/constants.js
+++ b/app/assets/javascripts/projects/settings/constants.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const LEVEL_TYPES = {
ROLE: 'role',
USER: 'user',
@@ -18,3 +20,8 @@ export const ACCESS_LEVELS = {
};
export const ACCESS_LEVEL_NONE = 0;
+
+// must match shared_runners_setting in update_service.rb
+export const CC_VALIDATION_REQUIRED_ERROR = __(
+ 'Shared runners enabled cannot be enabled until a valid credit card is on file',
+);
diff --git a/app/assets/javascripts/projects/settings/init_transfer_project_form.js b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
index 47b49031dc9..a5f720bffaa 100644
--- a/app/assets/javascripts/projects/settings/init_transfer_project_form.js
+++ b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
@@ -3,10 +3,14 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import TransferProjectForm from './components/transfer_project_form.vue';
const prepareNamespaces = (rawNamespaces = '') => {
+ if (!rawNamespaces) {
+ return { groupNamespaces: [], userNamespaces: [] };
+ }
+
const data = JSON.parse(rawNamespaces);
return {
- group: data?.group.map(convertObjectPropsToCamelCase),
- user: data?.user.map(convertObjectPropsToCamelCase),
+ groupNamespaces: data?.group?.map(convertObjectPropsToCamelCase) || [],
+ userNamespaces: data?.user?.map(convertObjectPropsToCamelCase) || [],
};
};
@@ -35,7 +39,7 @@ export default () => {
props: {
confirmButtonText,
confirmationPhrase,
- namespaces: prepareNamespaces(namespaces),
+ ...prepareNamespaces(namespaces),
},
on: {
selectNamespace: (id) => {
diff --git a/app/assets/javascripts/related_issues/components/add_issuable_form.vue b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
index f936c03c5d3..9ee2e7a4ffd 100644
--- a/app/assets/javascripts/related_issues/components/add_issuable_form.vue
+++ b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
@@ -9,6 +9,8 @@ import {
linkedIssueTypesMap,
addRelatedIssueErrorMap,
addRelatedItemErrorMap,
+ issuablesFormCategoryHeaderTextMap,
+ issuablesFormInputTextMap,
} from '../constants';
import RelatedIssuableInput from './related_issuable_input.vue';
@@ -134,6 +136,12 @@ export default {
epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics),
};
},
+ issuableCategoryHeaderText() {
+ return issuablesFormCategoryHeaderTextMap[this.issuableType];
+ },
+ issuableInputText() {
+ return issuablesFormInputTextMap[this.issuableType];
+ },
},
methods: {
onPendingIssuableRemoveRequest(params) {
@@ -162,7 +170,7 @@ export default {
<form @submit.prevent="onFormSubmit">
<template v-if="showCategorizedIssues">
<gl-form-group
- :label="__('The current issue')"
+ :label="issuableCategoryHeaderText"
label-for="linked-issue-type-radio"
label-class="label-bold"
class="mb-2"
@@ -175,7 +183,7 @@ export default {
/>
</gl-form-group>
<p class="bold">
- {{ __('the following issue(s)') }}
+ {{ issuableInputText }}
</p>
</template>
<related-issuable-input
diff --git a/app/assets/javascripts/related_issues/components/related_issues_block.vue b/app/assets/javascripts/related_issues/components/related_issues_block.vue
index 94535e1b8c9..bc97fab9ad2 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -5,6 +5,9 @@ import {
issuableQaClassMap,
linkedIssueTypesMap,
linkedIssueTypesTextMap,
+ issuablesBlockHeaderTextMap,
+ issuablesBlockHelpTextMap,
+ issuablesBlockAddButtonTextMap,
} from '../constants';
import AddIssuableForm from './add_issuable_form.vue';
import RelatedIssuesList from './related_issues_list.vue';
@@ -105,6 +108,15 @@ export default {
hasBody() {
return this.isFormVisible || this.shouldShowTokenBody;
},
+ headerText() {
+ return issuablesBlockHeaderTextMap[this.issuableType];
+ },
+ helpLinkText() {
+ return issuablesBlockHelpTextMap[this.issuableType];
+ },
+ addIssuableButtonText() {
+ return issuablesBlockAddButtonTextMap[this.issuableType];
+ },
badgeLabel() {
return this.isFetching && this.relatedIssues.length === 0 ? '...' : this.relatedIssues.length;
},
@@ -138,13 +150,14 @@ export default {
href="#related-issues"
aria-hidden="true"
/>
- <slot name="header-text">{{ __('Linked issues') }}</slot>
+ <slot name="header-text">{{ headerText }}</slot>
<gl-link
v-if="hasHelpPath"
:href="helpPath"
target="_blank"
class="gl-display-flex gl-align-items-center gl-ml-2 gl-text-gray-500"
- :aria-label="__('Read more about related issues')"
+ data-testid="help-link"
+ :aria-label="helpLinkText"
>
<gl-icon name="question" :size="12" />
</gl-link>
@@ -160,7 +173,7 @@ export default {
v-if="canAdmin"
data-qa-selector="related_issues_plus_button"
icon="plus"
- :aria-label="__('Add a related issue')"
+ :aria-label="addIssuableButtonText"
:class="qaClass"
@click="$emit('toggleAddRelatedIssuesForm', $event)"
/>
diff --git a/app/assets/javascripts/related_issues/constants.js b/app/assets/javascripts/related_issues/constants.js
index 89eae069a24..f911468d8f1 100644
--- a/app/assets/javascripts/related_issues/constants.js
+++ b/app/assets/javascripts/related_issues/constants.js
@@ -104,3 +104,28 @@ export const PathIdSeparator = {
Epic: '&',
Issue: '#',
};
+
+export const issuablesBlockHeaderTextMap = {
+ [issuableTypesMap.ISSUE]: __('Linked issues'),
+ [issuableTypesMap.EPIC]: __('Linked epics'),
+};
+
+export const issuablesBlockHelpTextMap = {
+ [issuableTypesMap.ISSUE]: __('Read more about related issues'),
+ [issuableTypesMap.EPIC]: __('Read more about related epics'),
+};
+
+export const issuablesBlockAddButtonTextMap = {
+ [issuableTypesMap.ISSUE]: __('Add a related issue'),
+ [issuableTypesMap.EPIC]: __('Add a related epic'),
+};
+
+export const issuablesFormCategoryHeaderTextMap = {
+ [issuableTypesMap.ISSUE]: __('The current issue'),
+ [issuableTypesMap.EPIC]: __('The current epic'),
+};
+
+export const issuablesFormInputTextMap = {
+ [issuableTypesMap.ISSUE]: __('the following issue(s)'),
+ [issuableTypesMap.EPIC]: __('the following epic(s)'),
+};
diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js
index 0ee99df1455..35858be90b2 100644
--- a/app/assets/javascripts/related_issues/index.js
+++ b/app/assets/javascripts/related_issues/index.js
@@ -8,6 +8,7 @@ export default function initRelatedIssues() {
// eslint-disable-next-line no-new
new Vue({
el: relatedIssuesRootElement,
+ name: 'RelatedIssuesRoot',
components: {
relatedIssuesRoot: RelatedIssuesRoot,
},
diff --git a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
index ed4f3c4e0fe..05ab5c2cc90 100644
--- a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
+++ b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
@@ -1,9 +1,10 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlBadge, GlLink } from '@gitlab/ui';
export default {
name: 'AccessibilityIssueBody',
components: {
+ GlBadge,
GlLink,
},
props: {
@@ -38,9 +39,9 @@ export default {
<template>
<div class="report-block-list-issue-description gl-mt-2 gl-mb-2">
<div ref="accessibility-issue-description" class="report-block-list-issue-description-text">
- <div v-if="isNew" ref="accessibility-issue-is-new-badge" class="badge badge-danger gl-mr-2">
- {{ s__('AccessibilityReport|New') }}
- </div>
+ <gl-badge v-if="isNew" class="gl-mr-2" variant="danger">{{
+ s__('AccessibilityReport|New')
+ }}</gl-badge>
<div>
{{
sprintf(
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 9368d7e6058..52963b49f68 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -9,12 +9,14 @@ import axios from '~/lib/utils/axios_utils';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
+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 { DEFAULT_BLOB_INFO, TEXT_FILE_TYPE, LFS_STORAGE } from '../constants';
import BlobButtonGroup from './blob_button_group.vue';
import BlobEdit from './blob_edit.vue';
import ForkSuggestion from './fork_suggestion.vue';
-import { loadViewer, viewerProps } from './blob_viewers';
+import { loadViewer } from './blob_viewers';
export default {
i18n: {
@@ -29,7 +31,7 @@ export default {
GlButton,
ForkSuggestion,
},
- mixins: [getRefMixin],
+ mixins: [getRefMixin, glFeatureFlagMixin()],
inject: {
originalBranch: {
default: '',
@@ -43,12 +45,11 @@ export default {
projectPath: this.projectPath,
filePath: this.path,
ref: this.originalBranch || this.ref,
+ shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
};
},
result() {
- this.switchViewer(
- this.hasRichViewer && !window.location.hash ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER,
- );
+ this.switchViewer(this.hasRichViewer ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER);
},
error() {
this.displayError();
@@ -78,50 +79,7 @@ export default {
isBinary: false,
isLoadingLegacyViewer: false,
activeViewerType: SIMPLE_BLOB_VIEWER,
- project: {
- userPermissions: {
- pushCode: false,
- downloadCode: false,
- createMergeRequestIn: false,
- forkProject: false,
- },
- pathLocks: {
- nodes: [],
- },
- repository: {
- empty: true,
- blobs: {
- nodes: [
- {
- name: '',
- size: '',
- rawTextBlob: '',
- type: '',
- fileType: '',
- tooLarge: false,
- path: '',
- editBlobPath: '',
- ideEditPath: '',
- forkAndEditPath: '',
- ideForkAndEditPath: '',
- storedExternally: false,
- externalStorage: '',
- canModifyBlob: false,
- canCurrentUserPushToBranch: false,
- archived: false,
- rawPath: '',
- externalStorageUrl: '',
- replacePath: '',
- pipelineEditorPath: '',
- deletePath: '',
- simpleViewer: {},
- richViewer: null,
- webPath: '',
- },
- ],
- },
- },
- },
+ project: DEFAULT_BLOB_INFO,
};
},
computed: {
@@ -132,7 +90,7 @@ export default {
return this.$apollo.queries.project.loading;
},
isBinaryFileType() {
- return this.isBinary || this.blobInfo.simpleViewer?.fileType !== 'text';
+ return this.isBinary || this.blobInfo.simpleViewer?.fileType !== TEXT_FILE_TYPE;
},
blobInfo() {
const nodes = this.project?.repository?.blobs?.nodes || [];
@@ -151,11 +109,16 @@ export default {
},
blobViewer() {
const { fileType } = this.viewer;
- return loadViewer(fileType);
+ return this.shouldLoadLegacyViewer ? null : loadViewer(fileType, this.isUsingLfs);
},
- viewerProps() {
- const { fileType } = this.viewer;
- return viewerProps(fileType, this.blobInfo);
+ shouldLoadLegacyViewer() {
+ return this.viewer.fileType === TEXT_FILE_TYPE && !this.glFeatures.highlightJs;
+ },
+ legacyViewerLoaded() {
+ return (
+ (this.activeViewerType === SIMPLE_BLOB_VIEWER && this.legacySimpleViewer) ||
+ (this.activeViewerType === RICH_BLOB_VIEWER && this.legacyRichViewer)
+ );
},
canLock() {
const { pushCode, downloadCode } = this.project.userPermissions;
@@ -183,18 +146,23 @@ export default {
? this.blobInfo.ideForkAndEditPath
: this.blobInfo.forkAndEditPath;
},
+ isUsingLfs() {
+ return this.blobInfo.storedExternally && this.blobInfo.externalStorage === LFS_STORAGE;
+ },
},
methods: {
- loadLegacyViewer(type) {
- if (this.legacyViewerLoaded(type)) {
+ loadLegacyViewer() {
+ if (this.legacyViewerLoaded) {
return;
}
+ const type = this.activeViewerType;
+
this.isLoadingLegacyViewer = true;
axios
.get(`${this.blobInfo.webPath}?format=json&viewer=${type}`)
.then(({ data: { html, binary } }) => {
- if (type === 'simple') {
+ if (type === SIMPLE_BLOB_VIEWER) {
this.legacySimpleViewer = html;
} else {
this.legacyRichViewer = html;
@@ -205,12 +173,6 @@ export default {
})
.catch(() => this.displayError());
},
- legacyViewerLoaded(type) {
- return (
- (type === SIMPLE_BLOB_VIEWER && this.legacySimpleViewer) ||
- (type === RICH_BLOB_VIEWER && this.legacyRichViewer)
- );
- },
displayError() {
createFlash({ message: __('An error occurred while loading the file. Please try again.') });
},
@@ -218,7 +180,7 @@ export default {
this.activeViewerType = newViewer || SIMPLE_BLOB_VIEWER;
if (!this.blobViewer) {
- this.loadLegacyViewer(this.activeViewerType);
+ this.loadLegacyViewer();
}
},
editBlob(target) {
@@ -243,10 +205,11 @@ export default {
<div v-if="blobInfo && !isLoading" class="file-holder">
<blob-header
:blob="blobInfo"
- :hide-viewer-switcher="!hasRichViewer || isBinaryFileType"
+ :hide-viewer-switcher="!hasRichViewer || isBinaryFileType || isUsingLfs"
:is-binary="isBinaryFileType"
:active-viewer-type="viewer.type"
:has-render-error="hasRenderError"
+ :show-path="false"
@viewer-changed="switchViewer"
>
<template #actions>
@@ -303,7 +266,7 @@ export default {
:hide-line-numbers="true"
:loading="isLoadingLegacyViewer"
/>
- <component :is="blobViewer" v-else v-bind="viewerProps" class="blob-viewer" />
+ <component :is="blobViewer" v-else :blob="blobInfo" class="blob-viewer" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
index 48fa33eb558..f7b318c64d9 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
@@ -9,19 +9,17 @@ export default {
GlLink,
},
props: {
- fileName: {
- type: String,
+ blob: {
+ type: Object,
required: true,
},
- filePath: {
- type: String,
- required: true,
- },
- fileSize: {
- type: Number,
- required: false,
- default: 0,
- },
+ },
+ data() {
+ return {
+ fileName: this.blob.name,
+ filePath: this.blob.rawPath,
+ fileSize: this.blob.rawSize || 0,
+ };
},
computed: {
downloadFileSize() {
diff --git a/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
index 83d36209bb3..5027f7877aa 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
@@ -1,15 +1,17 @@
<script>
export default {
props: {
- url: {
- type: String,
- required: true,
- },
- alt: {
- type: String,
+ blob: {
+ type: Object,
required: true,
},
},
+ data() {
+ return {
+ url: this.blob.rawPath,
+ alt: this.blob.name,
+ };
+ },
};
</script>
<template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/index.js b/app/assets/javascripts/repository/components/blob_viewers/index.js
index 8f6f2d15215..e942f59e7d8 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/index.js
+++ b/app/assets/javascripts/repository/components/blob_viewers/index.js
@@ -1,48 +1,19 @@
-export const loadViewer = (type) => {
- switch (type) {
- case 'empty':
- return () => import(/* webpackChunkName: 'blob_empty_viewer' */ './empty_viewer.vue');
- case 'text':
- return gon.features.highlightJs
- ? () =>
- import(
- /* webpackChunkName: 'blob_text_viewer' */ '~/vue_shared/components/source_viewer.vue'
- )
- : null;
- case 'download':
- return () => import(/* webpackChunkName: 'blob_download_viewer' */ './download_viewer.vue');
- case 'image':
- return () => import(/* webpackChunkName: 'blob_image_viewer' */ './image_viewer.vue');
- case 'video':
- return () => import(/* webpackChunkName: 'blob_video_viewer' */ './video_viewer.vue');
- case 'pdf':
- return () => import(/* webpackChunkName: 'blob_pdf_viewer' */ './pdf_viewer.vue');
- default:
- return null;
- }
+const viewers = {
+ download: () => import('./download_viewer.vue'),
+ image: () => import('./image_viewer.vue'),
+ video: () => import('./video_viewer.vue'),
+ empty: () => import('./empty_viewer.vue'),
+ text: () => import('~/vue_shared/components/source_viewer/source_viewer.vue'),
+ pdf: () => import('./pdf_viewer.vue'),
+ lfs: () => import('./lfs_viewer.vue'),
};
-export const viewerProps = (type, blob) => {
- return {
- text: {
- content: blob.rawTextBlob,
- autoDetect: true, // We'll eventually disable autoDetect and pass the language explicitly to reduce the footprint (https://gitlab.com/gitlab-org/gitlab/-/issues/348145)
- },
- download: {
- fileName: blob.name,
- filePath: blob.rawPath,
- fileSize: blob.rawSize,
- },
- image: {
- url: blob.rawPath,
- alt: blob.name,
- },
- video: {
- url: blob.rawPath,
- },
- pdf: {
- url: blob.rawPath,
- fileSize: blob.rawSize,
- },
- }[type];
+export const loadViewer = (type, isUsingLfs) => {
+ let viewer = viewers[type];
+
+ if (!viewer && isUsingLfs) {
+ viewer = viewers.lfs;
+ }
+
+ return viewer;
};
diff --git a/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue
new file mode 100644
index 00000000000..6dc7e10662e
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue
@@ -0,0 +1,38 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ i18n: {
+ lfsText: __(
+ 'This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead.',
+ ),
+ },
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ blob: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ fileName: this.blob.name,
+ filePath: this.blob.rawPath,
+ };
+ },
+};
+</script>
+
+<template>
+ <div class="gl-text-center gl-py-13 gl-bg-gray-50" data-type="lfs">
+ <gl-sprintf :message="$options.i18n.lfsText">
+ <template #link="{ content }">
+ <gl-link :href="filePath" :download="fileName" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
index 803a357df52..c3df5984426 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
@@ -11,17 +11,17 @@ export default {
tooLargeButtonText: __('Download PDF'),
},
props: {
- url: {
- type: String,
- required: true,
- },
- fileSize: {
- type: Number,
+ blob: {
+ type: Object,
required: true,
},
},
data() {
- return { totalPages: 0 };
+ return {
+ url: this.blob.rawPath,
+ fileSize: this.blob.rawSize,
+ totalPages: 0,
+ };
},
computed: {
tooLargeToDisplay() {
diff --git a/app/assets/javascripts/repository/components/blob_viewers/video_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/video_viewer.vue
index dec0c4802ca..260b831f4d1 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/video_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/video_viewer.vue
@@ -1,11 +1,16 @@
<script>
export default {
props: {
- url: {
- type: String,
+ blob: {
+ type: Object,
required: true,
},
},
+ data() {
+ return {
+ url: this.blob.rawPath,
+ };
+ },
};
</script>
<template>
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 43e114a91d3..c3d121505b6 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -139,8 +139,10 @@ export default {
/>
<gl-button
v-if="commit.descriptionHtml"
+ v-gl-tooltip
:class="{ open: showDescription }"
- :aria-label="__('Show commit description')"
+ :title="__('Toggle commit description')"
+ :aria-label="__('Toggle commit description')"
class="text-expander gl-vertical-align-bottom!"
icon="ellipsis_h"
@click="toggleShowDescription"
diff --git a/app/assets/javascripts/repository/components/table/parent_row.vue b/app/assets/javascripts/repository/components/table/parent_row.vue
index fb0e505a16e..8a081944600 100644
--- a/app/assets/javascripts/repository/components/table/parent_row.vue
+++ b/app/assets/javascripts/repository/components/table/parent_row.vue
@@ -1,10 +1,13 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
components: {
GlLoadingIcon,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
commitRef: {
type: String,
@@ -41,7 +44,13 @@ export default {
<template>
<tr class="tree-item">
- <td colspan="3" class="tree-item-file-name" @click.self="clickRow">
+ <td
+ v-gl-tooltip.left.viewport
+ :title="__('Go to parent directory')"
+ colspan="3"
+ class="tree-item-file-name"
+ @click.self="clickRow"
+ >
<gl-loading-icon
v-if="parentPath === loadingPath"
size="sm"
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 8fcec5fb893..7aac35e7613 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -195,6 +195,7 @@ export default {
projectPath: this.projectPath,
filePath: this.path,
ref: this.ref,
+ shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
});
},
apolloQuery(query, variables) {
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
index d01757d6141..e206d9bfbd2 100644
--- a/app/assets/javascripts/repository/constants.js
+++ b/app/assets/javascripts/repository/constants.js
@@ -25,3 +25,54 @@ export const PDF_MAX_FILE_SIZE = 10000000; // 10 MB
export const PDF_MAX_PAGE_LIMIT = 50;
export const ROW_APPEAR_DELAY = 150;
+
+export const DEFAULT_BLOB_INFO = {
+ userPermissions: {
+ pushCode: false,
+ downloadCode: false,
+ createMergeRequestIn: false,
+ forkProject: false,
+ },
+ pathLocks: {
+ nodes: [],
+ },
+ repository: {
+ empty: true,
+ blobs: {
+ nodes: [
+ {
+ name: '',
+ size: '',
+ rawTextBlob: '',
+ type: '',
+ fileType: '',
+ tooLarge: false,
+ path: '',
+ editBlobPath: '',
+ ideEditPath: '',
+ forkAndEditPath: '',
+ ideForkAndEditPath: '',
+ storedExternally: false,
+ externalStorage: '',
+ environmentFormattedExternalUrl: '',
+ environmentExternalUrlForRouteMap: '',
+ canModifyBlob: false,
+ canCurrentUserPushToBranch: false,
+ archived: false,
+ rawPath: '',
+ externalStorageUrl: '',
+ replacePath: '',
+ pipelineEditorPath: '',
+ deletePath: '',
+ simpleViewer: {},
+ richViewer: null,
+ webPath: '',
+ },
+ ],
+ },
+ },
+};
+
+export const TEXT_FILE_TYPE = 'text';
+
+export const LFS_STORAGE = 'lfs';
diff --git a/app/assets/javascripts/repository/fragmentTypes.json b/app/assets/javascripts/repository/fragmentTypes.json
deleted file mode 100644
index 949ebca432b..00000000000
--- a/app/assets/javascripts/repository/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"INTERFACE","name":"Entry","possibleTypes":[{"name":"Blob"},{"name":"Submodule"},{"name":"TreeEntry"}]}]}}
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index 96d712ce9b4..29aabe1b00f 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -1,19 +1,11 @@
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
-import introspectionQueryResultData from './fragmentTypes.json';
import { fetchLogsTree } from './log_tree';
Vue.use(VueApollo);
-// We create a fragment matcher so that we can create a fragment from an interface
-// Without this, Apollo throws a heuristic fragment matcher warning
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
-
const defaultClient = createDefaultClient(
{
Query: {
@@ -43,7 +35,6 @@ const defaultClient = createDefaultClient(
},
{
cacheConfig: {
- fragmentMatcher,
dataIdFromObject: (obj) => {
/* eslint-disable @gitlab/require-i18n-strings */
// eslint-disable-next-line no-underscore-dangle
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index ae20a0f0bc4..78323fdc5f4 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -1,6 +1,11 @@
#import "ee_else_ce/repository/queries/path_locks.fragment.graphql"
-query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
+query getBlobInfo(
+ $projectPath: ID!
+ $filePath: String!
+ $ref: String!
+ $shouldFetchRawText: Boolean!
+) {
project(fullPath: $projectPath) {
userPermissions {
pushCode
@@ -18,18 +23,22 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
name
size
rawSize
- rawTextBlob
+ rawTextBlob @include(if: $shouldFetchRawText)
fileType
+ language
path
editBlobPath
ideEditPath
forkAndEditPath
ideForkAndEditPath
+ environmentFormattedExternalUrl
+ environmentExternalUrlForRouteMap
canModifyBlob
canCurrentUserPushToBranch
archived
storedExternally
externalStorage
+ externalStorageUrl
rawPath
replacePath
pipelineEditorPath
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index ee9533bbec3..009afe03ea6 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, consistent-return, no-param-reassign */
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { setCookie } from '~/lib/utils/common_utils';
import { hide, fixTitle } from '~/tooltips';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
@@ -80,7 +80,7 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
hide($this);
if (!triggered) {
- Cookies.set('collapsed_gutter', $('.right-sidebar').hasClass('right-sidebar-collapsed'));
+ setCookie('collapsed_gutter', $('.right-sidebar').hasClass('right-sidebar-collapsed'));
}
};
diff --git a/app/assets/javascripts/runner/admin_runner_show/admin_runner_show_app.vue b/app/assets/javascripts/runner/admin_runner_show/admin_runner_show_app.vue
new file mode 100644
index 00000000000..2795ddbbbcb
--- /dev/null
+++ b/app/assets/javascripts/runner/admin_runner_show/admin_runner_show_app.vue
@@ -0,0 +1,77 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import { createAlert } from '~/flash';
+import { TYPE_CI_RUNNER } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import RunnerEditButton from '../components/runner_edit_button.vue';
+import RunnerPauseButton from '../components/runner_pause_button.vue';
+import RunnerHeader from '../components/runner_header.vue';
+import RunnerDetails from '../components/runner_details.vue';
+import { I18N_FETCH_ERROR } from '../constants';
+import getRunnerQuery from '../graphql/get_runner.query.graphql';
+import { captureException } from '../sentry_utils';
+
+export default {
+ name: 'AdminRunnerShowApp',
+ components: {
+ RunnerEditButton,
+ RunnerPauseButton,
+ RunnerHeader,
+ RunnerDetails,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runnerId: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ runner: null,
+ };
+ },
+ apollo: {
+ runner: {
+ query: getRunnerQuery,
+ variables() {
+ return {
+ id: convertToGraphQLId(TYPE_CI_RUNNER, this.runnerId),
+ };
+ },
+ error(error) {
+ createAlert({ message: I18N_FETCH_ERROR });
+
+ this.reportToSentry(error);
+ },
+ },
+ },
+ computed: {
+ canUpdate() {
+ return this.runner.userPermissions?.updateRunner;
+ },
+ },
+ errorCaptured(error) {
+ this.reportToSentry(error);
+ },
+ methods: {
+ reportToSentry(error) {
+ captureException({ error, component: this.$options.name });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <runner-header v-if="runner" :runner="runner">
+ <template #actions>
+ <runner-edit-button v-if="canUpdate && runner.editAdminUrl" :href="runner.editAdminUrl" />
+ <runner-pause-button v-if="canUpdate" :runner="runner" />
+ </template>
+ </runner-header>
+
+ <runner-details :runner="runner" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/admin_runner_show/index.js b/app/assets/javascripts/runner/admin_runner_show/index.js
new file mode 100644
index 00000000000..a781898cf8d
--- /dev/null
+++ b/app/assets/javascripts/runner/admin_runner_show/index.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import AdminRunnerShowApp from './admin_runner_show_app.vue';
+
+Vue.use(VueApollo);
+
+export const initAdminRunnerShow = (selector = '#js-admin-runner-show') => {
+ const el = document.querySelector(selector);
+
+ if (!el) {
+ return null;
+ }
+
+ const { runnerId } = el.dataset;
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ render(h) {
+ return h(AdminRunnerShowApp, {
+ props: {
+ runnerId,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
index bb2bac531a7..a968d4029f8 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -99,7 +99,10 @@ export default {
allRunnersCount: {
...runnersCountSmartQuery,
variables() {
- return this.countVariables;
+ return {
+ ...this.countVariables,
+ type: null,
+ };
},
},
instanceRunnersCount: {
@@ -276,7 +279,11 @@ export default {
</gl-link>
</template>
</runner-list>
- <runner-pagination v-model="search.pagination" :page-info="runners.pageInfo" />
+ <runner-pagination
+ v-model="search.pagination"
+ class="gl-mt-3"
+ :page-info="runners.pageInfo"
+ />
</template>
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/cells/link_cell.vue b/app/assets/javascripts/runner/components/cells/link_cell.vue
new file mode 100644
index 00000000000..2843ddbacaf
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/link_cell.vue
@@ -0,0 +1,27 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+
+export default {
+ props: {
+ href: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ component() {
+ if (this.href) {
+ return GlLink;
+ }
+ return 'span';
+ },
+ },
+};
+</script>
+
+<template>
+ <component :is="component" :href="href" v-bind="$attrs" v-on="$listeners">
+ <slot></slot>
+ </component>
+</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
index 0934508c87f..ae9c774f2a2 100644
--- a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
@@ -1,16 +1,14 @@
<script>
import { GlButton, GlButtonGroup, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import { createAlert } from '~/flash';
-import { __, s__, sprintf } from '~/locale';
+import { s__, sprintf } from '~/locale';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
-import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
import { captureException } from '~/runner/sentry_utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import RunnerEditButton from '../runner_edit_button.vue';
+import RunnerPauseButton from '../runner_pause_button.vue';
import RunnerDeleteModal from '../runner_delete_modal.vue';
-const I18N_EDIT = __('Edit');
-const I18N_PAUSE = __('Pause');
-const I18N_RESUME = __('Resume');
const I18N_DELETE = s__('Runners|Delete runner');
const I18N_DELETED_TOAST = s__('Runners|Runner %{name} was deleted');
@@ -19,6 +17,8 @@ export default {
components: {
GlButton,
GlButtonGroup,
+ RunnerEditButton,
+ RunnerPauseButton,
RunnerDeleteModal,
},
directives: {
@@ -38,20 +38,6 @@ export default {
};
},
computed: {
- 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_PAUSE : I18N_RESUME;
- },
deleteTitle() {
if (this.deleting) {
// Prevent a "sticky" tooltip: If this button is disabled,
@@ -77,35 +63,6 @@ export default {
},
},
methods: {
- async onToggleActive() {
- this.updating = true;
- try {
- const toggledActive = !this.runner.active;
-
- const {
- data: {
- runnerUpdate: { errors },
- },
- } = await this.$apollo.mutate({
- mutation: runnerActionsUpdateMutation,
- variables: {
- input: {
- id: this.runner.id,
- active: toggledActive,
- },
- },
- });
-
- if (errors && errors.length) {
- throw new Error(errors.join(' '));
- }
- } catch (e) {
- this.onError(e);
- } finally {
- this.updating = false;
- }
- },
-
async onDelete() {
// Deleting stays "true" until this row is removed,
// should only change back if the operation fails.
@@ -147,7 +104,6 @@ export default {
captureException({ error, component: this.$options.name });
},
},
- I18N_EDIT,
I18N_DELETE,
};
</script>
@@ -161,23 +117,8 @@ export default {
See https://gitlab.com/gitlab-org/gitlab/-/issues/334802
-->
- <gl-button
- v-if="canUpdate && runner.editAdminUrl"
- v-gl-tooltip.hover.viewport="$options.I18N_EDIT"
- :href="runner.editAdminUrl"
- :aria-label="$options.I18N_EDIT"
- icon="pencil"
- data-testid="edit-runner"
- />
- <gl-button
- v-if="canUpdate"
- v-gl-tooltip.hover.viewport="toggleActiveTitle"
- :aria-label="toggleActiveTitle"
- :icon="toggleActiveIcon"
- :loading="updating"
- data-testid="toggle-active-runner"
- @click="onToggleActive"
- />
+ <runner-edit-button v-if="canUpdate && runner.editAdminUrl" :href="runner.editAdminUrl" />
+ <runner-pause-button v-if="canUpdate" :runner="runner" :compact="true" />
<gl-button
v-if="canDelete"
v-gl-tooltip.hover.viewport="deleteTitle"
diff --git a/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue b/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue
index 0e259807f98..54c35e483dc 100644
--- a/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue
+++ b/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue
@@ -11,8 +11,10 @@ import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
export default {
name: 'RunnerRegistrationTokenReset',
i18n: {
- modalTitle: __('Reset registration token'),
+ modalAction: s__('Runners|Reset token'),
+ modalCancel: __('Cancel'),
modalCopy: __('Are you sure you want to reset the registration token?'),
+ modalTitle: __('Reset registration token'),
},
components: {
GlDropdownItem,
@@ -30,7 +32,7 @@ export default {
default: null,
},
},
- modalID: 'token-reset-modal',
+ modalId: 'token-reset-modal',
props: {
type: {
type: String,
@@ -111,10 +113,19 @@ export default {
};
</script>
<template>
- <gl-dropdown-item v-gl-modal="$options.modalID">
+ <gl-dropdown-item v-gl-modal="$options.modalId">
{{ __('Reset registration token') }}
<gl-modal
- :modal-id="$options.modalID"
+ size="sm"
+ :modal-id="$options.modalId"
+ :action-primary="{
+ text: $options.i18n.modalAction,
+ attributes: [{ variant: 'danger' }],
+ }"
+ :action-secondary="{
+ text: $options.i18n.modalCancel,
+ attributes: [{ variant: 'default' }],
+ }"
:title="$options.i18n.modalTitle"
@primary="handleModalPrimary"
>
diff --git a/app/assets/javascripts/runner/components/runner_assigned_item.vue b/app/assets/javascripts/runner/components/runner_assigned_item.vue
new file mode 100644
index 00000000000..ea8074199a6
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_assigned_item.vue
@@ -0,0 +1,39 @@
+<script>
+import { GlAvatar, GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlAvatar,
+ GlLink,
+ },
+ props: {
+ href: {
+ type: String,
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ fullName: {
+ type: String,
+ required: true,
+ },
+ avatarUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center gl-py-5">
+ <gl-link :href="href" data-testid="item-avatar" class="gl-text-decoration-none! gl-mr-3">
+ <gl-avatar shape="rect" :entity-name="name" :alt="name" :src="avatarUrl" :size="48" />
+ </gl-link>
+
+ <gl-link :href="href" class="gl-font-weight-bold gl-text-gray-900!">{{ fullName }}</gl-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_detail.vue b/app/assets/javascripts/runner/components/runner_detail.vue
new file mode 100644
index 00000000000..b1234818b7e
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_detail.vue
@@ -0,0 +1,50 @@
+<script>
+import { __ } from '~/locale';
+
+/**
+ * Usage:
+ *
+ * With a `value` prop:
+ *
+ * <runner-detail label="Field Name" :value="value" />
+ *
+ * Or a `value` slot:
+ *
+ * <runner-detail label="Field Name">
+ * <template #value>
+ * <strong>{{ value }}</strong>
+ * </template>
+ * </runner-detail>
+ *
+ */
+export default {
+ props: {
+ label: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: String,
+ default: null,
+ required: false,
+ },
+ emptyValue: {
+ type: String,
+ default: __('None'),
+ required: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-pb-4">
+ <dt class="gl-mr-2">{{ label }}</dt>
+ <dd class="gl-mb-0">
+ <template v-if="value || $slots.value">
+ <slot name="value">{{ value }}</slot>
+ </template>
+ <span v-else class="gl-text-gray-500">{{ emptyValue }}</span>
+ </dd>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_details.vue b/app/assets/javascripts/runner/components/runner_details.vue
new file mode 100644
index 00000000000..b6a5ffc7a64
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_details.vue
@@ -0,0 +1,124 @@
+<script>
+import { GlBadge, GlTabs, GlTab, GlIntersperse } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
+import { ACCESS_LEVEL_REF_PROTECTED, GROUP_TYPE, PROJECT_TYPE } from '../constants';
+import { formatJobCount } from '../utils';
+import RunnerDetail from './runner_detail.vue';
+import RunnerGroups from './runner_groups.vue';
+import RunnerProjects from './runner_projects.vue';
+import RunnerJobs from './runner_jobs.vue';
+import RunnerTags from './runner_tags.vue';
+
+export default {
+ components: {
+ GlBadge,
+ GlTabs,
+ GlTab,
+ GlIntersperse,
+ RunnerDetail,
+ RunnerGroups,
+ RunnerProjects,
+ RunnerJobs,
+ RunnerTags,
+ TimeAgo,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ maximumTimeout() {
+ const { maximumTimeout } = this.runner;
+ if (typeof maximumTimeout !== 'number') {
+ return null;
+ }
+ return timeIntervalInWords(maximumTimeout);
+ },
+ configTextProtected() {
+ if (this.runner.accessLevel === ACCESS_LEVEL_REF_PROTECTED) {
+ return s__('Runners|Protected');
+ }
+ return null;
+ },
+ configTextUntagged() {
+ if (this.runner.runUntagged) {
+ return s__('Runners|Runs untagged jobs');
+ }
+ return null;
+ },
+ isGroupRunner() {
+ return this.runner?.runnerType === GROUP_TYPE;
+ },
+ isProjectRunner() {
+ return this.runner?.runnerType === PROJECT_TYPE;
+ },
+ jobCount() {
+ return formatJobCount(this.runner?.jobCount);
+ },
+ },
+ ACCESS_LEVEL_REF_PROTECTED,
+};
+</script>
+
+<template>
+ <gl-tabs>
+ <gl-tab>
+ <template #title>{{ s__('Runners|Details') }}</template>
+
+ <template v-if="runner">
+ <div class="gl-pt-4">
+ <dl class="gl-mb-0" data-testid="runner-details-list">
+ <runner-detail :label="s__('Runners|Description')" :value="runner.description" />
+ <runner-detail
+ :label="s__('Runners|Last contact')"
+ :empty-value="s__('Runners|Never contacted')"
+ >
+ <template #value>
+ <time-ago v-if="runner.contactedAt" :time="runner.contactedAt" />
+ </template>
+ </runner-detail>
+ <runner-detail :label="s__('Runners|Version')" :value="runner.version" />
+ <runner-detail :label="s__('Runners|IP Address')" :value="runner.ipAddress" />
+ <runner-detail :label="s__('Runners|Configuration')">
+ <template #value>
+ <gl-intersperse v-if="configTextProtected || configTextUntagged">
+ <span v-if="configTextProtected">{{ configTextProtected }}</span>
+ <span v-if="configTextUntagged">{{ configTextUntagged }}</span>
+ </gl-intersperse>
+ </template>
+ </runner-detail>
+ <runner-detail :label="s__('Runners|Maximum job timeout')" :value="maximumTimeout" />
+ <runner-detail :label="s__('Runners|Tags')">
+ <template #value>
+ <runner-tags
+ v-if="runner.tagList && runner.tagList.length"
+ class="gl-vertical-align-middle"
+ :tag-list="runner.tagList"
+ size="sm"
+ />
+ </template>
+ </runner-detail>
+ </dl>
+ </div>
+
+ <runner-groups v-if="isGroupRunner" :runner="runner" />
+ <runner-projects v-if="isProjectRunner" :runner="runner" />
+ </template>
+ </gl-tab>
+ <gl-tab>
+ <template #title>
+ {{ s__('Runners|Jobs') }}
+ <gl-badge v-if="jobCount" data-testid="job-count-badge" class="gl-ml-1" size="sm">
+ {{ jobCount }}
+ </gl-badge>
+ </template>
+
+ <runner-jobs v-if="runner" :runner="runner" />
+ </gl-tab>
+ </gl-tabs>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_edit_button.vue b/app/assets/javascripts/runner/components/runner_edit_button.vue
new file mode 100644
index 00000000000..b115be09e69
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_edit_button.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+const I18N_EDIT = __('Edit');
+
+export default {
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ I18N_EDIT,
+};
+</script>
+
+<template>
+ <gl-button
+ v-gl-tooltip="$options.I18N_EDIT"
+ v-bind="$attrs"
+ :aria-label="$options.I18N_EDIT"
+ icon="pencil"
+ v-on="$listeners"
+ />
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_groups.vue b/app/assets/javascripts/runner/components/runner_groups.vue
new file mode 100644
index 00000000000..c3b35bd52a9
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_groups.vue
@@ -0,0 +1,37 @@
+<script>
+import RunnerAssignedItem from './runner_assigned_item.vue';
+
+export default {
+ components: {
+ RunnerAssignedItem,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ groups() {
+ return this.runner.groups?.nodes || [];
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-border-t-gray-100 gl-border-t-1 gl-border-t-solid">
+ <h3 class="gl-font-lg gl-mt-5 gl-mb-0">{{ s__('Runners|Assigned Group') }}</h3>
+ <template v-if="groups.length">
+ <runner-assigned-item
+ v-for="group in groups"
+ :key="group.id"
+ :href="group.webUrl"
+ :name="group.name"
+ :full-name="group.fullName"
+ :avatar-url="group.avatarUrl"
+ />
+ </template>
+ <span v-else class="gl-text-gray-500">{{ __('None') }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_header.vue b/app/assets/javascripts/runner/components/runner_header.vue
index 09f58df7bd0..abc07cec1ad 100644
--- a/app/assets/javascripts/runner/components/runner_header.vue
+++ b/app/assets/javascripts/runner/components/runner_header.vue
@@ -1,19 +1,23 @@
<script>
-import { GlSprintf } from '@gitlab/ui';
+import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { sprintf } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { I18N_DETAILS_TITLE } from '../constants';
+import { I18N_DETAILS_TITLE, I18N_LOCKED_RUNNER_DESCRIPTION } from '../constants';
import RunnerTypeBadge from './runner_type_badge.vue';
import RunnerStatusBadge from './runner_status_badge.vue';
export default {
components: {
+ GlIcon,
GlSprintf,
TimeAgo,
RunnerTypeBadge,
RunnerStatusBadge,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
runner: {
type: Object,
@@ -29,24 +33,36 @@ export default {
return sprintf(I18N_DETAILS_TITLE, { runner_id: id });
},
},
+ I18N_LOCKED_RUNNER_DESCRIPTION,
};
</script>
<template>
- <div class="gl-py-5 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
- <runner-status-badge :runner="runner" />
- <runner-type-badge v-if="runner" :type="runner.runnerType" />
- <template v-if="runner.createdAt">
- <gl-sprintf :message="__('%{runner} created %{timeago}')">
- <template #runner>
- <strong>{{ heading }}</strong>
- </template>
- <template #timeago>
- <time-ago :time="runner.createdAt" />
- </template>
- </gl-sprintf>
- </template>
- <template v-else>
- <strong>{{ heading }}</strong>
- </template>
+ <div
+ class="gl-display-flex gl-align-items-center gl-py-5 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
+ >
+ <div>
+ <runner-status-badge :runner="runner" />
+ <runner-type-badge v-if="runner" :type="runner.runnerType" />
+ <template v-if="runner.createdAt">
+ <gl-sprintf :message="__('%{runner} created %{timeago}')">
+ <template #runner>
+ <strong>{{ heading }}</strong>
+ <gl-icon
+ v-if="runner.locked"
+ v-gl-tooltip="$options.I18N_LOCKED_RUNNER_DESCRIPTION"
+ name="lock"
+ :aria-label="$options.I18N_LOCKED_RUNNER_DESCRIPTION"
+ />
+ </template>
+ <template #timeago>
+ <time-ago :time="runner.createdAt" />
+ </template>
+ </gl-sprintf>
+ </template>
+ <template v-else>
+ <strong>{{ heading }}</strong>
+ </template>
+ </div>
+ <div class="gl-ml-auto gl-flex-shrink-0"><slot name="actions"></slot></div>
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_jobs.vue b/app/assets/javascripts/runner/components/runner_jobs.vue
new file mode 100644
index 00000000000..c13e7e90168
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_jobs.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlSkeletonLoading } from '@gitlab/ui';
+import { createAlert } from '~/flash';
+import getRunnerJobsQuery from '../graphql/get_runner_jobs.query.graphql';
+import { I18N_FETCH_ERROR, I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '../constants';
+import { captureException } from '../sentry_utils';
+import { getPaginationVariables } from '../utils';
+import RunnerJobsTable from './runner_jobs_table.vue';
+import RunnerPagination from './runner_pagination.vue';
+
+export default {
+ name: 'RunnerJobs',
+ components: {
+ GlSkeletonLoading,
+ RunnerJobsTable,
+ RunnerPagination,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ jobs: {
+ items: [],
+ pageInfo: {},
+ },
+ pagination: {
+ page: 1,
+ },
+ };
+ },
+ apollo: {
+ jobs: {
+ query: getRunnerJobsQuery,
+ variables() {
+ return this.variables;
+ },
+ update({ runner }) {
+ return {
+ items: runner?.jobs?.nodes || [],
+ pageInfo: runner?.jobs?.pageInfo || {},
+ };
+ },
+ error(error) {
+ createAlert({ message: I18N_FETCH_ERROR });
+ this.reportToSentry(error);
+ },
+ },
+ },
+ computed: {
+ variables() {
+ const { id } = this.runner;
+ return {
+ id,
+ ...getPaginationVariables(this.pagination, RUNNER_DETAILS_JOBS_PAGE_SIZE),
+ };
+ },
+ loading() {
+ return this.$apollo.queries.jobs.loading;
+ },
+ },
+ methods: {
+ reportToSentry(error) {
+ captureException({ error, component: this.$options.name });
+ },
+ },
+ I18N_NO_JOBS_FOUND,
+};
+</script>
+
+<template>
+ <div class="gl-pt-3">
+ <gl-skeleton-loading v-if="loading" class="gl-py-5" />
+ <runner-jobs-table v-else-if="jobs.items.length" :jobs="jobs.items" />
+ <p v-else>{{ $options.I18N_NO_JOBS_FOUND }}</p>
+
+ <runner-pagination v-model="pagination" :disabled="loading" :page-info="jobs.pageInfo" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_jobs_table.vue b/app/assets/javascripts/runner/components/runner_jobs_table.vue
new file mode 100644
index 00000000000..7817577bab0
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_jobs_table.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlTableLite } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import RunnerTags from '~/runner/components/runner_tags.vue';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { tableField } from '../utils';
+import LinkCell from './cells/link_cell.vue';
+
+export default {
+ components: {
+ CiBadge,
+ GlTableLite,
+ LinkCell,
+ RunnerTags,
+ TimeAgo,
+ },
+ props: {
+ jobs: {
+ type: Array,
+ required: true,
+ },
+ },
+ methods: {
+ trAttr(job) {
+ if (job?.id) {
+ return { 'data-testid': `job-row-${getIdFromGraphQLId(job.id)}` };
+ }
+ return {};
+ },
+ jobId(job) {
+ return getIdFromGraphQLId(job.id);
+ },
+ jobPath(job) {
+ return job.detailedStatus?.detailsPath;
+ },
+ projectName(job) {
+ return job.pipeline?.project?.name;
+ },
+ projectWebUrl(job) {
+ return job.pipeline?.project?.webUrl;
+ },
+ commitShortSha(job) {
+ return job.shortSha;
+ },
+ commitPath(job) {
+ return job.commitPath;
+ },
+ },
+ fields: [
+ tableField({ key: 'status', label: s__('Job|Status') }),
+ tableField({ key: 'job', label: __('Job') }),
+ tableField({ key: 'project', label: __('Project') }),
+ tableField({ key: 'commit', label: __('Commit') }),
+ tableField({ key: 'finished_at', label: s__('Job|Finished at') }),
+ tableField({ key: 'tags', label: s__('Runners|Tags') }),
+ ],
+};
+</script>
+
+<template>
+ <gl-table-lite
+ :items="jobs"
+ :fields="$options.fields"
+ :tbody-tr-attr="trAttr"
+ primary-key="id"
+ stacked="md"
+ fixed
+ >
+ <template #cell(status)="{ item = {} }">
+ <ci-badge v-if="item.detailedStatus" :status="item.detailedStatus" />
+ </template>
+
+ <template #cell(job)="{ item = {} }">
+ <link-cell :href="jobPath(item)"> #{{ jobId(item) }} </link-cell>
+ </template>
+
+ <template #cell(project)="{ item = {} }">
+ <link-cell :href="projectWebUrl(item)">{{ projectName(item) }}</link-cell>
+ </template>
+
+ <template #cell(commit)="{ item = {} }">
+ <link-cell :href="commitPath(item)"> {{ commitShortSha(item) }}</link-cell>
+ </template>
+
+ <template #cell(tags)="{ item = {} }">
+ <runner-tags :tag-list="item.tags" />
+ </template>
+
+ <template #cell(finished_at)="{ item = {} }">
+ <time-ago v-if="item.finishedAt" :time="item.finishedAt" />
+ </template>
+ </gl-table-lite>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index 023308dbac2..bb36882d3ae 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -2,31 +2,14 @@
import { GlTable, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { formatNumber, __, s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import { RUNNER_JOB_COUNT_LIMIT } from '../constants';
+import { formatJobCount, tableField } from '../utils';
import RunnerActionsCell from './cells/runner_actions_cell.vue';
import RunnerSummaryCell from './cells/runner_summary_cell.vue';
import RunnerStatusCell from './cells/runner_status_cell.vue';
import RunnerTags from './runner_tags.vue';
-const tableField = ({ key, label = '', thClasses = [] }) => {
- return {
- key,
- label,
- thClass: [
- 'gl-bg-transparent!',
- 'gl-border-b-solid!',
- 'gl-border-b-gray-100!',
- 'gl-border-b-1!',
- ...thClasses,
- ],
- tdAttr: {
- 'data-testid': `td-${key}`,
- },
- };
-};
-
export default {
components: {
GlTable,
@@ -54,10 +37,7 @@ export default {
},
methods: {
formatJobCount(jobCount) {
- if (jobCount > RUNNER_JOB_COUNT_LIMIT) {
- return `${formatNumber(RUNNER_JOB_COUNT_LIMIT)}+`;
- }
- return formatNumber(jobCount);
+ return formatJobCount(jobCount);
},
runnerTrAttr(runner) {
if (runner) {
@@ -70,9 +50,9 @@ export default {
},
fields: [
tableField({ key: 'status', label: s__('Runners|Status') }),
- tableField({ key: 'summary', label: s__('Runners|Runner ID'), thClasses: ['gl-lg-w-25p'] }),
+ tableField({ key: 'summary', label: s__('Runners|Runner'), thClasses: ['gl-lg-w-25p'] }),
tableField({ key: 'version', label: __('Version') }),
- tableField({ key: 'ipAddress', label: __('IP Address') }),
+ tableField({ key: 'ipAddress', label: __('IP') }),
tableField({ key: 'jobCount', label: __('Jobs') }),
tableField({ key: 'tagList', label: __('Tags'), thClasses: ['gl-lg-w-25p'] }),
tableField({ key: 'contactedAt', label: __('Last contact') }),
diff --git a/app/assets/javascripts/runner/components/runner_pagination.vue b/app/assets/javascripts/runner/components/runner_pagination.vue
index 8645b90f5cd..b683a7f2330 100644
--- a/app/assets/javascripts/runner/components/runner_pagination.vue
+++ b/app/assets/javascripts/runner/components/runner_pagination.vue
@@ -29,7 +29,14 @@ export default {
},
methods: {
handlePageChange(page) {
- if (page > this.value.page) {
+ if (page === 1) {
+ // Small optimization for first page
+ // If we have loaded using "first",
+ // page is already cached.
+ this.$emit('input', {
+ page,
+ });
+ } else if (page > this.value.page) {
this.$emit('input', {
page,
after: this.pageInfo.endCursor,
@@ -47,11 +54,12 @@ export default {
<template>
<gl-pagination
+ v-bind="$attrs"
:value="value.page"
:prev-page="prevPage"
:next-page="nextPage"
align="center"
- class="gl-pagination gl-mt-3"
+ class="gl-pagination"
@input="handlePageChange"
/>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_pause_button.vue b/app/assets/javascripts/runner/components/runner_pause_button.vue
new file mode 100644
index 00000000000..a8b259f5b90
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_pause_button.vue
@@ -0,0 +1,122 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import runnerToggleActiveMutation from '~/runner/graphql/runner_toggle_active.mutation.graphql';
+import { createAlert } from '~/flash';
+import { captureException } from '~/runner/sentry_utils';
+import { I18N_PAUSE, I18N_RESUME } from '../constants';
+
+export default {
+ name: 'RunnerPauseButton',
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ compact: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ updating: false,
+ };
+ },
+ computed: {
+ isActive() {
+ return this.runner.active;
+ },
+ icon() {
+ return this.isActive ? 'pause' : 'play';
+ },
+ label() {
+ return this.isActive ? I18N_PAUSE : I18N_RESUME;
+ },
+ buttonContent() {
+ if (this.compact) {
+ return null;
+ }
+ return this.label;
+ },
+ ariaLabel() {
+ if (this.compact) {
+ return this.label;
+ }
+ return null;
+ },
+ tooltip() {
+ // Only show tooltip when compact.
+ // Also prevent a "sticky" tooltip: If this button is
+ // disabled, mouseout listeners don't run leaving the tooltip stuck
+ if (this.compact && !this.updating) {
+ return this.label;
+ }
+ return '';
+ },
+ },
+ methods: {
+ async onToggle() {
+ this.updating = true;
+ try {
+ const input = {
+ id: this.runner.id,
+ active: !this.isActive,
+ };
+
+ const {
+ data: {
+ runnerUpdate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: runnerToggleActiveMutation,
+ variables: {
+ input,
+ },
+ });
+
+ if (errors && errors.length) {
+ throw new Error(errors.join(' '));
+ }
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.updating = false;
+ }
+ },
+ onError(error) {
+ const { message } = error;
+ createAlert({ message });
+
+ this.reportToSentry(error);
+ },
+ reportToSentry(error) {
+ captureException({ error, component: this.$options.name });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button
+ v-gl-tooltip.hover.viewport="tooltip"
+ v-bind="$attrs"
+ :aria-label="ariaLabel"
+ :icon="icon"
+ :loading="updating"
+ @click="onToggle"
+ v-on="$listeners"
+ >
+ <!--
+ Use <template v-if> to ensure a square button is shown when compact: true.
+ Sending empty content will still show a distorted/rectangular button.
+ -->
+ <template v-if="buttonContent">{{ buttonContent }}</template>
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_projects.vue b/app/assets/javascripts/runner/components/runner_projects.vue
new file mode 100644
index 00000000000..c4065a24ff2
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_projects.vue
@@ -0,0 +1,111 @@
+<script>
+import { GlSkeletonLoading } from '@gitlab/ui';
+import { sprintf, formatNumber } from '~/locale';
+import { createAlert } from '~/flash';
+import getRunnerProjectsQuery from '../graphql/get_runner_projects.query.graphql';
+import {
+ I18N_ASSIGNED_PROJECTS,
+ I18N_NONE,
+ I18N_FETCH_ERROR,
+ RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+} from '../constants';
+import { getPaginationVariables } from '../utils';
+import { captureException } from '../sentry_utils';
+import RunnerAssignedItem from './runner_assigned_item.vue';
+import RunnerPagination from './runner_pagination.vue';
+
+export default {
+ name: 'RunnerProjects',
+ components: {
+ GlSkeletonLoading,
+ RunnerAssignedItem,
+ RunnerPagination,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ projects: {
+ items: [],
+ pageInfo: {},
+ count: 0,
+ },
+ pagination: {
+ page: 1,
+ },
+ };
+ },
+ apollo: {
+ projects: {
+ query: getRunnerProjectsQuery,
+ variables() {
+ return this.variables;
+ },
+ update(data) {
+ const { runner } = data;
+ return {
+ count: runner?.projectCount || 0,
+ items: runner?.projects?.nodes || [],
+ pageInfo: runner?.projects?.pageInfo || {},
+ };
+ },
+ error(error) {
+ createAlert({ message: I18N_FETCH_ERROR });
+
+ this.reportToSentry(error);
+ },
+ },
+ },
+ computed: {
+ variables() {
+ const { id } = this.runner;
+ return {
+ id,
+ ...getPaginationVariables(this.pagination, RUNNER_DETAILS_PROJECTS_PAGE_SIZE),
+ };
+ },
+ loading() {
+ return this.$apollo.queries.projects.loading;
+ },
+ heading() {
+ return sprintf(I18N_ASSIGNED_PROJECTS, {
+ projectCount: formatNumber(this.projects.count),
+ });
+ },
+ },
+ methods: {
+ reportToSentry(error) {
+ captureException({ error, component: this.$options.name });
+ },
+ },
+ I18N_NONE,
+};
+</script>
+
+<template>
+ <div class="gl-border-t-gray-100 gl-border-t-1 gl-border-t-solid">
+ <h3 class="gl-font-lg gl-mt-5 gl-mb-0">
+ {{ heading }}
+ </h3>
+
+ <gl-skeleton-loading v-if="loading" class="gl-py-5" />
+ <template v-else-if="projects.items.length">
+ <runner-assigned-item
+ v-for="(project, i) in projects.items"
+ :key="project.id"
+ :class="{ 'gl-border-t-gray-100 gl-border-t-1 gl-border-t-solid': i !== 0 }"
+ :href="project.webUrl"
+ :name="project.name"
+ :full-name="project.nameWithNamespace"
+ :avatar-url="project.avatarUrl"
+ />
+ </template>
+ <span v-else class="gl-text-gray-500">{{ $options.I18N_NONE }}</span>
+
+ <runner-pagination v-model="pagination" :disabled="loading" :page-info="projects.pageInfo" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_tags.vue b/app/assets/javascripts/runner/components/runner_tags.vue
index 8da5e33076f..797d2a35b2c 100644
--- a/app/assets/javascripts/runner/components/runner_tags.vue
+++ b/app/assets/javascripts/runner/components/runner_tags.vue
@@ -20,7 +20,7 @@ export default {
};
</script>
<template>
- <div>
+ <span>
<runner-tag
v-for="tag in tagList"
:key="tag"
@@ -28,5 +28,5 @@ export default {
:tag="tag"
:size="size"
/>
- </div>
+ </span>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_tabs.vue b/app/assets/javascripts/runner/components/runner_type_tabs.vue
index b767dafaccf..25ed6600dc9 100644
--- a/app/assets/javascripts/runner/components/runner_type_tabs.vue
+++ b/app/assets/javascripts/runner/components/runner_type_tabs.vue
@@ -1,27 +1,21 @@
<script>
import { GlTabs, GlTab } from '@gitlab/ui';
-import { s__ } from '~/locale';
import { searchValidator } from '~/runner/runner_search_utils';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
+import {
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ I18N_ALL_TYPES,
+ I18N_INSTANCE_TYPE,
+ I18N_GROUP_TYPE,
+ I18N_PROJECT_TYPE,
+} from '../constants';
-const tabs = [
- {
- title: s__('Runners|All'),
- runnerType: null,
- },
- {
- title: s__('Runners|Instance'),
- runnerType: INSTANCE_TYPE,
- },
- {
- title: s__('Runners|Group'),
- runnerType: GROUP_TYPE,
- },
- {
- title: s__('Runners|Project'),
- runnerType: PROJECT_TYPE,
- },
-];
+const I18N_TAB_TITLES = {
+ [INSTANCE_TYPE]: I18N_INSTANCE_TYPE,
+ [GROUP_TYPE]: I18N_GROUP_TYPE,
+ [PROJECT_TYPE]: I18N_PROJECT_TYPE,
+};
export default {
components: {
@@ -29,12 +23,34 @@ export default {
GlTab,
},
props: {
+ runnerTypes: {
+ type: Array,
+ required: false,
+ default: () => [INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE],
+ },
value: {
type: Object,
required: true,
validator: searchValidator,
},
},
+ computed: {
+ tabs() {
+ const tabs = this.runnerTypes.map((runnerType) => ({
+ title: I18N_TAB_TITLES[runnerType],
+ runnerType,
+ }));
+
+ // Always add a "All" tab that resets filters
+ return [
+ {
+ title: I18N_ALL_TYPES,
+ runnerType: null,
+ },
+ ...tabs,
+ ];
+ },
+ },
methods: {
onTabSelected({ runnerType }) {
this.$emit('input', {
@@ -47,13 +63,12 @@ export default {
return runnerType === this.value.runnerType;
},
},
- tabs,
};
</script>
<template>
<gl-tabs v-bind="$attrs" data-testid="runner-type-tabs">
<gl-tab
- v-for="tab in $options.tabs"
+ v-for="tab in tabs"
:key="`${tab.runnerType}`"
:active="isTabActive(tab)"
@click="onTabSelected(tab)"
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index ce8019ffaa0..1544efaaae2 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -1,13 +1,20 @@
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
export const RUNNER_PAGE_SIZE = 20;
export const RUNNER_JOB_COUNT_LIMIT = 1000;
-export const GROUP_RUNNER_COUNT_LIMIT = 1000;
+
+export const RUNNER_DETAILS_PROJECTS_PAGE_SIZE = 5;
+export const RUNNER_DETAILS_JOBS_PAGE_SIZE = 30;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
// Type
+
+export const I18N_ALL_TYPES = s__('Runners|All');
+export const I18N_INSTANCE_TYPE = s__('Runners|Instance');
+export const I18N_GROUP_TYPE = s__('Runners|Group');
+export const I18N_PROJECT_TYPE = s__('Runners|Project');
export const I18N_INSTANCE_RUNNER_DESCRIPTION = s__('Runners|Available to all projects');
export const I18N_GROUP_RUNNER_DESCRIPTION = s__(
'Runners|Available to all projects and subgroups in the group',
@@ -28,9 +35,21 @@ export const I18N_STALE_RUNNER_DESCRIPTION = s__(
'Runners|No contact from this runner in over 3 months',
);
+// Active flag
+export const I18N_PAUSE = __('Pause');
+export const I18N_RESUME = __('Resume');
+
export const I18N_LOCKED_RUNNER_DESCRIPTION = s__('Runners|You cannot assign to other projects');
export const I18N_PAUSED_RUNNER_DESCRIPTION = s__('Runners|Not available to run jobs');
+// Runner details
+
+export const I18N_ASSIGNED_PROJECTS = s__('Runners|Assigned Projects (%{projectCount})');
+export const I18N_NONE = __('None');
+export const I18N_NO_JOBS_FOUND = s__('Runner|This runner has not run any jobs.');
+
+// Styles
+
export const RUNNER_TAG_BADGE_VARIANT = 'neutral';
export const RUNNER_TAG_BG_CLASS = 'gl-bg-blue-100';
diff --git a/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
index f7bcd683718..986dd16b992 100644
--- a/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
@@ -28,10 +28,12 @@ query getGroupRunners(
edges {
webUrl
node {
+ __typename
...RunnerNode
}
}
pageInfo {
+ __typename
...PageInfo
}
}
diff --git a/app/assets/javascripts/runner/graphql/get_runner.query.graphql b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
index 59c55eae060..f6ce8281c64 100644
--- a/app/assets/javascripts/runner/graphql/get_runner.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
@@ -4,6 +4,7 @@ query getRunner($id: CiRunnerID!) {
# We have an id in deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
runner(id: $id) {
+ __typename
...RunnerDetails
}
}
diff --git a/app/assets/javascripts/runner/graphql/get_runner_jobs.query.graphql b/app/assets/javascripts/runner/graphql/get_runner_jobs.query.graphql
new file mode 100644
index 00000000000..2b1decd3ddd
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/get_runner_jobs.query.graphql
@@ -0,0 +1,36 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getRunnerJobs($id: CiRunnerID!, $first: Int, $last: Int, $before: String, $after: String) {
+ runner(id: $id) {
+ id
+ projectCount
+ jobs(before: $before, after: $after, first: $first, last: $last) {
+ nodes {
+ id
+ detailedStatus {
+ # fields for `<ci-badge>`
+ id
+ detailsPath
+ group
+ icon
+ text
+ }
+ pipeline {
+ id
+ project {
+ id
+ name
+ webUrl
+ }
+ }
+ shortSha
+ commitPath
+ tags
+ finishedAt
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/get_runner_projects.query.graphql b/app/assets/javascripts/runner/graphql/get_runner_projects.query.graphql
new file mode 100644
index 00000000000..f97237b8267
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/get_runner_projects.query.graphql
@@ -0,0 +1,26 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getRunnerProjects(
+ $id: CiRunnerID!
+ $first: Int
+ $last: Int
+ $before: String
+ $after: String
+) {
+ runner(id: $id) {
+ id
+ projectCount
+ projects(first: $first, last: $last, before: $before, after: $after) {
+ nodes {
+ id
+ avatarUrl
+ name
+ nameWithNamespace
+ webUrl
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/get_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_runners.query.graphql
index 05df399fa6a..ed03a8c34ae 100644
--- a/app/assets/javascripts/runner/graphql/get_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_runners.query.graphql
@@ -29,6 +29,7 @@ query getRunners(
editAdminUrl
}
pageInfo {
+ __typename
...PageInfo
}
}
diff --git a/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql
deleted file mode 100644
index 547cc43907c..00000000000
--- a/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql
+++ /dev/null
@@ -1,14 +0,0 @@
-#import "~/runner/graphql/runner_node.fragment.graphql"
-
-# Mutation for updates within the runners list via action
-# buttons (play, pause, ...), loads attributes shown in the
-# runner list.
-
-mutation runnerActionsUpdate($input: RunnerUpdateInput!) {
- runnerUpdate(input: $input) {
- runner {
- ...RunnerNode
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/runner/graphql/runner_details_shared.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_details_shared.fragment.graphql
index 8e968343b9b..74760bbaa07 100644
--- a/app/assets/javascripts/runner/graphql/runner_details_shared.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_details_shared.fragment.graphql
@@ -8,7 +8,27 @@ fragment RunnerDetailsShared on CiRunner {
ipAddress
description
maximumTimeout
+ jobCount
tagList
createdAt
status(legacyMode: null)
+ contactedAt
+ version
+ editAdminUrl
+ userPermissions {
+ updateRunner
+ deleteRunner
+ }
+ groups {
+ # Only a single group can be loaded here, while projects
+ # are loaded separately using the query with pagination
+ # parameters `get_runner_projects.query.graphql`.
+ nodes {
+ id
+ avatarUrl
+ name
+ fullName
+ webUrl
+ }
+ }
}
diff --git a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
index 4a771d779dc..fbdef817f2f 100644
--- a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
@@ -1,4 +1,5 @@
fragment RunnerNode on CiRunner {
+ __typename
id
description
runnerType
diff --git a/app/assets/javascripts/runner/graphql/runner_toggle_active.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_toggle_active.mutation.graphql
new file mode 100644
index 00000000000..9b15570dbc0
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/runner_toggle_active.mutation.graphql
@@ -0,0 +1,12 @@
+# Mutation executed for the pause/resume button in the
+# runner list and details views.
+
+mutation runnerToggleActive($input: RunnerUpdateInput!) {
+ runnerUpdate(input: $input) {
+ runner {
+ id
+ active
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
index 3a7b58e3dc9..c4ee0ad4dfb 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -1,9 +1,9 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlBadge, GlLink } from '@gitlab/ui';
import { createAlert } from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import { updateHistory } from '~/lib/utils/url_utility';
-import { formatNumber, sprintf, s__ } from '~/locale';
+import { formatNumber } from '~/locale';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
@@ -18,7 +18,7 @@ import {
I18N_FETCH_ERROR,
GROUP_FILTERED_SEARCH_NAMESPACE,
GROUP_TYPE,
- GROUP_RUNNER_COUNT_LIMIT,
+ PROJECT_TYPE,
STATUS_ONLINE,
STATUS_OFFLINE,
STATUS_STALE,
@@ -46,6 +46,7 @@ const runnersCountSmartQuery = {
export default {
name: 'GroupRunnersApp',
components: {
+ GlBadge,
GlLink,
RegistrationDropdown,
RunnerFilteredSearchBar,
@@ -131,6 +132,33 @@ export default {
};
},
},
+ allRunnersCount: {
+ ...runnersCountSmartQuery,
+ variables() {
+ return {
+ ...this.countVariables,
+ type: null,
+ };
+ },
+ },
+ groupRunnersCount: {
+ ...runnersCountSmartQuery,
+ variables() {
+ return {
+ ...this.countVariables,
+ type: GROUP_TYPE,
+ };
+ },
+ },
+ projectRunnersCount: {
+ ...runnersCountSmartQuery,
+ variables() {
+ return {
+ ...this.countVariables,
+ type: PROJECT_TYPE,
+ };
+ },
+ },
},
computed: {
variables() {
@@ -139,23 +167,17 @@ export default {
groupFullPath: this.groupFullPath,
};
},
+ countVariables() {
+ // Exclude pagination variables, leave only filters variables
+ const { sort, before, last, after, first, ...countVariables } = this.variables;
+ return countVariables;
+ },
runnersLoading() {
return this.$apollo.queries.runners.loading;
},
noRunnersFound() {
return !this.runnersLoading && !this.runners.items.length;
},
- groupRunnersCount() {
- if (this.groupRunnersLimitedCount > GROUP_RUNNER_COUNT_LIMIT) {
- return `${formatNumber(GROUP_RUNNER_COUNT_LIMIT)}+`;
- }
- return formatNumber(this.groupRunnersLimitedCount);
- },
- runnerCountMessage() {
- return sprintf(s__('Runners|Runners in this group: %{groupRunnersCount}'), {
- groupRunnersCount: this.groupRunnersCount,
- });
- },
searchTokens() {
return [statusTokenConfig];
},
@@ -179,10 +201,31 @@ export default {
this.reportToSentry(error);
},
methods: {
+ tabCount({ runnerType }) {
+ let count;
+ switch (runnerType) {
+ case null:
+ count = this.allRunnersCount;
+ break;
+ case GROUP_TYPE:
+ count = this.groupRunnersCount;
+ break;
+ case PROJECT_TYPE:
+ count = this.projectRunnersCount;
+ break;
+ default:
+ return null;
+ }
+ if (typeof count === 'number') {
+ return formatNumber(count);
+ }
+ return null;
+ },
reportToSentry(error) {
captureException({ error, component: this.$options.name });
},
},
+ TABS_RUNNER_TYPES: [GROUP_TYPE, PROJECT_TYPE],
GROUP_TYPE,
};
</script>
@@ -198,9 +241,17 @@ export default {
<div class="gl-display-flex gl-align-items-center">
<runner-type-tabs
v-model="search"
+ :runner-types="$options.TABS_RUNNER_TYPES"
content-class="gl-display-none"
nav-class="gl-border-none!"
- />
+ >
+ <template #title="{ tab }">
+ {{ tab.title }}
+ <gl-badge v-if="tabCount(tab)" class="gl-ml-1" size="sm">
+ {{ tabCount(tab) }}
+ </gl-badge>
+ </template>
+ </runner-type-tabs>
<registration-dropdown
class="gl-ml-auto"
diff --git a/app/assets/javascripts/runner/runner_search_utils.js b/app/assets/javascripts/runner/runner_search_utils.js
index c80a73948b8..fe141332be3 100644
--- a/app/assets/javascripts/runner/runner_search_utils.js
+++ b/app/assets/javascripts/runner/runner_search_utils.js
@@ -18,6 +18,7 @@ import {
RUNNER_PAGE_SIZE,
STATUS_NEVER_CONTACTED,
} from './constants';
+import { getPaginationVariables } from './utils';
/**
* The filters and sorting of the runners are built around
@@ -184,30 +185,27 @@ export const fromSearchToVariables = ({
sort = null,
pagination = {},
} = {}) => {
- const variables = {};
+ const filterVariables = {};
const queryObj = filterToQueryObject(processFilters(filters), {
filteredSearchTermKey: PARAM_KEY_SEARCH,
});
- [variables.status] = queryObj[PARAM_KEY_STATUS] || [];
- variables.search = queryObj[PARAM_KEY_SEARCH];
- variables.tagList = queryObj[PARAM_KEY_TAG];
+ [filterVariables.status] = queryObj[PARAM_KEY_STATUS] || [];
+ filterVariables.search = queryObj[PARAM_KEY_SEARCH];
+ filterVariables.tagList = queryObj[PARAM_KEY_TAG];
if (runnerType) {
- variables.type = runnerType;
+ filterVariables.type = runnerType;
}
if (sort) {
- variables.sort = sort;
+ filterVariables.sort = sort;
}
- if (pagination.before) {
- variables.before = pagination.before;
- variables.last = RUNNER_PAGE_SIZE;
- } else {
- variables.after = pagination.after;
- variables.first = RUNNER_PAGE_SIZE;
- }
+ const paginationVariables = getPaginationVariables(pagination, RUNNER_PAGE_SIZE);
- return variables;
+ return {
+ ...filterVariables,
+ ...paginationVariables,
+ };
};
diff --git a/app/assets/javascripts/runner/utils.js b/app/assets/javascripts/runner/utils.js
new file mode 100644
index 00000000000..6e4c8c45e7b
--- /dev/null
+++ b/app/assets/javascripts/runner/utils.js
@@ -0,0 +1,72 @@
+import { formatNumber } from '~/locale';
+import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
+import { RUNNER_JOB_COUNT_LIMIT } from './constants';
+
+/**
+ * Formats a job count, limited to a max number
+ *
+ * @param {Number} jobCount
+ * @returns Formatted string
+ */
+export const formatJobCount = (jobCount) => {
+ if (typeof jobCount !== 'number') {
+ return '';
+ }
+ if (jobCount > RUNNER_JOB_COUNT_LIMIT) {
+ return `${formatNumber(RUNNER_JOB_COUNT_LIMIT)}+`;
+ }
+ return formatNumber(jobCount);
+};
+
+/**
+ * Returns a GlTable fields with a given key and label
+ *
+ * @param {Object} options
+ * @returns Field object to add to GlTable fields
+ */
+export const tableField = ({ key, label = '', thClasses = [] }) => {
+ return {
+ key,
+ label,
+ thClass: [DEFAULT_TH_CLASSES, ...thClasses],
+ tdAttr: {
+ 'data-testid': `td-${key}`,
+ },
+ };
+};
+
+/**
+ * Returns variables for a GraphQL query that uses keyset
+ * pagination.
+ *
+ * https://docs.gitlab.com/ee/development/graphql_guide/pagination.html#keyset-pagination
+ *
+ * @param {Object} pagination - Contains before, after, page
+ * @param {Number} pageSize
+ * @returns Variables
+ */
+export const getPaginationVariables = (pagination, pageSize = 10) => {
+ const { before, after } = pagination;
+
+ // first + after: Next page
+ // Get the first N items after item X
+ if (after) {
+ return {
+ after,
+ first: pageSize,
+ };
+ }
+
+ // last + before: Prev page
+ // Get the first N items before item X, when you click on Prev
+ if (before) {
+ return {
+ before,
+ last: pageSize,
+ };
+ }
+
+ // first page
+ // Get the first N items
+ return { first: pageSize };
+};
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index d228f77f27d..c48c9067250 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -50,7 +50,7 @@ export default {
TrainingProviderList,
},
mixins: [glFeatureFlagsMixin()],
- inject: ['projectPath'],
+ inject: ['projectFullPath'],
props: {
augmentedSecurityFeatures: {
type: Array,
@@ -107,14 +107,14 @@ export default {
shouldShowAutoDevopsEnabledAlert() {
return (
this.autoDevopsEnabled &&
- !this.autoDevopsEnabledAlertDismissedProjects.includes(this.projectPath)
+ !this.autoDevopsEnabledAlertDismissedProjects.includes(this.projectFullPath)
);
},
},
methods: {
dismissAutoDevopsEnabledAlert() {
const dismissedProjects = new Set(this.autoDevopsEnabledAlertDismissedProjects);
- dismissedProjects.add(this.projectPath);
+ dismissedProjects.add(this.projectFullPath);
this.autoDevopsEnabledAlertDismissedProjects = Array.from(dismissedProjects);
},
onError(message) {
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 034dba29196..81d222438e3 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -123,7 +123,7 @@ export const COVERAGE_FUZZING_CONFIG_HELP_PATH = helpPagePath(
export const CORPUS_MANAGEMENT_NAME = __('Corpus Management');
export const CORPUS_MANAGEMENT_DESCRIPTION = s__(
- 'SecurityConfiguration|Manage corpus files used as mutation sources in coverage fuzzing.',
+ 'SecurityConfiguration|Manage corpus files used as seed inputs with coverage-guided fuzzing.',
);
export const CORPUS_MANAGEMENT_CONFIG_TEXT = s__('SecurityConfiguration|Manage corpus');
@@ -159,15 +159,6 @@ export const securityFeatures = [
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: SAST_IAC_NAME,
@@ -176,15 +167,6 @@ export const securityFeatures = [
helpPath: SAST_IAC_HELP_PATH,
configurationHelpPath: SAST_IAC_CONFIG_HELP_PATH,
type: REPORT_TYPE_SAST_IAC,
-
- // This field is currently hardcoded because SAST IaC 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 will eventually come from the backend, the progress is
- // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
- canEnableByMergeRequest: true,
},
{
name: DAST_NAME,
@@ -206,10 +188,6 @@ export const securityFeatures = [
helpPath: DEPENDENCY_SCANNING_HELP_PATH,
configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH,
type: REPORT_TYPE_DEPENDENCY_SCANNING,
-
- // This field will eventually come from the backend, the progress is
- // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
- canEnableByMergeRequest: true,
},
{
name: CONTAINER_SCANNING_NAME,
@@ -231,16 +209,6 @@ export const securityFeatures = [
helpPath: SECRET_DETECTION_HELP_PATH,
configurationHelpPath: SECRET_DETECTION_CONFIG_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
-
- // This field is currently hardcoded because Secret Detection is always
- // available. It will eventually come from the Backend, the progress is
- // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/333113
- 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: API_FUZZING_NAME,
diff --git a/app/assets/javascripts/security_configuration/components/feature_card.vue b/app/assets/javascripts/security_configuration/components/feature_card.vue
index 33d72b54f86..1c37d8008de 100644
--- a/app/assets/javascripts/security_configuration/components/feature_card.vue
+++ b/app/assets/javascripts/security_configuration/components/feature_card.vue
@@ -24,9 +24,6 @@ export default {
enabled() {
return this.available && this.feature.configured;
},
- hasStatus() {
- return !this.available || typeof this.feature.configured === 'boolean';
- },
shortName() {
return this.feature.shortName ?? this.feature.name;
},
@@ -93,19 +90,17 @@ export default {
data-testid="feature-status"
:data-qa-selector="`${feature.type}_status`"
>
- <template v-if="hasStatus">
- <template v-if="enabled">
- <gl-icon name="check-circle-filled" />
- <span class="gl-text-green-700">{{ $options.i18n.enabled }}</span>
- </template>
+ <template v-if="enabled">
+ <gl-icon name="check-circle-filled" />
+ <span class="gl-text-green-700">{{ $options.i18n.enabled }}</span>
+ </template>
- <template v-else-if="available">
- {{ $options.i18n.notEnabled }}
- </template>
+ <template v-else-if="available">
+ {{ $options.i18n.notEnabled }}
+ </template>
- <template v-else>
- {{ $options.i18n.availableWith }}
- </template>
+ <template v-else>
+ {{ $options.i18n.availableWith }}
</template>
</div>
</div>
diff --git a/app/assets/javascripts/security_configuration/components/training_provider_list.vue b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
index ca4596e16b3..539e2bff17c 100644
--- a/app/assets/javascripts/security_configuration/components/training_provider_list.vue
+++ b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
@@ -1,6 +1,13 @@
<script>
import { GlAlert, GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import Tracking from '~/tracking';
import { __ } from '~/locale';
+import {
+ TRACK_TOGGLE_TRAINING_PROVIDER_ACTION,
+ TRACK_TOGGLE_TRAINING_PROVIDER_LABEL,
+} from '~/security_configuration/constants';
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
import configureSecurityTrainingProvidersMutation from '../graphql/configure_security_training_providers.mutation.graphql';
@@ -21,10 +28,19 @@ export default {
GlLink,
GlSkeletonLoader,
},
- inject: ['projectPath'],
+ mixins: [Tracking.mixin()],
+ inject: ['projectFullPath'],
apollo: {
securityTrainingProviders: {
query: securityTrainingProvidersQuery,
+ variables() {
+ return {
+ fullPath: this.projectFullPath,
+ };
+ },
+ update({ project }) {
+ return project?.securityTrainingProviders;
+ },
error() {
this.errorMessage = this.$options.i18n.providerQueryErrorMessage;
},
@@ -33,8 +49,9 @@ export default {
data() {
return {
errorMessage: '',
- toggleLoading: false,
+ providerLoadingId: null,
securityTrainingProviders: [],
+ hasTouchedConfiguration: false,
};
},
computed: {
@@ -42,33 +59,59 @@ export default {
return this.$apollo.queries.securityTrainingProviders.loading;
},
},
+ created() {
+ const unwatchConfigChance = this.$watch('hasTouchedConfiguration', () => {
+ this.dismissFeaturePromotionCallout();
+ unwatchConfigChance();
+ });
+ },
methods: {
- toggleProvider(selectedProviderId) {
- const toggledProviders = this.securityTrainingProviders.map((provider) => ({
- ...provider,
- ...(provider.id === selectedProviderId && { isEnabled: !provider.isEnabled }),
- }));
+ async dismissFeaturePromotionCallout() {
+ try {
+ const {
+ data: {
+ userCalloutCreate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: dismissUserCalloutMutation,
+ variables: {
+ input: {
+ featureName: 'security_training_feature_promotion',
+ },
+ },
+ });
- const enabledProviderIds = toggledProviders
- .filter(({ isEnabled }) => isEnabled)
- .map(({ id }) => id);
+ // handle errors reported from the backend
+ if (errors?.length > 0) {
+ throw new Error(errors[0]);
+ }
+ } catch (e) {
+ Sentry.captureException(e);
+ }
+ },
+ toggleProvider(provider) {
+ const { isEnabled } = provider;
+ const toggledIsEnabled = !isEnabled;
- this.storeEnabledProviders(toggledProviders, enabledProviderIds);
+ this.trackProviderToggle(provider.id, toggledIsEnabled);
+ this.storeProvider({ ...provider, isEnabled: toggledIsEnabled });
},
- async storeEnabledProviders(toggledProviders, enabledProviderIds) {
- this.toggleLoading = true;
+ async storeProvider({ id, isEnabled, isPrimary }) {
+ this.providerLoadingId = id;
try {
const {
data: {
- configureSecurityTrainingProviders: { errors = [] },
+ securityTrainingUpdate: { errors = [] },
},
} = await this.$apollo.mutate({
mutation: configureSecurityTrainingProvidersMutation,
variables: {
input: {
- enabledProviders: enabledProviderIds,
- fullPath: this.projectPath,
+ projectPath: this.projectFullPath,
+ providerId: id,
+ isEnabled,
+ isPrimary,
},
},
});
@@ -77,12 +120,23 @@ export default {
// throwing an error here means we can handle scenarios within the `catch` block below
throw new Error();
}
+
+ this.hasTouchedConfiguration = true;
} catch {
this.errorMessage = this.$options.i18n.configMutationErrorMessage;
} finally {
- this.toggleLoading = false;
+ this.providerLoadingId = null;
}
},
+ trackProviderToggle(providerId, providerIsEnabled) {
+ this.track(TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, {
+ label: TRACK_TOGGLE_TRAINING_PROVIDER_LABEL,
+ property: providerId,
+ extra: {
+ providerIsEnabled,
+ },
+ });
+ },
},
i18n,
};
@@ -104,25 +158,21 @@ export default {
</gl-skeleton-loader>
</div>
<ul v-else class="gl-list-style-none gl-m-0 gl-p-0">
- <li
- v-for="{ id, isEnabled, name, description, url } in securityTrainingProviders"
- :key="id"
- class="gl-mb-6"
- >
+ <li v-for="provider in securityTrainingProviders" :key="provider.id" class="gl-mb-6">
<gl-card>
<div class="gl-display-flex">
<gl-toggle
- :value="isEnabled"
+ :value="provider.isEnabled"
:label="__('Training mode')"
label-position="hidden"
- :is-loading="toggleLoading"
- @change="toggleProvider(id)"
+ :is-loading="providerLoadingId === provider.id"
+ @change="toggleProvider(provider)"
/>
<div class="gl-ml-5">
- <h3 class="gl-font-lg gl-m-0 gl-mb-2">{{ name }}</h3>
+ <h3 class="gl-font-lg gl-m-0 gl-mb-2">{{ provider.name }}</h3>
<p>
- {{ description }}
- <gl-link :href="url" target="_blank">{{ __('Learn more.') }}</gl-link>
+ {{ provider.description }}
+ <gl-link :href="provider.url" target="_blank">{{ __('Learn more.') }}</gl-link>
</p>
</div>
</div>
diff --git a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
index 79e6b9d7a23..891d7bf2eb0 100644
--- a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
+++ b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
@@ -1,11 +1,16 @@
<script>
import { GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+
+export const SECURITY_UPGRADE_BANNER = 'security_upgrade_banner';
+export const UPGRADE_OR_FREE_TRIAL = 'upgrade_or_free_trial';
export default {
components: {
GlBanner,
},
+ mixins: [Tracking.mixin({ property: SECURITY_UPGRADE_BANNER })],
inject: ['upgradePath'],
i18n: {
title: s__('SecurityConfiguration|Secure your project'),
@@ -22,6 +27,17 @@ export default {
],
buttonText: s__('SecurityConfiguration|Upgrade or start a free trial'),
},
+ mounted() {
+ this.track('render', { label: SECURITY_UPGRADE_BANNER });
+ },
+ methods: {
+ bannerClosed() {
+ this.track('dismiss_banner', { label: SECURITY_UPGRADE_BANNER });
+ },
+ bannerButtonClicked() {
+ this.track('click_button', { label: UPGRADE_OR_FREE_TRIAL });
+ },
+ },
};
</script>
@@ -31,6 +47,8 @@ export default {
:button-text="$options.i18n.buttonText"
:button-link="upgradePath"
variant="introduction"
+ @close="bannerClosed"
+ @primary="bannerButtonClicked"
v-on="$listeners"
>
<p>{{ $options.i18n.bodyStart }}</p>
diff --git a/app/assets/javascripts/security_configuration/constants.js b/app/assets/javascripts/security_configuration/constants.js
new file mode 100644
index 00000000000..dc76436e91d
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/constants.js
@@ -0,0 +1,2 @@
+export const TRACK_TOGGLE_TRAINING_PROVIDER_ACTION = 'toggle_security_training_provider';
+export const TRACK_TOGGLE_TRAINING_PROVIDER_LABEL = 'update_security_training_provider';
diff --git a/app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql b/app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql
index 660e0fadafb..3528bfaf7b8 100644
--- a/app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql
+++ b/app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql
@@ -1,9 +1,10 @@
-mutation configureSecurityTrainingProviders($input: configureSecurityTrainingProvidersInput!) {
- configureSecurityTrainingProviders(input: $input) @client {
+mutation updateSecurityTraining($input: SecurityTrainingUpdateInput!) {
+ securityTrainingUpdate(input: $input) {
errors
- securityTrainingProviders {
+ training {
id
isEnabled
+ isPrimary
}
}
}
diff --git a/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql b/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql
index e0c5715ba8e..2baeda318f3 100644
--- a/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql
+++ b/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql
@@ -1,9 +1,13 @@
-query Query {
- securityTrainingProviders @client {
- name
+query getSecurityTrainingProviders($fullPath: ID!) {
+ project(fullPath: $fullPath) {
id
- description
- isEnabled
- url
+ securityTrainingProviders {
+ name
+ id
+ description
+ isPrimary
+ isEnabled
+ url
+ }
}
}
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index 24c0585e077..8416692dd27 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -5,7 +5,6 @@ import { parseBooleanDataAttributes } from '~/lib/utils/dom_utils';
import SecurityConfigurationApp from './components/app.vue';
import { securityFeatures, complianceFeatures } from './components/constants';
import { augmentFeatures } from './utils';
-import tempResolvers from './resolver';
export const initSecurityConfiguration = (el) => {
if (!el) {
@@ -15,11 +14,11 @@ export const initSecurityConfiguration = (el) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(tempResolvers),
+ defaultClient: createDefaultClient(),
});
const {
- projectPath,
+ projectFullPath,
upgradePath,
features,
latestPipelinePath,
@@ -38,7 +37,7 @@ export const initSecurityConfiguration = (el) => {
el,
apolloProvider,
provide: {
- projectPath,
+ projectFullPath,
upgradePath,
autoDevopsHelpPagePath,
autoDevopsPath,
diff --git a/app/assets/javascripts/security_configuration/resolver.js b/app/assets/javascripts/security_configuration/resolver.js
deleted file mode 100644
index 93175d4a3d1..00000000000
--- a/app/assets/javascripts/security_configuration/resolver.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import produce from 'immer';
-import { __ } from '~/locale';
-import securityTrainingProvidersQuery from './graphql/security_training_providers.query.graphql';
-
-// Note: this is behind a feature flag and only a placeholder
-// until the actual GraphQL fields have been added
-// https://gitlab.com/gitlab-org/gi tlab/-/issues/346480
-export default {
- Query: {
- securityTrainingProviders() {
- return [
- {
- __typename: 'SecurityTrainingProvider',
- id: 101,
- name: __('Kontra'),
- description: __('Interactive developer security education.'),
- url: 'https://application.security/',
- isEnabled: false,
- },
- {
- __typename: 'SecurityTrainingProvider',
- id: 102,
- name: __('SecureCodeWarrior'),
- description: __('Security training with guide and learning pathways.'),
- url: 'https://www.securecodewarrior.com/',
- isEnabled: true,
- },
- ];
- },
- },
-
- Mutation: {
- configureSecurityTrainingProviders: (
- _,
- { input: { enabledProviders, primaryProvider } },
- { cache },
- ) => {
- const sourceData = cache.readQuery({
- query: securityTrainingProvidersQuery,
- });
-
- const data = produce(sourceData.securityTrainingProviders, (draftData) => {
- /* eslint-disable no-param-reassign */
- draftData.forEach((provider) => {
- provider.isPrimary = provider.id === primaryProvider;
- provider.isEnabled =
- provider.id === primaryProvider || enabledProviders.includes(provider.id);
- });
- });
- return {
- __typename: 'configureSecurityTrainingProvidersPayload',
- securityTrainingProviders: data,
- };
- },
- },
-};
diff --git a/app/assets/javascripts/security_configuration/utils.js b/app/assets/javascripts/security_configuration/utils.js
index 47231497b8f..173560f8370 100644
--- a/app/assets/javascripts/security_configuration/utils.js
+++ b/app/assets/javascripts/security_configuration/utils.js
@@ -1,6 +1,19 @@
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
+/**
+ * This function takes in 3 arrays of objects, securityFeatures, complianceFeatures and features.
+ * securityFeatures and complianceFeatures are static arrays living in the constants.
+ * features is dynamic and coming from the backend.
+ * This function builds a superset of those arrays.
+ * It looks for matching keys within the dynamic and the static arrays
+ * and will enrich the objects with the available static data.
+ * @param [{}] securityFeatures
+ * @param [{}] complianceFeatures
+ * @param [{}] features
+ * @returns {Object} Object with enriched features from constants divided into Security and Compliance Features
+ */
+
export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
const featuresByType = features.reduce((acc, feature) => {
acc[feature.type] = convertObjectPropsToCamelCase(feature, { deep: true });
diff --git a/app/assets/javascripts/serverless/components/empty_state.vue b/app/assets/javascripts/serverless/components/empty_state.vue
index 8a5ed9debb3..6d1cea519c4 100644
--- a/app/assets/javascripts/serverless/components/empty_state.vue
+++ b/app/assets/javascripts/serverless/components/empty_state.vue
@@ -1,6 +1,8 @@
<script>
import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { mapState } from 'vuex';
+import { s__ } from '~/locale';
+import { DEPRECATION_POST_LINK } from '../constants';
export default {
components: {
@@ -8,6 +10,13 @@ export default {
GlLink,
GlSprintf,
},
+ i18n: {
+ title: s__('Serverless|Getting started with serverless'),
+ description: s__(
+ 'Serverless|Serverless was %{postLinkStart}deprecated%{postLinkEnd}. But if you opt to use it, you must install Knative in your Kubernetes cluster first. %{linkStart}Learn more.%{linkEnd}',
+ ),
+ },
+ deprecationPostLink: DEPRECATION_POST_LINK,
computed: {
...mapState(['emptyImagePath', 'helpPath']),
},
@@ -15,18 +24,12 @@ export default {
</script>
<template>
- <gl-empty-state
- :svg-path="emptyImagePath"
- :title="s__('Serverless|Getting started with serverless')"
- >
+ <gl-empty-state :svg-path="emptyImagePath" :title="$options.i18n.title">
<template #description>
- <gl-sprintf
- :message="
- s__(
- 'Serverless|In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. %{linkStart}More information%{linkEnd}',
- )
- "
- >
+ <gl-sprintf :message="$options.i18n.description">
+ <template #postLink="{ content }">
+ <gl-link :href="$options.deprecationPostLink" target="_blank">{{ content }}</gl-link>
+ </template>
<template #link="{ content }">
<gl-link :href="helpPath">{{ content }}</gl-link>
</template>
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index b2d7aa75051..e9461aa3ead 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,8 +1,14 @@
<script>
-import { GlLink, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import {
+ GlLink,
+ GlAlert,
+ GlSprintf,
+ GlLoadingIcon,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
import { mapState, mapActions, mapGetters } from 'vuex';
import { sprintf, s__ } from '~/locale';
-import { CHECKING_INSTALLED } from '../constants';
+import { CHECKING_INSTALLED, DEPRECATION_POST_LINK } from '../constants';
import EmptyState from './empty_state.vue';
import EnvironmentRow from './environment_row.vue';
@@ -11,11 +17,14 @@ export default {
EnvironmentRow,
EmptyState,
GlLink,
+ GlAlert,
+ GlSprintf,
GlLoadingIcon,
},
directives: {
SafeHtml,
},
+ deprecationPostLink: DEPRECATION_POST_LINK,
computed: {
...mapState(['installed', 'isLoading', 'hasFunctionData', 'helpPath', 'statusPath']),
...mapGetters(['getFunctions']),
@@ -65,6 +74,17 @@ export default {
<template>
<section id="serverless-functions" class="flex-grow">
+ <gl-alert class="gl-mt-6" variant="warning" :dismissible="false">
+ <gl-sprintf
+ :message="s__('Serverless|Serverless was %{linkStart}deprecated%{linkEnd} in GitLab 14.3.')"
+ ><template #link="{ content }"
+ ><gl-link :href="$options.deprecationPostLink" target="_blank">{{
+ content
+ }}</gl-link></template
+ ></gl-sprintf
+ >
+ </gl-alert>
+
<gl-loading-icon v-if="checkingInstalled" size="lg" class="gl-mt-3 gl-mb-3" />
<div v-else-if="isInstalled">
diff --git a/app/assets/javascripts/serverless/constants.js b/app/assets/javascripts/serverless/constants.js
index 2fa15e56ccb..42c9ee983b4 100644
--- a/app/assets/javascripts/serverless/constants.js
+++ b/app/assets/javascripts/serverless/constants.js
@@ -5,3 +5,6 @@ export const X_INTERVAL = 5; // Reflects the number of verticle bars on the x-ax
export const CHECKING_INSTALLED = 'checking'; // The backend is still determining whether or not Knative is installed
export const TIMEOUT = 'timeout';
+
+export const DEPRECATION_POST_LINK =
+ 'https://about.gitlab.com/releases/2021/09/22/gitlab-14-3-released/#gitlab-serverless';
diff --git a/app/assets/javascripts/serverless/survey_banner.js b/app/assets/javascripts/serverless/survey_banner.js
deleted file mode 100644
index 070e8f4c661..00000000000
--- a/app/assets/javascripts/serverless/survey_banner.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import Vue from 'vue';
-import { setUrlParams } from '~/lib/utils/url_utility';
-import SurveyBanner from './survey_banner.vue';
-
-let bannerInstance;
-const SURVEY_URL_BASE = 'https://gitlab.fra1.qualtrics.com/jfe/form/SV_00PfofFfY9s8Shf';
-
-export default function initServerlessSurveyBanner() {
- const el = document.querySelector('.js-serverless-survey-banner');
- if (el && !bannerInstance) {
- const { userName, userEmail } = el.dataset;
-
- // pre-populate survey fields
- const surveyUrl = setUrlParams(
- {
- Q_PopulateResponse: JSON.stringify({
- QID1: userEmail,
- QID2: userName,
- QID16: '1', // selects "yes" to "do you currently use GitLab?"
- }),
- },
- SURVEY_URL_BASE,
- );
-
- bannerInstance = new Vue({
- el,
- render(createElement) {
- return createElement(SurveyBanner, {
- props: {
- surveyUrl,
- },
- });
- },
- });
- }
-}
diff --git a/app/assets/javascripts/serverless/survey_banner.vue b/app/assets/javascripts/serverless/survey_banner.vue
deleted file mode 100644
index c48c294c0f7..00000000000
--- a/app/assets/javascripts/serverless/survey_banner.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-<script>
-import { GlBanner } from '@gitlab/ui';
-import Cookies from 'js-cookie';
-import { parseBoolean } from '~/lib/utils/common_utils';
-
-export default {
- components: {
- GlBanner,
- },
- props: {
- surveyUrl: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- visible: true,
- };
- },
- created() {
- if (parseBoolean(Cookies.get('hide_serverless_survey'))) {
- this.visible = false;
- }
- },
- methods: {
- handleClose() {
- Cookies.set('hide_serverless_survey', 'true', { expires: 365 * 10 });
- this.visible = false;
- },
- },
-};
-</script>
-
-<template>
- <gl-banner
- v-if="visible"
- class="mt-4"
- :title="s__('Serverless|Help shape the future of Serverless at GitLab')"
- :button-text="s__('Serverless|Sign up for First Look')"
- :button-link="surveyUrl"
- @close="handleClose"
- >
- <p>
- {{
- s__(
- 'Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly.',
- )
- }}
- </p>
- </gl-banner>
-</template>
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index 2c6da5669ef..fe5b21713a2 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -18,8 +18,6 @@ export function expandSection(sectionArg) {
const $section = $(sectionArg);
$section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Collapse'));
- // eslint-disable-next-line @gitlab/no-global-event-off
- $section.find('.settings-content').off('scroll.expandSection').scrollTop(0);
$section.addClass('expanded');
if (!$section.hasClass('no-animate')) {
$section
@@ -32,7 +30,6 @@ export function closeSection(sectionArg) {
const $section = $(sectionArg);
$section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Expand'));
- $section.find('.settings-content').on('scroll.expandSection', () => expandSection($section));
$section.removeClass('expanded');
if (!$section.hasClass('no-animate')) {
$section
@@ -55,18 +52,16 @@ export default function initSettingsPanels() {
const $section = $(elm);
$section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
- if (!isExpanded($section)) {
- $section.find('.settings-content').on('scroll.expandSection', () => {
- $section.removeClass('no-animate');
+ if (window.location.hash) {
+ const $target = $(window.location.hash);
+ if (
+ $target.length &&
+ !isExpanded($section) &&
+ ($section.is($target) || $section.find($target).length)
+ ) {
+ $section.addClass('no-animate');
expandSection($section);
- });
+ }
}
});
-
- if (window.location.hash) {
- const $target = $(window.location.hash);
- if ($target.length && $target.hasClass('settings')) {
- expandSection($target);
- }
- }
}
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 5b4dc20e9c8..18654b73ab3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -96,6 +96,9 @@ export default {
return data.workspace?.issuable;
},
result({ data }) {
+ if (!data) {
+ return;
+ }
const issuable = data.workspace?.issuable;
if (issuable) {
this.selected = cloneDeep(issuable.assignees.nodes);
diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
index dc0f2b54a7b..f234c5ea3c9 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
@@ -66,6 +66,9 @@ export default {
return data.workspace?.issuable?.confidential || false;
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.$emit('confidentialityUpdated', data.workspace?.issuable?.confidential);
},
error() {
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 404bcc3122a..be7a89c2869 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
@@ -86,6 +86,9 @@ export default {
return data.workspace?.issuable || {};
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.$emit(`${this.dateType}Updated`, data.workspace?.issuable?.[this.dateType]);
},
error() {
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index da792b3a2aa..ec23e817127 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -10,6 +10,7 @@ import {
GlIcon,
GlTooltipDirective,
} from '@gitlab/ui';
+import { kebabCase, snakeCase } from 'lodash';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { IssuableType } from '~/issues/constants';
@@ -221,6 +222,12 @@ export default {
// MV to EE https://gitlab.com/gitlab-org/gitlab/-/issues/345311
return this.issuableAttribute === IssuableType.Epic;
},
+ formatIssuableAttribute() {
+ return {
+ kebab: kebabCase(this.issuableAttribute),
+ snake: snakeCase(this.issuableAttribute),
+ };
+ },
},
methods: {
updateAttribute(attributeId) {
@@ -300,21 +307,28 @@ export default {
<sidebar-editable-item
ref="editable"
:title="attributeTypeTitle"
- :data-testid="`${issuableAttribute}-edit`"
+ :data-testid="`${formatIssuableAttribute.kebab}-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="attributeTypeIcon" />
- <span class="collapse-truncated-title">
- {{ attributeTitle }}
- </span>
- </div>
+ <slot name="value-collapsed" :current-attribute="currentAttribute">
+ <div
+ v-if="isClassicSidebar"
+ v-gl-tooltip.left.viewport
+ :title="attributeTypeTitle"
+ class="sidebar-collapsed-icon"
+ >
+ <gl-icon :aria-label="attributeTypeTitle" :name="attributeTypeIcon" />
+ <span class="collapse-truncated-title">
+ {{ attributeTitle }}
+ </span>
+ </div>
+ </slot>
<div
- :data-testid="`select-${issuableAttribute}`"
+ :data-testid="`select-${formatIssuableAttribute.kebab}`"
:class="isClassicSidebar ? 'hide-collapsed' : 'gl-mt-3'"
>
<span v-if="updating" class="gl-font-weight-bold">{{ selectedTitle }}</span>
@@ -332,7 +346,7 @@ export default {
v-gl-tooltip="tooltipText"
class="gl-text-gray-900! gl-font-weight-bold"
:href="attributeUrl"
- :data-qa-selector="`${issuableAttribute}_link`"
+ :data-qa-selector="`${formatIssuableAttribute.snake}_link`"
>
{{ attributeTitle }}
<span v-if="isAttributeOverdue(currentAttribute)">{{ $options.i18n.expired }}</span>
@@ -354,7 +368,7 @@ export default {
>
<gl-search-box-by-type ref="search" v-model="searchTerm" />
<gl-dropdown-item
- :data-testid="`no-${issuableAttribute}-item`"
+ :data-testid="`no-${formatIssuableAttribute.kebab}-item`"
:is-check-item="true"
:is-checked="isAttributeChecked($options.noAttributeId)"
@click="updateAttribute($options.noAttributeId)"
@@ -384,7 +398,7 @@ export default {
:key="attrItem.id"
:is-check-item="true"
:is-checked="isAttributeChecked(attrItem.id)"
- :data-testid="`${issuableAttribute}-items`"
+ :data-testid="`${formatIssuableAttribute.kebab}-items`"
@click="updateAttribute(attrItem.id)"
>
{{ attrItem.title }}
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 701833c4e95..7a10a9f3a4c 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
@@ -61,6 +61,9 @@ export default {
return data.workspace?.issuable?.subscribed || false;
},
result({ data }) {
+ if (!data) {
+ return;
+ }
this.emailsDisabled = this.parentIsGroup
? data.workspace?.emailsDisabled
: data.workspace?.issuable?.emailsDisabled;
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
index 7c157fe2775..bb90ef8e444 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -38,7 +38,10 @@ export default {
</script>
<template>
- <div data-testid="helpPane" class="time-tracking-help-state">
+ <div
+ data-testid="helpPane"
+ class="sidebar-help-state gl-bg-white gl-border-gray-100 gl-border-t-solid gl-border-b-solid gl-border-1"
+ >
<div class="time-tracking-info">
<h4>{{ __('Track time with quick actions') }}</h4>
<p>{{ __('Quick actions can be used in description and comment boxes.') }}</p>
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 91c67a03dfb..d222a2af382 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon, GlLink, GlModal, GlModalDirective, GlLoadingIcon } from '@gitlab/ui';
+import { GlIcon, GlLink, GlModal, GlButton, GlModalDirective, GlLoadingIcon } from '@gitlab/ui';
import { IssuableType } from '~/issues/constants';
import { s__, __ } from '~/locale';
import { timeTrackingQueries } from '~/sidebar/constants';
@@ -21,6 +21,7 @@ export default {
GlIcon,
GlLink,
GlModal,
+ GlButton,
GlLoadingIcon,
TimeTrackingCollapsedState,
TimeTrackingSpentOnlyPane,
@@ -187,7 +188,11 @@ export default {
</script>
<template>
- <div v-cloak class="time-tracker time-tracking-component-wrap" data-testid="time-tracker">
+ <div
+ v-cloak
+ class="time-tracker time-tracking-component-wrap sidebar-help-wrap"
+ data-testid="time-tracker"
+ >
<time-tracking-collapsed-state
v-if="showCollapsed"
:show-comparison-state="showComparisonState"
@@ -198,25 +203,21 @@ export default {
:time-spent-human-readable="humanTotalTimeSpent"
:time-estimate-human-readable="humanTimeEstimate"
/>
- <div class="hide-collapsed gl-line-height-20 gl-text-gray-900">
+ <div
+ class="hide-collapsed gl-line-height-20 gl-text-gray-900 gl-display-flex gl-align-items-center"
+ >
{{ __('Time tracking') }}
<gl-loading-icon v-if="isTimeTrackingInfoLoading" size="sm" inline />
- <div
- v-if="!showHelpState"
- data-testid="helpButton"
- class="help-button float-right"
- @click="toggleHelpState(true)"
+ <gl-button
+ :data-testid="showHelpState ? 'closeHelpButton' : 'helpButton'"
+ category="tertiary"
+ size="small"
+ variant="link"
+ class="gl-ml-auto"
+ @click="toggleHelpState(!showHelpState)"
>
- <gl-icon name="question-o" />
- </div>
- <div
- v-else
- data-testid="closeHelpButton"
- class="close-help-button float-right"
- @click="toggleHelpState(false)"
- >
- <gl-icon name="close" />
- </div>
+ <gl-icon :name="showHelpState ? 'close' : 'question-o'" class="gl-text-gray-900!" />
+ </gl-button>
</div>
<div v-if="!isTimeTrackingInfoLoading" class="hide-collapsed">
<div v-if="showEstimateOnlyState" data-testid="estimateOnlyPane">
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
index a9c4203af22..eabba619af5 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
@@ -59,6 +59,10 @@ export default {
return data.workspace?.issuable?.currentUserTodos.nodes[0]?.id;
},
result({ data }) {
+ if (!data) {
+ return;
+ }
+
const currentUserTodos = data.workspace?.issuable?.currentUserTodos?.nodes ?? [];
this.todoId = currentUserTodos[0]?.id;
this.$emit('todoUpdated', currentUserTodos.length > 0);
@@ -177,19 +181,14 @@ export default {
/>
<gl-button
v-if="isClassicSidebar"
+ v-gl-tooltip.left.viewport
+ :title="tootltipTitle"
category="tertiary"
type="reset"
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! gl-shadow-none!"
@click.stop.prevent="toggleTodo"
>
- <gl-icon
- v-gl-tooltip.left.viewport
- :title="tootltipTitle"
- :size="16"
- :class="{ 'todo-undone': hasTodo }"
- :name="collapsedButtonIcon"
- :aria-label="collapsedButtonIcon"
- />
+ <gl-icon :class="{ 'todo-undone': hasTodo }" :name="collapsedButtonIcon" />
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/fragmentTypes.json b/app/assets/javascripts/sidebar/fragmentTypes.json
deleted file mode 100644
index a1c68bba454..00000000000
--- a/app/assets/javascripts/sidebar/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"UNION","name":"Issuable","possibleTypes":[{"name":"Issue"},{"name":"MergeRequest"}]}, {"kind":"INTERFACE","name":"User","possibleTypes":[{"name":"UserCore"}]}]}}
diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js
index 5b2ce3fe446..fc757922f09 100644
--- a/app/assets/javascripts/sidebar/graphql.js
+++ b/app/assets/javascripts/sidebar/graphql.js
@@ -1,15 +1,11 @@
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import produce from 'immer';
import VueApollo from 'vue-apollo';
import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.graphql';
+import { resolvers as workItemResolvers } from '~/work_items/graphql/resolvers';
import createDefaultClient from '~/lib/graphql';
-import introspectionQueryResultData from './fragmentTypes.json';
-
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
const resolvers = {
+ ...workItemResolvers,
Mutation: {
updateIssueState: (_, { issueType = undefined, isDirty = false }, { cache }) => {
const sourceData = cache.readQuery({ query: getIssueStateQuery });
@@ -18,14 +14,11 @@ const resolvers = {
});
cache.writeQuery({ query: getIssueStateQuery, data });
},
+ ...workItemResolvers.Mutation,
},
};
-export const defaultClient = createDefaultClient(resolvers, {
- cacheConfig: {
- fragmentMatcher,
- },
-});
+export const defaultClient = createDefaultClient(resolvers);
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 1947c4801db..2aacce2fb00 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -21,6 +21,7 @@ export default class SidebarMilestone {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarMilestoneRoot',
components: {
timeTracker,
},
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 6363422259e..c29784aa328 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -57,6 +57,7 @@ function mountSidebarToDoWidget() {
return new Vue({
el,
+ name: 'SidebarTodoRoot',
apolloProvider,
components: {
SidebarTodoWidget,
@@ -103,6 +104,7 @@ function mountAssigneesComponentDeprecated(mediator) {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarAssigneesRoot',
apolloProvider,
components: {
SidebarAssignees,
@@ -135,6 +137,7 @@ function mountAssigneesComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarAssigneesRoot',
apolloProvider,
components: {
SidebarAssigneesWidget,
@@ -185,6 +188,7 @@ function mountReviewersComponent(mediator) {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarReviewersRoot',
apolloProvider,
components: {
SidebarReviewers,
@@ -218,6 +222,7 @@ function mountCrmContactsComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarCrmContactsRoot',
apolloProvider,
components: {
CrmContacts,
@@ -242,6 +247,7 @@ function mountMilestoneSelect() {
return new Vue({
el,
+ name: 'SidebarMilestoneRoot',
apolloProvider,
components: {
SidebarDropdownWidget,
@@ -274,6 +280,7 @@ export function mountSidebarLabels() {
return new Vue({
el,
+ name: 'SidebarLabelsRoot',
apolloProvider,
components: {
@@ -328,6 +335,7 @@ function mountConfidentialComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarConfidentialRoot',
apolloProvider,
components: {
SidebarConfidentialityWidget,
@@ -362,6 +370,7 @@ function mountDueDateComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarDueDateRoot',
apolloProvider,
components: {
SidebarDueDateWidget,
@@ -392,6 +401,7 @@ function mountReferenceComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarReferenceRoot',
apolloProvider,
components: {
SidebarReferenceWidget,
@@ -428,6 +438,7 @@ function mountLockComponent(store) {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarLockRoot',
store,
provide: {
fullPath,
@@ -451,6 +462,7 @@ function mountParticipantsComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarParticipantsRoot',
apolloProvider,
components: {
SidebarParticipantsWidget,
@@ -479,6 +491,7 @@ function mountSubscriptionsComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarSubscriptionsRoot',
apolloProvider,
components: {
SidebarSubscriptionsWidget,
@@ -509,6 +522,7 @@ function mountTimeTrackingComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarTimeTrackingRoot',
apolloProvider,
provide: { issuableType },
render: (createElement) =>
@@ -534,6 +548,7 @@ function mountSeverityComponent() {
return new Vue({
el: severityContainerEl,
+ name: 'SidebarSeverityRoot',
apolloProvider,
components: {
SidebarSeverity,
@@ -562,6 +577,7 @@ function mountCopyEmailComponent() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'SidebarCopyEmailRoot',
render: (createElement) =>
createElement(CopyEmailToClipboard, { props: { issueEmailAddress: createNoteEmail } }),
});
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 25468d4a697..4664bb56958 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,4 +1,4 @@
-import Store from 'ee_else_ce/sidebar/stores/sidebar_store';
+import Store from '~/sidebar/stores/sidebar_store';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
diff --git a/app/assets/javascripts/tabs/constants.js b/app/assets/javascripts/tabs/constants.js
index 3b84d7394d4..90c9a89d652 100644
--- a/app/assets/javascripts/tabs/constants.js
+++ b/app/assets/javascripts/tabs/constants.js
@@ -1,8 +1,4 @@
-export const ACTIVE_TAB_CLASSES = Object.freeze([
- 'active',
- 'gl-tab-nav-item-active',
- 'gl-tab-nav-item-active-indigo',
-]);
+export const ACTIVE_TAB_CLASSES = Object.freeze(['active', 'gl-tab-nav-item-active']);
export const ACTIVE_PANEL_CLASS = 'active';
diff --git a/app/assets/javascripts/terraform/components/states_table.vue b/app/assets/javascripts/terraform/components/states_table.vue
index d066834540f..efc2991f40f 100644
--- a/app/assets/javascripts/terraform/components/states_table.vue
+++ b/app/assets/javascripts/terraform/components/states_table.vue
@@ -1,14 +1,5 @@
<script>
-import {
- GlAlert,
- GlBadge,
- GlIcon,
- GlLink,
- GlLoadingIcon,
- GlSprintf,
- GlTable,
- GlTooltip,
-} from '@gitlab/ui';
+import { GlAlert, GlBadge, GlLink, GlLoadingIcon, GlSprintf, GlTable, GlTooltip } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { s__ } from '~/locale';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
@@ -21,7 +12,6 @@ export default {
CiBadge,
GlAlert,
GlBadge,
- GlIcon,
GlLink,
GlLoadingIcon,
GlSprintf,
@@ -128,7 +118,7 @@ export default {
>
<template #cell(name)="{ item }">
<div
- class="gl-display-flex align-items-center gl-justify-content-end gl-justify-content-md-start"
+ class="gl-display-flex align-items-center gl-justify-content-end gl-md-justify-content-start"
data-testid="terraform-states-table-name"
>
<p class="gl-font-weight-bold gl-m-0 gl-text-gray-900">
@@ -156,8 +146,7 @@ export default {
:id="`terraformLockedBadgeContainer${item.name}`"
class="gl-mx-3"
>
- <gl-badge :id="`terraformLockedBadge${item.name}`">
- <gl-icon name="lock" />
+ <gl-badge :id="`terraformLockedBadge${item.name}`" icon="lock">
{{ $options.i18n.locked }}
</gl-badge>
diff --git a/app/assets/javascripts/terraform/index.js b/app/assets/javascripts/terraform/index.js
index 1b8cab0d51e..34261f3c4db 100644
--- a/app/assets/javascripts/terraform/index.js
+++ b/app/assets/javascripts/terraform/index.js
@@ -1,5 +1,5 @@
+import { defaultDataIdFromObject } from '@apollo/client/core';
import { GlToast } from '@gitlab/ui';
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
diff --git a/app/assets/javascripts/toggles/index.js b/app/assets/javascripts/toggles/index.js
new file mode 100644
index 00000000000..046b9fc7dcd
--- /dev/null
+++ b/app/assets/javascripts/toggles/index.js
@@ -0,0 +1,65 @@
+import { kebabCase } from 'lodash';
+import Vue from 'vue';
+import { GlToggle } from '@gitlab/ui';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+export const initToggle = (el) => {
+ if (!el) {
+ return false;
+ }
+
+ const {
+ name,
+ isChecked,
+ disabled,
+ isLoading,
+ label,
+ help,
+ labelPosition,
+ ...dataset
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ props: {
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: parseBoolean(disabled),
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: parseBoolean(isLoading),
+ },
+ },
+ data() {
+ return {
+ value: parseBoolean(isChecked),
+ };
+ },
+ render(h) {
+ return h(GlToggle, {
+ props: {
+ name,
+ value: this.value,
+ disabled: this.disabled,
+ isLoading: this.isLoading,
+ label,
+ help,
+ labelPosition,
+ },
+ class: el.className,
+ attrs: Object.fromEntries(
+ Object.entries(dataset).map(([key, value]) => [`data-${kebabCase(key)}`, value]),
+ ),
+ on: {
+ change: (newValue) => {
+ this.value = newValue;
+ this.$emit('change', newValue);
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
index 49a43b120e0..4639671984a 100644
--- a/app/assets/javascripts/tooltips/index.js
+++ b/app/assets/javascripts/tooltips/index.js
@@ -21,6 +21,7 @@ const tooltipsApp = () => {
document.body.appendChild(container);
app = new Vue({
+ name: 'TooltipsRoot',
render(h) {
return h(Tooltips, {
props: {
diff --git a/app/assets/javascripts/user_callout.js b/app/assets/javascripts/user_callout.js
index 44e54c85f3c..ee23f8c5a0c 100644
--- a/app/assets/javascripts/user_callout.js
+++ b/app/assets/javascripts/user_callout.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import Cookies from 'js-cookie';
+import { getCookie, setCookie } from '~/lib/utils/common_utils';
export default class UserCallout {
constructor(options = {}) {
@@ -9,7 +9,7 @@ export default class UserCallout {
this.userCalloutBody = $(`.${className}`);
this.cookieName = this.userCalloutBody.data('uid');
- this.isCalloutDismissed = Cookies.get(this.cookieName);
+ this.isCalloutDismissed = getCookie(this.cookieName);
this.init();
}
@@ -30,7 +30,7 @@ export default class UserCallout {
cookieOptions.path = this.userCalloutBody.data('projectPath');
}
- Cookies.set(this.cookieName, 'true', cookieOptions);
+ setCookie(this.cookieName, 'true', cookieOptions);
if ($currentTarget.hasClass('close') || $currentTarget.hasClass('js-close')) {
this.userCalloutBody.remove();
diff --git a/app/assets/javascripts/vue_alerts.js b/app/assets/javascripts/vue_alerts.js
index b44f787cf30..f3bf121c0f8 100644
--- a/app/assets/javascripts/vue_alerts.js
+++ b/app/assets/javascripts/vue_alerts.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import Cookies from 'js-cookie';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { setCookie, parseBoolean } from '~/lib/utils/common_utils';
+
import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
const getCookieExpirationPeriod = (expirationPeriod) => {
@@ -33,7 +33,7 @@ const mountVueAlert = (el) => {
if (!dismissCookieName) {
return;
}
- Cookies.set(dismissCookieName, true, {
+ setCookie(dismissCookieName, true, {
expires: getCookieExpirationPeriod(dismissCookieExpire),
});
},
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 5ef7c2f72e0..7ba387c79b1 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,6 @@
<script>
import createFlash from '~/flash';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -79,6 +80,7 @@ export default {
[STOPPING]: {
actionName: STOPPING,
buttonText: s__('MrDeploymentActions|Stop environment'),
+ buttonVariant: 'danger',
busyText: __('This environment is being deployed'),
confirmMessage: __('Are you sure you want to stop this environment?'),
errorMessage: __('Something went wrong while stopping this environment. Please try again.'),
@@ -86,6 +88,7 @@ export default {
[DEPLOYING]: {
actionName: DEPLOYING,
buttonText: s__('MrDeploymentActions|Deploy'),
+ buttonVariant: 'confirm',
busyText: __('This environment is being deployed'),
confirmMessage: __('Are you sure you want to deploy this environment?'),
errorMessage: __('Something went wrong while deploying this environment. Please try again.'),
@@ -93,14 +96,27 @@ export default {
[REDEPLOYING]: {
actionName: REDEPLOYING,
buttonText: s__('MrDeploymentActions|Re-deploy'),
+ buttonVariant: 'confirm',
busyText: __('This environment is being re-deployed'),
confirmMessage: __('Are you sure you want to re-deploy this environment?'),
errorMessage: __('Something went wrong while deploying this environment. Please try again.'),
},
},
methods: {
- executeAction(endpoint, { actionName, confirmMessage, errorMessage }) {
- const isConfirmed = confirm(confirmMessage); //eslint-disable-line
+ async executeAction(
+ endpoint,
+ {
+ actionName,
+ buttonText: primaryBtnText,
+ buttonVariant: primaryBtnVariant,
+ confirmMessage,
+ errorMessage,
+ },
+ ) {
+ const isConfirmed = await confirmAction(confirmMessage, {
+ primaryBtnVariant,
+ primaryBtnText,
+ });
if (isConfirmed) {
this.actionInProgress = actionName;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index 7322958e6df..a25b4ab54e5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -128,10 +128,12 @@ export default {
api.trackRedisHllUserEvent(this.$options.expandEvent);
}
}),
- toggleCollapsed() {
- this.isCollapsed = !this.isCollapsed;
+ toggleCollapsed(e) {
+ if (!e?.target?.closest('.btn:not(.btn-icon),a')) {
+ this.isCollapsed = !this.isCollapsed;
- this.triggerRedisTracking();
+ this.triggerRedisTracking();
+ }
},
initExtensionPolling() {
const poll = new Poll({
@@ -139,7 +141,7 @@ export default {
fetchData: () => this.fetchCollapsedData(this.$props),
},
method: 'fetchData',
- successCallback: (data) => {
+ successCallback: ({ data }) => {
if (Object.keys(data).length > 0) {
poll.stop();
this.setCollapsedData(data);
@@ -207,6 +209,19 @@ export default {
this.showFade = true;
}
},
+ onRowMouseDown() {
+ this.down = Number(new Date());
+ },
+ onRowMouseUp(e) {
+ const up = Number(new Date());
+
+ // To allow for text to be selected we check if the the user is clicking
+ // or selecting, if they are selecting the time difference should be
+ // more than 200ms
+ if (up - this.down < 200) {
+ this.toggleCollapsed(e);
+ }
+ },
generateText,
},
EXTENSION_ICON_CLASS,
@@ -215,7 +230,7 @@ export default {
<template>
<section class="media-section" data-testid="widget-extension">
- <div class="media gl-p-5">
+ <div class="media gl-p-5 gl-cursor-pointer" @mousedown="onRowMouseDown" @mouseup="onRowMouseUp">
<status-icon
:name="$options.label || $options.name"
:is-loading="isLoadingSummary"
@@ -253,7 +268,7 @@ export default {
category="tertiary"
data-testid="toggle-button"
size="small"
- @click="toggleCollapsed"
+ @click.self="toggleCollapsed"
/>
</div>
</div>
@@ -317,9 +332,13 @@ export default {
<div v-if="data.link">
<gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
</div>
+ <div v-if="data.supportingText">
+ <p v-safe-html="generateText(data.supportingText)" class="gl-m-0"></p>
+ </div>
<gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
{{ data.badge.text }}
</gl-badge>
+
<actions
:widget="$options.label || $options.name"
:tertiary-buttons="data.actions"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
index cd5b7c3110d..8b410926c46 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
@@ -90,7 +90,7 @@ export default {
</template>
<div class="row">
<div
- class="col-md-5 order-md-last col-12 gl-mt-5 gl-mt-md-n2! gl-pt-md-2 svg-content svg-225"
+ class="col-md-5 order-md-last col-12 gl-mt-5 gl-md-mt-n2! gl-md-pt-2 svg-content svg-225"
>
<img data-testid="pipeline-image" :src="pipelineSvgPath" />
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue
new file mode 100644
index 00000000000..7279ad971be
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlModal, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ name: 'MergeFailedPipelineConfirmationDialog',
+ i18n: {
+ primary: __('Merge unverified changes'),
+ cancel: __('Cancel'),
+ info: __(
+ 'The latest pipeline for this merge request did not succeed. The latest changes are unverified.',
+ ),
+ confirmation: __('Are you sure you want to attempt to merge?'),
+ title: __('Merge unverified changes?'),
+ },
+ components: {
+ GlModal,
+ GlButton,
+ },
+ props: {
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ methods: {
+ hide() {
+ this.$refs.modal.hide();
+ },
+ cancel() {
+ this.hide();
+ this.$emit('cancel');
+ },
+ focusCancelButton() {
+ this.$refs.cancelButton.$el.focus();
+ },
+ mergeChanges() {
+ this.$emit('mergeWithFailedPipeline');
+ this.hide();
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ ref="modal"
+ size="sm"
+ modal-id="merge-train-failed-pipeline-confirmation-dialog"
+ :title="$options.i18n.title"
+ :visible="visible"
+ data-testid="merge-failed-pipeline-confirmation-dialog"
+ @shown="focusCancelButton"
+ @hide="$emit('cancel')"
+ >
+ <p>{{ $options.i18n.info }}</p>
+ <p>{{ $options.i18n.confirmation }}</p>
+ <template #modal-footer>
+ <gl-button ref="cancelButton" data-testid="merge-cancel-btn" @click="cancel">{{
+ $options.i18n.cancel
+ }}</gl-button>
+ <gl-button variant="danger" data-testid="merge-unverified-changes" @click="mergeChanges">
+ {{ $options.i18n.primary }}
+ </gl-button>
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
index 247877a8235..e0c4679b983 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
@@ -1,7 +1,14 @@
<script>
-import { MERGE_ACTIVE_STATUS_PHRASES } from '../../constants';
+import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+import simplePoll from '~/lib/utils/simple_poll';
+import MergeRequest from '../../../merge_request';
+import eventHub from '../../event_hub';
+import { MERGE_ACTIVE_STATUS_PHRASES, STATE_MACHINE } from '../../constants';
import statusIcon from '../mr_widget_status_icon.vue';
+const { transitions } = STATE_MACHINE;
+const { MERGE_FAILURE } = transitions;
+
export default {
name: 'MRWidgetMerging',
components: {
@@ -12,6 +19,10 @@ export default {
type: Object,
required: true,
},
+ service: {
+ type: Object,
+ required: true,
+ },
},
data() {
const statusCount = MERGE_ACTIVE_STATUS_PHRASES.length;
@@ -20,6 +31,53 @@ export default {
mergeStatus: MERGE_ACTIVE_STATUS_PHRASES[Math.floor(Math.random() * statusCount)],
};
},
+ mounted() {
+ this.initiateMergePolling();
+ },
+ methods: {
+ initiateMergePolling() {
+ simplePoll(
+ (continuePolling, stopPolling) => {
+ this.handleMergePolling(continuePolling, stopPolling);
+ },
+ { timeout: 0 },
+ );
+ },
+ handleMergePolling(continuePolling, stopPolling) {
+ this.service
+ .poll()
+ .then((res) => res.data)
+ .then((data) => {
+ if (data.state === 'merged') {
+ // If state is merged we should update the widget and stop the polling
+ eventHub.$emit('MRWidgetUpdateRequested');
+ eventHub.$emit('FetchActionsContent');
+ MergeRequest.hideCloseButton();
+ MergeRequest.decreaseCounter();
+ stopPolling();
+
+ refreshUserMergeRequestCounts();
+
+ // If user checked remove source branch and we didn't remove the branch yet
+ // we should start another polling for source branch remove process
+ if (this.removeSourceBranch && data.source_branch_exists) {
+ this.initiateRemoveSourceBranchPolling();
+ }
+ } else if (data.merge_error) {
+ eventHub.$emit('FailedToMerge', data.merge_error);
+ this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
+ stopPolling();
+ } else {
+ // MR is not merged yet, continue polling until the state becomes 'merged'
+ continuePolling();
+ }
+ })
+ .catch(() => {
+ this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
+ stopPolling();
+ });
+ },
+ },
};
</script>
<template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
index 5b03eda2eac..cadbd9c28a9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
@@ -1,9 +1,14 @@
<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { sprintf, s__ } from '~/locale';
+import { GlIcon, GlTooltipDirective, GlSprintf } from '@gitlab/ui';
+import { sprintf } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import missingBranchQuery from '../../queries/states/missing_branch.query.graphql';
+import {
+ MR_WIDGET_MISSING_BRANCH_WHICH,
+ MR_WIDGET_MISSING_BRANCH_RESTORE,
+ MR_WIDGET_MISSING_BRANCH_MANUALCLI,
+} from '../../i18n';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -13,6 +18,7 @@ export default {
},
components: {
GlIcon,
+ GlSprintf,
statusIcon,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
@@ -45,26 +51,20 @@ export default {
return this.mr.sourceBranchRemoved;
},
- missingBranchName() {
+ type() {
return this.sourceBranchRemoved ? 'source' : 'target';
},
- missingBranchNameMessage() {
- return sprintf(
- s__('mrWidget| Please restore it or use a different %{missingBranchName} branch'),
- {
- missingBranchName: this.missingBranchName,
- },
- );
+ name() {
+ return this.type === 'source' ? this.mr.sourceBranch : this.mr.targetBranch;
+ },
+ warning() {
+ return sprintf(MR_WIDGET_MISSING_BRANCH_WHICH, { type: this.type, name: this.name });
+ },
+ restore() {
+ return sprintf(MR_WIDGET_MISSING_BRANCH_RESTORE, { type: this.type });
},
message() {
- return sprintf(
- s__(
- 'mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line',
- ),
- {
- missingBranchName: this.missingBranchName,
- },
- );
+ return sprintf(MR_WIDGET_MISSING_BRANCH_MANUALCLI, { type: this.type });
},
},
};
@@ -79,9 +79,14 @@ export default {
'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
}"
class="bold js-branch-text"
+ data-testid="widget-content"
>
- <span class="capitalize" data-testid="missingBranchName"> {{ missingBranchName }} </span>
- {{ s__('mrWidget|branch does not exist.') }} {{ missingBranchNameMessage }}
+ <gl-sprintf :message="warning">
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ {{ restore }}
<gl-icon
v-gl-tooltip
:title="message"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
index d88dad2e086..d204befef58 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
@@ -20,7 +20,7 @@ export default {
},
i18n: {
failedMessage: s__(
- `mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions.`,
+ `mrWidget|Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}`,
),
},
};
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 06ce312bd4c..bc094501e89 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
@@ -14,7 +14,6 @@ import {
import { isEmpty } from 'lodash';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import createFlash from '~/flash';
import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import simplePoll from '~/lib/utils/simple_poll';
@@ -22,11 +21,8 @@ import { __, s__ } from '~/locale';
import SmartInterval from '~/smart_interval';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { helpPagePath } from '~/helpers/help_page_helper';
-import MergeRequest from '../../../merge_request';
import {
AUTO_MERGE_STRATEGIES,
- DANGER,
- CONFIRM,
WARNING,
MT_MERGE_STRATEGY,
PIPELINE_FAILED_STATE,
@@ -42,6 +38,7 @@ import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
import CommitsHeader from './commits_header.vue';
import SquashBeforeMerge from './squash_before_merge.vue';
+import MergeFailedPipelineConfirmationDialog from './merge_failed_pipeline_confirmation_dialog.vue';
const PIPELINE_RUNNING_STATE = 'running';
const PIPELINE_PENDING_STATE = 'pending';
@@ -52,7 +49,7 @@ const MERGE_SUCCESS_STATUS = 'success';
const MERGE_HOOK_VALIDATION_ERROR_STATUS = 'hook_validation_error';
const { transitions } = STATE_MACHINE;
-const { MERGE, MERGED, MERGE_FAILURE, AUTO_MERGE } = transitions;
+const { MERGE, MERGE_FAILURE, AUTO_MERGE, MERGING } = transitions;
export default {
name: 'ReadyToMerge',
@@ -106,6 +103,7 @@ export default {
GlDropdownItem,
GlFormCheckbox,
GlSkeletonLoader,
+ MergeFailedPipelineConfirmationDialog,
MergeTrainHelperIcon: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_icon.vue'),
MergeImmediatelyConfirmationDialog: () =>
@@ -138,7 +136,8 @@ export default {
squashBeforeMerge: this.mr.squashIsSelected,
isSquashReadOnly: this.mr.squashIsReadonly,
squashCommitMessage: this.mr.squashCommitMessage,
- isPipelineFailedModalVisible: false,
+ isPipelineFailedModalVisibleMergeTrain: false,
+ isPipelineFailedModalVisibleNormalMerge: false,
editCommitMessage: false,
};
},
@@ -166,6 +165,9 @@ export default {
return this.mr.isPipelineFailed;
},
+ showMergeFailedPipelineConfirmationDialog() {
+ return this.status === PIPELINE_FAILED_STATE && this.isPipelineFailed;
+ },
isMergeAllowed() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.mergeable;
@@ -248,13 +250,6 @@ export default {
return PIPELINE_SUCCESS_STATE;
},
- mergeButtonVariant() {
- if (this.status === PIPELINE_FAILED_STATE || this.isPipelineFailed) {
- return DANGER;
- }
-
- return CONFIRM;
- },
iconClass() {
if (this.shouldRenderMergeTrainHelperIcon && !this.mr.preventMerge) {
return PIPELINE_RUNNING_STATE;
@@ -279,6 +274,10 @@ export default {
return this.autoMergeText;
}
+ if (this.status === PIPELINE_FAILED_STATE || this.isPipelineFailed) {
+ return __('Merge...');
+ }
+
return __('Merge');
},
hasPipelineMustSucceedConflict() {
@@ -361,8 +360,13 @@ export default {
return this.$apollo.queries.state.refetch();
},
handleMergeButtonClick(useAutoMerge, mergeImmediately = false, confirmationClicked = false) {
- if (this.showFailedPipelineModal && !confirmationClicked) {
- this.isPipelineFailedModalVisible = true;
+ if (this.showMergeFailedPipelineConfirmationDialog && !confirmationClicked) {
+ this.isPipelineFailedModalVisibleNormalMerge = true;
+ return;
+ }
+
+ if (this.showFailedPipelineModalMergeTrain && !confirmationClicked) {
+ this.isPipelineFailedModalVisibleMergeTrain = true;
return;
}
@@ -406,7 +410,7 @@ export default {
eventHub.$emit('MRWidgetUpdateRequested');
this.mr.transitionStateMachine({ transition: AUTO_MERGE });
} else if (data.status === MERGE_SUCCESS_STATUS) {
- this.initiateMergePolling();
+ this.mr.transitionStateMachine({ transition: MERGING });
} else if (hasError) {
eventHub.$emit('FailedToMerge', data.merge_error);
this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
@@ -434,51 +438,8 @@ export default {
onMergeImmediatelyConfirmation() {
this.handleMergeButtonClick(false, true, true);
},
- initiateMergePolling() {
- simplePoll(
- (continuePolling, stopPolling) => {
- this.handleMergePolling(continuePolling, stopPolling);
- },
- { timeout: 0 },
- );
- },
- handleMergePolling(continuePolling, stopPolling) {
- this.service
- .poll()
- .then((res) => res.data)
- .then((data) => {
- if (data.state === 'merged') {
- // If state is merged we should update the widget and stop the polling
- eventHub.$emit('MRWidgetUpdateRequested');
- eventHub.$emit('FetchActionsContent');
- MergeRequest.hideCloseButton();
- MergeRequest.decreaseCounter();
- this.mr.transitionStateMachine({ transition: MERGED });
- stopPolling();
-
- refreshUserMergeRequestCounts();
-
- // If user checked remove source branch and we didn't remove the branch yet
- // we should start another polling for source branch remove process
- if (this.removeSourceBranch && data.source_branch_exists) {
- this.initiateRemoveSourceBranchPolling();
- }
- } else if (data.merge_error) {
- eventHub.$emit('FailedToMerge', data.merge_error);
- this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
- stopPolling();
- } else {
- // MR is not merged yet, continue polling until the state becomes 'merged'
- continuePolling();
- }
- })
- .catch(() => {
- createFlash({
- message: __('Something went wrong while merging this merge request. Please try again.'),
- });
- this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
- stopPolling();
- });
+ onMergeWithFailedPipelineConfirmation() {
+ this.handleMergeButtonClick(false, true, true);
},
initiateRemoveSourceBranchPolling() {
// We need to show source branch is being removed spinner in another component
@@ -559,7 +520,7 @@ export default {
category="primary"
class="accept-merge-request"
data-testid="merge-button"
- :variant="mergeButtonVariant"
+ variant="confirm"
:disabled="isMergeButtonDisabled"
:loading="isMakingRequest"
data-qa-selector="merge_button"
@@ -570,7 +531,7 @@ export default {
v-if="shouldShowMergeImmediatelyDropdown"
v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
- :variant="mergeButtonVariant"
+ variant="confirm"
data-qa-selector="merge_moment_dropdown"
toggle-class="btn-icon js-merge-moment"
>
@@ -593,18 +554,22 @@ export default {
/>
</gl-dropdown>
<merge-train-failed-pipeline-confirmation-dialog
- :visible="isPipelineFailedModalVisible"
+ :visible="isPipelineFailedModalVisibleMergeTrain"
@startMergeTrain="onStartMergeTrainConfirmation"
- @cancel="isPipelineFailedModalVisible = false"
+ @cancel="isPipelineFailedModalVisibleMergeTrain = false"
+ />
+ <merge-failed-pipeline-confirmation-dialog
+ :visible="isPipelineFailedModalVisibleNormalMerge"
+ @mergeWithFailedPipeline="onMergeWithFailedPipelineConfirmation"
+ @cancel="isPipelineFailedModalVisibleNormalMerge = false"
/>
</gl-button-group>
+ <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
<div
v-if="shouldShowMergeControls"
:class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }"
class="gl-display-flex gl-align-items-center gl-flex-wrap"
>
- <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
-
<gl-form-checkbox
v-if="canRemoveSourceBranch"
id="remove-source-branch-input"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
index 8cf6383c26a..25ba4bf12af 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
@@ -43,8 +43,8 @@ export default {
class="gl-ml-3"
size="small"
:icon="glFeatures.restructuredMrWidget ? undefined : 'comment-next'"
- :variant="glFeatures.restructuredMrWidget && 'confirm'"
- :category="glFeatures.restructuredMrWidget && 'secondary'"
+ :variant="glFeatures.restructuredMrWidget ? 'confirm' : 'default'"
+ :category="glFeatures.restructuredMrWidget ? 'secondary' : 'primary'"
@click="jumpToFirstUnresolvedDiscussion"
>
{{ s__('mrWidget|Jump to first unresolved thread') }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 32effb91043..d337a554663 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -68,6 +68,7 @@ const STATE_MACHINE = {
states: {
IDLE: 'IDLE',
MERGING: 'MERGING',
+ MERGED: 'MERGED',
AUTO_MERGE: 'AUTO_MERGE',
},
transitions: {
@@ -75,6 +76,7 @@ const STATE_MACHINE = {
AUTO_MERGE: 'start-auto-merge',
MERGE_FAILURE: 'merge-failed',
MERGED: 'merge-done',
+ MERGING: 'merging',
},
};
const { states, transitions } = STATE_MACHINE;
@@ -86,11 +88,12 @@ STATE_MACHINE.definition = {
on: {
[transitions.MERGE]: states.MERGING,
[transitions.AUTO_MERGE]: states.AUTO_MERGE,
+ [transitions.MERGING]: states.MERGING,
},
},
[states.MERGING]: {
on: {
- [transitions.MERGED]: states.IDLE,
+ [transitions.MERGED]: states.MERGED,
[transitions.MERGE_FAILURE]: states.IDLE,
},
},
@@ -110,6 +113,7 @@ export const stateToTransitionMap = {
};
export const stateToComponentMap = {
[states.MERGING]: classStateMap[stateKey.merging],
+ [states.MERGED]: classStateMap[stateKey.merged],
[states.AUTO_MERGE]: classStateMap[stateKey.autoMergeEnabled],
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
new file mode 100644
index 00000000000..168f10bd148
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
@@ -0,0 +1,120 @@
+import { uniqueId } from 'lodash';
+import { __, n__, s__, sprintf } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import { EXTENSION_ICONS } from '../../constants';
+
+export default {
+ name: 'WidgetAccessibility',
+ enablePolling: true,
+ i18n: {
+ loading: s__('Reports|Accessibility scanning results are being parsed'),
+ error: s__('Reports|Accessibility scanning failed loading results'),
+ },
+ props: ['accessibilityReportPath'],
+ computed: {
+ statusIcon() {
+ return this.collapsedData.status === 'failed'
+ ? EXTENSION_ICONS.warning
+ : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ summary() {
+ const numOfResults = this.collapsedData?.summary?.errored || 0;
+
+ const successText = s__(
+ 'Reports|Accessibility scanning detected no issues for the source branch only',
+ );
+ const warningText = sprintf(
+ n__(
+ 'Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only',
+ 'Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only',
+ numOfResults,
+ ),
+ {
+ number: numOfResults,
+ },
+ false,
+ );
+
+ return numOfResults === 0 ? successText : warningText;
+ },
+ fetchCollapsedData() {
+ return axios.get(this.accessibilityReportPath);
+ },
+ fetchFullData() {
+ return Promise.resolve(this.prepareReports());
+ },
+ parsedTECHSCode(code) {
+ /*
+ * In issue code looks like "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail"
+ * or "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent"
+ *
+ * The TECHS code is the "G18", "G168", "H91", etc. from the code which is used for the documentation.
+ * Here we simply split the string on `.` and get the code in the 5th position
+ */
+ return code?.split('.')[4];
+ },
+ formatLearnMoreUrl(code) {
+ const parsed = this.parsedTECHSCode(code);
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `https://www.w3.org/TR/WCAG20-TECHS/${parsed || 'Overview'}.html`;
+ },
+ formatText(code) {
+ return sprintf(
+ s__(
+ 'AccessibilityReport|The accessibility scanning found an error of the following type: %{code}',
+ ),
+ { code },
+ );
+ },
+ formatMessage(message) {
+ return sprintf(s__('AccessibilityReport|Message: %{message}'), { message });
+ },
+ prepareReports() {
+ const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+
+ const newErrors = new_errors.map((error) => {
+ return {
+ header: __('New'),
+ id: uniqueId('new-error-'),
+ text: this.formatText(error.code),
+ icon: { name: EXTENSION_ICONS.failed },
+ link: {
+ href: this.formatLearnMoreUrl(error.code),
+ text: __('Learn more'),
+ },
+ supportingText: this.formatMessage(error.message),
+ };
+ });
+
+ const existingErrors = existing_errors.map((error) => {
+ return {
+ id: uniqueId('existing-error-'),
+ text: this.formatText(error.code),
+ icon: { name: EXTENSION_ICONS.failed },
+ link: {
+ href: this.formatLearnMoreUrl(error.code),
+ text: __('Learn more'),
+ },
+ supportingText: this.formatMessage(error.message),
+ };
+ });
+
+ const resolvedErrors = resolved_errors.map((error) => {
+ return {
+ id: uniqueId('resolved-error-'),
+ text: this.formatText(error.code),
+ icon: { name: EXTENSION_ICONS.success },
+ link: {
+ href: this.formatLearnMoreUrl(error.code),
+ text: __('Learn more'),
+ },
+ supportingText: this.formatMessage(error.message),
+ };
+ });
+
+ return [...newErrors, ...existingErrors, ...resolvedErrors];
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
index ba3336df2eb..4aeebf095c4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -25,9 +25,9 @@ export default {
n__(
'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} change',
'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} changes',
- changesFound,
+ count,
),
- { changesFound },
+ { changesFound: count },
);
},
// Status icon to be used next to the summary text
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js
index a564acada02..8fcc4f818ec 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js
@@ -73,26 +73,30 @@ export default {
return `${title}${subtitle}`;
},
fetchCollapsedData() {
- return Promise.resolve(this.fetchPlans().then(this.prepareReports));
- },
- fetchFullData() {
- const { valid, invalid } = this.collapsedData;
- return Promise.resolve([...valid, ...invalid]);
- },
- // Custom methods
- fetchPlans() {
return axios
.get(this.terraformReportsPath)
- .then(({ data }) => {
- return Object.keys(data).map((key) => {
- return data[key];
+ .then((res) => {
+ const reports = Object.keys(res.data).map((key) => {
+ return res.data[key];
});
+
+ const formattedData = this.prepareReports(reports);
+
+ return {
+ ...res,
+ data: formattedData,
+ };
})
.catch(() => {
- const invalidData = { tf_report_error: 'api_error' };
- return [invalidData];
+ const formattedData = this.prepareReports([{ tf_report_error: 'api_error' }]);
+
+ return { data: formattedData };
});
},
+ fetchFullData() {
+ const { valid, invalid } = this.collapsedData;
+ return Promise.resolve([...valid, ...invalid]);
+ },
createReportRow(report, iconName) {
const addNum = Number(report.create);
const changeNum = Number(report.update);
diff --git a/app/assets/javascripts/vue_merge_request_widget/i18n.js b/app/assets/javascripts/vue_merge_request_widget/i18n.js
index c88e795e5f3..454a14faabb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/i18n.js
+++ b/app/assets/javascripts/vue_merge_request_widget/i18n.js
@@ -1,4 +1,14 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
+
+export const MR_WIDGET_MISSING_BRANCH_WHICH = s__(
+ 'mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist.',
+);
+export const MR_WIDGET_MISSING_BRANCH_RESTORE = s__(
+ 'mrWidget|Please restore it or use a different %{type} branch.',
+);
+export const MR_WIDGET_MISSING_BRANCH_MANUALCLI = s__(
+ 'mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line.',
+);
export const SQUASH_BEFORE_MERGE = {
tooltipTitle: __('Required in this project.'),
@@ -10,3 +20,8 @@ export const I18N_SHA_MISMATCH = {
warningMessage: __('Merge blocked: new changes were just added.'),
actionButtonLabel: __('Review changes'),
};
+
+export const MERGE_TRAIN_BUTTON_TEXT = {
+ failed: __('Start merge train...'),
+ passed: __('Start merge train'),
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index fa618756bb5..247a3711fc8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -48,7 +48,7 @@ export default {
pipelineId() {
return this.pipeline.id;
},
- showFailedPipelineModal() {
+ showFailedPipelineModalMergeTrain() {
return false;
},
},
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 83a07240403..11de58aa344 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
@@ -45,6 +45,7 @@ import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
import getStateQuery from './queries/get_state.query.graphql';
import terraformExtension from './extensions/terraform';
+import accessibilityExtension from './extensions/accessibility';
export default {
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
@@ -205,7 +206,7 @@ export default {
);
},
shouldShowAccessibilityReport() {
- return this.mr.accessibilityReportPath;
+ return Boolean(this.mr?.accessibilityReportPath);
},
formattedHumanAccess() {
return (this.mr.humanAccess || '').toLowerCase();
@@ -240,6 +241,11 @@ export default {
this.registerTerraformPlans();
}
},
+ shouldShowAccessibilityReport(newVal) {
+ if (newVal) {
+ this.registerAccessibilityExtension();
+ }
+ },
},
mounted() {
MRWidgetService.fetchInitialData()
@@ -478,6 +484,11 @@ export default {
registerExtension(terraformExtension);
}
},
+ registerAccessibilityExtension() {
+ if (this.shouldShowAccessibilityReport && this.shouldShowExtension) {
+ registerExtension(accessibilityExtension);
+ }
+ },
},
};
</script>
@@ -567,7 +578,7 @@ export default {
:endpoint="mr.accessibilityReportPath"
/>
- <div class="mr-widget-section">
+ <div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
index 0b8396b4461..25c44beaf18 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
@@ -3,7 +3,6 @@ query getState($projectPath: ID!, $iid: String!) {
id
archived
onlyAllowMergeIfPipelineSucceeds
-
mergeRequest(iid: $iid) {
id
autoMergeEnabled
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
index 2d79d35cf24..ad93a3a7371 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
@@ -4,6 +4,7 @@ query autoMergeEnabled($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
id
mergeRequest(iid: $iid) {
+ id
...autoMergeEnabled
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
index f713739f65a..556ecee254d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
@@ -2,6 +2,7 @@
query readyToMerge($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
...ReadyToMerge
}
}
diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js
index 9f1da9ae173..d0155c18b9c 100644
--- a/app/assets/javascripts/vue_shared/alert_details/index.js
+++ b/app/assets/javascripts/vue_shared/alert_details/index.js
@@ -1,4 +1,4 @@
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import { defaultDataIdFromObject } from '@apollo/client/core';
import produce from 'immer';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
@@ -70,6 +70,7 @@ export default (selector) => {
// eslint-disable-next-line no-new
new Vue({
el: selector,
+ name: 'AlertDetailsRoot',
components: {
AlertDetails,
},
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 82a28d4cb5f..b6010d4b70c 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -75,6 +75,9 @@ export default {
return this.noteAuthorId === this.currentUserId;
},
},
+ mounted() {
+ this.virtualScrollerItem = this.$el.closest('.vue-recycle-scroller__item-view');
+ },
methods: {
getAwardClassBindings(awardList) {
return {
@@ -162,6 +165,10 @@ export default {
},
setIsMenuOpen(menuOpen) {
this.isMenuOpen = menuOpen;
+
+ if (this.virtualScrollerItem) {
+ this.virtualScrollerItem.style.zIndex = this.isMenuOpen ? 1 : null;
+ }
},
},
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
index 2c74d56f617..3aaa7d915ea 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
@@ -1,6 +1,7 @@
<script>
import { GlIcon, GlSafeHtmlDirective } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import LineHighlighter from '~/blob/line_highlighter';
import { HIGHLIGHT_CLASS_NAME } from './constants';
import ViewerMixin from './mixins';
@@ -20,13 +21,22 @@ export default {
};
},
computed: {
+ refactorBlobViewerEnabled() {
+ return this.glFeatures.refactorBlobViewer;
+ },
+
lineNumbers() {
return this.content.split('\n').length;
},
},
mounted() {
- const { hash } = window.location;
- if (hash) this.scrollToLine(hash, true);
+ if (this.refactorBlobViewerEnabled) {
+ // This line will be removed once we start using highlight.js on the frontend (https://gitlab.com/groups/gitlab-org/-/epics/7146)
+ new LineHighlighter(); // eslint-disable-line no-new
+ } else {
+ const { hash } = window.location;
+ if (hash) this.scrollToLine(hash, true);
+ }
},
methods: {
scrollToLine(hash, scroll = false) {
@@ -51,7 +61,7 @@ export default {
<template>
<div>
<div class="file-content code js-syntax-highlight" :class="$options.userColorScheme">
- <div v-if="!hideLineNumbers" class="line-numbers">
+ <div v-if="!hideLineNumbers" class="line-numbers gl-pt-0!">
<a
v-for="line in lineNumbers"
:id="`L${line}`"
@@ -67,7 +77,7 @@ export default {
</div>
<div class="blob-content">
<pre
- class="code highlight"
+ class="code highlight gl-p-0! gl-display-flex"
><code v-safe-html="content" :data-blob-hash="blobHash"></code></pre>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
index 0575d7f6404..8b76af05ffe 100644
--- a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
@@ -45,7 +45,8 @@ export default {
:chart-data="chart.data"
:area-chart-options="chartOptions"
>
- {{ dateRange }}
+ <p>{{ dateRange }}</p>
+ <slot name="metrics" :selected-chart="selectedChart"></slot>
<template #tooltip-title>
<slot name="tooltip-title"></slot>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/confirm_fork_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_fork_modal.vue
new file mode 100644
index 00000000000..64e3b5d0bae
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_fork_modal.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export const i18n = {
+ btnText: __('Fork project'),
+ title: __('Fork project?'),
+ message: __(
+ 'You can’t edit files directly in this project. Fork this project and submit a merge request with your changes.',
+ ),
+};
+
+export default {
+ name: 'ConfirmForkModal',
+ components: {
+ GlModal,
+ },
+ model: {
+ prop: 'visible',
+ event: 'change',
+ },
+ props: {
+ visible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ modalId: {
+ type: String,
+ required: true,
+ },
+ forkPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ btnActions() {
+ return {
+ cancel: { text: __('Cancel') },
+ primary: {
+ text: this.$options.i18n.btnText,
+ attributes: {
+ href: this.forkPath,
+ variant: 'confirm',
+ 'data-qa-selector': 'fork_project_button',
+ 'data-method': 'post',
+ },
+ },
+ };
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <gl-modal
+ :visible="visible"
+ data-qa-selector="confirm_fork_modal"
+ :modal-id="modalId"
+ :title="$options.i18n.title"
+ :action-primary="btnActions.primary"
+ :action-cancel="btnActions.cancel"
+ @change="$emit('change', $event)"
+ >
+ <p>{{ $options.i18n.message }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue b/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue
index cb038a8c4e1..c411496fad1 100644
--- a/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue
+++ b/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue
@@ -28,12 +28,37 @@ export default {
required: false,
default: false,
},
+ isOnImage: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isDraft: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ size: {
+ type: String,
+ required: false,
+ default: 'md',
+ validator: (value) => ['sm', 'md'].includes(value),
+ },
+ ariaLabel: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
computed: {
isNewNote() {
return this.label === null;
},
pinLabel() {
+ if (this.ariaLabel) {
+ return this.ariaLabel;
+ }
+
return this.isNewNote
? __('Comment form position')
: sprintf(__("Comment '%{label}' position"), { label: this.label });
@@ -51,7 +76,10 @@ export default {
'js-image-badge design-note-pin': !isNewNote,
resolved: isResolved,
inactive: isInactive,
+ draft: isDraft,
+ 'on-image': isOnImage,
'gl-absolute': position,
+ small: size === 'sm',
}"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm"
type="button"
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 810d9f782b9..3d48c74b40b 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
@@ -23,9 +23,19 @@ export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __('None'), title:
export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __('Any'), title: __('Any') };
export const DEFAULT_NONE_ANY = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+export const DEFAULT_MILESTONE_UPCOMING = {
+ value: FILTER_UPCOMING,
+ text: __('Upcoming'),
+ title: __('Upcoming'),
+};
+export const DEFAULT_MILESTONE_STARTED = {
+ value: FILTER_STARTED,
+ text: __('Started'),
+ title: __('Started'),
+};
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
- { value: FILTER_UPCOMING, text: __('Upcoming'), title: __('Upcoming') },
- { value: FILTER_STARTED, text: __('Started'), title: __('Started') },
+ DEFAULT_MILESTONE_UPCOMING,
+ DEFAULT_MILESTONE_STARTED,
]);
export const SortDirection = {
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 bbc1888bc0b..157068b2c0f 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
@@ -163,19 +163,22 @@ export default {
},
},
methods: {
- handleInput: debounce(function debouncedSearch({ data }) {
- this.searchKey = data;
+ handleInput: debounce(function debouncedSearch({ data, operator }) {
+ // Prevent fetching suggestions when data or operator is not present
+ if (data || operator) {
+ this.searchKey = data;
- if (!this.suggestionsLoading && !this.activeTokenValue) {
- let search = this.searchTerm ? this.searchTerm : data;
+ if (!this.suggestionsLoading && !this.activeTokenValue) {
+ let search = this.searchTerm ? this.searchTerm : data;
- if (search.startsWith('"') && search.endsWith('"')) {
- search = stripQuotes(search);
- } else if (search.startsWith('"')) {
- search = search.slice(1, search.length);
- }
+ if (search.startsWith('"') && search.endsWith('"')) {
+ search = stripQuotes(search);
+ } else if (search.startsWith('"')) {
+ search = search.slice(1, search.length);
+ }
- this.$emit('fetch-suggestions', search);
+ this.$emit('fetch-suggestions', search);
+ }
}
}, DEBOUNCE_DELAY),
handleTokenValueSelected(selectedValue) {
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
index 0d3394788fa..11c081ab4f8 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
@@ -57,7 +57,12 @@ export default {
.fetchMilestones(searchTerm)
.then((response) => {
const data = Array.isArray(response) ? response : response.data;
- this.milestones = data.slice().sort(sortMilestonesByDueDate);
+
+ if (this.config.shouldSkipSort) {
+ this.milestones = data;
+ } else {
+ this.milestones = data.slice().sort(sortMilestonesByDueDate);
+ }
})
.catch(() => {
createFlash({ message: __('There was a problem fetching milestones.') });
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
deleted file mode 100644
index 9ab91e567e6..00000000000
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
+++ /dev/null
@@ -1,106 +0,0 @@
-<script>
-import Tribute from '@gitlab/tributejs';
-import {
- GfmAutocompleteType,
- tributeConfig,
-} from 'ee_else_ce/vue_shared/components/gfm_autocomplete/utils';
-import * as Emoji from '~/emoji';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
-
-export default {
- errorMessage: __(
- 'An error occurred while getting autocomplete data. Please refresh the page and try again.',
- ),
- props: {
- autocompleteTypes: {
- type: Array,
- required: false,
- default: () => Object.values(GfmAutocompleteType),
- },
- dataSources: {
- type: Object,
- required: false,
- default: () => gl.GfmAutoComplete?.dataSources || {},
- },
- },
- computed: {
- config() {
- return this.autocompleteTypes.map((type) => ({
- ...tributeConfig[type].config,
- loadingItemTemplate: `<span class="gl-spinner gl-vertical-align-text-bottom gl-ml-3 gl-mr-2"></span>${__(
- 'Loading',
- )}`,
- requireLeadingSpace: true,
- values: this.getValues(type),
- }));
- },
- },
- mounted() {
- this.cache = {};
- this.tribute = new Tribute({ collection: this.config });
-
- const input = this.$slots.default?.[0]?.elm;
- this.tribute.attach(input);
- },
- beforeDestroy() {
- const input = this.$slots.default?.[0]?.elm;
- this.tribute.detach(input);
- },
- methods: {
- cacheAssignees() {
- const isAssigneesLengthSame =
- this.assignees?.length === SidebarMediator.singleton?.store?.assignees?.length;
-
- if (!this.assignees || !isAssigneesLengthSame) {
- this.assignees =
- SidebarMediator.singleton?.store?.assignees?.map((assignee) => assignee.username) || [];
- }
- },
- filterValues(type) {
- // The assignees AJAX response can come after the user first invokes autocomplete
- // so we need to check more than once if we need to update the assignee cache
- this.cacheAssignees();
-
- return tributeConfig[type].filterValues
- ? tributeConfig[type].filterValues({
- assignees: this.assignees,
- collection: this.cache[type],
- fullText: this.$slots.default?.[0]?.elm?.value,
- selectionStart: this.$slots.default?.[0]?.elm?.selectionStart,
- })
- : this.cache[type];
- },
- getValues(type) {
- return (inputText, processValues) => {
- if (this.cache[type]) {
- processValues(this.filterValues(type));
- } else if (type === GfmAutocompleteType.Emojis) {
- Emoji.initEmojiMap()
- .then(() => {
- const emojis = Emoji.getValidEmojiNames();
- this.cache[type] = emojis;
- processValues(emojis);
- })
- .catch(() => createFlash({ message: this.$options.errorMessage }));
- } else if (this.dataSources[type]) {
- axios
- .get(this.dataSources[type])
- .then((response) => {
- this.cache[type] = response.data;
- processValues(this.filterValues(type));
- })
- .catch(() => createFlash({ message: this.$options.errorMessage }));
- } else {
- processValues([]);
- }
- };
- },
- },
- render(createElement) {
- return createElement('div', this.$slots.default);
- },
-};
-</script>
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
deleted file mode 100644
index 44c3fc34ba6..00000000000
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import { escape, last } from 'lodash';
-import * as Emoji from '~/emoji';
-import { spriteIcon } from '~/lib/utils/common_utils';
-
-const groupType = 'Group'; // eslint-disable-line @gitlab/require-i18n-strings
-
-// Number of users to show in the autocomplete menu to avoid doing a mass fetch of 100+ avatars
-const memberLimit = 10;
-
-const nonWordOrInteger = /\W|^\d+$/;
-
-export const menuItemLimit = 100;
-
-export const GfmAutocompleteType = {
- Emojis: 'emojis',
- Issues: 'issues',
- Labels: 'labels',
- Members: 'members',
- MergeRequests: 'mergeRequests',
- Milestones: 'milestones',
- QuickActions: 'commands',
- Snippets: 'snippets',
-};
-
-function doesCurrentLineStartWith(searchString, fullText, selectionStart) {
- const currentLineNumber = fullText.slice(0, selectionStart).split('\n').length;
- const currentLine = fullText.split('\n')[currentLineNumber - 1];
- return currentLine.startsWith(searchString);
-}
-
-export const tributeConfig = {
- [GfmAutocompleteType.Emojis]: {
- config: {
- trigger: ':',
- lookup: (value) => value,
- menuItemLimit,
- menuItemTemplate: ({ original }) => `${original} ${Emoji.glEmojiTag(original)}`,
- selectTemplate: ({ original }) => `:${original}:`,
- },
- },
-
- [GfmAutocompleteType.Issues]: {
- config: {
- trigger: '#',
- lookup: (value) => `${value.iid}${value.title}`,
- menuItemLimit,
- menuItemTemplate: ({ original }) =>
- `<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
- selectTemplate: ({ original }) => original.reference || `#${original.iid}`,
- },
- },
-
- [GfmAutocompleteType.Labels]: {
- config: {
- trigger: '~',
- lookup: 'title',
- menuItemLimit,
- menuItemTemplate: ({ original }) => `
- <span class="dropdown-label-box" style="background: ${escape(original.color)};"></span>
- ${escape(original.title)}`,
- selectTemplate: ({ original }) =>
- nonWordOrInteger.test(original.title)
- ? `~"${escape(original.title)}"`
- : `~${escape(original.title)}`,
- },
- filterValues({ collection, fullText, selectionStart }) {
- if (doesCurrentLineStartWith('/label', fullText, selectionStart)) {
- return collection.filter((label) => !label.set);
- }
-
- if (doesCurrentLineStartWith('/unlabel', fullText, selectionStart)) {
- return collection.filter((label) => label.set);
- }
-
- return collection;
- },
- },
-
- [GfmAutocompleteType.Members]: {
- config: {
- trigger: '@',
- fillAttr: 'username',
- lookup: (value) =>
- value.type === groupType ? last(value.name.split(' / ')) : `${value.name}${value.username}`,
- menuItemLimit: memberLimit,
- menuItemTemplate: ({ original }) => {
- const commonClasses = 'gl-avatar gl-avatar-s32 gl-flex-shrink-0';
- const noAvatarClasses = `${commonClasses} gl-rounded-small
- gl-display-flex gl-align-items-center gl-justify-content-center`;
-
- const avatar = original.avatar_url
- ? `<img class="${commonClasses} gl-avatar-circle" src="${original.avatar_url}" alt="" />`
- : `<div class="${noAvatarClasses}" aria-hidden="true">
- ${original.username.charAt(0).toUpperCase()}</div>`;
-
- let displayName = original.name;
- let parentGroupOrUsername = `@${original.username}`;
-
- if (original.type === groupType) {
- const splitName = original.name.split(' / ');
- displayName = splitName.pop();
- parentGroupOrUsername = splitName.pop();
- }
-
- const count = original.count && !original.mentionsDisabled ? ` (${original.count})` : '';
-
- const disabledMentionsIcon = original.mentionsDisabled
- ? spriteIcon('notifications-off', 's16 gl-ml-3')
- : '';
-
- return `
- <div class="gl-display-flex gl-align-items-center">
- ${avatar}
- <div class="gl-line-height-normal gl-ml-4">
- <div>${escape(displayName)}${count}</div>
- <div class="gl-text-gray-700">${escape(parentGroupOrUsername)}</div>
- </div>
- ${disabledMentionsIcon}
- </div>
- `;
- },
- },
- filterValues({ assignees, collection, fullText, selectionStart }) {
- if (doesCurrentLineStartWith('/assign', fullText, selectionStart)) {
- return collection.filter((member) => !assignees.includes(member.username));
- }
-
- if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
- return collection.filter((member) => assignees.includes(member.username));
- }
-
- return collection;
- },
- },
-
- [GfmAutocompleteType.MergeRequests]: {
- config: {
- trigger: '!',
- lookup: (value) => `${value.iid}${value.title}`,
- menuItemLimit,
- menuItemTemplate: ({ original }) =>
- `<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
- selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
- },
- },
-
- [GfmAutocompleteType.Milestones]: {
- config: {
- trigger: '%',
- lookup: 'title',
- menuItemLimit,
- menuItemTemplate: ({ original }) => escape(original.title),
- selectTemplate: ({ original }) => `%"${escape(original.title)}"`,
- },
- },
-
- [GfmAutocompleteType.QuickActions]: {
- config: {
- trigger: '/',
- fillAttr: 'name',
- lookup: (value) => `${value.name}${value.aliases.join()}`,
- menuItemLimit,
- menuItemTemplate: ({ original }) => {
- const aliases = original.aliases.length
- ? `<small>(or /${original.aliases.join(', /')})</small>`
- : '';
-
- const params = original.params.length ? `<small>${original.params.join(' ')}</small>` : '';
-
- let description = '';
-
- if (original.warning) {
- const confidentialIcon =
- original.icon === 'confidential' ? spriteIcon('eye-slash', 's16 gl-mr-2') : '';
- description = `<small>${confidentialIcon}<em>${original.warning}</em></small>`;
- } else if (original.description) {
- description = `<small><em>${original.description}</em></small>`;
- }
-
- return `<div>/${original.name} ${aliases} ${params}</div>
- <div>${description}</div>`;
- },
- },
- },
-
- [GfmAutocompleteType.Snippets]: {
- config: {
- trigger: '$',
- fillAttr: 'id',
- lookup: (value) => `${value.id}${value.title}`,
- menuItemLimit,
- menuItemTemplate: ({ original }) => `<small>${original.id}</small> ${escape(original.title)}`,
- },
- },
-};
diff --git a/app/assets/javascripts/vue_shared/components/help_popover.vue b/app/assets/javascripts/vue_shared/components/help_popover.vue
index f36b9107a6e..f3b871c91b6 100644
--- a/app/assets/javascripts/vue_shared/components/help_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/help_popover.vue
@@ -33,6 +33,9 @@ export default {
<template #default>
<div v-safe-html="options.content"></div>
</template>
+ <template v-for="slot in Object.keys($slots)" #[slot]>
+ <slot :name="slot"></slot>
+ </template>
</gl-popover>
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 5c86c928ce3..cbf38984e23 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -8,7 +8,6 @@ import GLForm from '~/gl_form';
import axios from '~/lib/utils/axios_utils';
import { stripHtml } from '~/lib/utils/text_utility';
import { __, sprintf } from '~/locale';
-import GfmAutocomplete from '~/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MarkdownHeader from './header.vue';
@@ -20,7 +19,6 @@ function cleanUpLine(content) {
export default {
components: {
- GfmAutocomplete,
MarkdownHeader,
MarkdownToolbar,
GlIcon,
@@ -212,15 +210,16 @@ export default {
return new GLForm(
$(this.$refs['gl-form']),
{
- emojis: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- members: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- epics: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- milestones: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- labels: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- snippets: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
+ emojis: this.enableAutocomplete,
+ members: this.enableAutocomplete,
+ issues: this.enableAutocomplete,
+ mergeRequests: this.enableAutocomplete,
+ epics: this.enableAutocomplete,
+ milestones: this.enableAutocomplete,
+ labels: this.enableAutocomplete,
+ snippets: this.enableAutocomplete,
vulnerabilities: this.enableAutocomplete,
+ contacts: this.enableAutocomplete && this.glFeatures.contactsAutocomplete,
},
true,
);
@@ -311,10 +310,7 @@ export default {
/>
<div v-show="!previewMarkdown" class="md-write-holder">
<div class="zen-backdrop">
- <gfm-autocomplete v-if="glFeatures.tributeAutocomplete">
- <slot name="textarea"></slot>
- </gfm-autocomplete>
- <slot v-else name="textarea"></slot>
+ <slot name="textarea"></slot>
<a
class="zen-control zen-control-leave js-zen-leave gl-text-gray-500"
href="#"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 3ed9de6c133..e2b6579a841 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,9 +1,9 @@
<script>
-import { GlPopover, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlPopover, GlButton, GlTooltipDirective, GlTabs, GlTab } from '@gitlab/ui';
import $ from 'jquery';
import { keysFor, BOLD_TEXT, ITALIC_TEXT, LINK_TEXT } from '~/behaviors/shortcuts/keybindings';
import { getSelectedFragment } from '~/lib/utils/common_utils';
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm';
import ToolbarButton from './toolbar_button.vue';
@@ -12,6 +12,8 @@ export default {
ToolbarButton,
GlPopover,
GlButton,
+ GlTabs,
+ GlTab,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -144,136 +146,143 @@ export default {
italic: keysFor(ITALIC_TEXT),
link: keysFor(LINK_TEXT),
},
+ i18n: {
+ writeTabTitle: __('Write'),
+ previewTabTitle: __('Preview'),
+ },
};
</script>
<template>
<div class="md-header">
- <ul class="nav-links clearfix">
- <li :class="{ active: !previewMarkdown }" class="md-header-tab">
- <button class="js-write-link" type="button" @click="writeMarkdownTab($event)">
- {{ __('Write') }}
- </button>
- </li>
- <li :class="{ active: previewMarkdown }" class="md-header-tab">
- <button
- class="js-preview-link js-md-preview-button"
- type="button"
- @click="previewMarkdownTab($event)"
- >
- {{ __('Preview') }}
- </button>
- </li>
- <li :class="{ active: !previewMarkdown }" class="md-header-toolbar">
- <toolbar-button
- tag="**"
- :button-title="
- sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey })
- "
- :shortcuts="$options.shortcuts.bold"
- icon="bold"
- />
- <toolbar-button
- tag="_"
- :button-title="
- sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey })
- "
- :shortcuts="$options.shortcuts.italic"
- icon="italic"
- />
- <toolbar-button
- :prepend="true"
- :tag="tag"
- :button-title="__('Insert a quote')"
- icon="quote"
- @click="handleQuote"
- />
- <template v-if="canSuggest">
+ <gl-tabs content-class="gl-display-none">
+ <gl-tab
+ title-link-class="gl-pt-3 gl-px-3 js-md-write-button"
+ :title="$options.i18n.writeTabTitle"
+ :active="!previewMarkdown"
+ data-testid="write-tab"
+ @click="writeMarkdownTab($event)"
+ />
+ <gl-tab
+ title-link-class="gl-pt-3 gl-px-3 js-md-preview-button"
+ :title="$options.i18n.previewTabTitle"
+ :active="previewMarkdown"
+ data-testid="preview-tab"
+ @click="previewMarkdownTab($event)"
+ />
+
+ <template v-if="!previewMarkdown" #tabs-end>
+ <div class="md-header-toolbar gl-ml-auto gl-pb-3 gl-justify-content-center">
+ <toolbar-button
+ tag="**"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey })
+ "
+ :shortcuts="$options.shortcuts.bold"
+ icon="bold"
+ />
+ <toolbar-button
+ tag="_"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey })
+ "
+ :shortcuts="$options.shortcuts.italic"
+ icon="italic"
+ />
<toolbar-button
- ref="suggestButton"
- :tag="mdSuggestion"
:prepend="true"
- :button-title="__('Insert suggestion')"
- :cursor-offset="4"
- :tag-content="lineContent"
- icon="doc-code"
- data-qa-selector="suggestion_button"
- class="js-suggestion-btn"
- @click="handleSuggestDismissed"
+ :tag="tag"
+ :button-title="__('Insert a quote')"
+ icon="quote"
+ @click="handleQuote"
/>
- <gl-popover
- v-if="suggestPopoverVisible"
- :target="$refs.suggestButton.$el"
- :css-classes="['diff-suggest-popover']"
- placement="bottom"
- :show="suggestPopoverVisible"
- >
- <strong>{{ __('New! Suggest changes directly') }}</strong>
- <p class="mb-2">
- {{
- __(
- 'Suggest code changes which can be immediately applied in one click. Try it out!',
- )
- }}
- </p>
- <gl-button
- variant="info"
- category="primary"
- size="small"
+ <template v-if="canSuggest">
+ <toolbar-button
+ ref="suggestButton"
+ :tag="mdSuggestion"
+ :prepend="true"
+ :button-title="__('Insert suggestion')"
+ :cursor-offset="4"
+ :tag-content="lineContent"
+ icon="doc-code"
+ data-qa-selector="suggestion_button"
+ class="js-suggestion-btn"
@click="handleSuggestDismissed"
+ />
+ <gl-popover
+ v-if="suggestPopoverVisible"
+ :target="$refs.suggestButton.$el"
+ :css-classes="['diff-suggest-popover']"
+ placement="bottom"
+ :show="suggestPopoverVisible"
>
- {{ __('Got it') }}
- </gl-button>
- </gl-popover>
- </template>
- <toolbar-button tag="`" tag-block="```" :button-title="__('Insert code')" icon="code" />
- <toolbar-button
- tag="[{text}](url)"
- tag-select="url"
- :button-title="
- sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey })
- "
- :shortcuts="$options.shortcuts.link"
- icon="link"
- />
- <toolbar-button
- :prepend="true"
- tag="- "
- :button-title="__('Add a bullet list')"
- icon="list-bulleted"
- />
- <toolbar-button
- :prepend="true"
- tag="1. "
- :button-title="__('Add a numbered list')"
- icon="list-numbered"
- />
- <toolbar-button
- :prepend="true"
- tag="- [ ] "
- :button-title="__('Add a task list')"
- icon="list-task"
- />
- <toolbar-button
- :tag="mdCollapsibleSection"
- :prepend="true"
- tag-select="Click to expand"
- :button-title="__('Add a collapsible section')"
- icon="details-block"
- />
- <toolbar-button
- :tag="mdTable"
- :prepend="true"
- :button-title="__('Add a table')"
- icon="table"
- />
- <toolbar-button
- class="js-zen-enter"
- :prepend="true"
- :button-title="__('Go full screen')"
- icon="maximize"
- />
- </li>
- </ul>
+ <strong>{{ __('New! Suggest changes directly') }}</strong>
+ <p class="mb-2">
+ {{
+ __(
+ 'Suggest code changes which can be immediately applied in one click. Try it out!',
+ )
+ }}
+ </p>
+ <gl-button
+ variant="info"
+ category="primary"
+ size="small"
+ @click="handleSuggestDismissed"
+ >
+ {{ __('Got it') }}
+ </gl-button>
+ </gl-popover>
+ </template>
+ <toolbar-button tag="`" tag-block="```" :button-title="__('Insert code')" icon="code" />
+ <toolbar-button
+ tag="[{text}](url)"
+ tag-select="url"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey })
+ "
+ :shortcuts="$options.shortcuts.link"
+ icon="link"
+ />
+ <toolbar-button
+ :prepend="true"
+ tag="- "
+ :button-title="__('Add a bullet list')"
+ icon="list-bulleted"
+ />
+ <toolbar-button
+ :prepend="true"
+ tag="1. "
+ :button-title="__('Add a numbered list')"
+ icon="list-numbered"
+ />
+ <toolbar-button
+ :prepend="true"
+ tag="- [ ] "
+ :button-title="__('Add a task list')"
+ icon="list-task"
+ />
+ <toolbar-button
+ :tag="mdCollapsibleSection"
+ :prepend="true"
+ tag-select="Click to expand"
+ :button-title="__('Add a collapsible section')"
+ icon="details-block"
+ />
+ <toolbar-button
+ :tag="mdTable"
+ :prepend="true"
+ :button-title="__('Add a table')"
+ icon="table"
+ />
+ <toolbar-button
+ class="js-zen-enter"
+ :prepend="true"
+ :button-title="__('Go full screen')"
+ icon="maximize"
+ />
+ </div>
+ </template>
+ </gl-tabs>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
index 7d2af7983d1..521b1a1075a 100644
--- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
@@ -1,34 +1,74 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { __ } from '~/locale';
+export const EMPTY_NAMESPACE_ID = -1;
export const i18n = {
DEFAULT_TEXT: __('Select a new namespace'),
+ DEFAULT_EMPTY_NAMESPACE_TEXT: __('No namespace'),
GROUPS: __('Groups'),
USERS: __('Users'),
};
-const filterByName = (data, searchTerm = '') =>
- data.filter((d) => d.humanName.toLowerCase().includes(searchTerm));
+const filterByName = (data, searchTerm = '') => {
+ if (!searchTerm) {
+ return data;
+ }
+
+ return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase()));
+};
export default {
name: 'NamespaceSelect',
components: {
GlDropdown,
+ GlDropdownDivider,
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
},
props: {
- data: {
- type: Object,
- required: true,
+ groupNamespaces: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ userNamespaces: {
+ type: Array,
+ required: false,
+ default: () => [],
},
fullWidth: {
type: Boolean,
required: false,
default: false,
},
+ defaultText: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_TEXT,
+ },
+ includeHeaders: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ emptyNamespaceTitle: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_EMPTY_NAMESPACE_TEXT,
+ },
+ includeEmptyNamespace: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -38,21 +78,33 @@ export default {
},
computed: {
hasUserNamespaces() {
- return this.data.user?.length;
+ return this.userNamespaces.length;
},
hasGroupNamespaces() {
- return this.data.group?.length;
+ return this.groupNamespaces.length;
},
filteredGroupNamespaces() {
if (!this.hasGroupNamespaces) return [];
- return filterByName(this.data.group, this.searchTerm);
+ return filterByName(this.groupNamespaces, this.searchTerm);
},
filteredUserNamespaces() {
if (!this.hasUserNamespaces) return [];
- return filterByName(this.data.user, this.searchTerm);
+ return filterByName(this.userNamespaces, this.searchTerm);
},
selectedNamespaceText() {
- return this.selectedNamespace?.humanName || this.$options.i18n.DEFAULT_TEXT;
+ return this.selectedNamespace?.humanName || this.defaultText;
+ },
+ filteredEmptyNamespaceTitle() {
+ const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
+
+ if (!includeEmptyNamespace) {
+ return '';
+ }
+ if (!searchTerm) {
+ return emptyNamespaceTitle;
+ }
+
+ return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase());
},
},
methods: {
@@ -60,31 +112,47 @@ export default {
this.selectedNamespace = item;
this.$emit('select', item);
},
+ handleSelectEmptyNamespace() {
+ this.handleSelect({ id: EMPTY_NAMESPACE_ID, humanName: this.emptyNamespaceTitle });
+ },
},
i18n,
};
</script>
<template>
- <gl-dropdown :text="selectedNamespaceText" :block="fullWidth">
+ <gl-dropdown :text="selectedNamespaceText" :block="fullWidth" data-qa-selector="namespaces_list">
<template #header>
<gl-search-box-by-type v-model.trim="searchTerm" />
</template>
- <div v-if="hasGroupNamespaces" class="qa-namespaces-list-groups">
- <gl-dropdown-section-header>{{ $options.i18n.GROUPS }}</gl-dropdown-section-header>
+ <div v-if="filteredEmptyNamespaceTitle">
+ <gl-dropdown-item
+ data-qa-selector="namespaces_list_item"
+ @click="handleSelectEmptyNamespace()"
+ >
+ {{ emptyNamespaceTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </div>
+ <div v-if="hasGroupNamespaces" data-qa-selector="namespaces_list_groups">
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.GROUPS
+ }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="item in filteredGroupNamespaces"
:key="item.id"
- class="qa-namespaces-list-item"
+ data-qa-selector="namespaces_list_item"
@click="handleSelect(item)"
>{{ item.humanName }}</gl-dropdown-item
>
</div>
- <div v-if="hasUserNamespaces" class="qa-namespaces-list-users">
- <gl-dropdown-section-header>{{ $options.i18n.USERS }}</gl-dropdown-section-header>
+ <div v-if="hasUserNamespaces" data-qa-selector="namespaces_list_users">
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.USERS
+ }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="item in filteredUserNamespaces"
:key="item.id"
- class="qa-namespaces-list-item"
+ data-qa-selector="namespaces_list_item"
@click="handleSelect(item)"
>{{ item.humanName }}</gl-dropdown-item
>
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
deleted file mode 100644
index 3c0ac32e512..00000000000
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-<script>
-import { GlDatepicker } from '@gitlab/ui';
-import { pikadayToString } from '~/lib/utils/datetime_utility';
-
-export default {
- name: 'DatePicker',
- components: {
- GlDatepicker,
- },
- props: {
- selectedDate: {
- type: Date,
- required: false,
- default: null,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
- },
- methods: {
- selected(date) {
- this.$emit('newDateSelected', pikadayToString(date));
- },
- toggled() {
- this.$emit('hidePicker');
- },
- },
-};
-</script>
-
-<template>
- <gl-datepicker
- :value="selectedDate"
- :min-date="minDate"
- :max-date="maxDate"
- start-opened
- @close="toggled"
- @click="toggled"
- @input="selected"
- />
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
index d886a67fff7..5d144c0d699 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -13,7 +13,7 @@ export default {
},
modalId: 'runner-instructions-modal',
i18n: {
- buttonText: s__('Runners|Show Runner installation instructions'),
+ buttonText: s__('Runners|Show runner installation instructions'),
},
data() {
return {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
deleted file mode 100644
index 460a10e08ed..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-
-export default {
- name: 'CollapsedCalendarIcon',
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlIcon,
- },
- props: {
- containerClass: {
- type: String,
- required: false,
- default: '',
- },
- text: {
- type: String,
- required: false,
- default: '',
- },
- showIcon: {
- type: Boolean,
- required: false,
- default: true,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- },
- methods: {
- click() {
- this.$emit('click');
- },
- },
-};
-</script>
-
-<template>
- <div v-gl-tooltip.left.viewport="tooltipText" :class="containerClass" @click="click">
- <gl-icon v-if="showIcon" name="calendar" />
- <slot>
- <span> {{ text }} </span>
- </slot>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
deleted file mode 100644
index 4531fafbf72..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
+++ /dev/null
@@ -1,148 +0,0 @@
-<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import { dateInWords } from '../../../lib/utils/datetime_utility';
-import datePicker from '../pikaday.vue';
-import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
-import toggleSidebar from './toggle_sidebar.vue';
-
-export default {
- name: 'SidebarDatePicker',
- components: {
- datePicker,
- toggleSidebar,
- collapsedCalendarIcon,
- GlLoadingIcon,
- },
- props: {
- blockClass: {
- type: String,
- required: false,
- default: '',
- },
- collapsed: {
- type: Boolean,
- required: false,
- default: true,
- },
- showToggleSidebar: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- editable: {
- type: Boolean,
- required: false,
- default: false,
- },
- label: {
- type: String,
- required: false,
- default: __('Date picker'),
- },
- selectedDate: {
- type: Date,
- required: false,
- default: null,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- editing: false,
- };
- },
- computed: {
- selectedAndEditable() {
- return this.selectedDate && this.editable;
- },
- selectedDateWords() {
- return dateInWords(this.selectedDate, true);
- },
- collapsedText() {
- return this.selectedDateWords ? this.selectedDateWords : __('None');
- },
- },
- methods: {
- stopEditing() {
- this.editing = false;
- },
- toggleDatePicker() {
- this.editing = !this.editing;
- },
- newDateSelected(date = null) {
- this.date = date;
- this.editing = false;
- this.$emit('saveDate', date);
- },
- toggleSidebar() {
- this.$emit('toggleCollapse');
- },
- },
-};
-</script>
-
-<template>
- <div :class="blockClass" class="block">
- <div class="issuable-sidebar-header">
- <toggle-sidebar :collapsed="collapsed" @toggle="toggleSidebar" />
- </div>
- <collapsed-calendar-icon :text="collapsedText" class="sidebar-collapsed-icon" />
- <div class="title">
- {{ label }}
- <gl-loading-icon v-if="isLoading" size="sm" :inline="true" />
- <div class="float-right">
- <button
- v-if="editable && !editing"
- type="button"
- class="btn-blank btn-link btn-primary-hover-link btn-sidebar-action"
- @click="toggleDatePicker"
- >
- {{ __('Edit') }}
- </button>
- <toggle-sidebar v-if="showToggleSidebar" :collapsed="collapsed" @toggle="toggleSidebar" />
- </div>
- </div>
- <div class="value">
- <date-picker
- v-if="editing"
- :selected-date="selectedDate"
- :min-date="minDate"
- :max-date="maxDate"
- :label="label"
- @newDateSelected="newDateSelected"
- @hidePicker="stopEditing"
- />
- <span v-else class="value-content">
- <template v-if="selectedDate">
- <strong>{{ selectedDateWords }}</strong>
- <span v-if="selectedAndEditable" class="no-value">
- -
- <button
- type="button"
- class="btn-blank btn-link btn-secondary-hover-link"
- @click="newDateSelected(null)"
- >
- {{ __('remove') }}
- </button>
- </span>
- </template>
- <span v-else class="no-value">{{ __('None') }}</span>
- </span>
- </div>
- </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
index b99083713a8..88977652556 100644
--- 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
@@ -117,7 +117,11 @@ export default {
labelCreate: { label },
},
},
- ) => this.updateLabelsInCache(store, label),
+ ) => {
+ if (label) {
+ this.updateLabelsInCache(store, label);
+ }
+ },
});
if (labelCreate.errors.length) {
[this.error] = labelCreate.errors;
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
deleted file mode 100644
index 17904f20341..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownForm, GlDropdownDivider } from '@gitlab/ui';
-
-export default {
- components: {
- GlDropdownForm,
- GlDropdown,
- GlDropdownDivider,
- },
- props: {
- headerText: {
- type: String,
- required: true,
- },
- text: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <gl-dropdown class="show" :text="text" @toggle="$emit('toggle')">
- <template #header>
- <p class="gl-font-weight-bold gl-text-center gl-mt-2 gl-mb-4">{{ headerText }}</p>
- <gl-dropdown-divider />
- <slot name="search"></slot>
- </template>
- <gl-dropdown-form>
- <slot name="items"></slot>
- </gl-dropdown-form>
- <template #footer>
- <slot name="footer"></slot>
- </template>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
new file mode 100644
index 00000000000..9efe0147c37
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
@@ -0,0 +1,111 @@
+// Language map from Rouge::Lexer to highlight.js
+// Rouge::Lexer - We use it on the BE to determine the language of a source file (https://github.com/rouge-ruby/rouge/blob/master/docs/Languages.md).
+// Highlight.js - We use it on the FE to highlight the syntax of a source file (https://github.com/highlightjs/highlight.js/tree/main/src/languages).
+export const ROUGE_TO_HLJS_LANGUAGE_MAP = {
+ bsl: '1c',
+ actionscript: 'actionscript',
+ ada: 'ada',
+ apache: 'apache',
+ applescript: 'applescript',
+ armasm: 'armasm',
+ awk: 'awk',
+ c: 'c',
+ ceylon: 'ceylon',
+ clean: 'clean',
+ clojure: 'clojure',
+ cmake: 'cmake',
+ coffeescript: 'coffeescript',
+ coq: 'coq',
+ cpp: 'cpp',
+ crystal: 'crystal',
+ csharp: 'csharp',
+ css: 'css',
+ d: 'd',
+ dart: 'dart',
+ pascal: 'delphi',
+ diff: 'diff',
+ jinja: 'django',
+ docker: 'dockerfile',
+ batchfile: 'dos',
+ elixir: 'elixir',
+ elm: 'elm',
+ erb: 'erb',
+ erlang: 'erlang',
+ fortran: 'fortran',
+ fsharp: 'fsharp',
+ gherkin: 'gherkin',
+ glsl: 'glsl',
+ go: 'go',
+ gradle: 'gradle',
+ groovy: 'groovy',
+ haml: 'haml',
+ handlebars: 'handlebars',
+ haskell: 'haskell',
+ haxe: 'haxe',
+ http: 'http',
+ hylang: 'hy',
+ ini: 'ini',
+ isbl: 'isbl',
+ java: 'java',
+ javascript: 'javascript',
+ json: 'json',
+ julia: 'julia',
+ kotlin: 'kotlin',
+ lasso: 'lasso',
+ tex: 'latex',
+ common_lisp: 'lisp',
+ livescript: 'livescript',
+ llvm: 'llvm',
+ hlsl: 'lsl',
+ lua: 'lua',
+ make: 'makefile',
+ markdown: 'markdown',
+ mathematica: 'mathematica',
+ matlab: 'matlab',
+ moonscript: 'moonscript',
+ nginx: 'nginx',
+ nim: 'nim',
+ nix: 'nix',
+ objective_c: 'objectivec',
+ ocaml: 'ocaml',
+ perl: 'perl',
+ php: 'php',
+ plaintext: 'plaintext',
+ pony: 'pony',
+ powershell: 'powershell',
+ prolog: 'prolog',
+ properties: 'properties',
+ protobuf: 'protobuf',
+ puppet: 'puppet',
+ python: 'python',
+ q: 'q',
+ qml: 'qml',
+ r: 'r',
+ reasonml: 'reasonml',
+ ruby: 'ruby',
+ rust: 'rust',
+ sas: 'sas',
+ scala: 'scala',
+ scheme: 'scheme',
+ scss: 'scss',
+ shell: 'shell',
+ smalltalk: 'smalltalk',
+ sml: 'sml',
+ sqf: 'sqf',
+ sql: 'sql',
+ stan: 'stan',
+ stata: 'stata',
+ swift: 'swift',
+ tap: 'tap',
+ tcl: 'tcl',
+ twig: 'twig',
+ typescript: 'typescript',
+ vala: 'vala',
+ vb: 'vbnet',
+ verilog: 'verilog',
+ vhdl: 'vhdl',
+ viml: 'vim',
+ xml: 'xml',
+ xquery: 'xquery',
+ yaml: 'yaml',
+};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
index 99895926653..5aae1812de3 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
@@ -1,36 +1,31 @@
<script>
-import { GlSafeHtmlDirective } from '@gitlab/ui';
+import { GlSafeHtmlDirective, GlLoadingIcon } from '@gitlab/ui';
import LineNumbers from '~/vue_shared/components/line_numbers.vue';
import { sanitize } from '~/lib/dompurify';
+import { ROUGE_TO_HLJS_LANGUAGE_MAP } from './constants';
+import { wrapLines } from './utils';
const LINE_SELECT_CLASS_NAME = 'hll';
export default {
components: {
LineNumbers,
+ GlLoadingIcon,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
},
props: {
- content: {
- type: String,
+ blob: {
+ type: Object,
required: true,
},
- language: {
- type: String,
- required: false,
- default: 'plaintext',
- },
- autoDetect: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
languageDefinition: null,
+ content: this.blob.rawTextBlob,
+ language: ROUGE_TO_HLJS_LANGUAGE_MAP[this.blob.language],
hljs: null,
};
},
@@ -42,14 +37,14 @@ export default {
let highlightedContent;
if (this.hljs) {
- if (this.autoDetect) {
+ if (!this.language) {
highlightedContent = this.hljs.highlightAuto(this.content).value;
} else if (this.languageDefinition) {
highlightedContent = this.hljs.highlight(this.content, { language: this.language }).value;
}
}
- return this.wrapLines(highlightedContent);
+ return wrapLines(highlightedContent);
},
},
watch: {
@@ -63,14 +58,14 @@ export default {
async mounted() {
this.hljs = await this.loadHighlightJS();
- if (!this.autoDetect) {
+ if (this.language) {
this.languageDefinition = await this.loadLanguage();
}
},
methods: {
loadHighlightJS() {
- // With auto-detect enabled we load all common languages else we load only the core (smallest footprint)
- return this.autoDetect ? import('highlight.js/lib/common') : import('highlight.js/lib/core');
+ // If no language can be mapped to highlight.js we load all common languages else we load only the core (smallest footprint)
+ return !this.language ? import('highlight.js/lib/common') : import('highlight.js/lib/core');
},
async loadLanguage() {
let languageDefinition;
@@ -84,15 +79,6 @@ export default {
return languageDefinition;
},
- wrapLines(content) {
- return (
- content &&
- content
- .split('\n')
- .map((line, i) => `<span id="LC${i + 1}" class="line">${line}</span>`)
- .join('\r\n')
- );
- },
selectLine() {
const hash = sanitize(this.$route.hash);
const lineToSelect = hash && this.$el.querySelector(hash);
@@ -115,9 +101,16 @@ export default {
};
</script>
<template>
- <div class="file-content code js-syntax-highlight" :class="$options.userColorScheme">
+ <gl-loading-icon v-if="!highlightedContent" size="sm" class="gl-my-5" />
+ <div
+ v-else
+ class="file-content code js-syntax-highlight blob-content gl-display-flex"
+ :class="$options.userColorScheme"
+ data-type="simple"
+ data-qa-selector="blob_viewer_file_content"
+ >
<line-numbers :lines="lineNumbers" />
- <pre class="code"><code v-safe-html="highlightedContent"></code>
+ <pre class="code gl-pb-0!"><code v-safe-html="highlightedContent"></code>
</pre>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/utils.js b/app/assets/javascripts/vue_shared/components/source_viewer/utils.js
new file mode 100644
index 00000000000..e64e564bf61
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/utils.js
@@ -0,0 +1,26 @@
+export const wrapLines = (content) => {
+ return (
+ content &&
+ content
+ .split('\n')
+ .map((line, i) => {
+ let formattedLine;
+ const idAttribute = `id="LC${i + 1}"`;
+
+ if (line.includes('<span class="hljs') && !line.includes('</span>')) {
+ /**
+ * In some cases highlight.js will wrap multiple lines in a span, in these cases we want to append the line number to the existing span
+ *
+ * example (before): <span class="hljs-code">```bash
+ * example (after): <span id="LC67" class="hljs-code">```bash
+ */
+ formattedLine = line.replace(/(?=class="hljs)/, `${idAttribute} `);
+ } else {
+ formattedLine = `<span ${idAttribute} class="line">${line}</span>`;
+ }
+
+ return formattedLine;
+ })
+ .join('\n')
+ );
+};
diff --git a/app/assets/javascripts/vue_shared/components/svg_gradient.vue b/app/assets/javascripts/vue_shared/components/svg_gradient.vue
deleted file mode 100644
index 5ce45d492f9..00000000000
--- a/app/assets/javascripts/vue_shared/components/svg_gradient.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-<script>
-export default {
- props: {
- colors: {
- type: Array,
- required: true,
- validator(value) {
- return value.length === 2;
- },
- },
- opacity: {
- type: Array,
- required: true,
- validator(value) {
- return value.length === 2;
- },
- },
- identifierName: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-<template>
- <svg height="0" width="0">
- <defs>
- <linearGradient :id="identifierName">
- <stop :stop-color="colors[0]" :stop-opacity="opacity[0]" offset="0%" />
- <stop :stop-color="colors[1]" :stop-opacity="opacity[1]" offset="100%" />
- </linearGradient>
- </defs>
- </svg>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue
index 0a7a22ed3a8..62de76e46b5 100644
--- a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue
+++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue
@@ -41,6 +41,16 @@ export default {
required: false,
default: false,
},
+ inputFieldName: {
+ type: String,
+ required: false,
+ default: 'upload_file',
+ },
+ shouldUpdateInputOnFileDrop: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -84,6 +94,30 @@ export default {
return;
}
+ // NOTE: This is a temporary solution to integrate dropzone into a Rails
+ // form. On file drop if `shouldUpdateInputOnFileDrop` is true, the file
+ // input value is updated. So that when the form is submitted — the file
+ // value would be send together with the form data. This solution should
+ // be removed when License file upload page is fully migrated:
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/352501
+ // NOTE: as per https://caniuse.com/mdn-api_htmlinputelement_files, IE11
+ // is not able to set input.files property, thought the user would still
+ // be able to use the file picker dialogue option, by clicking the
+ // "openFileUpload" button
+ if (this.shouldUpdateInputOnFileDrop) {
+ // Since FileList cannot be easily manipulated, to match requirement of
+ // singleFileSelection, we're throwing an error if multiple files were
+ // dropped on the dropzone
+ // NOTE: we can drop this logic together with
+ // `shouldUpdateInputOnFileDrop` flag
+ if (this.singleFileSelection && files.length > 1) {
+ this.$emit('error');
+ return;
+ }
+
+ this.$refs.fileUpload.files = files;
+ }
+
this.$emit('change', this.singleFileSelection ? files[0] : files);
},
ondragenter(e) {
@@ -116,6 +150,7 @@ export default {
<slot>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
@click="openFileUpload"
>
<div
@@ -147,7 +182,7 @@ export default {
<input
ref="fileUpload"
type="file"
- name="upload_file"
+ :name="inputFieldName"
:accept="validFileMimetypes"
class="hide"
:multiple="!singleFileSelection"
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index f02cd5c4e2e..82022d1f4d6 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -1,9 +1,9 @@
<script>
-import $ from 'jquery';
import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import ActionsButton from '~/vue_shared/components/actions_button.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import ConfirmForkModal from '~/vue_shared/components/confirm_fork_modal.vue';
const KEY_EDIT = 'edit';
const KEY_WEB_IDE = 'webide';
@@ -16,6 +16,7 @@ export default {
GlModal,
GlSprintf,
GlLink,
+ ConfirmForkModal,
},
i18n: {
modal: {
@@ -103,11 +104,22 @@ export default {
required: false,
default: false,
},
+ forkPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ forkModalId: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
selection: KEY_WEB_IDE,
showEnableGitpodModal: false,
+ showForkModal: false,
};
},
computed: {
@@ -128,7 +140,7 @@ export default {
return;
}
- this.showJQueryModal('#modal-confirm-fork-edit');
+ this.showModal('showForkModal');
},
}
: { href: this.editUrl };
@@ -171,7 +183,7 @@ export default {
return;
}
- this.showJQueryModal('#modal-confirm-fork-webide');
+ this.showModal('showForkModal');
},
}
: { href: this.webIdeUrl };
@@ -247,9 +259,6 @@ export default {
select(key) {
this.selection = key;
},
- showJQueryModal(id) {
- $(id).modal('show');
- },
showModal(dataKey) {
this[dataKey] = true;
},
@@ -282,5 +291,11 @@ export default {
</template>
</gl-sprintf>
</gl-modal>
+ <confirm-fork-modal
+ v-if="showWebIdeButton || showEditButton"
+ v-model="showForkModal"
+ :modal-id="forkModalId"
+ :fork-path="forkPath"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
index af0235bfc69..8008b85bbdb 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
@@ -31,10 +31,6 @@ export default {
type: Object,
required: true,
},
- enableLabelPermalinks: {
- type: Boolean,
- required: true,
- },
labelFilterParam: {
type: String,
required: false,
@@ -121,7 +117,10 @@ export default {
},
showIssuableMeta() {
return Boolean(
- this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
+ this.hasSlotContents('status') ||
+ this.hasSlotContents('statistics') ||
+ this.showDiscussions ||
+ this.issuable.assignees,
);
},
issuableNotesLink() {
@@ -139,11 +138,8 @@ export default {
return label.title || label.name;
},
labelTarget(label) {
- if (this.enableLabelPermalinks) {
- const value = encodeURIComponent(this.labelTitle(label));
- return `?${this.labelFilterParam}[]=${value}`;
- }
- return '#';
+ const value = encodeURIComponent(this.labelTitle(label));
+ return `?${this.labelFilterParam}[]=${value}`;
},
/**
* This is needed as an independent method since
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
index 2f8401b45f0..028d48e7e8a 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -15,6 +15,7 @@ const VueDraggable = () => import('vuedraggable');
export default {
vueDraggableAttributes: {
animation: 200,
+ forceFallback: true,
ghostClass: 'gl-visibility-hidden',
tag: 'ul',
},
@@ -78,6 +79,11 @@ export default {
required: false,
default: null,
},
+ truncateCounts: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
currentTab: {
type: String,
required: true,
@@ -127,11 +133,6 @@ export default {
required: false,
default: 2,
},
- enableLabelPermalinks: {
- type: Boolean,
- required: false,
- default: true,
- },
labelFilterParam: {
type: String,
required: false,
@@ -261,6 +262,7 @@ export default {
:tabs="tabs"
:tab-counts="tabCounts"
:current-tab="currentTab"
+ :truncate-counts="truncateCounts"
@click="$emit('click-tab', $event)"
>
<template #nav-actions>
@@ -314,7 +316,6 @@ export default {
:data-qa-issuable-title="issuable.title"
:issuable-symbol="issuableSymbol"
:issuable="issuable"
- :enable-label-permalinks="enableLabelPermalinks"
:label-filter-param="labelFilterParam"
:show-checkbox="showBulkEditSidebar"
:checked="issuableChecked(issuable)"
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
index 9bf54e98cc4..0691bc02b5c 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
@@ -1,5 +1,6 @@
<script>
import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
+import { numberToMetricPrefix } from '~/lib/utils/number_utils';
import { formatNumber } from '~/locale';
export default {
@@ -22,6 +23,11 @@ export default {
type: String,
required: true,
},
+ truncateCounts: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
methods: {
isTabActive(tabName) {
@@ -31,7 +37,7 @@ export default {
return Number.isInteger(this.tabCounts[tab.name]);
},
formatNumber(count) {
- return formatNumber(count);
+ return this.truncateCounts ? numberToMetricPrefix(count) : formatNumber(count);
},
},
};
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
index d7da533d055..ee7e113af72 100644
--- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
@@ -102,7 +102,7 @@ export default {
</div>
</div>
<span>
- {{ __('Opened') }}
+ {{ __('Created') }}
<time-ago-tooltip data-testid="startTimeItem" :time="createdAt" />
{{ __('by') }}
</span>
diff --git a/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue
index 99dcccd12ed..774267639fc 100644
--- a/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue
@@ -1,8 +1,8 @@
<script>
import { GlIcon } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import Cookies from 'js-cookie';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
+
import { USER_COLLAPSED_GUTTER_COOKIE } from '../constants';
export default {
@@ -10,7 +10,7 @@ export default {
GlIcon,
},
data() {
- const userExpanded = !parseBoolean(Cookies.get(USER_COLLAPSED_GUTTER_COOKIE));
+ const userExpanded = !parseBoolean(getCookie(USER_COLLAPSED_GUTTER_COOKIE));
// We're deliberately keeping two different props for sidebar status;
// 1. userExpanded reflects value based on cookie `collapsed_gutter`.
@@ -46,7 +46,7 @@ export default {
this.isExpanded = !this.isExpanded;
this.userExpanded = this.isExpanded;
- Cookies.set(USER_COLLAPSED_GUTTER_COOKIE, !this.userExpanded);
+ setCookie(USER_COLLAPSED_GUTTER_COOKIE, !this.userExpanded);
this.updatePageContainerClass();
},
},
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 f67e590e2ce..1f3cc663848 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
@@ -11,7 +11,7 @@ export default {
WelcomePage,
LegacyContainer,
CreditCardVerification: () =>
- import('ee_component/pages/groups/new/components/credit_card_verification.vue'),
+ import('ee_component/namespaces/verification/components/credit_card_verification.vue'),
},
directives: {
SafeHtml,
diff --git a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
index d1630c9ac13..3afd1f9410b 100644
--- a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
+++ b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
@@ -14,7 +14,7 @@ export default {
components: {
GlButton,
},
- inject: ['projectPath'],
+ inject: ['projectFullPath'],
props: {
feature: {
type: Object,
@@ -47,7 +47,7 @@ export default {
try {
const { mutationSettings } = this;
const { data } = await this.$apollo.mutate(
- mutationSettings.getMutationPayload(this.projectPath),
+ mutationSettings.getMutationPayload(this.projectFullPath),
);
const { errors, successPath } = data[mutationSettings.mutationId];
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 12f2bc71505..f6d85599dba 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
@@ -102,8 +102,8 @@ export default {
error(error) {
this.showError(error);
},
- result({ loading }) {
- if (loading) {
+ result({ loading, data }) {
+ if (loading || !data) {
return;
}
diff --git a/app/assets/javascripts/work_items/graphql/fragmentTypes.json b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
deleted file mode 100644
index 3b837e84ee9..00000000000
--- a/app/assets/javascripts/work_items/graphql/fragmentTypes.json
+++ /dev/null
@@ -1 +0,0 @@
-{"__schema":{"types":[{"kind":"INTERFACE","name":"LocalWorkItemWidget","possibleTypes":[{"name":"LocalTitleWidget"}]}]}}
diff --git a/app/assets/javascripts/work_items/graphql/project_work_item_types.query.graphql b/app/assets/javascripts/work_items/graphql/project_work_item_types.query.graphql
new file mode 100644
index 00000000000..e7e3ce8c1ae
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/project_work_item_types.query.graphql
@@ -0,0 +1,11 @@
+query projectWorkItemTypes($fullPath: ID!) {
+ workspace: project(fullPath: $fullPath) {
+ id
+ workItemTypes {
+ nodes {
+ id
+ name
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js
index fb536a425c0..676fffb12d8 100644
--- a/app/assets/javascripts/work_items/graphql/provider.js
+++ b/app/assets/javascripts/work_items/graphql/provider.js
@@ -1,23 +1,14 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql';
import workItemQuery from './work_item.query.graphql';
-import introspectionQueryResultData from './fragmentTypes.json';
import { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql';
-const fragmentMatcher = new IntrospectionFragmentMatcher({
- introspectionQueryResultData,
-});
-
export function createApolloProvider() {
Vue.use(VueApollo);
const defaultClient = createDefaultClient(resolvers, {
- cacheConfig: {
- fragmentMatcher,
- },
typeDefs,
});
diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js
index 7cc8a23b7b1..10fae9b9cc0 100644
--- a/app/assets/javascripts/work_items/index.js
+++ b/app/assets/javascripts/work_items/index.js
@@ -5,11 +5,15 @@ import { createApolloProvider } from './graphql/provider';
export const initWorkItemsRoot = () => {
const el = document.querySelector('#js-work-items');
+ const { fullPath } = el.dataset;
return new Vue({
el,
router: createRouter(el.dataset.fullPath),
apolloProvider: createApolloProvider(),
+ provide: {
+ fullPath,
+ },
render(createElement) {
return createElement(App);
},
diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue
index 12bad5606d4..6c3bcf8f6a8 100644
--- a/app/assets/javascripts/work_items/pages/create_work_item.vue
+++ b/app/assets/javascripts/work_items/pages/create_work_item.vue
@@ -1,6 +1,8 @@
<script>
-import { GlButton, GlAlert } from '@gitlab/ui';
+import { GlButton, GlAlert, GlLoadingIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { s__ } from '~/locale';
import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
+import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
import ItemTitle from '../components/item_title.vue';
@@ -8,14 +10,55 @@ export default {
components: {
GlButton,
GlAlert,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
ItemTitle,
},
+ inject: ['fullPath'],
+ props: {
+ isModal: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ initialTitle: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
data() {
return {
- title: '',
- error: false,
+ title: this.initialTitle,
+ error: null,
+ workItemTypes: [],
+ selectedWorkItemType: null,
};
},
+ apollo: {
+ workItemTypes: {
+ query: projectWorkItemTypesQuery,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ };
+ },
+ update(data) {
+ return data.workspace?.workItemTypes?.nodes;
+ },
+ error() {
+ this.error = s__(
+ 'WorkItem|Something went wrong when fetching work item types. Please try again',
+ );
+ },
+ },
+ },
+ computed: {
+ dropdownButtonText() {
+ return this.selectedWorkItemType?.name || s__('WorkItem|Type');
+ },
+ },
methods: {
async createWorkItem() {
try {
@@ -35,35 +78,82 @@ export default {
},
},
} = response;
- this.$router.push({ name: 'workItem', params: { id } });
+ if (!this.isModal) {
+ this.$router.push({ name: 'workItem', params: { id } });
+ } else {
+ this.$emit('onCreate', this.title);
+ }
} catch {
- this.error = true;
+ this.error = s__(
+ 'WorkItem|Something went wrong when creating a work item. Please try again',
+ );
}
},
handleTitleInput(title) {
this.title = title;
},
+ handleCancelClick() {
+ if (!this.isModal) {
+ this.$router.go(-1);
+ return;
+ }
+ this.$emit('closeModal');
+ },
+ selectWorkItemType(type) {
+ this.selectedWorkItemType = type;
+ },
},
};
</script>
<template>
<form @submit.prevent="createWorkItem">
- <gl-alert v-if="error" variant="danger" @dismiss="error = false">{{
- __('Something went wrong when creating a work item. Please try again')
- }}</gl-alert>
- <item-title data-testid="title-input" @title-input="handleTitleInput" />
- <div class="gl-bg-gray-10 gl-py-5 gl-px-6">
+ <gl-alert v-if="error" variant="danger" @dismiss="error = null">{{ error }}</gl-alert>
+ <div :class="{ 'gl-px-5': isModal }" data-testid="content">
+ <item-title
+ :initial-title="title"
+ data-testid="title-input"
+ @title-input="handleTitleInput"
+ />
+ <div>
+ <gl-dropdown :text="dropdownButtonText">
+ <gl-loading-icon
+ v-if="$apollo.queries.workItemTypes.loading"
+ size="md"
+ data-testid="loading-types"
+ />
+ <template v-else>
+ <gl-dropdown-item
+ v-for="type in workItemTypes"
+ :key="type.id"
+ @click="selectWorkItemType(type)"
+ >
+ {{ type.name }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+ </div>
+ </div>
+ <div
+ class="gl-bg-gray-10 gl-py-5 gl-px-6 gl-mt-4"
+ :class="{ 'gl-display-flex gl-justify-content-end': isModal }"
+ >
<gl-button
variant="confirm"
:disabled="title.length === 0"
- class="gl-mr-3"
+ :class="{ 'gl-mr-3': !isModal }"
data-testid="create-button"
type="submit"
>
- {{ __('Create') }}
+ {{ s__('WorkItem|Create work item') }}
</gl-button>
- <gl-button type="button" data-testid="cancel-button" @click="$router.go(-1)">
+ <gl-button
+ type="button"
+ data-testid="cancel-button"
+ class="gl-order-n1"
+ :class="{ 'gl-mr-3': isModal }"
+ @click="handleCancelClick"
+ >
{{ __('Cancel') }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/work_items_hierarchy/components/app.vue b/app/assets/javascripts/work_items_hierarchy/components/app.vue
new file mode 100644
index 00000000000..621cfe5bace
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/components/app.vue
@@ -0,0 +1,101 @@
+<script>
+import { GlBanner } from '@gitlab/ui';
+import Cookies from 'js-cookie';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import RESPONSE from '../static_response';
+import { WORK_ITEMS_SURVEY_COOKIE_NAME, workItemTypes } from '../constants';
+import Hierarchy from './hierarchy.vue';
+
+export default {
+ components: {
+ GlBanner,
+ Hierarchy,
+ },
+ inject: ['illustrationPath', 'licensePlan'],
+ data() {
+ return {
+ bannerVisible: !parseBoolean(Cookies.get(WORK_ITEMS_SURVEY_COOKIE_NAME)),
+ workItemHierarchy: RESPONSE[this.licensePlan],
+ };
+ },
+ computed: {
+ hasUnavailableStructure() {
+ return this.workItemTypes.unavailable.length > 0;
+ },
+ workItemTypes() {
+ return this.workItemHierarchy.reduce(
+ (itemTypes, item) => {
+ const skipItem = workItemTypes[item.type].isWorkItem && !window.gon?.features?.workItems;
+
+ if (skipItem) {
+ return itemTypes;
+ }
+ const key = item.available ? 'available' : 'unavailable';
+ const nestedTypes = item.nestedTypes?.map((type) => workItemTypes[type]);
+
+ itemTypes[key].push({
+ ...item,
+ ...workItemTypes[item.type],
+ nestedTypes,
+ });
+
+ return itemTypes;
+ },
+ { available: [], unavailable: [] },
+ );
+ },
+ },
+ methods: {
+ handleClose() {
+ Cookies.set(WORK_ITEMS_SURVEY_COOKIE_NAME, 'true', { expires: 365 * 10 });
+ this.bannerVisible = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-banner
+ v-if="bannerVisible"
+ class="gl-mt-4 gl-px-5!"
+ :title="s__('Hierarchy|Help us improve work items in GitLab!')"
+ :button-text="s__('Hierarchy|Take the work items survey')"
+ button-link="https://forms.gle/u1BmRp8rTbwj52iq5"
+ :svg-path="illustrationPath"
+ @close="handleClose"
+ >
+ <p>
+ {{
+ s__(
+ 'Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you.',
+ )
+ }}
+ </p>
+ </gl-banner>
+ <h3 class="gl-mt-5!">{{ s__('Hierarchy|Planning hierarchy') }}</h3>
+ <p>
+ {{
+ s__(
+ 'Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals.',
+ )
+ }}
+ </p>
+
+ <div class="gl-font-weight-bold gl-mb-2">{{ s__('Hierarchy|Current structure') }}</div>
+ <p class="gl-mb-3!">{{ s__('Hierarchy|You can start using these items now.') }}</p>
+ <hierarchy :work-item-types="workItemTypes.available" />
+
+ <div
+ v-if="hasUnavailableStructure"
+ data-testid="unavailable-structure"
+ class="gl-font-weight-bold gl-mt-5 gl-mb-2"
+ >
+ {{ s__('Hierarchy|Unavailable structure') }}
+ </div>
+ <p v-if="hasUnavailableStructure" class="gl-mb-3!">
+ {{ s__('Hierarchy|These items are unavailable in the current structure.') }}
+ </p>
+ <hierarchy :work-item-types="workItemTypes.unavailable" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/work_items_hierarchy/components/hierarchy.vue b/app/assets/javascripts/work_items_hierarchy/components/hierarchy.vue
new file mode 100644
index 00000000000..9b81218b6e4
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/components/hierarchy.vue
@@ -0,0 +1,119 @@
+<script>
+import { GlIcon, GlBadge } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ GlBadge,
+ },
+ props: {
+ workItemTypes: {
+ type: Array,
+ required: true,
+ },
+ },
+ methods: {
+ isLastItem(index, workItem) {
+ const hasMoreThanOneItem = workItem.nestedTypes.length > 1;
+ const isLastItemInArray = index === workItem.nestedTypes.length - 1;
+
+ return isLastItemInArray && hasMoreThanOneItem;
+ },
+ nestedWorkItemTypeMargin(index, workItem) {
+ const isLastItemInArray = index === workItem.nestedTypes.length - 1;
+ const hasMoreThanOneItem = workItem.nestedTypes.length > 1;
+
+ if (isLastItemInArray && hasMoreThanOneItem) {
+ return 'gl-ml-0';
+ }
+
+ return 'gl-ml-6';
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div
+ v-for="workItem in workItemTypes"
+ :key="workItem.id"
+ class="gl-mb-3"
+ :class="{ flex: !workItem.available }"
+ >
+ <span
+ class="gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base gl-pl-2 gl-pt-2 gl-pb-2 gl-pr-3 gl-display-inline-flex gl-align-items-center gl-justify-content-center gl-line-height-normal"
+ data-testid="work-item-wrapper"
+ >
+ <span
+ :style="{
+ backgroundColor: workItem.backgroundColor,
+ color: workItem.color,
+ }"
+ class="gl-rounded-base gl-mr-2 gl-display-inline-flex justify-content-center align-items-center hierarchy-icon-wrapper"
+ >
+ <gl-icon :size="workItem.iconSize || 12" :name="workItem.icon" />
+ </span>
+
+ {{ workItem.title }}
+ </span>
+
+ <gl-badge
+ v-if="!workItem.available"
+ variant="info"
+ icon="license"
+ size="sm"
+ class="gl-ml-3 gl-align-self-center"
+ >{{ workItem.license }}</gl-badge
+ >
+
+ <div v-if="workItem.nestedTypes" :class="{ 'gl-relative': workItem.nestedTypes.length > 1 }">
+ <svg
+ v-if="workItem.nestedTypes.length > 1"
+ class="hierarchy-rounded-arrow-tail gl-text-gray-400"
+ data-testid="hierarchy-rounded-arrow-tail"
+ width="2"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <line
+ x1="0.75"
+ y1="1"
+ x2="0.75"
+ y2="100%"
+ stroke="currentColor"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ </svg>
+ <template v-for="(nestedWorkItem, index) in workItem.nestedTypes">
+ <div :key="nestedWorkItem.id" class="gl-display-block gl-mt-2 gl-ml-6">
+ <gl-icon name="arrow-down" class="gl-text-gray-400" />
+ </div>
+ <gl-icon
+ v-if="isLastItem(index, workItem)"
+ :key="nestedWorkItem.id"
+ name="level-up"
+ class="gl-text-gray-400 gl-ml-2 hierarchy-rounded-arrow"
+ />
+ <span
+ :key="nestedWorkItem.id"
+ class="gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base gl-pl-2 gl-pt-2 gl-pb-2 gl-pr-3 gl-display-inline-flex gl-align-items-center gl-justify-content-center gl-mt-2 gl-line-height-normal"
+ :class="nestedWorkItemTypeMargin(index, workItem)"
+ >
+ <span
+ :style="{
+ backgroundColor: nestedWorkItem.backgroundColor,
+ color: nestedWorkItem.color,
+ }"
+ class="gl-rounded-base gl-mr-2 gl-display-inline-flex justify-content-center align-items-center hierarchy-icon-wrapper"
+ >
+ <gl-icon :size="nestedWorkItem.iconSize || 12" :name="nestedWorkItem.icon" />
+ </span>
+
+ {{ nestedWorkItem.title }}
+ </span>
+ </template>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/work_items_hierarchy/constants.js b/app/assets/javascripts/work_items_hierarchy/constants.js
new file mode 100644
index 00000000000..c14fe67af4d
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/constants.js
@@ -0,0 +1,62 @@
+import { __ } from '~/locale';
+
+export const WORK_ITEMS_SURVEY_COOKIE_NAME = 'hide_work_items_hierarchy_survey';
+
+/**
+ * Hard-coded strings since we're rendering hierarchy
+ * items from mock responses. Remove this when we
+ * have a real hierarchy endpoint.
+ */
+export const LICENSE_PLAN = {
+ FREE: 'free',
+ PREMIUM: 'premium',
+ ULTIMATE: 'ultimate',
+};
+
+export const workItemTypes = {
+ EPIC: {
+ title: __('Epic'),
+ icon: 'epic',
+ color: '#694CC0',
+ backgroundColor: '#E1D8F9',
+ },
+ ISSUE: {
+ title: __('Issue'),
+ icon: 'issues',
+ color: '#1068BF',
+ backgroundColor: '#CBE2F9',
+ },
+ TASK: {
+ title: __('Task'),
+ icon: 'task-done',
+ color: '#217645',
+ backgroundColor: '#C3E6CD',
+ isWorkItem: true,
+ },
+ INCIDENT: {
+ title: __('Incident'),
+ icon: 'issue-type-incident',
+ backgroundColor: '#db2a0f',
+ color: '#FDD4CD',
+ iconSize: 16,
+ },
+ SUB_EPIC: {
+ title: __('Child epic'),
+ icon: 'epic',
+ color: '#AB6100',
+ backgroundColor: '#F5D9A8',
+ },
+ REQUIREMENT: {
+ title: __('Requirement'),
+ icon: 'requirements',
+ color: '#0068c5',
+ backgroundColor: '#c5e3fb',
+ },
+ TEST_CASE: {
+ title: __('Test case'),
+ icon: 'issue-type-test-case',
+ backgroundColor: '#007a3f',
+ color: '#bae8cb',
+ iconSize: 16,
+ },
+};
diff --git a/app/assets/javascripts/work_items_hierarchy/hierarchy_util.js b/app/assets/javascripts/work_items_hierarchy/hierarchy_util.js
new file mode 100644
index 00000000000..61d93acdb91
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/hierarchy_util.js
@@ -0,0 +1,10 @@
+import { LICENSE_PLAN } from './constants';
+
+export function inferLicensePlan({ hasSubEpics, hasEpics }) {
+ if (hasSubEpics) {
+ return LICENSE_PLAN.ULTIMATE;
+ } else if (hasEpics) {
+ return LICENSE_PLAN.PREMIUM;
+ }
+ return LICENSE_PLAN.FREE;
+}
diff --git a/app/assets/javascripts/work_items_hierarchy/static_response.js b/app/assets/javascripts/work_items_hierarchy/static_response.js
new file mode 100644
index 00000000000..d1e2e486082
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/static_response.js
@@ -0,0 +1,142 @@
+const FREE_TIER = 'free';
+const ULTIMATE_TIER = 'ultimate';
+const PREMIUM_TIER = 'premium';
+
+const RESPONSE = {
+ [FREE_TIER]: [
+ {
+ id: '1',
+ type: 'ISSUE',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '2',
+ type: 'TASK',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '3',
+ type: 'INCIDENT',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '4',
+ type: 'EPIC',
+ available: false,
+ license: 'Premium', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ {
+ id: '5',
+ type: 'SUB_EPIC',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ {
+ id: '6',
+ type: 'REQUIREMENT',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ {
+ id: '7',
+ type: 'TEST_CASE',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ ],
+
+ [PREMIUM_TIER]: [
+ {
+ id: '1',
+ type: 'EPIC',
+ available: true,
+ license: null,
+ nestedTypes: ['ISSUE'],
+ },
+ {
+ id: '2',
+ type: 'TASK',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '3',
+ type: 'INCIDENT',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '5',
+ type: 'SUB_EPIC',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ {
+ id: '6',
+ type: 'REQUIREMENT',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ {
+ id: '7',
+ type: 'TEST_CASE',
+ available: false,
+ license: 'Ultimate', // eslint-disable-line @gitlab/require-i18n-strings
+ nestedTypes: null,
+ },
+ ],
+
+ [ULTIMATE_TIER]: [
+ {
+ id: '1',
+ type: 'EPIC',
+ available: true,
+ license: null,
+ nestedTypes: ['SUB_EPIC', 'ISSUE'],
+ },
+ {
+ id: '2',
+ type: 'TASK',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '3',
+ type: 'INCIDENT',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '6',
+ type: 'REQUIREMENT',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ {
+ id: '7',
+ type: 'TEST_CASE',
+ available: true,
+ license: null,
+ nestedTypes: null,
+ },
+ ],
+};
+
+export default RESPONSE;
diff --git a/app/assets/javascripts/work_items_hierarchy/work_items_hierarchy_bundle.js b/app/assets/javascripts/work_items_hierarchy/work_items_hierarchy_bundle.js
new file mode 100644
index 00000000000..2258c725301
--- /dev/null
+++ b/app/assets/javascripts/work_items_hierarchy/work_items_hierarchy_bundle.js
@@ -0,0 +1,26 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import App from './components/app.vue';
+import { inferLicensePlan } from './hierarchy_util';
+
+export const initWorkItemsHierarchy = () => {
+ const el = document.querySelector('#js-work-items-hierarchy');
+
+ const { illustrationPath, hasEpics, hasSubEpics } = el.dataset;
+
+ const licensePlan = inferLicensePlan({
+ hasEpics: parseBoolean(hasEpics),
+ hasSubEpics: parseBoolean(hasSubEpics),
+ });
+
+ return new Vue({
+ el,
+ provide: {
+ illustrationPath,
+ licensePlan,
+ },
+ render(createElement) {
+ return createElement(App);
+ },
+ });
+};
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index ff2b82d1806..24549a170bd 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -31,3 +31,4 @@
@import './pages/storage_quota';
@import './pages/tree';
@import './pages/users';
+@import './pages/hierarchy';
diff --git a/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
index 377d5130571..a9be1d89495 100644
--- a/app/assets/stylesheets/components/design_management/design.scss
+++ b/app/assets/stylesheets/components/design_management/design.scss
@@ -1,4 +1,5 @@
$design-pin-diameter: 28px;
+$design-pin-diameter-sm: 24px;
$t-gray-a-16-design-pin: rgba($black, 0.16);
.layout-page.design-detail-layout {
@@ -12,24 +13,6 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
top: 35px;
}
- .design-note-pin {
- display: flex;
- height: $design-pin-diameter;
- width: $design-pin-diameter;
- box-sizing: content-box;
- background-color: $purple-500;
- color: $white;
- font-weight: $gl-font-weight-bold;
- border-radius: 50%;
- z-index: 1;
- padding: 0;
- border: 0;
-
- &.resolved {
- background-color: $gray-500;
- }
- }
-
.comment-indicator {
border-radius: 50%;
}
@@ -40,35 +23,6 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
cursor: grabbing;
}
}
-
- /**
- * Design pin that overlays the design
- */
- .frame .design-note-pin {
- box-shadow: 0 2px 4px $t-gray-a-08, 0 0 1px $t-gray-a-24;
- border: $white 2px solid;
- will-change: transform, box-shadow, opacity;
- // NOTE: verbose transition property required for Safari
- transition: transform $general-hover-transition-duration linear, box-shadow $general-hover-transition-duration linear, opacity $general-hover-transition-duration linear;
- transform-origin: 0 0;
- transform: translate(-50%, -50%);
-
- &:hover {
- transform: scale(1.2) translate(-50%, -50%);
- }
-
- &:active {
- box-shadow: 0 0 4px $t-gray-a-16-design-pin, 0 4px 12px $t-gray-a-16-design-pin;
- }
-
- &.inactive {
- @include gl-opacity-5;
-
- &:hover {
- @include gl-opacity-10;
- }
- }
- }
}
.design-scaler-wrapper {
@@ -177,3 +131,63 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
.design-card-header {
background: transparent;
}
+
+.design-note-pin {
+ display: flex;
+ height: $design-pin-diameter;
+ width: $design-pin-diameter;
+ box-sizing: content-box;
+ background-color: $purple-500;
+ color: $white;
+ font-weight: $gl-font-weight-bold;
+ border-radius: 50%;
+ z-index: 1;
+ padding: 0;
+ border: 0;
+
+ &.draft {
+ background-color: $orange-500;
+ }
+
+ &.resolved {
+ background-color: $gray-500;
+ }
+
+ &.on-image {
+ box-shadow: 0 2px 4px $t-gray-a-08, 0 0 1px $t-gray-a-24;
+ border: $white 2px solid;
+ will-change: transform, box-shadow, opacity;
+ // NOTE: verbose transition property required for Safari
+ transition: transform $general-hover-transition-duration linear, box-shadow $general-hover-transition-duration linear, opacity $general-hover-transition-duration linear;
+ transform-origin: 0 0;
+ transform: translate(-50%, -50%);
+
+ &:hover {
+ transform: scale(1.2) translate(-50%, -50%);
+ }
+
+ &:active {
+ box-shadow: 0 0 4px $t-gray-a-16-design-pin, 0 4px 12px $t-gray-a-16-design-pin;
+ }
+
+ &.inactive {
+ @include gl-opacity-5;
+
+ &:hover {
+ @include gl-opacity-10;
+ }
+ }
+ }
+
+ &.small {
+ position: absolute;
+ border: 1px solid $white;
+ height: $design-pin-diameter-sm;
+ width: $design-pin-diameter-sm;
+ }
+
+ &.user-avatar {
+ top: 25px;
+ right: 8px;
+ }
+}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index c1c8bfffff7..8e43a9b1b0d 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -46,7 +46,6 @@
@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/blank.scss b/app/assets/stylesheets/framework/blank.scss
deleted file mode 100644
index 7dd7ab339dd..00000000000
--- a/app/assets/stylesheets/framework/blank.scss
+++ /dev/null
@@ -1,118 +0,0 @@
-.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/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index e0e9043ae24..9cebd4f49a4 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -158,12 +158,6 @@
line-height: $gl-btn-small-line-height;
}
- &.btn-xs {
- padding: 2px $gl-btn-padding;
- font-size: $gl-btn-xs-font-size;
- line-height: $gl-btn-xs-line-height;
- }
-
&.btn-success {
@include btn-green;
}
@@ -372,29 +366,6 @@
background-color: transparent;
border-color: transparent;
}
-
- &.btn-secondary-hover-link,
- &.btn-default-hover-link {
- color: $gl-text-color-secondary;
-
- &:hover,
- &:active,
- &:focus {
- color: $blue-600;
- text-decoration: none;
- }
- }
-
- &.btn-primary-hover-link {
- color: inherit;
-
- &:hover,
- &:active,
- &:focus {
- color: $blue-600;
- text-decoration: none;
- }
- }
}
// The .btn-svg class is available for legacy icon buttons to
@@ -438,10 +409,6 @@ fieldset[disabled] .btn,
cursor: default;
}
-.btn-no-padding {
- padding: 0;
-}
-
// This class helps convert `.gl-button` children so that they consistently
// match the style of `.btn` elements which might be around them. Ideally we
// wouldn't need this class.
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 2a3ed29258a..7b4f68e7a44 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -267,6 +267,8 @@
.nav-item-name {
flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
> a,
@@ -336,7 +338,8 @@
.nav-sidebar-inner-scroll {
@include gl-h-full;
@include gl-w-full;
- @include gl-overflow-auto;
+ @include gl-overflow-x-hidden;
+ @include gl-overflow-y-auto;
> div.context-header {
@include gl-mt-2;
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index ffacac07517..f0495fdc94e 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -582,6 +582,25 @@ table.code {
}
}
+.diff-expansion-cell {
+ flex: 1 1;
+ min-width: max-content;
+}
+
+.diff-expansion-cell-middle {
+ flex: 0 1 max-content;
+}
+
+@media only screen and (min-width: $breakpoint-xl) {
+ .diff-expansion-cell-start {
+ text-align: right;
+ }
+
+ .diff-expansion-cell-end {
+ text-align: left;
+ }
+}
+
// Merge request diff grid layout
.diff-grid {
.diff-td {
@@ -603,6 +622,14 @@ table.code {
grid-template-columns: 50px 8px 0 1fr;
}
+ .diff-grid-3-col {
+ grid-template-columns: 50px 1fr !important;
+ }
+
+ &.inline-diff-view .diff-grid-3-col {
+ grid-template-columns: 50px 50px 1fr !important;
+ }
+
.diff-grid-comments {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -832,6 +859,8 @@ table.code {
}
.diff-files-changed {
+ background-color: $body-bg;
+
.inline-parallel-buttons {
@include gl-relative;
z-index: 1;
@@ -840,7 +869,6 @@ table.code {
@include media-breakpoint-up(sm) {
@include gl-sticky;
top: calc(#{$header-height} + #{$mr-tabs-height});
- @include gl-bg-white;
z-index: 200;
.with-performance-bar & {
@@ -1064,24 +1092,6 @@ table.code {
}
}
-.frame .badge.badge-pill,
-.image-diff-avatar-link .badge.badge-pill,
-.user-avatar-link .badge.badge-pill,
-.notes > .badge.badge-pill {
- position: absolute;
- background-color: $blue-400;
- color: $white;
- border: $white 1px solid;
- min-height: $gl-padding;
- padding: 5px 8px;
- border-radius: 12px;
-
- &:focus {
- outline: none;
- }
-}
-
-.frame .badge.badge-pill,
.frame .image-comment-badge,
.frame .comment-indicator {
// Center align badges on the frame
@@ -1113,11 +1123,6 @@ table.code {
}
}
-.notes > .badge.badge-pill {
- display: none;
- left: -13px;
-}
-
.discussion-notes {
min-height: 35px;
@@ -1126,18 +1131,22 @@ table.code {
min-height: 25px;
}
+ .diff-notes-expand {
+ display: none;
+ }
+
&.collapsed {
background-color: $white;
+ .diff-notes-expand {
+ display: initial;
+ }
+
.diff-notes-collapse,
.note,
.discussion-reply-holder {
display: none;
}
-
- .notes > .badge.badge-pill {
- display: block;
- }
}
}
@@ -1183,7 +1192,7 @@ table.code {
}
}
-@media (max-width: map-get($grid-breakpoints, md)-1) {
+@media (max-width: map-get($grid-breakpoints, lg)-1) {
.diffs .files {
@include fixed-width-container;
flex-direction: column;
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 9209a0c2173..9387500e66f 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -411,11 +411,6 @@ span.idiff {
margin-right: 1.5em;
}
-.label-lfs {
- color: $common-gray-light;
- border: 1px solid $common-gray-light;
-}
-
.preview-container {
overflow: auto;
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 2a46e50f0da..4d0d64ae723 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -150,6 +150,10 @@ label {
margin-bottom: 0;
margin-top: #{$grid-size / 2};
font-size: $gl-font-size;
+
+ .invisible {
+ visibility: hidden;
+ }
}
.gl-field-error,
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 68535badd78..1004383cfd3 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -150,7 +150,7 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
}
li {
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
+ .badge.badge-pill:not(.gl-badge) {
box-shadow: none;
font-weight: $gl-font-weight-bold;
}
@@ -415,49 +415,6 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
}
}
-.title-container,
-.navbar-nav {
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
- position: inherit;
- font-weight: $gl-font-weight-normal;
- margin-left: -6px;
- font-size: 11px;
- color: var(--gray-950, $white);
- padding: 0 5px;
- line-height: 12px;
- border-radius: 7px;
- box-shadow: 0 1px 0 rgba($gl-header-color, 0.2);
-
- &.green-badge {
- background-color: var(--green-400, $green-400);
- }
-
- &.merge-requests-count {
- background-color: var(--orange-400, $orange-400);
- }
-
- &.todos-count {
- background-color: var(--blue-400, $blue-400);
- }
- }
-
- .canary-badge {
- .badge {
- font-size: $gl-font-size-small;
- line-height: $gl-line-height;
- padding: 0 $grid-size;
- }
-
- &:hover {
- text-decoration: none;
-
- .badge {
- text-decoration: none;
- }
- }
- }
-}
-
@include media-breakpoint-down(xs) {
.navbar-gitlab .container-fluid {
font-size: 18px;
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index c6e52c13e83..7731ec751c9 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -67,6 +67,27 @@
}
}
}
+
+ .gl-tabs-nav {
+ @include media-breakpoint-down(xs) {
+ .nav-item {
+ flex: 1;
+ border-bottom: 1px solid $border-color;
+ }
+
+ .gl-tab-nav-item {
+ padding-top: $gl-padding-4;
+ padding-bottom: $gl-padding-8;
+ }
+
+ .md-header-toolbar {
+ width: 100%;
+ display: flex;
+ flex-wrap: wrap;
+ margin-top: $gl-padding-8;
+ }
+ }
+ }
}
.md-header-tab {
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 563075b911c..8cad55f414a 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -18,7 +18,6 @@
line-height: 28px;
color: $gl-text-color-secondary;
border: 0;
- border-bottom: 2px solid transparent;
white-space: nowrap;
&:hover,
@@ -26,7 +25,7 @@
&:focus {
text-decoration: none;
color: $black;
- border-bottom: 2px solid $gray-darkest;
+ box-shadow: inset 0 -2px 0 0 $gray-darkest;
}
}
@@ -40,7 +39,7 @@
a.active {
color: $black;
font-weight: $gl-font-weight-bold;
- border-bottom: 2px solid var(--gl-theme-accent, $theme-indigo-500);
+ box-shadow: inset 0 -2px 0 0 var(--gl-theme-accent, $theme-indigo-500);
.badge.badge-pill {
color: $black;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 51c41c46f61..feedc40b487 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -47,6 +47,10 @@
margin-bottom: $gl-spacing-scale-2;
}
+ img {
+ max-width: 100%;
+ }
+
img:not(.emoji) {
margin: 0 0 8px;
}
@@ -62,15 +66,6 @@
min-width: inherit;
min-height: inherit;
background-color: inherit;
- max-width: 100%;
- }
-
- &:not(.md) img:not(.emoji) {
- border: 1px solid $white-normal;
- padding: 5px;
- margin: 5px 0;
- // Ensure that image does not exceed viewport
- max-height: calc(100vh - 100px);
}
details {
@@ -375,7 +370,8 @@
// Loose lists need bottom margin added back
p ~ ol,
p ~ ul {
- margin-bottom: 16px; }
+ margin-bottom: 16px;
+ }
}
ul:dir(rtl),
@@ -521,32 +517,26 @@
-moz-osx-font-smoothing: grayscale;
}
- .fa-2x,
.admonitionblock td.icon [class^='fa icon-'] {
font-size: 2em;
}
- .fa-exclamation-triangle::before,
.admonitionblock td.icon .icon-warning::before {
content: 'âš ';
}
- .fa-exclamation-circle::before,
.admonitionblock td.icon .icon-important::before {
content: 'â—';
}
- .fa-lightbulb-o::before,
.admonitionblock td.icon .icon-tip::before {
content: '💡';
}
- .fa-thumb-tack::before,
.admonitionblock td.icon .icon-note::before {
content: '📌';
}
- .fa-fire::before,
.admonitionblock td.icon .icon-caution::before {
content: '🔥';
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 21add43ad3f..31ef5ae0646 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -52,6 +52,11 @@ $spacing-scale: (
5: #{4 * $grid-size}
);
+/* Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709 */
+$gl-spacing-scale-48: 48 * $grid-size;
+$gl-spacing-scale-75: 75 * $grid-size;
+/* End gitlab-ui#1709 */
+
/*
* Why another sizing scale???
* Great question, friend!
@@ -589,8 +594,6 @@ $gl-btn-vert-padding: 8px;
$gl-btn-horz-padding: 12px;
$gl-btn-small-font-size: 13px;
$gl-btn-small-line-height: 18px;
-$gl-btn-xs-font-size: 13px;
-$gl-btn-xs-line-height: 13px;
/*
* Badges
@@ -722,7 +725,7 @@ $calendar-activity-colors: (
#7fa8c9,
#527ba0,
#254e77,
-);
+) !default;
/*
* Commit Page
@@ -931,8 +934,6 @@ Merge requests
*/
$mr-tabs-height: 48px;
$mr-version-controls-height: 56px;
-$mr-widget-margin-left: 40px;
-$mr-review-bar-height: calc(2rem + 13px);
/*
Compare Branches
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index 97dd7edef13..bd327082e20 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -28,8 +28,24 @@
border-bottom: 1px solid $border;
}
- a {
+ button {
color: $link;
+ border: 0;
+ background: transparent;
+
+ &[disabled] {
+ color: desaturate($link, 100%);
+ opacity: 0.5;
+ cursor: default;
+ }
+
+ &:hover:not([disabled]) {
+ text-decoration: underline;
+ }
+
+ &:not(:focus-visible) {
+ outline: 0;
+ }
}
}
@@ -37,11 +53,11 @@
transition: border-left 0.1s ease-out;
&.coverage {
- border-left: 4px solid $coverage;
+ border-left: 2px solid $coverage;
}
&.no-coverage {
- border-left: 2px solid $no-coverage;
+ border-left: 4px solid $no-coverage;
}
}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 0b696f1be60..28878280d24 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -36,6 +36,7 @@ $dark-cm: #969896;
$dark-cp: #969896;
$dark-c1: #969896;
$dark-cs: #969896;
+$dark-cd: #969896;
$dark-gd: #c66;
$dark-gh: #8abeb7;
$dark-gi: #b5bd68;
@@ -168,8 +169,8 @@ $dark-il: #de935f;
}
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
@include line-number-hover;
@@ -236,6 +237,7 @@ $dark-il: #de935f;
.cp { color: $dark-cp; } /* Comment.Preproc */
.c1 { color: $dark-c1; } /* Comment.Single */
.cs { color: $dark-cs; } /* Comment.Special */
+ .cd { color: $dark-cd; } /* Comment.Doc */
.gd { color: $dark-gd; } /* Generic.Deleted */
.ge { font-style: italic; } /* Generic.Emph */
.gh { /* Generic.Heading */
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index ae72c0b6bf4..6faf1cffdef 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -38,6 +38,7 @@ $monokai-cm: #75715e;
$monokai-cp: #75715e;
$monokai-c1: #75715e;
$monokai-cs: #75715e;
+$monokai-cd: #75715e;
$monokai-kc: #66d9ef;
$monokai-kd: #66d9ef;
$monokai-kn: #f92672;
@@ -169,8 +170,8 @@ $monokai-gh: #75715e;
}
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
@include line-number-hover;
@@ -240,6 +241,7 @@ $monokai-gh: #75715e;
.cp { color: $monokai-cp; } /* Comment.Preproc */
.c1 { color: $monokai-c1; } /* Comment.Single */
.cs { color: $monokai-cs; } /* Comment.Special */
+ .cd { color: $monokai-cd; } /* Comment.Doc */
.ge { font-style: italic; } /* Generic.Emph */
.gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
.kc { color: $monokai-kc; } /* Keyword.Constant */
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 913b289d808..9c28d9463dc 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -66,9 +66,9 @@
}
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
- &.code-search-line:hover {
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
+ &:not(.match) &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
@include line-number-hover;
}
@@ -204,6 +204,7 @@
.cp { color: $gl-text-color; } /* Comment.Preproc */
.c1 { color: $gl-text-color; } /* Comment.Single */
.cs { color: $gl-text-color; } /* Comment.Special */
+ .cd { color: $gl-text-color; } /* Comment.Doc */
.ge { color: $gl-text-color; } /* Generic.Emph */
.gr { color: $gl-text-color; } /* Generic.Error */
.gh { color: $gl-text-color; } /* Generic.Heading */
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index eee699ca4c2..c9f889c79fc 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -35,6 +35,7 @@ $solarized-dark-cm: #586e75;
$solarized-dark-cp: #859900;
$solarized-dark-c1: #586e75;
$solarized-dark-cs: #859900;
+$solarized-dark-cd: #586e75;
$solarized-dark-gd: #2aa198;
$solarized-dark-ge: #93a1a1;
$solarized-dark-gr: #dc322f;
@@ -148,8 +149,8 @@ $solarized-dark-il: #2aa198;
@include line-coverage-border-color($solarized-dark-coverage, $solarized-dark-no-coverage);
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
@include line-number-hover;
@@ -258,6 +259,7 @@ $solarized-dark-il: #2aa198;
.cp { color: $solarized-dark-cp; } /* Comment.Preproc */
.c1 { color: $solarized-dark-c1; } /* Comment.Single */
.cs { color: $solarized-dark-cs; } /* Comment.Special */
+ .cd { color: $solarized-dark-cd; } /* Comment.Doc */
.gd { color: $solarized-dark-gd; } /* Generic.Deleted */
.ge { /* Generic.Emph */
color: $solarized-dark-ge;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 8c5e1f7318b..0108d7e496f 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -37,6 +37,7 @@ $solarized-light-cm: #93a1a1;
$solarized-light-cp: #859900;
$solarized-light-c1: #93a1a1;
$solarized-light-cs: #859900;
+$solarized-light-cd: #93a1a1;
$solarized-light-gd: #2aa198;
$solarized-light-ge: #586e75;
$solarized-light-gr: #dc322f;
@@ -168,8 +169,8 @@ $solarized-light-il: #2aa198;
}
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
@include line-number-hover;
@@ -266,6 +267,7 @@ $solarized-light-il: #2aa198;
.cp { color: $solarized-light-cp; } /* Comment.Preproc */
.c1 { color: $solarized-light-c1; } /* Comment.Single */
.cs { color: $solarized-light-cs; } /* Comment.Special */
+ .cd { color: $solarized-light-cd; } /* Comment.Doc */
.gd { color: $solarized-light-gd; } /* Generic.Deleted */
.ge { /* Generic.Emph */
color: $solarized-light-ge;
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 80052f4a4d5..91d8f4a1ba5 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -18,6 +18,7 @@ $white-cm: #998;
$white-cp: #999;
$white-c1: #998;
$white-cs: #999;
+$white-cd: #998;
$white-gd: $black;
$white-gd-bg: #fdd;
$white-gd-x: $black;
@@ -118,6 +119,15 @@ pre.code,
.line_expansion {
@include diff-expansion($gray-light, $border-color, $blue-600);
+
+ &.diff-tr:last-child {
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+
+ .diff-td {
+ border-bottom: 0;
+ }
+ }
}
// Diff line
@@ -128,8 +138,8 @@ pre.code,
@include match-line;
}
- .diff-grid-left:hover,
- .diff-grid-right:hover,
+ &:not(.match) .diff-grid-left:hover,
+ &:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
.diff-line-num:not(.empty-cell):not(.conflict_marker_their):not(.conflict_marker_our) {
@include line-number-hover;
@@ -281,6 +291,9 @@ span.highlight_word {
font-weight: $gl-font-weight-bold;
font-style: italic; }
+.cd { color: $white-cd;
+ font-style: italic; }
+
.gd {
color: $white-gd;
background-color: $white-gd-bg;
diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
index 75c2428c1d4..fd212d14e30 100644
--- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss
+++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
@@ -22,6 +22,7 @@ $highlighted-cm: #998;
$highlighted-cp: #999;
$highlighted-c1: #998;
$highlighted-cs: #999;
+$highlighted-cd: #998;
$highlighted-gd: #000;
$highlighted-gd-bg: #fdd;
$highlighted-gd-x: #000;
@@ -173,6 +174,9 @@ span.highlight_word {
font-weight: $gl-font-weight-bold;
font-style: italic; }
+.cd { color: $highlighted-cd;
+ font-style: italic; }
+
.gd {
color: $highlighted-gd;
background-color: $highlighted-gd-bg;
diff --git a/app/assets/stylesheets/page_bundles/dashboard_projects.scss b/app/assets/stylesheets/page_bundles/dashboard_projects.scss
new file mode 100644
index 00000000000..eb0e1701b7f
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/dashboard_projects.scss
@@ -0,0 +1,35 @@
+@import 'mixins_and_variables_and_functions';
+
+.blank-state {
+ padding: 20px 50px;
+ min-height: 240px;
+ width: calc(50% - #{$gl-padding-8});
+
+ @include media-breakpoint-down(sm) {
+ width: 100%;
+ flex-direction: column;
+ justify-content: center;
+ padding: 50px 20px;
+ }
+}
+
+.blank-state-link {
+ &:hover {
+ background-color: $gray-light;
+ text-decoration: none;
+ color: $gl-text-color;
+ }
+}
+
+.blank-state-icon {
+ svg {
+ display: block;
+ }
+}
+
+.blank-state-body {
+ @include media-breakpoint-down(sm) {
+ text-align: center;
+ margin-top: 20px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index d37171bc75e..6c270852e53 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -630,7 +630,6 @@ $ide-commit-header-height: 48px;
width: 1px;
background: var(--ide-highlight-background, $white);
}
-
}
&.is-right {
@@ -642,17 +641,6 @@ $ide-commit-header-height: 48px;
left: -1px;
}
}
-
- .ide-commit-badge {
- background-color: var(--ide-highlight-accent, $almost-black) !important;
- color: var(--ide-highlight-background, $white) !important;
- position: absolute;
- left: 38px;
- top: $gl-padding-8;
- font-size: $gl-font-size-12;
- padding: 2px $gl-padding-4;
- font-weight: $gl-font-weight-bold !important;
- }
}
.ide-activity-bar {
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index 9fe0490571e..1c8fd7e2590 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -40,10 +40,6 @@ $header-height: 40px;
max-width: 1000px;
}
-.jira-connect-app-body {
- max-width: 768px;
-}
-
// needed for external_link
svg.s16 {
width: 16px;
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 37ab2e2be2b..63e951be698 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -1,5 +1,10 @@
@import 'mixins_and_variables_and_functions';
+$mr-review-bar-height: calc(2rem + 13px);
+$mr-widget-margin-left: 40px;
+$mr-widget-min-height: 69px;
+$tabs-holder-z-index: 250;
+
.compare-versions-container {
min-width: 0;
}
@@ -45,11 +50,9 @@
top: calc(#{$top-pos} + var(--system-header-height, 0px) + var(--performance-bar-height, 0px));
// stylelint-disable-next-line length-zero-no-unit
max-height: calc(100vh - #{$top-pos} - var(--system-header-height, 0px) - var(--performance-bar-height, 0px) - var(--review-bar-height, 0px));
- z-index: 205;
.drag-handle {
bottom: 16px;
- transform: translateX(10px);
}
}
@@ -94,7 +97,7 @@
line-height: 0;
}
-@media (max-width: map-get($grid-breakpoints, md)-1) {
+@media (max-width: map-get($grid-breakpoints, lg)-1) {
.diffs .files {
.diff-tree-list {
position: relative;
@@ -110,6 +113,638 @@
}
}
+.ci-widget-container {
+ justify-content: space-between;
+ flex: 1;
+ flex-direction: row;
+
+ @include media-breakpoint-down(sm) {
+ flex-direction: column;
+
+ .stage-cell .stage-container {
+ margin-top: 16px;
+ }
+
+ .dropdown .mini-pipeline-graph-dropdown-menu.dropdown-menu {
+ transform: initial;
+ }
+ }
+
+ .coverage {
+ font-size: 12px;
+ color: var(--gray-500, $gray-500);
+ line-height: initial;
+ }
+}
+
+.deploy-body {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+
+ @include media-breakpoint-up(xs) {
+ flex-wrap: nowrap;
+ white-space: nowrap;
+ }
+
+ @include media-breakpoint-down(md) {
+ flex-direction: column;
+ align-items: flex-start;
+
+ .deployment-info {
+ margin-bottom: $gl-padding;
+ }
+ }
+
+ > *:not(:last-child) {
+ margin-right: 0.3em;
+ }
+
+ svg {
+ vertical-align: text-top;
+ }
+
+ .deployment-info {
+ flex: 1;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ min-width: 100px;
+
+ @include media-breakpoint-up(xs) {
+ min-width: 0;
+ max-width: 100%;
+ }
+ }
+
+ .dropdown-menu {
+ width: 400px;
+ }
+}
+
+.deploy-heading,
+.merge-train-position-indicator {
+ @include media-breakpoint-up(md) {
+ padding: $gl-padding-8 $gl-padding;
+ }
+
+ .media-body {
+ min-width: 0;
+ font-size: 12px;
+ margin-left: 32px;
+ }
+
+ &:not(:last-child) {
+ border-bottom: 1px solid var(--border-color, $border-color);
+ }
+}
+
+.diff-file-row.is-active {
+ background-color: var(--gray-50, $gray-50);
+}
+
+.mr-conflict-loader {
+ max-width: 334px;
+
+ > svg {
+ vertical-align: middle;
+ }
+}
+
+.mr-info-list {
+ clear: left;
+ position: relative;
+ padding-top: 4px;
+
+ p {
+ margin: 0;
+ position: relative;
+ padding: 4px 0;
+
+ &:last-child {
+ padding-bottom: 0;
+ }
+ }
+
+ &.mr-memory-usage {
+ p {
+ float: left;
+ }
+
+ .memory-graph-container {
+ float: left;
+ margin-left: 5px;
+ }
+ }
+}
+
+.mr-memory-usage {
+ width: 100%;
+
+ p.usage-info-loading .usage-info-load-spinner {
+ margin-right: 10px;
+ font-size: 16px;
+ }
+}
+
+.mr-ready-to-merge-loader {
+ max-width: 418px;
+
+ > svg {
+ vertical-align: middle;
+ }
+}
+
+.mr-section-container {
+ border: 1px solid var(--border-color, $border-color);
+ border-radius: $border-radius-default;
+ background: var(--white, $white);
+
+ > .mr-widget-border-top:first-of-type {
+ border-top: 0;
+ }
+}
+
+.mr-source-target {
+ flex-wrap: wrap;
+ padding: $gl-padding;
+ background: var(--white, $white);
+ min-height: $mr-widget-min-height;
+
+ @include media-breakpoint-up(md) {
+ align-items: center;
+ }
+
+ .git-merge-container {
+ justify-content: space-between;
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+
+ @include media-breakpoint-down(md) {
+ flex-direction: column;
+ align-items: stretch;
+
+ .branch-actions {
+ margin-top: 16px;
+ }
+ }
+
+ @include media-breakpoint-up(lg) {
+ .branch-actions {
+ align-self: center;
+ margin-left: $gl-padding;
+ white-space: nowrap;
+ }
+ }
+ }
+
+ .diverged-commits-count {
+ color: var(--gray-500, $gl-text-color-secondary);
+ }
+}
+
+.mr-state-widget {
+ color: var(--gl-text-color, $gl-text-color);
+
+ .commit-message-edit {
+ border-radius: $border-radius-default;
+ }
+
+ .mr-widget-section:not(:first-child) {
+ border-top: solid 1px var(--border-color, $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;
+ }
+
+ .commits-list {
+ > li {
+ padding: $gl-padding;
+
+ @include media-breakpoint-up(md) {
+ margin-left: $gl-spacing-scale-7;
+ }
+ }
+ }
+
+ .mr-commit-dropdown {
+ .dropdown-menu {
+ @include media-breakpoint-up(md) {
+ width: 150%;
+ }
+ }
+ }
+
+ .mr-report {
+ padding: 0;
+
+ > .media {
+ padding: $gl-padding;
+ }
+ }
+
+ form {
+ margin-bottom: 0;
+
+ .clearfix {
+ margin-bottom: 0;
+ }
+ }
+
+ label {
+ margin-bottom: 0;
+ }
+
+ .btn {
+ font-size: $gl-font-size;
+ }
+
+ .accept-merge-holder {
+ .accept-action {
+ display: inline-block;
+ float: left;
+ }
+ }
+
+ .ci-widget {
+ color: var(--gl-text-color, $gl-text-color);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ @include media-breakpoint-down(xs) {
+ flex-wrap: wrap;
+ }
+
+ .ci-widget-content {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ }
+ }
+
+ .mr-widget-icon {
+ font-size: 22px;
+ }
+
+ .mr-loading-icon {
+ margin: 3px 0;
+ }
+
+ .ci-status-icon svg {
+ margin: 3px 0;
+ position: relative;
+ overflow: visible;
+ display: block;
+ }
+
+ .mr-widget-pipeline-graph {
+ .dropdown-menu {
+ z-index: $zindex-dropdown-menu;
+ }
+ }
+
+ .normal {
+ flex: 1;
+ flex-basis: auto;
+ }
+
+ .capitalize {
+ text-transform: capitalize;
+ }
+
+ .label-branch {
+ @include gl-font-monospace;
+ font-size: 95%;
+ color: var(--gl-text-color, $gl-text-color);
+ font-weight: normal;
+ overflow: hidden;
+ word-break: break-all;
+ }
+
+ .deploy-link,
+ .label-branch {
+ &.label-truncate {
+ // NOTE: This selector targets its children because some of the HTML comes from
+ // 'source_branch_link'. Once this external HTML is no longer used, we could
+ // simplify this.
+ > a,
+ > span {
+ display: inline-block;
+ max-width: 12.5em;
+ margin-bottom: -6px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+ }
+
+ .mr-widget-body {
+ &:not(.mr-widget-body-line-height-1) {
+ line-height: 28px;
+ }
+
+ @include clearfix;
+
+ .approve-btn {
+ margin-right: 5px;
+ }
+
+ h4 {
+ float: left;
+ font-weight: $gl-font-weight-bold;
+ font-size: 14px;
+ line-height: inherit;
+ margin-top: 0;
+ margin-bottom: 0;
+
+ time {
+ font-weight: $gl-font-weight-normal;
+ }
+ }
+
+ .btn-grouped {
+ margin-left: 0;
+ margin-right: 7px;
+ }
+
+ label {
+ font-weight: $gl-font-weight-normal;
+ }
+
+ .spacing {
+ margin: 0 0 0 10px;
+ }
+
+ .bold,
+ .gl-font-weight-bold {
+ font-weight: $gl-font-weight-bold;
+ color: var(--gray-600, $gray-600);
+ margin-left: 10px;
+ }
+
+ .state-label {
+ font-weight: $gl-font-weight-bold;
+ padding-right: 10px;
+ }
+
+ .danger {
+ color: var(--red-500, $red-500);
+ }
+
+ .spacing,
+ .bold,
+ .gl-font-weight-bold {
+ vertical-align: middle;
+ }
+
+ .dropdown-menu {
+ li a {
+ padding: 5px;
+ }
+
+ .merge-opt-icon {
+ line-height: 1.5;
+ }
+
+ .merge-opt-title {
+ margin-left: 8px;
+ }
+ }
+
+ .has-custom-error {
+ display: inline-block;
+ }
+
+ @include media-breakpoint-down(xs) {
+ p {
+ font-size: 13px;
+ }
+
+ .btn-grouped {
+ float: none;
+ margin-right: 0;
+ }
+
+ .accept-action {
+ width: 100%;
+ text-align: center;
+ }
+ }
+
+ .commit-message-editor {
+ label {
+ padding: 0;
+ }
+ }
+
+ &.mr-widget-empty-state {
+ line-height: 20px;
+ padding: $gl-padding;
+
+ .artwork {
+
+ @include media-breakpoint-down(md) {
+ margin-bottom: $gl-padding;
+ }
+ }
+
+ .text {
+ p {
+ margin-top: $gl-padding;
+ }
+
+ .highlight {
+ margin: 0 0 $gl-padding;
+ font-weight: $gl-font-weight-bold;
+ }
+ }
+ }
+
+ &.mr-pipeline-suggest {
+ border-radius: $border-radius-default;
+ line-height: 20px;
+ border: 1px solid var(--border-color, $border-color);
+
+ .circle-icon-container {
+ color: var(--gray-100, $gl-text-color-quaternary);
+ }
+ }
+ }
+
+ .ci-coverage {
+ float: right;
+ }
+
+ .stop-env-container {
+ color: var(--gl-text-color, $gl-text-color);
+ float: right;
+
+ a {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+ }
+}
+
+.mr-widget-alert-container {
+ $radius: $border-radius-default - 1px;
+
+ border-radius: $radius $radius 0 0;
+
+ .gl-alert:not(:last-child) {
+ margin-bottom: 1px;
+ }
+}
+
+.mr-widget-body,
+.mr-widget-content {
+ padding: $gl-padding;
+}
+
+.mr-widget-border-top {
+ border-top: 1px solid var(--border-color, $border-color);
+}
+
+.mr-widget-extension {
+ border-top: 1px solid var(--border-color, $border-color);
+ background-color: var(--gray-50, $gray-50);
+
+ &.clickable:hover {
+ background-color: var(--gray-100, $gray-100);
+ cursor: pointer;
+ }
+}
+
+.mr-widget-extension-icon::before {
+ @include gl-content-empty;
+ @include gl-absolute;
+ @include gl-left-0;
+ @include gl-top-0;
+ @include gl-opacity-3;
+ @include gl-border-solid;
+ @include gl-border-4;
+ @include gl-rounded-full;
+
+ width: 24px;
+ height: 24px;
+}
+
+.mr-widget-heading {
+ position: relative;
+ border: 1px solid var(--border-color, $border-color);
+ border-radius: $border-radius-default;
+ background: var(--white, $white);
+
+ .gl-skeleton-loader {
+ display: block;
+ }
+}
+
+.mr-widget-info {
+ padding-left: $gl-padding;
+ padding-right: $gl-padding;
+}
+
+.mr-widget-margin-left {
+ margin-left: $mr-widget-margin-left;
+}
+
+.mr-widget-section {
+ .code-text {
+ flex: 1;
+ }
+}
+
+.mr-widget-workflow {
+ margin-top: $gl-padding;
+ position: relative;
+
+ &::before {
+ content: '';
+ border-left: 1px solid var(--gray-100, $gray-100);
+ position: absolute;
+ left: 28px;
+ top: -17px;
+ height: 16px;
+ }
+}
+
+.mr-version-controls {
+ position: relative;
+ z-index: $tabs-holder-z-index + 10;
+ background: var(--white, $white);
+ color: var(--gl-text-color, $gl-text-color);
+ margin-top: -1px;
+
+ .mr-version-menus-container {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ padding: 16px;
+ z-index: 199;
+ white-space: nowrap;
+
+ .gl-dropdown-toggle {
+ width: auto;
+ max-width: 170px;
+
+ svg {
+ top: 10px;
+ right: 8px;
+ }
+ }
+ }
+
+ .content-block {
+ padding: $gl-padding;
+ border-bottom: 0;
+ }
+
+ .mr-version-dropdown,
+ .mr-version-compare-dropdown {
+ margin: 0 0.5rem;
+ }
+
+ .dropdown-title {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ // Shortening button height by 1px to make compare-versions
+ // header 56px and fit into our 8px design grid
+ .btn {
+ height: 34px;
+ }
+
+ @include media-breakpoint-up(md) {
+ position: -webkit-sticky;
+ position: sticky;
+ top: calc(#{$header-height} + #{$mr-tabs-height});
+
+ .with-system-header & {
+ top: calc(#{$header-height} + #{$mr-tabs-height} + #{$system-header-height});
+ }
+
+ .with-system-header.with-performance-bar & {
+ top: calc(#{$header-height} + #{$mr-tabs-height} + #{$system-header-height} + #{$performance-bar-height});
+ }
+
+ .mr-version-menus-container {
+ flex-wrap: nowrap;
+ }
+
+ .with-performance-bar & {
+ top: calc(#{$header-height} + #{$performance-bar-height} + #{$mr-tabs-height});
+ }
+ }
+}
+
// TODO: Move to GitLab UI
.mr-extenson-scrim {
background: linear-gradient(to bottom, rgba($gray-light, 0), rgba($gray-light, 1));
diff --git a/app/assets/stylesheets/page_bundles/milestone.scss b/app/assets/stylesheets/page_bundles/milestone.scss
index 08d9d24d246..989219552a6 100644
--- a/app/assets/stylesheets/page_bundles/milestone.scss
+++ b/app/assets/stylesheets/page_bundles/milestone.scss
@@ -42,12 +42,6 @@ $status-box-line-height: 26px;
}
.milestone-content {
- .issues-count {
- margin-right: 17px;
- float: right;
- width: 105px;
- }
-
.issuable-row {
span {
a {
diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index a9d353a0444..cbb6d68bf35 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -139,7 +139,7 @@
}
.gl-downstream-pipeline-job-width {
- width: 240px;
+ width: 170px;
}
.gl-linked-pipeline-padding {
diff --git a/app/assets/stylesheets/page_bundles/project.scss b/app/assets/stylesheets/page_bundles/project.scss
index 7f044f081d4..0bc3cc6678c 100644
--- a/app/assets/stylesheets/page_bundles/project.scss
+++ b/app/assets/stylesheets/page_bundles/project.scss
@@ -49,7 +49,7 @@
.project-repo-buttons {
.btn {
svg {
- fill: $gray-500;
+ fill: var(--gray-500, $gray-500);
}
}
@@ -80,3 +80,134 @@
margin-top: $gl-padding-8;
}
}
+
+.project-stats,
+.project-buttons {
+ .scrolling-tabs-container {
+ .scrolling-tabs {
+ margin-top: $gl-padding-8;
+ margin-bottom: $gl-padding-8 - $browser-scrollbar-size;
+ padding-bottom: $browser-scrollbar-size;
+ flex-wrap: wrap;
+ border-bottom: 0;
+ }
+
+ .fade-left,
+ .fade-right {
+ top: 0;
+ height: calc(100% - #{$browser-scrollbar-size});
+
+ svg {
+ top: 50%;
+ margin-top: -$gl-padding-8;
+ }
+ }
+
+ .nav {
+ flex-basis: 100%;
+
+ + .nav {
+ margin: $gl-padding-8 0;
+ }
+ }
+
+ @include media-breakpoint-down(md) {
+ flex-direction: column;
+
+ .nav {
+ flex-wrap: nowrap;
+ }
+
+ .nav:first-child {
+ margin-right: $gl-padding-8;
+ }
+ }
+ }
+
+ .nav {
+ > li {
+ display: inline-block;
+
+ &:not(:last-child) {
+ margin-right: $gl-padding;
+ }
+
+ &.right {
+ vertical-align: top;
+ margin-top: 0;
+
+ @include media-breakpoint-up(lg) {
+ float: right;
+ }
+ }
+ }
+
+ .stat-text,
+ .stat-link {
+ padding: $gl-btn-vert-padding 0;
+ background-color: transparent;
+ font-size: $gl-font-size;
+ line-height: $gl-btn-line-height;
+ color: var(--gray-500, $gl-text-color-secondary);
+ white-space: pre-wrap;
+ }
+
+ .stat-link {
+ border-bottom: 0;
+ color: var(--black, $black);
+
+ &:hover,
+ &:focus {
+ text-decoration: underline;
+ border-bottom: 0;
+ }
+
+ .project-stat-value {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ .icon {
+ color: var(--gray-500, $gl-text-color-secondary);
+ }
+
+ .add-license-link {
+ &,
+ .icon {
+ color: var(--blue-600, $blue-600);
+ }
+ }
+ }
+
+ .btn {
+ margin-bottom: $gl-padding-8;
+ padding: $gl-btn-vert-padding $gl-btn-padding;
+ line-height: $gl-btn-line-height;
+
+ .icon {
+ top: 0;
+ }
+ }
+ }
+}
+
+.project-buttons {
+ .nav > li:not(:last-child) {
+ margin-right: $gl-padding-8;
+ }
+}
+
+.git-empty {
+ margin-bottom: 7px;
+
+ h5 {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ .light-well {
+ border-radius: 2px;
+
+ color: var(--gray-600, $well-light-text-color);
+ font-size: 13px;
+ line-height: 1.6em;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/projects_edit.scss b/app/assets/stylesheets/page_bundles/projects_edit.scss
new file mode 100644
index 00000000000..9a8b4ffcdd7
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/projects_edit.scss
@@ -0,0 +1,25 @@
+@import 'page_bundles/mixins_and_variables_and_functions';
+
+.project-repo-select {
+ transition: background 2s ease-out;
+
+ &:disabled {
+ opacity: 0.5;
+ pointer-events: none;
+ }
+
+ .highlight-changes & {
+ background: var(--green-50, $highlight-changes-color);
+ transition: none;
+ }
+}
+
+.project-feature-controls {
+ max-width: 432px;
+}
+
+.project-feature-setting-group {
+ .project-feature-controls {
+ max-width: 400px;
+ }
+}
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index 5a091c14e53..d9ad82d4e4b 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -7,13 +7,6 @@
}
}
- .gl-card-body {
- @include media-breakpoint-up(sm) {
- @include gl-pt-2;
- min-height: 372px;
- }
- }
-
@include media-breakpoint-down(xs) {
.nav-controls {
@include gl-w-full;
@@ -27,6 +20,13 @@
}
}
+.cluster-card-item {
+ @include media-breakpoint-up(sm) {
+ @include gl-pt-2;
+ min-height: 372px;
+ }
+}
+
.agent-activity-list {
.system-note .timeline-entry-inner {
.timeline-icon {
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index ca6c9b9a073..7ac3ef2221f 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -112,19 +112,6 @@ table.pipeline-project-metrics tr td {
font-weight: $gl-font-weight-normal;
}
-.js-groups-dropdown {
- width: 100%;
-}
-
-.dropdown-group-transfer {
- bottom: 100%;
- top: initial;
-
- .dropdown-content {
- overflow-y: unset;
- }
-}
-
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
diff --git a/app/assets/stylesheets/pages/hierarchy.scss b/app/assets/stylesheets/pages/hierarchy.scss
new file mode 100644
index 00000000000..0812e4cc41e
--- /dev/null
+++ b/app/assets/stylesheets/pages/hierarchy.scss
@@ -0,0 +1,15 @@
+.hierarchy-rounded-arrow-tail {
+ position: absolute;
+ top: 4px;
+ left: 5px;
+ height: calc(100% - 20px);
+}
+
+.hierarchy-icon-wrapper {
+ height: $default-icon-size;
+ width: $default-icon-size;
+}
+
+.hierarchy-rounded-arrow {
+ transform: scale(1, -1) rotate(90deg);
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index cdef843c9b4..fa07d29b536 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -148,12 +148,7 @@
}
.gl-label .gl-label-link:hover {
- text-decoration: none;
color: inherit;
-
- .gl-label-text:last-of-type {
- text-decoration: underline;
- }
}
.btn-link {
@@ -274,16 +269,10 @@
font-weight: $gl-font-weight-normal;
}
- .no-value,
- .btn-default-hover-link,
- .btn-secondary-hover-link {
+ .no-value {
color: $gl-text-color-secondary;
}
- .btn-secondary-hover-link:hover {
- color: $blue-600;
- }
-
.sidebar-collapsed-icon {
display: none;
}
@@ -753,6 +742,26 @@
}
}
+.sidebar-help-wrap {
+ .sidebar-help-state {
+ margin: 16px -20px -20px;
+ padding: 16px 20px;
+ }
+
+ .help-state-toggle-enter-active {
+ transition: all 0.8s ease;
+ }
+
+ .help-state-toggle-leave-active {
+ transition: all 0.5s ease;
+ }
+
+ .help-state-toggle-enter,
+ .help-state-toggle-leave-active {
+ opacity: 0;
+ }
+}
+
.time-tracker {
.sidebar-collapsed-icon {
> .stopwatch-svg {
@@ -770,11 +779,6 @@
}
}
- .help-button,
- .close-help-button {
- cursor: pointer;
- }
-
.compare-meter {
&.over_estimate {
.time-remaining,
@@ -787,31 +791,6 @@
.compare-display-container {
font-size: 13px;
}
-
- .time-tracking-help-state {
- background: $white;
- margin: 16px -20px -20px;
- padding: 16px 20px;
- border-top: 1px solid $border-gray-light;
- border-bottom: 1px solid $border-gray-light;
-
- a:hover {
- color: $btn-white-active;
- }
- }
-
- .help-state-toggle-enter-active {
- transition: all 0.8s ease;
- }
-
- .help-state-toggle-leave-active {
- transition: all 0.5s ease;
- }
-
- .help-state-toggle-enter,
- .help-state-toggle-leave-active {
- opacity: 0;
- }
}
.issuable-todo-btn {
@@ -890,3 +869,13 @@
}
}
}
+
+.icon-overlap-and-shadow {
+ filter:
+ drop-shadow(0 1px 0.5px #fff)
+ drop-shadow(1px 0 0.5px #fff)
+ drop-shadow(0 -1px 0.5px #fff)
+ drop-shadow(-1px 0 0.5px #fff);
+ margin-right: -7px;
+ z-index: 1;
+}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index d77c8a40a79..9bb4c5357e7 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -249,7 +249,9 @@ ul.related-merge-requests > li gl-emoji {
@include media-breakpoint-up(sm) {
width: calc(100% - #{$gutter-collapsed-width});
}
+}
+.limit-container-width {
.issue-sticky-header-text {
max-width: $limited-layout-width;
}
@@ -305,3 +307,32 @@ ul.related-merge-requests > li gl-emoji {
.issuable-header-slide-leave-to {
transform: translateY(-100%);
}
+
+.description.work-items-enabled {
+ ul.task-list {
+ > li.task-list-item {
+ padding-inline-start: 2.25rem;
+
+ .js-add-task {
+ svg {
+ visibility: hidden;
+ }
+
+ &:focus svg {
+ visibility: visible;
+ }
+ }
+
+ > input.task-list-item-checkbox {
+ left: 0.875rem;
+ }
+
+ &:hover,
+ &:focus-within {
+ .js-add-task svg {
+ visibility: visible;
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index fffea301a4f..4a3ec5992a5 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -242,10 +242,14 @@
}
.navless-container {
- padding: 65px 15px; // height of footer + bottom padding of email confirmation link
+ padding: 0 15px 65px; // height of footer + bottom padding of email confirmation link
+ }
+
+ .flash-container {
+ padding-bottom: 65px;
@include media-breakpoint-down(xs) {
- padding: 0 15px 65px;
+ padding-bottom: 0;
}
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 10026e290e8..f95cff012d0 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -2,8 +2,6 @@
* MR -> show: Automerge widget
*
*/
-
-$mr-widget-min-height: 69px;
$tabs-holder-z-index: 250;
.space-children {
@@ -18,12 +16,6 @@ $tabs-holder-z-index: 250;
}
}
-.mr-widget-border-top {
- border-top: 1px solid $border-color;
-}
-
-.mr-widget-margin-left { margin-left: $mr-widget-margin-left; }
-
.media-section {
@include media-breakpoint-down(md) {
align-items: flex-start;
@@ -42,140 +34,9 @@ $tabs-holder-z-index: 250;
}
}
-.mr-widget-section {
- .code-text {
- flex: 1;
- }
-}
-
-.mr-widget-heading {
- position: relative;
- border: 1px solid $border-color;
- border-radius: $border-radius-default;
- background: var(--white, $white);
-
- .gl-skeleton-loader {
- display: block;
- }
-}
-
-.mr-widget-extension {
- border-top: 1px solid $border-color;
- background-color: $gray-50;
-
- &.clickable:hover {
- background-color: $gray-100;
- cursor: pointer;
- }
-}
-
-.mr-widget-workflow {
- margin-top: $gl-padding;
- position: relative;
-
- &::before {
- content: '';
- border-left: 1px solid $gray-100;
- position: absolute;
- left: 28px;
- top: -17px;
- height: 16px;
- }
-}
-
-.mr-section-container {
- border: 1px solid $border-color;
- border-radius: $border-radius-default;
- background: var(--white, $white);
-
- > .mr-widget-border-top:first-of-type {
- border-top: 0;
- }
-}
-
-.mr-widget-body,
-.mr-widget-content,
-.mr-widget-footer {
- padding: $gl-padding;
-}
-
-.mr-widget-info {
- padding-left: $gl-padding;
- padding-right: $gl-padding;
-}
-
.mr-state-widget {
- color: $gl-text-color;
-
- .commit-message-edit {
- border-radius: $border-radius-default;
- }
-
- .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;
- }
-
- .commits-list {
- > li {
- padding: $gl-padding;
-
- @include media-breakpoint-up(md) {
- margin-left: $gl-spacing-scale-7;
- }
- }
- }
-
- .mr-commit-dropdown {
- .dropdown-menu {
- @include media-breakpoint-up(md) {
- width: 150%;
- }
- }
- }
-
- .mr-widget-footer {
- padding: 0;
- }
-
- .mr-report {
- padding: 0;
-
- > .media {
- padding: $gl-padding;
- }
- }
-
- form {
- margin-bottom: 0;
-
- .clearfix {
- margin-bottom: 0;
- }
- }
-
- label {
- margin-bottom: 0;
- }
-
- .btn {
- font-size: $gl-font-size;
- }
-
.accept-merge-holder {
.accept-action {
- display: inline-block;
- float: left;
-
.accept-merge-request {
&.ci-preparing,
&.ci-pending,
@@ -192,227 +53,6 @@ $tabs-holder-z-index: 250;
}
}
}
-
- .ci-widget {
- color: $gl-text-color;
- display: flex;
- align-items: center;
- justify-content: space-between;
-
- @include media-breakpoint-down(xs) {
- flex-wrap: wrap;
- }
-
- .ci-widget-content {
- display: flex;
- align-items: center;
- flex: 1;
- }
- }
-
- .mr-widget-icon {
- font-size: 22px;
- }
-
- .mr-loading-icon {
- margin: 3px 0;
- }
-
- .ci-status-icon svg {
- margin: 3px 0;
- position: relative;
- overflow: visible;
- display: block;
- }
-
- .mr-widget-pipeline-graph {
- .dropdown-menu {
- z-index: $zindex-dropdown-menu;
- }
- }
-
- .normal {
- flex: 1;
- flex-basis: auto;
- }
-
- .capitalize {
- text-transform: capitalize;
- }
-
- .label-branch {
- @include gl-font-monospace;
- font-size: 95%;
- color: $gl-text-color;
- font-weight: normal;
- overflow: hidden;
- word-break: break-all;
- }
-
- .deploy-link,
- .label-branch {
- &.label-truncate {
- // NOTE: This selector targets its children because some of the HTML comes from
- // 'source_branch_link'. Once this external HTML is no longer used, we could
- // simplify this.
- > a,
- > span {
- display: inline-block;
- max-width: 12.5em;
- margin-bottom: -3px;
- white-space: nowrap;
- text-overflow: ellipsis;
- line-height: 14px;
- overflow: hidden;
- }
- }
- }
-
- .mr-widget-body {
- &:not(.mr-widget-body-line-height-1) {
- line-height: 28px;
- }
-
- @include clearfix;
-
- .approve-btn {
- margin-right: 5px;
- }
-
- h4 {
- float: left;
- font-weight: $gl-font-weight-bold;
- font-size: 14px;
- line-height: inherit;
- margin-top: 0;
- margin-bottom: 0;
-
- time {
- font-weight: $gl-font-weight-normal;
- }
- }
-
- .btn-grouped {
- margin-left: 0;
- margin-right: 7px;
- }
-
- label {
- font-weight: $gl-font-weight-normal;
- }
-
- .spacing {
- margin: 0 0 0 10px;
- }
-
- .bold,
- .gl-font-weight-bold {
- font-weight: $gl-font-weight-bold;
- color: $gray-600;
- margin-left: 10px;
- }
-
- .state-label {
- font-weight: $gl-font-weight-bold;
- padding-right: 10px;
- }
-
- .danger {
- color: $red-500;
- }
-
- .spacing,
- .bold,
- .gl-font-weight-bold {
- vertical-align: middle;
- }
-
- .dropdown-menu {
- li a {
- padding: 5px;
- }
-
- .merge-opt-icon {
- line-height: 1.5;
- }
-
- .merge-opt-title {
- margin-left: 8px;
- }
- }
-
- .has-custom-error {
- display: inline-block;
- }
-
- @include media-breakpoint-down(xs) {
- p {
- font-size: 13px;
- }
-
- .btn-grouped {
- float: none;
- margin-right: 0;
- }
-
- .accept-action {
- width: 100%;
- text-align: center;
- }
- }
-
- .commit-message-editor {
- label {
- padding: 0;
- }
- }
-
- &.mr-widget-empty-state {
- line-height: 20px;
- padding: $gl-padding;
-
- .artwork {
-
- @include media-breakpoint-down(md) {
- margin-bottom: $gl-padding;
- }
- }
-
- .text {
- p {
- margin-top: $gl-padding;
- }
-
- .highlight {
- margin: 0 0 $gl-padding;
- font-weight: $gl-font-weight-bold;
- }
- }
- }
-
- &.mr-pipeline-suggest {
- border-radius: $border-radius-default;
- line-height: 20px;
- border: 1px solid $border-color;
-
- .circle-icon-container {
- color: $gl-text-color-quaternary;
- }
- }
- }
-
- .ci-coverage {
- float: right;
- }
-
- .stop-env-container {
- color: $gl-text-color;
- float: right;
-
- a {
- color: $gl-text-color;
- }
- }
}
.mr_source_commit,
@@ -478,72 +118,6 @@ $tabs-holder-z-index: 250;
}
}
-.mr-info-list {
- clear: left;
- position: relative;
- padding-top: 4px;
-
- p {
- margin: 0;
- position: relative;
- padding: 4px 0;
-
- &:last-child {
- padding-bottom: 0;
- }
- }
-
- &.mr-memory-usage {
- p {
- float: left;
- }
-
- .memory-graph-container {
- float: left;
- margin-left: 5px;
- }
- }
-}
-
-.mr-source-target {
- flex-wrap: wrap;
- padding: $gl-padding;
- background: var(--white, $white);
- min-height: $mr-widget-min-height;
-
- @include media-breakpoint-up(md) {
- align-items: center;
- }
-
- .git-merge-container {
- justify-content: space-between;
- flex: 1;
- flex-direction: row;
- align-items: center;
-
- @include media-breakpoint-down(md) {
- flex-direction: column;
- align-items: stretch;
-
- .branch-actions {
- margin-top: 16px;
- }
- }
-
- @include media-breakpoint-up(lg) {
- .branch-actions {
- align-self: center;
- margin-left: $gl-padding;
- white-space: nowrap;
- }
- }
- }
-
- .diverged-commits-count {
- color: $gl-text-color-secondary;
- }
-}
-
.card-new-merge-request {
.card-header {
padding: 5px 10px;
@@ -640,79 +214,14 @@ $tabs-holder-z-index: 250;
}
}
-.mr-version-controls {
- position: relative;
- z-index: $tabs-holder-z-index + 10;
- background: $white;
- color: $gl-text-color;
- margin-top: -1px;
-
- .mr-version-menus-container {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- padding: 16px;
- z-index: 199;
- white-space: nowrap;
-
- .gl-dropdown-toggle {
- width: auto;
- max-width: 170px;
-
- svg {
- top: 10px;
- right: 8px;
- }
- }
- }
-
- .content-block {
- padding: $gl-padding;
- border-bottom: 0;
- }
-
- .mr-version-dropdown,
- .mr-version-compare-dropdown {
- margin: 0 0.5rem;
- }
-
- .dropdown-title {
- color: $gl-text-color;
- }
-
- // Shortening button height by 1px to make compare-versions
- // header 56px and fit into our 8px design grid
- .btn {
- height: 34px;
- }
-
- @include media-breakpoint-up(md) {
- position: -webkit-sticky;
- position: sticky;
- top: calc(#{$header-height} + #{$mr-tabs-height});
-
- .with-system-header & {
- top: calc(#{$header-height} + #{$mr-tabs-height} + #{$system-header-height});
- }
-
- .with-system-header.with-performance-bar & {
- top: calc(#{$header-height} + #{$mr-tabs-height} + #{$system-header-height} + #{$performance-bar-height});
- }
-
- .mr-version-menus-container {
- flex-wrap: nowrap;
- }
-
- .with-performance-bar & {
- top: calc(#{$header-height} + #{$performance-bar-height} + #{$mr-tabs-height});
- }
- }
-}
-
.merge-request-tabs-holder,
.epic-tabs-holder {
top: $header-height;
z-index: $tabs-holder-z-index;
+ margin-left: -$gl-padding;
+ margin-right: -$gl-padding;
+ padding-left: $gl-padding;
+ padding-right: $gl-padding;
background-color: $body-bg;
border-bottom: 1px solid $border-color;
@@ -834,80 +343,10 @@ $tabs-holder-z-index: 250;
}
}
-.mr-memory-usage {
- width: 100%;
-
- p.usage-info-loading .usage-info-load-spinner {
- margin-right: 10px;
- font-size: 16px;
- }
-}
-
.fork-sprite {
margin-right: -5px;
}
-.deploy-heading,
-.merge-train-position-indicator {
- @include media-breakpoint-up(md) {
- padding: $gl-padding-8 $gl-padding;
- }
-
- .media-body {
- min-width: 0;
- font-size: 12px;
- margin-left: 32px;
- }
-
- &:not(:last-child) {
- border-bottom: 1px solid $border-color;
- }
-}
-
-.deploy-body {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
-
- @include media-breakpoint-up(xs) {
- flex-wrap: nowrap;
- white-space: nowrap;
- }
-
- @include media-breakpoint-down(md) {
- flex-direction: column;
- align-items: flex-start;
-
- .deployment-info {
- margin-bottom: $gl-padding;
- }
- }
-
- > *:not(:last-child) {
- margin-right: 0.3em;
- }
-
- svg {
- vertical-align: text-top;
- }
-
- .deployment-info {
- flex: 1;
- white-space: nowrap;
- text-overflow: ellipsis;
- min-width: 100px;
-
- @include media-breakpoint-up(xs) {
- min-width: 0;
- max-width: 100%;
- }
- }
-
- .dropdown-menu {
- width: 400px;
- }
-}
-
// Hack alert: we've rewritten `btn` class in a way that
// we've broken it and it is not possible to use with `btn-link`
// which causes a blank button when it's disabled and hovering
@@ -925,30 +364,6 @@ $tabs-holder-z-index: 250;
}
}
-.ci-widget-container {
- justify-content: space-between;
- flex: 1;
- flex-direction: row;
-
- @include media-breakpoint-down(sm) {
- flex-direction: column;
-
- .stage-cell .stage-container {
- margin-top: 16px;
- }
-
- .dropdown .mini-pipeline-graph-dropdown-menu.dropdown-menu {
- transform: initial;
- }
- }
-
- .coverage {
- font-size: 12px;
- color: $gray-500;
- line-height: initial;
- }
-}
-
.merge-request-details .file-finder-overlay.diff-file-finder {
position: fixed;
z-index: 99999;
@@ -964,47 +379,3 @@ $tabs-holder-z-index: 250;
}
}
}
-
-.diff-file-row.is-active {
- background-color: $gray-50;
-}
-
-.mr-conflict-loader {
- max-width: 334px;
-
- > svg {
- vertical-align: middle;
- }
-}
-
-.mr-ready-to-merge-loader {
- max-width: 418px;
-
- > svg {
- 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;
- }
-}
-
-.mr-widget-extension-icon::before {
- @include gl-content-empty;
- @include gl-absolute;
- @include gl-left-0;
- @include gl-top-0;
- @include gl-opacity-3;
- @include gl-border-solid;
- @include gl-border-4;
- @include gl-rounded-full;
-
- width: 24px;
- height: 24px;
-}
diff --git a/app/assets/stylesheets/pages/pages.scss b/app/assets/stylesheets/pages/pages.scss
index ebaf875ad8f..2de33f20595 100644
--- a/app/assets/stylesheets/pages/pages.scss
+++ b/app/assets/stylesheets/pages/pages.scss
@@ -42,8 +42,6 @@
}
:first-child {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
line-height: $gl-line-height;
}
@@ -52,7 +50,6 @@
}
:last-child {
- border-bottom-right-radius: $border-radius-default;
- border-top-right-radius: $border-radius-default;
+ border-radius: $border-radius-default;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 6b4d7c2520c..ac3d4dad585 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -52,37 +52,6 @@
}
}
-// INFO Scoped to project_feature_setting and settings_panel components in app/assets/javascripts/pages/projects/shared/permissions/components
-.project-repo-select {
- transition: background 2s ease-out;
-
- &:disabled {
- opacity: 0.5;
- pointer-events: none;
- }
-
- .highlight-changes & {
- background: $highlight-changes-color;
- transition: none;
- }
-}
-
-// INFO Scoped to project_feature_setting and settings_panel components in app/assets/javascripts/pages/projects/shared/permissions/components
-.project-feature-controls {
- max-width: 432px;
-}
-
-// INFO Scoped to settings_panel component in app/assets/javascripts/pages/projects/shared/permissions/components
-.project-feature-setting-group {
- .project-feature-controls {
- max-width: 400px;
- }
-}
-
-.nav > .project-buttons {
- margin-top: 0;
-}
-
.save-project-loader {
margin-top: 50px;
margin-bottom: 50px;
@@ -317,121 +286,6 @@
}
}
-.project-stats,
-.project-buttons {
- .scrolling-tabs-container {
- .scrolling-tabs {
- margin-top: $gl-padding-8;
- margin-bottom: $gl-padding-8 - $browser-scrollbar-size;
- padding-bottom: $browser-scrollbar-size;
- flex-wrap: wrap;
- border-bottom: 0;
- }
-
- .fade-left,
- .fade-right {
- top: 0;
- height: calc(100% - #{$browser-scrollbar-size});
-
- svg {
- top: 50%;
- margin-top: -$gl-padding-8;
- }
- }
-
- .nav {
- flex-basis: 100%;
-
- + .nav {
- margin: $gl-padding-8 0;
- }
- }
-
- @include media-breakpoint-down(md) {
- flex-direction: column;
-
- .nav {
- flex-wrap: nowrap;
- }
-
- .nav:first-child {
- margin-right: $gl-padding-8;
- }
- }
- }
-
- .nav {
- > li {
- display: inline-block;
-
- &:not(:last-child) {
- margin-right: $gl-padding;
- }
-
- &.right {
- vertical-align: top;
- margin-top: 0;
-
- @include media-breakpoint-up(lg) {
- float: right;
- }
- }
- }
-
- .stat-text,
- .stat-link {
- padding: $gl-btn-vert-padding 0;
- background-color: transparent;
- font-size: $gl-font-size;
- line-height: $gl-btn-line-height;
- color: $gl-text-color-secondary;
- white-space: pre-wrap;
- }
-
- .stat-link {
- border-bottom: 0;
- color: $black;
-
- &:hover,
- &:focus {
- text-decoration: underline;
- border-bottom: 0;
- }
-
- .project-stat-value {
- color: $gl-text-color;
- }
-
- .icon {
- color: $gl-text-color-secondary;
- }
-
- .add-license-link {
- &,
- .icon {
- color: $blue-600;
- }
- }
- }
-
- .btn {
- margin-bottom: $gl-padding-8;
- padding: $gl-btn-vert-padding $gl-btn-padding;
- line-height: $gl-btn-line-height;
-
- .icon {
- top: 0;
- }
- }
- }
-}
-
-.project-buttons {
- .nav > li:not(:last-child) {
- margin-right: $gl-padding-8;
- }
-}
-
.repository-languages-bar {
height: 8px;
margin-bottom: $gl-padding-8;
@@ -460,22 +314,6 @@ pre.light-well {
border-color: $well-light-border;
}
-.git-empty {
- margin-bottom: 7px;
-
- h5 {
- color: $gl-text-color;
- }
-
- .light-well {
- border-radius: 2px;
-
- color: $well-light-text-color;
- font-size: 13px;
- line-height: 1.6em;
- }
-}
-
/*
* Projects list rendered on dashboard and user page
*/
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 633051918a4..5956368a977 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -130,10 +130,6 @@
border-radius: $border-radius-base;
}
-.empty-variables {
- padding: 20px 0;
-}
-
.warning-title {
color: $gray-900;
}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index c72de0e6f29..1397590cc31 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -7,12 +7,8 @@ body.gl-dark {
--gray-100: #404040;
--gray-600: #bfbfbf;
--gray-900: #fafafa;
- --gray-950: #fff;
--green-100: #0d532a;
- --green-400: #108548;
--green-700: #91d4a8;
- --blue-400: #1f75cb;
- --orange-400: #ab6100;
--indigo-900-alpha-008: rgba(235, 235, 250, 0.08);
--gl-text-color: #fafafa;
--border-color: #4f4f4f;
@@ -314,10 +310,18 @@ h1 {
padding-left: 0.6em;
border-radius: 10rem;
}
+.badge-success {
+ color: #fff;
+ background-color: #2da160;
+}
.badge-info {
color: #fff;
background-color: #428fdc;
}
+.badge-warning {
+ color: #fff;
+ background-color: #c17d10;
+}
.bg-transparent {
background-color: transparent !important;
}
@@ -394,6 +398,34 @@ a.gl-badge.badge-info:active {
0 0 0 1px rgba(51, 51, 51, 0.4), 0 0 0 4px rgba(66, 143, 220, 0.48);
outline: none;
}
+.gl-badge.badge-success {
+ background-color: #0d532a;
+ color: #91d4a8;
+}
+a.gl-badge.badge-success.active,
+a.gl-badge.badge-success:active {
+ color: #ecf4ee;
+ background-color: #24663b;
+}
+a.gl-badge.badge-success:active {
+ box-shadow: inset 0 0 0 1px rgba(51, 51, 51, 0.8),
+ 0 0 0 1px rgba(51, 51, 51, 0.4), 0 0 0 4px rgba(66, 143, 220, 0.48);
+ outline: none;
+}
+.gl-badge.badge-warning {
+ background-color: #703800;
+ color: #e9be74;
+}
+a.gl-badge.badge-warning.active,
+a.gl-badge.badge-warning:active {
+ color: #fdf1dd;
+ background-color: #8f4700;
+}
+a.gl-badge.badge-warning:active {
+ box-shadow: inset 0 0 0 1px rgba(51, 51, 51, 0.8),
+ 0 0 0 1px rgba(51, 51, 51, 0.4), 0 0 0 4px rgba(66, 143, 220, 0.48);
+ outline: none;
+}
.gl-button .gl-badge {
top: 0;
}
@@ -837,7 +869,7 @@ input {
.container-fluid
.navbar-nav
li
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
+ .badge.badge-pill:not(.gl-badge) {
box-shadow: none;
font-weight: 600;
}
@@ -920,44 +952,6 @@ input {
line-height: 18px;
margin: 4px 0 4px 2px;
}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge),
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
- position: inherit;
- font-weight: 400;
- margin-left: -6px;
- font-size: 11px;
- 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:not(.merge-request-badge):not(.version-check-badge).green-badge,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).green-badge {
- background-color: var(--green-400, #108548);
-}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).merge-requests-count,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).merge-requests-count {
- background-color: var(--orange-400, #ab6100);
-}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).todos-count,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).todos-count {
- background-color: var(--blue-400, #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;
@@ -1103,6 +1097,8 @@ input {
}
.nav-sidebar li .nav-item-name {
flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.nav-sidebar li > a,
.nav-sidebar li > .fly-out-top-item-container {
@@ -1335,7 +1331,8 @@ input {
.nav-sidebar-inner-scroll {
height: 100%;
width: 100%;
- overflow: auto;
+ overflow-x: hidden;
+ overflow-y: auto;
}
.nav-sidebar-inner-scroll > div.context-header {
margin-top: 0.25rem;
@@ -1780,10 +1777,16 @@ body.gl-dark {
--purple-800: #cbbbf2;
--purple-900: #e1d8f9;
--purple-950: #f4f0ff;
+ --dark-icon-color-purple-1: #524a68;
+ --dark-icon-color-purple-2: #715bae;
+ --dark-icon-color-purple-3: #9a79f7;
+ --dark-icon-color-orange-1: #665349;
+ --dark-icon-color-orange-2: #b37a5d;
--gl-text-color: #fafafa;
--border-color: #4f4f4f;
--white: #333;
--black: #fff;
+ --black-normal: #fafafa;
--svg-status-bg: #333;
}
.nav-sidebar li a {
@@ -2005,10 +2008,16 @@ body.gl-dark {
--purple-800: #cbbbf2;
--purple-900: #e1d8f9;
--purple-950: #f4f0ff;
+ --dark-icon-color-purple-1: #524a68;
+ --dark-icon-color-purple-2: #715bae;
+ --dark-icon-color-purple-3: #9a79f7;
+ --dark-icon-color-orange-1: #665349;
+ --dark-icon-color-orange-2: #b37a5d;
--gl-text-color: #fafafa;
--border-color: #4f4f4f;
--white: #333;
--black: #fff;
+ --black-normal: #fafafa;
--svg-status-bg: #333;
}
.tab-width-8 {
@@ -2026,18 +2035,9 @@ body.gl-dark {
white-space: nowrap;
width: 1px;
}
-.gl-bg-green-500 {
- background-color: #2da160;
-}
.gl-border-none\! {
border-style: none !important;
}
-.gl-rounded-pill {
- border-radius: 0.75rem;
-}
-.gl-text-white {
- color: #333;
-}
.gl-display-none {
display: none;
}
@@ -2059,9 +2059,8 @@ body.gl-dark {
.gl-pr-2 {
padding-right: 0.25rem;
}
-.gl-py-1 {
- padding-top: 0.125rem;
- padding-bottom: 0.125rem;
+.gl-ml-n2 {
+ margin-left: -0.25rem;
}
.gl-ml-3 {
margin-left: 0.5rem;
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 2f79c86cdc6..0d35c400676 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -295,10 +295,18 @@ h1 {
padding-left: 0.6em;
border-radius: 10rem;
}
+.badge-success {
+ color: #fff;
+ background-color: #108548;
+}
.badge-info {
color: #fff;
background-color: #1f75cb;
}
+.badge-warning {
+ color: #fff;
+ background-color: #ab6100;
+}
.bg-transparent {
background-color: transparent !important;
}
@@ -375,6 +383,34 @@ a.gl-badge.badge-info:active {
0 0 0 1px rgba(255, 255, 255, 0.4), 0 0 0 4px rgba(31, 117, 203, 0.48);
outline: none;
}
+.gl-badge.badge-success {
+ background-color: #c3e6cd;
+ color: #24663b;
+}
+a.gl-badge.badge-success.active,
+a.gl-badge.badge-success:active {
+ color: #0a4020;
+ background-color: #91d4a8;
+}
+a.gl-badge.badge-success:active {
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.8),
+ 0 0 0 1px rgba(255, 255, 255, 0.4), 0 0 0 4px rgba(31, 117, 203, 0.48);
+ outline: none;
+}
+.gl-badge.badge-warning {
+ background-color: #f5d9a8;
+ color: #8f4700;
+}
+a.gl-badge.badge-warning.active,
+a.gl-badge.badge-warning:active {
+ color: #5c2900;
+ background-color: #e9be74;
+}
+a.gl-badge.badge-warning:active {
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.8),
+ 0 0 0 1px rgba(255, 255, 255, 0.4), 0 0 0 4px rgba(31, 117, 203, 0.48);
+ outline: none;
+}
.gl-button .gl-badge {
top: 0;
}
@@ -818,7 +854,7 @@ input {
.container-fluid
.navbar-nav
li
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
+ .badge.badge-pill:not(.gl-badge) {
box-shadow: none;
font-weight: 600;
}
@@ -901,44 +937,6 @@ input {
line-height: 18px;
margin: 4px 0 4px 2px;
}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge),
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge) {
- position: inherit;
- font-weight: 400;
- margin-left: -6px;
- font-size: 11px;
- 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:not(.merge-request-badge):not(.version-check-badge).green-badge,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).green-badge {
- background-color: var(--green-400, #2da160);
-}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).merge-requests-count,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).merge-requests-count {
- background-color: var(--orange-400, #c17d10);
-}
-.title-container
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-badge).todos-count,
-.navbar-nav
- .badge.badge-pill:not(.merge-request-badge):not(.version-check-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;
@@ -1084,6 +1082,8 @@ input {
}
.nav-sidebar li .nav-item-name {
flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.nav-sidebar li > a,
.nav-sidebar li > .fly-out-top-item-container {
@@ -1316,7 +1316,8 @@ input {
.nav-sidebar-inner-scroll {
height: 100%;
width: 100%;
- overflow: auto;
+ overflow-x: hidden;
+ overflow-y: auto;
}
.nav-sidebar-inner-scroll > div.context-header {
margin-top: 0.25rem;
@@ -1697,18 +1698,9 @@ svg.s16 {
white-space: nowrap;
width: 1px;
}
-.gl-bg-green-500 {
- background-color: #108548;
-}
.gl-border-none\! {
border-style: none !important;
}
-.gl-rounded-pill {
- border-radius: 0.75rem;
-}
-.gl-text-white {
- color: #fff;
-}
.gl-display-none {
display: none;
}
@@ -1730,9 +1722,8 @@ svg.s16 {
.gl-pr-2 {
padding-right: 0.25rem;
}
-.gl-py-1 {
- padding-top: 0.125rem;
- padding-bottom: 0.125rem;
+.gl-ml-n2 {
+ margin-left: -0.25rem;
}
.gl-ml-3 {
margin-left: 0.5rem;
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index 3ed257caf60..c5cbe58ec27 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -138,10 +138,10 @@ hr {
margin-right: -15px;
margin-left: -15px;
}
-.col,
-.col-sm-5,
+.col-sm-12,
.col-sm-7,
-.col-sm-12 {
+.col-sm-5,
+.col {
position: relative;
width: 100%;
padding-right: 15px;
@@ -160,12 +160,12 @@ hr {
}
@media (min-width: 576px) {
.col-sm-5 {
- flex: 0 0 41.66667%;
- max-width: 41.66667%;
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
}
.col-sm-7 {
- flex: 0 0 58.33333%;
- max-width: 58.33333%;
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
}
.col-sm-12 {
flex: 0 0 100%;
@@ -725,11 +725,14 @@ svg {
margin-top: 40px;
}
.devise-layout-html body .navless-container {
- padding: 65px 15px;
+ padding: 0 15px 65px;
+}
+.devise-layout-html body .flash-container {
+ padding-bottom: 65px;
}
@media (max-width: 575.98px) {
- .devise-layout-html body .navless-container {
- padding: 0 15px 65px;
+ .devise-layout-html body .flash-container {
+ padding-bottom: 0;
}
}
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index c79816e3579..9db134ffa65 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -93,6 +93,7 @@ $gray-darker: #4f4f4f;
$gray-darkest: #c4c4c4;
$black: #fff;
+$black-normal: $gray-900;
$white: #333;
$white-light: #2b2b2b;
$white-normal: #333;
@@ -187,11 +188,18 @@ body.gl-dark {
--purple-900: #{$purple-900};
--purple-950: #{$purple-950};
+ --dark-icon-color-purple-1: #524a68;
+ --dark-icon-color-purple-2: #715bae;
+ --dark-icon-color-purple-3: #9a79f7;
+ --dark-icon-color-orange-1: #665349;
+ --dark-icon-color-orange-2: #b37a5d;
+
--gl-text-color: #{$gray-900};
--border-color: #{$border-color};
--white: #{$white};
--black: #{$black};
+ --black-normal: #{$black-normal};
--svg-status-bg: #{$white};
@@ -257,3 +265,11 @@ $line-removed-dark: $red-200;
$well-expand-item: $gray-200;
$well-inner-border: $gray-200;
+
+$calendar-activity-colors: (
+ #303030,
+ #333861,
+ #4a5593,
+ #6172c5,
+ #788ff7
+);
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 0e7e52129b4..8a4f9c32f9f 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -200,6 +200,12 @@
}
}
+.gl-xl-ml-3 {
+ @include media-breakpoint-up(lg) {
+ margin-left: $gl-spacing-scale-3;
+ }
+}
+
.gl-mb-n3 {
margin-bottom: -$gl-spacing-scale-3;
}
@@ -247,30 +253,6 @@ $gl-line-height-42: px-to-rem(42px);
max-width: 50%;
}
-// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1490
-.gl-w-grid-size-28 {
- width: $grid-size * 28;
-}
-
-// Will be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2347 is merged
-.gl-min-w-8 {
- min-width: $gl-spacing-scale-8;
-}
-
-// Will be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2347 is merged
-.gl-min-w-10 {
- min-width: $gl-spacing-scale-10;
-}
-
-// Will both be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1526
-.gl-opacity-6 {
- opacity: 0.6;
-}
-
-.gl-opacity-7 {
- opacity: 0.7;
-}
-
/**
Note: ::-webkit-scrollbar is a non-standard rule only
supported by webkit browsers.
@@ -298,14 +280,66 @@ $gl-line-height-42: px-to-rem(42px);
@include gl-focus($gl-border-size-1, $gray-900, true);
}
-// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1637
-.gl-lg-w-25p {
- @include gl-media-breakpoint-up(lg) {
- width: 25%;
- }
-}
-
// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2600
.gl-pr-10 {
padding-right: $gl-spacing-scale-10;
}
+
+/*
+All of the following (up until the "End gitlab-ui#1709" comment) will be moved
+to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
+*/
+.gl-sm-grid-template-columns-2 {
+ @include media-breakpoint-up(sm) {
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+.gl-md-grid-template-columns-2 {
+ @include media-breakpoint-up(md) {
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+.gl-md-grid-template-columns-3 {
+ @include media-breakpoint-up(md) {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+.gl-lg-grid-template-columns-4 {
+ @include media-breakpoint-up(lg) {
+ grid-template-columns: repeat(4, 1fr);
+ }
+}
+
+.gl-gap-6 {
+ gap: $gl-spacing-scale-6;
+}
+
+.gl-max-w-48 {
+ max-width: $gl-spacing-scale-48;
+}
+
+.gl-max-w-75 {
+ max-width: $gl-spacing-scale-75;
+}
+
+.gl-md-pt-11 {
+ @include media-breakpoint-up(md) {
+ padding-top: $gl-spacing-scale-11 !important; // only need !important for now so that it overrides styles from @gitlab/ui which currently take precedence
+ }
+}
+
+.gl-md-mb-6 {
+ @include media-breakpoint-up(md) {
+ margin-bottom: $gl-spacing-scale-6 !important; // only need !important for now so that it overrides styles from @gitlab/ui which currently take precedence
+ }
+}
+
+.gl-md-mb-12 {
+ @include media-breakpoint-up(md) {
+ margin-bottom: $gl-spacing-scale-12 !important; // only need !important for now so that it overrides styles from @gitlab/ui which currently take precedence
+ }
+}
+/* End gitlab-ui#1709 */
diff --git a/app/assets/stylesheets/vendors/tribute.scss b/app/assets/stylesheets/vendors/tribute.scss
deleted file mode 100644
index 65f3d1b6199..00000000000
--- a/app/assets/stylesheets/vendors/tribute.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-.tribute-container {
- background: $white;
- border: 1px solid $gray-100;
- border-radius: $border-radius-base;
- box-shadow: 0 0 5px $issue-boards-card-shadow;
- color: $black;
- margin-top: $gl-padding-12;
- max-height: 200px;
- min-width: 120px;
- overflow-y: auto;
- z-index: 11110 !important;
-
- ul {
- list-style: none;
- margin-bottom: 0;
- padding: $gl-padding-8 1px;
- }
-
- li {
- cursor: pointer;
- padding: $gl-padding-8 $gl-padding;
- white-space: nowrap;
-
- small {
- color: $gray-500;
- }
-
- &.highlight {
- background-color: $gray-darker;
-
- .avatar {
- @include disable-all-animation;
- border: 1px solid $white;
- }
-
- small {
- color: inherit;
- }
- }
- }
-}
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb
index 9d1c68eea89..206a5b11e4b 100644
--- a/app/controllers/abuse_reports_controller.rb
+++ b/app/controllers/abuse_reports_controller.rb
@@ -20,8 +20,10 @@ class AbuseReportsController < ApplicationController
message = _("Thank you for your report. A GitLab administrator will look into it shortly.")
redirect_to root_path, notice: message
- else
+ elsif report_params[:user_id].present?
render :new
+ else
+ redirect_to root_path, alert: _("Cannot create the abuse report. The reported user was invalid. Please try again or contact support.")
end
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 8644d95b96c..1d0930ba73c 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -27,7 +27,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
feature_category :source_code_management, [:repository, :clear_repository_check_states]
feature_category :continuous_integration, [:ci_cd, :reset_registration_token]
- feature_category :service_ping, [:usage_data]
+ feature_category :service_ping, [:usage_data, :service_usage_data]
feature_category :integrations, [:integrations]
feature_category :pages, [:lets_encrypt_terms_of_service]
@@ -52,6 +52,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
@integrations = Integration.find_or_initialize_all_non_project_specific(Integration.for_instance).sort_by(&:title)
end
+ def service_usage_data
+ end
+
def update
perform_update
end
@@ -59,11 +62,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def usage_data
respond_to do |format|
format.html do
- usage_data_json = Gitlab::Json.pretty_generate(Gitlab::UsageData.data)
+ usage_data_json = Gitlab::Json.pretty_generate(Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true))
render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json')
end
- format.json { render json: Gitlab::UsageData.to_json }
+ format.json { render json: Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true).to_json }
end
end
diff --git a/app/controllers/admin/instance_review_controller.rb b/app/controllers/admin/instance_review_controller.rb
index 5567ffbdc84..1ce6e66c6de 100644
--- a/app/controllers/admin/instance_review_controller.rb
+++ b/app/controllers/admin/instance_review_controller.rb
@@ -16,7 +16,7 @@ class Admin::InstanceReviewController < Admin::ApplicationController
}
if Gitlab::CurrentSettings.usage_ping_enabled?
- data = ::Gitlab::UsageData.data
+ data = Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true)
counts = data[:counts]
result[:instance_review].merge!(
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 16657612050..f7f78ab3229 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -34,7 +34,7 @@ class Admin::RunnersController < Admin::ApplicationController
end
def destroy
- @runner.destroy
+ Ci::UnregisterRunnerService.new(@runner).execute
redirect_to admin_runners_path, status: :found
end
@@ -85,7 +85,11 @@ class Admin::RunnersController < Admin::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def assign_builds_and_projects
- @builds = runner.builds.order('id DESC').preload_project_and_pipeline_project.first(30)
+ @builds = runner
+ .builds
+ .order_id_desc
+ .preload_project_and_pipeline_project.first(30)
+
@projects =
if params[:search].present?
::Project.search(params[:search])
@@ -93,12 +97,10 @@ class Admin::RunnersController < Admin::ApplicationController
Project.all
end
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do
- @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
- @projects = @projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
- @projects = @projects.inc_routes
- @projects = @projects.page(params[:page]).per(30).without_count
- end
+ runner_projects_ids = runner.runner_projects.pluck(:project_id)
+ @projects = @projects.where.not(id: runner_projects_ids) if runner_projects_ids.any?
+ @projects = @projects.inc_routes
+ @projects = @projects.page(params[:page]).per(30).without_count
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index b40e2affcee..c1fa104ffda 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -16,7 +16,7 @@ class Admin::UsersController < Admin::ApplicationController
return redirect_to admin_cohorts_path if params[:tab] == 'cohorts'
@users = User.filter_items(params[:filter]).order_name_asc
- @users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present?
+ @users = @users.search(params[:search_query], with_private_emails: true) if params[:search_query].present?
@users = users_with_included_associations(@users)
@users = @users.sort_by_attribute(@sort = params[:sort])
@users = @users.page(params[:page])
@@ -370,7 +370,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def check_ban_user_feature_flag
- access_denied! unless Feature.enabled?(:ban_user_feature_flag)
+ access_denied! unless Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
end
def log_impersonation_event
diff --git a/app/controllers/clusters/base_controller.rb b/app/controllers/clusters/base_controller.rb
index b1ffdf00b87..f88d381b3bf 100644
--- a/app/controllers/clusters/base_controller.rb
+++ b/app/controllers/clusters/base_controller.rb
@@ -4,7 +4,7 @@ class Clusters::BaseController < ApplicationController
include RoutableActions
skip_before_action :authenticate_user!
- before_action :authorize_read_cluster!
+ before_action :authorize_admin_cluster!, except: [:show, :index, :new, :authorize_aws_role, :update]
helper_method :clusterable
@@ -18,11 +18,11 @@ class Clusters::BaseController < ApplicationController
end
def authorize_update_cluster!
- access_denied! unless can?(current_user, :update_cluster, cluster)
+ access_denied! unless can?(current_user, :update_cluster, clusterable)
end
def authorize_admin_cluster!
- access_denied! unless can?(current_user, :admin_cluster, cluster)
+ access_denied! unless can?(current_user, :admin_cluster, clusterable)
end
def authorize_read_cluster!
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 15a261f572a..c12ceca9c3b 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -10,9 +10,9 @@ class Clusters::ClustersController < Clusters::BaseController
before_action :validate_gcp_token, only: [:new]
before_action :gcp_cluster, only: [:new]
before_action :user_cluster, only: [:new]
+ before_action :authorize_read_cluster!, only: [:show, :index]
before_action :authorize_create_cluster!, only: [:new, :authorize_aws_role]
before_action :authorize_update_cluster!, only: [:update]
- before_action :authorize_admin_cluster!, only: [:destroy, :clear_cache]
before_action :update_applications_status, only: [:cluster_status]
helper_method :token_in_session
diff --git a/app/controllers/concerns/bizible_csp.rb b/app/controllers/concerns/bizible_csp.rb
new file mode 100644
index 00000000000..521f3127759
--- /dev/null
+++ b/app/controllers/concerns/bizible_csp.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BizibleCSP
+ extend ActiveSupport::Concern
+
+ included do
+ content_security_policy do |policy|
+ next unless helpers.bizible_enabled? || policy.directives.present?
+
+ default_script_src = policy.directives['script-src'] || policy.directives['default-src']
+ script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.bizible.com/scripts/bizible.js']
+ policy.script_src(*script_src_values)
+ end
+ end
+end
diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb
index f6e98c25b72..1f788860c8f 100644
--- a/app/controllers/concerns/integrations/actions.rb
+++ b/app/controllers/concerns/integrations/actions.rb
@@ -8,9 +8,6 @@ module Integrations::Actions
include IntegrationsHelper
before_action :integration, only: [:edit, :update, :overrides, :test]
- before_action do
- push_frontend_feature_flag(:vue_integration_form, current_user, default_enabled: :yaml)
- end
urgency :low, [:test]
end
diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb
index 945540d1f8c..80acb369cb2 100644
--- a/app/controllers/concerns/integrations/params.rb
+++ b/app/controllers/concerns/integrations/params.rb
@@ -30,6 +30,7 @@ module Integrations
:datadog_site,
:datadog_env,
:datadog_service,
+ :datadog_tags,
:default_irc_uri,
:device,
:disable_diffs,
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index bac9732018c..eae087bca4d 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -17,7 +17,10 @@ module IssuableActions
def show
respond_to do |format|
format.html do
- @show_crm_contacts = issuable.is_a?(Issue) && can?(current_user, :read_crm_contact, issuable.project.group) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @show_crm_contacts = issuable.is_a?(Issue) && # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ can?(current_user, :read_crm_contact, issuable.project.group) &&
+ CustomerRelations::Contact.exists_for_group?(issuable.project.group)
+
@issuable_sidebar = serializer.represent(issuable, serializer: 'sidebar') # rubocop:disable Gitlab/ModuleWithInstanceVariables
render 'show'
end
diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb
index 85bb73463db..685c93fc2a2 100644
--- a/app/controllers/concerns/multiple_boards_actions.rb
+++ b/app/controllers/concerns/multiple_boards_actions.rb
@@ -14,7 +14,7 @@ module MultipleBoardsActions
end
def recent
- recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(4)
+ recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(Board::RECENT_BOARDS_SIZE)
recent_boards = recent_visits.map(&:board)
render json: serialize_as_json(recent_boards)
diff --git a/app/controllers/concerns/planning_hierarchy.rb b/app/controllers/concerns/planning_hierarchy.rb
new file mode 100644
index 00000000000..5df838bc183
--- /dev/null
+++ b/app/controllers/concerns/planning_hierarchy.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module PlanningHierarchy
+ extend ActiveSupport::Concern
+
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def planning_hierarchy
+ return access_denied! unless can?(current_user, :read_planning_hierarchy, @project)
+
+ render 'shared/planning_hierarchy'
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+end
+
+PlanningHierarchy.prepend_mod_with('PlanningHierarchy')
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
index f489de42864..e1bfe92f61b 100644
--- a/app/controllers/concerns/uploads_actions.rb
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -142,6 +142,14 @@ module UploadsActions
uploader && uploader.exists? && uploader.embeddable?
end
+ def bypass_auth_checks_on_uploads?
+ if ::Feature.enabled?(:enforce_auth_checks_on_uploads, default_enabled: :yaml)
+ false
+ else
+ action_name == 'show' && embeddable?
+ end
+ end
+
def find_model
nil
end
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index d861ef646f8..0074bcac360 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -35,7 +35,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def starred
- @projects = load_projects(params.merge(starred: true))
+ @projects = load_projects(params.merge(starred: true, not_aimed_for_deletion: true))
.includes(:forked_from_project, :topics)
@groups = []
@@ -54,7 +54,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
private
def projects
- @projects ||= load_projects(params.merge(non_public: true))
+ @projects ||= load_projects(params.merge(non_public: true, not_aimed_for_deletion: true))
end
def render_projects
@@ -65,8 +65,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def load_projects(finder_params)
- @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true }, current_user: current_user).execute
- @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true }, current_user: current_user).execute
+ @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute
+ @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute
finder_params[:use_cte] = true if use_cte_for_finder?
finder_params[:without_deleted] = true
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 2ecd17db487..f94da77609f 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -20,6 +20,10 @@ class DashboardController < Dashboard::ApplicationController
urgency :low, [:merge_requests]
+ before_action only: [:merge_requests] do
+ push_frontend_feature_flag(:mr_attention_requests, default_enabled: :yaml)
+ end
+
def activity
respond_to do |format|
format.html
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 14dd2ae5691..f8a6d9f808e 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -92,7 +92,12 @@ class Explore::ProjectsController < Explore::ApplicationController
def load_projects
load_project_counts
- projects = ProjectsFinder.new(current_user: current_user, params: params.merge(minimum_search_length: MIN_SEARCH_LENGTH)).execute
+ finder_params = {
+ minimum_search_length: MIN_SEARCH_LENGTH,
+ not_aimed_for_deletion: true
+ }
+
+ projects = ProjectsFinder.new(current_user: current_user, params: params.merge(finder_params)).execute
projects = preload_associations(projects)
projects = projects.page(params[:page]).without_count
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 689ca32f6d9..ef229a2abec 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -31,6 +31,7 @@ class GraphqlController < ApplicationController
before_action :authorize_access_api!
before_action :set_user_last_activity
before_action :track_vs_code_usage
+ before_action :track_jetbrains_usage
before_action :disable_query_limiting
before_action :limit_query_size
@@ -137,6 +138,11 @@ class GraphqlController < ApplicationController
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
end
+ def track_jetbrains_usage
+ Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter
+ .track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
+ end
+
def execute_multiplex
GitlabSchema.multiplex(multiplex_queries, context: context)
end
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 6de77450a46..6fac6fcf426 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -11,8 +11,8 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
- e.use { }
- e.try { }
+ e.control { }
+ e.candidate { }
end.run
end
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
index 00839583ecc..8513979c53b 100644
--- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -120,7 +120,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
end
def manifest_file_name
- @manifest_file_name ||= "#{image}:#{tag}.json"
+ @manifest_file_name ||= Gitlab::Utils.check_path_traversal!("#{image}:#{tag}.json")
end
def group
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index f602d02a165..b194aeff80d 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -9,10 +9,8 @@ class Groups::RunnersController < Groups::ApplicationController
feature_category :runner
def index
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do
- finder = Ci::RunnersFinder.new(current_user: current_user, params: { group: @group })
- @group_runners_limited_count = finder.execute.except(:limit, :offset).page.total_count_with_limit(:all, limit: 1000)
- end
+ finder = Ci::RunnersFinder.new(current_user: current_user, params: { group: @group })
+ @group_runners_limited_count = finder.execute.except(:limit, :offset).page.total_count_with_limit(:all, limit: 1000)
end
def runner_list_group_view_vue_ui_enabled
@@ -37,7 +35,7 @@ class Groups::RunnersController < Groups::ApplicationController
if @runner.belongs_to_more_than_one_project?
redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), status: :found, alert: _('Runner was not deleted because it is assigned to multiple projects.')
else
- @runner.destroy
+ Ci::UnregisterRunnerService.new(@runner).execute
redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), status: :found
end
@@ -62,11 +60,9 @@ class Groups::RunnersController < Groups::ApplicationController
private
def runner
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do
- @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute
- .except(:limit, :offset)
- .find(params[:id])
- end
+ @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute
+ .except(:limit, :offset)
+ .find(params[:id])
end
def runner_params
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index e125385f841..a290ef9b5e7 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -23,11 +23,6 @@ module Groups
@group_runners = runners_finder.execute.page(params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
@sort = runners_finder.sort_key
-
- # Allow sql generated by the two relations above, @all_group_runners and @group_runners
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do
- render
- end
end
def update
diff --git a/app/controllers/groups/uploads_controller.rb b/app/controllers/groups/uploads_controller.rb
index 49249f87d31..387f7be56cd 100644
--- a/app/controllers/groups/uploads_controller.rb
+++ b/app/controllers/groups/uploads_controller.rb
@@ -4,7 +4,7 @@ class Groups::UploadsController < Groups::ApplicationController
include UploadsActions
include WorkhorseRequest
- skip_before_action :group, if: -> { action_name == 'show' && embeddable? }
+ skip_before_action :group, if: -> { bypass_auth_checks_on_uploads? }
before_action :authorize_upload_file!, only: [:create, :authorize]
before_action :verify_workhorse_api!, only: [:authorize]
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 4acbb0482f3..12af76efe0d 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -38,6 +38,8 @@ class GroupsController < Groups::ApplicationController
before_action :check_export_rate_limit!, only: [:export, :download_export]
+ before_action :track_experiment_event, only: [:new]
+
helper_method :captcha_required?
skip_cross_project_access_check :index, :new, :create, :edit, :update,
@@ -207,6 +209,20 @@ class GroupsController < Groups::ApplicationController
end
end
+ def issues
+ return super if !html_request? || Feature.disabled?(:vue_issues_list, group, default_enabled: :yaml)
+
+ @has_issues = IssuesFinder.new(current_user, group_id: group.id).execute
+ .non_archived
+ .exists?
+
+ @has_projects = group_projects.exists?
+
+ respond_to do |format|
+ format.html
+ end
+ end
+
protected
def render_show_html
@@ -378,6 +394,12 @@ class GroupsController < Groups::ApplicationController
def captcha_required?
captcha_enabled? && !params[:parent_id]
end
+
+ def track_experiment_event
+ return if params[:parent_id]
+
+ experiment(:require_verification_for_namespace_creation, user: current_user).track(:start_create_group)
+ end
end
GroupsController.prepend_mod_with('GroupsController')
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index 8de270e9d25..9b8c480e529 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -38,7 +38,7 @@ class Import::GitlabProjectsController < Import::BaseController
def project_params
params.permit(
- :path, :namespace_id, :file
+ :name, :path, :namespace_id, :file
)
end
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index d3dea2ce159..a0c307a0a03 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -7,7 +7,6 @@ class MetricsController < ActionController::Base
def index
response = if Gitlab::Metrics.prometheus_metrics_enabled?
- Gitlab::Metrics::RailsSlis.initialize_request_slis_if_needed!
metrics_service.metrics_text
else
help_page = help_page_url('administration/monitoring/prometheus/gitlab_metrics',
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index ddf70c1892a..d1c409d071e 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -3,6 +3,7 @@
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
+ include Gitlab::Utils::StrongMemoize
before_action :verify_confirmed_email!, :verify_confidential_application!
@@ -27,6 +28,56 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
private
+ def pre_auth_params
+ # Cannot be achieved with a before_action hook, due to the execution order.
+ downgrade_scopes! if action_name == 'new'
+
+ super
+ end
+
+ # limit scopes when signing in with GitLab
+ def downgrade_scopes!
+ return unless Feature.enabled?(:omniauth_login_minimal_scopes, current_user,
+ default_enabled: :yaml)
+
+ auth_type = params.delete('gl_auth_type')
+ return unless auth_type == 'login'
+
+ ensure_read_user_scope!
+
+ params['scope'] = Gitlab::Auth::READ_USER_SCOPE.to_s if application_has_read_user_scope?
+ end
+
+ # Configure the application to support read_user scope, if it already
+ # supports scopes with greater levels of privileges.
+ def ensure_read_user_scope!
+ return if application_has_read_user_scope?
+ return unless application_has_api_scope?
+
+ add_read_user_scope!
+ end
+
+ def add_read_user_scope!
+ return unless doorkeeper_application
+
+ scopes = doorkeeper_application.scopes
+ scopes.add(Gitlab::Auth::READ_USER_SCOPE)
+ doorkeeper_application.scopes = scopes
+ doorkeeper_application.save!
+ end
+
+ def doorkeeper_application
+ strong_memoize(:doorkeeper_application) { ::Doorkeeper::OAuth::Client.find(params['client_id'])&.application }
+ end
+
+ def application_has_read_user_scope?
+ doorkeeper_application&.includes_scope?(Gitlab::Auth::READ_USER_SCOPE)
+ end
+
+ def application_has_api_scope?
+ doorkeeper_application&.includes_scope?(*::Gitlab::Auth::API_SCOPES)
+ end
+
# Confidential apps require the client_secret to be sent with the request.
# Doorkeeper allows implicit grant flow requests (response_type=token) to
# work without client_secret regardless of the confidential setting.
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index cf432cfb429..f678e19d05d 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -2,8 +2,9 @@
class Projects::AutocompleteSourcesController < Projects::ApplicationController
before_action :authorize_read_milestone!, only: :milestones
+ before_action :authorize_read_crm_contact!, only: :contacts
- feature_category :team_planning, [:issues, :labels, :milestones, :commands]
+ feature_category :team_planning, [:issues, :labels, :milestones, :commands, :contacts]
feature_category :code_review, [:merge_requests]
feature_category :users, [:members]
feature_category :snippets, [:snippets]
@@ -38,6 +39,10 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
render json: autocomplete_service.snippets
end
+ def contacts
+ render json: autocomplete_service.contacts
+ end
+
private
def autocomplete_service
@@ -49,6 +54,10 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
.new(project, current_user)
.execute(params[:type], params[:type_id])
end
+
+ def authorize_read_crm_contact!
+ render_404 unless can?(current_user, :read_crm_contact, project.root_ancestor)
+ end
end
Projects::AutocompleteSourcesController.prepend_mod_with('Projects::AutocompleteSourcesController')
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index 8023e51b552..42bd87e1c01 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -8,6 +8,7 @@ class Projects::BadgesController < Projects::ApplicationController
feature_category :continuous_integration, [:index, :pipeline]
feature_category :code_testing, [:coverage]
+ feature_category :release_orchestration, [:release]
def pipeline
pipeline_status = Gitlab::Ci::Badge::Pipeline::Status
@@ -34,6 +35,17 @@ class Projects::BadgesController < Projects::ApplicationController
render_badge coverage_report
end
+ def release
+ latest_release = Gitlab::Ci::Badge::Release::LatestRelease
+ .new(project, current_user, opts: {
+ key_text: params[:key_text],
+ key_width: params[:key_width],
+ order_by: params[:order_by]
+ })
+
+ render_badge latest_release
+ end
+
private
def badge_layout
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index adaa47b48cb..0170cff6160 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -11,8 +11,8 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
- e.use { }
- e.try { }
+ e.control { }
+ e.candidate { }
end.run
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 63ac5f97420..dad73c37fea 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -131,11 +131,28 @@ class Projects::BranchesController < Projects::ApplicationController
private
def sort_value_for_mode
- return params[:sort] if params[:sort].present?
+ custom_sort || default_sort
+ end
+
+ def custom_sort
+ sort = params[:sort].presence
+
+ unless sort.in?(supported_sort_options)
+ flash.now[:alert] = _("Unsupported sort value.")
+ sort = nil
+ end
+ sort
+ end
+
+ def default_sort
'stale' == @mode ? sort_value_oldest_updated : sort_value_recently_updated
end
+ def supported_sort_options
+ [nil, sort_value_name, sort_value_oldest_updated, sort_value_recently_updated]
+ end
+
# It can be expensive to calculate the diverging counts for each
# branch. Normally the frontend should be specifying a set of branch
# names, but prior to
diff --git a/app/controllers/projects/cluster_agents_controller.rb b/app/controllers/projects/cluster_agents_controller.rb
index 404d3907128..84bb01ee266 100644
--- a/app/controllers/projects/cluster_agents_controller.rb
+++ b/app/controllers/projects/cluster_agents_controller.rb
@@ -16,7 +16,7 @@ class Projects::ClusterAgentsController < Projects::ApplicationController
private
def authorize_can_read_cluster_agent!
- return if can?(current_user, :admin_cluster, project)
+ return if can?(current_user, :read_cluster, project)
access_denied!
end
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index 8f45fa1cb9f..440375bf3c9 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -6,6 +6,7 @@ class Projects::ClustersController < Clusters::ClustersController
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
+ push_frontend_feature_flag(:show_gitlab_agent_feedback, type: :ops, default_enabled: :yaml)
end
layout 'project'
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 62935e133c5..0ce0b8b8895 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -92,6 +92,8 @@ class Projects::CommitController < Projects::ApplicationController
end
def branches
+ return git_not_found! unless commit
+
# branch_names_contains/tag_names_contains can take a long time when there are thousands of
# branches/tags - each `git branch --contains xxx` request can consume a cpu core.
# so only do the query when there are a manageable number of branches/tags
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 1ca35903703..82a13b60b13 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -67,11 +67,11 @@ class Projects::CommitsController < Projects::ApplicationController
def set_commits
render_404 unless @path.empty? || request.format == :atom || @repository.blob_at(@commit.id, @path) || @repository.tree(@commit.id, @path).entries.present?
- limit = params[:limit].to_i
+ limit = permitted_params[:limit].to_i
@limit = limit > 0 ? limit : COMMITS_DEFAULT_LIMIT # limit can only ever be a positive number
- @offset = (params[:offset] || 0).to_i
- search = params[:search]
- author = params[:author]
+ @offset = (permitted_params[:offset] || 0).to_i
+ search = permitted_params[:search]
+ author = permitted_params[:author]
@commits =
if search.present?
@@ -87,4 +87,8 @@ class Projects::CommitsController < Projects::ApplicationController
@commits = @commits.with_latest_pipeline(@ref)
@commits = set_commits_for_rendering(@commits)
end
+
+ def permitted_params
+ params.permit(:limit, :offset, :search, :author)
+ end
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 07f7c1cf7de..243cc7a346c 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -28,6 +28,7 @@ class Projects::CompareController < Projects::ApplicationController
COMMIT_DIFFS_PER_PAGE = 20
def index
+ compare_params
end
def show
@@ -44,9 +45,9 @@ class Projects::CompareController < Projects::ApplicationController
def create
from_to_vars = {
- from: params[:from].presence,
- to: params[:to].presence,
- from_project_id: params[:from_project_id].presence
+ from: compare_params[:from].presence,
+ to: compare_params[:to].presence,
+ from_project_id: compare_params[:from_project_id].presence
}
if from_to_vars[:from].blank? || from_to_vars[:to].blank?
@@ -87,10 +88,10 @@ class Projects::CompareController < Projects::ApplicationController
# target == start_ref == from
def target_project
strong_memoize(:target_project) do
- next source_project unless params.key?(:from_project_id)
- next source_project if params[:from_project_id].to_i == source_project.id
+ next source_project unless compare_params.key?(:from_project_id)
+ next source_project if compare_params[:from_project_id].to_i == source_project.id
- target_project = target_projects(source_project).find_by_id(params[:from_project_id])
+ target_project = target_projects(source_project).find_by_id(compare_params[:from_project_id])
# Just ignore the field if it points at a non-existent or hidden project
next source_project unless target_project && can?(current_user, :download_code, target_project)
@@ -111,13 +112,13 @@ class Projects::CompareController < Projects::ApplicationController
end
def start_ref
- @start_ref ||= Addressable::URI.unescape(params[:from])
+ @start_ref ||= Addressable::URI.unescape(compare_params[:from])
end
def head_ref
return @ref if defined?(@ref)
- @ref = @head_ref = Addressable::URI.unescape(params[:to])
+ @ref = @head_ref = Addressable::URI.unescape(compare_params[:to])
end
def define_commits
@@ -146,4 +147,8 @@ class Projects::CompareController < Projects::ApplicationController
.find_by(source_project: source_project, source_branch: head_ref, target_branch: start_ref)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def compare_params
+ @compare_params ||= params.permit(:from, :to, :from_project_id)
+ end
end
diff --git a/app/controllers/projects/design_management/designs_controller.rb b/app/controllers/projects/design_management/designs_controller.rb
index 550d8578396..2aa48249c0e 100644
--- a/app/controllers/projects/design_management/designs_controller.rb
+++ b/app/controllers/projects/design_management/designs_controller.rb
@@ -4,6 +4,7 @@ class Projects::DesignManagement::DesignsController < Projects::ApplicationContr
before_action :authorize_read_design!
feature_category :design_management
+ urgency :low
private
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index ba83f8dad35..475c41eec9c 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -22,14 +22,14 @@ class Projects::ForksController < Projects::ApplicationController
end
def index
- @sort = params[:sort]
+ @sort = forks_params[:sort]
@total_forks_count = project.forks.size
@public_forks_count = project.forks.public_only.size
@private_forks_count = @total_forks_count - project.forks.public_and_internal_only.size
@internal_forks_count = @total_forks_count - @public_forks_count - @private_forks_count
- @forks = load_forks.page(params[:page])
+ @forks = load_forks.page(forks_params[:page])
prepare_projects_for_rendering(@forks)
@@ -98,7 +98,7 @@ class Projects::ForksController < Projects::ApplicationController
def load_forks
forks = ForkProjectsFinder.new(
project,
- params: params.merge(search: params[:filter_projects]),
+ params: forks_params.merge(search: forks_params[:filter_projects]),
current_user: current_user
).execute
@@ -117,6 +117,10 @@ class Projects::ForksController < Projects::ApplicationController
end
end
+ def forks_params
+ params.permit(:filter_projects, :sort, :page)
+ end
+
def fork_params
params.permit(:path, :name, :description, :visibility).tap do |param|
param[:namespace] = fork_namespace
diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb
index 4e7fd73e378..1941eb8a5f9 100644
--- a/app/controllers/projects/google_cloud/deployments_controller.rb
+++ b/app/controllers/projects/google_cloud/deployments_controller.rb
@@ -4,10 +4,63 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base
before_action :validate_gcp_token!
def cloud_run
- render json: "Placeholder"
+ params = { token_in_session: token_in_session }
+ enable_cloud_run_response = GoogleCloud::EnableCloudRunService
+ .new(project, current_user, params).execute
+
+ if enable_cloud_run_response[:status] == :error
+ flash[:error] = enable_cloud_run_response[:message]
+ redirect_to project_google_cloud_index_path(project)
+ else
+ params = { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN }
+ generate_pipeline_response = GoogleCloud::GeneratePipelineService
+ .new(project, current_user, params).execute
+
+ if generate_pipeline_response[:status] == :error
+ flash[:error] = 'Failed to generate pipeline'
+ redirect_to project_google_cloud_index_path(project)
+ else
+ cloud_run_mr_params = cloud_run_mr_params(generate_pipeline_response[:branch_name])
+ redirect_to project_new_merge_request_path(project, merge_request: cloud_run_mr_params)
+ end
+ end
+ rescue Google::Apis::ClientError => error
+ handle_gcp_error(error, project)
end
def cloud_storage
render json: "Placeholder"
end
+
+ private
+
+ def cloud_run_mr_params(branch_name)
+ {
+ title: cloud_run_mr_title,
+ description: cloud_run_mr_description(branch_name),
+ source_project_id: project.id,
+ target_project_id: project.id,
+ source_branch: branch_name,
+ target_branch: project.default_branch
+ }
+ end
+
+ def cloud_run_mr_title
+ 'Enable deployments to Cloud Run'
+ end
+
+ def cloud_run_mr_description(branch_name)
+ <<-TEXT
+This merge request includes a Cloud Run deployment job in the pipeline definition (.gitlab-ci.yml).
+
+The `deploy-to-cloud-run` job:
+* Requires the following environment variables
+ * `GCP_PROJECT_ID`
+ * `GCP_SERVICE_ACCOUNT_KEY`
+* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library
+
+This pipeline definition has been committed to the branch `#{branch_name}`.
+You may modify the pipeline definition further or accept the changes as-is if suitable.
+ TEXT
+ end
end
diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb
index 1fa8ae60376..206a8c7e391 100644
--- a/app/controllers/projects/google_cloud_controller.rb
+++ b/app/controllers/projects/google_cloud_controller.rb
@@ -6,6 +6,8 @@ class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController
screen: 'home',
serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project,
createServiceAccountUrl: project_google_cloud_service_accounts_path(project),
+ enableCloudRunUrl: project_google_cloud_deployments_cloud_run_path(project),
+ enableCloudStorageUrl: project_google_cloud_deployments_cloud_storage_path(project),
emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg')
}.to_json
end
diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb
index 27893fe510d..6bc81381d92 100644
--- a/app/controllers/projects/group_links_controller.rb
+++ b/app/controllers/projects/group_links_controller.rb
@@ -28,7 +28,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
if group_link.expires?
render json: {
- expires_in: helpers.distance_of_time_in_words_to_now(group_link.expires_at),
+ expires_in: helpers.time_ago_with_tooltip(group_link.expires_at),
expires_soon: group_link.expires_soon?
}
else
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 785fbdaa611..1b98810b09b 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -10,7 +10,7 @@ class Projects::IssuesController < Projects::ApplicationController
include RecordUserLastActivity
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
- SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
+ SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[calendar service_desk].freeze
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
@@ -42,18 +42,20 @@ class Projects::IssuesController < Projects::ApplicationController
if: -> { Feature.disabled?('rate_limited_service_issues_create', project, default_enabled: :yaml) }
before_action do
- push_frontend_feature_flag(:tribute_autocomplete, @project)
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
push_frontend_feature_flag(:vue_issues_list, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
+ push_frontend_feature_flag(:contacts_autocomplete, project&.group, default_enabled: :yaml)
+ push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml)
end
before_action only: :show do
- push_frontend_feature_flag(:real_time_issue_sidebar, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:real_time_issue_sidebar, project, default_enabled: :yaml)
push_frontend_feature_flag(:confidential_notes, project&.group, default_enabled: :yaml)
- push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:fix_comment_scroll, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:issue_assignees_widget, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:paginated_issue_discussions, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:fix_comment_scroll, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:work_items, project, default_enabled: :yaml)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
@@ -71,11 +73,14 @@ class Projects::IssuesController < Projects::ApplicationController
]
feature_category :service_desk, [:service_desk]
+ urgency :low, [:service_desk]
feature_category :importers, [:import_csv, :export_csv]
attr_accessor :vulnerability_id
def index
+ set_issuables_index if !html_request? || Feature.disabled?(:vue_issues_list, project&.group, default_enabled: :yaml)
+
@issues = @issuables
respond_to do |format|
@@ -317,7 +322,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def reorder_params
- params.permit(:move_before_id, :move_after_id, :group_full_path)
+ params.permit(:move_before_id, :move_after_id)
end
def store_uri
diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb
index 645720a0889..686d2c1dc1f 100644
--- a/app/controllers/projects/merge_requests/drafts_controller.rb
+++ b/app/controllers/projects/merge_requests/drafts_controller.rb
@@ -92,7 +92,8 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli
:commit_id,
:note,
:position,
- :resolve_discussion
+ :resolve_discussion,
+ :line_code
).tap do |h|
# Old FE version will still be sending `draft_note[commit_id]` as 'undefined'.
# That can result to having a note linked to a commit with 'undefined' ID
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index f936aeb0084..6445f920db5 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -30,24 +30,31 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :set_issuables_index, only: [:index]
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
+ before_action only: [:index, :show] do
+ push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml)
+ end
+
before_action only: [:show] do
push_frontend_feature_flag(:file_identifier_hash)
- push_frontend_feature_flag(:merge_request_widget_graphql, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:default_merge_ref_for_diffs, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:core_security_mr_widget_counts, @project)
- push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:merge_request_widget_graphql, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:default_merge_ref_for_diffs, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:core_security_mr_widget_counts, project)
+ push_frontend_feature_flag(:paginated_notes, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:confidential_notes, 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(:restructured_mr_widget, project, default_enabled: :yaml)
- push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
- push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml)
- push_frontend_feature_flag(:refactor_mr_widgets_extensions, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:rebase_without_ci_ui, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:refactor_mr_widgets_extensions, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:rebase_without_ci_ui, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml)
# Usage data feature flags
- push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:users_expanding_widgets_usage_data, project, default_enabled: :yaml)
push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)
- push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:usage_data_diff_searches, project, default_enabled: :yaml)
+ end
+
+ before_action do
+ push_frontend_feature_flag(:permit_all_shared_groups_for_approval, @project, default_enabled: :yaml)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
@@ -100,10 +107,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
# rubocop:disable Metrics/AbcSize
def show
close_merge_request_if_no_source_project
-
- if Feature.disabled?(:check_mergeability_async_in_widget, @project, default_enabled: :yaml)
- @merge_request.check_mergeability(async: true)
- end
+ @merge_request.check_mergeability(async: true)
respond_to do |format|
format.html do
@@ -504,6 +508,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
.can_push_to_branch?(@merge_request.source_branch)
access_denied! unless access_check
+
+ access_denied! unless merge_request.permits_force_push?
end
def merge_access_check
diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb
index c02a0a56e03..2fe353b7acb 100644
--- a/app/controllers/projects/packages/infrastructure_registry_controller.rb
+++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb
@@ -9,11 +9,7 @@ module Projects
def show
@package = project.packages.find(params[:id])
- @package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- @package.installable_package_files.recent
- else
- @package.package_files.recent
- end
+ @package_files = @package.installable_package_files.recent
end
end
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 71dc67bb6dc..7f680bbf121 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -13,6 +13,9 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
+ before_action do
+ push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml)
+ end
before_action do
push_frontend_feature_flag(:jobs_tab_vue, @project, default_enabled: :yaml)
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index e8074f7d793..dc0614c6bdd 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -13,8 +13,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
def index
@sort = params[:sort].presence || sort_value_name
- @skip_groups = @project.invited_group_ids
- @skip_groups += @project.group.self_and_ancestors_ids if @project.group
+ @skip_groups = @project.related_group_ids
@group_links = @project.project_group_links
@group_links = @group_links.search(params[:search_groups]) if params[:search_groups].present?
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 73eb6bb2bf2..b070f9419fc 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -18,7 +18,7 @@ class Projects::RefsController < Projects::ApplicationController
respond_to do |format|
format.html do
new_path =
- case params[:destination]
+ case permitted_params[:destination]
when "tree"
project_tree_path(@project, @id)
when "blob"
@@ -45,7 +45,7 @@ class Projects::RefsController < Projects::ApplicationController
def logs_tree
tree_summary = ::Gitlab::TreeSummary.new(
@commit, @project, current_user,
- path: @path, offset: params[:offset], limit: 25)
+ path: @path, offset: permitted_params[:offset], limit: 25)
respond_to do |format|
format.html { render_404 }
@@ -62,6 +62,10 @@ class Projects::RefsController < Projects::ApplicationController
private
def validate_ref_id
- return not_found! if params[:id].present? && params[:id] !~ Gitlab::PathRegex.git_reference_regex
+ return not_found if permitted_params[:id].present? && permitted_params[:id] !~ Gitlab::PathRegex.git_reference_regex
+ end
+
+ def permitted_params
+ params.permit(:id, :offset, :destination)
end
end
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index 77826a2f789..9fc75fff807 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -23,7 +23,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
feature_category :source_code_management
def create
- @project.create_repository
+ @project.create_repository unless @project.repository_exists?
redirect_to project_path(@project)
end
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index 62a9f8a4625..192a29730d9 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -23,7 +23,7 @@ class Projects::RunnersController < Projects::ApplicationController
def destroy
if @runner.only_for?(project)
- @runner.destroy
+ Ci::UnregisterRunnerService.new(@runner).execute
end
redirect_to project_runners_path(@project), status: :found
diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb
index 14f765814e6..7b799cc0aa6 100644
--- a/app/controllers/projects/security/configuration_controller.rb
+++ b/app/controllers/projects/security/configuration_controller.rb
@@ -10,6 +10,8 @@ module Projects
def show
render_403 unless can?(current_user, :read_security_configuration, project)
+ @configuration ||= configuration_presenter
+
respond_to do |format|
format.html
format.json do
diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb
index 1fb07c3a903..aa0e70121df 100644
--- a/app/controllers/projects/service_desk_controller.rb
+++ b/app/controllers/projects/service_desk_controller.rb
@@ -4,6 +4,7 @@ class Projects::ServiceDeskController < Projects::ApplicationController
before_action :authorize_admin_project!
feature_category :service_desk
+ urgency :low
def show
json_response
diff --git a/app/controllers/projects/service_ping_controller.rb b/app/controllers/projects/service_ping_controller.rb
index 00530c09be8..368da8d1ef2 100644
--- a/app/controllers/projects/service_ping_controller.rb
+++ b/app/controllers/projects/service_ping_controller.rb
@@ -13,6 +13,14 @@ class Projects::ServicePingController < Projects::ApplicationController
head(200)
end
+ def web_ide_clientside_preview_success
+ return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
+
+ Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_success_count
+
+ head(200)
+ end
+
def web_ide_pipelines_count
Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 9896f75c099..1321111faaf 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -12,9 +12,6 @@ class Projects::ServicesController < Projects::ApplicationController
before_action :web_hook_logs, only: [:edit, :update]
before_action :set_deprecation_notice_for_prometheus_integration, only: [:edit, :update]
before_action :redirect_deprecated_prometheus_integration, only: [:update]
- before_action do
- push_frontend_feature_flag(:vue_integration_form, current_user, default_enabled: :yaml)
- end
respond_to :html
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index c71134e0547..dd2fb57f7ac 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -160,6 +160,8 @@ module Projects
@badges.map! do |badge|
badge.new(@project, @ref).metadata
end
+
+ @badges.append(Gitlab::Ci::Badge::Release::LatestRelease.new(@project, current_user).metadata)
end
def define_auto_devops_variables
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index d750bd201e2..a28c08e87cb 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -25,7 +25,7 @@ module Projects
if result[:status] == :success
flash[:notice] = _('Repository cleanup has started. You will receive an email once the cleanup operation is complete.')
else
- flash[:alert] = status.fetch(:message, _('Failed to upload object map file'))
+ flash[:alert] = result.fetch(:message, _('Failed to upload object map file'))
end
redirect_to project_settings_repository_path(project)
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index de0faaca9c0..6472d3c3454 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -16,13 +16,16 @@ class Projects::TagsController < Projects::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def index
begin
- params[:sort] = params[:sort].presence || sort_value_recently_updated
+ tags_params = params
+ .permit(:search, :sort, :per_page, :page_token, :page)
+ .with_defaults(sort: sort_value_recently_updated)
- @sort = params[:sort]
+ @sort = tags_params[:sort]
+ @search = tags_params[:search]
- @tags = TagsFinder.new(@repository, params).execute
+ @tags = TagsFinder.new(@repository, tags_params).execute
- @tags = Kaminari.paginate_array(@tags).page(params[:page])
+ @tags = Kaminari.paginate_array(@tags).page(tags_params[:page])
tag_names = @tags.map(&:name)
@tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names)
@@ -31,6 +34,7 @@ class Projects::TagsController < Projects::ApplicationController
rescue Gitlab::Git::CommandError => e
@tags = []
+ @releases = []
@tags_loading_error = e
end
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
index c15768e7bbb..ed5bd73d6d1 100644
--- a/app/controllers/projects/uploads_controller.rb
+++ b/app/controllers/projects/uploads_controller.rb
@@ -6,7 +6,7 @@ class Projects::UploadsController < Projects::ApplicationController
# These will kick you out if you don't have access.
skip_before_action :project, :repository,
- if: -> { action_name == 'show' && embeddable? }
+ if: -> { bypass_auth_checks_on_uploads? }
before_action :authorize_upload_file!, only: [:create, :authorize]
before_action :verify_workhorse_api!, only: [:authorize]
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 64abcd7cc33..519d9cd0d52 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -10,6 +10,7 @@ class ProjectsController < Projects::ApplicationController
include ImportUrlParams
include FiltersEvents
include SourcegraphDecorator
+ include PlanningHierarchy
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
@@ -41,6 +42,7 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml)
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:work_items, @project, default_enabled: :yaml)
end
layout :determine_layout
@@ -54,6 +56,7 @@ class ProjectsController < Projects::ApplicationController
feature_category :team_planning, [:preview_markdown, :new_issuable_address]
feature_category :importers, [:export, :remove_export, :generate_new_export, :download_export]
feature_category :code_review, [:unfoldered_environment_names]
+ feature_category :portfolio_management, [:planning_hierarchy]
urgency :low, [:refs]
urgency :high, [:unfoldered_environment_names]
@@ -283,7 +286,7 @@ class ProjectsController < Projects::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def refs
- find_refs = params['find']
+ find_refs = refs_params['find']
find_branches = true
find_tags = true
@@ -298,13 +301,13 @@ class ProjectsController < Projects::ApplicationController
options = {}
if find_branches
- branches = BranchesFinder.new(@repository, params).execute.take(100).map(&:name)
+ branches = BranchesFinder.new(@repository, refs_params).execute.take(100).map(&:name)
options['Branches'] = branches
end
if find_tags && @repository.tag_count.nonzero?
tags = begin
- TagsFinder.new(@repository, params).execute
+ TagsFinder.new(@repository, refs_params).execute
rescue Gitlab::Git::CommandError
[]
end
@@ -313,7 +316,7 @@ class ProjectsController < Projects::ApplicationController
end
# If reference is commit id - we should add it to branch/tag selectbox
- ref = Addressable::URI.unescape(params[:ref])
+ ref = Addressable::URI.unescape(refs_params[:ref])
if find_commits && ref && options.flatten(2).exclude?(ref) && ref =~ /\A[0-9a-zA-Z]{6,52}\z/
options['Commits'] = [ref]
end
@@ -342,6 +345,14 @@ class ProjectsController < Projects::ApplicationController
private
+ def refs_params
+ if Feature.enabled?(:strong_parameters_for_project_controller, @project, default_enabled: :yaml)
+ params.permit(:search, :sort, :ref, find: [])
+ else
+ params
+ end
+ end
+
# Render project landing depending of which features are available
# So if page is not available in the list it renders the next page
#
@@ -461,8 +472,8 @@ class ProjectsController < Projects::ApplicationController
:suggestion_commit_message,
:packages_enabled,
:service_desk_enabled,
- :merge_commit_template,
- :squash_commit_template,
+ :merge_commit_template_or_default,
+ :squash_commit_template_or_default,
project_setting_attributes: project_setting_attributes
] + [project_feature_attributes: project_feature_attributes]
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index c1765d367d1..057c451ace2 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -6,6 +6,7 @@ class RegistrationsController < Devise::RegistrationsController
include RecaptchaHelper
include InvisibleCaptchaOnSignup
include OneTrustCSP
+ include BizibleCSP
layout 'devise'
@@ -35,6 +36,7 @@ class RegistrationsController < Devise::RegistrationsController
persist_accepted_terms_if_required(new_user)
set_role_required(new_user)
+ track_experiment_event(new_user)
if pending_approval?
NotificationService.new.new_instance_access_request(new_user)
@@ -223,6 +225,14 @@ class RegistrationsController < Devise::RegistrationsController
def context_user
current_user
end
+
+ def track_experiment_event(new_user)
+ # Track signed up event to relate it with click "Sign up" button events from
+ # the experimental logged out header with marketing links. This allows us to
+ # have a funnel of visitors clicking on the header and those visitors
+ # signing up and becoming users
+ experiment(:logged_out_marketing_header, actor: new_user).track(:signed_up) if new_user.persisted?
+ end
end
RegistrationsController.prepend_mod_with('RegistrationsController')
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index c002c9b83f9..24520a187e3 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -17,6 +17,9 @@ module Repositories
prepend_before_action :authenticate_user, :parse_repo_path
+ skip_around_action :sessionless_bypass_admin_mode!
+ around_action :bypass_admin_mode!, if: :authenticated_user
+
feature_category :source_code_management
def authenticated_user
@@ -136,6 +139,12 @@ module Repositories
container &&
Guest.can?(repo_type.guest_read_ability, container)
end
+
+ def bypass_admin_mode!(&block)
+ return yield unless Gitlab::CurrentSettings.admin_mode
+
+ Gitlab::Auth::CurrentUserMode.bypass_session!(authenticated_user.id, &block)
+ end
end
end
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 2b0aa67326e..7deda473b9d 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -155,7 +155,6 @@ module Repositories
end
def should_auto_link?
- return false unless Feature.enabled?(:lfs_auto_link_fork_source, project, default_enabled: :yaml)
return false unless project.forked?
# Sanity check in case for some reason the user doesn't have access to the parent
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index d58ed252a36..e38eeaed367 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -144,6 +144,7 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.filters.state'] = params[:state]
payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results]
payload[:metadata]['meta.search.project_ids'] = params[:project_ids]
+ payload[:metadata]['meta.search.search_level'] = params[:search_level]
if search_service.abuse_detected?
payload[:metadata]['abuse.confidence'] = Gitlab::Abuse.confidence(:certain)
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 7e8e3ea8789..e907e291eeb 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -10,6 +10,7 @@ class SessionsController < Devise::SessionsController
include KnownSignIn
include Gitlab::Utils::StrongMemoize
include OneTrustCSP
+ include BizibleCSP
skip_before_action :check_two_factor_requirement, only: [:destroy]
skip_before_action :check_password_expiration, only: [:destroy]
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 8710eebf210..f6cef7e133c 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -148,7 +148,11 @@ class UsersController < ApplicationController
end
def exists
- render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) }
+ if Gitlab::CurrentSettings.signup_enabled? || current_user
+ render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) }
+ else
+ render json: { error: _('You must be authenticated to access this path.') }, status: :unauthorized
+ end
end
def follow
@@ -182,7 +186,7 @@ class UsersController < ApplicationController
end
def starred_projects
- StarredProjectsFinder.new(user, current_user: current_user).execute
+ StarredProjectsFinder.new(user, params: finder_params, current_user: current_user).execute
end
def contributions_calendar
@@ -248,6 +252,15 @@ class UsersController < ApplicationController
end
end
end
+
+ def finder_params
+ {
+ # don't display projects pending deletion
+ without_deleted: true,
+ # don't display projects marked for deletion
+ not_aimed_for_deletion: true
+ }
+ end
end
UsersController.prepend_mod_with('UsersController')
diff --git a/app/events/ci/job_artifacts_deleted_event.rb b/app/events/ci/job_artifacts_deleted_event.rb
new file mode 100644
index 00000000000..2972342cae6
--- /dev/null
+++ b/app/events/ci/job_artifacts_deleted_event.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Ci
+ class JobArtifactsDeletedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'required' => ['job_ids'],
+ 'properties' => {
+ 'job_ids' => {
+ 'type' => 'array',
+ 'properties' => {
+ 'job_id' => { 'type' => 'integer' }
+ }
+ }
+ }
+ }
+ end
+ end
+end
diff --git a/app/events/members/members_added_event.rb b/app/events/members/members_added_event.rb
new file mode 100644
index 00000000000..c174ffebab6
--- /dev/null
+++ b/app/events/members/members_added_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Members
+ class MembersAddedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'required' => %w[source_id source_type],
+ 'properties' => {
+ 'source_id' => { 'type' => 'integer' },
+ 'source_type' => { 'type' => 'string' }
+ }
+ }
+ end
+ end
+end
diff --git a/app/events/projects/project_deleted_event.rb b/app/events/projects/project_deleted_event.rb
new file mode 100644
index 00000000000..ac58c5c6755
--- /dev/null
+++ b/app/events/projects/project_deleted_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Projects
+ class ProjectDeletedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[project_id namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index 859716b4739..f6af7ca15bb 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -1,14 +1,6 @@
# frozen_string_literal: true
-class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/NamespacedClass
- def enabled?
- return false if Feature::Definition.get(feature_flag_name).nil? # there has to be a feature flag yaml file
- return false unless Gitlab.dev_env_or_com? # we have to be in an environment that allows experiments
-
- # the feature flag has to be rolled out
- Feature.get(feature_flag_name).state != :off # rubocop:disable Gitlab/AvoidFeatureGet
- end
-
+class ApplicationExperiment < Gitlab::Experiment
def publish(_result = nil)
super
@@ -41,10 +33,6 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
# define a default nil control behavior so we can omit it when not needed
end
- def track(action, **event_args)
- super(action, **tracking_context.merge(event_args))
- end
-
# TODO: remove
# This is deprecated logic as of v0.6.0 and should eventually be removed, but
# needs to stay intact for actively running experiments. The new strategy
@@ -64,24 +52,16 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
private
- def tracking_context
+ def tracking_context(event_args)
{
namespace: context.try(:namespace) || context.try(:group),
project: context.try(:project),
user: user_or_actor
- }.compact || {}
+ }.merge(event_args)
end
def user_or_actor
actor = context.try(:actor)
actor.respond_to?(:id) ? actor : context.try(:user)
end
-
- def feature_flag_name
- name.tr('/', '_')
- end
-
- def experiment_group?
- Feature.enabled?(feature_flag_name, self, type: :experiment, default_enabled: :yaml)
- end
end
diff --git a/app/experiments/combined_registration_experiment.rb b/app/experiments/combined_registration_experiment.rb
index 08c015838db..576e10815aa 100644
--- a/app/experiments/combined_registration_experiment.rb
+++ b/app/experiments/combined_registration_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CombinedRegistrationExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class CombinedRegistrationExperiment < ApplicationExperiment
include Rails.application.routes.url_helpers
def key_for(source, _ = nil)
diff --git a/app/experiments/empty_repo_upload_experiment.rb b/app/experiments/empty_repo_upload_experiment.rb
index d0d79a5fb45..c8c75f32d69 100644
--- a/app/experiments/empty_repo_upload_experiment.rb
+++ b/app/experiments/empty_repo_upload_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class EmptyRepoUploadExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class EmptyRepoUploadExperiment < ApplicationExperiment
include ProjectCommitCount
TRACKING_START_DATE = DateTime.parse('2021/4/20')
diff --git a/app/experiments/force_company_trial_experiment.rb b/app/experiments/force_company_trial_experiment.rb
index 00bdd5d693d..e7b98bb18ad 100644
--- a/app/experiments/force_company_trial_experiment.rb
+++ b/app/experiments/force_company_trial_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ForceCompanyTrialExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class ForceCompanyTrialExperiment < ApplicationExperiment
exclude :setup_for_personal
private
diff --git a/app/experiments/in_product_guidance_environments_webide_experiment.rb b/app/experiments/in_product_guidance_environments_webide_experiment.rb
index d77063a9834..6567ec0b3f1 100644
--- a/app/experiments/in_product_guidance_environments_webide_experiment.rb
+++ b/app/experiments/in_product_guidance_environments_webide_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class InProductGuidanceEnvironmentsWebideExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class InProductGuidanceEnvironmentsWebideExperiment < ApplicationExperiment
exclude :has_environments?
def control_behavior
diff --git a/app/experiments/new_project_readme_content_experiment.rb b/app/experiments/new_project_readme_content_experiment.rb
deleted file mode 100644
index 1de7632268d..00000000000
--- a/app/experiments/new_project_readme_content_experiment.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class NewProjectReadmeContentExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
- TEMPLATE_PATH = Rails.root.join('app', 'experiments', 'templates', 'new_project_readme_content')
- include Rails.application.routes.url_helpers
-
- def run_with(project, variant: nil)
- @project = project
- publish_to_database
- run(variant)
- end
-
- def control_behavior
- template('readme_basic.md')
- end
-
- def advanced_behavior
- template('readme_advanced.md')
- end
-
- def redirect(to_url)
- experiment_redirect_url(self, url: to_url)
- end
-
- private
-
- def template(name)
- ERB.new(File.read(TEMPLATE_PATH.join("#{name}.tt")), trim_mode: '<>').result(binding)
- end
-end
diff --git a/app/experiments/new_project_sast_enabled_experiment.rb b/app/experiments/new_project_sast_enabled_experiment.rb
index a779b8ec633..ee9d0dc1700 100644
--- a/app/experiments/new_project_sast_enabled_experiment.rb
+++ b/app/experiments/new_project_sast_enabled_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class NewProjectSastEnabledExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class NewProjectSastEnabledExperiment < ApplicationExperiment
def publish(_result = nil)
super
diff --git a/app/experiments/require_verification_for_namespace_creation_experiment.rb b/app/experiments/require_verification_for_namespace_creation_experiment.rb
index 1cadac7e7d4..0c47f5d183c 100644
--- a/app/experiments/require_verification_for_namespace_creation_experiment.rb
+++ b/app/experiments/require_verification_for_namespace_creation_experiment.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
-class RequireVerificationForNamespaceCreationExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class RequireVerificationForNamespaceCreationExperiment < ApplicationExperiment
+ exclude :existing_user
+
+ EXPERIMENT_START_DATE = Date.new(2022, 1, 31)
+
def control_behavior
false
end
@@ -24,4 +28,10 @@ class RequireVerificationForNamespaceCreationExperiment < ApplicationExperiment
def subject
context.value[:user]
end
+
+ def existing_user
+ return false unless user_or_actor
+
+ user_or_actor.created_at < EXPERIMENT_START_DATE
+ end
end
diff --git a/app/experiments/security_reports_mr_widget_prompt_experiment.rb b/app/experiments/security_reports_mr_widget_prompt_experiment.rb
index fa0ba8e24d4..bcb9d64fcb7 100644
--- a/app/experiments/security_reports_mr_widget_prompt_experiment.rb
+++ b/app/experiments/security_reports_mr_widget_prompt_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class SecurityReportsMrWidgetPromptExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+class SecurityReportsMrWidgetPromptExperiment < ApplicationExperiment
def publish(_result = nil)
super
diff --git a/app/experiments/templates/new_project_readme_content/readme_basic.md.tt b/app/experiments/templates/new_project_readme_content/readme_basic.md.tt
deleted file mode 100644
index 1e68eaf2f05..00000000000
--- a/app/experiments/templates/new_project_readme_content/readme_basic.md.tt
+++ /dev/null
@@ -1,3 +0,0 @@
-# <%= @project.name %>
-
-<%= @project.description %>
diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb
index a9fffd3f411..33d9a8a3dbc 100644
--- a/app/finders/autocomplete/users_finder.rb
+++ b/app/finders/autocomplete/users_finder.rb
@@ -62,7 +62,7 @@ module Autocomplete
find_users
.active
.reorder_by_name
- .optionally_search(search)
+ .optionally_search(search, use_minimum_char_limit: use_minimum_char_limit)
.where_not_in(skip_users)
.limit_to_todo_authors(
user: current_user,
@@ -99,6 +99,12 @@ module Autocomplete
ActiveRecord::Associations::Preloader.new.preload(items, :status)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def use_minimum_char_limit
+ return if project.blank? && group.blank? # We return nil so that we use the default defined in the User model
+
+ false
+ end
end
end
diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb
index 4408c9cdb6d..5fc9c0e1778 100644
--- a/app/finders/ci/jobs_finder.rb
+++ b/app/finders/ci/jobs_finder.rb
@@ -4,10 +4,11 @@ module Ci
class JobsFinder
include Gitlab::Allowable
- def initialize(current_user:, pipeline: nil, project: nil, params: {}, type: ::Ci::Build)
+ def initialize(current_user:, pipeline: nil, project: nil, runner: nil, params: {}, type: ::Ci::Build)
@pipeline = pipeline
@current_user = current_user
@project = project
+ @runner = runner
@params = params
@type = type
raise ArgumentError 'type must be a subclass of Ci::Processable' unless type < ::Ci::Processable
@@ -22,10 +23,10 @@ module Ci
private
- attr_reader :current_user, :pipeline, :project, :params, :type
+ attr_reader :current_user, :pipeline, :project, :runner, :params, :type
def init_collection
- pipeline_jobs || project_jobs || all_jobs
+ pipeline_jobs || project_jobs || runner_jobs || all_jobs
end
def all_jobs
@@ -34,6 +35,13 @@ module Ci
type.all
end
+ def runner_jobs
+ return unless runner
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_builds, runner)
+
+ jobs_by_type(runner, type).relevant
+ end
+
def project_jobs
return unless project
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, project)
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 3ebf6bd1562..356915722fe 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -4,7 +4,7 @@ module Ci
class RunnersFinder < UnionFinder
include Gitlab::Allowable
- ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date].freeze
+ ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date token_expires_at_asc token_expires_at_desc].freeze
DEFAULT_SORT = 'created_at_desc'
def initialize(current_user:, params:)
@@ -53,13 +53,7 @@ module Ci
when :direct
Ci::Runner.belonging_to_group(@group.id)
when :descendants, nil
- if ::Feature.enabled?(:ci_find_runners_by_ci_mirrors, @group, default_enabled: :yaml)
- Ci::Runner.belonging_to_group_or_project_descendants(@group.id)
- else
- # Getting all runners from the group itself and all its descendant groups/projects
- descendant_projects = Project.for_group_and_its_subgroups(@group)
- Ci::Runner.legacy_belonging_to_group_or_project(@group.self_and_descendants, descendant_projects)
- end
+ Ci::Runner.belonging_to_group_or_project_descendants(@group.id)
else
raise ArgumentError, 'Invalid membership filter'
end
diff --git a/app/finders/crm/contacts_finder.rb b/app/finders/crm/contacts_finder.rb
new file mode 100644
index 00000000000..c2d44bec27b
--- /dev/null
+++ b/app/finders/crm/contacts_finder.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+# Finder for retrieving contacts scoped to a group
+#
+# Arguments:
+# current_user - user performing the action. Must have the correct permission level for the group.
+# params:
+# group: Group, required
+module Crm
+ class ContactsFinder
+ include Gitlab::Allowable
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :params, :current_user
+
+ def initialize(current_user, params = {})
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return CustomerRelations::Contact.none unless root_group
+
+ root_group.contacts
+ end
+
+ private
+
+ def root_group
+ strong_memoize(:root_group) do
+ group = params[:group]&.root_ancestor
+
+ next unless can?(@current_user, :read_crm_contact, group)
+
+ group
+ end
+ end
+ end
+end
diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb
index bb9d204ab73..04b82ee04ec 100644
--- a/app/finders/deployments_finder.rb
+++ b/app/finders/deployments_finder.rb
@@ -49,6 +49,10 @@ class DeploymentsFinder
private
+ def raise_for_inefficient_updated_at_query?
+ params.fetch(:raise_for_inefficient_updated_at_query, Rails.env.development? || Rails.env.test?)
+ end
+
def validate!
if filter_by_updated_at? && filter_by_finished_at?
raise InefficientQueryError, 'Both `updated_at` filter and `finished_at` filter can not be specified'
@@ -57,9 +61,11 @@ class DeploymentsFinder
# Currently, the inefficient parameters are allowed in order to avoid breaking changes in Deployment API.
# We'll switch to a hard error in https://gitlab.com/gitlab-org/gitlab/-/issues/328500.
if (filter_by_updated_at? && !order_by_updated_at?) || (!filter_by_updated_at? && order_by_updated_at?)
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
- InefficientQueryError.new('`updated_at` filter and `updated_at` sorting must be paired')
- )
+ error = InefficientQueryError.new('`updated_at` filter and `updated_at` sorting must be paired')
+
+ Gitlab::ErrorTracking.log_exception(error)
+
+ raise error if raise_for_inefficient_updated_at_query?
end
if (filter_by_finished_at? && !order_by_finished_at?) || (!filter_by_finished_at? && order_by_finished_at?)
diff --git a/app/finders/environments/environments_by_deployments_finder.rb b/app/finders/environments/environments_by_deployments_finder.rb
index 1a0d5ff0d5e..bffd0c9a319 100644
--- a/app/finders/environments/environments_by_deployments_finder.rb
+++ b/app/finders/environments/environments_by_deployments_finder.rb
@@ -15,8 +15,8 @@ module Environments
deployments =
if ref
Deployment.where(ref: ref.to_s)
- elsif commit
- Deployment.where(sha: commit.sha)
+ elsif sha
+ Deployment.where(sha: sha)
else
Deployment.none
end
@@ -47,7 +47,7 @@ module Environments
return false unless Ability.allowed?(current_user, :read_environment, environment)
return false if ref && params[:recently_updated] && !environment.recently_updated_on_branch?(ref)
- return false if ref && commit && !environment.includes_commit?(commit)
+ return false if ref && sha && !environment.includes_commit?(sha)
true
end
@@ -56,8 +56,8 @@ module Environments
params[:ref].try(:to_s)
end
- def commit
- params[:commit]
+ def sha
+ params[:sha] || params[:commit]&.id
end
end
end
diff --git a/app/finders/git_refs_finder.rb b/app/finders/git_refs_finder.rb
index 11af659d37c..dbe0060d8ae 100644
--- a/app/finders/git_refs_finder.rb
+++ b/app/finders/git_refs_finder.rb
@@ -11,11 +11,11 @@ class GitRefsFinder
attr_reader :repository, :params
def search
- @params[:search].presence
+ @params[:search].to_s.presence
end
def sort
- @params[:sort].presence || 'name'
+ @params[:sort].to_s.presence || 'name'
end
def by_search(refs)
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index 3d9b6e94cc6..40d6be03a17 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -25,7 +25,7 @@ class GroupDescendantsFinder
def initialize(current_user: nil, parent_group:, params: {})
@current_user = current_user
@parent_group = parent_group
- @params = params.reverse_merge(non_archived: params[:archived].blank?)
+ @params = params.reverse_merge(non_archived: params[:archived].blank?, not_aimed_for_deletion: true)
end
def execute
@@ -110,8 +110,13 @@ class GroupDescendantsFinder
# rubocop: disable CodeReuse/ActiveRecord
def ancestors_of_groups(base_for_ancestors)
group_ids = base_for_ancestors.except(:select, :sort).select(:id)
- Gitlab::ObjectHierarchy.new(Group.where(id: group_ids))
- .base_and_ancestors(upto: parent_group.id)
+ groups = Group.where(id: group_ids)
+
+ if Feature.enabled?(:linear_group_descendants_finder_upto, current_user, default_enabled: :yaml)
+ groups.self_and_ancestors(upto: parent_group.id)
+ else
+ Gitlab::ObjectHierarchy.new(groups).base_and_ancestors(upto: parent_group.id)
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb
index d3c26fd845c..00b700a101e 100644
--- a/app/finders/group_projects_finder.rb
+++ b/app/finders/group_projects_finder.rb
@@ -13,6 +13,7 @@
# only_shared: boolean
# limit: integer
# include_subgroups: boolean
+# include_ancestor_groups: boolean
# params:
# sort: string
# visibility_level: int
@@ -113,12 +114,19 @@ class GroupProjectsFinder < ProjectsFinder
options.fetch(:include_subgroups, false)
end
+ # ancestor groups are supported only for owned projects not for shared
+ def include_ancestor_groups?
+ options.fetch(:include_ancestor_groups, false)
+ end
+
def owned_projects
- if include_subgroups?
- Project.for_group_and_its_subgroups(group)
- else
- group.projects
- end
+ return group.projects unless include_subgroups? || include_ancestor_groups?
+
+ union_relations = []
+ union_relations << Project.for_group_and_its_subgroups(group) if include_subgroups?
+ union_relations << Project.for_group_and_its_ancestor_groups(group) if include_ancestor_groups?
+
+ Project.from_union(union_relations)
end
def shared_projects
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index de750b49c6a..a7eaaddd187 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -108,8 +108,14 @@ class IssuesFinder < IssuableFinder
if params.filter_by_no_due_date?
items.without_due_date
+ elsif params.filter_by_any_due_date?
+ items.with_due_date
elsif params.filter_by_overdue?
items.due_before(Date.today)
+ elsif params.filter_by_due_today?
+ items.due_today
+ elsif params.filter_by_due_tomorrow?
+ items.due_tomorrow
elsif params.filter_by_due_this_week?
items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif params.filter_by_due_this_month?
diff --git a/app/finders/issues_finder/params.rb b/app/finders/issues_finder/params.rb
index 02b89f08f9e..57bfb35f1b8 100644
--- a/app/finders/issues_finder/params.rb
+++ b/app/finders/issues_finder/params.rb
@@ -10,6 +10,10 @@ class IssuesFinder
user_can_see_all_issues?
end
+ def filter_by_any_due_date?
+ due_date? && params[:due_date] == Issue::AnyDueDate.name
+ end
+
def filter_by_no_due_date?
due_date? && params[:due_date] == Issue::NoDueDate.name
end
@@ -18,6 +22,14 @@ class IssuesFinder
due_date? && params[:due_date] == Issue::Overdue.name
end
+ def filter_by_due_today?
+ due_date? && params[:due_date] == Issue::DueToday.name
+ end
+
+ def filter_by_due_tomorrow?
+ due_date? && params[:due_date] == Issue::DueTomorrow.name
+ end
+
def filter_by_due_this_week?
due_date? && params[:due_date] == Issue::DueThisWeek.name
end
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index 81e4ab7014d..06feefb9059 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -44,7 +44,8 @@ class MergeRequestsFinder < IssuableFinder
:reviewer_id,
:reviewer_username,
:target_branch,
- :wip
+ :wip,
+ :attention
]
end
@@ -69,6 +70,7 @@ class MergeRequestsFinder < IssuableFinder
items = by_approvals(items)
items = by_deployments(items)
items = by_reviewer(items)
+ items = by_attention(items)
by_source_project_id(items)
end
@@ -218,6 +220,12 @@ class MergeRequestsFinder < IssuableFinder
end
end
+ def by_attention(items)
+ return items unless params.attention?
+
+ items.attention(params.attention)
+ end
+
def parse_datetime(input)
# To work around http://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/
DateTime.parse(input.byteslice(0, 128)) if input
diff --git a/app/finders/merge_requests_finder/params.rb b/app/finders/merge_requests_finder/params.rb
index e44e96054d3..1c6a425c8af 100644
--- a/app/finders/merge_requests_finder/params.rb
+++ b/app/finders/merge_requests_finder/params.rb
@@ -21,5 +21,11 @@ class MergeRequestsFinder
end
end
end
+
+ def attention
+ strong_memoize(:attention) do
+ User.find_by_username(params[:attention])
+ end
+ end
end
end
diff --git a/app/finders/packages/package_file_finder.rb b/app/finders/packages/package_file_finder.rb
index 55dc4be2001..786302d65b1 100644
--- a/app/finders/packages/package_file_finder.rb
+++ b/app/finders/packages/package_file_finder.rb
@@ -19,13 +19,7 @@ class Packages::PackageFileFinder
private
def package_files
- files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- by_file_name(files)
+ by_file_name(package.installable_package_files)
end
def by_file_name(files)
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 7245bb36ac9..f6db150c5d8 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -27,6 +27,7 @@
# last_activity_before: datetime
# repository_storage: string
# without_deleted: boolean
+# not_aimed_for_deletion: boolean
#
class ProjectsFinder < UnionFinder
include CustomAttributesFilter
@@ -84,6 +85,7 @@ class ProjectsFinder < UnionFinder
collection = by_archived(collection)
collection = by_custom_attributes(collection)
collection = by_deleted_status(collection)
+ collection = by_not_aimed_for_deletion(collection)
collection = by_last_activity_after(collection)
collection = by_last_activity_before(collection)
by_repository_storage(collection)
@@ -203,6 +205,10 @@ class ProjectsFinder < UnionFinder
params[:without_deleted].present? ? items.without_deleted : items
end
+ def by_not_aimed_for_deletion(items)
+ params[:not_aimed_for_deletion].present? ? items.not_aimed_for_deletion : items
+ end
+
def by_last_activity_after(items)
if params[:last_activity_after].present?
items.where("last_activity_at > ?", params[:last_activity_after]) # rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/releases_finder.rb b/app/finders/releases_finder.rb
index 0cfa4310ab7..0d72d6ffc6b 100644
--- a/app/finders/releases_finder.rb
+++ b/app/finders/releases_finder.rb
@@ -38,19 +38,17 @@ class ReleasesFinder
if parent.is_a?(Project)
Ability.allowed?(current_user, :read_release, parent) ? [parent] : []
elsif parent.is_a?(Group)
- accessible_projects
+ Ability.allowed?(current_user, :read_release, parent) ? accessible_projects : []
end
end
end
def accessible_projects
- projects = if include_subgroups?
- Project.for_group_and_its_subgroups(parent)
- else
- parent.projects
- end
-
- projects.select { |project| Ability.allowed?(current_user, :read_release, project) }
+ if include_subgroups?
+ Project.for_group_and_its_subgroups(parent)
+ else
+ parent.projects
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index 2b4ce615090..b983882b272 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -32,7 +32,7 @@ class UsersFinder
end
def execute
- users = User.all.order_id_desc
+ users = base_scope
users = by_username(users)
users = by_id(users)
users = by_admins(users)
@@ -53,6 +53,10 @@ class UsersFinder
private
+ def base_scope
+ User.all.order_id_desc
+ end
+
def by_username(users)
return users unless params[:username]
diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb
index 290cd4d7146..ac1a4a6b9ef 100644
--- a/app/graphql/graphql_triggers.rb
+++ b/app/graphql/graphql_triggers.rb
@@ -8,4 +8,8 @@ module GraphqlTriggers
def self.issue_crm_contacts_updated(issue)
GitlabSchema.subscriptions.trigger('issueCrmContactsUpdated', { issuable_id: issue.to_gid }, issue)
end
+
+ def self.issuable_title_updated(issuable)
+ GitlabSchema.subscriptions.trigger('issuableTitleUpdated', { issuable_id: issuable.to_gid }, issuable)
+ end
end
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index c4f91d0c15c..b1db355aa40 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -8,7 +8,7 @@ module Mutations
ADMIN_MESSAGE = 'You must be an admin to use this mutation'
- ::Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
+ ::Gitlab::ApplicationContext.known_keys.each do |key|
argument key,
GraphQL::Types::String,
required: false,
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
index 04840ac43bd..f8d1a383706 100644
--- a/app/graphql/mutations/alert_management/http_integration/create.rb
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -4,10 +4,10 @@ module Mutations
module AlertManagement
module HttpIntegration
class Create < HttpIntegrationBase
- include FindsProject
-
graphql_name 'HttpIntegrationCreate'
+ include FindsProject
+
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project to create the integration in.'
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
index 0153bd0e42a..9c3aefce033 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -4,10 +4,10 @@ module Mutations
module AlertManagement
module PrometheusIntegration
class Create < PrometheusIntegrationBase
- include FindsProject
-
graphql_name 'PrometheusIntegrationCreate'
+ include FindsProject
+
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project to create the integration in.'
diff --git a/app/graphql/mutations/boards/create.rb b/app/graphql/mutations/boards/create.rb
index 080bf7c6e79..773ba08a291 100644
--- a/app/graphql/mutations/boards/create.rb
+++ b/app/graphql/mutations/boards/create.rb
@@ -3,10 +3,9 @@
module Mutations
module Boards
class Create < ::Mutations::BaseMutation
- include Mutations::ResolvesResourceParent
-
graphql_name 'CreateBoard'
+ include Mutations::ResolvesResourceParent
include Mutations::Boards::CommonMutationArguments
field :board,
diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb
index 078c84bcdc0..b851622bfde 100644
--- a/app/graphql/mutations/branches/create.rb
+++ b/app/graphql/mutations/branches/create.rb
@@ -3,10 +3,10 @@
module Mutations
module Branches
class Create < BaseMutation
- include FindsProject
-
graphql_name 'CreateBranch'
+ include FindsProject
+
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project full path the branch is associated with.'
diff --git a/app/graphql/mutations/ci/ci_cd_settings_update.rb b/app/graphql/mutations/ci/ci_cd_settings_update.rb
index 7bd38bc2998..dec90ced962 100644
--- a/app/graphql/mutations/ci/ci_cd_settings_update.rb
+++ b/app/graphql/mutations/ci/ci_cd_settings_update.rb
@@ -3,10 +3,10 @@
module Mutations
module Ci
class CiCdSettingsUpdate < BaseMutation
- include FindsProject
-
graphql_name 'CiCdSettingsUpdate'
+ include FindsProject
+
authorize :admin_project
argument :full_path, GraphQL::Types::ID,
diff --git a/app/graphql/mutations/ci/job_token_scope/add_project.rb b/app/graphql/mutations/ci/job_token_scope/add_project.rb
index 41adcae2c82..e16c08cb116 100644
--- a/app/graphql/mutations/ci/job_token_scope/add_project.rb
+++ b/app/graphql/mutations/ci/job_token_scope/add_project.rb
@@ -4,10 +4,10 @@ module Mutations
module Ci
module JobTokenScope
class AddProject < BaseMutation
- include FindsProject
-
graphql_name 'CiJobTokenScopeAddProject'
+ include FindsProject
+
authorize :admin_project
argument :project_path, GraphQL::Types::ID,
diff --git a/app/graphql/mutations/ci/job_token_scope/remove_project.rb b/app/graphql/mutations/ci/job_token_scope/remove_project.rb
index dd6b2358dd5..f503b4f2f7a 100644
--- a/app/graphql/mutations/ci/job_token_scope/remove_project.rb
+++ b/app/graphql/mutations/ci/job_token_scope/remove_project.rb
@@ -4,10 +4,10 @@ module Mutations
module Ci
module JobTokenScope
class RemoveProject < BaseMutation
- include FindsProject
-
graphql_name 'CiJobTokenScopeRemoveProject'
+ include FindsProject
+
authorize :admin_project
argument :project_path, GraphQL::Types::ID,
diff --git a/app/graphql/mutations/ci/runner/delete.rb b/app/graphql/mutations/ci/runner/delete.rb
index 88dc426398b..21c3d55881c 100644
--- a/app/graphql/mutations/ci/runner/delete.rb
+++ b/app/graphql/mutations/ci/runner/delete.rb
@@ -20,7 +20,7 @@ module Mutations
error = authenticate_delete_runner!(runner)
return { errors: [error] } if error
- runner.destroy!
+ ::Ci::UnregisterRunnerService.new(runner).execute
{ errors: runner.errors.full_messages }
end
diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb
index e37ab1081f9..e6123b4283a 100644
--- a/app/graphql/mutations/ci/runner/update.rb
+++ b/app/graphql/mutations/ci/runner/update.rb
@@ -28,7 +28,12 @@ module Mutations
argument :active, GraphQL::Types::Boolean,
required: false,
- description: 'Indicates the runner is allowed to receive jobs.'
+ description: 'Indicates the runner is allowed to receive jobs.',
+ deprecated: { reason: :renamed, replacement: 'paused', milestone: '14.8' }
+
+ argument :paused, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Indicates the runner is not allowed to receive jobs.'
argument :locked, GraphQL::Types::Boolean, required: false,
description: 'Indicates the runner is locked.'
diff --git a/app/graphql/mutations/clusters/agents/create.rb b/app/graphql/mutations/clusters/agents/create.rb
index 0896cc7b203..deaa9c2d656 100644
--- a/app/graphql/mutations/clusters/agents/create.rb
+++ b/app/graphql/mutations/clusters/agents/create.rb
@@ -4,12 +4,12 @@ module Mutations
module Clusters
module Agents
class Create < BaseMutation
+ graphql_name 'CreateClusterAgent'
+
include FindsProject
authorize :create_cluster
- graphql_name 'CreateClusterAgent'
-
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Full path of the associated project for this cluster agent.'
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index 3eb1912dbc4..00ec64becc8 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -3,6 +3,8 @@
module Mutations
module Commits
class Create < BaseMutation
+ graphql_name 'CommitCreate'
+
include FindsProject
class UrlHelpers
@@ -10,8 +12,6 @@ module Mutations
include Gitlab::Routing
end
- graphql_name 'CommitCreate'
-
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project full path the branch is associated with.'
diff --git a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
deleted file mode 100644
index f1ae54aa014..00000000000
--- a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- # This concern is deprecated and will be deleted in 14.6
- #
- # Use the SpamProtection concern instead.
- module CanMutateSpammable
- extend ActiveSupport::Concern
-
- DEPRECATION_NOTICE = {
- reason: 'Use spam protection with HTTP headers instead',
- milestone: '13.11'
- }.freeze
-
- included do
- argument :captcha_response, GraphQL::Types::String,
- required: false,
- deprecated: DEPRECATION_NOTICE,
- description: 'Valid CAPTCHA response value obtained by using the provided captchaSiteKey with a CAPTCHA API to present a challenge to be solved on the client. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
-
- argument :spam_log_id, GraphQL::Types::Int,
- required: false,
- deprecated: DEPRECATION_NOTICE,
- description: 'Spam log ID which must be passed along with a valid CAPTCHA response for the operation to be completed. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
-
- field :spam,
- GraphQL::Types::Boolean,
- null: true,
- deprecated: DEPRECATION_NOTICE,
- description: 'Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response.'
-
- field :needs_captcha_response,
- GraphQL::Types::Boolean,
- null: true,
- deprecated: DEPRECATION_NOTICE,
- description: 'Indicates whether the operation was detected as possible spam and not completed. If CAPTCHA is enabled, the request must be resubmitted with a valid CAPTCHA response and spam_log_id included for the operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
-
- field :spam_log_id,
- GraphQL::Types::Int,
- null: true,
- deprecated: DEPRECATION_NOTICE,
- description: 'Spam log ID which must be passed along with a valid CAPTCHA response for an operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
-
- field :captcha_site_key,
- GraphQL::Types::String,
- null: true,
- deprecated: DEPRECATION_NOTICE,
- description: 'CAPTCHA site key which must be used to render a challenge for the user to solve to obtain a valid captchaResponse value. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
- end
- end
-end
diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb
index db4acadfc38..762058acf3d 100644
--- a/app/graphql/mutations/container_expiration_policies/update.rb
+++ b/app/graphql/mutations/container_expiration_policies/update.rb
@@ -3,10 +3,10 @@
module Mutations
module ContainerExpirationPolicies
class Update < Mutations::BaseMutation
- include FindsProject
-
graphql_name 'UpdateContainerExpirationPolicy'
+ include FindsProject
+
authorize :destroy_container_image
argument :project_path,
diff --git a/app/graphql/mutations/container_repositories/destroy_tags.rb b/app/graphql/mutations/container_repositories/destroy_tags.rb
index c2737820d22..7777f903516 100644
--- a/app/graphql/mutations/container_repositories/destroy_tags.rb
+++ b/app/graphql/mutations/container_repositories/destroy_tags.rb
@@ -3,12 +3,11 @@
module Mutations
module ContainerRepositories
class DestroyTags < ::Mutations::ContainerRepositories::DestroyBase
- LIMIT = 20
+ graphql_name 'DestroyContainerRepositoryTags'
+ LIMIT = 20
TOO_MANY_TAGS_ERROR_MESSAGE = "Number of tags is greater than #{LIMIT}"
- graphql_name 'DestroyContainerRepositoryTags'
-
authorize :destroy_container_image
argument :id,
diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb
index ad392d6c814..269ea6c9999 100644
--- a/app/graphql/mutations/custom_emoji/create.rb
+++ b/app/graphql/mutations/custom_emoji/create.rb
@@ -3,10 +3,10 @@
module Mutations
module CustomEmoji
class Create < BaseMutation
- include Mutations::ResolvesGroup
-
graphql_name 'CreateCustomEmoji'
+ include Mutations::ResolvesGroup
+
authorize :create_custom_emoji
field :custom_emoji,
diff --git a/app/graphql/mutations/customer_relations/contacts/create.rb b/app/graphql/mutations/customer_relations/contacts/create.rb
index 3495f30f227..96dc047c3db 100644
--- a/app/graphql/mutations/customer_relations/contacts/create.rb
+++ b/app/graphql/mutations/customer_relations/contacts/create.rb
@@ -4,11 +4,11 @@ module Mutations
module CustomerRelations
module Contacts
class Create < BaseMutation
+ graphql_name 'CustomerRelationsContactCreate'
+
include ResolvesIds
include Gitlab::Graphql::Authorize::AuthorizeResource
- graphql_name 'CustomerRelationsContactCreate'
-
field :contact,
Types::CustomerRelations::ContactType,
null: true,
diff --git a/app/graphql/mutations/customer_relations/contacts/update.rb b/app/graphql/mutations/customer_relations/contacts/update.rb
index e2f671058f0..a3abf37f21f 100644
--- a/app/graphql/mutations/customer_relations/contacts/update.rb
+++ b/app/graphql/mutations/customer_relations/contacts/update.rb
@@ -4,10 +4,10 @@ module Mutations
module CustomerRelations
module Contacts
class Update < Mutations::BaseMutation
- include ResolvesIds
-
graphql_name 'CustomerRelationsContactUpdate'
+ include ResolvesIds
+
authorize :admin_crm_contact
field :contact,
diff --git a/app/graphql/mutations/customer_relations/organizations/create.rb b/app/graphql/mutations/customer_relations/organizations/create.rb
index 17e0e9ad459..43c50a9fb30 100644
--- a/app/graphql/mutations/customer_relations/organizations/create.rb
+++ b/app/graphql/mutations/customer_relations/organizations/create.rb
@@ -4,11 +4,11 @@ module Mutations
module CustomerRelations
module Organizations
class Create < BaseMutation
+ graphql_name 'CustomerRelationsOrganizationCreate'
+
include ResolvesIds
include Gitlab::Graphql::Authorize::AuthorizeResource
- graphql_name 'CustomerRelationsOrganizationCreate'
-
field :organization,
Types::CustomerRelations::OrganizationType,
null: true,
diff --git a/app/graphql/mutations/customer_relations/organizations/update.rb b/app/graphql/mutations/customer_relations/organizations/update.rb
index 21fcf565239..0c05541dbd7 100644
--- a/app/graphql/mutations/customer_relations/organizations/update.rb
+++ b/app/graphql/mutations/customer_relations/organizations/update.rb
@@ -4,10 +4,10 @@ module Mutations
module CustomerRelations
module Organizations
class Update < Mutations::BaseMutation
- include ResolvesIds
-
graphql_name 'CustomerRelationsOrganizationUpdate'
+ include ResolvesIds
+
authorize :admin_crm_organization
field :organization,
diff --git a/app/graphql/mutations/dependency_proxy/group_settings/update.rb b/app/graphql/mutations/dependency_proxy/group_settings/update.rb
index d10e43cde29..65c919db3c3 100644
--- a/app/graphql/mutations/dependency_proxy/group_settings/update.rb
+++ b/app/graphql/mutations/dependency_proxy/group_settings/update.rb
@@ -4,10 +4,10 @@ module Mutations
module DependencyProxy
module GroupSettings
class Update < Mutations::BaseMutation
- include Mutations::ResolvesGroup
-
graphql_name 'UpdateDependencyProxySettings'
+ include Mutations::ResolvesGroup
+
authorize :admin_dependency_proxy
argument :group_path,
diff --git a/app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb b/app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb
index a5eb114b2da..79d7a93c4e2 100644
--- a/app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb
+++ b/app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb
@@ -4,10 +4,10 @@ module Mutations
module DependencyProxy
module ImageTtlGroupPolicy
class Update < Mutations::BaseMutation
- include Mutations::ResolvesGroup
-
graphql_name 'UpdateDependencyProxyImageTtlGroupPolicy'
+ include Mutations::ResolvesGroup
+
authorize :admin_dependency_proxy
argument :group_path,
diff --git a/app/graphql/mutations/design_management/delete.rb b/app/graphql/mutations/design_management/delete.rb
index 4e9f0aad934..9e643110628 100644
--- a/app/graphql/mutations/design_management/delete.rb
+++ b/app/graphql/mutations/design_management/delete.rb
@@ -3,10 +3,10 @@
module Mutations
module DesignManagement
class Delete < Base
- Errors = ::Gitlab::Graphql::Errors
-
graphql_name "DesignManagementDelete"
+ Errors = ::Gitlab::Graphql::Errors
+
argument :filenames, [GraphQL::Types::String],
required: true,
description: "Filenames of the designs to delete.",
diff --git a/app/graphql/mutations/groups/update.rb b/app/graphql/mutations/groups/update.rb
index 9c5628a57cd..be7a14d0b43 100644
--- a/app/graphql/mutations/groups/update.rb
+++ b/app/graphql/mutations/groups/update.rb
@@ -3,10 +3,10 @@
module Mutations
module Groups
class Update < Mutations::BaseMutation
- include Mutations::ResolvesGroup
-
graphql_name 'GroupUpdate'
+ include Mutations::ResolvesGroup
+
authorize :admin_group
field :group, Types::GroupType,
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 72b03cc27c2..6bf8caf82d7 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -3,12 +3,12 @@
module Mutations
module Issues
class Create < BaseMutation
+ graphql_name 'CreateIssue'
+
include Mutations::SpamProtection
include FindsProject
include CommonMutationArguments
- graphql_name 'CreateIssue'
-
authorize :create_issue
argument :project_path, GraphQL::Types::ID,
@@ -51,6 +51,14 @@ module Mutations
required: false,
description: 'Array of user IDs to assign to the issue.'
+ argument :move_before_id, ::Types::GlobalIDType[::Issue],
+ required: false,
+ description: 'Global ID of issue that should be placed before the current issue.'
+
+ argument :move_after_id, ::Types::GlobalIDType[::Issue],
+ required: false,
+ description: 'Global ID of issue that should be placed after the current issue.'
+
field :issue,
Types::IssueType,
null: true,
@@ -93,6 +101,13 @@ module Mutations
params[:assignee_ids] &&= params[:assignee_ids].map { |assignee_id| assignee_id&.model_id }
params[:label_ids] &&= params[:label_ids].map { |label_id| label_id&.model_id }
+ if params[:move_before_id].present? || params[:move_after_id].present?
+ params[:move_between_ids] = [
+ params.delete(:move_before_id)&.model_id,
+ params.delete(:move_after_id)&.model_id
+ ]
+ end
+
params
end
diff --git a/app/graphql/mutations/issues/set_confidential.rb b/app/graphql/mutations/issues/set_confidential.rb
index 35e629ddc90..abfd6fec0bd 100644
--- a/app/graphql/mutations/issues/set_confidential.rb
+++ b/app/graphql/mutations/issues/set_confidential.rb
@@ -3,10 +3,10 @@
module Mutations
module Issues
class SetConfidential < Base
- include Mutations::SpamProtection
-
graphql_name 'IssueSetConfidential'
+ include Mutations::SpamProtection
+
argument :confidential,
GraphQL::Types::Boolean,
required: true,
diff --git a/app/graphql/mutations/issues/set_escalation_status.rb b/app/graphql/mutations/issues/set_escalation_status.rb
index 6073b73277b..4f3fcb4886d 100644
--- a/app/graphql/mutations/issues/set_escalation_status.rb
+++ b/app/graphql/mutations/issues/set_escalation_status.rb
@@ -14,7 +14,7 @@ module Mutations
project = issue.project
authorize_escalation_status!(project)
- check_feature_availability!(project, issue)
+ check_feature_availability!(issue)
::Issues::UpdateService.new(
project: project,
@@ -36,8 +36,8 @@ module Mutations
raise_resource_not_available_error!
end
- def check_feature_availability!(project, issue)
- return if Feature.enabled?(:incident_escalations, project) && issue.supports_escalation?
+ def check_feature_availability!(issue)
+ return if issue.supports_escalation?
raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature unavailable for provided issue'
end
diff --git a/app/graphql/mutations/jira_import/import_users.rb b/app/graphql/mutations/jira_import/import_users.rb
index 8d82a058dd0..b3874caee61 100644
--- a/app/graphql/mutations/jira_import/import_users.rb
+++ b/app/graphql/mutations/jira_import/import_users.rb
@@ -3,10 +3,10 @@
module Mutations
module JiraImport
class ImportUsers < BaseMutation
- include FindsProject
-
graphql_name 'JiraImportUsers'
+ include FindsProject
+
authorize :admin_project
field :jira_users,
diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb
index 4929d6f394a..ea071c45bcf 100644
--- a/app/graphql/mutations/jira_import/start.rb
+++ b/app/graphql/mutations/jira_import/start.rb
@@ -3,10 +3,10 @@
module Mutations
module JiraImport
class Start < BaseMutation
- include FindsProject
-
graphql_name 'JiraImportStart'
+ include FindsProject
+
authorize :admin_project
field :jira_import,
diff --git a/app/graphql/mutations/labels/create.rb b/app/graphql/mutations/labels/create.rb
index cb3ba7939ae..3cd41dc01de 100644
--- a/app/graphql/mutations/labels/create.rb
+++ b/app/graphql/mutations/labels/create.rb
@@ -3,10 +3,10 @@
module Mutations
module Labels
class Create < BaseMutation
- include Mutations::ResolvesResourceParent
-
graphql_name 'LabelCreate'
+ include Mutations::ResolvesResourceParent
+
field :label,
Types::LabelType,
null: true,
diff --git a/app/graphql/mutations/merge_requests/accept.rb b/app/graphql/mutations/merge_requests/accept.rb
index 7ce850901af..ebd9e2b8fdd 100644
--- a/app/graphql/mutations/merge_requests/accept.rb
+++ b/app/graphql/mutations/merge_requests/accept.rb
@@ -3,12 +3,6 @@
module Mutations
module MergeRequests
class Accept < Base
- NOT_MERGEABLE = 'This branch cannot be merged'
- HOOKS_VALIDATION_ERROR = 'Pre-merge hooks failed'
- SHA_MISMATCH = 'The merge-head is not at the anticipated SHA'
- MERGE_FAILED = 'The merge failed'
- ALREADY_SCHEDULED = 'The merge request is already scheduled to be merged'
-
graphql_name 'MergeRequestAccept'
authorize :accept_merge_request
description <<~DESC
@@ -17,6 +11,12 @@ module Mutations
immediately if possible, or using one of the automatic merge strategies.
DESC
+ NOT_MERGEABLE = 'This branch cannot be merged'
+ HOOKS_VALIDATION_ERROR = 'Pre-merge hooks failed'
+ SHA_MISMATCH = 'The merge-head is not at the anticipated SHA'
+ MERGE_FAILED = 'The merge failed'
+ ALREADY_SCHEDULED = 'The merge request is already scheduled to be merged'
+
argument :strategy,
::Types::MergeStrategyEnum,
required: false,
diff --git a/app/graphql/mutations/merge_requests/create.rb b/app/graphql/mutations/merge_requests/create.rb
index dc1d5a22bc9..2883c02a671 100644
--- a/app/graphql/mutations/merge_requests/create.rb
+++ b/app/graphql/mutations/merge_requests/create.rb
@@ -3,10 +3,10 @@
module Mutations
module MergeRequests
class Create < BaseMutation
- include FindsProject
-
graphql_name 'MergeRequestCreate'
+ include FindsProject
+
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project full path the merge request is associated with.'
diff --git a/app/graphql/mutations/namespace/package_settings/update.rb b/app/graphql/mutations/namespace/package_settings/update.rb
index 400169d6b64..934b75193d7 100644
--- a/app/graphql/mutations/namespace/package_settings/update.rb
+++ b/app/graphql/mutations/namespace/package_settings/update.rb
@@ -4,10 +4,10 @@ module Mutations
module Namespace
module PackageSettings
class Update < Mutations::BaseMutation
- include Mutations::ResolvesNamespace
-
graphql_name 'UpdateNamespacePackageSettings'
+ include Mutations::ResolvesNamespace
+
authorize :create_package_settings
argument :namespace_path,
diff --git a/app/graphql/mutations/release_asset_links/create.rb b/app/graphql/mutations/release_asset_links/create.rb
index db486640507..f6445514ce9 100644
--- a/app/graphql/mutations/release_asset_links/create.rb
+++ b/app/graphql/mutations/release_asset_links/create.rb
@@ -3,14 +3,13 @@
module Mutations
module ReleaseAssetLinks
class Create < BaseMutation
- include FindsProject
-
graphql_name 'ReleaseAssetLinkCreate'
- authorize :create_release
-
+ include FindsProject
include Types::ReleaseAssetLinkSharedInputArguments
+ authorize :create_release
+
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Full path of the project the asset link is associated with.'
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index c01b0e4a01b..2921a77b86d 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -3,14 +3,13 @@
module Mutations
module Snippets
class Create < BaseMutation
+ graphql_name 'CreateSnippet'
+
include ServiceCompatibility
- include CanMutateSpammable
include Mutations::SpamProtection
authorize :create_snippet
- graphql_name 'CreateSnippet'
-
field :snippet,
Types::SnippetType,
null: true,
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 9ecaa8d4bf2..2a2941c5328 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -3,12 +3,11 @@
module Mutations
module Snippets
class Update < Base
+ graphql_name 'UpdateSnippet'
+
include ServiceCompatibility
- include CanMutateSpammable
include Mutations::SpamProtection
- graphql_name 'UpdateSnippet'
-
argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'Global ID of the snippet to update.'
diff --git a/app/graphql/mutations/user_preferences/update.rb b/app/graphql/mutations/user_preferences/update.rb
new file mode 100644
index 00000000000..c92c6d725b7
--- /dev/null
+++ b/app/graphql/mutations/user_preferences/update.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Mutations
+ module UserPreferences
+ class Update < BaseMutation
+ graphql_name 'UserPreferencesUpdate'
+
+ argument :issues_sort, Types::IssueSortEnum,
+ required: false,
+ description: 'Sort order for issue lists.'
+
+ field :user_preferences,
+ Types::UserPreferencesType,
+ null: true,
+ description: 'User preferences after mutation.'
+
+ def resolve(**attributes)
+ user_preferences = current_user.user_preference
+ user_preferences.update(attributes)
+
+ {
+ user_preferences: user_preferences.valid? ? user_preferences : nil,
+ errors: errors_on_object(user_preferences)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb
index 88b8cefd8d2..81454db62b1 100644
--- a/app/graphql/mutations/work_items/create.rb
+++ b/app/graphql/mutations/work_items/create.rb
@@ -3,10 +3,13 @@
module Mutations
module WorkItems
class Create < BaseMutation
+ graphql_name 'WorkItemCreate'
+
include Mutations::SpamProtection
include FindsProject
- graphql_name 'WorkItemCreate'
+ description "Creates a work item." \
+ " Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice."
authorize :create_work_item
@@ -29,16 +32,21 @@ module Mutations
def resolve(project_path:, **attributes)
project = authorized_find!(project_path)
+
+ unless Feature.enabled?(:work_items, project)
+ return { errors: ['`work_items` feature flag disabled for this project'] }
+ end
+
params = global_id_compatibility_params(attributes).merge(author_id: current_user.id)
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
- work_item = ::WorkItems::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
+ create_result = ::WorkItems::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
- check_spam_action_response!(work_item)
+ check_spam_action_response!(create_result[:work_item]) if create_result[:work_item]
{
- work_item: work_item.valid? ? work_item : nil,
- errors: errors_on_object(work_item)
+ work_item: create_result.success? ? create_result[:work_item] : nil,
+ errors: create_result.errors
}
end
diff --git a/app/graphql/mutations/work_items/delete.rb b/app/graphql/mutations/work_items/delete.rb
new file mode 100644
index 00000000000..71792a802c0
--- /dev/null
+++ b/app/graphql/mutations/work_items/delete.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Mutations
+ module WorkItems
+ class Delete < BaseMutation
+ graphql_name 'WorkItemDelete'
+ description "Deletes a work item." \
+ " Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice."
+
+ authorize :delete_work_item
+
+ argument :id, ::Types::GlobalIDType[::WorkItem],
+ required: true,
+ description: 'Global ID of the work item.'
+
+ field :project, Types::ProjectType,
+ null: true,
+ description: 'Project the deleted work item belonged to.'
+
+ def resolve(id:)
+ work_item = authorized_find!(id: id)
+
+ unless Feature.enabled?(:work_items, work_item.project)
+ return { errors: ['`work_items` feature flag disabled for this project'] }
+ end
+
+ result = ::WorkItems::DeleteService.new(
+ project: work_item.project,
+ current_user: current_user
+ ).execute(work_item)
+
+ {
+ project: result.success? ? work_item.project : nil,
+ errors: result.errors
+ }
+ end
+
+ private
+
+ def find_object(id:)
+ # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb
new file mode 100644
index 00000000000..3ab9ba2d502
--- /dev/null
+++ b/app/graphql/mutations/work_items/update.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Mutations
+ module WorkItems
+ class Update < BaseMutation
+ graphql_name 'WorkItemUpdate'
+ description "Updates a work item by Global ID." \
+ " Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice."
+
+ include Mutations::SpamProtection
+
+ authorize :update_work_item
+
+ argument :id, ::Types::GlobalIDType[::WorkItem],
+ required: true,
+ description: 'Global ID of the work item.'
+ argument :state_event, Types::WorkItems::StateEventEnum,
+ description: 'Close or reopen a work item.',
+ required: false
+ argument :title, GraphQL::Types::String,
+ required: false,
+ description: copy_field_description(Types::WorkItemType, :title)
+
+ field :work_item, Types::WorkItemType,
+ null: true,
+ description: 'Updated work item.'
+
+ def resolve(id:, **attributes)
+ work_item = authorized_find!(id: id)
+
+ unless Feature.enabled?(:work_items, work_item.project)
+ return { errors: ['`work_items` feature flag disabled for this project'] }
+ end
+
+ spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
+
+ ::WorkItems::UpdateService.new(
+ project: work_item.project,
+ current_user: current_user,
+ params: attributes,
+ spam_params: spam_params
+ ).execute(work_item)
+
+ check_spam_action_response!(work_item)
+
+ {
+ work_item: work_item.valid? ? work_item : nil,
+ errors: errors_on_object(work_item)
+ }
+ end
+
+ private
+
+ def find_object(id:)
+ # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
index 5dece2f81cc..f4921706f7e 100644
--- a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
+++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
@@ -120,6 +120,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
hasDetails
detailsPath
group
+ label
action {
__typename
id
diff --git a/app/graphql/resolvers/ci/project_pipeline_counts_resolver.rb b/app/graphql/resolvers/ci/project_pipeline_counts_resolver.rb
new file mode 100644
index 00000000000..728bc9627c5
--- /dev/null
+++ b/app/graphql/resolvers/ci/project_pipeline_counts_resolver.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class ProjectPipelineCountsResolver < BaseResolver
+ type Types::Ci::PipelineCountsType, null: true
+
+ argument :ref,
+ GraphQL::Types::String,
+ required: false,
+ description: "Filter pipelines by the ref they are run for."
+
+ argument :sha,
+ GraphQL::Types::String,
+ required: false,
+ description: "Filter pipelines by the SHA of the commit they are run for."
+
+ argument :source,
+ GraphQL::Types::String,
+ required: false,
+ description: "Filter pipelines by their source."
+
+ def resolve(**args)
+ ::Gitlab::PipelineScopeCounts.new(context[:current_user], object, args)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runner_jobs_resolver.rb b/app/graphql/resolvers/ci/runner_jobs_resolver.rb
new file mode 100644
index 00000000000..2f6ca09d031
--- /dev/null
+++ b/app/graphql/resolvers/ci/runner_jobs_resolver.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class RunnerJobsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include LooksAhead
+
+ type ::Types::Ci::JobType.connection_type, null: true
+ authorize :read_builds
+ authorizes_object!
+
+ argument :statuses, [::Types::Ci::JobStatusEnum],
+ required: false,
+ description: 'Filter jobs by status.'
+
+ alias_method :runner, :object
+
+ def ready?(**args)
+ context[self.class] ||= { executions: 0 }
+ context[self.class][:executions] += 1
+
+ raise GraphQL::ExecutionError, "Jobs can be requested for only one runner at a time" if context[self.class][:executions] > 1
+
+ super
+ end
+
+ def resolve_with_lookahead(statuses: nil)
+ jobs = ::Ci::JobsFinder.new(current_user: current_user, runner: runner, params: { scope: statuses }).execute
+
+ apply_lookahead(jobs)
+ end
+
+ private
+
+ def preloads
+ {
+ previous_stage_jobs_and_needs: [:needs, :pipeline],
+ artifacts: [:job_artifacts],
+ pipeline: [:user]
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 9848b5a503f..e221dfea4d0 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -9,7 +9,12 @@ module Resolvers
argument :active, ::GraphQL::Types::Boolean,
required: false,
- description: 'Filter runners by active (true) or paused (false) status.'
+ description: 'Filter runners by `active` (true) or `paused` (false) status.',
+ deprecated: { reason: :renamed, replacement: 'paused', milestone: '14.8' }
+
+ argument :paused, ::GraphQL::Types::Boolean,
+ required: false,
+ description: 'Filter runners by `paused` (true) or `active` (false) status.'
argument :status, ::Types::Ci::RunnerStatusEnum,
required: false,
@@ -41,8 +46,11 @@ module Resolvers
protected
def runners_finder_params(params)
+ # Give preference to paused argument over the deprecated 'active' argument
+ paused = params.fetch(:paused, params[:active] ? !params[:active] : nil)
+
{
- active: params[:active],
+ active: paused.nil? ? nil : !paused,
status_status: params[:status]&.to_s,
type_type: params[:type],
tag_name: params[:tag_list],
diff --git a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
index 8208fa56485..722fbab3bb7 100644
--- a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
+++ b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
@@ -25,7 +25,7 @@ module Resolvers
private
def can_read_agent_tokens?
- current_user.can?(:admin_cluster, project)
+ current_user.can?(:read_cluster, project)
end
end
end
diff --git a/app/graphql/resolvers/kas/agent_configurations_resolver.rb b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
index a1b1d3bfe4c..9db104287a6 100644
--- a/app/graphql/resolvers/kas/agent_configurations_resolver.rb
+++ b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
@@ -21,7 +21,7 @@ module Resolvers
private
def can_read_agent_configuration?
- current_user.can?(:admin_cluster, project)
+ current_user.can?(:read_cluster, project)
end
def kas_client
diff --git a/app/graphql/resolvers/kas/agent_connections_resolver.rb b/app/graphql/resolvers/kas/agent_connections_resolver.rb
index 8b7c4003598..cf1a47aac75 100644
--- a/app/graphql/resolvers/kas/agent_connections_resolver.rb
+++ b/app/graphql/resolvers/kas/agent_connections_resolver.rb
@@ -29,7 +29,7 @@ module Resolvers
def get_connected_agents
kas_client.get_connected_agents(project: project)
- rescue GRPC::BadStatus => e
+ rescue GRPC::BadStatus, Gitlab::Kas::Client::ConfigurationError => e
raise Gitlab::Graphql::Errors::ResourceNotAvailable, e.class.name
end
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index 6dbcbe0e04d..72372ae6b42 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -55,6 +55,19 @@ module Resolvers
required: false,
description: 'Limit result to draft merge requests.'
+ argument :created_after, Types::TimeType,
+ required: false,
+ description: 'Merge requests created after this timestamp.'
+ argument :created_before, Types::TimeType,
+ required: false,
+ description: 'Merge requests created before this timestamp.'
+ argument :updated_after, Types::TimeType,
+ required: false,
+ description: 'Merge requests updated after this timestamp.'
+ argument :updated_before, Types::TimeType,
+ required: false,
+ description: 'Merge requests updated before this timestamp.'
+
argument :labels, [GraphQL::Types::String],
required: false,
as: :label_name,
@@ -72,12 +85,6 @@ module Resolvers
description: 'Sort merge requests by this criteria.',
required: false,
default_value: :created_desc
- argument :created_after, Types::TimeType,
- required: false,
- description: 'Merge requests created after this timestamp.'
- argument :created_before, Types::TimeType,
- required: false,
- description: 'Merge requests created before this timestamp.'
negated do
argument :labels, [GraphQL::Types::String],
diff --git a/app/graphql/resolvers/paginated_tree_resolver.rb b/app/graphql/resolvers/paginated_tree_resolver.rb
index 6c0545d26de..d29d87ca204 100644
--- a/app/graphql/resolvers/paginated_tree_resolver.rb
+++ b/app/graphql/resolvers/paginated_tree_resolver.rb
@@ -11,14 +11,14 @@ module Resolvers
required: false,
default_value: '', # root of the repository
description: 'Path to get the tree for. Default value is the root of the repository.'
- argument :ref, GraphQL::Types::String,
- required: false,
- default_value: :head,
- description: 'Commit ref to get the tree for. Default value is HEAD.'
argument :recursive, GraphQL::Types::Boolean,
required: false,
default_value: false,
description: 'Used to get a recursive tree. Default is false.'
+ argument :ref, GraphQL::Types::String,
+ required: false,
+ default_value: :head,
+ description: 'Commit ref to get the tree for. Default value is HEAD.'
alias_method :repository, :object
diff --git a/app/graphql/resolvers/project_jobs_resolver.rb b/app/graphql/resolvers/project_jobs_resolver.rb
index 8a2693ee46b..b09158d475d 100644
--- a/app/graphql/resolvers/project_jobs_resolver.rb
+++ b/app/graphql/resolvers/project_jobs_resolver.rb
@@ -18,7 +18,8 @@ module Resolvers
def ready?(**args)
context[self.class] ||= { executions: 0 }
context[self.class][:executions] += 1
- raise GraphQL::ExecutionError, "Jobs can only be requested for one project at a time" if context[self.class][:executions] > 1
+
+ raise GraphQL::ExecutionError, "Jobs can be requested for only one project at a time" if context[self.class][:executions] > 1
super
end
diff --git a/app/graphql/resolvers/recent_boards_resolver.rb b/app/graphql/resolvers/recent_boards_resolver.rb
new file mode 100644
index 00000000000..4de5b8f072b
--- /dev/null
+++ b/app/graphql/resolvers/recent_boards_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class RecentBoardsResolver < BaseResolver
+ type Types::BoardType, null: true
+
+ def resolve
+ parent = object.respond_to?(:sync) ? object.sync : object
+ return Board.none unless parent
+
+ recent_visits =
+ ::Boards::VisitsFinder.new(parent, current_user).latest(Board::RECENT_BOARDS_SIZE)
+
+ recent_visits&.map(&:board) || []
+ end
+ end
+end
diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb
index 8d6ece0956e..f02eb226810 100644
--- a/app/graphql/resolvers/tree_resolver.rb
+++ b/app/graphql/resolvers/tree_resolver.rb
@@ -10,14 +10,14 @@ module Resolvers
required: false,
default_value: '',
description: 'Path to get the tree for. Default value is the root of the repository.'
- argument :ref, GraphQL::Types::String,
- required: false,
- default_value: :head,
- description: 'Commit ref to get the tree for. Default value is HEAD.'
argument :recursive, GraphQL::Types::Boolean,
required: false,
default_value: false,
description: 'Used to get a recursive tree. Default is false.'
+ argument :ref, GraphQL::Types::String,
+ required: false,
+ default_value: :head,
+ description: 'Commit ref to get the tree for. Default value is HEAD.'
alias_method :repository, :object
diff --git a/app/graphql/resolvers/users/groups_resolver.rb b/app/graphql/resolvers/users/groups_resolver.rb
index d8492a8fcf9..09c6b51cc3d 100644
--- a/app/graphql/resolvers/users/groups_resolver.rb
+++ b/app/graphql/resolvers/users/groups_resolver.rb
@@ -11,13 +11,13 @@ module Resolvers
authorize :read_user_groups
authorizes_object!
- argument :search, GraphQL::Types::String,
- required: false,
- description: 'Search by group name or path.'
argument :permission_scope,
::Types::PermissionTypes::GroupEnum,
required: false,
description: 'Filter by permissions the user has on groups.'
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search by group name or path.'
before_connection_authorization do |nodes, current_user|
Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute
diff --git a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
index 8276549ddcc..1fc47303d67 100644
--- a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
+++ b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
@@ -5,10 +5,11 @@ module Types
module Analytics
module UsageTrends
class MeasurementType < BaseObject
- include Gitlab::Graphql::Authorize::AuthorizeResource
graphql_name 'UsageTrendsMeasurement'
description 'Represents a recorded measurement (object count) for the Admins'
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
authorize :read_usage_trends_measurement
field :recorded_at, Types::TimeType, null: true,
diff --git a/app/graphql/types/alert_management/prometheus_integration_type.rb b/app/graphql/types/alert_management/prometheus_integration_type.rb
index 27e4832d8f6..9a2ef78eca7 100644
--- a/app/graphql/types/alert_management/prometheus_integration_type.rb
+++ b/app/graphql/types/alert_management/prometheus_integration_type.rb
@@ -3,11 +3,11 @@
module Types
module AlertManagement
class PrometheusIntegrationType < ::Types::BaseObject
- include ::Gitlab::Routing
-
graphql_name 'AlertManagementPrometheusIntegration'
description 'An endpoint and credentials used to accept Prometheus alerts for a project'
+ include ::Gitlab::Routing
+
implements(Types::AlertManagement::IntegrationType)
authorize :admin_project
diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb
index 8c67803e39e..733006369ea 100644
--- a/app/graphql/types/board_list_type.rb
+++ b/app/graphql/types/board_list_type.rb
@@ -3,11 +3,11 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class BoardListType < BaseObject
- include Gitlab::Utils::StrongMemoize
-
graphql_name 'BoardList'
description 'Represents a list for an issue board'
+ include Gitlab::Utils::StrongMemoize
+
alias_method :list, :object
field :id, GraphQL::Types::ID,
diff --git a/app/graphql/types/ci/pipeline_counts_type.rb b/app/graphql/types/ci/pipeline_counts_type.rb
new file mode 100644
index 00000000000..9c2b822091e
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_counts_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineCountsType < BaseObject
+ graphql_name 'PipelineCounts'
+ description "Represents pipeline counts for the project"
+
+ authorize :read_pipeline
+
+ (::Types::Ci::PipelineScopeEnum.values.keys - %w[BRANCHES TAGS]).each do |scope|
+ field scope.downcase,
+ GraphQL::Types::Int,
+ null: true,
+ description: "Number of pipelines with scope #{scope} for the project"
+ end
+
+ field :all,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of pipelines for the project.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/runner_sort_enum.rb b/app/graphql/types/ci/runner_sort_enum.rb
index 95ec1867fea..8f2a13bd699 100644
--- a/app/graphql/types/ci/runner_sort_enum.rb
+++ b/app/graphql/types/ci/runner_sort_enum.rb
@@ -10,6 +10,8 @@ module Types
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
+ value 'TOKEN_EXPIRES_AT_ASC', 'Ordered by token_expires_at in ascending order.', value: :token_expires_at_asc
+ value 'TOKEN_EXPIRES_AT_DESC', 'Ordered by token_expires_at in descending order.', value: :token_expires_at_desc
end
end
end
diff --git a/app/graphql/types/ci/runner_status_enum.rb b/app/graphql/types/ci/runner_status_enum.rb
index dd056191ceb..2e65e2d4e1e 100644
--- a/app/graphql/types/ci/runner_status_enum.rb
+++ b/app/graphql/types/ci/runner_status_enum.rb
@@ -7,12 +7,20 @@ module Types
value 'ACTIVE',
description: 'Runner that is not paused.',
- deprecated: { reason: 'Use CiRunnerType.active instead', milestone: '14.6' },
+ deprecated: {
+ reason: :renamed,
+ replacement: 'CiRunner.paused',
+ milestone: '14.6'
+ },
value: :active
value 'PAUSED',
description: 'Runner that is paused.',
- deprecated: { reason: 'Use CiRunnerType.active instead', milestone: '14.6' },
+ deprecated: {
+ reason: :renamed,
+ replacement: 'CiRunner.paused',
+ milestone: '14.6'
+ },
value: :paused
value 'ONLINE',
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index 4fe65734911..9094c6b96e4 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -3,12 +3,13 @@
module Types
module Ci
class RunnerType < BaseObject
+ graphql_name 'CiRunner'
+
edge_type_class(RunnerWebUrlEdge)
connection_type_class(Types::CountableConnectionType)
- graphql_name 'CiRunner'
+
authorize :read_runner
present_using ::Ci::RunnerPresenter
-
expose_permissions Types::PermissionTypes::Ci::Runner
JOB_COUNT_LIMIT = 1000
@@ -24,12 +25,18 @@ module Types
field :contacted_at, Types::TimeType, null: true,
description: 'Timestamp of last contact from this runner.',
method: :contacted_at
+ field :token_expires_at, Types::TimeType, null: true,
+ description: 'Runner token expiration time.',
+ method: :token_expires_at
field :maximum_timeout, GraphQL::Types::Int, null: true,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false,
description: 'Access level of the runner.'
field :active, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the runner is allowed to receive jobs.'
+ description: 'Indicates the runner is allowed to receive jobs.',
+ deprecated: { reason: 'Use paused', milestone: '14.8' }
+ field :paused, GraphQL::Types::Boolean, null: false,
+ description: 'Indicates the runner is paused and not available to run jobs.'
field :status,
Types::Ci::RunnerStatusEnum,
null: false,
@@ -63,6 +70,14 @@ module Types
description: 'Executor last advertised by the runner.',
method: :executor_name,
feature_flag: :graphql_ci_runner_executor
+ field :groups, ::Types::GroupType.connection_type, null: true,
+ description: 'Groups the runner is associated with. For group runners only.'
+ field :projects, ::Types::ProjectType.connection_type, null: true,
+ description: 'Projects the runner is associated with. For project runners only.'
+ field :jobs, ::Types::Ci::JobType.connection_type, null: true,
+ description: 'Jobs assigned to the runner.',
+ authorize: :read_builds,
+ resolver: ::Resolvers::Ci::RunnerJobsResolver
def job_count
# We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT
@@ -94,11 +109,40 @@ module Types
end
# rubocop: enable CodeReuse/ActiveRecord
+ def groups
+ return unless runner.group_type?
+
+ batched_owners(::Ci::RunnerNamespace, Group, :runner_groups, :namespace_id)
+ end
+
+ def projects
+ return unless runner.project_type?
+
+ batched_owners(::Ci::RunnerProject, Project, :runner_projects, :project_id)
+ end
+
private
def can_admin_runners?
context[:current_user]&.can_admin_all_resources?
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def batched_owners(runner_assoc_type, assoc_type, key, column_name)
+ BatchLoader::GraphQL.for(runner.id).batch(key: key) do |runner_ids, loader, args|
+ runner_and_owner_ids = runner_assoc_type.where(runner_id: runner_ids).pluck(:runner_id, column_name)
+
+ owner_ids_by_runner_id = runner_and_owner_ids.group_by(&:first).transform_values { |v| v.pluck(1) }
+ owner_ids = runner_and_owner_ids.pluck(1).uniq
+
+ owners = assoc_type.where(id: owner_ids).index_by(&:id)
+
+ runner_ids.each do |runner_id|
+ loader.call(runner_id, owner_ids_by_runner_id[runner_id]&.map { |owner_id| owners[owner_id] } || [])
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/app/graphql/types/clusters/agent_activity_event_type.rb b/app/graphql/types/clusters/agent_activity_event_type.rb
index 79a9fd70505..3484acfe25e 100644
--- a/app/graphql/types/clusters/agent_activity_event_type.rb
+++ b/app/graphql/types/clusters/agent_activity_event_type.rb
@@ -5,7 +5,7 @@ module Types
class AgentActivityEventType < BaseObject
graphql_name 'ClusterAgentActivityEvent'
- authorize :admin_cluster
+ authorize :read_cluster
connection_type_class(Types::CountableConnectionType)
diff --git a/app/graphql/types/clusters/agent_token_type.rb b/app/graphql/types/clusters/agent_token_type.rb
index 96fdb5f05c8..24489707698 100644
--- a/app/graphql/types/clusters/agent_token_type.rb
+++ b/app/graphql/types/clusters/agent_token_type.rb
@@ -5,7 +5,7 @@ module Types
class AgentTokenType < BaseObject
graphql_name 'ClusterAgentToken'
- authorize :admin_cluster
+ authorize :read_cluster
connection_type_class(Types::CountableConnectionType)
diff --git a/app/graphql/types/clusters/agent_type.rb b/app/graphql/types/clusters/agent_type.rb
index 89316ed4728..546252b2285 100644
--- a/app/graphql/types/clusters/agent_type.rb
+++ b/app/graphql/types/clusters/agent_type.rb
@@ -5,7 +5,7 @@ module Types
class AgentType < BaseObject
graphql_name 'ClusterAgent'
- authorize :admin_cluster
+ authorize :read_cluster
connection_type_class(Types::CountableConnectionType)
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index 2584e15ff0b..8bc00359ccb 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -10,33 +10,37 @@ module Types
field :id, type: GraphQL::Types::ID, null: false,
description: 'ID (global ID) of the commit.'
+
field :sha, type: GraphQL::Types::String, null: false,
description: 'SHA1 ID of the commit.'
+
field :short_id, type: GraphQL::Types::String, null: false,
description: 'Short SHA1 ID of the commit.'
field :title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Title of the commit message.'
- markdown_field :title_html, null: true
field :full_title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Full title of the commit message.'
- markdown_field :full_title_html, null: true
field :description, type: GraphQL::Types::String, null: true,
description: 'Description of the commit message.'
- markdown_field :description_html, null: true
field :message, type: GraphQL::Types::String, null: true,
description: 'Raw commit message.'
+
field :authored_date, type: Types::TimeType, null: true,
description: 'Timestamp of when the commit was authored.'
+
field :web_url, type: GraphQL::Types::String, null: false,
description: 'Web URL of the commit.'
+
field :web_path, type: GraphQL::Types::String, null: false,
description: 'Web path of the commit.'
+
field :signature_html, type: GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Rendered HTML of the commit signature.'
+
field :author_name, type: GraphQL::Types::String, null: true,
description: 'Commit authors name.'
field :author_email, type: GraphQL::Types::String, null: true,
@@ -53,6 +57,10 @@ module Types
description: 'Pipelines of the commit ordered latest first.',
resolver: Resolvers::CommitPipelinesResolver
+ markdown_field :title_html, null: true
+ markdown_field :full_title_html, null: true
+ markdown_field :description_html, null: true
+
def author_gravatar
GravatarService.new.execute(object.author_email, 40)
end
diff --git a/app/graphql/types/group_invitation_type.rb b/app/graphql/types/group_invitation_type.rb
index 9410253553c..48281dcfd9f 100644
--- a/app/graphql/types/group_invitation_type.rb
+++ b/app/graphql/types/group_invitation_type.rb
@@ -2,14 +2,14 @@
module Types
class GroupInvitationType < BaseObject
+ graphql_name 'GroupInvitation'
+ description 'Represents a Group Invitation'
+
expose_permissions Types::PermissionTypes::Group
authorize :admin_group
implements InvitationInterface
- graphql_name 'GroupInvitation'
- description 'Represents a Group Invitation'
-
field :group, Types::GroupType, null: true,
description: 'Group that a User is invited to.'
diff --git a/app/graphql/types/group_member_type.rb b/app/graphql/types/group_member_type.rb
index 8b8e69d795d..d68abc11bba 100644
--- a/app/graphql/types/group_member_type.rb
+++ b/app/graphql/types/group_member_type.rb
@@ -2,14 +2,14 @@
module Types
class GroupMemberType < BaseObject
+ graphql_name 'GroupMember'
+ description 'Represents a Group Membership'
+
expose_permissions Types::PermissionTypes::Group
authorize :read_group
implements MemberInterface
- graphql_name 'GroupMember'
- description 'Represents a Group Membership'
-
field :group, Types::GroupType, null: true,
description: 'Group that a User is a member of.'
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index e02650fd285..5f63aa20953 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -94,6 +94,12 @@ module Types
max_page_size: 2000,
resolver: Resolvers::BoardsResolver
+ field :recent_issue_boards,
+ Types::BoardType.connection_type,
+ null: true,
+ description: 'List of recently visited boards of the group. Maximum size is 4.',
+ resolver: Resolvers::RecentBoardsResolver
+
field :board,
Types::BoardType,
null: true,
@@ -170,15 +176,6 @@ module Types
null: true,
description: 'Dependency proxy TTL policy for the group.'
- def label(title:)
- BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
- LabelsFinder
- .new(current_user, group: args[:key], title: titles)
- .execute
- .each { |label| loader.call(label.title, label) }
- end
- end
-
field :labels,
Types::LabelType.connection_type,
null: true,
@@ -215,6 +212,15 @@ module Types
description: 'Work item types available to the group.',
feature_flag: :work_items
+ def label(title:)
+ BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
+ LabelsFinder
+ .new(current_user, group: args[:key], title: titles)
+ .execute
+ .each { |label| loader.call(label.title, label) }
+ end
+ end
+
def avatar_url
object.avatar_url(only_path: false)
end
diff --git a/app/graphql/types/issuable_type.rb b/app/graphql/types/issuable_type.rb
index 6ca74087f8a..4a39b5ed6ec 100644
--- a/app/graphql/types/issuable_type.rb
+++ b/app/graphql/types/issuable_type.rb
@@ -5,10 +5,12 @@ module Types
graphql_name 'Issuable'
description 'Represents an issuable.'
- possible_types Types::IssueType, Types::MergeRequestType
+ possible_types Types::IssueType, Types::MergeRequestType, Types::WorkItemType
def self.resolve_type(object, context)
case object
+ when WorkItem
+ Types::WorkItemType
when Issue
Types::IssueType
when MergeRequest
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 46fe91feae4..ee57961ee4a 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -21,10 +21,8 @@ module Types
description: "Internal ID of the issue."
field :title, GraphQL::Types::String, null: false,
description: 'Title of the issue.'
- markdown_field :title_html, null: true
field :description, GraphQL::Types::String, null: true,
description: 'Description of the issue.'
- markdown_field :description_html, null: true
field :state, IssueStateEnum, null: false,
description: 'State of the issue.'
@@ -143,6 +141,9 @@ module Types
field :escalation_status, Types::IncidentManagement::EscalationStatusEnum, null: true,
description: 'Escalation status of the issue.'
+ markdown_field :title_html, null: true
+ markdown_field :description_html, null: true
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
@@ -168,13 +169,11 @@ module Types
end
def hidden?
- object.hidden? if Feature.enabled?(:ban_user_feature_flag)
+ object.hidden? if Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
end
def escalation_status
- return unless Feature.enabled?(:incident_escalations, object.project) && object.supports_escalation?
-
- object.escalation_status&.status_name
+ object.supports_escalation? ? object.escalation_status&.status_name : nil
end
end
end
diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb
index bb2d561014e..5a10bcfee74 100644
--- a/app/graphql/types/label_type.rb
+++ b/app/graphql/types/label_type.rb
@@ -12,7 +12,6 @@ module Types
description: 'Label ID.'
field :description, GraphQL::Types::String, null: true,
description: 'Description of the label (Markdown rendered as HTML for caching).'
- markdown_field :description_html, null: true
field :title, GraphQL::Types::String, null: false,
description: 'Content of the label.'
field :color, GraphQL::Types::String, null: false,
@@ -23,5 +22,7 @@ module Types
description: 'When this label was created.'
field :updated_at, Types::TimeType, null: false,
description: 'When this label was last updated.'
+
+ markdown_field :description_html, null: true
end
end
diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb
index c5623cd4710..67d0e18b522 100644
--- a/app/graphql/types/member_interface.rb
+++ b/app/graphql/types/member_interface.rb
@@ -25,6 +25,12 @@ module Types
field :user, Types::UserType, null: true,
description: 'User that is associated with the member object.'
+ field :merge_request_interaction, Types::UserMergeRequestInteractionType,
+ null: true,
+ description: 'Find a merge request.' do
+ argument :id, ::Types::GlobalIDType[::MergeRequest], required: true, description: 'Global ID of the merge request.'
+ end
+
definition_methods do
def resolve_type(object, context)
case object
@@ -37,5 +43,11 @@ module Types
end
end
end
+
+ def merge_request_interaction(id: nil)
+ Gitlab::Graphql::Lazy.with_value(GitlabSchema.object_from_id(id, expected_class: ::MergeRequest)) do |merge_request|
+ Users::MergeRequestInteraction.new(user: object.user, merge_request: merge_request) if merge_request
+ end
+ end
end
end
diff --git a/app/graphql/types/merge_request_sort_enum.rb b/app/graphql/types/merge_request_sort_enum.rb
index d75eae6abc4..a74c5a01769 100644
--- a/app/graphql/types/merge_request_sort_enum.rb
+++ b/app/graphql/types/merge_request_sort_enum.rb
@@ -9,5 +9,7 @@ module Types
value 'MERGED_AT_DESC', 'Merge time by descending order.', value: :merged_at_desc
value 'CLOSED_AT_ASC', 'Closed time by ascending order.', value: :closed_at_asc
value 'CLOSED_AT_DESC', 'Closed time by descending order.', value: :closed_at_desc
+ value 'TITLE_ASC', 'Title by ascending order.', value: :title_asc
+ value 'TITLE_DESC', 'Title by descending order.', value: :title_desc
end
end
diff --git a/app/graphql/types/merge_requests/assignee_type.rb b/app/graphql/types/merge_requests/assignee_type.rb
index 8448477370e..24321d057a3 100644
--- a/app/graphql/types/merge_requests/assignee_type.rb
+++ b/app/graphql/types/merge_requests/assignee_type.rb
@@ -3,11 +3,12 @@
module Types
module MergeRequests
class AssigneeType < ::Types::UserType
+ graphql_name 'MergeRequestAssignee'
+ description 'A user assigned to a merge request.'
+
include FindClosest
include ::Types::MergeRequests::InteractsWithMergeRequest
- graphql_name 'MergeRequestAssignee'
- description 'A user assigned to a merge request.'
authorize :read_user
end
end
diff --git a/app/graphql/types/merge_requests/interacts_with_merge_request.rb b/app/graphql/types/merge_requests/interacts_with_merge_request.rb
index d4a1f2faa8d..15621ef1472 100644
--- a/app/graphql/types/merge_requests/interacts_with_merge_request.rb
+++ b/app/graphql/types/merge_requests/interacts_with_merge_request.rb
@@ -5,6 +5,8 @@ module Types
module InteractsWithMergeRequest
extend ActiveSupport::Concern
+ include FindClosest
+
included do
field :merge_request_interaction,
type: ::Types::UserMergeRequestInteractionType,
@@ -13,8 +15,9 @@ module Types
description: "Details of this user's interactions with the merge request."
end
- def merge_request_interaction(parent:)
+ def merge_request_interaction(parent:, id: nil)
merge_request = closest_parent([::Types::MergeRequestType], parent)
+
return unless merge_request
Users::MergeRequestInteraction.new(user: object, merge_request: merge_request)
diff --git a/app/graphql/types/merge_requests/reviewer_type.rb b/app/graphql/types/merge_requests/reviewer_type.rb
index 1ced821c839..11f7ceaf461 100644
--- a/app/graphql/types/merge_requests/reviewer_type.rb
+++ b/app/graphql/types/merge_requests/reviewer_type.rb
@@ -3,11 +3,12 @@
module Types
module MergeRequests
class ReviewerType < ::Types::UserType
+ graphql_name 'MergeRequestReviewer'
+ description 'A user assigned to a merge request as a reviewer.'
+
include FindClosest
include ::Types::MergeRequests::InteractsWithMergeRequest
- graphql_name 'MergeRequestReviewer'
- description 'A user assigned to a merge request as a reviewer.'
authorize :read_user
end
end
diff --git a/app/graphql/types/metrics/dashboards/annotation_type.rb b/app/graphql/types/metrics/dashboards/annotation_type.rb
index fb35f2bd9a1..0c787476f54 100644
--- a/app/graphql/types/metrics/dashboards/annotation_type.rb
+++ b/app/graphql/types/metrics/dashboards/annotation_type.rb
@@ -4,8 +4,8 @@ module Types
module Metrics
module Dashboards
class AnnotationType < ::Types::BaseObject
- authorize :read_metrics_dashboard_annotation
graphql_name 'MetricsDashboardAnnotation'
+ authorize :read_metrics_dashboard_annotation
field :description, GraphQL::Types::String, null: true,
description: 'Description of the annotation.'
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index c350f4dd922..3c735231595 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -2,10 +2,10 @@
module Types
class MutationType < BaseObject
- include Gitlab::Graphql::MountMutation
-
graphql_name 'Mutation'
+ include Gitlab::Graphql::MountMutation
+
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
mount_mutation Mutations::AlertManagement::CreateAlertIssue
mount_mutation Mutations::AlertManagement::UpdateAlertStatus
@@ -121,10 +121,13 @@ module Types
mount_mutation Mutations::Namespace::PackageSettings::Update
mount_mutation Mutations::Groups::Update
mount_mutation Mutations::UserCallouts::Create
+ mount_mutation Mutations::UserPreferences::Update
mount_mutation Mutations::Packages::Destroy
mount_mutation Mutations::Packages::DestroyFile
mount_mutation Mutations::Echo
- mount_mutation Mutations::WorkItems::Create, feature_flag: :work_items
+ mount_mutation Mutations::WorkItems::Create
+ mount_mutation Mutations::WorkItems::Delete
+ mount_mutation Mutations::WorkItems::Update
end
end
diff --git a/app/graphql/types/notes/discussion_type.rb b/app/graphql/types/notes/discussion_type.rb
index 56579c357a7..ffe61c9ff88 100644
--- a/app/graphql/types/notes/discussion_type.rb
+++ b/app/graphql/types/notes/discussion_type.rb
@@ -3,10 +3,10 @@
module Types
module Notes
class DiscussionType < BaseObject
- DiscussionID = ::Types::GlobalIDType[::Discussion]
-
graphql_name 'Discussion'
+ DiscussionID = ::Types::GlobalIDType[::Discussion]
+
authorize :read_note
implements(Types::ResolvableInterface)
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
index 1d2cf9649d8..444ecb5e792 100644
--- a/app/graphql/types/packages/package_details_type.rb
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -3,16 +3,17 @@
module Types
module Packages
class PackageDetailsType < PackageType
- include ::PackagesHelper
-
graphql_name 'PackageDetailsType'
description 'Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes'
+
+ include ::PackagesHelper
+
authorize :read_package
field :versions, ::Types::Packages::PackageType.connection_type, null: true,
description: 'Other versions of the package.'
- field :package_files, Types::Packages::PackageFileType.connection_type, null: true, description: 'Package files.'
+ field :package_files, Types::Packages::PackageFileType.connection_type, null: true, method: :installable_package_files, description: 'Package files.'
field :dependency_links, Types::Packages::PackageDependencyLinkType.connection_type, null: true, description: 'Dependency link.'
@@ -36,14 +37,6 @@ module Types
object.versions
end
- def package_files
- if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- object.installable_package_files
- else
- object.package_files
- end
- end
-
def composer_config_repository_url
composer_config_repository_name(object.project.group&.id)
end
diff --git a/app/graphql/types/permission_types/issue.rb b/app/graphql/types/permission_types/issue.rb
index 94e1bffd685..b38971b64cd 100644
--- a/app/graphql/types/permission_types/issue.rb
+++ b/app/graphql/types/permission_types/issue.rb
@@ -3,8 +3,8 @@
module Types
module PermissionTypes
class Issue < BasePermissionType
- description 'Check permissions for the current user on a issue'
graphql_name 'IssuePermissions'
+ description 'Check permissions for the current user on a issue'
abilities :read_issue, :admin_issue, :update_issue, :reopen_issue,
:read_design, :create_design, :destroy_design,
diff --git a/app/graphql/types/permission_types/merge_request.rb b/app/graphql/types/permission_types/merge_request.rb
index 52c11fe5588..73a2f820f79 100644
--- a/app/graphql/types/permission_types/merge_request.rb
+++ b/app/graphql/types/permission_types/merge_request.rb
@@ -3,15 +3,16 @@
module Types
module PermissionTypes
class MergeRequest < BasePermissionType
+ graphql_name 'MergeRequestPermissions'
+ description 'Check permissions for the current user on a merge request'
+
+ present_using MergeRequestPresenter
+
PERMISSION_FIELDS = %i[push_to_source_branch
remove_source_branch
cherry_pick_on_current_merge_request
revert_on_current_merge_request].freeze
- present_using MergeRequestPresenter
- description 'Check permissions for the current user on a merge request'
- graphql_name 'MergeRequestPermissions'
-
abilities :read_merge_request, :admin_merge_request,
:update_merge_request, :create_note
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index d49244f6b65..dc428e7bdce 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -15,6 +15,8 @@ module Types
description: 'Full path of the project.'
field :path, GraphQL::Types::String, null: false,
description: 'Path of the project.'
+ field :ci_config_path_or_default, GraphQL::Types::String, null: false,
+ description: 'Path of the CI configuration file.'
field :sast_ci_configuration, Types::CiConfiguration::Sast::Type, null: true,
calls_gitaly: true,
@@ -195,6 +197,12 @@ module Types
extras: [:lookahead],
resolver: Resolvers::ProjectPipelineResolver
+ field :pipeline_counts,
+ Types::Ci::PipelineCountsType,
+ null: true,
+ description: 'Build pipeline counts of the project.',
+ resolver: Resolvers::Ci::ProjectPipelineCountsResolver
+
field :ci_cd_settings,
Types::Ci::CiCdSettingType,
null: true,
@@ -231,6 +239,12 @@ module Types
max_page_size: 2000,
resolver: Resolvers::BoardsResolver
+ field :recent_issue_boards,
+ Types::BoardType.connection_type,
+ null: true,
+ description: 'List of recently visited boards of the project. Maximum size is 4.',
+ resolver: Resolvers::RecentBoardsResolver
+
field :board,
Types::BoardType,
null: true,
diff --git a/app/graphql/types/query_complexity_type.rb b/app/graphql/types/query_complexity_type.rb
index 3f58a15aef7..13b618cf5ce 100644
--- a/app/graphql/types/query_complexity_type.rb
+++ b/app/graphql/types/query_complexity_type.rb
@@ -3,10 +3,10 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class QueryComplexityType < ::Types::BaseObject
- ANALYZER = GraphQL::Analysis::QueryComplexity.new { |_query, complexity| complexity }
-
graphql_name 'QueryComplexity'
+ ANALYZER = GraphQL::Analysis::QueryComplexity.new { |_query, complexity| complexity }
+
alias_method :query, :object
field :limit, GraphQL::Types::Int,
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index 28339093172..bfd59763a07 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -4,10 +4,10 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
# This is presented through `Repository` that has its own authorization
class BlobType < BaseObject
- present_using BlobPresenter
-
graphql_name 'RepositoryBlob'
+ present_using BlobPresenter
+
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the blob.'
@@ -87,6 +87,14 @@ module Types
description: 'Web path to blob permalink.',
calls_gitaly: true
+ field :environment_formatted_external_url, GraphQL::Types::String, null: true,
+ description: 'Environment on which the blob is available.',
+ calls_gitaly: true
+
+ field :environment_external_url_for_route_map, GraphQL::Types::String, null: true,
+ description: 'Web path to blob on an environment.',
+ calls_gitaly: true
+
field :code_owners, [Types::UserType], null: true,
description: 'List of code owners for the blob.',
calls_gitaly: true
@@ -117,6 +125,12 @@ module Types
field :archived, GraphQL::Types::Boolean, null: true, method: :archived?,
description: 'Whether the current project is archived.'
+ field :language, GraphQL::Types::String,
+ description: 'Blob language.',
+ method: :blob_language,
+ null: true,
+ calls_gitaly: true
+
def raw_text_blob
object.data unless object.binary?
end
diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb
index 88dc6036bfd..4dcadf1274f 100644
--- a/app/graphql/types/root_storage_statistics_type.rb
+++ b/app/graphql/types/root_storage_statistics_type.rb
@@ -15,5 +15,6 @@ module Types
field :snippets_size, GraphQL::Types::Float, null: false, description: 'Snippets size in bytes.'
field :pipeline_artifacts_size, GraphQL::Types::Float, null: false, description: 'CI pipeline artifacts size in bytes.'
field :uploads_size, GraphQL::Types::Float, null: false, description: 'Uploads size in bytes.'
+ field :dependency_proxy_size, GraphQL::Types::Float, null: false, description: 'Dependency Proxy sizes in bytes.'
end
end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index 3629edb5b33..db6a247179d 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -9,5 +9,8 @@ module Types
field :issue_crm_contacts_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the crm contacts of an issuable are updated.'
+
+ field :issuable_title_updated, subscription: Subscriptions::IssuableUpdated, null: true,
+ description: 'Triggered when the title of an issuable is updated.'
end
end
diff --git a/app/graphql/types/terraform/state_version_type.rb b/app/graphql/types/terraform/state_version_type.rb
index bf1af4565bc..59da550aa1b 100644
--- a/app/graphql/types/terraform/state_version_type.rb
+++ b/app/graphql/types/terraform/state_version_type.rb
@@ -3,10 +3,10 @@
module Types
module Terraform
class StateVersionType < BaseObject
- include ::API::Helpers::RelatedResourcesHelpers
-
graphql_name 'TerraformStateVersion'
+ include ::API::Helpers::RelatedResourcesHelpers
+
authorize :read_terraform_state
field :id, GraphQL::Types::ID,
diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb
index bb15d91a62f..bcff65be652 100644
--- a/app/graphql/types/tree/blob_type.rb
+++ b/app/graphql/types/tree/blob_type.rb
@@ -4,12 +4,11 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
# This is presented through `Repository` that has its own authorization
class BlobType < BaseObject
- implements Types::Tree::EntryType
+ graphql_name 'Blob'
+ implements Types::Tree::EntryType
present_using BlobPresenter
- graphql_name 'Blob'
-
field :web_url, GraphQL::Types::String, null: true,
description: 'Web URL of the blob.'
field :web_path, GraphQL::Types::String, null: true,
diff --git a/app/graphql/types/tree/submodule_type.rb b/app/graphql/types/tree/submodule_type.rb
index 05d8c1a951a..bc7828dbffa 100644
--- a/app/graphql/types/tree/submodule_type.rb
+++ b/app/graphql/types/tree/submodule_type.rb
@@ -4,10 +4,10 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
# This is presented through `Repository` that has its own authorization
class SubmoduleType < BaseObject
- implements Types::Tree::EntryType
-
graphql_name 'Submodule'
+ implements Types::Tree::EntryType
+
field :web_url, type: GraphQL::Types::String, null: true,
description: 'Web URL for the sub-module.'
field :tree_url, type: GraphQL::Types::String, null: true,
diff --git a/app/graphql/types/tree/tree_entry_type.rb b/app/graphql/types/tree/tree_entry_type.rb
index 998b3617574..cdc84c8e318 100644
--- a/app/graphql/types/tree/tree_entry_type.rb
+++ b/app/graphql/types/tree/tree_entry_type.rb
@@ -4,13 +4,12 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
# This is presented through `Repository` that has its own authorization
class TreeEntryType < BaseObject
- implements Types::Tree::EntryType
-
- present_using TreeEntryPresenter
-
graphql_name 'TreeEntry'
description 'Represents a directory'
+ implements Types::Tree::EntryType
+ present_using TreeEntryPresenter
+
field :web_url, GraphQL::Types::String, null: true,
description: 'Web URL for the tree entry (directory).'
field :web_path, GraphQL::Types::String, null: true,
diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb
index 6bb4cb29cdd..24fca80d5a9 100644
--- a/app/graphql/types/user_interface.rb
+++ b/app/graphql/types/user_interface.rb
@@ -31,7 +31,7 @@ module Types
null: false,
resolver_method: :redacted_name,
description: 'Human-readable name of the user. ' \
- 'Will return `****` if the user is a project bot and the requester does not have permission to read resource access tokens.'
+ 'Returns `****` if the user is a project bot and the requester does not have permission to view the project.'
field :state,
type: Types::UserStateEnum,
@@ -127,7 +127,7 @@ module Types
def redacted_name
return object.name unless object.project_bot?
- return object.name if context[:current_user]&.can?(:read_resource_access_tokens, object.projects.first)
+ return object.name if context[:current_user]&.can?(:read_project, object.projects.first)
# If the requester does not have permission to read the project bot name,
# the API returns an arbitrary string. UI changes will be addressed in a follow up issue:
diff --git a/app/graphql/types/user_preferences_type.rb b/app/graphql/types/user_preferences_type.rb
new file mode 100644
index 00000000000..9a1ea4a2e4f
--- /dev/null
+++ b/app/graphql/types/user_preferences_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes
+ # Only used to render the current user's own preferences
+ class UserPreferencesType < BaseObject
+ graphql_name 'UserPreferences'
+
+ field :issues_sort, Types::IssueSortEnum,
+ description: 'Sort order for issue lists.',
+ null: true
+
+ def issues_sort
+ object.issues_sort.to_sym
+ end
+ end
+end
diff --git a/app/graphql/types/work_item_state_enum.rb b/app/graphql/types/work_item_state_enum.rb
new file mode 100644
index 00000000000..8fe58f76d9a
--- /dev/null
+++ b/app/graphql/types/work_item_state_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class WorkItemStateEnum < BaseEnum
+ graphql_name 'WorkItemState'
+ description 'State of a GitLab work item'
+
+ value 'OPEN', 'In open state.', value: 'opened'
+ value 'CLOSED', 'In closed state.', value: 'closed'
+ end
+end
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
index 486c1e52987..15a5557b489 100644
--- a/app/graphql/types/work_item_type.rb
+++ b/app/graphql/types/work_item_type.rb
@@ -12,6 +12,8 @@ module Types
description: 'Global ID of the work item.'
field :iid, GraphQL::Types::ID, null: false,
description: 'Internal ID of the work item.'
+ field :state, WorkItemStateEnum, null: false,
+ description: 'State of the work item.'
field :title, GraphQL::Types::String, null: false,
description: 'Title of the work item.'
field :work_item_type, Types::WorkItems::TypeType, null: false,
diff --git a/app/graphql/types/work_items/state_event_enum.rb b/app/graphql/types/work_items/state_event_enum.rb
new file mode 100644
index 00000000000..db54d494c12
--- /dev/null
+++ b/app/graphql/types/work_items/state_event_enum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ class StateEventEnum < BaseEnum
+ graphql_name 'WorkItemStateEvent'
+ description 'Values for work item state events'
+
+ value 'REOPEN', 'Reopens the work item.', value: 'reopen'
+ value 'CLOSE', 'Closes the work item.', value: 'close'
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e88d1832480..e675c01bcbb 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -396,7 +396,8 @@ module ApplicationHelper
labels: labels_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
milestones: milestones_project_autocomplete_sources_path(object),
commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
- snippets: snippets_project_autocomplete_sources_path(object)
+ snippets: snippets_project_autocomplete_sources_path(object),
+ contacts: contacts_project_autocomplete_sources_path(object)
}
end
end
@@ -428,7 +429,7 @@ module ApplicationHelper
experiment(:logged_out_marketing_header, actor: nil) do |e|
html_class = 'logged-out-marketing-header-candidate'
e.candidate { html_class }
- e.try(:trial_focused) { html_class }
+ e.variant(:trial_focused) { html_class }
e.control {}
e.run
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 7541247b19f..fa9b3bfc912 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -234,7 +234,9 @@ module ApplicationSettingsHelper
:outbound_local_requests_allowlist_raw,
:dsa_key_restriction,
:ecdsa_key_restriction,
+ :ecdsa_sk_key_restriction,
:ed25519_key_restriction,
+ :ed25519_sk_key_restriction,
:eks_integration_enabled,
:eks_account_id,
:eks_access_key_id,
@@ -421,7 +423,12 @@ module ApplicationSettingsHelper
:sidekiq_job_limiter_compression_threshold_bytes,
:sidekiq_job_limiter_limit_bytes,
:suggest_pipeline_enabled,
- :user_email_lookup_limit
+ :user_email_lookup_limit,
+ :users_get_by_id_limit,
+ :users_get_by_id_limit_allowlist_raw,
+ :runner_token_expiration_interval,
+ :group_runner_token_expiration_interval,
+ :project_runner_token_expiration_interval
].tap do |settings|
settings << :deactivate_dormant_users unless Gitlab.com?
end
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index dd852a68682..9dc93779b12 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module AvatarsHelper
+ DEFAULT_AVATAR_PATH = 'no_avatar.png'
+
def project_icon(project, options = {})
source_icon(project, options)
end
@@ -33,12 +35,12 @@ module AvatarsHelper
end
end
- def avatar_icon_for_user(user = nil, size = nil, scale = 2, only_path: true)
- if user
- user.avatar_url(size: size, only_path: only_path) || default_avatar
- else
- gravatar_icon(nil, size, scale)
- end
+ def avatar_icon_for_user(user = nil, size = nil, scale = 2, only_path: true, current_user: nil)
+ return gravatar_icon(nil, size, scale) unless user
+ return default_avatar if blocked_or_unconfirmed?(user) && !can_admin?(current_user)
+
+ user_avatar = user.avatar_url(size: size, only_path: only_path)
+ user_avatar || default_avatar
end
def gravatar_icon(user_email = '', size = nil, scale = 2)
@@ -47,7 +49,7 @@ module AvatarsHelper
end
def default_avatar
- ActionController::Base.helpers.image_path('no_avatar.png')
+ ActionController::Base.helpers.image_path(DEFAULT_AVATAR_PATH)
end
def author_avatar(commit_or_event, options = {})
@@ -103,8 +105,8 @@ module AvatarsHelper
end
def avatar_without_link(resource, options = {})
- if resource.is_a?(User)
- user_avatar_without_link(options.merge(user: resource))
+ if resource.is_a?(Namespaces::UserNamespace)
+ user_avatar_without_link(options.merge(user: resource.first_owner))
elsif resource.is_a?(Group)
group_icon(resource, options.merge(class: 'avatar'))
end
@@ -157,4 +159,14 @@ module AvatarsHelper
source.name[0, 1].upcase
end
end
+
+ def blocked_or_unconfirmed?(user)
+ user.blocked? || !user.confirmed?
+ end
+
+ def can_admin?(user)
+ return false unless user
+
+ user.can_admin_all_resources?
+ end
end
diff --git a/app/helpers/bizible_helper.rb b/app/helpers/bizible_helper.rb
new file mode 100644
index 00000000000..970cc6558da
--- /dev/null
+++ b/app/helpers/bizible_helper.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module BizibleHelper
+ def bizible_enabled?
+ Feature.enabled?(:ecomm_instrumentation, type: :ops) &&
+ Gitlab.config.extra.has_key?('bizible') &&
+ Gitlab.config.extra.bizible.present? &&
+ Gitlab.config.extra.bizible == true
+ end
+end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 57da04b38cc..28cd61e10d9 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -17,7 +17,6 @@ module BoardsHelper
can_update: can_update?.to_s,
can_admin_list: can_admin_list?.to_s,
time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s,
- recent_boards_endpoint: recent_boards_path,
parent: current_board_parent.model_name.param_key,
group_id: group_id,
labels_filter_base_path: build_issue_link_base,
@@ -128,10 +127,6 @@ module BoardsHelper
}
end
- def recent_boards_path
- recent_project_boards_path(@project) if current_board_parent.is_a?(Project)
- end
-
def serializer
CurrentBoardSerializer.new
end
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index bb7226da74e..3f0379b1baa 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -12,6 +12,8 @@ module Ci
initial_branch = params[:branch_name]
latest_commit = project.repository.commit(initial_branch) || project.commit
commit_sha = latest_commit ? latest_commit.sha : ''
+ total_branches = project.repository_exists? ? project.repository.branch_count : 0
+
{
"ci-config-path": project.ci_config_path_or_default,
"ci-examples-help-page-path" => help_page_path('ci/examples/index'),
@@ -29,7 +31,7 @@ module Ci
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/index'),
- "total-branches" => project.repository.branches.length,
+ "total-branches" => total_branches,
"yml-help-page-path" => help_page_path('ci/yaml/index')
}
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 93b6b4e8fe2..1475a26ca09 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -28,7 +28,8 @@ module ClustersHelper
clusters_empty_state_image: image_path('illustrations/empty-state/empty-state-clusters.svg'),
empty_state_help_text: clusterable.empty_state_help_text,
new_cluster_path: clusterable.new_path(tab: 'create'),
- can_add_cluster: clusterable.can_add_cluster?.to_s
+ can_add_cluster: clusterable.can_add_cluster?.to_s,
+ can_admin_cluster: clusterable.can_admin_cluster?.to_s
}
end
@@ -38,7 +39,8 @@ module ClustersHelper
empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg'),
project_path: clusterable.full_path,
add_cluster_path: clusterable.new_path(tab: 'add'),
- kas_address: Gitlab::Kas.external_url
+ kas_address: Gitlab::Kas.external_url,
+ gitlab_version: Gitlab.version_info
}.merge(js_clusters_list_data(clusterable))
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 7296560a450..c58a365b884 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -139,7 +139,7 @@ module GroupsHelper
{}
end
- def require_verification_for_group_creation_enabled?
+ def require_verification_for_namespace_creation_enabled?
# overridden in EE
false
end
@@ -204,7 +204,7 @@ module GroupsHelper
end
def group_url_error_message
- s_('GroupSettings|Please choose a group URL with no special characters or spaces.')
+ s_('GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores.')
end
# Maps `jobs_to_be_done` values to option texts
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 4d81aeca37a..bd1571f3956 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -34,7 +34,7 @@ module IdeHelper
def enable_environments_guidance?
experiment(:in_product_guidance_environments_webide, project: @project) do |e|
- e.try { !has_dismissed_ide_environments_callout? }
+ e.candidate { !has_dismissed_ide_environments_callout? }
e.run
end
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index 230f80e20a5..f5ba978e860 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -228,10 +228,6 @@ module IntegrationsHelper
name: integration.to_param
}
end
-
- def vue_integration_form_enabled?
- Feature.enabled?(:vue_integration_form, current_user, default_enabled: :yaml)
- end
end
IntegrationsHelper.prepend_mod_with('IntegrationsHelper')
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index 8b26b646fdd..1f225e9c0e5 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -6,7 +6,7 @@ module InviteMembersHelper
def can_invite_members_for_project?(project)
# do not use the can_admin_project_member? helper here due to structure of the view and how membership_locked?
# is leveraged for inviting groups
- Feature.enabled?(:invite_members_group_modal, project.group) && can?(current_user, :admin_project_member, project)
+ Feature.enabled?(:invite_members_group_modal, project.group, default_enabled: :yaml) && can?(current_user, :admin_project_member, project)
end
def invite_accepted_notice(member)
@@ -21,6 +21,11 @@ module InviteMembersHelper
end
def group_select_data(group)
+ # This should only be used for groups to load the invite group modal.
+ # For instance the invite groups modal should not call this from a project scope
+ # this is only to be called in scope of a group context as noted in this thread
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79036#note_821465513
+ # the group sharing in projects disabling is explained there as well
if group.root_ancestor.namespace_settings.prevent_sharing_groups_outside_hierarchy
{ groups_filter: 'descendant_groups', parent_id: group.root_ancestor.id }
else
@@ -28,6 +33,18 @@ module InviteMembersHelper
end
end
+ def common_invite_group_modal_data(source, member_class, is_project)
+ {
+ id: source.id,
+ name: source.name,
+ default_access_level: Gitlab::Access::GUEST,
+ invalid_groups: source.related_group_ids,
+ help_link: help_page_url('user/permissions'),
+ is_project: is_project,
+ access_levels: member_class.access_level_roles.to_json
+ }
+ end
+
def common_invite_modal_dataset(source)
dataset = {
id: source.id,
@@ -69,3 +86,5 @@ module InviteMembersHelper
projects.map { |project| { id: project.id, title: project.title } }
end
end
+
+InviteMembersHelper.prepend_mod_with('InviteMembersHelper')
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index 6c23f888823..a82a5ac0fb0 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -38,7 +38,13 @@ module IssuablesDescriptionTemplatesHelper
# Only local templates will be listed if licenses for inherited templates are not present
all_templates = all_templates.values.flatten.map { |tpl| tpl[:name] }.compact.uniq
- all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
+ template = all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
+
+ unless issuable.description.present?
+ template ||= all_templates.find { |tmpl_name| tmpl_name.casecmp?('default') }
+ end
+
+ template
end
def available_service_desk_templates_for(project)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 53a7487741e..ec1f8ca5f00 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -201,10 +201,7 @@ module IssuablesHelper
count = issuables_count_for_state(issuable_type, state)
if count != -1
- html << " " << content_tag(:span,
- format_count(issuable_type, count, Gitlab::IssuablesCountForState::THRESHOLD),
- class: 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex'
- )
+ html << " " << gl_badge_tag(format_count(issuable_type, count, Gitlab::IssuablesCountForState::THRESHOLD), { variant: :muted, size: :sm }, { class: "gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex" })
end
html.html_safe
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 5aa2aca37f3..8e7f5060412 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -63,7 +63,7 @@ module IssuesHelper
end
def issue_hidden?(issue)
- Feature.enabled?(:ban_user_feature_flag) && issue.hidden?
+ Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml) && issue.hidden?
end
def hidden_issue_icon(issue)
@@ -199,6 +199,7 @@ module IssuesHelper
calendar_path: url_for(safe_params.merge(calendar_url_options)),
empty_state_svg_path: image_path('illustrations/issues.svg'),
full_path: namespace.full_path,
+ initial_sort: current_user&.user_preference&.issues_sort,
is_anonymous_search_disabled: Feature.enabled?(:disable_anonymous_search, type: :ops).to_s,
is_issue_repositioning_disabled: issue_repositioning_disabled?.to_s,
is_signed_in: current_user.present?.to_s,
@@ -231,10 +232,10 @@ module IssuesHelper
)
end
- def group_issues_list_data(group, current_user, issues, projects)
+ def group_issues_list_data(group, current_user)
common_issues_list_data(group, current_user).merge(
- has_any_issues: issues.to_a.any?.to_s,
- has_any_projects: any_projects?(projects).to_s
+ has_any_issues: @has_issues.to_s,
+ has_any_projects: @has_projects.to_s
)
end
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 6330b8fc829..7dfd9ed47e3 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -33,8 +33,8 @@ module LearnGitlabHelper
actor: current_user,
sticky_to: project.namespace
) do |e|
- e.use { urls_to_use = action_urls }
- e.try { urls_to_use = new_action_urls(project) }
+ e.control { urls_to_use = action_urls }
+ e.candidate { urls_to_use = new_action_urls(project) }
end
urls_to_use.to_h do |action, url|
diff --git a/app/helpers/listbox_helper.rb b/app/helpers/listbox_helper.rb
new file mode 100644
index 00000000000..d24680bc0b0
--- /dev/null
+++ b/app/helpers/listbox_helper.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module ListboxHelper
+ DROPDOWN_CONTAINER_CLASSES = %w[dropdown b-dropdown gl-new-dropdown btn-group js-redirect-listbox].freeze
+ DROPDOWN_BUTTON_CLASSES = %w[btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle].freeze
+ DROPDOWN_INNER_CLASS = 'gl-new-dropdown-button-text'
+ DROPDOWN_ICON_CLASS = 'gl-button-icon dropdown-chevron gl-icon'
+
+ # Creates a listbox component with redirect behavior.
+ #
+ # Use this for migrating existing deprecated dropdowns to become
+ # Pajamas-compliant. New features should use Vue components directly instead.
+ #
+ # The `items` parameter must be an array of hashes, each with `value`, `text`
+ # and `href` keys, where `value` is a unique identifier for the item (e.g.,
+ # the sort key), `text` is the user-facing string for the item, and `href` is
+ # the path to redirect to when that item is selected.
+ #
+ # The `selected` parameter is the currently selected `value`, and must
+ # correspond to one of the `items`, or be `nil`. When `selected.nil?`, the first item is selected.
+ #
+ # The final parameter `html_options` applies arbitrary attributes to the
+ # returned tag. Some of these are passed to the underlying Vue component as
+ # props, e.g., to right-align the menu of items, add `data: { right: true }`.
+ #
+ # Examples:
+ # # Create a listbox with two items, with the first item selected
+ # - items = [{ value: 'foo', text: 'Name, ascending', href: '/foo' },
+ # { value: 'bar', text: 'Name, descending', href: '/bar' }]
+ # = gl_redirect_listbox_tag items, 'foo'
+ #
+ # # Create the same listbox, right-align the menu and add margin styling
+ # = gl_redirect_listbox_tag items, 'foo', class: 'gl-ml-3', data: { right: true }
+ def gl_redirect_listbox_tag(items, selected, html_options = {})
+ # Add script tag for app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js
+ content_for :page_specific_javascripts do
+ webpack_bundle_tag 'redirect_listbox'
+ end
+
+ selected ||= items.first[:value]
+ selected_option = items.find { |opt| opt[:value] == selected }
+ raise ArgumentError, "cannot find #{selected} in #{items}" unless selected_option
+
+ button = button_tag(type: :button, class: DROPDOWN_BUTTON_CLASSES) do
+ content_tag(:span, selected_option[:text], class: DROPDOWN_INNER_CLASS) +
+ sprite_icon('chevron-down', css_class: DROPDOWN_ICON_CLASS)
+ end
+
+ classes = [*DROPDOWN_CONTAINER_CLASSES, *html_options[:class]]
+ data = html_options.fetch(:data, {}).merge(items: items, selected: selected)
+
+ content_tag(:div, button, html_options.merge({
+ class: classes,
+ data: data
+ }))
+ end
+end
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index 24102a90a3b..9420c95c9ce 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -253,14 +253,18 @@ module Nav
end
def projects_submenu
- # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
builder = ::Gitlab::Nav::TopNavMenuBuilder.new
+ projects_submenu_items(builder: builder)
+ builder.build
+ end
+
+ def projects_submenu_items(builder:)
+ # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
builder.add_primary_menu_item(id: 'your', title: _('Your projects'), href: dashboard_projects_path)
builder.add_primary_menu_item(id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path)
builder.add_primary_menu_item(id: 'explore', title: _('Explore projects'), href: explore_root_path)
builder.add_primary_menu_item(id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path)
builder.add_secondary_menu_item(id: 'create', title: _('Create new project'), href: new_project_path)
- builder.build
end
def groups_submenu
diff --git a/app/helpers/projects/cluster_agents_helper.rb b/app/helpers/projects/cluster_agents_helper.rb
index e3027759d65..43d520d0eab 100644
--- a/app/helpers/projects/cluster_agents_helper.rb
+++ b/app/helpers/projects/cluster_agents_helper.rb
@@ -5,6 +5,7 @@ module Projects::ClusterAgentsHelper
{
activity_empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg'),
agent_name: agent_name,
+ can_admin_vulnerability: can?(current_user, :admin_vulnerability, project).to_s,
empty_state_svg_path: image_path('illustrations/operations-dashboard_empty.svg'),
project_path: project.full_path
}
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 084c962d34c..6098ef63ec3 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -54,31 +54,37 @@ module ProjectsHelper
default_opts = { avatar: true, name: true, title: ":name" }
opts = default_opts.merge(opts)
+ return "(deleted)" unless author
+
data_attrs = {
user_id: author.id,
username: author.username,
name: author.name
}
- return "(deleted)" unless author
+ inject_classes = ["author-link", opts[:extra_class]]
- author_html = []
+ if opts[:name]
+ inject_classes.concat(["js-user-link", opts[:mobile_classes]])
+ else
+ inject_classes.append( "has-tooltip" )
+ end
+
+ inject_classes = inject_classes.compact.join(" ")
+ author_html = []
# Build avatar image tag
author_html << link_to_member_avatar(author, opts) if opts[:avatar]
-
# Build name span tag
author_html << author_content_tag(author, opts) if opts[:name]
-
author_html << capture(&block) if block
-
author_html = author_html.join.html_safe
if opts[:name]
- link_to(author_html, user_path(author), class: "author-link js-user-link #{"#{opts[:extra_class]}" if opts[:extra_class]} #{"#{opts[:mobile_classes]}" if opts[:mobile_classes]}", data: data_attrs).html_safe
+ link_to(author_html, user_path(author), class: inject_classes, data: data_attrs).html_safe
else
title = opts[:title].sub(":name", sanitize(author.name))
- link_to(author_html, user_path(author), class: "author-link has-tooltip", title: title, data: { container: 'body', qa_selector: 'assignee_link' }).html_safe
+ link_to(author_html, user_path(author), class: inject_classes, title: title, data: { container: 'body', qa_selector: 'assignee_link' }).html_safe
end
end
@@ -424,6 +430,18 @@ module ProjectsHelper
end
end
+ def import_from_bitbucket_message
+ link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path("integration/bitbucket") }
+
+ str = if current_user.admin?
+ 'ImportProjects|To enable importing projects from Bitbucket, as administrator you need to configure %{link_start}OAuth integration%{link_end}'
+ else
+ 'ImportProjects|To enable importing projects from Bitbucket, ask your GitLab administrator to configure %{link_start}OAuth integration%{link_end}'
+ end
+
+ s_(str).html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ end
+
private
def tab_ability_map
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 6efede8d565..5b596c328d1 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -164,6 +164,23 @@ module SearchHelper
options
end
+ # search_context exposes a bit too much data to the frontend, this controls what data we share and when.
+ def header_search_context
+ {}.tap do |hash|
+ hash[:group] = { id: search_context.group.id, name: search_context.group.name } if search_context.for_group?
+ hash[:group_metadata] = search_context.group_metadata if search_context.for_group?
+
+ hash[:project] = { id: search_context.project.id, name: search_context.project.name } if search_context.for_project?
+ hash[:project_metadata] = search_context.project_metadata if search_context.for_project?
+
+ hash[:scope] = search_context.scope if search_context.for_project? || search_context.for_group?
+ hash[:code_search] = search_context.code_search? if search_context.for_project? || search_context.for_group?
+
+ hash[:ref] = search_context.ref if can?(current_user, :download_code, search_context.project)
+ hash[:for_snippets] = search_context.for_snippets?
+ end
+ end
+
private
# Autocomplete results for various settings pages
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index a60143db739..34ba66db444 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -23,4 +23,42 @@ module StorageHelper
_("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}") % counters
end
+
+ def storage_enforcement_banner_info(namespace)
+ return if namespace.paid?
+ return unless namespace.storage_enforcement_date && namespace.storage_enforcement_date >= Date.today
+ return if user_dismissed_storage_enforcement_banner?(namespace)
+
+ {
+ text: html_escape_once(s_("UsageQuota|From %{storage_enforcement_date} storage limits will apply to this namespace. " \
+ "View and manage your usage in %{strong_start}Group Settings &gt; Usage quotas%{strong_end}.")).html_safe %
+ { storage_enforcement_date: namespace.storage_enforcement_date, strong_start: "<strong>".html_safe, strong_end: "</strong>".html_safe },
+ variant: 'warning',
+ callouts_path: group_callouts_path,
+ callouts_feature_name: storage_enforcement_banner_user_callouts_feature_name(namespace),
+ learn_more_link: link_to(_('Learn more.'), help_page_path('/'), rel: 'noopener noreferrer', target: '_blank') # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ }
+ end
+
+ private
+
+ def storage_enforcement_banner_user_callouts_feature_name(namespace)
+ "storage_enforcement_banner_#{storage_enforcement_banner_threshold(namespace)}_enforcement_threshold"
+ end
+
+ def storage_enforcement_banner_threshold(namespace)
+ days_to_enforcement_date = (namespace.storage_enforcement_date - Date.today)
+
+ return :first if days_to_enforcement_date > 30
+ return :second if days_to_enforcement_date > 15 && days_to_enforcement_date <= 30
+ return :third if days_to_enforcement_date > 7 && days_to_enforcement_date <= 15
+ return :fourth if days_to_enforcement_date > 0 && days_to_enforcement_date <= 7
+ end
+
+ def user_dismissed_storage_enforcement_banner?(namespace)
+ return false unless current_user
+
+ current_user.dismissed_callout_for_group?(feature_name: storage_enforcement_banner_user_callouts_feature_name(namespace),
+ group: namespace)
+ end
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index f2e1d158c2d..b45ce10a2f6 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -42,7 +42,8 @@ module SystemNoteHelper
'cloned' => 'documents',
'issue_type' => 'pencil-square',
'attention_requested' => 'user',
- 'attention_request_removed' => 'user'
+ 'attention_request_removed' => 'user',
+ 'contact' => 'users'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 2efc3f27dc7..dbbe7069ca4 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -33,7 +33,7 @@ module TabHelper
#
def gl_tab_link_to(name = nil, options = {}, html_options = {}, &block)
link_classes = %w[nav-link gl-tab-nav-item]
- active_link_classes = %w[active gl-tab-nav-item-active gl-tab-nav-item-active-indigo]
+ active_link_classes = %w[active gl-tab-nav-item-active]
if block_given?
# Shift params to skip the omitted "name" param
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index 86289ec8ed2..8216144c04c 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -6,12 +6,6 @@ module TagsHelper
end
def filter_tags_path(options = {})
- exist_opts = {
- search: params[:search],
- sort: params[:sort]
- }
-
- options = exist_opts.merge(options)
project_tags_path(@project, @id, options)
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 4437f309a9c..23a9601aed7 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -175,6 +175,21 @@ module TreeHelper
}
end
+ def fork_modal_options(project, ref, path, blob)
+ if show_edit_button?({ blob: blob })
+ fork_path = fork_and_edit_path(project, ref, path)
+ fork_modal_id = "modal-confirm-fork-edit"
+ elsif show_web_ide_button?
+ fork_path = ide_fork_and_edit_path(project, ref, path)
+ fork_modal_id = "modal-confirm-fork-webide"
+ end
+
+ {
+ fork_path: fork_path,
+ fork_modal_id: fork_modal_id
+ }
+ end
+
def web_ide_button_data(options = {})
{
project_path: project_to_use.full_path,
diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb
index b66c7f9f821..0aa4eb89499 100644
--- a/app/helpers/users/group_callouts_helper.rb
+++ b/app/helpers/users/group_callouts_helper.rb
@@ -3,6 +3,7 @@
module Users
module GroupCalloutsHelper
INVITE_MEMBERS_BANNER = 'invite_members_banner'
+ APPROACHING_SEAT_COUNT_THRESHOLD = 'approaching_seat_count_threshold'
def show_invite_banner?(group)
Ability.allowed?(current_user, :admin_group, group) &&
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index c64c2ab35fb..1247f9ae260 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -101,6 +101,7 @@ module UsersHelper
badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin?
badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external?
badges << { text: s_("AdminUsers|It's you!"), variant: 'muted' } if current_user == user
+ badges << { text: s_("AdminUsers|Locked"), variant: 'warning' } if user.access_locked?
end
end
@@ -124,7 +125,7 @@ module UsersHelper
end
def ban_feature_available?
- Feature.enabled?(:ban_user_feature_flag)
+ Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
end
def confirm_user_data(user)
@@ -171,6 +172,10 @@ module UsersHelper
}
end
+ def display_public_email?(user)
+ user.public_email.present?
+ end
+
private
def admin_users_paths
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index b64e6c59817..06ff18ca409 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -4,6 +4,7 @@ class ApplicationRecord < ActiveRecord::Base
include DatabaseReflection
include Transactions
include LegacyBulkInsert
+ include CrossDatabaseModification
self.abstract_class = true
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 3c9f7c4dd7f..02fbf0f855e 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -563,6 +563,12 @@ class ApplicationSetting < ApplicationRecord
presence: true, length: { maximum: 255 },
if: :sentry_enabled?
+ validates :users_get_by_id_limit,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :users_get_by_id_limit_allowlist,
+ length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') },
+ allow_nil: false
+
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 25198178f69..415f0b35f3a 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -69,7 +69,9 @@ module ApplicationSettingImplementation
domain_allowlist: Settings.gitlab['domain_allowlist'],
dsa_key_restriction: 0,
ecdsa_key_restriction: 0,
+ ecdsa_sk_key_restriction: 0,
ed25519_key_restriction: 0,
+ ed25519_sk_key_restriction: 0,
eks_access_key_id: nil,
eks_account_id: nil,
eks_integration_enabled: false,
@@ -229,7 +231,9 @@ module ApplicationSettingImplementation
rate_limiting_response_text: nil,
whats_new_variant: 0,
user_deactivation_emails_enabled: true,
- user_email_lookup_limit: 60
+ user_email_lookup_limit: 60,
+ users_get_by_id_limit: 300,
+ users_get_by_id_limit_allowlist: []
}
end
@@ -332,6 +336,14 @@ module ApplicationSettingImplementation
self.notes_create_limit_allowlist = strings_to_array(values).map(&:downcase)
end
+ def users_get_by_id_limit_allowlist_raw
+ array_to_string(self.users_get_by_id_limit_allowlist)
+ end
+
+ def users_get_by_id_limit_allowlist_raw=(values)
+ self.users_get_by_id_limit_allowlist = strings_to_array(values).map(&:downcase)
+ end
+
def asset_proxy_whitelist=(values)
values = strings_to_array(values) if values.is_a?(String)
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 35c4e08730e..8e8e9389e2d 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -69,8 +69,7 @@ class AuditEvent < ApplicationRecord
end
def author
- lazy_author&.itself.presence ||
- ::Gitlab::Audit::NullAuthor.for(author_id, (self[:author_name] || details[:author_name]))
+ lazy_author&.itself.presence || default_author_value
end
def lazy_author
@@ -98,7 +97,7 @@ class AuditEvent < ApplicationRecord
end
def default_author_value
- ::Gitlab::Audit::NullAuthor.for(author_id, (self[:author_name] || details[:author_name]))
+ ::Gitlab::Audit::NullAuthor.for(author_id, self)
end
def parallel_persist
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 5731d38abe4..cc7758d9674 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -178,6 +178,10 @@ class Blob < SimpleDelegator
end
end
+ def symlink?
+ mode == MODE_SYMLINK
+ end
+
def extension
@extension ||= extname.downcase.delete('.')
end
diff --git a/app/models/board.rb b/app/models/board.rb
index 7938819b6e4..8a7330e7320 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Board < ApplicationRecord
+ RECENT_BOARDS_SIZE = 4
+
belongs_to :group
belongs_to :project
diff --git a/app/models/ci/namespace_mirror.rb b/app/models/ci/namespace_mirror.rb
index ce3faf3546b..d5cbbb96134 100644
--- a/app/models/ci/namespace_mirror.rb
+++ b/app/models/ci/namespace_mirror.rb
@@ -6,7 +6,7 @@ module Ci
class NamespaceMirror < ApplicationRecord
belongs_to :namespace
- scope :contains_namespace, -> (id) do
+ scope :by_group_and_descendants, -> (id) do
where('traversal_ids @> ARRAY[?]::int[]', id)
end
@@ -32,7 +32,7 @@ module Ci
private
def sync_children_namespaces!(namespace_id, traversal_ids)
- contains_namespace(namespace_id)
+ by_group_and_descendants(namespace_id)
.where.not(namespace_id: namespace_id)
.update_all(
"traversal_ids = ARRAY[#{sanitize_sql(traversal_ids.join(','))}]::int[] || traversal_ids[array_position(traversal_ids, #{sanitize_sql(namespace_id)}) + 1:]"
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 00d331df4c3..a1311b8555f 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -40,6 +40,10 @@ module Ci
# https://gitlab.com/gitlab-org/gitlab/-/issues/259010
attr_accessor :merged_yaml
+ # This is used to retain access to the method defined by `Ci::HasRef`
+ # before being overridden in this class.
+ alias_method :jobs_git_ref, :git_ref
+
belongs_to :project, inverse_of: :all_pipelines
belongs_to :user
belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
@@ -72,8 +76,6 @@ module Ci
has_many :build_trace_chunks, class_name: 'Ci::BuildTraceChunk', through: :builds, source: :trace_chunks
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
- has_many :deployments, through: :builds
- has_many :environments, -> { distinct.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338658') }, through: :deployments
has_many :latest_builds, -> { latest.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build'
has_many :downloadable_artifacts, -> do
not_expired.or(where_exists(::Ci::Pipeline.artifacts_locked.where('ci_pipelines.id = ci_builds.commit_id'))).downloadable.with_job
@@ -352,7 +354,7 @@ module Ci
#
# ref - The name (or names) of the branch(es)/tag(s) to limit the list of
# pipelines to.
- # sha - The commit SHA (or mutliple SHAs) to limit the list of pipelines to.
+ # sha - The commit SHA (or multiple SHAs) to limit the list of pipelines to.
# limit - This limits a backlog search, default to 100.
def self.newest_first(ref: nil, sha: nil, limit: 100)
relation = order(id: :desc)
@@ -1163,7 +1165,11 @@ module Ci
end
def merge_request?
- merge_request_id.present?
+ if Feature.enabled?(:ci_pipeline_merge_request_presence_check, default_enabled: :yaml)
+ merge_request_id.present? && merge_request
+ else
+ merge_request_id.present?
+ end
end
def external_pull_request?
@@ -1284,18 +1290,6 @@ module Ci
end
end
- def create_deployment_in_separate_transaction?
- strong_memoize(:create_deployment_in_separate_transaction) do
- ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
- end
- end
-
- def use_variables_builder_definitions?
- strong_memoize(:use_variables_builder_definitions) do
- ::Feature.enabled?(:ci_use_variables_builder_definitions, project, default_enabled: :yaml)
- end
- end
-
private
def add_message(severity, content)
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 809c245d2b9..11150e839a3 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -13,7 +13,7 @@ module Ci
include TaggableQueries
include Presentable
- add_authentication_token_field :token, encrypted: :optional
+ add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration, expiration_enforced?: :token_expiration_enforced?
enum access_level: {
not_protected: 0,
@@ -67,7 +67,7 @@ module Ci
has_many :builds
has_many :runner_projects, inverse_of: :runner, autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :projects, through: :runner_projects
+ has_many :projects, through: :runner_projects, disable_joins: true
has_many :runner_namespaces, inverse_of: :runner, autosave: true
has_many :groups, through: :runner_namespaces, disable_joins: true
@@ -101,7 +101,7 @@ module Ci
}
scope :belonging_to_group_or_project_descendants, -> (group_id) {
- group_ids = Ci::NamespaceMirror.contains_namespace(group_id).select(:namespace_id)
+ group_ids = Ci::NamespaceMirror.by_group_and_descendants(group_id).select(:namespace_id)
project_ids = Ci::ProjectMirror.by_namespace_id(group_ids).select(:project_id)
group_runners = joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: group_ids })
@@ -119,30 +119,6 @@ module Ci
.where(ci_runner_namespaces: { namespace_id: group_self_and_ancestors_ids })
}
- # deprecated
- # split this into: belonging_to_group & belonging_to_group_and_ancestors
- scope :legacy_belonging_to_group, -> (group_id, include_ancestors: false) {
- groups = ::Group.where(id: group_id)
- groups = groups.self_and_ancestors if include_ancestors
-
- joins(:runner_namespaces)
- .where(ci_runner_namespaces: { namespace_id: groups })
- .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
- }
-
- # deprecated
- scope :legacy_belonging_to_group_or_project, -> (group_id, project_id) {
- groups = ::Group.where(id: group_id)
-
- group_runners = joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: groups })
- project_runners = joins(:runner_projects).where(ci_runner_projects: { project_id: project_id })
-
- union_sql = ::Gitlab::SQL::Union.new([group_runners, project_runners]).to_sql
-
- from("(#{union_sql}) #{table_name}")
- .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
- }
-
scope :belonging_to_parent_group_of_project, -> (project_id) {
raise ArgumentError, "only 1 project_id allowed for performance reasons" unless project_id.is_a?(Integer)
@@ -152,11 +128,23 @@ module Ci
}
scope :owned_or_instance_wide, -> (project_id) do
+ project = project_id.respond_to?(:shared_runners) ? project_id : Project.find(project_id)
+
from_union(
[
belonging_to_project(project_id),
- belonging_to_parent_group_of_project(project_id),
- instance_type
+ project.group_runners_enabled? ? belonging_to_parent_group_of_project(project_id) : nil,
+ project.shared_runners
+ ].compact,
+ remove_duplicates: false
+ )
+ end
+
+ scope :group_or_instance_wide, -> (group) do
+ from_union(
+ [
+ belonging_to_group_and_ancestors(group.id),
+ group.shared_runners
],
remove_duplicates: false
)
@@ -179,6 +167,8 @@ module Ci
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 :order_token_expires_at_asc, -> { order(token_expires_at: :asc) }
+ scope :order_token_expires_at_desc, -> { order(token_expires_at: :desc) }
scope :with_tags, -> { preload(:tags) }
validate :tag_constraints
@@ -210,7 +200,9 @@ module Ci
validates :config, json_schema: { filename: 'ci_runner_config' }
- validates :maintainer_note, length: { maximum: 255 }
+ validates :maintenance_note, length: { maximum: 255 }
+
+ alias_attribute :maintenance_note, :maintainer_note
# Searches for runners matching the given query.
#
@@ -247,6 +239,10 @@ module Ci
order_contacted_at_desc
when 'created_at_asc'
order_created_at_asc
+ when 'token_expires_at_asc'
+ order_token_expires_at_asc
+ when 'token_expires_at_desc'
+ order_token_expires_at_desc
else
order_created_at_desc
end
@@ -360,27 +356,12 @@ module Ci
runner_projects.any?
end
- # TODO: remove this method in favor of `matches_build?` once feature flag is removed
- # https://gitlab.com/gitlab-org/gitlab/-/issues/323317
- def can_pick?(build)
- if Feature.enabled?(:ci_runners_short_circuit_assignable_for, self, default_enabled: :yaml)
- matches_build?(build)
- else
- # Run `matches_build?` checks before, since they are cheaper than
- # `assignable_for?`.
- #
- matches_build?(build) && assignable_for?(build.project_id)
- end
- end
-
def match_build_if_online?(build)
- active? && online? && can_pick?(build)
+ active? && online? && matches_build?(build)
end
def only_for?(project)
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do
- projects == [project]
- end
+ !runner_projects.where.not(project_id: project.id).exists?
end
def short_sha
@@ -388,8 +369,6 @@ module Ci
end
def tag_list
- return super unless Feature.enabled?(:ci_preload_runner_tags, default_enabled: :yaml)
-
if tags.loaded?
tags.map(&:name)
else
@@ -455,6 +434,10 @@ module Ci
tick_runner_queue if matches_build?(build)
end
+ def matches_build?(build)
+ runner_matcher.matches?(build.build_matcher)
+ end
+
def uncached_contacted_at
read_attribute(:contacted_at)
end
@@ -465,6 +448,21 @@ module Ci
end
end
+ def compute_token_expiration
+ case runner_type
+ when 'instance_type'
+ compute_token_expiration_instance
+ when 'group_type'
+ compute_token_expiration_group
+ when 'project_type'
+ compute_token_expiration_project
+ end
+ end
+
+ def self.token_expiration_enforced?
+ Feature.enabled?(:enforce_runner_token_expires_at, default_enabled: :yaml)
+ end
+
private
EXECUTOR_NAME_TO_TYPES = {
@@ -484,6 +482,20 @@ module Ci
EXECUTOR_TYPE_TO_NAMES = EXECUTOR_NAME_TO_TYPES.invert.freeze
+ def compute_token_expiration_instance
+ return unless expiration_interval = Gitlab::CurrentSettings.runner_token_expiration_interval
+
+ expiration_interval.seconds.from_now
+ end
+
+ def compute_token_expiration_group
+ ::Group.where(id: runner_namespaces.map(&:namespace_id)).map(&:effective_runner_token_expiration_interval).compact.min&.from_now
+ end
+
+ def compute_token_expiration_project
+ Project.where(id: runner_projects.map(&:project_id)).map(&:effective_runner_token_expiration_interval).compact.min&.from_now
+ end
+
def cleanup_runner_queue
Gitlab::Redis::SharedState.with do |redis|
redis.del(runner_queue_key)
@@ -510,12 +522,6 @@ module Ci
end
end
- # TODO: remove this method once feature flag ci_runners_short_circuit_assignable_for
- # is removed. https://gitlab.com/gitlab-org/gitlab/-/issues/323317
- def assignable_for?(project_id)
- self.class.owned_or_instance_wide(project_id).where(id: self.id).any?
- end
-
def no_projects
if runner_projects.any?
errors.add(:runner, 'cannot have projects assigned')
@@ -539,10 +545,6 @@ module Ci
errors.add(:runner, 'needs to be assigned to exactly one group')
end
end
-
- def matches_build?(build)
- runner_matcher.matches?(build.build_matcher)
- end
end
end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 33cd5de3518..07eaca87fad 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.36.0'
+ VERSION = '0.37.1'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/commit.rb b/app/models/commit.rb
index f0c5f3c2d12..5293bfcf1ab 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -513,9 +513,7 @@ class Commit
# We don't want to do anything for `Commit` model, so this is empty.
end
- # WIP is deprecated in favor of Draft. Currently both options are supported
- # https://gitlab.com/gitlab-org/gitlab/-/issues/227426
- DRAFT_REGEX = /\A\s*#{Regexp.union(Gitlab::Regex.merge_request_wip, Gitlab::Regex.merge_request_draft)}|(fixup!|squash!)\s/.freeze
+ DRAFT_REGEX = /\A\s*#{Gitlab::Regex.merge_request_draft}|(fixup!|squash!)\s/.freeze
def work_in_progress?
!!(title =~ DRAFT_REGEX)
diff --git a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
index 324e0fb57cb..7cc4bc569d3 100644
--- a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
+++ b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
module Analytics
module CycleAnalytics
module StageEventModel
@@ -16,12 +15,39 @@ module Analytics
scope :authored, ->(user) { where(author_id: user) }
scope :with_milestone_id, ->(milestone_id) { where(milestone_id: milestone_id) }
scope :end_event_is_not_happened_yet, -> { where(end_event_timestamp: nil) }
+ scope :order_by_end_event, -> (direction) do
+ # ORDER BY end_event_timestamp, merge_request_id/issue_id, start_event_timestamp
+ # start_event_timestamp must be included in the ORDER BY clause for the duration
+ # calculation to work: SELECT end_event_timestamp - start_event_timestamp
+ keyset_order(
+ :end_event_timestamp => { order_expression: arel_order(arel_table[:end_event_timestamp], direction), distinct: false },
+ issuable_id_column => { order_expression: arel_order(arel_table[issuable_id_column], direction), distinct: true },
+ :start_event_timestamp => { order_expression: arel_order(arel_table[:start_event_timestamp], direction), distinct: false }
+ )
+ end
+ scope :order_by_duration, -> (direction) do
+ # ORDER BY EXTRACT('epoch', end_event_timestamp - start_event_timestamp)
+ duration = Arel::Nodes::Subtraction.new(
+ arel_table[:end_event_timestamp],
+ arel_table[:start_event_timestamp]
+ )
+ duration_in_seconds = Arel::Nodes::Extract.new(duration, :epoch)
+
+ keyset_order(
+ :total_time => { order_expression: arel_order(duration_in_seconds, direction), distinct: false, sql_type: 'double precision' },
+ issuable_id_column => { order_expression: arel_order(arel_table[issuable_id_column], direction), distinct: true }
+ )
+ end
end
def issuable_id
attributes[self.class.issuable_id_column.to_s]
end
+ def total_time
+ read_attribute(:total_time) || (end_event_timestamp - start_event_timestamp).to_f
+ end
+
class_methods do
def upsert_data(data)
upsert_values = data.map do |row|
@@ -68,6 +94,18 @@ module Analytics
result = connection.execute(query)
result.cmd_tuples
end
+
+ def keyset_order(column_definition_options)
+ built_definitions = column_definition_options.map do |attribute_name, column_options|
+ ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: attribute_name, **column_options)
+ end
+
+ order(Gitlab::Pagination::Keyset::Order.build(built_definitions))
+ end
+
+ def arel_order(arel_node, direction)
+ direction.to_sym == :desc ? arel_node.desc : arel_node.asc
+ end
end
end
end
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index ed3b422251f..88b7bb89b89 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -11,26 +11,9 @@ module Ci
#
def scoped_variables(environment: expanded_environment_name, dependencies: true)
track_duration do
- variables = pipeline.variables_builder.scoped_variables(self, environment: environment, dependencies: dependencies)
-
- next variables if pipeline.use_variables_builder_definitions?
-
- variables.concat(project.predefined_variables)
- variables.concat(pipeline.predefined_variables)
- variables.concat(runner.predefined_variables) if runnable? && runner
- variables.concat(kubernetes_variables)
- variables.concat(deployment_variables(environment: environment))
- variables.concat(yaml_variables)
- variables.concat(user_variables)
- variables.concat(dependency_variables) if dependencies
- variables.concat(secret_instance_variables)
- variables.concat(secret_group_variables(environment: environment))
- variables.concat(secret_project_variables(environment: environment))
- variables.concat(trigger_request.user_variables) if trigger_request
- variables.concat(pipeline.variables)
- variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline.pipeline_schedule
-
- variables
+ pipeline
+ .variables_builder
+ .scoped_variables(self, environment: environment, dependencies: dependencies)
end
end
@@ -60,29 +43,5 @@ module Ci
scoped_variables(environment: nil, dependencies: false)
end
end
-
- def user_variables
- pipeline.variables_builder.user_variables(user)
- end
-
- def kubernetes_variables
- pipeline.variables_builder.kubernetes_variables(self)
- end
-
- def deployment_variables(environment:)
- pipeline.variables_builder.deployment_variables(job: self, environment: environment)
- end
-
- def secret_instance_variables
- pipeline.variables_builder.secret_instance_variables(ref: git_ref)
- end
-
- def secret_group_variables(environment: expanded_environment_name)
- pipeline.variables_builder.secret_group_variables(environment: environment, ref: git_ref)
- end
-
- def secret_project_variables(environment: expanded_environment_name)
- pipeline.variables_builder.secret_project_variables(environment: environment, ref: git_ref)
- end
end
end
diff --git a/app/models/concerns/ci/has_variable.rb b/app/models/concerns/ci/has_variable.rb
index 7309469c77e..3b437fbba16 100644
--- a/app/models/concerns/ci/has_variable.rb
+++ b/app/models/concerns/ci/has_variable.rb
@@ -31,7 +31,24 @@ module Ci
end
def to_runner_variable
+ var_cache_key = to_runner_variable_cache_key
+
+ return uncached_runner_variable unless var_cache_key
+
+ ::Gitlab::SafeRequestStore.fetch(var_cache_key) { uncached_runner_variable }
+ end
+
+ private
+
+ def uncached_runner_variable
{ key: key, value: value, public: false, file: file? }
end
+
+ def to_runner_variable_cache_key
+ return unless persisted?
+
+ variable_id = read_attribute(self.class.primary_key)
+ "#{self.class}#to_runner_variable:#{variable_id}:#{key}"
+ end
end
end
diff --git a/app/models/concerns/cross_database_modification.rb b/app/models/concerns/cross_database_modification.rb
new file mode 100644
index 00000000000..85645e482f6
--- /dev/null
+++ b/app/models/concerns/cross_database_modification.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+module CrossDatabaseModification
+ extend ActiveSupport::Concern
+
+ class TransactionStackTrackRecord
+ DEBUG_STACK = Rails.env.test? && ENV['DEBUG_GITLAB_TRANSACTION_STACK']
+ LOG_FILENAME = Rails.root.join("log", "gitlab_transaction_stack.log")
+
+ EXCLUDE_DEBUG_TRACE = %w[
+ lib/gitlab/database/query_analyzer
+ app/models/concerns/cross_database_modification.rb
+ ].freeze
+
+ def self.logger
+ @logger ||= Logger.new(LOG_FILENAME, formatter: ->(_, _, _, msg) { Gitlab::Json.dump(msg) + "\n" })
+ end
+
+ def self.log_gitlab_transactions_stack(action: nil, example: nil)
+ return unless DEBUG_STACK
+
+ message = "gitlab_transactions_stack performing #{action}"
+ message += " in example #{example}" if example
+
+ cleaned_backtrace = Gitlab::BacktraceCleaner.clean_backtrace(caller)
+ .reject { |line| EXCLUDE_DEBUG_TRACE.any? { |exclusion| line.include?(exclusion) } }
+ .first(5)
+
+ logger.warn({
+ message: message,
+ action: action,
+ gitlab_transactions_stack: ::ApplicationRecord.gitlab_transactions_stack,
+ caller: cleaned_backtrace,
+ thread: Thread.current.object_id
+ })
+ end
+
+ def initialize(subject, gitlab_schema)
+ @subject = subject
+ @gitlab_schema = gitlab_schema
+ @subject.gitlab_transactions_stack.push(gitlab_schema)
+
+ self.class.log_gitlab_transactions_stack(action: :after_push)
+ end
+
+ def done!
+ unless @done
+ @done = true
+
+ self.class.log_gitlab_transactions_stack(action: :before_pop)
+ @subject.gitlab_transactions_stack.pop
+ end
+
+ true
+ end
+
+ def trigger_transactional_callbacks?
+ false
+ end
+
+ def before_committed!
+ end
+
+ def rolledback!(force_restore_state: false, should_run_callbacks: true)
+ done!
+ end
+
+ def committed!(should_run_callbacks: true)
+ done!
+ end
+ end
+
+ included do
+ private_class_method :gitlab_schema
+ end
+
+ class_methods do
+ def gitlab_transactions_stack
+ Thread.current[:gitlab_transactions_stack] ||= []
+ end
+
+ def transaction(**options, &block)
+ if track_gitlab_schema_in_current_transaction?
+ super(**options) do
+ # Hook into current transaction to ensure that once
+ # the `COMMIT` is executed the `gitlab_transactions_stack`
+ # will be allowing to execute `after_commit_queue`
+ record = TransactionStackTrackRecord.new(self, gitlab_schema)
+
+ begin
+ connection.current_transaction.add_record(record)
+
+ yield
+ ensure
+ record.done!
+ end
+ end
+ else
+ super(**options, &block)
+ end
+ end
+
+ def track_gitlab_schema_in_current_transaction?
+ return false unless Feature::FlipperFeature.table_exists?
+
+ Feature.enabled?(:track_gitlab_schema_in_current_transaction, default_enabled: :yaml)
+ rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
+ false
+ end
+
+ def gitlab_schema
+ case self.name
+ when 'ActiveRecord::Base', 'ApplicationRecord'
+ :gitlab_main
+ when 'Ci::ApplicationRecord'
+ :gitlab_ci
+ else
+ Gitlab::Database::GitlabSchema.table_schema(table_name) if table_name
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/has_environment_scope.rb b/app/models/concerns/has_environment_scope.rb
index 9553abe4dd3..c01996c0c4c 100644
--- a/app/models/concerns/has_environment_scope.rb
+++ b/app/models/concerns/has_environment_scope.rb
@@ -70,6 +70,14 @@ module HasEnvironmentScope
relation
end
+
+ scope :for_environment, ->(environment) do
+ if environment
+ on_environment(environment)
+ else
+ where(environment_scope: '*')
+ end
+ end
end
def environment_scope=(new_environment_scope)
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index dcd80201d3f..0138c0ad20f 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -194,6 +194,8 @@ module Issuable
end
def supports_escalation?
+ return false unless ::Feature.enabled?(:incident_escalations, project)
+
incident?
end
@@ -363,9 +365,10 @@ module Issuable
end
# Includes table keys in group by clause when sorting
- # preventing errors in postgres
+ # preventing errors in Postgres
+ #
+ # Returns an array of Arel columns
#
- # Returns an array of arel columns
def grouping_columns(sort)
sort = sort.to_s
grouping_columns = [arel_table[:id]]
@@ -384,9 +387,10 @@ module Issuable
end
# Includes all table keys in group by clause when sorting
- # preventing errors in postgres when using CTE search optimisation
+ # preventing errors in Postgres when using CTE search optimization
+ #
+ # Returns an array of Arel columns
#
- # Returns an array of arel columns
def issue_grouping_columns(use_cte: false)
if use_cte
attribute_names.map { |attr| arel_table[attr.to_sym] }
@@ -576,7 +580,7 @@ module Issuable
##
# Overridden in MergeRequest
#
- def wipless_title_changed(old_title)
+ def draftless_title_changed(old_title)
old_title != title
end
end
diff --git a/app/models/concerns/mirror_authentication.rb b/app/models/concerns/mirror_authentication.rb
index 4dbf4dcec77..14c8be93ce0 100644
--- a/app/models/concerns/mirror_authentication.rb
+++ b/app/models/concerns/mirror_authentication.rb
@@ -4,11 +4,6 @@
# implements support for persisting the necessary data in a `credentials`
# serialized attribute. It also needs an `url` method to be defined
module MirrorAuthentication
- SSH_PRIVATE_KEY_OPTS = {
- type: 'RSA',
- bits: 4096
- }.freeze
-
extend ActiveSupport::Concern
included do
@@ -84,10 +79,10 @@ module MirrorAuthentication
return if ssh_private_key.blank?
comment = "git@#{::Gitlab.config.gitlab.host}"
- ::SSHKey.new(ssh_private_key, comment: comment).ssh_public_key
+ SSHData::PrivateKey.parse(ssh_private_key).first.public_key.openssh(comment: comment)
end
def generate_ssh_private_key!
- self.ssh_private_key = ::SSHKey.generate(SSH_PRIVATE_KEY_OPTS).private_key
+ self.ssh_private_key = SSHData::PrivateKey::RSA.generate(4096).openssl.to_pem
end
end
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index ea4fe5b27dc..c1aac235d33 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -176,7 +176,7 @@ module Noteable
Gitlab::Routing.url_helpers.project_noteable_notes_path(
project,
- target_type: self.class.name.underscore,
+ target_type: noteable_target_type_name,
target_id: id
)
end
@@ -201,6 +201,10 @@ module Noteable
project_email.sub('@', "-#{iid}@")
end
+ def noteable_target_type_name
+ model_name.singular
+ end
+
private
# Synthetic system notes don't have discussion IDs because these are generated dynamically
diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb
index 2d46889ce6a..1520ec0828e 100644
--- a/app/models/concerns/packages/debian/distribution.rb
+++ b/app/models/concerns/packages/debian/distribution.rb
@@ -97,12 +97,8 @@ module Packages
end
def package_files
- if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- ::Packages::PackageFile.installable
- .for_package_ids(packages.select(:id))
- else
- ::Packages::PackageFile.for_package_ids(packages.select(:id))
- end
+ ::Packages::PackageFile.installable
+ .for_package_ids(packages.select(:id))
end
private
diff --git a/app/models/concerns/resolvable_discussion.rb b/app/models/concerns/resolvable_discussion.rb
index aae338e9759..92a88d2f7c8 100644
--- a/app/models/concerns/resolvable_discussion.rb
+++ b/app/models/concerns/resolvable_discussion.rb
@@ -99,6 +99,12 @@ module ResolvableDiscussion
update { |notes| notes.unresolve! }
end
+ def clear_memoized_values
+ self.class.memoized_values.each do |name|
+ clear_memoization(name)
+ end
+ end
+
private
def update
@@ -110,8 +116,6 @@ module ResolvableDiscussion
# Set the notes array to the updated notes
@notes = notes_relation.fresh.to_a # rubocop:disable Gitlab/ModuleWithInstanceVariables
- self.class.memoized_values.each do |name|
- clear_memoization(name)
- end
+ clear_memoized_values
end
end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index 4d1c1d44af7..e41a0ca28f9 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -15,17 +15,16 @@ module Taskable
INCOMPLETE_PATTERN = /(\[\s\])/.freeze
ITEM_PATTERN = %r{
^
- (?:(?:>\s{0,4})*) # optional blockquote characters
- (?:\s*(?:[-+*]|(?:\d+\.)))+ # list prefix (one or more) required - task item has to be always in a list
- \s+ # whitespace prefix has to be always presented for a list item
- (\[\s\]|\[[xX]\]) # checkbox
- (\s.+) # followed by whitespace and some text.
+ (?:(?:>\s{0,4})*) # optional blockquote characters
+ ((?:\s*(?:[-+*]|(?:\d+\.)))+) # list prefix (one or more) required - task item has to be always in a list
+ \s+ # whitespace prefix has to be always presented for a list item
+ (\[\s\]|\[[xX]\]) # checkbox
+ (\s.+) # followed by whitespace and some text.
}x.freeze
def self.get_tasks(content)
- content.to_s.scan(ITEM_PATTERN).map do |checkbox, label|
- # ITEM_PATTERN strips out the hyphen, but Item requires it. Rabble rabble.
- TaskList::Item.new("- #{checkbox}", label.strip)
+ content.to_s.scan(ITEM_PATTERN).map do |prefix, checkbox, label|
+ TaskList::Item.new("#{prefix} #{checkbox}", label.strip)
end
end
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb
index 3fe9d7f4d71..943ef3fa59f 100644
--- a/app/models/concerns/timebox.rb
+++ b/app/models/concerns/timebox.rb
@@ -51,7 +51,7 @@ module Timebox
validate :dates_within_4_digits
cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :description
+ cache_markdown_field :description, issuable_reference_expansion_enabled: true
belongs_to :project
belongs_to :group
@@ -125,17 +125,6 @@ module Timebox
fuzzy_search(query, [:title, :description])
end
- # Searches for timeboxes with a matching title.
- #
- # This method uses ILIKE on PostgreSQL
- #
- # query - The search query as a String
- #
- # Returns an ActiveRecord::Relation.
- def search_title(query)
- fuzzy_search(query, [:title])
- end
-
def filter_by_state(timeboxes, state)
case state
when 'closed' then timeboxes.closed
diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb
index 34c8630bb90..f44ad8ebe90 100644
--- a/app/models/concerns/token_authenticatable.rb
+++ b/app/models/concerns/token_authenticatable.rb
@@ -64,6 +64,18 @@ module TokenAuthenticatable
mod.define_method("format_#{token_field}") do |token|
token
end
+
+ mod.define_method("#{token_field}_expires_at") do
+ strategy.expires_at(self)
+ end
+
+ mod.define_method("#{token_field}_expired?") do
+ strategy.expired?(self)
+ end
+
+ mod.define_method("#{token_field}_with_expiration") do
+ strategy.token_with_expiration(self)
+ end
end
def token_authenticatable_module
diff --git a/app/models/concerns/token_authenticatable_strategies/base.rb b/app/models/concerns/token_authenticatable_strategies/base.rb
index f72a41f06b1..2cec4ab460e 100644
--- a/app/models/concerns/token_authenticatable_strategies/base.rb
+++ b/app/models/concerns/token_authenticatable_strategies/base.rb
@@ -7,6 +7,7 @@ module TokenAuthenticatableStrategies
def initialize(klass, token_field, options)
@klass = klass
@token_field = token_field
+ @expires_at_field = "#{token_field}_expires_at"
@options = options
end
@@ -44,6 +45,25 @@ module TokenAuthenticatableStrategies
instance.save! if Gitlab::Database.read_write?
end
+ def expires_at(instance)
+ instance.read_attribute(@expires_at_field)
+ end
+
+ def expired?(instance)
+ return false unless expirable? && token_expiration_enforced?
+
+ exp = expires_at(instance)
+ !!exp && Time.current > exp
+ end
+
+ def expirable?
+ !!@options[:expires_at]
+ end
+
+ def token_with_expiration(instance)
+ API::Support::TokenWithExpiration.new(self, instance)
+ end
+
def self.fabricate(model, field, options)
if options[:digest] && options[:encrypted]
raise ArgumentError, _('Incompatible options set!')
@@ -64,6 +84,10 @@ module TokenAuthenticatableStrategies
new_token = generate_available_token
formatted_token = format_token(instance, new_token)
set_token(instance, formatted_token)
+
+ if expirable?
+ instance[@expires_at_field] = @options[:expires_at].to_proc.call(instance)
+ end
end
def unique
@@ -82,11 +106,21 @@ module TokenAuthenticatableStrategies
end
def relation(unscoped)
- unscoped ? @klass.unscoped : @klass
+ unscoped ? @klass.unscoped : @klass.where(not_expired)
end
def token_set?(instance)
raise NotImplementedError
end
+
+ def token_expiration_enforced?
+ return true unless @options[:expiration_enforced?]
+
+ @options[:expiration_enforced?].to_proc.call(@klass)
+ end
+
+ def not_expired
+ Arel.sql("#{@expires_at_field} IS NULL OR #{@expires_at_field} >= NOW()") if expirable? && token_expiration_enforced?
+ end
end
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index b03d946fc47..1f123cb0244 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -5,15 +5,24 @@ class ContainerRepository < ApplicationRecord
include Gitlab::SQL::Pattern
include EachBatch
include Sortable
+ include AfterCommitQueue
WAITING_CLEANUP_STATUSES = %i[cleanup_scheduled cleanup_unfinished].freeze
REQUIRING_CLEANUP_STATUSES = %i[cleanup_unscheduled cleanup_scheduled].freeze
+ IDLE_MIGRATION_STATES = %w[default pre_import_done import_done import_aborted import_skipped].freeze
+ ACTIVE_MIGRATION_STATES = %w[pre_importing importing].freeze
+ ABORTABLE_MIGRATION_STATES = (ACTIVE_MIGRATION_STATES + %w[pre_import_done default]).freeze
+ MIGRATION_STATES = (IDLE_MIGRATION_STATES + ACTIVE_MIGRATION_STATES).freeze
+
+ TooManyImportsError = Class.new(StandardError)
+ NativeImportError = Class.new(StandardError)
belongs_to :project
validates :name, length: { minimum: 0, allow_nil: false }
validates :name, uniqueness: { scope: :project_id }
- validates :migration_state, presence: true
+ validates :migration_state, presence: true, inclusion: { in: MIGRATION_STATES }
+ validates :migration_aborted_in_state, inclusion: { in: ABORTABLE_MIGRATION_STATES }, allow_nil: true
validates :migration_retries_count, presence: true,
numericality: { greater_than_or_equal_to: 0 },
@@ -23,7 +32,7 @@ class ContainerRepository < ApplicationRecord
enum expiration_policy_cleanup_status: { cleanup_unscheduled: 0, cleanup_scheduled: 1, cleanup_unfinished: 2, cleanup_ongoing: 3 }
enum migration_skipped_reason: { not_in_plan: 0, too_many_retries: 1, too_many_tags: 2, root_namespace_in_deny_list: 3 }
- delegate :client, to: :registry
+ delegate :client, :gitlab_api_client, to: :registry
scope :ordered, -> { order(:name) }
scope :with_api_entity_associations, -> { preload(project: [:route, { namespace: :route }]) }
@@ -39,7 +48,152 @@ 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_migration_import_started_at_nil_or_before, ->(timestamp) { where("COALESCE(migration_import_started_at, '01-01-1970') < ?", timestamp) }
+ scope :with_migration_pre_import_started_at_nil_or_before, ->(timestamp) { where("COALESCE(migration_pre_import_started_at, '01-01-1970') < ?", timestamp) }
+ scope :with_migration_pre_import_done_at_nil_or_before, ->(timestamp) { where("COALESCE(migration_pre_import_done_at, '01-01-1970') < ?", timestamp) }
scope :with_stale_ongoing_cleanup, ->(threshold) { cleanup_ongoing.where('expiration_policy_started_at < ?', threshold) }
+ scope :import_in_process, -> { where(migration_state: %w[pre_importing pre_import_done importing]) }
+
+ scope :recently_done_migration_step, -> do
+ where(migration_state: %w[import_done pre_import_done import_aborted])
+ .order(Arel.sql('GREATEST(migration_pre_import_done_at, migration_import_done_at, migration_aborted_at) DESC'))
+ end
+
+ scope :ready_for_import, -> do
+ # There is no yaml file for the container_registry_phase_2_deny_list
+ # feature flag since it is only accessed in this query.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350543 tracks the rollout and
+ # removal of this feature flag.
+ joins(:project).where(
+ migration_state: [:default],
+ created_at: ...ContainerRegistry::Migration.created_before
+ ).with_target_import_tier
+ .where(
+ "NOT EXISTS (
+ SELECT 1
+ FROM feature_gates
+ WHERE feature_gates.feature_key = 'container_registry_phase_2_deny_list'
+ AND feature_gates.key = 'actors'
+ AND feature_gates.value = concat('Group:', projects.namespace_id)
+ )"
+ )
+ end
+
+ state_machine :migration_state, initial: :default, use_transactions: false do
+ state :pre_importing do
+ validates :migration_pre_import_started_at, presence: true
+ validates :migration_pre_import_done_at, presence: false
+ end
+
+ state :pre_import_done do
+ validates :migration_pre_import_done_at, presence: true
+ end
+
+ state :importing do
+ validates :migration_import_started_at, presence: true
+ validates :migration_import_done_at, presence: false
+ end
+
+ state :import_done
+
+ state :import_skipped do
+ validates :migration_skipped_reason,
+ :migration_skipped_at,
+ presence: true
+ end
+
+ state :import_aborted do
+ validates :migration_aborted_at, presence: true
+ validates :migration_retries_count, presence: true, numericality: { greater_than_or_equal_to: 1 }
+ end
+
+ event :start_pre_import do
+ transition default: :pre_importing
+ end
+
+ event :finish_pre_import do
+ transition %i[pre_importing import_aborted] => :pre_import_done
+ end
+
+ event :start_import do
+ transition pre_import_done: :importing
+ end
+
+ event :finish_import do
+ transition %i[importing import_aborted] => :import_done
+ end
+
+ event :already_migrated do
+ transition default: :import_done
+ end
+
+ event :abort_import do
+ transition ABORTABLE_MIGRATION_STATES.map(&:to_sym) => :import_aborted
+ end
+
+ event :skip_import do
+ transition ABORTABLE_MIGRATION_STATES.map(&:to_sym) => :import_skipped
+ end
+
+ event :retry_pre_import do
+ transition import_aborted: :pre_importing
+ end
+
+ event :retry_import do
+ transition import_aborted: :importing
+ end
+
+ before_transition any => :pre_importing do |container_repository|
+ container_repository.migration_pre_import_started_at = Time.zone.now
+ container_repository.migration_pre_import_done_at = nil
+ end
+
+ after_transition any => :pre_importing do |container_repository|
+ container_repository.try_import do
+ container_repository.migration_pre_import
+ end
+ end
+
+ before_transition %i[pre_importing import_aborted] => :pre_import_done do |container_repository|
+ container_repository.migration_pre_import_done_at = Time.zone.now
+ end
+
+ before_transition any => :importing do |container_repository|
+ container_repository.migration_import_started_at = Time.zone.now
+ container_repository.migration_import_done_at = nil
+ end
+
+ after_transition any => :importing do |container_repository|
+ container_repository.try_import do
+ container_repository.migration_import
+ end
+ end
+
+ before_transition %i[importing import_aborted] => :import_done do |container_repository|
+ container_repository.migration_import_done_at = Time.zone.now
+ end
+
+ before_transition any => :import_aborted do |container_repository|
+ container_repository.migration_aborted_in_state = container_repository.migration_state
+ container_repository.migration_aborted_at = Time.zone.now
+ container_repository.migration_retries_count += 1
+ end
+
+ before_transition import_aborted: any do |container_repository|
+ container_repository.migration_aborted_at = nil
+ container_repository.migration_aborted_in_state = nil
+ end
+
+ before_transition any => :import_skipped do |container_repository|
+ container_repository.migration_skipped_at = Time.zone.now
+ end
+
+ before_transition any => %i[import_done import_aborted] do |container_repository|
+ container_repository.run_after_commit do
+ ::ContainerRegistry::Migration::EnqueuerWorker.perform_async
+ end
+ end
+ end
def self.exists_by_path?(path)
where(
@@ -64,6 +218,114 @@ class ContainerRepository < ApplicationRecord
with_enabled_policy.cleanup_unfinished
end
+ def self.with_stale_migration(before_timestamp)
+ stale_pre_importing = with_migration_states(:pre_importing)
+ .with_migration_pre_import_started_at_nil_or_before(before_timestamp)
+ stale_pre_import_done = with_migration_states(:pre_import_done)
+ .with_migration_pre_import_done_at_nil_or_before(before_timestamp)
+ stale_importing = with_migration_states(:importing)
+ .with_migration_import_started_at_nil_or_before(before_timestamp)
+
+ union = ::Gitlab::SQL::Union.new([
+ stale_pre_importing,
+ stale_pre_import_done,
+ stale_importing
+ ])
+ from("(#{union.to_sql}) #{ContainerRepository.table_name}")
+ end
+
+ def self.with_target_import_tier
+ # overridden in ee
+ #
+ # Repositories are being migrated by tier on Saas, so we need to
+ # filter by plan/subscription which is not available in FOSS
+ all
+ end
+
+ def skip_import(reason:)
+ self.migration_skipped_reason = reason
+
+ super
+ end
+
+ def start_pre_import
+ return false unless ContainerRegistry::Migration.enabled?
+
+ super
+ end
+
+ def retry_pre_import
+ return false unless ContainerRegistry::Migration.enabled?
+
+ super
+ end
+
+ def retry_import
+ return false unless ContainerRegistry::Migration.enabled?
+
+ super
+ end
+
+ def finish_pre_import_and_start_import
+ # nothing to do between those two transitions for now.
+ finish_pre_import && start_import
+ end
+
+ def retry_aborted_migration
+ return unless migration_state == 'import_aborted'
+
+ case external_import_status
+ when 'native'
+ raise NativeImportError
+ when 'import_in_progress'
+ nil
+ when 'import_complete'
+ finish_import
+ when 'import_failed'
+ retry_import
+ when 'pre_import_in_progress'
+ nil
+ when 'pre_import_complete'
+ finish_pre_import_and_start_import
+ when 'pre_import_failed'
+ retry_pre_import
+ else
+ # If the import_status request fails, use the timestamp to guess current state
+ migration_pre_import_done_at ? retry_import : retry_pre_import
+ end
+ end
+
+ def try_import
+ raise ArgumentError, 'block not given' unless block_given?
+
+ try_count = 0
+ begin
+ try_count += 1
+ return true if yield == :ok
+
+ abort_import
+ false
+ rescue TooManyImportsError
+ if try_count <= ::ContainerRegistry::Migration.start_max_retries
+ sleep 0.1 * try_count
+ retry
+ else
+ abort_import
+ false
+ end
+ end
+ end
+
+ def last_import_step_done_at
+ [migration_pre_import_done_at, migration_import_done_at, migration_aborted_at].compact.max
+ end
+
+ def external_import_status
+ strong_memoize(:import_status) do
+ gitlab_api_client.import_status(self.path)
+ end
+ end
+
# rubocop: disable CodeReuse/ServiceClass
def registry
@registry ||= begin
@@ -146,6 +408,36 @@ class ContainerRepository < ApplicationRecord
update!(expiration_policy_started_at: Time.zone.now)
end
+ def migration_in_active_state?
+ migration_state.in?(ACTIVE_MIGRATION_STATES)
+ end
+
+ def migration_importing?
+ migration_state == 'importing'
+ end
+
+ def migration_pre_importing?
+ migration_state == 'pre_importing'
+ end
+
+ def migration_pre_import
+ return :error unless gitlab_api_client.supports_gitlab_api?
+
+ response = gitlab_api_client.pre_import_repository(self.path)
+ raise TooManyImportsError if response == :too_many_imports
+
+ response
+ end
+
+ def migration_import
+ return :error unless gitlab_api_client.supports_gitlab_api?
+
+ response = gitlab_api_client.import_repository(self.path)
+ raise TooManyImportsError if response == :too_many_imports
+
+ response
+ end
+
def self.build_from_path(path)
self.new(project: path.repository_project,
name: path.repository_name)
@@ -169,6 +461,11 @@ class ContainerRepository < ApplicationRecord
self.find_by!(project: path.repository_project,
name: path.repository_name)
end
+
+ def self.find_by_path(path)
+ self.find_by(project: path.repository_project,
+ name: path.repository_name)
+ end
end
ContainerRepository.prepend_mod_with('ContainerRepository')
diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb
index 168f1c48a6c..a981351f4a0 100644
--- a/app/models/customer_relations/contact.rb
+++ b/app/models/customer_relations/contact.rb
@@ -26,6 +26,18 @@ class CustomerRelations::Contact < ApplicationRecord
validate :validate_email_format
validate :unique_email_for_group_hierarchy
+ def self.reference_prefix
+ '[contact:'
+ end
+
+ def self.reference_prefix_quoted
+ '["contact:'
+ end
+
+ def self.reference_postfix
+ ']'
+ end
+
def self.find_ids_by_emails(group, emails)
raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK
@@ -33,6 +45,12 @@ class CustomerRelations::Contact < ApplicationRecord
.pluck(:id)
end
+ def self.exists_for_group?(group)
+ return false unless group
+
+ exists?(group_id: group.self_and_ancestor_ids)
+ end
+
private
def validate_email_format
diff --git a/app/models/customer_relations/issue_contact.rb b/app/models/customer_relations/issue_contact.rb
index 89dac6bad22..3e9d1e97c8c 100644
--- a/app/models/customer_relations/issue_contact.rb
+++ b/app/models/customer_relations/issue_contact.rb
@@ -16,6 +16,12 @@ class CustomerRelations::IssueContact < ApplicationRecord
.pluck(:contact_id)
end
+ def self.delete_for_project(project_id)
+ joins(:issue)
+ .where(issues: { project_id: project_id })
+ .delete_all
+ end
+
private
def contact_belongs_to_issue_group_or_ancestor
diff --git a/app/models/dependency_proxy/blob.rb b/app/models/dependency_proxy/blob.rb
index e4018ab4770..f7b08f1d077 100644
--- a/app/models/dependency_proxy/blob.rb
+++ b/app/models/dependency_proxy/blob.rb
@@ -14,6 +14,8 @@ class DependencyProxy::Blob < ApplicationRecord
validates :file, presence: true
validates :file_name, presence: true
+ scope :with_files_stored_locally, -> { where(file_store: ::DependencyProxy::FileUploader::Store::LOCAL) }
+
mount_file_store_uploader DependencyProxy::FileUploader
def self.total_size
@@ -24,3 +26,5 @@ class DependencyProxy::Blob < ApplicationRecord
find_or_initialize_by(file_name: file_name)
end
end
+
+DependencyProxy::Blob.prepend_mod_with('DependencyProxy::Blob')
diff --git a/app/models/dependency_proxy/manifest.rb b/app/models/dependency_proxy/manifest.rb
index fe887c99e81..c2587ffac9d 100644
--- a/app/models/dependency_proxy/manifest.rb
+++ b/app/models/dependency_proxy/manifest.rb
@@ -17,6 +17,7 @@ class DependencyProxy::Manifest < ApplicationRecord
validates :digest, presence: true
scope :order_id_desc, -> { reorder(id: :desc) }
+ scope :with_files_stored_locally, -> { where(file_store: ::DependencyProxy::FileUploader::Store::LOCAL) }
mount_file_store_uploader DependencyProxy::FileUploader
@@ -24,3 +25,5 @@ class DependencyProxy::Manifest < ApplicationRecord
find_by(file_name: file_name) || find_by(digest: digest)
end
end
+
+DependencyProxy::Manifest.prepend_mod_with('DependencyProxy::Manifest')
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 2f04d99f9f6..46409465209 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -255,10 +255,10 @@ class Deployment < ApplicationRecord
end
end
- def includes_commit?(commit)
- return false unless commit
+ def includes_commit?(ancestor_sha)
+ return false unless sha
- project.repository.ancestor?(commit.id, sha)
+ project.repository.ancestor?(ancestor_sha, sha)
end
def update_merge_request_metrics!
@@ -294,10 +294,6 @@ class Deployment < ApplicationRecord
@stop_action ||= manual_actions.find { |action| action.name == self.on_stop }
end
- def finished_at
- read_attribute(:finished_at) || legacy_finished_at
- end
-
def deployed_at
return unless success?
@@ -405,10 +401,6 @@ class Deployment < ApplicationRecord
raise ArgumentError, "The status #{status.inspect} is invalid"
end
end
-
- def legacy_finished_at
- self.created_at if success? && !read_attribute(:finished_at)
- end
end
Deployment.prepend_mod_with('Deployment')
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index 203e14f1227..8a167034629 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -25,7 +25,7 @@ class Discussion
:to_ability_name,
:editable?,
:resolved_by_id,
- :system_note_with_references_visible_for?,
+ :system_note_visible_for?,
:resource_parent,
:save,
to: :first_note
diff --git a/app/models/draft_note.rb b/app/models/draft_note.rb
index febede9beba..9f7977fce68 100644
--- a/app/models/draft_note.rb
+++ b/app/models/draft_note.rb
@@ -25,6 +25,7 @@ class DraftNote < ApplicationRecord
validates :merge_request_id, presence: true
validates :author_id, presence: true, uniqueness: { scope: [:merge_request_id, :discussion_id] }, if: :discussion_id?
validates :discussion_id, allow_nil: true, format: { with: /\A\h{40}\z/ }
+ validates :line_code, length: { maximum: 255 }, allow_nil: true
scope :authored_by, ->(u) { where(author_id: u.id) }
@@ -89,7 +90,11 @@ class DraftNote < ApplicationRecord
end
def line_code
- @line_code ||= diff_file&.line_code_for_position(original_position)
+ super.presence || find_line_code
+ end
+
+ def find_line_code
+ write_attribute(:line_code, diff_file&.line_code_for_position(original_position))
end
def publish_params
diff --git a/app/models/environment.rb b/app/models/environment.rb
index a830c04f291..51a9024721b 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -235,10 +235,10 @@ class Environment < ApplicationRecord
self.environment_type = names.many? ? names.first : nil
end
- def includes_commit?(commit)
+ def includes_commit?(sha)
return false unless last_deployment
- last_deployment.includes_commit?(commit)
+ last_deployment.includes_commit?(sha)
end
def last_deployed_at
diff --git a/app/models/event.rb b/app/models/event.rb
index 409bc66c66c..a8cf2e2dfb0 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -354,7 +354,7 @@ class Event < ApplicationRecord
# hence we add the extra WHERE clause for last_activity_at.
Project.unscoped.where(id: project_id)
.where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago)
- .update_all(last_activity_at: created_at)
+ .touch_all(:last_activity_at, time: created_at) # rubocop: disable Rails/SkipsModelValidations
end
def authored_by?(user)
@@ -430,7 +430,7 @@ class Event < ApplicationRecord
def set_last_repository_updated_at
Project.unscoped.where(id: project_id)
.where("last_repository_updated_at < ? OR last_repository_updated_at IS NULL", REPOSITORY_UPDATED_AT_INTERVAL.ago)
- .update_all(last_repository_updated_at: created_at)
+ .touch_all(:last_repository_updated_at, time: created_at) # rubocop: disable Rails/SkipsModelValidations
end
def design_action_names
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 3320c13e87b..7e538238cbd 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -50,8 +50,9 @@ class WebHook < ApplicationRecord
end
# rubocop: disable CodeReuse/ServiceClass
- def execute(data, hook_name)
- WebHookService.new(self, data, hook_name).execute if executable?
+ def execute(data, hook_name, force: false)
+ # hook.executable? is checked in WebHookService#execute
+ WebHookService.new(self, data, hook_name, force: force).execute
end
# rubocop: enable CodeReuse/ServiceClass
diff --git a/app/models/instance_configuration.rb b/app/models/instance_configuration.rb
index dc025e576ed..2016024b2f4 100644
--- a/app/models/instance_configuration.rb
+++ b/app/models/instance_configuration.rb
@@ -118,7 +118,12 @@ class InstanceConfiguration
group_export_download: application_setting_limit_per_minute(:group_download_export_limit),
group_import: application_setting_limit_per_minute(:group_import_limit),
raw_blob: application_setting_limit_per_minute(:raw_blob_request_limit),
- user_email_lookup: application_setting_limit_per_minute(:user_email_lookup_limit)
+ user_email_lookup: application_setting_limit_per_minute(:user_email_lookup_limit),
+ users_get_by_id: {
+ enabled: application_settings[:users_get_by_id_limit] > 0,
+ requests_per_period: application_settings[:users_get_by_id_limit],
+ period_in_seconds: 10.minutes
+ }
}
end
@@ -147,7 +152,7 @@ class InstanceConfiguration
end
def ssh_algorithm_sha256(ssh_file_content)
- Gitlab::SSHPublicKey.new(ssh_file_content).fingerprint('SHA256')
+ Gitlab::SSHPublicKey.new(ssh_file_content).fingerprint_sha256
end
def application_settings
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 89b34932e20..e9cd90649ba 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -392,8 +392,7 @@ class Integration < ApplicationRecord
end
def api_field_names
- fields.map { |field| field[:name] }
- .reject { |field_name| field_name =~ /(password|token|key|title|description)/ }
+ fields.pluck(:name).grep_v(/password|token|key|title|description/)
end
def global_fields
diff --git a/app/models/integrations/chat_message/base_message.rb b/app/models/integrations/chat_message/base_message.rb
index ab213f4b43f..554b422c0fa 100644
--- a/app/models/integrations/chat_message/base_message.rb
+++ b/app/models/integrations/chat_message/base_message.rb
@@ -47,16 +47,21 @@ module Integrations
format(message)
end
+ # NOTE: Make sure to call `#strip_markup` on any untrusted user input that's added to the
+ # `title`, `subtitle`, `text`, `fallback`, or `author_name` fields.
def attachments
raise NotImplementedError
end
+ # NOTE: Make sure to call `#strip_markup` on any untrusted user input that's added to the
+ # `title`, `subtitle`, `text`, `fallback`, or `author_name` fields.
def activity
raise NotImplementedError
end
private
+ # NOTE: Make sure to call `#strip_markup` on any untrusted user input that's added to the string.
def message
raise NotImplementedError
end
diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb
index b86f0aaa7ef..bb0fb6b9079 100644
--- a/app/models/integrations/datadog.rb
+++ b/app/models/integrations/datadog.rb
@@ -13,7 +13,11 @@ module Integrations
pipeline job
].freeze
- prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env
+ TAG_KEY_VALUE_RE = %r{\A [\w-]+ : .*\S.* \z}x.freeze
+
+ prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env, :datadog_tags
+
+ before_validation :strip_properties
with_options if: :activated? do
validates :api_key, presence: true, format: { with: /\A\w+\z/ }
@@ -21,6 +25,7 @@ module Integrations
validates :api_url, public_url: { allow_blank: true }
validates :datadog_site, presence: true, unless: -> (obj) { obj.api_url.present? }
validates :api_url, presence: true, unless: -> (obj) { obj.datadog_site.present? }
+ validate :datadog_tags_are_valid
end
def initialize_properties
@@ -140,6 +145,20 @@ module Integrations
linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
linkClose: '</a>'.html_safe
}
+ },
+ {
+ type: 'textarea',
+ name: 'datadog_tags',
+ title: s_('DatadogIntegration|Tags'),
+ placeholder: "tag:value\nanother_tag:value",
+ help: ERB::Util.html_escape(
+ s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe,
+ linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
+ linkClose: '</a>'.html_safe
+ }
}
]
@@ -153,7 +172,8 @@ module Integrations
query = {
"dd-api-key" => api_key,
service: datadog_service.presence,
- env: datadog_env.presence
+ env: datadog_env.presence,
+ tags: datadog_tags_query_param.presence
}.compact
url.query = query.to_query
url.to_s
@@ -193,5 +213,35 @@ module Integrations
data
end
+
+ def strip_properties
+ datadog_service.strip! if datadog_service && !datadog_service.frozen?
+ datadog_env.strip! if datadog_env && !datadog_env.frozen?
+ datadog_tags.strip! if datadog_tags && !datadog_tags.frozen?
+ end
+
+ def datadog_tags_are_valid
+ return unless datadog_tags
+
+ unless datadog_tags.split("\n").select(&:present?).all? { _1 =~ TAG_KEY_VALUE_RE }
+ errors.add(:datadog_tags, s_("DatadogIntegration|have an invalid format"))
+ end
+ end
+
+ def datadog_tags_query_param
+ return unless datadog_tags
+
+ datadog_tags.split("\n").filter_map do |tag|
+ tag.strip!
+
+ next if tag.blank?
+
+ if tag.include?(',')
+ "\"#{tag}\""
+ else
+ tag
+ end
+ end.join(',')
+ end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 4f2773f4147..68ea6cb3abc 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -29,8 +29,10 @@ class Issue < ApplicationRecord
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
- AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze
+ AnyDueDate = DueDateStruct.new('Any Due Date', 'any').freeze
Overdue = DueDateStruct.new('Overdue', 'overdue').freeze
+ DueToday = DueDateStruct.new('Due Today', 'today').freeze
+ DueTomorrow = DueDateStruct.new('Due Tomorrow', 'tomorrow').freeze
DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze
DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
@@ -107,7 +109,9 @@ class Issue < ApplicationRecord
scope :without_due_date, -> { where(due_date: nil) }
scope :due_before, ->(date) { where('issues.due_date < ?', date) }
scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) }
+ scope :due_today, -> { where(due_date: Date.current) }
scope :due_tomorrow, -> { where(due_date: Date.tomorrow) }
+
scope :not_authored_by, ->(user) { where.not(author_id: user) }
scope :order_due_date_asc, -> { reorder(::Gitlab::Database.nulls_last_order('due_date', 'ASC')) }
@@ -121,7 +125,6 @@ class Issue < ApplicationRecord
scope :preload_associated_models, -> { preload(:assignees, :labels, project: :namespace) }
scope :with_web_entity_associations, -> { preload(:author, project: [:project_feature, :route, namespace: :route]) }
scope :preload_awardable, -> { preload(:award_emoji) }
- scope :with_label_attributes, ->(label_attributes) { joins(:labels).where(labels: label_attributes) }
scope :with_alert_management_alerts, -> { joins(:alert_management_alert) }
scope :with_prometheus_alert_events, -> { joins(:issues_prometheus_alert_events) }
scope :with_self_managed_prometheus_alert_events, -> { joins(:issues_self_managed_prometheus_alert_events) }
@@ -140,7 +143,7 @@ class Issue < ApplicationRecord
scope :confidential_only, -> { where(confidential: true) }
scope :without_hidden, -> {
- if Feature.enabled?(:ban_user_feature_flag)
+ if Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
where('NOT EXISTS (?)', Users::BannedUser.select(1).where('issues.author_id = banned_users.user_id'))
else
all
@@ -584,7 +587,7 @@ class Issue < ApplicationRecord
def readable_by?(user)
if user.can_read_all_resources?
true
- elsif project.owner == user
+ elsif project.personal? && project.team.owner?(user)
true
elsif confidential? && !assignee_or_author?(user)
project.team.member?(user, Gitlab::Access::REPORTER)
diff --git a/app/models/key.rb b/app/models/key.rb
index 933c939fdf5..4a4e792c074 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -130,7 +130,7 @@ class Key < ApplicationRecord
return unless public_key.valid?
self.fingerprint_md5 = public_key.fingerprint
- self.fingerprint_sha256 = public_key.fingerprint("SHA256").gsub("SHA256:", "")
+ self.fingerprint_sha256 = public_key.fingerprint_sha256.gsub("SHA256:", "")
end
def key_meets_restrictions
diff --git a/app/models/loose_foreign_keys/deleted_record.rb b/app/models/loose_foreign_keys/deleted_record.rb
index db82d5bbf29..ebda5872f1c 100644
--- a/app/models/loose_foreign_keys/deleted_record.rb
+++ b/app/models/loose_foreign_keys/deleted_record.rb
@@ -46,17 +46,39 @@ class LooseForeignKeys::DeletedRecord < Gitlab::Database::SharedModel
.to_a
end
- def self.mark_records_processed(all_records)
- # Run a query for each partition to optimize the row lookup by primary key (partition, id)
+ def self.mark_records_processed(records)
+ update_by_partition(records) do |partitioned_scope|
+ partitioned_scope.update_all(status: :processed)
+ end
+ end
+
+ def self.reschedule(records, consume_after)
+ update_by_partition(records) do |partitioned_scope|
+ partitioned_scope.update_all(consume_after: consume_after, cleanup_attempts: 0)
+ end
+ end
+
+ def self.increment_attempts(records)
+ update_by_partition(records) do |partitioned_scope|
+ # Naive incrementing of the cleanup_attempts is good enough for us.
+ partitioned_scope.update_all('cleanup_attempts = cleanup_attempts + 1')
+ end
+ end
+
+ def self.update_by_partition(records)
update_count = 0
- all_records.group_by(&:partition_number).each do |partition, records_within_partition|
- update_count += status_pending
+ # Run a query for each partition to optimize the row lookup by primary key (partition, id)
+ records.group_by(&:partition_number).each do |partition, records_within_partition|
+ partitioned_scope = status_pending
.for_partition(partition)
.where(id: records_within_partition.pluck(:id))
- .update_all(status: :processed)
+
+ update_count += yield(partitioned_scope)
end
update_count
end
+
+ private_class_method :update_by_partition
end
diff --git a/app/models/member.rb b/app/models/member.rb
index 6c0503dca3f..528c6855d9c 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -108,6 +108,8 @@ class Member < ApplicationRecord
.reorder(nil)
end
+ scope :active_state, -> { where(state: STATE_ACTIVE) }
+
scope :connected_to_user, -> { where.not(user_id: nil) }
# This scope is exclusively used to get the members
@@ -115,6 +117,7 @@ class Member < ApplicationRecord
# to projects/groups.
scope :authorizable, -> do
connected_to_user
+ .active_state
.non_request
.non_minimal_access
end
@@ -128,7 +131,8 @@ class Member < ApplicationRecord
end
scope :without_invites_and_requests, -> do
- non_request
+ active_state
+ .non_request
.non_invite
.non_minimal_access
end
@@ -180,6 +184,7 @@ class Member < ApplicationRecord
scope :on_project_and_ancestors, ->(project) { where(source: [project] + project.ancestors) }
+ before_validation :set_member_namespace_id, on: :create
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? && !member.invite_accepted_at? }
after_create :send_invite, if: :invite?, unless: :importing?
@@ -203,7 +208,7 @@ class Member < ApplicationRecord
class << self
def search(query)
- joins(:user).merge(User.search(query))
+ joins(:user).merge(User.search(query, use_minimum_char_limit: false))
end
def search_invite_email(query)
@@ -380,6 +385,12 @@ class Member < ApplicationRecord
private
+ # TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
+ # temporary until we can we properly remove the source columns
+ def set_member_namespace_id
+ self.member_namespace_id = self.source_id
+ end
+
def access_level_inclusion
return if access_level.in?(Gitlab::Access.all_values)
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 6fc665cb87a..3a449055bc1 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -118,6 +118,13 @@ class ProjectMember < Member
# rubocop:enable CodeReuse/ServiceClass
end
+ # TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
+ # temporary until we can we properly remove the source columns
+ override :set_member_namespace_id
+ def set_member_namespace_id
+ self.member_namespace_id = project&.project_namespace_id
+ end
+
def send_invite
run_after_commit_or_now { notification_service.invite_project_member(self, @raw_invite_token) }
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index cf36e72a565..29540cbde2f 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -406,6 +406,17 @@ class MergeRequest < ApplicationRecord
)
end
+ scope :attention, ->(user) do
+ # rubocop: disable Gitlab/Union
+ union = Gitlab::SQL::Union.new([
+ MergeRequestReviewer.select(:merge_request_id).where(user_id: user.id, state: MergeRequestReviewer.states[:attention_requested]),
+ MergeRequestAssignee.select(:merge_request_id).where(user_id: user.id, state: MergeRequestAssignee.states[:attention_requested])
+ ])
+ # rubocop: enable Gitlab/Union
+
+ with(Gitlab::SQL::CTE.new(:reviewers_and_assignees, union).to_arel).where('merge_requests.id in (select merge_request_id from reviewers_and_assignees)')
+ end
+
def self.total_time_to_merge
join_metrics
.merge(MergeRequest::Metrics.with_valid_time_to_merge)
@@ -471,6 +482,12 @@ class MergeRequest < ApplicationRecord
rebase_jid.present? && Gitlab::SidekiqStatus.running?(rebase_jid)
end
+ def permits_force_push?
+ return true unless ProtectedBranch.protected?(source_project, source_branch)
+
+ ProtectedBranch.allow_force_push?(source_project, source_branch)
+ end
+
# Use this method whenever you need to make sure the head_pipeline is synced with the
# branch head commit, for example checking if a merge request can be merged.
# For more information check: https://gitlab.com/gitlab-org/gitlab-foss/issues/40004
@@ -561,20 +578,24 @@ class MergeRequest < ApplicationRecord
end
end
- # WIP is deprecated in favor of Draft. Currently both options are supported
- # https://gitlab.com/gitlab-org/gitlab/-/issues/227426
- DRAFT_REGEX = /\A*#{Regexp.union(Gitlab::Regex.merge_request_wip, Gitlab::Regex.merge_request_draft)}+\s*/i.freeze
+ DRAFT_REGEX = /\A*#{Gitlab::Regex.merge_request_draft}+\s*/i.freeze
- def self.work_in_progress?(title)
+ def self.draft?(title)
!!(title =~ DRAFT_REGEX)
end
- def self.wipless_title(title)
+ def self.draftless_title(title)
title.sub(DRAFT_REGEX, "")
end
- def self.wip_title(title)
- work_in_progress?(title) ? title : "Draft: #{title}"
+ def self.draft_title(title)
+ draft?(title) ? title : "Draft: #{title}"
+ end
+
+ class << self
+ alias_method :work_in_progress?, :draft?
+ alias_method :wipless_title, :draftless_title
+ alias_method :wip_title, :draft_title
end
def self.participant_includes
@@ -587,9 +608,10 @@ class MergeRequest < ApplicationRecord
# Verifies if title has changed not taking into account Draft prefix
# for merge requests.
- def wipless_title_changed(old_title)
- self.class.wipless_title(old_title) != self.wipless_title
+ def draftless_title_changed(old_title)
+ self.class.draftless_title(old_title) != self.draftless_title
end
+ alias_method :wipless_title_changed, :draftless_title_changed
def hook_attrs
Gitlab::HookData::MergeRequestBuilder.new(self).build
@@ -1088,18 +1110,20 @@ class MergeRequest < ApplicationRecord
@closed_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: :closed).last
end
- def work_in_progress?
- self.class.work_in_progress?(title)
+ def draft?
+ self.class.draft?(title)
end
- alias_method :draft?, :work_in_progress?
+ alias_method :work_in_progress?, :draft?
- def wipless_title
- self.class.wipless_title(self.title)
+ def draftless_title
+ self.class.draftless_title(self.title)
end
+ alias_method :wipless_title, :draftless_title
- def wip_title
- self.class.wip_title(self.title)
+ def draft_title
+ self.class.draft_title(self.title)
end
+ alias_method :wip_title, :draft_title
def mergeable?(skip_ci_check: false, skip_discussions_check: false)
return false unless mergeable_state?(skip_ci_check: skip_ci_check,
@@ -1754,6 +1778,8 @@ class MergeRequest < ApplicationRecord
paths = active_diff_discussions.flat_map { |n| n.diff_file.paths }.uniq
+ active_discussions_resolved = active_diff_discussions.all?(&:resolved?)
+
service = Discussions::UpdateDiffPositionService.new(
self.project,
current_user,
@@ -1764,9 +1790,15 @@ class MergeRequest < ApplicationRecord
active_diff_discussions.each do |discussion|
service.execute(discussion)
+ discussion.clear_memoized_values
end
- if project.resolve_outdated_diff_discussions?
+ # If they were all already resolved, this method will have already been called.
+ # If they all don't get resolved, we don't need to call the method
+ # If they go from unresolved -> resolved, then we call the method
+ if !active_discussions_resolved &&
+ active_diff_discussions.all?(&:resolved?) &&
+ project.resolve_outdated_diff_discussions?
MergeRequests::ResolvedDiscussionNotificationService
.new(project: project, current_user: current_user)
.execute(self)
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 868bee9961b..2c95cc2672c 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -52,6 +52,17 @@ class Milestone < ApplicationRecord
state :active
end
+ # Searches for timeboxes with a matching title.
+ #
+ # This method uses ILIKE on PostgreSQL
+ #
+ # query - The search query as a String
+ #
+ # Returns an ActiveRecord::Relation.
+ def self.search_title(query)
+ fuzzy_search(query, [:title])
+ end
+
def self.min_chars_for_partial_matching
2
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 0dc20e0016c..5c55f4d3def 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -43,6 +43,7 @@ class Namespace < ApplicationRecord
has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :project_statistics
has_one :namespace_settings, inverse_of: :namespace, class_name: 'NamespaceSetting', autosave: true
+ has_one :namespace_statistics
has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route'
has_many :namespace_members, foreign_key: :member_namespace_id, inverse_of: :member_namespace, class_name: 'Member'
@@ -492,6 +493,10 @@ class Namespace < ApplicationRecord
end
end
+ def shared_runners
+ @shared_runners ||= shared_runners_enabled ? Ci::Runner.instance_type : Ci::Runner.none
+ end
+
def root?
!has_parent?
end
@@ -508,6 +513,12 @@ class Namespace < ApplicationRecord
Feature.enabled?(:create_project_namespace_on_project_create, self, default_enabled: :yaml)
end
+ def storage_enforcement_date
+ # should return something like Date.new(2022, 02, 03)
+ # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ nil
+ end
+
private
def expire_child_caches
diff --git a/app/models/namespace/root_storage_statistics.rb b/app/models/namespace/root_storage_statistics.rb
index 99e32537595..ee04ec39b1e 100644
--- a/app/models/namespace/root_storage_statistics.rb
+++ b/app/models/namespace/root_storage_statistics.rb
@@ -27,10 +27,17 @@ class Namespace::RootStorageStatistics < ApplicationRecord
update!(merged_attributes)
end
+ def self.namespace_statistics_attributes
+ %w(storage_size dependency_proxy_size)
+ end
+
private
def merged_attributes
- attributes_from_project_statistics.merge!(attributes_from_personal_snippets) { |key, v1, v2| v1 + v2 }
+ attributes_from_project_statistics.merge!(
+ attributes_from_personal_snippets,
+ attributes_from_namespace_statistics
+ ) { |key, v1, v2| v1 + v2 }
end
def attributes_from_project_statistics
@@ -68,6 +75,27 @@ class Namespace::RootStorageStatistics < ApplicationRecord
.where(author: namespace.owner_id)
.select("COALESCE(SUM(s.repository_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}")
end
+
+ def from_namespace_statistics
+ namespace
+ .self_and_descendants
+ .joins("INNER JOIN namespace_statistics ns ON ns.namespace_id = namespaces.id")
+ .select(
+ 'COALESCE(SUM(ns.storage_size), 0) AS storage_size',
+ 'COALESCE(SUM(ns.dependency_proxy_size), 0) AS dependency_proxy_size'
+ )
+ end
+
+ def attributes_from_namespace_statistics
+ # At the moment, only groups can have some storage data because of dependency proxy assets.
+ # Therefore, if the namespace is not a group one, there is no need to perform
+ # the query. If this changes in the future and we add some sort of resource to
+ # users that it's store in NamespaceStatistics, we will need to remove this
+ # guard clause.
+ return {} unless namespace.group_namespace?
+
+ from_namespace_statistics.take.slice(*self.class.namespace_statistics_attributes)
+ end
end
Namespace::RootStorageStatistics.prepend_mod_with('Namespace::RootStorageStatistics')
diff --git a/app/models/namespace_statistics.rb b/app/models/namespace_statistics.rb
new file mode 100644
index 00000000000..04ca05d85ff
--- /dev/null
+++ b/app/models/namespace_statistics.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+class NamespaceStatistics < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass
+ include AfterCommitQueue
+
+ belongs_to :namespace
+
+ validates :namespace, presence: true
+
+ scope :for_namespaces, -> (namespaces) { where(namespace: namespaces) }
+
+ before_save :update_storage_size
+ after_save :update_root_storage_statistics, if: :saved_change_to_storage_size?
+ after_destroy :update_root_storage_statistics
+
+ delegate :group_namespace?, to: :namespace
+
+ def refresh!(only: [])
+ return if Gitlab::Database.read_only?
+ return unless group_namespace?
+
+ self.class.columns_to_refresh.each do |column|
+ if only.empty? || only.include?(column)
+ public_send("update_#{column}") # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+
+ save!
+ end
+
+ def update_storage_size
+ # This prevents failures with older database schemas, such as those
+ # in migration specs.
+ return unless self.class.database.cached_column_exists?(:dependency_proxy_size)
+
+ self.storage_size = dependency_proxy_size
+ end
+
+ def update_dependency_proxy_size
+ return unless group_namespace?
+
+ self.dependency_proxy_size = namespace.dependency_proxy_manifests.sum(:size) + namespace.dependency_proxy_blobs.sum(:size)
+ end
+
+ def self.columns_to_refresh
+ [:dependency_proxy_size]
+ end
+
+ private
+
+ def update_root_storage_statistics
+ return unless group_namespace?
+
+ run_after_commit do
+ Namespaces::ScheduleAggregationWorker.perform_async(namespace.id)
+ end
+ end
+end
+
+NamespaceStatistics.prepend_mod_with('NamespaceStatistics')
diff --git a/app/models/namespaces/sync_event.rb b/app/models/namespaces/sync_event.rb
index 8534d8afb8c..fbe047f2c5a 100644
--- a/app/models/namespaces/sync_event.rb
+++ b/app/models/namespaces/sync_event.rb
@@ -13,4 +13,8 @@ class Namespaces::SyncEvent < ApplicationRecord
def self.enqueue_worker
::Namespaces::ProcessSyncEventsWorker.perform_async # rubocop:disable CodeReuse/Worker
end
+
+ def self.upper_bound_count
+ select('COALESCE(MAX(id) - MIN(id) + 1, 0) AS upper_bound_count').to_a.first.upper_bound_count
+ end
end
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index 757a0e40eb3..99a5b8cb063 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -43,14 +43,23 @@ module Namespaces
included do
before_update :lock_both_roots, if: -> { sync_traversal_ids? && parent_id_changed? }
- after_create :sync_traversal_ids, if: -> { sync_traversal_ids? }
after_update :sync_traversal_ids, if: -> { sync_traversal_ids? && saved_change_to_parent_id? }
+ # sync traversal_ids on namespace create, which can happen quite early within a transaction, thus keeping the lock on root namespace record
+ # for a relatively long time, e.g. creating the project namespace when a project is being created.
+ after_create :sync_traversal_ids, if: -> { sync_traversal_ids? && !sync_traversal_ids_before_commit? }
+ # This uses rails internal before_commit API to sync traversal_ids on namespace create, right before transaction is committed.
+ # This helps reduce the time during which the root namespace record is locked to ensure updated traversal_ids are valid
+ before_commit :sync_traversal_ids, on: [:create], if: -> { sync_traversal_ids? && sync_traversal_ids_before_commit? }
end
def sync_traversal_ids?
Feature.enabled?(:sync_traversal_ids, root_ancestor, default_enabled: :yaml)
end
+ def sync_traversal_ids_before_commit?
+ Feature.enabled?(:sync_traversal_ids_before_commit, root_ancestor, default_enabled: :yaml)
+ end
+
def use_traversal_ids?
return false unless Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
diff --git a/app/models/namespaces/traversal/linear_scopes.rb b/app/models/namespaces/traversal/linear_scopes.rb
index 9f0f49e729c..09d69a5f77a 100644
--- a/app/models/namespaces/traversal/linear_scopes.rb
+++ b/app/models/namespaces/traversal/linear_scopes.rb
@@ -12,7 +12,7 @@ module Namespaces
def as_ids
return super unless use_traversal_ids?
- select('namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id')
+ select(Arel.sql('namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)]').as('id'))
end
def roots
@@ -53,7 +53,7 @@ module Namespaces
end
def self_and_descendants(include_self: true)
- return super unless use_traversal_ids?
+ return super unless use_traversal_ids_for_descendants_scopes?
if Feature.enabled?(:traversal_ids_btree, default_enabled: :yaml)
self_and_descendants_with_comparison_operators(include_self: include_self)
@@ -65,7 +65,7 @@ module Namespaces
end
def self_and_descendant_ids(include_self: true)
- return super unless use_traversal_ids?
+ return super unless use_traversal_ids_for_descendants_scopes?
if Feature.enabled?(:traversal_ids_btree, default_enabled: :yaml)
self_and_descendants_with_comparison_operators(include_self: include_self).as_ids
@@ -75,6 +75,12 @@ module Namespaces
end
end
+ def self_and_hierarchy
+ return super unless use_traversal_ids_for_self_and_hierarchy_scopes?
+
+ unscoped.from_union([all.self_and_ancestors, all.self_and_descendants(include_self: false)])
+ end
+
def order_by_depth(hierarchy_order)
return all unless hierarchy_order
@@ -109,6 +115,16 @@ module Namespaces
use_traversal_ids?
end
+ def use_traversal_ids_for_descendants_scopes?
+ Feature.enabled?(:use_traversal_ids_for_descendants_scopes, default_enabled: :yaml) &&
+ use_traversal_ids?
+ end
+
+ def use_traversal_ids_for_self_and_hierarchy_scopes?
+ Feature.enabled?(:use_traversal_ids_for_self_and_hierarchy_scopes, default_enabled: :yaml) &&
+ use_traversal_ids?
+ end
+
def self_and_descendants_with_comparison_operators(include_self: true)
base = all.select(
:traversal_ids,
diff --git a/app/models/namespaces/traversal/recursive_scopes.rb b/app/models/namespaces/traversal/recursive_scopes.rb
index 583c53f8221..c6f09a4d134 100644
--- a/app/models/namespaces/traversal/recursive_scopes.rb
+++ b/app/models/namespaces/traversal/recursive_scopes.rb
@@ -53,6 +53,11 @@ module Namespaces
self_and_descendants(include_self: include_self).as_ids
end
alias_method :recursive_self_and_descendant_ids, :self_and_descendant_ids
+
+ def self_and_hierarchy
+ Gitlab::ObjectHierarchy.new(all).all_objects
+ end
+ alias_method :recursive_self_and_hierarchy, :self_and_hierarchy
end
end
end
diff --git a/app/models/namespaces/user_namespace.rb b/app/models/namespaces/user_namespace.rb
index 14b867b2607..408acb6dcce 100644
--- a/app/models/namespaces/user_namespace.rb
+++ b/app/models/namespaces/user_namespace.rb
@@ -25,5 +25,9 @@ module Namespaces
def self.sti_name
'User'
end
+
+ def owners
+ Array.wrap(owner)
+ end
end
end
diff --git a/app/models/note.rb b/app/models/note.rb
index a143c21c0f9..3f3fa968393 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -27,10 +27,14 @@ class Note < ApplicationRecord
redact_field :note
- TYPES_RESTRICTED_BY_ABILITY = {
+ TYPES_RESTRICTED_BY_PROJECT_ABILITY = {
branch: :download_code
}.freeze
+ TYPES_RESTRICTED_BY_GROUP_ABILITY = {
+ contact: :read_crm_contact
+ }.freeze
+
# Aliases to make application_helper#edited_time_ago_with_tooltip helper work properly with notes.
# See https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/10392/diffs#note_28719102
alias_attribute :last_edited_by, :updated_by
@@ -119,7 +123,7 @@ class Note < ApplicationRecord
scope :inc_author, -> { includes(:author) }
scope :with_api_entity_associations, -> { preload(:note_diff_file, :author) }
scope :inc_relations_for_view, -> do
- includes(:project, { author: :status }, :updated_by, :resolved_by, :award_emoji,
+ includes({ project: :group }, { author: :status }, :updated_by, :resolved_by, :award_emoji,
{ system_note_metadata: :description_version }, :note_diff_file, :diff_note_positions, :suggestions)
end
@@ -565,10 +569,10 @@ class Note < ApplicationRecord
noteable.user_mentions.where(note: self)
end
- def system_note_with_references_visible_for?(user)
+ def system_note_visible_for?(user)
return true unless system?
- (!system_note_with_references? || all_referenced_mentionables_allowed?(user)) && system_note_viewable_by?(user)
+ system_note_viewable_by?(user) && all_referenced_mentionables_allowed?(user)
end
def parent_user
@@ -617,10 +621,17 @@ class Note < ApplicationRecord
def system_note_viewable_by?(user)
return true unless system_note_metadata
- restriction = TYPES_RESTRICTED_BY_ABILITY[system_note_metadata.action.to_sym]
- return Ability.allowed?(user, restriction, project) if restriction
+ system_note_viewable_by_project_ability?(user) && system_note_viewable_by_group_ability?(user)
+ end
- true
+ def system_note_viewable_by_project_ability?(user)
+ project_restriction = TYPES_RESTRICTED_BY_PROJECT_ABILITY[system_note_metadata.action.to_sym]
+ !project_restriction || Ability.allowed?(user, project_restriction, project)
+ end
+
+ def system_note_viewable_by_group_ability?(user)
+ group_restriction = TYPES_RESTRICTED_BY_GROUP_ABILITY[system_note_metadata.action.to_sym]
+ !group_restriction || Ability.allowed?(user, group_restriction, project&.group)
end
def keep_around_commit
@@ -646,6 +657,8 @@ class Note < ApplicationRecord
end
def all_referenced_mentionables_allowed?(user)
+ return true unless system_note_with_references?
+
if user_visible_reference_count.present? && total_reference_count.present?
# if they are not equal, then there are private/confidential references as well
user_visible_reference_count > 0 && user_visible_reference_count == total_reference_count
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 4a97ae97ea0..c76473c9438 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -138,7 +138,7 @@ class Packages::Package < ApplicationRecord
scope :without_nuget_temporary_name, -> { where.not(name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
scope :has_version, -> { where.not(version: nil) }
- scope :preload_files, -> { Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml) ? preload(:installable_package_files) : preload(:package_files) }
+ scope :preload_files, -> { preload(:installable_package_files) }
scope :preload_pipelines, -> { preload(pipelines: :user) }
scope :last_of_each_version, -> { where(id: all.select('MAX(id) AS id').group(:version)) }
scope :limit_recent, ->(limit) { order_created_desc.limit(limit) }
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 190081c4e8e..fc7c348dfdb 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -55,12 +55,11 @@ class Packages::PackageFile < ApplicationRecord
end
scope :for_helm_with_channel, ->(project, channel) do
- result = joins(:package)
- .merge(project.packages.helm.installable)
- .joins(:helm_file_metadatum)
- .where(packages_helm_file_metadata: { channel: channel })
- result = result.installable if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- result
+ joins(:package)
+ .merge(project.packages.helm.installable)
+ .joins(:helm_file_metadatum)
+ .where(packages_helm_file_metadata: { channel: channel })
+ .installable
end
scope :with_conan_file_type, ->(file_type) do
@@ -110,13 +109,9 @@ class Packages::PackageFile < ApplicationRecord
cte_name = :packages_cte
cte = Gitlab::SQL::CTE.new(cte_name, packages.select(:id))
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- ::Packages::PackageFile.installable.limit_recent(1)
- .where(arel_table[:package_id].eq(Arel.sql("#{cte_name}.id")))
- else
- ::Packages::PackageFile.limit_recent(1)
- .where(arel_table[:package_id].eq(Arel.sql("#{cte_name}.id")))
- end
+ package_files = ::Packages::PackageFile.installable
+ .limit_recent(1)
+ .where(arel_table[:package_id].eq(Arel.sql("#{cte_name}.id")))
package_files = package_files.joins(extra_join) if extra_join
package_files = package_files.where(extra_where) if extra_where
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index c21027455b1..2804588be85 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -245,8 +245,8 @@ class PagesDomain < ApplicationRecord
def validate_pages_domain
return unless domain
- if domain.downcase.ends_with?(Settings.pages.host.downcase)
- self.errors.add(:domain, "*.#{Settings.pages.host} is restricted. Please compare our documentation at https://docs.gitlab.com/ee/administration/pages/#advanced-configuration against your configuration.")
+ if domain.downcase.ends_with?(".#{Settings.pages.host.downcase}") || domain.casecmp(Settings.pages.host) == 0
+ self.errors.add(:domain, "#{Settings.pages.host} and its subdomains cannot be used as custom pages domains. Please compare our documentation at https://docs.gitlab.com/ee/administration/pages/#advanced-configuration against your configuration.")
end
end
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 1778e927dd1..2f515f3443d 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -33,6 +33,7 @@ class PersonalAccessToken < ApplicationRecord
scope :preload_users, -> { preload(:user) }
scope :order_expires_at_asc, -> { reorder(expires_at: :asc) }
scope :order_expires_at_desc, -> { reorder(expires_at: :desc) }
+ scope :project_access_token, -> { includes(:user).where(user: { user_type: :project_bot }) }
validates :scopes, presence: true
validate :validate_scopes
@@ -93,6 +94,10 @@ class PersonalAccessToken < ApplicationRecord
"#{self.class.token_prefix}#{token}"
end
+ def project_access_token?
+ user&.project_bot?
+ end
+
protected
def validate_scopes
diff --git a/app/models/preloaders/single_hierarchy_project_group_plans_preloader.rb b/app/models/preloaders/single_hierarchy_project_group_plans_preloader.rb
new file mode 100644
index 00000000000..179214666ed
--- /dev/null
+++ b/app/models/preloaders/single_hierarchy_project_group_plans_preloader.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Preloaders
+ class SingleHierarchyProjectGroupPlansPreloader
+ attr_reader :projects
+
+ def initialize(projects_relation)
+ @projects = projects_relation
+ end
+
+ def execute
+ # no-op in FOSS
+ end
+ end
+end
+
+Preloaders::SingleHierarchyProjectGroupPlansPreloader.prepend_mod_with('Preloaders::SingleHierarchyProjectGroupPlansPreloader')
diff --git a/app/models/preloaders/users_max_access_level_in_projects_preloader.rb b/app/models/preloaders/users_max_access_level_in_projects_preloader.rb
new file mode 100644
index 00000000000..b4ce61a869c
--- /dev/null
+++ b/app/models/preloaders/users_max_access_level_in_projects_preloader.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Preloaders
+ # This class preloads the max access level (role) for the users within the given projects and
+ # stores the values in requests store via the ProjectTeam class.
+ class UsersMaxAccessLevelInProjectsPreloader
+ def initialize(projects:, users:)
+ @projects = projects
+ @users = users
+ end
+
+ def execute
+ return unless @projects.present? && @users.present?
+
+ access_levels.each do |(project_id, user_id), access_level|
+ project = projects_by_id[project_id]
+
+ project.team.write_member_access_for_user_id(user_id, access_level)
+ end
+ end
+
+ private
+
+ def access_levels
+ ProjectAuthorization
+ .where(project_id: project_ids, user_id: user_ids)
+ .group(:project_id, :user_id)
+ .maximum(:access_level)
+ end
+
+ # Use reselect to override the existing select to prevent
+ # the error `subquery has too many columns`
+ # NotificationsController passes in an Array so we need to check the type
+ def project_ids
+ @projects.is_a?(ActiveRecord::Relation) ? @projects.reselect(:id) : @projects
+ end
+
+ def user_ids
+ @users.is_a?(ActiveRecord::Relation) ? @users.reselect(:id) : @users
+ end
+
+ def projects_by_id
+ @projects_by_id ||= @projects.index_by(&:id)
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 7f823b5ed6b..512c6ac1acb 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -74,6 +74,21 @@ class Project < ApplicationRecord
GL_REPOSITORY_TYPES = [Gitlab::GlRepository::PROJECT, Gitlab::GlRepository::WIKI, Gitlab::GlRepository::DESIGN].freeze
+ MAX_SUGGESTIONS_TEMPLATE_LENGTH = 255
+ MAX_COMMIT_TEMPLATE_LENGTH = 500
+
+ DEFAULT_MERGE_COMMIT_TEMPLATE = <<~MSG.rstrip.freeze
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{issues}
+
+ See merge request %{reference}
+ MSG
+
+ DEFAULT_SQUASH_COMMIT_TEMPLATE = '%{title}'
+
cache_markdown_field :description, pipeline: :description
default_value_for :packages_enabled, true
@@ -506,11 +521,12 @@ class Project < ApplicationRecord
validates :variables, nested_attributes_duplicates: { scope: :environment_scope }
validates :bfg_object_map, file_size: { maximum: :max_attachment_size }
validates :max_artifacts_size, numericality: { only_integer: true, greater_than: 0, allow_nil: true }
- validates :suggestion_commit_message, length: { maximum: 255 }
+ validates :suggestion_commit_message, length: { maximum: MAX_SUGGESTIONS_TEMPLATE_LENGTH }
# Scopes
scope :pending_delete, -> { where(pending_delete: true) }
scope :without_deleted, -> { where(pending_delete: false) }
+ scope :not_aimed_for_deletion, -> { where(marked_for_deletion_at: nil).without_deleted }
scope :with_storage_feature, ->(feature) do
where(arel_table[:storage_version].gteq(HASHED_STORAGE_FEATURES[feature]))
@@ -727,6 +743,7 @@ class Project < ApplicationRecord
scope :joins_import_state, -> { joins("INNER JOIN project_mirror_data import_state ON import_state.project_id = projects.id") }
scope :for_group, -> (group) { where(group: group) }
scope :for_group_and_its_subgroups, ->(group) { where(namespace_id: group.self_and_descendants.select(:id)) }
+ scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) }
class << self
# Searches for a list of projects based on the query given in `query`.
@@ -987,7 +1004,7 @@ class Project < ApplicationRecord
end
def context_commits_enabled?
- Feature.enabled?(:context_commits, self, default_enabled: :yaml)
+ Feature.enabled?(:context_commits, self.group, default_enabled: :yaml)
end
# LFS and hashed repository storage are required for using Design Management.
@@ -1513,9 +1530,25 @@ class Project < ApplicationRecord
# rubocop: enable CodeReuse/ServiceClass
def owner
+ # This will be phased out and replaced with `owners` relationship
+ # backed by memberships with direct/inherited Owner access roles
+ # See https://gitlab.com/groups/gitlab-org/-/epics/7405
+ group || namespace.try(:owner)
+ end
+
+ def deprecated_owner
+ # Kept in order to maintain webhook structures until we remove owner_name and owner_email
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350603
group || namespace.try(:owner)
end
+ def owners
+ # This will be phased out and replaced with `owners` relationship
+ # backed by memberships with direct/inherited Owner access roles
+ # See https://gitlab.com/groups/gitlab-org/-/epics/7405
+ team.owners
+ end
+
def first_owner
obj = owner
@@ -2168,14 +2201,6 @@ class Project < ApplicationRecord
end
end
- def ci_instance_variables_for(ref:)
- if protected_for?(ref)
- Ci::InstanceVariable.all_cached
- else
- Ci::InstanceVariable.unprotected_cached
- end
- end
-
def protected_for?(ref)
raise Repository::AmbiguousRefError if repository.ambiguous_ref?(ref)
@@ -2610,6 +2635,14 @@ class Project < ApplicationRecord
[project&.id, root_group&.id]
end
+ def related_group_ids
+ ids = invited_group_ids
+
+ ids += group.self_and_ancestors_ids if group
+
+ ids
+ end
+
def package_already_taken?(package_name, package_version, package_type:)
Packages::Package.with_name(package_name)
.with_version(package_version)
@@ -2746,6 +2779,32 @@ class Project < ApplicationRecord
].compact.min
end
+ def merge_commit_template_or_default
+ merge_commit_template.presence || DEFAULT_MERGE_COMMIT_TEMPLATE
+ end
+
+ def merge_commit_template_or_default=(value)
+ project_setting.merge_commit_template =
+ if value.blank? || value.delete("\r") == DEFAULT_MERGE_COMMIT_TEMPLATE
+ nil
+ else
+ value
+ end
+ end
+
+ def squash_commit_template_or_default
+ squash_commit_template.presence || DEFAULT_SQUASH_COMMIT_TEMPLATE
+ end
+
+ def squash_commit_template_or_default=(value)
+ project_setting.squash_commit_template =
+ if value.blank? || value.delete("\r") == DEFAULT_SQUASH_COMMIT_TEMPLATE
+ nil
+ else
+ value
+ end
+ end
+
private
# overridden in EE
@@ -2754,6 +2813,12 @@ class Project < ApplicationRecord
end
def save_topics
+ topic_ids_before = self.topic_ids
+ update_topics
+ Projects::Topic.update_non_private_projects_counter(topic_ids_before, self.topic_ids, visibility_level_previously_was, visibility_level)
+ end
+
+ def update_topics
return if @topic_list.nil?
@topic_list = @topic_list.split(',') if @topic_list.instance_of?(String)
diff --git a/app/models/project_import_state.rb b/app/models/project_import_state.rb
index 633e669b5fc..0f04eb7d4af 100644
--- a/app/models/project_import_state.rb
+++ b/app/models/project_import_state.rb
@@ -57,6 +57,12 @@ class ProjectImportState < ApplicationRecord
end
end
+ after_transition any => :failed do |state, _|
+ if Feature.enabled?(:remove_import_data_on_failure, state.project, default_enabled: :yaml)
+ state.project.remove_import_data
+ end
+ end
+
after_transition started: :finished do |state, _|
project = state.project
diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb
index 4e37174e604..ae3d7038a88 100644
--- a/app/models/project_setting.rb
+++ b/app/models/project_setting.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class ProjectSetting < ApplicationRecord
+ include IgnorableColumns
+
+ ignore_column :show_diff_preview_in_email, remove_with: '14.10', remove_after: '2022-03-22'
+
belongs_to :project, inverse_of: :project_setting
enum squash_option: {
@@ -12,8 +16,12 @@ class ProjectSetting < ApplicationRecord
self.primary_key = :project_id
- validates :merge_commit_template, length: { maximum: 500 }
- validates :squash_commit_template, length: { maximum: 500 }
+ validates :merge_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
+ validates :squash_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
+
+ default_value_for(:legacy_open_source_license_available) do
+ Feature.enabled?(:legacy_open_source_license_available, default_enabled: :yaml, type: :ops)
+ end
def squash_enabled_by_default?
%w[always default_on].include?(squash_option)
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 8061554006d..c3c7508df9f 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -107,6 +107,10 @@ class ProjectTeam
end
end
+ def owner?(user)
+ owners.include?(user)
+ end
+
def import(source_project, current_user = nil)
target_project = project
diff --git a/app/models/projects/sync_event.rb b/app/models/projects/sync_event.rb
index 5221b00c55f..7af863c0cf0 100644
--- a/app/models/projects/sync_event.rb
+++ b/app/models/projects/sync_event.rb
@@ -13,4 +13,8 @@ class Projects::SyncEvent < ApplicationRecord
def self.enqueue_worker
::Projects::ProcessSyncEventsWorker.perform_async # rubocop:disable CodeReuse/Worker
end
+
+ def self.upper_bound_count
+ select('COALESCE(MAX(id) - MIN(id) + 1, 0) AS upper_bound_count').to_a.first.upper_bound_count
+ end
end
diff --git a/app/models/projects/topic.rb b/app/models/projects/topic.rb
index 8d6f8c3a9ca..78bc2df2e1e 100644
--- a/app/models/projects/topic.rb
+++ b/app/models/projects/topic.rb
@@ -25,6 +25,29 @@ module Projects
def search(query)
fuzzy_search(query, [:name])
end
+
+ def update_non_private_projects_counter(ids_before, ids_after, project_visibility_level_before, project_visibility_level_after)
+ project_visibility_level_before ||= project_visibility_level_after
+
+ topics_to_decrement = []
+ topics_to_increment = []
+ topic_ids_removed = ids_before - ids_after
+ topic_ids_retained = ids_before & ids_after
+ topic_ids_added = ids_after - ids_before
+
+ if project_visibility_level_before > Gitlab::VisibilityLevel::PRIVATE
+ topics_to_decrement += topic_ids_removed
+ topics_to_decrement += topic_ids_retained if project_visibility_level_after == Gitlab::VisibilityLevel::PRIVATE
+ end
+
+ if project_visibility_level_after > Gitlab::VisibilityLevel::PRIVATE
+ topics_to_increment += topic_ids_added
+ topics_to_increment += topic_ids_retained if project_visibility_level_before == Gitlab::VisibilityLevel::PRIVATE
+ end
+
+ where(id: topics_to_increment).update_counters(non_private_projects_count: 1) unless topics_to_increment.empty?
+ where(id: topics_to_decrement).where('non_private_projects_count > 0').update_counters(non_private_projects_count: -1) unless topics_to_decrement.empty?
+ end
end
end
end
diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb
index 68f0ab06bea..0a59d9cef9b 100644
--- a/app/models/resource_label_event.rb
+++ b/app/models/resource_label_event.rb
@@ -54,7 +54,7 @@ class ResourceLabelEvent < ResourceEvent
end
def banzai_render_context(field)
- super.merge(pipeline: :label, only_path: true)
+ super.merge(pipeline: :label, only_path: true, label_url_method: label_url_method)
end
def refresh_invalid_reference
@@ -91,6 +91,10 @@ class ResourceLabelEvent < ResourceEvent
end
end
+ def label_url_method
+ issuable.is_a?(MergeRequest) ? :project_merge_requests_url : :project_issues_url
+ end
+
def expire_etag_cache
issuable.expire_note_etag_cache
end
diff --git a/app/models/state_note.rb b/app/models/state_note.rb
index 5e35f15aac4..93c025a9bf0 100644
--- a/app/models/state_note.rb
+++ b/app/models/state_note.rb
@@ -18,11 +18,11 @@ class StateNote < SyntheticNote
def note_text(html: false)
if event.state == 'closed'
if event.close_after_error_tracking_resolve
- return 'resolved the corresponding error and closed the issue.'
+ return 'resolved the corresponding error and closed the issue'
end
if event.close_auto_resolve_prometheus_alert
- return 'automatically closed this issue because the alert resolved.'
+ return 'automatically closed this incident because the alert resolved'
end
end
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index a3c9db90b5d..0be56d8b4a4 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -24,7 +24,7 @@ class SystemNoteMetadata < ApplicationRecord
opened closed merged duplicate locked unlocked outdated reviewer
tag due_date pinned_embed cherry_pick health_status approved unapproved
status alert_issue_added relate unrelate new_alert_added severity
- attention_requested attention_request_removed
+ attention_requested attention_request_removed contact
].freeze
validates :note, presence: true, unless: :importing?
diff --git a/app/models/user.rb b/app/models/user.rb
index 1d452fc2e50..74832bff9ac 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -149,6 +149,7 @@ class User < ApplicationRecord
has_many :members
has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, class_name: 'GroupMember'
has_many :groups, through: :group_members
+ has_many :groups_with_active_memberships, -> { where(members: { state: ::Member::STATE_ACTIVE }) }, through: :group_members, source: :group
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group
has_many :developer_groups, -> { where(members: { access_level: ::Gitlab::Access::DEVELOPER }) }, through: :group_members, source: :group
@@ -170,6 +171,7 @@ class User < ApplicationRecord
has_many :project_members, -> { where(requested_at: nil) }
has_many :projects, through: :project_members
has_many :created_projects, foreign_key: :creator_id, class_name: 'Project'
+ has_many :projects_with_active_memberships, -> { where(members: { state: ::Member::STATE_ACTIVE }) }, through: :project_members, source: :project
has_many :users_star_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :starred_projects, through: :users_star_projects, source: :project
has_many :project_authorizations, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
@@ -668,7 +670,8 @@ class User < ApplicationRecord
sanitized_order_sql = Arel.sql(sanitize_sql_array([order, query: query]))
- scope = options[:with_private_emails] ? search_with_secondary_emails(query) : search_with_public_emails(query)
+ scope = options[:with_private_emails] ? with_primary_or_secondary_email(query) : with_public_email(query)
+ scope = scope.or(search_by_name_or_username(query, use_minimum_char_limit: options[:use_minimum_char_limit]))
scope.reorder(sanitized_order_sql, :name)
end
@@ -685,50 +688,32 @@ class User < ApplicationRecord
reorder(:name)
end
- def search_with_public_emails(query)
- return none if query.blank?
-
- query = query.downcase
+ # searches user by given pattern
+ # it compares name and username fields with given pattern
+ # This method uses ILIKE on PostgreSQL.
+ def search_by_name_or_username(query, use_minimum_char_limit: nil)
+ use_minimum_char_limit = user_search_minimum_char_limit if use_minimum_char_limit.nil?
where(
- fuzzy_arel_match(:name, query, use_minimum_char_limit: user_search_minimum_char_limit)
- .or(fuzzy_arel_match(:username, query, use_minimum_char_limit: user_search_minimum_char_limit))
- .or(arel_table[:public_email].eq(query))
+ fuzzy_arel_match(:name, query, use_minimum_char_limit: use_minimum_char_limit)
+ .or(fuzzy_arel_match(:username, query, use_minimum_char_limit: use_minimum_char_limit))
)
end
- def search_without_secondary_emails(query)
- return none if query.blank?
-
- query = query.downcase
-
- where(
- fuzzy_arel_match(:name, query, lower_exact_match: true)
- .or(fuzzy_arel_match(:username, query, lower_exact_match: true))
- .or(arel_table[:email].eq(query))
- )
+ def with_public_email(email_address)
+ where(public_email: email_address)
end
- # searches user by given pattern
- # it compares name, email, username fields and user's secondary emails with given pattern
- # This method uses ILIKE on PostgreSQL.
-
- def search_with_secondary_emails(query)
- return none if query.blank?
-
- query = query.downcase
-
+ def with_primary_or_secondary_email(email_address)
email_table = Email.arel_table
matched_by_email_user_id = email_table
.project(email_table[:user_id])
- .where(email_table[:email].eq(query))
+ .where(email_table[:email].eq(email_address))
.take(1) # at most 1 record as there is a unique constraint
where(
- fuzzy_arel_match(:name, query, use_minimum_char_limit: user_search_minimum_char_limit)
- .or(fuzzy_arel_match(:username, query, use_minimum_char_limit: user_search_minimum_char_limit))
- .or(arel_table[:email].eq(query))
- .or(arel_table[:id].eq(matched_by_email_user_id))
+ arel_table[:email].eq(email_address)
+ .or(arel_table[:id].eq(matched_by_email_user_id))
)
end
@@ -1608,7 +1593,7 @@ class User < ApplicationRecord
.distinct
.reorder(nil)
- Project.where(id: events)
+ Project.where(id: events).not_aimed_for_deletion
end
def can_be_removed?
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
index 8394192c5ae..5c39e29a128 100644
--- a/app/models/users/callout.rb
+++ b/app/models/users/callout.rb
@@ -40,8 +40,9 @@ module Users
profile_personal_access_token_expiry: 37, # EE-only
terraform_notification_dismissed: 38,
security_newsletter_callout: 39,
- verification_reminder: 40, # EE-only
- ci_deprecation_warning_for_types_keyword: 41
+ verification_reminder: 40, # EE-only
+ ci_deprecation_warning_for_types_keyword: 41,
+ security_training_feature_promotion: 42 # EE-only
}
validates :feature_name,
diff --git a/app/models/users/group_callout.rb b/app/models/users/group_callout.rb
index da9b95fd718..0dc449719ab 100644
--- a/app/models/users/group_callout.rb
+++ b/app/models/users/group_callout.rb
@@ -9,7 +9,12 @@ module Users
belongs_to :group
enum feature_name: {
- invite_members_banner: 1
+ invite_members_banner: 1,
+ approaching_seat_count_threshold: 2, # EE-only
+ storage_enforcement_banner_first_enforcement_threshold: 43,
+ storage_enforcement_banner_second_enforcement_threshold: 44,
+ storage_enforcement_banner_third_enforcement_threshold: 45,
+ storage_enforcement_banner_fourth_enforcement_threshold: 46
}
validates :group, presence: true
diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb
index c633e2d8b3d..1549c099a64 100644
--- a/app/models/users_star_project.rb
+++ b/app/models/users_star_project.rb
@@ -32,7 +32,7 @@ class UsersStarProject < ApplicationRecord
end
def search(query)
- joins(:user).merge(User.search(query))
+ joins(:user).merge(User.search(query, use_minimum_char_limit: false))
end
end
end
diff --git a/app/models/vulnerability.rb b/app/models/vulnerability.rb
index 4e1f48227d9..a5881e80e88 100644
--- a/app/models/vulnerability.rb
+++ b/app/models/vulnerability.rb
@@ -2,6 +2,7 @@
# Placeholder class for model that is implemented in EE
class Vulnerability < ApplicationRecord
+ include EachBatch
include IgnorableColumns
def self.link_reference_pattern
diff --git a/app/models/work_item.rb b/app/models/work_item.rb
index 02f52f04c85..99f05e4a181 100644
--- a/app/models/work_item.rb
+++ b/app/models/work_item.rb
@@ -3,4 +3,8 @@
class WorkItem < Issue
self.table_name = 'issues'
self.inheritance_column = :_type_disabled
+
+ def noteable_target_type_name
+ 'issue'
+ end
end
diff --git a/app/policies/ci/project_pipelines_policy.rb b/app/policies/ci/project_pipelines_policy.rb
new file mode 100644
index 00000000000..aab1208a8fe
--- /dev/null
+++ b/app/policies/ci/project_pipelines_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Ci
+ class ProjectPipelinesPolicy < BasePolicy
+ delegate { @subject.project }
+ end
+end
diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb
index 43478cf36c2..bdbe7021276 100644
--- a/app/policies/ci/runner_policy.rb
+++ b/app/policies/ci/runner_policy.rb
@@ -11,6 +11,10 @@ module Ci
rule { anonymous }.prevent_all
+ rule { admin }.policy do
+ enable :read_builds
+ end
+
rule { admin | owned_runner }.policy do
enable :assign_runner
enable :read_runner
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index fee47fe0ae9..76e5b3ece53 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -100,6 +100,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :read_group
enable :upload_file
enable :guest_access
+ enable :read_release
end
rule { admin }.policy do
@@ -144,6 +145,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :developer_access
enable :admin_crm_organization
enable :admin_crm_contact
+ enable :read_cluster
end
rule { reporter }.policy do
@@ -166,7 +168,6 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :create_projects
enable :admin_pipeline
enable :admin_build
- enable :read_cluster
enable :add_cluster
enable :create_cluster
enable :update_cluster
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index d9ea7c38f11..e85f18f2d37 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -16,7 +16,7 @@ class NotePolicy < BasePolicy
condition(:for_design) { @subject.for_design? }
- condition(:is_visible) { @subject.system_note_with_references_visible_for?(@user) }
+ condition(:is_visible) { @subject.system_note_visible_for?(@user) }
condition(:confidential, scope: :subject) { @subject.confidential? }
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 55f43cd9f7b..4cc5ed06d61 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -240,6 +240,7 @@ class ProjectPolicy < BasePolicy
enable :read_wiki
enable :read_issue
enable :read_label
+ enable :read_planning_hierarchy
enable :read_milestone
enable :read_snippet
enable :read_project_member
@@ -258,11 +259,13 @@ class ProjectPolicy < BasePolicy
rule { can?(:reporter_access) & can?(:create_issue) }.enable :create_incident
- rule { can?(:guest_access) & can?(:create_issue) }.policy do
+ rule { can?(:create_issue) }.policy do
enable :create_task
enable :create_work_item
end
+ rule { can?(:update_issue) }.enable :update_work_item
+
# These abilities are not allowed to admins that are not members of the project,
# that's why they are defined separately.
rule { guest & can?(:download_code) }.enable :build_download_code
@@ -385,6 +388,7 @@ class ProjectPolicy < BasePolicy
enable :destroy_environment
enable :create_deployment
enable :update_deployment
+ enable :read_cluster
enable :create_release
enable :update_release
enable :destroy_release
@@ -433,7 +437,6 @@ class ProjectPolicy < BasePolicy
enable :read_pages
enable :update_pages
enable :remove_pages
- enable :read_cluster
enable :add_cluster
enable :create_cluster
enable :update_cluster
@@ -572,6 +575,7 @@ class ProjectPolicy < BasePolicy
enable :read_issue_board_list
enable :read_wiki
enable :read_label
+ enable :read_planning_hierarchy
enable :read_milestone
enable :read_snippet
enable :read_project_member
diff --git a/app/policies/work_item_policy.rb b/app/policies/work_item_policy.rb
new file mode 100644
index 00000000000..7ba5102a406
--- /dev/null
+++ b/app/policies/work_item_policy.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class WorkItemPolicy < BasePolicy
+ delegate { @subject.project }
+
+ desc 'User is author of the work item'
+ condition(:author) do
+ @user && @user == @subject.author
+ end
+
+ rule { can?(:owner_access) | author }.enable :delete_work_item
+end
diff --git a/app/presenters/README.md b/app/presenters/README.md
index dfd1818f97d..31e5c971a88 100644
--- a/app/presenters/README.md
+++ b/app/presenters/README.md
@@ -223,13 +223,9 @@ To add methods of a module to an allowlist, use `delegator_override_with`. For e
```ruby
module Ci
class PipelinePresenter < Gitlab::View::Presenter::Delegated
- include Gitlab::Utils::StrongMemoize
- include ActionView::Helpers::UrlHelper
+ include ActionView::Helpers::TagHelper
- delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
- delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::UrlHelper` inclusion as it overrides `Ci::Pipeline#tag`
+ delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::TagHelper` inclusion as it overrides `Ci::Pipeline#tag`
```
-Keep in mind that if you use `delegator_override_with`,
-there is a high chance that you're doing **something wrong**.
Read the [Validate Accidental Overrides](#validate-accidental-overrides) for more information.
diff --git a/app/presenters/alert_management/alert_presenter.rb b/app/presenters/alert_management/alert_presenter.rb
index 86fe9859271..b692935d229 100644
--- a/app/presenters/alert_management/alert_presenter.rb
+++ b/app/presenters/alert_management/alert_presenter.rb
@@ -6,7 +6,7 @@ module AlertManagement
include ActionView::Helpers::UrlHelper
presents ::AlertManagement::Alert
- delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
+ delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
MARKDOWN_LINE_BREAK = " \n"
HORIZONTAL_LINE = "\n\n---\n\n"
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
index 2577fcaf303..47b72df32a2 100644
--- a/app/presenters/blob_presenter.rb
+++ b/app/presenters/blob_presenter.rb
@@ -32,7 +32,7 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
end
def blob_language
- @_blob_language ||= Gitlab::Diff::CustomDiff.transformed_blob_language(blob) || language
+ @_blob_language ||= Gitlab::Diff::CustomDiff.transformed_blob_language(blob) || gitattr_language || detect_language
end
def raw_plain_data
@@ -79,6 +79,18 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
url_helpers.project_blob_path(project, File.join(project.repository.commit.sha, blob.path))
end
+ def environment_formatted_external_url
+ return unless environment
+
+ environment.formatted_external_url
+ end
+
+ def environment_external_url_for_route_map
+ return unless environment
+
+ environment.external_url_for(blob.path, blob.commit_id)
+ end
+
# Will be overridden in EE
def code_owners
[]
@@ -113,7 +125,7 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
def external_storage_url
return unless static_objects_external_storage_enabled?
- external_storage_url_or_path(url_helpers.project_raw_url(project, ref_qualified_path))
+ external_storage_url_or_path(url_helpers.project_raw_url(project, ref_qualified_path), project)
end
private
@@ -122,6 +134,12 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
Gitlab::Routing.url_helpers
end
+ def environment
+ environment_params = project.repository.branch_exists?(blob.commit_id) ? { ref: blob.commit_id } : { sha: blob.commit_id }
+ environment_params[:find_latest] = true
+ ::Environments::EnvironmentsByDeploymentsFinder.new(project, current_user, environment_params).execute.last
+ end
+
def project
blob.repository.project
end
@@ -148,9 +166,15 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
@all_lines ||= blob.data.lines
end
- def language
+ def gitattr_language
blob.language_from_gitattributes
end
+
+ def detect_language
+ return if blob.binary?
+
+ Rouge::Lexer.guess(filename: blob.path, source: blob_data(nil)) { |lex| lex.min_by(&:tag) }.tag
+ end
end
BlobPresenter.prepend_mod_with('BlobPresenter')
diff --git a/app/presenters/blobs/unfold_presenter.rb b/app/presenters/blobs/unfold_presenter.rb
index b921b5bf670..90b471abf22 100644
--- a/app/presenters/blobs/unfold_presenter.rb
+++ b/app/presenters/blobs/unfold_presenter.rb
@@ -108,7 +108,7 @@ module Blobs
def limit(lines)
return lines if full?
- lines[since - 1..to - 1]
+ lines[since - 1..to - 1] || []
end
end
end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 7f5dffadcfb..2818e6da036 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -4,7 +4,7 @@ module Ci
class PipelinePresenter < Gitlab::View::Presenter::Delegated
include Gitlab::Utils::StrongMemoize
- delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
+ delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::UrlHelper` inclusion as it overrides `Ci::Pipeline#tag`
# We use a class method here instead of a constant, allowing EE to redefine
diff --git a/app/presenters/ci/runner_presenter.rb b/app/presenters/ci/runner_presenter.rb
index ffd826fab64..482534f27b9 100644
--- a/app/presenters/ci/runner_presenter.rb
+++ b/app/presenters/ci/runner_presenter.rb
@@ -15,5 +15,9 @@ module Ci
def executor_name
Ci::Runner::EXECUTOR_TYPE_TO_NAMES[executor_type&.to_sym]
end
+
+ def paused
+ !active
+ end
end
end
diff --git a/app/presenters/clusterable_presenter.rb b/app/presenters/clusterable_presenter.rb
index 4b645510b51..cc466e0ff81 100644
--- a/app/presenters/clusterable_presenter.rb
+++ b/app/presenters/clusterable_presenter.rb
@@ -16,6 +16,10 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
can?(current_user, :add_cluster, clusterable)
end
+ def can_admin_cluster?
+ can?(current_user, :admin_cluster, clusterable)
+ end
+
def can_create_cluster?
can?(current_user, :create_cluster, clusterable)
end
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index ce060476cfd..e2fc2b4b485 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -4,7 +4,7 @@ module Clusters
class ClusterPresenter < Gitlab::View::Presenter::Delegated
include ::Gitlab::Utils::StrongMemoize
- delegator_override_with ::Gitlab::Utils::StrongMemoize # TODO: Remove `::Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
+ delegator_override_with ::Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
presents ::Clusters::Cluster, as: :cluster
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index eeb94a8e657..8450679dd79 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -8,7 +8,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
include ChecksCollaboration
include Gitlab::Utils::StrongMemoize
- delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
+ delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
APPROVALS_WIDGET_BASE_TYPE = 'base'
diff --git a/app/presenters/packages/conan/package_presenter.rb b/app/presenters/packages/conan/package_presenter.rb
index 57636922676..0c7a81038dd 100644
--- a/app/presenters/packages/conan/package_presenter.rb
+++ b/app/presenters/packages/conan/package_presenter.rb
@@ -81,11 +81,7 @@ module Packages
return unless @package
strong_memoize(:package_files) do
- if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- @package.installable_package_files.preload_conan_file_metadata
- else
- @package.package_files.preload_conan_file_metadata
- end
+ @package.installable_package_files.preload_conan_file_metadata
end
end
diff --git a/app/presenters/packages/detail/package_presenter.rb b/app/presenters/packages/detail/package_presenter.rb
index c257edcadfb..b82b558f0cd 100644
--- a/app/presenters/packages/detail/package_presenter.rb
+++ b/app/presenters/packages/detail/package_presenter.rb
@@ -39,11 +39,7 @@ module Packages
private
def package_file_views
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- @package.installable_package_files
- else
- @package.package_files
- end
+ package_files = @package.installable_package_files
package_files.map { |pf| build_package_file_view(pf) }
end
diff --git a/app/presenters/packages/npm/package_presenter.rb b/app/presenters/packages/npm/package_presenter.rb
index 1f94187204f..fabb0a36746 100644
--- a/app/presenters/packages/npm/package_presenter.rb
+++ b/app/presenters/packages/npm/package_presenter.rb
@@ -26,11 +26,7 @@ module Packages
.preload_npm_metadatum
batched_packages.each do |package|
- package_file = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files.last
- else
- package.package_files.last
- end
+ package_file = package.installable_package_files.last
next unless package_file
diff --git a/app/presenters/packages/nuget/presenter_helpers.rb b/app/presenters/packages/nuget/presenter_helpers.rb
index cd3e123033c..5334e4aa6f8 100644
--- a/app/presenters/packages/nuget/presenter_helpers.rb
+++ b/app/presenters/packages/nuget/presenter_helpers.rb
@@ -27,13 +27,10 @@ module Packages
end
def archive_url_for(package)
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- package_filename = package_files.with_format(NUGET_PACKAGE_FORMAT).last&.file_name
+ package_filename = package.installable_package_files
+ .with_format(NUGET_PACKAGE_FORMAT)
+ .last
+ &.file_name
path = api_v4_projects_packages_nuget_download_package_name_package_version_package_filename_path(
{
id: package.project_id,
diff --git a/app/presenters/packages/pypi/package_presenter.rb b/app/presenters/packages/pypi/package_presenter.rb
index 33854e4d2fc..a779ce41cf9 100644
--- a/app/presenters/packages/pypi/package_presenter.rb
+++ b/app/presenters/packages/pypi/package_presenter.rb
@@ -36,11 +36,7 @@ module Packages
refs = []
@packages.map do |package|
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
+ package_files = package.installable_package_files
package_files.each do |file|
url = build_pypi_package_path(file)
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 64cd54953e2..9e64d2d43a2 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -13,7 +13,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
include Gitlab::Experiment::Dsl
delegator_override_with GitlabRoutingHelper # TODO: Remove `GitlabRoutingHelper` inclusion as it's duplicate
- delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
+ delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
presents ::Project, as: :project
diff --git a/app/presenters/projects/import_export/project_export_presenter.rb b/app/presenters/projects/import_export/project_export_presenter.rb
index 7b2ffb6d755..53c547cde9e 100644
--- a/app/presenters/projects/import_export/project_export_presenter.rb
+++ b/app/presenters/projects/import_export/project_export_presenter.rb
@@ -3,11 +3,14 @@
module Projects
module ImportExport
class ProjectExportPresenter < Gitlab::View::Presenter::Delegated
+ # NOTE: This is needed because this presenter is serialized to JSON,
+ # and we need to make sure that `#as_json` is called in this class so
+ # it will use the overriden attributes below. Otherwise the call is
+ # delegated to the model and will use the original methods.
include ActiveModel::Serializers::JSON
presents ::Project, as: :project
- # TODO: Remove `ActiveModel::Serializers::JSON` inclusion as it's duplicate
delegator_override_with ActiveModel::Serializers::JSON
delegator_override_with ActiveModel::Naming
delegator_override :include_root_in_json, :include_root_in_json?
diff --git a/app/presenters/projects/security/configuration_presenter.rb b/app/presenters/projects/security/configuration_presenter.rb
index 89fca1a451a..1798d4b780f 100644
--- a/app/presenters/projects/security/configuration_presenter.rb
+++ b/app/presenters/projects/security/configuration_presenter.rb
@@ -80,7 +80,8 @@ module Projects
type: scan.type,
configured: scan.configured?,
configuration_path: scan.configuration_path,
- available: scan.available?
+ available: scan.available?,
+ can_enable_by_merge_request: scan.can_enable_by_merge_request?
}
end
diff --git a/app/presenters/snippet_blob_presenter.rb b/app/presenters/snippet_blob_presenter.rb
index 026d442291c..51ce6ccea58 100644
--- a/app/presenters/snippet_blob_presenter.rb
+++ b/app/presenters/snippet_blob_presenter.rb
@@ -33,7 +33,7 @@ class SnippetBlobPresenter < BlobPresenter
blob.container
end
- def language
+ def gitattr_language
nil
end
diff --git a/app/serializers/analytics_summary_entity.rb b/app/serializers/analytics_summary_entity.rb
index dc42d7f52ad..a92214d0efa 100644
--- a/app/serializers/analytics_summary_entity.rb
+++ b/app/serializers/analytics_summary_entity.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class AnalyticsSummaryEntity < Grape::Entity
+ expose :identifier
expose :value, safe: true
expose :title
expose :unit, if: { with_unit: true }
diff --git a/app/serializers/codequality_degradation_entity.rb b/app/serializers/codequality_degradation_entity.rb
index be561052507..6289260465b 100644
--- a/app/serializers/codequality_degradation_entity.rb
+++ b/app/serializers/codequality_degradation_entity.rb
@@ -2,7 +2,9 @@
class CodequalityDegradationEntity < Grape::Entity
expose :description
- expose :severity
+ expose :severity do |degradation|
+ degradation.dig(:severity)&.downcase
+ end
expose :file_path do |degradation|
degradation.dig(:location, :path)
diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb
index 11445f93609..8d9b73b2290 100644
--- a/app/serializers/environment_serializer.rb
+++ b/app/serializers/environment_serializer.rb
@@ -52,17 +52,13 @@ class EnvironmentSerializer < BaseSerializer
end
def batch_load(resource)
- if ::Feature.enabled?(:custom_preloader_for_deployments, default_enabled: :yaml)
- resource = resource.preload(environment_associations.except(:last_deployment, :upcoming_deployment))
+ resource = resource.preload(environment_associations.except(:last_deployment, :upcoming_deployment))
- Preloaders::Environments::DeploymentPreloader.new(resource)
- .execute_with_union(:last_deployment, deployment_associations)
+ Preloaders::Environments::DeploymentPreloader.new(resource)
+ .execute_with_union(:last_deployment, deployment_associations)
- Preloaders::Environments::DeploymentPreloader.new(resource)
- .execute_with_union(:upcoming_deployment, deployment_associations)
- else
- resource = resource.preload(environment_associations)
- end
+ Preloaders::Environments::DeploymentPreloader.new(resource)
+ .execute_with_union(:upcoming_deployment, deployment_associations)
resource.all.to_a.tap do |environments|
environments.each do |environment|
diff --git a/app/serializers/group_child_entity.rb b/app/serializers/group_child_entity.rb
index c469dbdd6b8..08070c03bf8 100644
--- a/app/serializers/group_child_entity.rb
+++ b/app/serializers/group_child_entity.rb
@@ -58,6 +58,10 @@ class GroupChildEntity < Grape::Entity
end
end
+ expose :can_remove, unless: lambda { |_instance, _options| project? } do |group|
+ can?(request.current_user, :admin_group, group)
+ end
+
expose :number_users_with_delimiter, unless: lambda { |_instance, _options| project? } do |instance|
number_with_delimiter(instance.member_count)
end
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
index 14e416fb71a..b66aad6cc65 100644
--- a/app/serializers/issuable_sidebar_basic_entity.rb
+++ b/app/serializers/issuable_sidebar_basic_entity.rb
@@ -110,6 +110,7 @@ class IssuableSidebarBasicEntity < Grape::Entity
expose :supports_time_tracking?, as: :supports_time_tracking
expose :supports_milestone?, as: :supports_milestone
expose :supports_severity?, as: :supports_severity
+ expose :supports_escalation?, as: :supports_escalation
private
diff --git a/app/serializers/issue_sidebar_basic_entity.rb b/app/serializers/issue_sidebar_basic_entity.rb
index f93a42e5f98..9c6601afd5e 100644
--- a/app/serializers/issue_sidebar_basic_entity.rb
+++ b/app/serializers/issue_sidebar_basic_entity.rb
@@ -4,6 +4,12 @@ class IssueSidebarBasicEntity < IssuableSidebarBasicEntity
expose :due_date
expose :confidential
expose :severity
+
+ expose :current_user, merge: true do
+ expose :can_update_escalation_status, if: -> (issue, _) { issue.supports_escalation? } do |issue|
+ can?(current_user, :update_escalation_status, issue.project)
+ end
+ end
end
IssueSidebarBasicEntity.prepend_mod_with('IssueSidebarBasicEntity')
diff --git a/app/serializers/member_user_entity.rb b/app/serializers/member_user_entity.rb
index 01920fc95bb..fde3282ad25 100644
--- a/app/serializers/member_user_entity.rb
+++ b/app/serializers/member_user_entity.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class MemberUserEntity < UserEntity
- unexpose :show_status
unexpose :path
unexpose :state
unexpose :status_tooltip_html
diff --git a/app/serializers/merge_request_poll_cached_widget_entity.rb b/app/serializers/merge_request_poll_cached_widget_entity.rb
index 5bf02c93c99..9d001d18aa6 100644
--- a/app/serializers/merge_request_poll_cached_widget_entity.rb
+++ b/app/serializers/merge_request_poll_cached_widget_entity.rb
@@ -8,7 +8,6 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
expose :merged_commit_sha
expose :short_merged_commit_sha
expose :merge_error
- expose :public_merge_status, as: :merge_status
expose :merge_user_id
expose :source_branch
expose :source_project_id
@@ -26,6 +25,11 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
expose :source_branch_exists?, as: :source_branch_exists
expose :branch_missing?, as: :branch_missing
+ expose :merge_status do |merge_request|
+ merge_request.check_mergeability(async: true)
+ merge_request.public_merge_status
+ end
+
expose :default_squash_commit_message do |merge_request|
merge_request.default_squash_commit_message(user: request.current_user)
end
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index f68477e82c9..12998d70a22 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -24,8 +24,6 @@ class MergeRequestPollWidgetEntity < Grape::Entity
end
expose :mergeable do |merge_request, options|
- next merge_request.mergeable? if Feature.disabled?(:check_mergeability_async_in_widget, merge_request.project, default_enabled: :yaml)
-
merge_request.mergeable?
end
diff --git a/app/serializers/test_case_entity.rb b/app/serializers/test_case_entity.rb
index 0e64b843fd3..8a5fadf53a6 100644
--- a/app/serializers/test_case_entity.rb
+++ b/app/serializers/test_case_entity.rb
@@ -4,7 +4,7 @@ class TestCaseEntity < Grape::Entity
include API::Helpers::RelatedResourcesHelpers
expose :status
- expose :name
+ expose :name, default: "(No name)"
expose :classname
expose :file
expose :execution_time
diff --git a/app/services/alert_management/alerts/update_service.rb b/app/services/alert_management/alerts/update_service.rb
index 7a9bcf2a52d..0769adc862e 100644
--- a/app/services/alert_management/alerts/update_service.rb
+++ b/app/services/alert_management/alerts/update_service.rb
@@ -12,6 +12,7 @@ module AlertManagement
@alert = alert
@param_errors = []
@status = params.delete(:status)
+ @status_change_reason = params.delete(:status_change_reason)
super(project: alert.project, current_user: current_user, params: params)
end
@@ -36,7 +37,7 @@ module AlertManagement
private
- attr_reader :alert, :param_errors, :status
+ attr_reader :alert, :param_errors, :status, :status_change_reason
def allowed?
current_user&.can?(:update_alert_management_alert, alert)
@@ -133,7 +134,7 @@ module AlertManagement
end
def add_status_change_system_note
- SystemNoteService.change_alert_status(alert, current_user)
+ SystemNoteService.change_alert_status(alert, current_user, status_change_reason)
end
def resolve_todos
@@ -144,13 +145,17 @@ module AlertManagement
::Issues::UpdateService.new(
project: project,
current_user: current_user,
- params: { escalation_status: { status: status } }
+ params: {
+ escalation_status: {
+ status: status,
+ status_change_reason: " by changing the status of #{alert.to_reference(project)}"
+ }
+ }
).execute(alert.issue)
end
def should_sync_to_incident?
- Feature.enabled?(:incident_escalations, project) &&
- alert.issue &&
+ alert.issue &&
alert.issue.supports_escalation? &&
alert.issue.escalation_status &&
alert.issue.escalation_status.status != alert.status
diff --git a/app/services/alert_management/create_alert_issue_service.rb b/app/services/alert_management/create_alert_issue_service.rb
index a81c2380dad..ab8d1176b9e 100644
--- a/app/services/alert_management/create_alert_issue_service.rb
+++ b/app/services/alert_management/create_alert_issue_service.rb
@@ -22,8 +22,6 @@ module AlertManagement
return result unless result.success?
issue = result.payload[:issue]
- return error(object_errors(alert), issue) unless associate_alert_with_issue(issue)
-
update_title_for(issue)
SystemNoteService.new_alert_issue(alert, issue, user)
@@ -47,14 +45,11 @@ module AlertManagement
user,
title: alert_presenter.title,
description: alert_presenter.issue_description,
- severity: alert.severity
+ severity: alert.severity,
+ alert: alert
).execute
end
- def associate_alert_with_issue(issue)
- alert.update(issue_id: issue.id)
- end
-
def update_title_for(issue)
return unless issue.title == DEFAULT_ALERT_TITLE
@@ -78,9 +73,5 @@ module AlertManagement
alert.present
end
end
-
- def object_errors(object)
- object.errors.full_messages.to_sentence
- end
end
end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index f2b1d89161c..ad733c455a9 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -5,7 +5,7 @@ class AuditEventService
# Instantiates a new service
#
- # @param [User] author the user who authors the change
+ # @param [User, token String] author the entity who authors the change
# @param [User, Project, Group] entity the scope which audit event belongs to
# This param is also used to determine the visibility of the audit event.
# - Project: events are visible at Project and Instance level
@@ -44,7 +44,7 @@ class AuditEventService
# Writes event to a file and creates an event record in DB
#
- # @return [AuditEvent] persited if saves and non-persisted if fails
+ # @return [AuditEvent] persisted if saves and non-persisted if fails
def security_event
log_security_event_to_file
log_authentication_event_to_database
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index a92a2c8aef5..84518fd6b0e 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -14,6 +14,10 @@ module Auth
:build_destroy_container_image
].freeze
+ FORBIDDEN_IMPORTING_SCOPES = %w[push delete *].freeze
+
+ ActiveImportError = Class.new(StandardError)
+
def execute(authentication_abilities:)
@authentication_abilities = authentication_abilities
@@ -26,17 +30,27 @@ module Auth
end
{ token: authorized_token(*scopes).encoded }
+ rescue ActiveImportError
+ error(
+ 'DENIED',
+ status: 403,
+ message: 'Your repository is currently being migrated to a new platform and writes are temporarily disabled. Go to https://gitlab.com/groups/gitlab-org/-/epics/5523 to learn more.'
+ )
end
def self.full_access_token(*names)
access_token(%w(*), names)
end
+ def self.import_access_token
+ access_token(%w(*), ['import'], 'registry')
+ end
+
def self.pull_access_token(*names)
access_token(['pull'], names)
end
- def self.access_token(actions, names)
+ def self.access_token(actions, names, type = 'repository')
names = names.flatten
registry = Gitlab.config.registry
token = JSONWebToken::RSAToken.new(registry.key)
@@ -46,10 +60,10 @@ module Auth
token[:access] = names.map do |name|
{
- type: 'repository',
+ type: type,
name: name,
actions: actions,
- migration_eligible: migration_eligible(repository_path: name)
+ migration_eligible: type == 'repository' ? migration_eligible(repository_path: name) : nil
}.compact
end
@@ -104,6 +118,8 @@ module Auth
def process_repository_access(type, path, actions)
return unless path.valid?
+ raise ActiveImportError if actively_importing?(actions, path)
+
requested_project = path.repository_project
return unless requested_project
@@ -124,11 +140,19 @@ module Auth
type: type,
name: path.to_s,
actions: authorized_actions,
- migration_eligible: self.class.migration_eligible(project: requested_project),
- cdn_redirect: cdn_redirect
+ migration_eligible: self.class.migration_eligible(project: requested_project)
}.compact
end
+ def actively_importing?(actions, path)
+ return false if FORBIDDEN_IMPORTING_SCOPES.intersection(actions).empty?
+
+ container_repository = ContainerRepository.find_by_path(path)
+ return false unless container_repository
+
+ container_repository.migration_importing?
+ end
+
def self.migration_eligible(project: nil, repository_path: nil)
return unless Feature.enabled?(:container_registry_migration_phase1)
@@ -151,13 +175,6 @@ module Auth
false
end
- # This is used to determine whether blob download requests using a given JWT token should be redirected to Google
- # Cloud CDN or not. The intent is to enable a percentage of time rollout for this new feature on the Container
- # Registry side. See https://gitlab.com/gitlab-org/gitlab/-/issues/349417 for more details.
- def cdn_redirect
- Feature.enabled?(:container_registry_cdn_redirect) || nil
- end
-
##
# Because we do not have two way communication with registry yet,
# we create a container repository image resource when push to the
diff --git a/app/services/boards/base_item_move_service.rb b/app/services/boards/base_item_move_service.rb
index be16c595abb..9d711d83fd2 100644
--- a/app/services/boards/base_item_move_service.rb
+++ b/app/services/boards/base_item_move_service.rb
@@ -39,7 +39,7 @@ module Boards
end
def reposition_params(reposition_ids)
- reposition_parent.merge(move_between_ids: reposition_ids)
+ { move_between_ids: reposition_ids }
end
def move_single_issuable(issuable, issuable_modification_params)
@@ -91,7 +91,7 @@ module Boards
end
def move_between_ids(move_params)
- ids = [move_params[:move_after_id], move_params[:move_before_id]]
+ ids = [move_params[:move_before_id], move_params[:move_after_id]]
.map(&:to_i)
.map { |m| m > 0 ? m : nil }
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 959a7fa3ad2..90226b9d4e0 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -54,10 +54,6 @@ module Boards
def update(issue, issue_modification_params)
::Issues::UpdateService.new(project: issue.project, current_user: current_user, params: issue_modification_params).execute(issue)
end
-
- def reposition_parent
- { board_group_id: board.group&.id }
- end
end
end
end
diff --git a/app/services/branches/create_service.rb b/app/services/branches/create_service.rb
index b5faf2ec281..7300b31e3b3 100644
--- a/app/services/branches/create_service.rb
+++ b/app/services/branches/create_service.rb
@@ -21,7 +21,7 @@ module Branches
error("Failed to create branch '#{branch_name}': invalid reference name '#{ref}'")
end
rescue Gitlab::Git::PreReceiveError => e
- Gitlab::ErrorTracking.track_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
+ Gitlab::ErrorTracking.log_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
error(e.message)
end
diff --git a/app/services/ci/after_requeue_job_service.rb b/app/services/ci/after_requeue_job_service.rb
index ee0ae6651ca..097b29cf143 100644
--- a/app/services/ci/after_requeue_job_service.rb
+++ b/app/services/ci/after_requeue_job_service.rb
@@ -22,13 +22,9 @@ module Ci
end
def dependent_jobs
- if ::Feature.enabled?(:ci_order_subsequent_jobs_by_stage, @processable.pipeline.project, default_enabled: :yaml)
- stage_dependent_jobs
- .or(needs_dependent_jobs.except(:preload))
- .ordered_by_stage
- else
- stage_dependent_jobs | needs_dependent_jobs
- end
+ stage_dependent_jobs
+ .or(needs_dependent_jobs.except(:preload))
+ .ordered_by_stage
end
def process(job)
diff --git a/app/services/ci/copy_cross_database_associations_service.rb b/app/services/ci/copy_cross_database_associations_service.rb
new file mode 100644
index 00000000000..c69e966dc04
--- /dev/null
+++ b/app/services/ci/copy_cross_database_associations_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Ci
+ class CopyCrossDatabaseAssociationsService
+ def execute(old_build, new_build)
+ ServiceResponse.success
+ end
+ end
+end
+
+Ci::CopyCrossDatabaseAssociationsService.prepend_mod_with('Ci::CopyCrossDatabaseAssociationsService')
diff --git a/app/services/ci/create_downstream_pipeline_service.rb b/app/services/ci/create_downstream_pipeline_service.rb
index a65c22e273c..a2e53cbf9b8 100644
--- a/app/services/ci/create_downstream_pipeline_service.rb
+++ b/app/services/ci/create_downstream_pipeline_service.rb
@@ -125,7 +125,9 @@ module Ci
config_checksum(pipeline) unless pipeline.child?
end
- pipeline_checksums.uniq.length != pipeline_checksums.length
+ # To avoid false positives we allow 1 cycle in the ancestry and
+ # fail when 2 cycles are detected: A -> B -> A -> B -> A
+ pipeline_checksums.tally.any? { |_checksum, occurrences| occurrences > 2 }
end
end
@@ -137,7 +139,7 @@ module Ci
end
def config_checksum(pipeline)
- [pipeline.project_id, pipeline.ref].hash
+ [pipeline.project_id, pipeline.ref, pipeline.source].hash
end
end
end
diff --git a/app/services/ci/pipeline_schedule_service.rb b/app/services/ci/pipeline_schedule_service.rb
index 596c3b80bda..536eaa56f9b 100644
--- a/app/services/ci/pipeline_schedule_service.rb
+++ b/app/services/ci/pipeline_schedule_service.rb
@@ -3,6 +3,8 @@
module Ci
class PipelineScheduleService < BaseService
def execute(schedule)
+ return unless project.persisted?
+
# Ensure `next_run_at` is set properly before creating a pipeline.
# Otherwise, multiple pipelines could be created in a short interval.
schedule.schedule_next_run!
diff --git a/app/services/ci/process_sync_events_service.rb b/app/services/ci/process_sync_events_service.rb
index 11ce6e8eeaf..d90ee02b1c6 100644
--- a/app/services/ci/process_sync_events_service.rb
+++ b/app/services/ci/process_sync_events_service.rb
@@ -2,7 +2,6 @@
module Ci
class ProcessSyncEventsService
- include Gitlab::Utils::StrongMemoize
include ExclusiveLeaseGuard
BATCH_SIZE = 1000
@@ -10,22 +9,27 @@ module Ci
def initialize(sync_event_class, sync_class)
@sync_event_class = sync_event_class
@sync_class = sync_class
+ @results = {}
end
def execute
- return unless ::Feature.enabled?(:ci_namespace_project_mirrors, default_enabled: :yaml)
-
# preventing parallel processing over the same event table
try_obtain_lease { process_events }
enqueue_worker_if_there_still_event
+
+ @results
end
private
def process_events
+ add_result(estimated_total_events: @sync_event_class.upper_bound_count)
+
events = @sync_event_class.preload_synced_relation.first(BATCH_SIZE)
+ add_result(consumable_events: events.size)
+
return if events.empty?
processed_events = []
@@ -37,6 +41,7 @@ module Ci
processed_events << event
end
ensure
+ add_result(processed_events: processed_events.size)
@sync_event_class.id_in(processed_events).delete_all
end
end
@@ -52,5 +57,9 @@ module Ci
def lease_timeout
1.minute
end
+
+ def add_result(result)
+ @results.merge!(result)
+ end
end
end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index e0f0f8f58b8..59c4c17a964 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -159,7 +159,7 @@ module Ci
return
end
- if runner.can_pick?(build)
+ if runner.matches_build?(build)
@metrics.increment_queue_operation(:build_can_pick)
else
@metrics.increment_queue_operation(:build_not_pick)
diff --git a/app/services/ci/register_runner_service.rb b/app/services/ci/register_runner_service.rb
index 0a2027e33ce..7c6cd82565d 100644
--- a/app/services/ci/register_runner_service.rb
+++ b/app/services/ci/register_runner_service.rb
@@ -3,7 +3,7 @@
module Ci
class RegisterRunnerService
def execute(registration_token, attributes)
- runner_type_attrs = check_token_and_extract_attrs(registration_token)
+ runner_type_attrs = extract_runner_type_attrs(registration_token)
return unless runner_type_attrs
@@ -12,16 +12,32 @@ module Ci
private
- def check_token_and_extract_attrs(registration_token)
+ def extract_runner_type_attrs(registration_token)
+ @attrs_from_token ||= check_token(registration_token)
+
+ return unless @attrs_from_token
+
+ attrs = @attrs_from_token.clone
+ case attrs[:runner_type]
+ when :project_type
+ attrs[:projects] = [attrs.delete(:scope)]
+ when :group_type
+ attrs[:groups] = [attrs.delete(:scope)]
+ end
+
+ attrs
+ end
+
+ def check_token(registration_token)
if runner_registration_token_valid?(registration_token)
# Create shared runner. Requires admin access
{ runner_type: :instance_type }
elsif runner_registrar_valid?('project') && project = ::Project.find_by_runners_token(registration_token)
# Create a specific runner for the project
- { runner_type: :project_type, projects: [project] }
+ { runner_type: :project_type, scope: project }
elsif runner_registrar_valid?('group') && group = ::Group.find_by_runners_token(registration_token)
# Create a specific runner for the group
- { runner_type: :group_type, groups: [group] }
+ { runner_type: :group_type, scope: group }
end
end
@@ -32,5 +48,11 @@ module Ci
def runner_registrar_valid?(type)
Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?(type)
end
+
+ def token_scope
+ @attrs_from_token[:scope]
+ end
end
end
+
+Ci::RegisterRunnerService.prepend_mod
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 7e5d5373648..73c5d0163da 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -40,17 +40,15 @@ module Ci
new_build = clone_build(build)
new_build.run_after_commit do
+ ::Ci::CopyCrossDatabaseAssociationsService.new.execute(build, new_build)
+
+ ::Deployments::CreateForBuildService.new.execute(new_build)
+
::MergeRequests::AddTodoWhenBuildFailsService
.new(project: project)
.close(new_build)
end
- if create_deployment_in_separate_transaction?
- new_build.run_after_commit do |new_build|
- ::Deployments::CreateForBuildService.new.execute(new_build)
- end
- end
-
::Ci::Pipelines::AddJobService.new(build.pipeline).execute!(new_build) do |job|
BulkInsertableAssociations.with_bulk_insert do
job.save!
@@ -74,11 +72,7 @@ module Ci
def check_assignable_runners!(build); end
def clone_build(build)
- project.builds.new(build_attributes(build)).tap do |new_build|
- unless create_deployment_in_separate_transaction?
- new_build.assign_attributes(deployment_attributes_for(new_build, build))
- end
- end
+ project.builds.new(build_attributes(build))
end
def build_attributes(build)
@@ -86,7 +80,7 @@ module Ci
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
- if create_deployment_in_separate_transaction? && build.persisted_environment.present?
+ if build.persisted_environment.present?
attributes[:metadata_attributes] ||= {}
attributes[:metadata_attributes][:expanded_environment_name] = build.expanded_environment_name
end
@@ -94,17 +88,6 @@ module Ci
attributes[:user] = current_user
attributes
end
-
- def deployment_attributes_for(new_build, old_build)
- ::Gitlab::Ci::Pipeline::Seed::Build
- .deployment_attributes_for(new_build, old_build.persisted_environment)
- end
-
- def create_deployment_in_separate_transaction?
- strong_memoize(:create_deployment_in_separate_transaction) do
- ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
- end
- end
end
end
diff --git a/app/services/ci/unregister_runner_service.rb b/app/services/ci/unregister_runner_service.rb
new file mode 100644
index 00000000000..97d9852b7ed
--- /dev/null
+++ b/app/services/ci/unregister_runner_service.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Ci
+ class UnregisterRunnerService
+ attr_reader :runner
+
+ # @param [Ci::Runner] runner the runner to unregister/destroy
+ def initialize(runner)
+ @runner = runner
+ end
+
+ def execute
+ @runner&.destroy
+ end
+ end
+end
diff --git a/app/services/ci/update_build_queue_service.rb b/app/services/ci/update_build_queue_service.rb
index 2e38969c7a9..5a011a8cac6 100644
--- a/app/services/ci/update_build_queue_service.rb
+++ b/app/services/ci/update_build_queue_service.rb
@@ -100,7 +100,7 @@ module Ci
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)
+ runners = runners.with_tags
metrics.observe_active_runners(-> { runners.to_a.size })
diff --git a/app/services/ci/update_runner_service.rb b/app/services/ci/update_runner_service.rb
index e4117a51fe6..4a17e25c0cc 100644
--- a/app/services/ci/update_runner_service.rb
+++ b/app/services/ci/update_runner_service.rb
@@ -9,6 +9,8 @@ module Ci
end
def update(params)
+ params[:active] = !params.delete(:paused) if params.include?(:paused)
+
runner.update(params).tap do |updated|
runner.tick_runner_queue if updated
end
diff --git a/app/services/concerns/members/bulk_create_users.rb b/app/services/concerns/members/bulk_create_users.rb
index b98917f1396..9cfef96311e 100644
--- a/app/services/concerns/members/bulk_create_users.rb
+++ b/app/services/concerns/members/bulk_create_users.rb
@@ -48,6 +48,7 @@ module Members
end
if user_ids.present?
+ # we should handle the idea of existing members where users are passed as users - https://gitlab.com/gitlab-org/gitlab/-/issues/352617
# the below will automatically discard invalid user_ids
users.concat(User.id_in(user_ids))
# helps not have to perform another query per user id to see if the member exists later on when fetching
diff --git a/app/services/concerns/rate_limited_service.rb b/app/services/concerns/rate_limited_service.rb
index 87cba7814fe..c8dc60355cf 100644
--- a/app/services/concerns/rate_limited_service.rb
+++ b/app/services/concerns/rate_limited_service.rb
@@ -17,7 +17,7 @@ module RateLimitedService
end
def log_request(request, current_user)
- rate_limiter.class.log_request(request, "#{key}_request_limit".to_sym, current_user)
+ rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
end
private
@@ -26,20 +26,19 @@ module RateLimitedService
end
class RateLimiterScopedAndKeyed
- attr_reader :key, :opts, :rate_limiter_klass
+ attr_reader :key, :opts, :rate_limiter
- def initialize(key:, opts:, rate_limiter_klass:)
+ def initialize(key:, opts:, rate_limiter:)
@key = key
@opts = opts
- @rate_limiter_klass = rate_limiter_klass
+ @rate_limiter = rate_limiter
end
def rate_limit!(service)
evaluated_scope = evaluated_scope_for(service)
return if feature_flag_disabled?(evaluated_scope[:project])
- rate_limiter = new_rate_limiter(evaluated_scope)
- if rate_limiter.throttled?
+ if rate_limiter.throttled?(key, **opts.merge(scope: evaluated_scope.values, users_allowlist: users_allowlist))
raise RateLimitedError.new(key: key, rate_limiter: rate_limiter), _('This endpoint has been requested too many times. Try again later.')
end
end
@@ -59,20 +58,16 @@ module RateLimitedService
def feature_flag_disabled?(project)
Feature.disabled?("rate_limited_service_#{key}", project, default_enabled: :yaml)
end
-
- def new_rate_limiter(evaluated_scope)
- rate_limiter_klass.new(key, **opts.merge(scope: evaluated_scope.values, users_allowlist: users_allowlist))
- end
end
prepended do
attr_accessor :rate_limiter_bypassed
cattr_accessor :rate_limiter_scoped_and_keyed
- def self.rate_limit(key:, opts:, rate_limiter_klass: ::Gitlab::ApplicationRateLimiter)
+ def self.rate_limit(key:, opts:, rate_limiter: ::Gitlab::ApplicationRateLimiter)
self.rate_limiter_scoped_and_keyed = RateLimiterScopedAndKeyed.new(key: key,
opts: opts,
- rate_limiter_klass: rate_limiter_klass)
+ rate_limiter: rate_limiter)
end
end
diff --git a/app/services/google_cloud/create_service_accounts_service.rb b/app/services/google_cloud/create_service_accounts_service.rb
index fa025e8f672..e360b3a8e4e 100644
--- a/app/services/google_cloud/create_service_accounts_service.rb
+++ b/app/services/google_cloud/create_service_accounts_service.rb
@@ -5,6 +5,7 @@ module GoogleCloud
def execute
service_account = google_api_client.create_service_account(gcp_project_id, service_account_name, service_account_desc)
service_account_key = google_api_client.create_service_account_key(gcp_project_id, service_account.unique_id)
+ google_api_client.grant_service_account_roles(gcp_project_id, service_account.email)
service_accounts_service.add_for_project(
environment_name,
@@ -35,7 +36,7 @@ module GoogleCloud
end
def google_api_client
- GoogleApi::CloudPlatform::Client.new(google_oauth2_token, nil)
+ @google_api_client_instance ||= GoogleApi::CloudPlatform::Client.new(google_oauth2_token, nil)
end
def service_accounts_service
@@ -50,7 +51,7 @@ module GoogleCloud
"GitLab generated service account for project '#{project.name}' and environment '#{environment_name}'"
end
- # Overriden in EE
+ # Overridden in EE
def environment_protected?
false
end
diff --git a/app/services/google_cloud/enable_cloud_run_service.rb b/app/services/google_cloud/enable_cloud_run_service.rb
new file mode 100644
index 00000000000..643f2b2b6d2
--- /dev/null
+++ b/app/services/google_cloud/enable_cloud_run_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ class EnableCloudRunService < :: BaseService
+ def execute
+ gcp_project_ids = unique_gcp_project_ids
+
+ if gcp_project_ids.empty?
+ error("No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.")
+ else
+ google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+
+ gcp_project_ids.each do |gcp_project_id|
+ google_api_client.enable_cloud_run(gcp_project_id)
+ google_api_client.enable_artifacts_registry(gcp_project_id)
+ google_api_client.enable_cloud_build(gcp_project_id)
+ end
+
+ success({ gcp_project_ids: gcp_project_ids })
+ end
+ end
+
+ private
+
+ def unique_gcp_project_ids
+ all_gcp_project_ids = project.variables.filter { |var| var.key == 'GCP_PROJECT_ID' }.map { |var| var.value }
+ all_gcp_project_ids.uniq
+ end
+
+ def token_in_session
+ @params[:token_in_session]
+ end
+ end
+end
diff --git a/app/services/google_cloud/generate_pipeline_service.rb b/app/services/google_cloud/generate_pipeline_service.rb
new file mode 100644
index 00000000000..077f815e60c
--- /dev/null
+++ b/app/services/google_cloud/generate_pipeline_service.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ class GeneratePipelineService < :: BaseService
+ ACTION_DEPLOY_TO_CLOUD_RUN = 'DEPLOY_TO_CLOUD_RUN'
+ ACTION_DEPLOY_TO_CLOUD_STORAGE = 'DEPLOY_TO_CLOUD_STORAGE'
+
+ def execute
+ commit_attributes = generate_commit_attributes
+ create_branch_response = ::Branches::CreateService.new(project, current_user)
+ .execute(commit_attributes[:branch_name], project.default_branch)
+
+ if create_branch_response[:status] == :error
+ return create_branch_response
+ end
+
+ branch = create_branch_response[:branch]
+
+ service = default_branch_gitlab_ci_yml.present? ? ::Files::UpdateService : ::Files::CreateService
+
+ commit_response = service.new(project, current_user, commit_attributes).execute
+
+ if commit_response[:status] == :error
+ return commit_response
+ end
+
+ success({ branch_name: branch.name, commit: commit_response })
+ end
+
+ private
+
+ def action
+ @params[:action]
+ end
+
+ def generate_commit_attributes
+ if action == ACTION_DEPLOY_TO_CLOUD_RUN
+ branch_name = "deploy-to-cloud-run-#{SecureRandom.hex(8)}"
+ {
+ commit_message: 'Enable Cloud Run deployments',
+ file_path: '.gitlab-ci.yml',
+ file_content: pipeline_content('gcp/cloud-run.gitlab-ci.yml'),
+ branch_name: branch_name,
+ start_branch: branch_name
+ }
+ elsif action == ACTION_DEPLOY_TO_CLOUD_STORAGE
+ branch_name = "deploy-to-cloud-storage-#{SecureRandom.hex(8)}"
+ {
+ commit_message: 'Enable Cloud Storage deployments',
+ file_path: '.gitlab-ci.yml',
+ file_content: pipeline_content('gcp/cloud-storage.gitlab-ci.yml'),
+ branch_name: branch_name,
+ start_branch: branch_name
+ }
+ end
+ end
+
+ def default_branch_gitlab_ci_yml
+ @default_branch_gitlab_ci_yml ||= project.repository.gitlab_ci_yml_for(project.default_branch)
+ end
+
+ def pipeline_content(include_path)
+ gitlab_ci_yml = Gitlab::Config::Loader::Yaml.new(default_branch_gitlab_ci_yml || '{}').load!
+ append_remote_include(gitlab_ci_yml, "https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/#{include_path}")
+ end
+
+ def append_remote_include(gitlab_ci_yml, include_url)
+ stages = gitlab_ci_yml['stages'] || []
+ gitlab_ci_yml['stages'] = (stages + %w[build test deploy]).uniq
+
+ includes = gitlab_ci_yml['include'] || []
+ includes = Array.wrap(includes)
+ includes << { 'remote' => include_url }
+ gitlab_ci_yml['include'] = includes.uniq
+
+ gitlab_ci_yml.to_yaml
+ end
+ end
+end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index da3cebc2e6d..67cbbaf84f6 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -61,6 +61,8 @@ module Groups
delay = Namespaces::InviteTeamEmailService::DELIVERY_DELAY_IN_MINUTES
Namespaces::InviteTeamEmailWorker.perform_in(delay, group.id, current_user.id)
end
+
+ track_experiment_event
end
def remove_unallowed_params
@@ -112,6 +114,15 @@ module Groups
@group.shared_runners_enabled = @group.parent.shared_runners_enabled
@group.allow_descendants_override_disabled_shared_runners = @group.parent.allow_descendants_override_disabled_shared_runners
end
+
+ def track_experiment_event
+ return unless group.persisted?
+
+ # Track namespace created events to relate them with signed up events for
+ # the same experiment. This will let us associate created namespaces to
+ # users that signed up from the experimental logged out header.
+ experiment(:logged_out_marketing_header, actor: current_user).track(:namespace_created, namespace: group)
+ end
end
end
diff --git a/app/services/groups/update_statistics_service.rb b/app/services/groups/update_statistics_service.rb
new file mode 100644
index 00000000000..9efce79ef42
--- /dev/null
+++ b/app/services/groups/update_statistics_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Groups
+ class UpdateStatisticsService
+ attr_reader :group, :statistics
+
+ def initialize(group, statistics: [])
+ @group = group
+ @statistics = statistics
+ end
+
+ def execute
+ unless group
+ return ServiceResponse.error(message: 'Invalid group', http_status: 400)
+ end
+
+ namespace_statistics.refresh!(only: statistics.map(&:to_sym))
+
+ ServiceResponse.success(message: 'Group statistics successfully updated.')
+ end
+
+ private
+
+ def namespace_statistics
+ @namespace_statistics ||= group.namespace_statistics || group.build_namespace_statistics
+ end
+ end
+end
diff --git a/app/services/incident_management/create_incident_label_service.rb b/app/services/incident_management/create_incident_label_service.rb
deleted file mode 100644
index 595f5df184f..00000000000
--- a/app/services/incident_management/create_incident_label_service.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module IncidentManagement
- class CreateIncidentLabelService < BaseService
- LABEL_PROPERTIES = {
- title: 'incident',
- color: '#CC0033',
- description: <<~DESCRIPTION.chomp
- Denotes a disruption to IT services and \
- the associated issues require immediate attention
- DESCRIPTION
- }.freeze
-
- def execute
- label = Labels::FindOrCreateService
- .new(current_user, project, **LABEL_PROPERTIES)
- .execute(skip_authorization: true)
-
- ServiceResponse.success(payload: { label: label })
- end
- end
-end
diff --git a/app/services/incident_management/incidents/create_service.rb b/app/services/incident_management/incidents/create_service.rb
index f8437290d9b..ef66325fdcc 100644
--- a/app/services/incident_management/incidents/create_service.rb
+++ b/app/services/incident_management/incidents/create_service.rb
@@ -2,15 +2,16 @@
module IncidentManagement
module Incidents
- class CreateService < BaseService
+ class CreateService < ::BaseProjectService
ISSUE_TYPE = 'incident'
- def initialize(project, current_user, title:, description:, severity: IssuableSeverity::DEFAULT)
- super(project, current_user)
+ def initialize(project, current_user, title:, description:, severity: IssuableSeverity::DEFAULT, alert: nil)
+ super(project: project, current_user: current_user)
@title = title
@description = description
@severity = severity
+ @alert = alert
end
def execute
@@ -21,11 +22,16 @@ module IncidentManagement
title: title,
description: description,
issue_type: ISSUE_TYPE,
- severity: severity
+ severity: severity,
+ alert_management_alert: alert
},
spam_params: nil
).execute
+ if alert
+ return error(alert.errors.full_messages.to_sentence, issue) unless alert.valid?
+ end
+
return error(issue.errors.full_messages.to_sentence, issue) unless issue.valid?
success(issue)
@@ -33,7 +39,7 @@ module IncidentManagement
private
- attr_reader :title, :description, :severity
+ attr_reader :title, :description, :severity, :alert
def success(issue)
ServiceResponse.success(payload: { issue: issue })
diff --git a/app/services/incident_management/issuable_escalation_statuses/after_update_service.rb b/app/services/incident_management/issuable_escalation_statuses/after_update_service.rb
index a7a99f88b32..b7f8b268f18 100644
--- a/app/services/incident_management/issuable_escalation_statuses/after_update_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/after_update_service.rb
@@ -3,12 +3,12 @@
module IncidentManagement
module IssuableEscalationStatuses
class AfterUpdateService < ::BaseProjectService
- def initialize(issuable, current_user)
+ def initialize(issuable, current_user, **params)
@issuable = issuable
@escalation_status = issuable.escalation_status
@alert = issuable.alert_management_alert
- super(project: issuable.project, current_user: current_user)
+ super(project: issuable.project, current_user: current_user, params: params)
end
def execute
@@ -22,19 +22,27 @@ module IncidentManagement
attr_reader :issuable, :escalation_status, :alert
def after_update
- sync_to_alert
+ sync_status_to_alert
+ add_status_system_note
end
- def sync_to_alert
+ def sync_status_to_alert
return unless alert
return if alert.status == escalation_status.status
::AlertManagement::Alerts::UpdateService.new(
alert,
current_user,
- status: escalation_status.status_name
+ status: escalation_status.status_name,
+ status_change_reason: " by changing the incident status of #{issuable.to_reference(project)}"
).execute
end
+
+ def add_status_system_note
+ return unless escalation_status.status_previously_changed?
+
+ SystemNoteService.change_incident_status(issuable, current_user, params[:status_change_reason])
+ end
end
end
end
diff --git a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
index 1a660e1a163..8f591b375ee 100644
--- a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
@@ -2,18 +2,16 @@
module IncidentManagement
module IssuableEscalationStatuses
- class PrepareUpdateService
+ class PrepareUpdateService < ::BaseProjectService
include Gitlab::Utils::StrongMemoize
- SUPPORTED_PARAMS = %i[status].freeze
-
- InvalidParamError = Class.new(StandardError)
+ SUPPORTED_PARAMS = %i[status status_change_reason].freeze
def initialize(issuable, current_user, params)
@issuable = issuable
- @current_user = current_user
- @params = params.dup || {}
- @project = issuable.project
+ @param_errors = []
+
+ super(project: issuable.project, current_user: current_user, params: Hash(params))
end
def execute
@@ -23,19 +21,18 @@ module IncidentManagement
filter_attributes
filter_redundant_params
+ return invalid_param_error if param_errors.any?
+
ServiceResponse.success(payload: { escalation_status: params })
- rescue InvalidParamError
- invalid_param_error
end
private
- attr_reader :issuable, :current_user, :params, :project
+ attr_reader :issuable, :param_errors
def available?
- Feature.enabled?(:incident_escalations, project) &&
+ issuable.supports_escalation? &&
user_has_permissions? &&
- issuable.supports_escalation? &&
escalation_status.present?
end
@@ -66,7 +63,7 @@ module IncidentManagement
return unless status
status_event = escalation_status.status_event_for(status)
- raise InvalidParamError unless status_event
+ add_param_error(:status) && return unless status_event
params[:status_event] = status_event
end
@@ -85,12 +82,16 @@ module IncidentManagement
end
end
+ def add_param_error(param)
+ param_errors << param
+ end
+
def availability_error
ServiceResponse.error(message: 'Escalation status updates are not available for this issue, user, or project.')
end
def invalid_param_error
- ServiceResponse.error(message: 'Invalid value was provided for a parameter.')
+ ServiceResponse.error(message: "Invalid value was provided for parameters: #{param_errors.join(', ')}")
end
end
end
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index 38050708fc5..9ee54c7ba0f 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -71,7 +71,7 @@ module Issuable
def create_title_change_note(old_title)
create_draft_note(old_title)
- if issuable.wipless_title_changed(old_title)
+ if issuable.draftless_title_changed(old_title)
SystemNoteService.change_title(issuable, issuable.project, current_user, old_title)
end
end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index ecf10cf97a8..95093b88155 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -162,6 +162,8 @@ class IssuableBaseService < ::BaseProjectService
return unless result.success? && result.payload.present?
+ @escalation_status_change_reason = result[:escalation_status].delete(:status_change_reason)
+
params[:incident_management_issuable_escalation_status_attributes] = result[:escalation_status]
end
@@ -492,11 +494,12 @@ class IssuableBaseService < ::BaseProjectService
def handle_move_between_ids(issuable_position)
return unless params[:move_between_ids]
- after_id, before_id = params.delete(:move_between_ids)
- positioning_scope_id = params.delete(positioning_scope_key)
+ before_id, after_id = params.delete(:move_between_ids)
+
+ positioning_scope = issuable_position.class.relative_positioning_query_base(issuable_position)
- issuable_before = issuable_for_positioning(before_id, positioning_scope_id)
- issuable_after = issuable_for_positioning(after_id, positioning_scope_id)
+ issuable_before = issuable_for_positioning(before_id, positioning_scope)
+ issuable_after = issuable_for_positioning(after_id, positioning_scope)
raise ActiveRecord::RecordNotFound unless issuable_before || issuable_after
@@ -521,7 +524,7 @@ class IssuableBaseService < ::BaseProjectService
def invalidate_cache_counts(issuable, users: [])
users.each do |user|
- user.public_send("invalidate_#{issuable.model_name.singular}_cache_counts") # rubocop:disable GitlabSecurity/PublicSend
+ user.public_send("invalidate_#{issuable.noteable_target_type_name}_cache_counts") # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 37d667d4be8..61a95e49228 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -2,6 +2,7 @@
module Issues
class BaseService < ::IssuableBaseService
+ extend ::Gitlab::Utils::Override
include IncidentManagement::UsageData
include IssueTypeHelpers
@@ -61,6 +62,21 @@ module Issues
issue.system_note_timestamp = params[:created_at] || params[:updated_at]
end
+ override :handle_move_between_ids
+ def handle_move_between_ids(issue)
+ issue.check_repositioning_allowed! if params[:move_between_ids]
+
+ super
+
+ rebalance_if_needed(issue)
+ end
+
+ def issuable_for_positioning(id, positioning_scope)
+ return unless id
+
+ positioning_scope.find(id)
+ end
+
def create_assignee_note(issue, old_assignees)
SystemNoteService.change_issuable_assignees(
issue, issue.project, current_user, old_assignees)
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index 65f143d0b21..ff45091c7e6 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -81,7 +81,7 @@ module Issues
return if alert.resolved?
if alert.resolve
- SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project, author: current_user).closed_alert_issue(issue)
+ SystemNoteService.change_alert_status(alert, current_user, " by closing incident #{issue.to_reference(project)}")
else
Gitlab::AppLogger.warn(
message: 'Cannot resolve an associated Alert Management alert',
@@ -97,7 +97,7 @@ module Issues
status = issue.incident_management_issuable_escalation_status || issue.build_incident_management_issuable_escalation_status
- SystemNoteService.resolve_incident_status(issue, current_user) if status.resolve
+ SystemNoteService.change_incident_status(issue, current_user, ' by closing the incident') if status.resolve
end
def store_first_mentioned_in_commit_at(issue, merge_request, max_commit_lookup: 100)
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index e29bcf4a453..7fbf7c6af58 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -21,6 +21,8 @@ module Issues
def execute(skip_system_notes: false)
@issue = @build_service.execute
+ handle_move_between_ids(@issue)
+
filter_resolve_discussion_params
create(@issue, skip_system_notes: skip_system_notes)
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index 4418b4eb2bf..e210e6a2362 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -2,6 +2,8 @@
module Issues
class MoveService < Issuable::Clone::BaseService
+ extend ::Gitlab::Utils::Override
+
MoveError = Class.new(StandardError)
def execute(issue, target_project)
@@ -47,6 +49,7 @@ module Issues
.sent_notifications.update_all(project_id: new_entity.project_id, noteable_id: new_entity.id)
end
+ override :update_old_entity
def update_old_entity
super
@@ -54,6 +57,13 @@ module Issues
mark_as_moved
end
+ override :update_new_entity
+ def update_new_entity
+ super
+
+ copy_contacts
+ end
+
def create_new_entity
new_params = {
id: nil,
@@ -99,6 +109,13 @@ module Issues
target_issue_links.update_all(target_id: new_entity.id)
end
+ def copy_contacts
+ return unless Feature.enabled?(:customer_relations, original_entity.project.root_ancestor)
+ return unless original_entity.project.root_ancestor == new_entity.project.root_ancestor
+
+ new_entity.customer_relations_contacts = original_entity.customer_relations_contacts
+ end
+
def notify_participants
notification_service.async.issue_moved(original_entity, new_entity, @current_user)
end
diff --git a/app/services/issues/reorder_service.rb b/app/services/issues/reorder_service.rb
index 9c5fbec7d8e..5443d41ac30 100644
--- a/app/services/issues/reorder_service.rb
+++ b/app/services/issues/reorder_service.rb
@@ -2,47 +2,31 @@
module Issues
class ReorderService < Issues::BaseService
+ include Gitlab::Utils::StrongMemoize
+
def execute(issue)
return false unless can?(current_user, :update_issue, issue)
- return false if group && !can?(current_user, :read_group, group)
-
- attrs = issue_params(group)
- return false if attrs.empty?
+ return false unless move_between_ids
- update(issue, attrs)
+ update(issue, { move_between_ids: move_between_ids })
end
private
- def group
- return unless params[:group_full_path]
-
- @group ||= Group.find_by_full_path(params[:group_full_path])
- end
-
def update(issue, attrs)
::Issues::UpdateService.new(project: project, current_user: current_user, params: attrs).execute(issue)
rescue ActiveRecord::RecordNotFound
false
end
- def issue_params(group)
- attrs = {}
-
- if move_between_ids
- attrs[:move_between_ids] = move_between_ids
- attrs[:board_group_id] = group&.id
- end
-
- attrs
- end
-
def move_between_ids
- ids = [params[:move_after_id], params[:move_before_id]]
- .map(&:to_i)
- .map { |m| m > 0 ? m : nil }
+ strong_memoize(:move_between_ids) do
+ ids = [params[:move_before_id], params[:move_after_id]]
+ .map(&:to_i)
+ .map { |m| m > 0 ? m : nil }
- ids.any? ? ids : nil
+ ids.any? ? ids : nil
+ end
end
end
end
diff --git a/app/services/issues/set_crm_contacts_service.rb b/app/services/issues/set_crm_contacts_service.rb
index 947d46f0809..2edc944435b 100644
--- a/app/services/issues/set_crm_contacts_service.rb
+++ b/app/services/issues/set_crm_contacts_service.rb
@@ -16,6 +16,9 @@ module Issues
determine_changes if params[:replace_ids].present?
return error_too_many if too_many?
+ @added_count = 0
+ @removed_count = 0
+
add if params[:add_ids].present?
remove if params[:remove_ids].present?
@@ -25,6 +28,7 @@ module Issues
if issue.valid?
GraphqlTriggers.issue_crm_contacts_updated(issue)
issue.touch
+ create_system_note
ServiceResponse.success(payload: issue)
else
# The default error isn't very helpful: "Issue customer relations contacts is invalid"
@@ -36,7 +40,7 @@ module Issues
private
- attr_accessor :issue, :errors, :existing_ids
+ attr_accessor :issue, :errors, :existing_ids, :added_count, :removed_count
def determine_changes
params[:add_ids] = params[:replace_ids] - existing_ids
@@ -48,16 +52,24 @@ module Issues
end
def add_by_email
- contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group, params[:add_emails])
+ contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group, emails(:add_emails))
add_by_id(contact_ids)
end
+ def emails(key)
+ params[key].map do |email|
+ extract_email_from_request_param(email)
+ end
+ end
+
def add_by_id(contact_ids)
contact_ids -= existing_ids
contact_ids.uniq.each do |contact_id|
issue_contact = issue.issue_customer_relations_contacts.create(contact_id: contact_id)
- unless issue_contact.persisted?
+ if issue_contact.persisted?
+ @added_count += 1
+ else
# The validation ensures that the id exists and the user has permission
errors << "#{contact_id}: The resource that you are attempting to access does not exist or you don't have permission to perform this action"
end
@@ -69,17 +81,24 @@ module Issues
end
def remove_by_email
- contact_ids = ::CustomerRelations::IssueContact.find_contact_ids_by_emails(issue.id, params[:remove_emails])
+ contact_ids = ::CustomerRelations::IssueContact.find_contact_ids_by_emails(issue.id, emails(:remove_emails))
remove_by_id(contact_ids)
end
def remove_by_id(contact_ids)
contact_ids &= existing_ids
- issue.issue_customer_relations_contacts
+ @removed_count += issue.issue_customer_relations_contacts
.where(contact_id: contact_ids) # rubocop: disable CodeReuse/ActiveRecord
.delete_all
end
+ def extract_email_from_request_param(email_param)
+ email_param.delete_prefix(::CustomerRelations::Contact.reference_prefix_quoted)
+ .delete_prefix(::CustomerRelations::Contact.reference_prefix)
+ .delete_suffix(::CustomerRelations::Contact.reference_postfix)
+ .tr('"', '')
+ end
+
def allowed?
current_user&.can?(:set_issue_crm_contacts, issue)
end
@@ -116,6 +135,11 @@ module Issues
params[:add_emails] && params[:add_emails].length > MAX_ADDITIONAL_CONTACTS
end
+ def create_system_note
+ SystemNoteService.change_issuable_contacts(
+ issue, issue.project, current_user, added_count, removed_count)
+ end
+
def error_no_permissions
ServiceResponse.error(message: _('You have insufficient permissions to set customer relations contacts for this issue'))
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index aecb22453b7..8372cd919e5 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -2,8 +2,6 @@
module Issues
class UpdateService < Issues::BaseService
- extend ::Gitlab::Utils::Override
-
# NOTE: For Issues::UpdateService, we default the spam_params to nil, because spam_checking is not
# necessary in many cases, and we don't want to require every caller to explicitly pass it as nil
# to disable spam checking.
@@ -92,18 +90,6 @@ module Issues
todo_service.update_issue(issuable, current_user)
end
- def handle_move_between_ids(issue)
- issue.check_repositioning_allowed! if params[:move_between_ids]
-
- super
-
- rebalance_if_needed(issue)
- end
-
- def positioning_scope_key
- :board_group_id
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def change_issue_duplicate(issue)
canonical_issue_id = params.delete(:canonical_issue_id)
@@ -214,23 +200,12 @@ module Issues
return unless old_escalation_status.present?
return if issue.escalation_status&.slice(:status, :policy_id) == old_escalation_status
- ::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(issue, current_user).execute
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def issuable_for_positioning(id, board_group_id = nil)
- return unless id
-
- issue =
- if board_group_id
- IssuesFinder.new(current_user, group_id: board_group_id, include_subgroups: true).find_by(id: id)
- else
- project.issues.find(id)
- end
-
- issue if can?(current_user, :update_issue, issue)
+ ::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(
+ issue,
+ current_user,
+ status_change_reason: @escalation_status_change_reason # Defined in IssuableBaseService before save
+ ).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
def create_confidentiality_note(issue)
SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user)
diff --git a/app/services/loose_foreign_keys/batch_cleaner_service.rb b/app/services/loose_foreign_keys/batch_cleaner_service.rb
index de52cbba576..f3db2037911 100644
--- a/app/services/loose_foreign_keys/batch_cleaner_service.rb
+++ b/app/services/loose_foreign_keys/batch_cleaner_service.rb
@@ -2,6 +2,9 @@
module LooseForeignKeys
class BatchCleanerService
+ CLEANUP_ATTEMPTS_BEFORE_RESCHEDULE = 3
+ CONSUME_AFTER_RESCHEDULE = 5.minutes
+
def initialize(parent_table:, loose_foreign_key_definitions:, deleted_parent_records:, modification_tracker: LooseForeignKeys::ModificationTracker.new)
@parent_table = parent_table
@loose_foreign_key_definitions = loose_foreign_key_definitions
@@ -11,15 +14,31 @@ module LooseForeignKeys
:loose_foreign_key_processed_deleted_records,
'The number of processed loose foreign key deleted records'
)
+ @deleted_records_rescheduled_count = Gitlab::Metrics.counter(
+ :loose_foreign_key_rescheduled_deleted_records,
+ 'The number of rescheduled loose foreign key deleted records'
+ )
+ @deleted_records_incremented_count = Gitlab::Metrics.counter(
+ :loose_foreign_key_incremented_deleted_records,
+ 'The number of loose foreign key deleted records with incremented cleanup_attempts'
+ )
end
def execute
loose_foreign_key_definitions.each do |loose_foreign_key_definition|
run_cleaner_service(loose_foreign_key_definition, with_skip_locked: true)
- break if modification_tracker.over_limit?
+
+ if modification_tracker.over_limit?
+ handle_over_limit
+ break
+ end
run_cleaner_service(loose_foreign_key_definition, with_skip_locked: false)
- break if modification_tracker.over_limit?
+
+ if modification_tracker.over_limit?
+ handle_over_limit
+ break
+ end
end
return if modification_tracker.over_limit?
@@ -27,12 +46,33 @@ module LooseForeignKeys
# At this point, all associations are cleaned up, we can update the status of the parent records
update_count = LooseForeignKeys::DeletedRecord.mark_records_processed(deleted_parent_records)
- deleted_records_counter.increment({ table: parent_table, db_config_name: LooseForeignKeys::DeletedRecord.connection.pool.db_config.name }, update_count)
+ deleted_records_counter.increment({ table: parent_table, db_config_name: db_config_name }, update_count)
end
private
- attr_reader :parent_table, :loose_foreign_key_definitions, :deleted_parent_records, :modification_tracker, :deleted_records_counter
+ attr_reader :parent_table, :loose_foreign_key_definitions, :deleted_parent_records, :modification_tracker, :deleted_records_counter, :deleted_records_rescheduled_count, :deleted_records_incremented_count
+
+ def handle_over_limit
+ return if Feature.disabled?(:lfk_fair_queueing)
+
+ records_to_reschedule = []
+ records_to_increment = []
+
+ deleted_parent_records.each do |deleted_record|
+ if deleted_record.cleanup_attempts >= CLEANUP_ATTEMPTS_BEFORE_RESCHEDULE
+ records_to_reschedule << deleted_record
+ else
+ records_to_increment << deleted_record
+ end
+ end
+
+ reschedule_count = LooseForeignKeys::DeletedRecord.reschedule(records_to_reschedule, CONSUME_AFTER_RESCHEDULE.from_now)
+ deleted_records_rescheduled_count.increment({ table: parent_table, db_config_name: db_config_name }, reschedule_count)
+
+ increment_count = LooseForeignKeys::DeletedRecord.increment_attempts(records_to_increment)
+ deleted_records_incremented_count.increment({ table: parent_table, db_config_name: db_config_name }, increment_count)
+ end
def record_result(cleaner, result)
if cleaner.async_delete?
@@ -60,5 +100,9 @@ module LooseForeignKeys
end
end
end
+
+ def db_config_name
+ LooseForeignKeys::DeletedRecord.connection.pool.db_config.name
+ end
end
end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index acd00d0d1ec..dc29bb2c6da 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -24,6 +24,9 @@ module Members
add_members
enqueue_onboarding_progress_action
+
+ publish_event!
+
result
rescue BlankInvitesError, TooManyInvitesError, MembershipLockedError => e
error(e.message)
@@ -144,6 +147,15 @@ module Members
def formatted_errors
errors.to_sentence
end
+
+ def publish_event!
+ Gitlab::EventStore.publish(
+ Members::MembersAddedEvent.new(data: {
+ source_id: source.id,
+ source_type: source.class.name
+ })
+ )
+ end
end
end
diff --git a/app/services/members/creator_service.rb b/app/services/members/creator_service.rb
index e766a7e9044..fcce32ead94 100644
--- a/app/services/members/creator_service.rb
+++ b/app/services/members/creator_service.rb
@@ -67,6 +67,7 @@ module Members
def create_member_task
return unless member.persisted?
return if member_task_attributes.value?(nil)
+ return if member.member_task.present?
member.create_member_task(member_task_attributes)
end
diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb
index d2c83f82ff8..93a0d375b97 100644
--- a/app/services/merge_requests/after_create_service.rb
+++ b/app/services/merge_requests/after_create_service.rb
@@ -5,9 +5,8 @@ module MergeRequests
include Gitlab::Utils::StrongMemoize
def execute(merge_request)
- prepare_for_mergeability(merge_request) if early_prepare_for_mergeability?(merge_request)
+ prepare_for_mergeability(merge_request)
prepare_merge_request(merge_request)
- mark_as_unchecked(merge_request) unless early_prepare_for_mergeability?(merge_request)
end
private
@@ -15,7 +14,7 @@ module MergeRequests
def prepare_for_mergeability(merge_request)
create_pipeline_for(merge_request, current_user)
merge_request.update_head_pipeline
- mark_as_unchecked(merge_request)
+ check_mergeability(merge_request)
end
def prepare_merge_request(merge_request)
@@ -26,11 +25,6 @@ module MergeRequests
notification_service.new_merge_request(merge_request, current_user)
- unless early_prepare_for_mergeability?(merge_request)
- create_pipeline_for(merge_request, current_user)
- merge_request.update_head_pipeline
- end
-
merge_request.diffs(include_stats: false).write_cache
merge_request.create_cross_references!(current_user)
@@ -49,14 +43,13 @@ module MergeRequests
LinkLfsObjectsService.new(project: merge_request.target_project).execute(merge_request)
end
- def early_prepare_for_mergeability?(merge_request)
- strong_memoize("early_prepare_for_mergeability_#{merge_request.target_project_id}".to_sym) do
- Feature.enabled?(:early_prepare_for_mergeability, merge_request.target_project)
- end
- end
+ def check_mergeability(merge_request)
+ return unless merge_request.preparing?
- def mark_as_unchecked(merge_request)
- merge_request.mark_as_unchecked if merge_request.preparing?
+ # Need to set to unchecked to be able to check for mergeability or else
+ # it'll be a no-op.
+ merge_request.mark_as_unchecked
+ merge_request.check_mergeability(async: true)
end
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index b0d0c32abd1..3363fc90997 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -246,7 +246,9 @@ module MergeRequests
def remove_all_attention_requests(merge_request)
return unless merge_request.attention_requested_enabled?
- ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request).execute
+ users = merge_request.reviewers + merge_request.assignees
+
+ ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, users: users.uniq).execute
end
def remove_attention_requested(merge_request, user)
diff --git a/app/services/merge_requests/bulk_remove_attention_requested_service.rb b/app/services/merge_requests/bulk_remove_attention_requested_service.rb
index dd2ff741ba6..6573b623779 100644
--- a/app/services/merge_requests/bulk_remove_attention_requested_service.rb
+++ b/app/services/merge_requests/bulk_remove_attention_requested_service.rb
@@ -3,20 +3,24 @@
module MergeRequests
class BulkRemoveAttentionRequestedService < MergeRequests::BaseService
attr_accessor :merge_request
+ attr_accessor :users
- def initialize(project:, current_user:, merge_request:)
+ def initialize(project:, current_user:, merge_request:, users:)
super(project: project, current_user: current_user)
@merge_request = merge_request
+ @users = users
end
+ # rubocop: disable CodeReuse/ActiveRecord
def execute
return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
- merge_request.merge_request_assignees.update_all(state: :reviewed)
- merge_request.merge_request_reviewers.update_all(state: :reviewed)
+ merge_request.merge_request_assignees.where(user_id: users).update_all(state: :reviewed)
+ merge_request.merge_request_reviewers.where(user_id: users).update_all(state: :reviewed)
success
end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 3e294aeaa07..30531fcc17b 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -14,8 +14,8 @@ module MergeRequests
def async_execute
return service_error if service_error
- return unless merge_request.mark_as_checking
+ merge_request.mark_as_checking
MergeRequestMergeabilityCheckWorker.perform_async(merge_request.id)
end
diff --git a/app/services/merge_requests/rebase_service.rb b/app/services/merge_requests/rebase_service.rb
index d1f45b4b49c..1c4e1784b34 100644
--- a/app/services/merge_requests/rebase_service.rb
+++ b/app/services/merge_requests/rebase_service.rb
@@ -2,7 +2,7 @@
module MergeRequests
class RebaseService < MergeRequests::BaseService
- REBASE_ERROR = 'Rebase failed. Please rebase locally'
+ REBASE_ERROR = 'Rebase failed: Rebase locally, resolve all conflicts, then push the branch.'
attr_reader :merge_request, :rebase_error
@@ -35,7 +35,7 @@ module MergeRequests
def set_rebase_error(exception)
@rebase_error =
if exception.is_a?(Gitlab::Git::PreReceiveError)
- "Something went wrong during the rebase pre-receive hook: #{exception.message}."
+ "The rebase pre-receive hook failed: #{exception.message}."
else
REBASE_ERROR
end
diff --git a/app/services/merge_requests/squash_service.rb b/app/services/merge_requests/squash_service.rb
index 69b9740c2a5..f04682bf08a 100644
--- a/app/services/merge_requests/squash_service.rb
+++ b/app/services/merge_requests/squash_service.rb
@@ -9,9 +9,9 @@ module MergeRequests
return success(squash_sha: merge_request.diff_head_sha)
end
- return error(s_('MergeRequests|This project does not allow squashing commits when merge requests are accepted.')) if squash_forbidden?
+ return error(s_("MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging.")) if squash_forbidden?
- squash! || error(s_('MergeRequests|Failed to squash. Should be done manually.'))
+ squash! || error(s_('MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch.'))
end
private
diff --git a/app/services/packages/maven/metadata/sync_service.rb b/app/services/packages/maven/metadata/sync_service.rb
index 4f35db36fb0..dacf6750412 100644
--- a/app/services/packages/maven/metadata/sync_service.rb
+++ b/app/services/packages/maven/metadata/sync_service.rb
@@ -93,11 +93,7 @@ module Packages
def metadata_package_file_for(package)
return unless package
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
+ package_files = package.installable_package_files
package_files.with_file_name(Metadata.filename)
.recent
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index 55f16aa3e3d..e6b1b33a82a 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -33,6 +33,11 @@ module Projects
SnippetsFinder.new(current_user, project: project).execute.select([:id, :title])
end
+ def contacts
+ Crm::ContactsFinder.new(current_user, group: project.group).execute
+ .select([:id, :email, :first_name, :last_name])
+ end
+
def labels_as_hash(target)
super(target, project_id: project.id, include_ancestor_groups: true)
end
diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb
index 410cf6c624e..b4a57c70111 100644
--- a/app/services/projects/container_repository/delete_tags_service.rb
+++ b/app/services/projects/container_repository/delete_tags_service.rb
@@ -14,6 +14,7 @@ module Projects
@tag_names = params[:tags]
return error('not tags specified') if @tag_names.blank?
+ return error('repository importing') if @container_repository.migration_importing?
delete_tags
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 1d187b140ef..c885369dfec 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -89,7 +89,7 @@ module Projects
end
def after_create_actions
- log_info("#{@project.owner.name} created a new project \"#{@project.full_name}\"")
+ log_info("#{current_user.name} created a new project \"#{@project.full_name}\"")
if @project.import?
experiment(:combined_registration, user: current_user).track(:import_project)
@@ -167,7 +167,7 @@ module Projects
end
def readme_content
- @readme_template.presence || experiment(:new_project_readme_content, namespace: @project.namespace).run_with(@project)
+ @readme_template.presence || ReadmeRendererService.new(@project, current_user).execute
end
def skip_wiki?
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 5c4a0e947de..95af5a6863f 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -37,6 +37,8 @@ module Projects
system_hook_service.execute_hooks_for(project, :destroy)
log_info("Project \"#{project.full_path}\" was deleted")
+ publish_project_deleted_event_for(project) if Feature.enabled?(:publish_project_deleted_event, default_enabled: :yaml)
+
current_user.invalidate_personal_projects_count
true
@@ -139,6 +141,7 @@ module Projects
destroy_web_hooks!
destroy_project_bots!
destroy_ci_records!
+ destroy_mr_diff_commits!
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
@@ -154,6 +157,33 @@ module Projects
log_info("Attempting to destroy #{project.full_path} (#{project.id})")
end
+ # Projects will have at least one merge_request_diff_commit for every commit
+ # contained in every MR, which deleting via `project.destroy!` and
+ # cascading deletes may exceed statement timeouts, causing failures.
+ # (see https://gitlab.com/gitlab-org/gitlab/-/issues/346166)
+ #
+ # rubocop: disable CodeReuse/ActiveRecord
+ def destroy_mr_diff_commits!
+ mr_batch_size = 100
+ delete_batch_size = 1000
+
+ project.merge_requests.each_batch(column: :iid, of: mr_batch_size) do |relation_ids|
+ loop do
+ inner_query = MergeRequestDiffCommit
+ .select(:merge_request_diff_id, :relative_order)
+ .where(merge_request_diff_id: MergeRequestDiff.where(merge_request_id: relation_ids).select(:id))
+ .limit(delete_batch_size)
+
+ deleted_rows = MergeRequestDiffCommit
+ .where('(merge_request_diff_commits.merge_request_diff_id, merge_request_diff_commits.relative_order) IN (?)', inner_query)
+ .delete_all
+
+ break if deleted_rows == 0
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def destroy_ci_records!
project.all_pipelines.find_each(batch_size: BATCH_SIZE) do |pipeline| # rubocop: disable CodeReuse/ActiveRecord
# Destroy artifacts, then builds, then pipelines
@@ -232,6 +262,12 @@ module Projects
def flush_caches(project)
Projects::ForksCountService.new(project).delete_cache
end
+
+ def publish_project_deleted_event_for(project)
+ data = { project_id: project.id, namespace_id: project.namespace_id }
+ event = Projects::ProjectDeletedEvent.new(data: data)
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index b1a2182fbdc..b91b7f34d42 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -47,8 +47,7 @@ module Projects
end
def save_all!
- if save_exporters
- Gitlab::ImportExport::Saver.save(exportable: project, shared: shared)
+ if save_exporters && save_export_archive
notify_success
else
notify_error!
@@ -59,6 +58,10 @@ module Projects
exporters.all?(&:save)
end
+ def save_export_archive
+ Gitlab::ImportExport::Saver.save(exportable: project, shared: shared)
+ end
+
def exporters
[
version_saver, avatar_saver, project_tree_saver, uploads_saver,
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index fe9dce26029..9da72d9300e 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -34,7 +34,7 @@ module Projects
def wrap_download_errors(&block)
yield
rescue SizeError, OidError, ResponseError, StandardError => e
- error("LFS file with oid #{lfs_oid} could't be downloaded from #{lfs_sanitized_url}: #{e.message}")
+ error("LFS file with oid #{lfs_oid} couldn't be downloaded from #{lfs_sanitized_url}: #{e.message}")
end
def download_lfs_file!
@@ -104,7 +104,7 @@ module Projects
rescue StandardError => e
# If the lfs file is successfully downloaded it will be removed
# when it is added to the project's lfs files.
- # Nevertheless if any excetion raises the file would remain
+ # Nevertheless if any exception raises the file would remain
# in the file system. Here we ensure to remove it
File.unlink(file) if File.exist?(file)
diff --git a/app/services/projects/overwrite_project_service.rb b/app/services/projects/overwrite_project_service.rb
index c58fba33b2a..eea8f867b45 100644
--- a/app/services/projects/overwrite_project_service.rb
+++ b/app/services/projects/overwrite_project_service.rb
@@ -6,30 +6,34 @@ module Projects
return unless source_project && source_project.namespace_id == @project.namespace_id
start_time = ::Gitlab::Metrics::System.monotonic_time
+ original_source_name = source_project.name
+ original_source_path = source_project.path
+ tmp_source_name, tmp_source_path = tmp_source_project_name(source_project)
- Project.transaction do
- move_before_destroy_relationships(source_project)
- # Reset is required in order to get the proper
- # uncached fork network method calls value.
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/340256') do
- destroy_old_project(source_project.reset)
- end
- rename_project(source_project.name, source_project.path)
-
- @project
+ move_relationships_between(source_project, @project)
+
+ source_project_rename = rename_project(source_project, tmp_source_name, tmp_source_path)
+
+ if source_project_rename[:status] == :error
+ raise 'Source project rename failed during project overwrite'
end
- # Projects::DestroyService can raise Exceptions, but we don't want
- # to pass that kind of exception to the caller. Instead, we change it
- # for a StandardError exception
- rescue Exception => e # rubocop:disable Lint/RescueException
- attempt_restore_repositories(source_project)
-
- if e.instance_of?(Exception)
- raise StandardError, e.message
- else
- raise
+
+ new_project_rename = rename_project(@project, original_source_name, original_source_path)
+
+ if new_project_rename[:status] == :error
+ rename_project(source_project, original_source_name, original_source_path)
+
+ raise 'New project rename failed during project overwrite'
end
+ schedule_source_project_deletion(source_project)
+
+ @project
+ rescue StandardError => e
+ move_relationships_between(@project, source_project)
+ remove_source_project_from_fork_network(source_project)
+
+ raise e
ensure
track_service(start_time, source_project, e)
end
@@ -48,45 +52,63 @@ module Projects
error: exception.class.name)
end
- def move_before_destroy_relationships(source_project)
+ def move_relationships_between(source_project, target_project)
options = { remove_remaining_elements: false }
- ::Projects::MoveUsersStarProjectsService.new(@project, @current_user).execute(source_project, **options)
- ::Projects::MoveAccessService.new(@project, @current_user).execute(source_project, **options)
- ::Projects::MoveDeployKeysProjectsService.new(@project, @current_user).execute(source_project, **options)
- ::Projects::MoveNotificationSettingsService.new(@project, @current_user).execute(source_project, **options)
- ::Projects::MoveForksService.new(@project, @current_user).execute(source_project, **options)
- ::Projects::MoveLfsObjectsProjectsService.new(@project, @current_user).execute(source_project, **options)
- add_source_project_to_fork_network(source_project)
- end
-
- def destroy_old_project(source_project)
- # Delete previous project (synchronously) and unlink relations
- ::Projects::DestroyService.new(source_project, @current_user).execute
+ Project.transaction do
+ ::Projects::MoveUsersStarProjectsService.new(target_project, @current_user).execute(source_project, **options)
+ ::Projects::MoveAccessService.new(target_project, @current_user).execute(source_project, **options)
+ ::Projects::MoveDeployKeysProjectsService.new(target_project, @current_user).execute(source_project, **options)
+ ::Projects::MoveNotificationSettingsService.new(target_project, @current_user).execute(source_project, **options)
+ ::Projects::MoveForksService.new(target_project, @current_user).execute(source_project, **options)
+ ::Projects::MoveLfsObjectsProjectsService.new(target_project, @current_user).execute(source_project, **options)
+
+ add_source_project_to_fork_network(source_project)
+ end
end
- def rename_project(name, path)
- # Update de project's name and path to the original name/path
- ::Projects::UpdateService.new(@project,
- @current_user,
- { name: name, path: path })
- .execute
+ def schedule_source_project_deletion(source_project)
+ ::Projects::DestroyService.new(source_project, @current_user).async_execute
end
- def attempt_restore_repositories(project)
- ::Projects::DestroyRollbackService.new(project, @current_user).execute
+ def rename_project(target_project, name, path)
+ ::Projects::UpdateService.new(target_project, @current_user, { name: name, path: path }).execute
end
def add_source_project_to_fork_network(source_project)
- return unless @project.fork_network
+ return if source_project == @project
+ return unless fork_network
# Because they have moved all references in the fork network from the source_project
# we won't be able to query the database (only through its cached data),
# for its former relationships. That's why we're adding it to the network
# as a fork of the target project
- ForkNetworkMember.create!(fork_network: @project.fork_network,
+ ForkNetworkMember.create!(fork_network: fork_network,
project: source_project,
forked_from_project: @project)
end
+
+ def remove_source_project_from_fork_network(source_project)
+ return unless fork_network
+
+ fork_member = ForkNetworkMember.find_by( # rubocop: disable CodeReuse/ActiveRecord
+ fork_network: fork_network,
+ project: source_project,
+ forked_from_project: @project)
+
+ fork_member&.destroy
+ end
+
+ def tmp_source_project_name(source_project)
+ random_string = SecureRandom.hex
+ tmp_name = "#{source_project.name}-old-#{random_string}"
+ tmp_path = "#{source_project.path}-old-#{random_string}"
+
+ [tmp_name, tmp_path]
+ end
+
+ def fork_network
+ @project.fork_network_member&.fork_network
+ end
end
end
diff --git a/app/services/projects/readme_renderer_service.rb b/app/services/projects/readme_renderer_service.rb
new file mode 100644
index 00000000000..6871976aded
--- /dev/null
+++ b/app/services/projects/readme_renderer_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Projects
+ class ReadmeRendererService < BaseService
+ include Rails.application.routes.url_helpers
+
+ TEMPLATE_PATH = Rails.root.join('app', 'views', 'projects', 'readme_templates')
+
+ def execute
+ render(params[:template_name] || :default)
+ end
+
+ private
+
+ def render(template_name)
+ ERB.new(File.read(sanitized_filename(template_name)), trim_mode: '<>').result(binding)
+ end
+
+ def sanitized_filename(template_name)
+ path = Gitlab::Utils.check_path_traversal!("#{template_name}.md.tt")
+ path = TEMPLATE_PATH.join(path).to_s
+ Gitlab::Utils.check_allowed_absolute_path!(path, [TEMPLATE_PATH.to_s])
+
+ path
+ end
+ end
+end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 17da77fe950..51c0989ee55 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -2,11 +2,11 @@
# Projects::TransferService class
#
-# Used for transfer project to another namespace
+# Used to transfer a project to another namespace
#
# Ex.
-# # Move projects to namespace with ID 17 by user
-# Projects::TransferService.new(project, user, namespace_id: 17).execute
+# # Move project to namespace by user
+# Projects::TransferService.new(project, user).execute(namespace)
#
module Projects
class TransferService < BaseService
@@ -103,6 +103,8 @@ module Projects
update_repository_configuration(@new_path)
+ remove_issue_contacts
+
execute_system_hooks
end
@@ -254,6 +256,12 @@ module Projects
namespace_traversal_ids: new_namespace.traversal_ids
}
end
+
+ def remove_issue_contacts
+ return unless @old_group&.root_ancestor != @new_namespace&.root_ancestor
+
+ CustomerRelations::IssueContact.delete_for_project(project.id)
+ end
end
end
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index ab489ba49ca..906c4b98f56 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -61,28 +61,32 @@ module QuickActions
private
+ def failed_parse(message)
+ raise Gitlab::QuickActions::CommandDefinition::ParseError, message
+ end
+
def extractor
Gitlab::QuickActions::Extractor.new(self.class.command_definitions)
end
- # rubocop: disable CodeReuse/ActiveRecord
def extract_users(params)
- return [] if params.nil?
+ return [] if params.blank?
- users = extract_references(params, :user)
+ # We are using the a simple User.by_username query here rather than a ReferenceExtractor
+ # because the needs here are much simpler: we only deal in usernames, and
+ # want to also handle bare usernames. The ReferenceExtractor also has
+ # different behaviour, and will return all group members for groups named
+ # using a user-style reference, which is not in scope here.
+ args = params.split(/\s|,/).select(&:present?).uniq - ['and']
+ usernames = (args - ['me']).map { _1.delete_prefix('@') }
+ found = User.by_username(usernames).to_a.select { can?(:read_user_profile, _1) }
+ found_names = found.map(&:username).to_set
+ missing = args.reject { |arg| arg == 'me' || found_names.include?(arg.delete_prefix('@')) }.map { "'#{_1}'" }
- if users.empty?
- users =
- if params.strip == 'me'
- [current_user]
- else
- User.where(username: params.split(' ').map(&:strip))
- end
- end
+ failed_parse(format(_("Failed to find users for %{missing}"), missing: missing.to_sentence)) if missing.present?
- users
+ found + [current_user].select { args.include?('me') }
end
- # rubocop: enable CodeReuse/ActiveRecord
def find_milestones(project, params = {})
group_ids = project.group.self_and_ancestors.select(:id) if project.group
@@ -187,6 +191,10 @@ module QuickActions
user: current_user
)
end
+
+ def can?(ability, object)
+ Ability.allowed?(current_user, ability, object)
+ end
end
end
diff --git a/app/services/resource_events/change_state_service.rb b/app/services/resource_events/change_state_service.rb
index d68b86a1513..a396f7a1907 100644
--- a/app/services/resource_events/change_state_service.rb
+++ b/app/services/resource_events/change_state_service.rb
@@ -14,7 +14,7 @@ module ResourceEvents
ResourceStateEvent.create(
user: user,
- resource.class.underscore => resource,
+ resource.noteable_target_type_name => resource,
source_commit: commit_id_of(mentionable_source),
source_merge_request_id: merge_request_id_of(mentionable_source),
state: ResourceStateEvent.states[state],
diff --git a/app/services/security/ci_configuration/container_scanning_create_service.rb b/app/services/security/ci_configuration/container_scanning_create_service.rb
new file mode 100644
index 00000000000..788533575e6
--- /dev/null
+++ b/app/services/security/ci_configuration/container_scanning_create_service.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class ContainerScanningCreateService < ::Security::CiConfiguration::BaseCreateService
+ private
+
+ def action
+ Security::CiConfiguration::ContainerScanningBuildAction.new(project.auto_devops_enabled?, existing_gitlab_ci_content).generate
+ end
+
+ def next_branch
+ 'set-container-scanning-config'
+ end
+
+ def message
+ _('Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist')
+ end
+
+ def description
+ _('Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings.')
+ end
+ end
+ end
+end
diff --git a/app/services/service_ping/build_payload_service.rb b/app/services/service_ping/build_payload_service.rb
index 2bef3d32103..f4ae939fd07 100644
--- a/app/services/service_ping/build_payload_service.rb
+++ b/app/services/service_ping/build_payload_service.rb
@@ -19,7 +19,7 @@ module ServicePing
end
def raw_payload
- @raw_payload ||= ::Gitlab::UsageData.data(force_refresh: true)
+ @raw_payload ||= ::Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)
end
end
end
diff --git a/app/services/service_ping/submit_service.rb b/app/services/service_ping/submit_service.rb
index d3d9dcecb2b..c8733bc2f11 100644
--- a/app/services/service_ping/submit_service.rb
+++ b/app/services/service_ping/submit_service.rb
@@ -5,6 +5,7 @@ module ServicePing
PRODUCTION_BASE_URL = 'https://version.gitlab.com'
STAGING_BASE_URL = 'https://gitlab-services-version-gitlab-com-staging.gs-staging.gitlab.org'
USAGE_DATA_PATH = 'usage_data'
+ ERROR_PATH = 'usage_ping_errors'
SubmissionError = Class.new(StandardError)
@@ -15,13 +16,24 @@ module ServicePing
def execute
return unless ServicePing::ServicePingSettings.product_intelligence_enabled?
+ start = Time.current
begin
usage_data = BuildPayloadService.new.execute
response = submit_usage_data_payload(usage_data)
- rescue StandardError
+ rescue StandardError => e
return unless Gitlab::CurrentSettings.usage_ping_enabled?
- usage_data = Gitlab::UsageData.data(force_refresh: true)
+ error_payload = {
+ time: Time.current,
+ uuid: Gitlab::UsageData.add_metric('UuidMetric'),
+ hostname: Gitlab::UsageData.add_metric('HostnameMetric'),
+ version: Gitlab::UsageData.alt_usage_data { Gitlab::VERSION },
+ message: e.message,
+ elapsed: (Time.current - start).round(1)
+ }
+ submit_payload({ error: error_payload }, url: error_url)
+
+ usage_data = Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)
response = submit_usage_data_payload(usage_data)
end
@@ -42,12 +54,16 @@ module ServicePing
URI.join(base_url, USAGE_DATA_PATH)
end
+ def error_url
+ URI.join(base_url, ERROR_PATH)
+ end
+
private
- def submit_payload(usage_data)
+ def submit_payload(payload, url: self.url)
Gitlab::HTTP.post(
url,
- body: usage_data.to_json,
+ body: payload.to_json,
allow_local_requests: true,
headers: { 'Content-type' => 'application/json' }
)
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 0d13c73d49d..1f1edad7a69 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -45,6 +45,10 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).change_issuable_reviewers(old_reviewers)
end
+ def change_issuable_contacts(issuable, project, author, added_count, removed_count)
+ ::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).change_issuable_contacts(added_count, removed_count)
+ end
+
def relate_issue(noteable, noteable_ref, user)
::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).relate_issue(noteable_ref)
end
@@ -319,8 +323,8 @@ module SystemNoteService
merge_requests_service(noteable, noteable.project, user).unapprove_mr
end
- def change_alert_status(alert, author)
- ::SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project, author: author).change_alert_status(alert)
+ def change_alert_status(alert, author, reason = nil)
+ ::SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project, author: author).change_alert_status(reason)
end
def new_alert_issue(alert, issue, author)
@@ -335,8 +339,8 @@ module SystemNoteService
::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).change_incident_severity
end
- def resolve_incident_status(incident, author)
- ::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).resolve_incident_status
+ def change_incident_status(incident, author, reason = nil)
+ ::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).change_incident_status(reason)
end
def log_resolving_alert(alert, monitoring_tool)
diff --git a/app/services/system_notes/alert_management_service.rb b/app/services/system_notes/alert_management_service.rb
index 70cdd5c6434..994e3174668 100644
--- a/app/services/system_notes/alert_management_service.rb
+++ b/app/services/system_notes/alert_management_service.rb
@@ -24,11 +24,12 @@ module SystemNotes
# Example Note text:
#
# "changed the status to Acknowledged"
+ # "changed the status to Acknowledged by changing the incident status of #540"
#
# Returns the created Note object
- def change_alert_status(alert)
- status = alert.state.to_s.titleize
- body = "changed the status to **#{status}**"
+ def change_alert_status(reason)
+ status = noteable.state.to_s.titleize
+ body = "changed the status to **#{status}**#{reason}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
end
@@ -39,30 +40,15 @@ module SystemNotes
#
# Example Note text:
#
- # "created issue #17 for this alert"
+ # "created incident #17 for this alert"
#
# Returns the created Note object
def new_alert_issue(issue)
- body = "created issue #{issue.to_reference(project)} for this alert"
+ body = "created incident #{issue.to_reference(project)} for this alert"
create_note(NoteSummary.new(noteable, project, author, body, action: 'alert_issue_added'))
end
- # Called when an AlertManagement::Alert is resolved due to the associated issue being closed
- #
- # issue - Issue object.
- #
- # Example Note text:
- #
- # "changed the status to Resolved by closing issue #17"
- #
- # Returns the created Note object
- def closed_alert_issue(issue)
- body = "changed the status to **Resolved** by closing issue #{issue.to_reference(project)}"
-
- create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
- end
-
# Called when an alert is resolved due to received resolving alert payload
#
# alert - AlertManagement::Alert object.
diff --git a/app/services/system_notes/incident_service.rb b/app/services/system_notes/incident_service.rb
index 785291e0637..f3f9dfbec96 100644
--- a/app/services/system_notes/incident_service.rb
+++ b/app/services/system_notes/incident_service.rb
@@ -26,8 +26,19 @@ module SystemNotes
end
end
- def resolve_incident_status
- body = 'changed the status to **Resolved** by closing the incident'
+ # Called when the status of an IncidentManagement::IssuableEscalationStatus has changed
+ #
+ # reason - String.
+ #
+ # Example Note text:
+ #
+ # "changed the incident status to Acknowledged"
+ # "changed the incident status to Acknowledged by changing the status of ^alert#540"
+ #
+ # Returns the created Note object
+ def change_incident_status(reason)
+ status = noteable.escalation_status.status_name.to_s.titleize
+ body = "changed the incident status to **#{status}**#{reason}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
end
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index d33dcd65589..09f36bb6501 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -111,6 +111,35 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'reviewer'))
end
+ # Called when the contacts of an issuable are changed or removed
+ # We intend to reference the contacts but for security we are just
+ # going to state how many were added/removed for now. See discussion:
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77816#note_806114273
+ #
+ # added_count - number of contacts added, or 0
+ # removed_count - number of contacts removed, or 0
+ #
+ # Example Note text:
+ #
+ # "added 2 contacts"
+ #
+ # "added 3 contacts and removed one contact"
+ #
+ # Returns the created Note object
+ def change_issuable_contacts(added_count, removed_count)
+ text_parts = []
+
+ Gitlab::I18n.with_default_locale do
+ text_parts << "added #{added_count} #{'contact'.pluralize(added_count)}" if added_count > 0
+ text_parts << "removed #{removed_count} #{'contact'.pluralize(removed_count)}" if removed_count > 0
+ end
+
+ return if text_parts.empty?
+
+ body = text_parts.join(' and ')
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'contact'))
+ end
+
# Called when the title of a Noteable is changed
#
# old_title - Previous String title
diff --git a/app/services/task_list_toggle_service.rb b/app/services/task_list_toggle_service.rb
index 32cfa198ce8..082fa1447fc 100644
--- a/app/services/task_list_toggle_service.rb
+++ b/app/services/task_list_toggle_service.rb
@@ -38,7 +38,7 @@ class TaskListToggleService
return unless markdown_task.chomp == line_source
return unless source_checkbox = Taskable::ITEM_PATTERN.match(markdown_task)
- currently_checked = TaskList::Item.new(source_checkbox[1]).complete?
+ currently_checked = TaskList::Item.new(source_checkbox[2]).complete?
# Check `toggle_as_checked` to make sure we don't accidentally replace
# any `[ ]` or `[x]` in the middle of the text
diff --git a/app/services/test_hooks/base_service.rb b/app/services/test_hooks/base_service.rb
index 0fda6fb1ed0..b41a9959c13 100644
--- a/app/services/test_hooks/base_service.rb
+++ b/app/services/test_hooks/base_service.rb
@@ -18,7 +18,7 @@ module TestHooks
return error('Testing not available for this hook') if trigger_key.nil? || data.blank?
return error(data[:error]) if data[:error].present?
- hook.execute(data, trigger_key)
+ hook.execute(data, trigger_key, force: true)
end
end
end
diff --git a/app/services/update_container_registry_info_service.rb b/app/services/update_container_registry_info_service.rb
index 531335839a9..7d79b257687 100644
--- a/app/services/update_container_registry_info_service.rb
+++ b/app/services/update_container_registry_info_service.rb
@@ -15,6 +15,12 @@ class UpdateContainerRegistryInfoService
client = ContainerRegistry::Client.new(registry_config.api_url, token: token)
info = client.registry_info
+ gitlab_api_client = ContainerRegistry::GitlabApiClient.new(registry_config.api_url, token: token)
+ if gitlab_api_client.supports_gitlab_api?
+ info[:features] ||= []
+ info[:features] << ContainerRegistry::GitlabApiClient::REGISTRY_GITLAB_V1_API_FEATURE
+ end
+
Gitlab::CurrentSettings.update!(
container_registry_vendor: info[:vendor] || '',
container_registry_version: info[:version] || '',
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index 1634cc017ae..4ec875098fa 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -65,10 +65,7 @@ module Users
user.destroy_dependent_associations_in_batches(exclude: [:snippets])
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
- user_data = nil
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/340260') do
- user_data = user.destroy
- end
+ user_data = user.destroy
namespace.destroy
user_data
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 33e34ec41e2..b1d8872aa5e 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -34,11 +34,12 @@ class WebHookService
hook_name.to_s.singularize.titleize
end
- def initialize(hook, data, hook_name, uniqueness_token = nil)
+ def initialize(hook, data, hook_name, uniqueness_token = nil, force: false)
@hook = hook
@data = data
@hook_name = hook_name.to_s
@uniqueness_token = uniqueness_token
+ @force = force
@request_options = {
timeout: Gitlab.config.gitlab.webhook_timeout,
use_read_total_timeout: true,
@@ -46,10 +47,17 @@ class WebHookService
}
end
+ def disabled?
+ !@force && !hook.executable?
+ end
+
def execute
- return { status: :error, message: 'Hook disabled' } unless hook.executable?
+ return { status: :error, message: 'Hook disabled' } if disabled?
- log_recursion_limit if recursion_blocked?
+ if recursion_blocked?
+ log_recursion_blocked
+ return { status: :error, message: 'Recursive webhook blocked' }
+ end
Gitlab::WebHooks::RecursionDetection.register!(hook)
@@ -96,13 +104,14 @@ class WebHookService
def async_execute
Gitlab::ApplicationContext.with_context(hook.application_context) do
- break log_rate_limit if rate_limited?
+ break log_rate_limited if rate_limited?
+ break log_recursion_blocked if recursion_blocked?
- log_recursion_limit if recursion_blocked?
+ params = {
+ recursion_detection_request_uuid: Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid
+ }.compact
- data[:_gitlab_recursion_detection_request_uuid] = Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid
-
- WebHookWorker.perform_async(hook.id, data, hook_name)
+ WebHookWorker.perform_async(hook.id, data, hook_name, params)
end
end
@@ -144,8 +153,12 @@ class WebHookService
internal_error_message: error_message
}
- ::WebHooks::LogExecutionWorker
- .perform_async(hook.id, log_data, category, uniqueness_token)
+ if @force # executed as part of test - run log-execution inline.
+ ::WebHooks::LogExecutionService.new(hook: hook, log_data: log_data, response_category: category).execute
+ else
+ ::WebHooks::LogExecutionWorker
+ .perform_async(hook.id, log_data, category, uniqueness_token)
+ end
end
def response_category(response)
@@ -202,7 +215,7 @@ class WebHookService
@rate_limit ||= hook.rate_limit
end
- def log_rate_limit
+ def log_rate_limited
Gitlab::AuthLogger.error(
message: 'Webhook rate limit exceeded',
hook_id: hook.id,
@@ -212,9 +225,9 @@ class WebHookService
)
end
- def log_recursion_limit
+ def log_recursion_blocked
Gitlab::AuthLogger.error(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: hook.id,
hook_type: hook.type,
hook_name: hook_name,
diff --git a/app/services/work_items/create_service.rb b/app/services/work_items/create_service.rb
index 49f7b89158b..705735fe403 100644
--- a/app/services/work_items/create_service.rb
+++ b/app/services/work_items/create_service.rb
@@ -2,6 +2,8 @@
module WorkItems
class CreateService
+ include ::Services::ReturnServiceResponses
+
def initialize(project:, current_user: nil, params: {}, spam_params:)
@create_service = ::Issues::CreateService.new(
project: project,
@@ -10,10 +12,28 @@ module WorkItems
spam_params: spam_params,
build_service: ::WorkItems::BuildService.new(project: project, current_user: current_user, params: params)
)
+ @current_user = current_user
+ @project = project
end
def execute
- @create_service.execute
+ unless @current_user.can?(:create_work_item, @project)
+ return error(_('Operation not allowed'), :forbidden)
+ end
+
+ work_item = @create_service.execute
+
+ if work_item.valid?
+ success(payload(work_item))
+ else
+ error(work_item.errors.full_messages, :unprocessable_entity, pass_back: payload(work_item))
+ end
+ end
+
+ private
+
+ def payload(work_item)
+ { work_item: work_item }
end
end
end
diff --git a/app/services/work_items/delete_service.rb b/app/services/work_items/delete_service.rb
new file mode 100644
index 00000000000..1093a403a1c
--- /dev/null
+++ b/app/services/work_items/delete_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class DeleteService < Issuable::DestroyService
+ def execute(work_item)
+ unless current_user.can?(:delete_work_item, work_item)
+ return ::ServiceResponse.error(message: 'User not authorized to delete work item')
+ end
+
+ if super
+ ::ServiceResponse.success
+ else
+ ::ServiceResponse.error(message: work_item.errors.full_messages)
+ end
+ end
+ end
+end
diff --git a/app/services/work_items/update_service.rb b/app/services/work_items/update_service.rb
new file mode 100644
index 00000000000..5c45f4d90e5
--- /dev/null
+++ b/app/services/work_items/update_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class UpdateService < ::Issues::UpdateService
+ private
+
+ def after_update(issuable)
+ super
+
+ GraphqlTriggers.issuable_title_updated(issuable) if issuable.previous_changes.key?(:title)
+ end
+ end
+end
diff --git a/app/uploaders/import_export_uploader.rb b/app/uploaders/import_export_uploader.rb
index 7b161d72efb..1dcd336d5d9 100644
--- a/app/uploaders/import_export_uploader.rb
+++ b/app/uploaders/import_export_uploader.rb
@@ -12,6 +12,10 @@ class ImportExportUploader < AttachmentUploader
end
def move_to_cache
+ # Exports create temporary files that we can safely move.
+ # Imports may be from project templates that we want to copy.
+ return super if mounted_as == :export_file
+
false
end
diff --git a/app/validators/x509_certificate_credentials_validator.rb b/app/validators/x509_certificate_credentials_validator.rb
index d2f18e956c3..11b53d59c7d 100644
--- a/app/validators/x509_certificate_credentials_validator.rb
+++ b/app/validators/x509_certificate_credentials_validator.rb
@@ -41,7 +41,7 @@ class X509CertificateCredentialsValidator < ActiveModel::Validator
return if private_key.nil? || certificate.nil?
- unless certificate.public_key.fingerprint == private_key.public_key.fingerprint
+ unless certificate.check_private_key(private_key)
record.errors.add(options[:pkey], _('private key does not match certificate.'))
end
end
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 e46a88b2217..189986b3dec 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -15,6 +15,7 @@
= f.label :max_attachment_size, _('Maximum attachment size (MB)'), class: 'label-bold'
= f.number_field :max_attachment_size, class: 'form-control gl-form-input', title: _('Maximum size of individual attachments in comments.'), data: { toggle: 'tooltip', container: 'body' }
+ = render 'admin/application_settings/repository_size_limit_setting_registration_features_cta', form: f
= render_if_exists 'admin/application_settings/repository_size_limit_setting', form: f
.form-group
diff --git a/app/views/admin/application_settings/_note_limits.html.haml b/app/views/admin/application_settings/_note_limits.html.haml
index eb6122f244a..38a5d6a1010 100644
--- a/app/views/admin/application_settings/_note_limits.html.haml
+++ b/app/views/admin/application_settings/_note_limits.html.haml
@@ -9,7 +9,7 @@
= f.label :notes_create_limit_allowlist, _('Users to exclude from the rate limit'), class: 'label-bold'
= f.text_area :notes_create_limit_allowlist_raw, placeholder: 'username1, username2', class: 'form-control gl-form-input', rows: 5
.form-text.text-muted
- = _('Comma-separated list of users allowed to exceed the rate limit.')
+ = _('List of users allowed to exceed the rate limit.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_repository_check.html.haml b/app/views/admin/application_settings/_repository_check.html.haml
index 6df1be9f6cb..ce81f81c125 100644
--- a/app/views/admin/application_settings/_repository_check.html.haml
+++ b/app/views/admin/application_settings/_repository_check.html.haml
@@ -16,7 +16,7 @@
= _("If you get a lot of false alarms from repository checks, you can clear all repository check information from the database.")
- clear_repository_checks_link = _('Clear all repository checks')
- clear_repository_checks_message = _('This clears repository check states for all projects in the database and cannot be undone. Are you sure?')
- = link_to clear_repository_checks_link, clear_repository_check_states_admin_application_settings_path, data: { confirm: clear_repository_checks_message }, method: :put, class: "gl-button btn btn-sm btn-danger gl-mt-3"
+ = link_to clear_repository_checks_link, clear_repository_check_states_admin_application_settings_path, data: { confirm: clear_repository_checks_message, confirm_btn_variant: 'danger' }, aria: { label: _('Clear repository checks') }, method: :put, class: "gl-button btn btn-sm btn-danger gl-mt-3"
.sub-section
%h4= _("Housekeeping")
diff --git a/app/views/admin/application_settings/_repository_size_limit_setting_registration_features_cta.html.haml b/app/views/admin/application_settings/_repository_size_limit_setting_registration_features_cta.html.haml
new file mode 100644
index 00000000000..8daa5aa8c73
--- /dev/null
+++ b/app/views/admin/application_settings/_repository_size_limit_setting_registration_features_cta.html.haml
@@ -0,0 +1,8 @@
+- return unless registration_features_can_be_prompted?
+
+.form-group
+ = form.label :disabled_repository_size_limit, class: 'label-bold' do
+ = _('Size limit per repository (MB)')
+ = form.number_field :disabled_repository_size_limit, value: '', class: 'form-control gl-form-input', disabled: true
+ %span.form-text.text-muted
+ = render 'shared/registration_features_discovery_message'
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 4fba1aee12d..326aae26d5e 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -28,8 +28,8 @@
%button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
.gl-spinner.js-spinner.gl-display-none.gl-mr-2
- .js-text.d-inline= _('Preview payload')
- %pre.service-data-payload-container.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
+ .js-text.gl-display-inline= _('Preview payload')
+ %pre.service-data-payload-container.js-syntax-highlight.code.highlight.gl-mt-2.gl-display-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
- else
= _('Service ping is disabled in your configuration file, and cannot be enabled through this form.')
- deactivating_service_ping_path = help_page_path('development/service_ping/index.md', anchor: 'disable-service-ping-using-the-configuration-file')
diff --git a/app/views/admin/application_settings/_users_api_limits.html.haml b/app/views/admin/application_settings/_users_api_limits.html.haml
new file mode 100644
index 00000000000..e9b657f8942
--- /dev/null
+++ b/app/views/admin/application_settings/_users_api_limits.html.haml
@@ -0,0 +1,14 @@
+= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-users-api-limits-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ = f.label :users_get_by_id_limit, _('Maximum requests per 10 minutes per user'), class: 'label-bold'
+ = f.number_field :users_get_by_id_limit, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :users_get_by_id_limit_allowlist_raw, _('Users to exclude from the rate limit'), class: 'label-bold'
+ = f.text_area :users_get_by_id_limit_allowlist_raw, placeholder: 'username1, username2', class: 'form-control gl-form-input', rows: 5
+ .form-text.text-muted
+ = _('List of users allowed to exceed the rate limit.')
+
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 242d0c364f4..90183b028f0 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -122,6 +122,18 @@
.settings-content
= render 'note_limits'
+%section.settings.as-users-api-limits.no-animate#js-users-api-limits-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Users API rate limit')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Set the per-user rate limit for getting a user by ID via the API.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/rate_limit_on_users_api.md'), target: '_blank', rel: 'noopener noreferrer'
+ .settings-content
+ = render 'users_api_limits'
+
%section.settings.as-import-export-limits.no-animate#js-import-export-limits-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
diff --git a/app/views/admin/application_settings/service_usage_data.html.haml b/app/views/admin/application_settings/service_usage_data.html.haml
new file mode 100644
index 00000000000..d9825183d88
--- /dev/null
+++ b/app/views/admin/application_settings/service_usage_data.html.haml
@@ -0,0 +1,16 @@
+- name = _("Service usage data")
+
+- breadcrumb_title name
+- page_title name
+- @content_class = "limit-container-width" unless fluid_layout
+- payload_class = 'js-service-ping-payload'
+
+%h3= name
+
+%button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
+ .gl-spinner.js-spinner.gl-display-none.gl-mr-2
+ .js-text.gl-display-inline= _('Preview payload')
+%button.gl-button.btn.btn-default.js-payload-download-trigger{ type: 'button', data: { endpoint: usage_data_admin_application_settings_path(format: :json) } }
+ .gl-spinner.js-spinner.gl-display-none.gl-mr-2
+ .js-text.d-inline= _('Download payload')
+%pre.js-syntax-highlight.code.highlight.gl-mt-2.gl-display-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
diff --git a/app/views/admin/background_migrations/index.html.haml b/app/views/admin/background_migrations/index.html.haml
index 13ac511f1b4..afceb6427e0 100644
--- a/app/views/admin/background_migrations/index.html.haml
+++ b/app/views/admin/background_migrations/index.html.haml
@@ -1,33 +1,26 @@
- 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']
+= gl_tabs_nav do
+ = gl_tab_link_to admin_background_migrations_path, item_active: @current_tab == 'queued' do
+ = _('Queued')
+ = gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['queued'])
+ = gl_tab_link_to admin_background_migrations_path(tab: 'failed'), item_active: @current_tab == 'failed' do
+ = _('Failed')
+ = gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['failed'])
+ = gl_tab_link_to admin_background_migrations_path(tab: 'finished'), item_active: @current_tab == 'finished' do
+ = _('Finished')
+ = gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['finished'])
- %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')
- = gl_tab_counter_badge 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')
- = gl_tab_counter_badge 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')
- = gl_tab_counter_badge 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')
+ %th.table-th-transparent.border-bottom{ role: 'cell' }
+ %tbody{ role: 'rowgroup' }
+ = render partial: 'migration', collection: @migrations
- .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')
- %th.table-th-transparent.border-bottom{ role: 'cell' }
- %tbody{ role: 'rowgroup' }
- = render partial: 'migration', collection: @migrations
-
- = paginate_collection @migrations
+ = paginate_collection @migrations
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 9dce33bf037..3f07bea7840 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -11,33 +11,33 @@
%br.clearfix
- if @broadcast_messages.any?
- %table.table.table-responsive
- %thead
- %tr
- %th= _('Status')
- %th= _('Preview')
- %th= _('Starts')
- %th= _('Ends')
- %th= _(' Target Path')
- %th= _(' Type')
- %th &nbsp;
- %tbody
- - @broadcast_messages.each do |message|
+ .table-responsive
+ %table.table.b-table.gl-table
+ %thead
%tr
- %td
- = broadcast_message_status(message)
- %td
- = broadcast_message(message, preview: true)
- %td
- = message.starts_at
- %td
- = message.ends_at
- %td
- = message.target_path
- %td
- = message.broadcast_type.capitalize
- %td.gl-white-space-nowrap.gl-display-flex
- = link_to sprite_icon('pencil-square', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: _('Edit'), class: 'btn btn-icon gl-button'
- = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: _('Remove'), class: 'js-remove-tr btn btn-icon gl-button btn-danger ml-2'
-
- = paginate @broadcast_messages, theme: 'gitlab'
+ %th= _('Status')
+ %th= _('Preview')
+ %th= _('Starts')
+ %th= _('Ends')
+ %th= _(' Target Path')
+ %th= _(' Type')
+ %th &nbsp;
+ %tbody
+ - @broadcast_messages.each do |message|
+ %tr
+ %td
+ = broadcast_message_status(message)
+ %td
+ = broadcast_message(message, preview: true)
+ %td
+ = message.starts_at
+ %td
+ = message.ends_at
+ %td
+ = message.target_path
+ %td
+ = message.broadcast_type.capitalize
+ %td.gl-white-space-nowrap
+ = link_to sprite_icon('pencil-square', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: _('Edit'), class: 'btn btn-icon gl-button'
+ = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: _('Remove'), class: 'js-remove-tr btn btn-icon gl-button btn-danger ml-2'
+ = paginate @broadcast_messages, theme: 'gitlab'
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 85b6ebfc63a..69033d274a2 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -143,6 +143,11 @@
= _('GitLab Pages')
%span.float-right
= Gitlab::Pages::VERSION
+ - if Gitlab::Kas.enabled?
+ %p
+ = _('GitLab KAS')
+ %span.gl-float-right
+ = Gitlab::Kas.version
= render_if_exists 'admin/dashboard/geo'
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index 0c2280a2f63..c27ff348f59 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -33,4 +33,4 @@
.controls.gl-flex-shrink-0.gl-ml-5
= link_to _('Edit'), admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'btn gl-button btn-default'
- = link_to _('Delete'), [:admin, group], data: { confirm: _("Are you sure you want to remove %{group_name}?") % { group_name: group.name } }, method: :delete, class: 'gl-button btn btn-danger'
+ = link_to _('Delete'), [:admin, group], aria: { label: _('Remove') }, data: { confirm: _("Are you sure you want to remove %{group_name}?") % { group_name: group.name }, confirm_btn_variant: 'danger' }, method: :delete, class: 'gl-button btn btn-danger'
diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml
index 9c258e10008..566d8a99ac6 100644
--- a/app/views/admin/hooks/edit.html.haml
+++ b/app/views/admin/hooks/edit.html.haml
@@ -13,7 +13,7 @@
.form-actions
%span>= f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mr-3'
= render 'shared/web_hooks/test_button', hook: @hook
- = link_to _('Delete'), admin_hook_path(@hook), method: :delete, class: 'btn gl-button btn-danger float-right', data: { confirm: _('Are you sure?') }
+ = link_to _('Delete'), admin_hook_path(@hook), method: :delete, class: 'btn gl-button btn-danger float-right', aria: { label: s_('Webhooks|Delete webhook') }, data: { confirm: s_('Webhooks|Are you sure you want to delete this webhook?'), confirm_btn_variant: 'danger' }
%hr
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index 16661efce04..ae8fed8964f 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -3,5 +3,5 @@
.label-actions-list
= link_to edit_admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
- = link_to admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary hover-red js-remove-label label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: "Delete this label? Are you sure?" }, aria_label: _('Delete'), method: :delete, remote: true do
+ = link_to admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary hover-red js-remove-label label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: _('Are you sure you want to delete this label?'), confirm_btn_variant: 'danger' }, aria: { label: _('Delete label') }, method: :delete, remote: true do
= sprite_icon('remove')
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index ee2e63353f0..e8bcf479d70 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -39,15 +39,15 @@
= _('Namespace:')
%strong
- if @project.namespace
- = link_to @project.namespace.human_name, [:admin, @project.group || @project.owner]
+ = link_to @project.namespace.human_name, [:admin, @project.personal? ? @project.namespace.owner : @project.group]
- else
= s_('ProjectSettings|Global')
%li
%span.light
= _('Owned by:')
%strong
- - if @project.owner
- = link_to @project.owner_name, [:admin, @project.owner]
+ - if @project.owners.any?
+ = safe_join(@project.owners.map { |owner| link_to(owner.name, [:admin, owner]) }, ", ".html_safe)
- else
= _('(deleted)')
diff --git a/app/views/admin/runners/edit.html.haml b/app/views/admin/runners/edit.html.haml
index 0257983016c..b65fead49ab 100644
--- a/app/views/admin/runners/edit.html.haml
+++ b/app/views/admin/runners/edit.html.haml
@@ -1,7 +1,7 @@
- add_page_specific_style 'page_bundles/ci_status'
- runner_name = "##{@runner.id} (#{@runner.short_sha})"
-- if Feature.enabled?(:runner_read_only_admin_view)
+- if Feature.enabled?(:runner_read_only_admin_view, default_enabled: :yaml)
- breadcrumb_title _('Edit')
- page_title _('Edit'), runner_name
- add_to_breadcrumbs _('Runners'), admin_runners_path
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 7b4390ae463..5c4a7026f50 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -5,4 +5,4 @@
- page_title title
- add_to_breadcrumbs _('Runners'), admin_runners_path
--# Empty view in development behind feature flag runner_read_only_admin_view
+#js-admin-runner-show{ data: {runner_id: @runner.id} }
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 5977de7c84c..1e4c3f3bb62 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -26,10 +26,10 @@
= render_if_exists 'admin/users/auditor_access_level_radio', f: f, disabled: editing_current_user
- - help_text = s_('AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation.')
- - help_text += ' ' + s_('AdminUsers|You cannot remove your own admin rights.') if editing_current_user
+ - help_text = s_('AdminUsers|The user has unlimited access to all groups, projects, users, and features.')
+ - help_text += ' ' + s_('AdminUsers|You cannot remove your own administrator access.') if editing_current_user
= f.gitlab_ui_radio_component :access_level, :admin,
- s_('AdminUsers|Admin'),
+ s_('AdminUsers|Administrator'),
radio_options: { disabled: editing_current_user },
help_text: help_text
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index 5edd5403d49..6fdf383d571 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -6,43 +6,44 @@
.gl-alert-body
= render 'shared/registration_features_discovery_message', feature_title: s_('RegistrationFeatures|send emails to users')
-.top-area.scrolling-tabs-container.inner-page-scroll-tabs
- .fade-left
- = sprite_icon('chevron-lg-left', size: 12)
- .fade-right
- = sprite_icon('chevron-lg-right', size: 12)
- = gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1' }) do
- = gl_tab_link_to admin_users_path, { item_active: active_when(params[:filter].nil?), class: 'gl-border-0!' } do
- = s_('AdminUsers|Active')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.active_without_ghosts))
- = gl_tab_link_to admin_users_path(filter: "admins"), { item_active: active_when(params[:filter] == 'admins'), class: 'gl-border-0!' } do
- = s_('AdminUsers|Admins')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.admins))
- = gl_tab_link_to admin_users_path(filter: 'two_factor_enabled'), { item_active: active_when(params[:filter] == 'two_factor_enabled'), class: 'filter-two-factor-enabled gl-border-0!' } do
- = s_('AdminUsers|2FA Enabled')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.with_two_factor))
- = gl_tab_link_to admin_users_path(filter: 'two_factor_disabled'), { item_active: active_when(params[:filter] == 'two_factor_disabled'), class: 'filter-two-factor-disabled gl-border-0!' } do
- = s_('AdminUsers|2FA Disabled')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_two_factor))
- = gl_tab_link_to admin_users_path(filter: 'external'), { item_active: active_when(params[:filter] == 'external'), class: 'gl-border-0!' } do
- = s_('AdminUsers|External')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.external))
- = gl_tab_link_to admin_users_path(filter: "blocked"), { item_active: active_when(params[:filter] == 'blocked'), class: 'gl-border-0!' } do
- = s_('AdminUsers|Blocked')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked))
- - if ban_feature_available?
- = gl_tab_link_to admin_users_path(filter: "banned"), { item_active: active_when(params[:filter] == 'banned'), class: 'gl-border-0!' } do
- = s_('AdminUsers|Banned')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.banned))
- = gl_tab_link_to admin_users_path(filter: "blocked_pending_approval"), { item_active: active_when(params[:filter] == 'blocked_pending_approval'), class: 'filter-blocked-pending-approval gl-border-0!', data: { qa_selector: 'pending_approval_tab' } } do
- = s_('AdminUsers|Pending approval')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked_pending_approval))
- = gl_tab_link_to admin_users_path(filter: "deactivated"), { item_active: active_when(params[:filter] == 'deactivated'), class: 'gl-border-0!' } do
- = s_('AdminUsers|Deactivated')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.deactivated))
- = gl_tab_link_to admin_users_path(filter: "wop"), { item_active: active_when(params[:filter] == 'wop'), class: 'gl-border-0!' } do
- = s_('AdminUsers|Without projects')
- = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_projects))
+.top-area
+ .scrolling-tabs-container.inner-page-scroll-tabs.gl-flex-grow-1.gl-min-w-0.gl-w-full
+ .fade-left
+ = sprite_icon('chevron-lg-left', size: 12)
+ .fade-right
+ = sprite_icon('chevron-lg-right', size: 12)
+ = gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1 gl-w-full' }) do
+ = gl_tab_link_to admin_users_path, { item_active: active_when(params[:filter].nil?), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Active')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.active_without_ghosts))
+ = gl_tab_link_to admin_users_path(filter: "admins"), { item_active: active_when(params[:filter] == 'admins'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Admins')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.admins))
+ = gl_tab_link_to admin_users_path(filter: 'two_factor_enabled'), { item_active: active_when(params[:filter] == 'two_factor_enabled'), class: 'filter-two-factor-enabled gl-border-0!' } do
+ = s_('AdminUsers|2FA Enabled')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.with_two_factor))
+ = gl_tab_link_to admin_users_path(filter: 'two_factor_disabled'), { item_active: active_when(params[:filter] == 'two_factor_disabled'), class: 'filter-two-factor-disabled gl-border-0!' } do
+ = s_('AdminUsers|2FA Disabled')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_two_factor))
+ = gl_tab_link_to admin_users_path(filter: 'external'), { item_active: active_when(params[:filter] == 'external'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|External')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.external))
+ = gl_tab_link_to admin_users_path(filter: "blocked"), { item_active: active_when(params[:filter] == 'blocked'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Blocked')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked))
+ - if ban_feature_available?
+ = gl_tab_link_to admin_users_path(filter: "banned"), { item_active: active_when(params[:filter] == 'banned'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Banned')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.banned))
+ = gl_tab_link_to admin_users_path(filter: "blocked_pending_approval"), { item_active: active_when(params[:filter] == 'blocked_pending_approval'), class: 'filter-blocked-pending-approval gl-border-0!', data: { qa_selector: 'pending_approval_tab' } } do
+ = s_('AdminUsers|Pending approval')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked_pending_approval))
+ = gl_tab_link_to admin_users_path(filter: "deactivated"), { item_active: active_when(params[:filter] == 'deactivated'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Deactivated')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.deactivated))
+ = gl_tab_link_to admin_users_path(filter: "wop"), { item_active: active_when(params[:filter] == 'wop'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Without projects')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_projects))
.nav-controls
= render_if_exists 'admin/users/admin_email_users'
= render_if_exists 'admin/users/admin_export_user_permissions'
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index f51ac40df4f..580cfe9f956 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -16,7 +16,7 @@
.float-right
%span.light.vertical-align-middle= group_member.human_access
- unless group_member.owner?
- = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), testid: 'remove-user' }, method: :delete, remote: true, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from group') do
+ = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), confirm_btn_variant: 'danger', testid: 'remove-user' }, aria: { label: _('Remove') }, method: :delete, remote: true, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from group') do
= sprite_icon('remove', size: 16, css_class: 'gl-icon')
.row
@@ -46,7 +46,7 @@
%span.light.vertical-align-middle= member.human_access
- if member.respond_to? :project
- = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from project') do
+ = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member), confirm_btn_variant: 'danger' }, aria: { label: _('Remove') }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from project') do
= sprite_icon('remove', size: 16, css_class: 'gl-icon')
= render partial: 'admin/users/modals'
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index bdc5bdabb21..94542af3b96 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -10,7 +10,7 @@
= @user.name
%ul.content-list
%li
- = image_tag avatar_icon_for_user(@user, 60), class: "avatar s60"
+ = image_tag avatar_icon_for_user(@user, 60, current_user: current_user), class: "avatar s60"
%li
%span.light= _('Profile page:')
%strong
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 c872ee481ad..f0a9936112b 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -1,6 +1,6 @@
- link = link_to _("Install GitLab Runner and ensure it's running."), 'https://docs.gitlab.com/runner/install/', target: '_blank', rel: 'noopener noreferrer'
.gl-mb-3
- %h5= _("Set up a %{type} Runner for a project") % { type: type }
+ %h5= _("Set up a %{type} runner for a project") % { type: type }
%ol
%li
= link.html_safe
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index bf654999f2f..fb46b4e5064 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -22,8 +22,6 @@
.js-cluster-application-notice
.flash-container
- .js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
-
%h4.gl-my-5.gl-display-flex.gl-align-items-center
= @cluster.name
= gl_badge_tag cluster_type_label(@cluster.cluster_type), { variant: :info }, { class: 'gl-ml-3' }
diff --git a/app/views/dashboard/_projects_nav.html.haml b/app/views/dashboard/_projects_nav.html.haml
index 64aa1e01d06..90b40f3c7b7 100644
--- a/app/views/dashboard/_projects_nav.html.haml
+++ b/app/views/dashboard/_projects_nav.html.haml
@@ -10,4 +10,4 @@
= gl_tab_counter_badge(limited_counter_with_delimiter(@total_starred_projects_count))
= gl_tab_link_to _("Explore projects"), explore_root_path, { item_active: is_explore_projects_path, data: { placement: 'right' } }
= gl_tab_link_to _("Explore topics"), topics_explore_projects_path, { data: { placement: 'right' } }
- = render_if_exists "dashboard/removed_projects_tab", removed_projects_count: @removed_projects_count
+ = render_if_exists "dashboard/removed_projects_tab"
diff --git a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
index 20bf7d232ce..eba5e7c6e9b 100644
--- a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
@@ -1,40 +1,42 @@
-.blank-state-row
+- link_classes = "blank-state blank-state-link gl-text-body gl-display-flex gl-align-items-center gl-border-1 gl-border-solid gl-border-gray-100 gl-rounded-base gl-mb-5"
+
+.gl-display-flex.gl-flex-wrap.gl-justify-content-space-between
- if has_start_trial?
= render_if_exists "dashboard/projects/blank_state_ee_trial"
- = link_to new_project_path, class: "blank-state blank-state-link" do
+ = link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Create a project
- %p.blank-state-text
- Projects are where you store your code, access issues, wiki and other features of GitLab.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Create a project')
+ %p
+ = _('Projects are where you store your code, access issues, wiki and other features of GitLab.')
- if current_user.can_create_group?
- = link_to new_group_path, class: "blank-state blank-state-link" do
+ = link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Create a group
- %p.blank-state-text
- Groups are a great way to organize projects and people.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Create a group')
+ %p
+ = _('Groups are a great way to organize projects and people.')
- = link_to new_admin_user_path, class: "blank-state blank-state-link" do
+ = link_to new_admin_user_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_user", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Add people
- %p.blank-state-text
- Add your team members and others to GitLab.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Add people')
+ %p
+ = _('Add your team members and others to GitLab.')
- = link_to admin_root_path, class: "blank-state blank-state-link" do
+ = link_to admin_root_path, class: link_classes do
.blank-state-icon
= custom_icon("configure_server", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Configure GitLab
- %p.blank-state-text
- Make adjustments to how your GitLab instance is set up.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Configure GitLab')
+ %p
+ = _('Make adjustments to how your GitLab instance is set up.')
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index 003e6f18b33..e0b8850357e 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -1,48 +1,49 @@
-.blank-state-row
+- link_classes = "blank-state blank-state-link gl-text-body gl-display-flex gl-align-items-center gl-border-1 gl-border-solid gl-border-gray-100 gl-rounded-base gl-mb-5"
+
+.gl-display-flex.gl-flex-wrap.gl-justify-content-space-between
- if current_user.can_create_project?
- = link_to new_project_path, class: "blank-state blank-state-link" do
+ = link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Create a project
- %p.blank-state-text
- Projects are where you store your code, access issues, wiki and other features of GitLab.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Create a project')
+ %p
+ = _('Projects are where you store your code, access issues, wiki and other features of GitLab.')
- else
- .blank-state
+ .blank-state.gl-display-flex.gl-align-items-center.gl-border-1.gl-border-solid.gl-border-gray-100.gl-rounded-base.gl-mb-5
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Create a project
- %p.blank-state-text
- If you are added to a project, it will be displayed here.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Create a project')
+ %p
+ = _('If you are added to a project, it will be displayed here.')
- if current_user.can_create_group?
- = link_to new_group_path, class: "blank-state blank-state-link" do
+ = link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Create a group
- %p.blank-state-text
- Groups are the best way to manage projects and members.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Create a group')
+ %p
+ = _('Groups are the best way to manage projects and members.')
- = link_to trending_explore_projects_path, class: "blank-state blank-state-link" do
+ = link_to trending_explore_projects_path, class: link_classes do
.blank-state-icon
= custom_icon("globe", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Explore public projects
- %p.blank-state-text
- Public projects are an easy way to allow
- everyone to have read-only access.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Explore public projects')
+ %p
+ = _('Public projects are an easy way to allow everyone to have read-only access.')
- = link_to "https://docs.gitlab.com/", class: "blank-state blank-state-link" do
+ = link_to "https://docs.gitlab.com/", class: link_classes do
.blank-state-icon
= custom_icon("lightbulb", size: 50)
- .blank-state-body
- %h3.blank-state-title
- Learn more about GitLab
- %p.blank-state-text
- Take a look at the documentation to discover all of GitLab's capabilities.
+ .blank-state-body.gl-sm-pl-0.gl-pl-6
+ %h3.gl-font-size-h2.gl-mt-0
+ = _('Learn more about GitLab')
+ %p
+ = _('Take a look at the documentation to discover all of GitLab’s capabilities.')
diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
index b5f5025b581..e72762f2ae5 100644
--- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
@@ -1,13 +1,10 @@
-.blank-state-parent-container
- .section-container.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
- .container.section-body
- .row
- .blank-state-welcome.w-100
- %h2.blank-state-welcome-title{ data: { qa_selector: 'welcome_title_content' } }
- = _('Welcome to GitLab')
- %p.blank-state-text
- = _('Faster releases. Better code. Less pain.')
- - if current_user.admin?
- = render "blank_state_admin_welcome"
- - else
- = render "blank_state_welcome"
+.container
+ .gl-text-center.gl-pt-6.gl-pb-7
+ %h2.gl-font-size-h1{ data: { qa_selector: 'welcome_title_content' } }
+ = _('Welcome to GitLab')
+ %p.gl-m-0
+ = _('Faster releases. Better code. Less pain.')
+ - if current_user.admin?
+ = render "blank_state_admin_welcome"
+ - else
+ = render "blank_state_welcome"
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index 4252b60514a..0d9257e659a 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -7,6 +7,7 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+- add_page_specific_style 'page_bundles/dashboard_projects'
= render "projects/last_push"
- if show_projects?(@projects, params)
diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml
index 1d46a43e5bd..ef19ac33a15 100644
--- a/app/views/devise/confirmations/almost_there.haml
+++ b/app/views/devise/confirmations/almost_there.haml
@@ -4,6 +4,7 @@
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
+ = render "layouts/bizible"
= render "layouts/google_tag_manager_body"
.well-confirmation.gl-text-center.gl-mb-6
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 87108c8ea78..60c3df718a1 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -3,6 +3,7 @@
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
+ = render "layouts/bizible"
= render "layouts/google_tag_manager_body"
.signup-page
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 175b45dbbfa..c669f3efec6 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,6 +1,7 @@
- page_title _("Sign in")
- content_for :page_specific_javascripts do
= render "layouts/one_trust"
+ = render "layouts/bizible"
#signin-container
- if any_form_based_providers_enabled?
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 982171b9e34..970e490dd72 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,7 +1,8 @@
- max_first_name_length = max_last_name_length = 127
- omniauth_providers_placement ||= :bottom
+- borderless ||= false
-.gl-mb-3.gl-p-4.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base
+.gl-mb-3.gl-p-4{ class: (borderless ? '' : 'gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base') }
- if show_omniauth_providers && omniauth_providers_placement == :top
= render 'devise/shared/signup_omniauth_providers_top'
diff --git a/app/views/discussions/_diff_with_notes.html.haml b/app/views/discussions/_diff_with_notes.html.haml
index b34b6f09662..cd0c9a016a5 100644
--- a/app/views/discussions/_diff_with_notes.html.haml
+++ b/app/views/discussions/_diff_with_notes.html.haml
@@ -29,7 +29,7 @@
%td.line_content.js-success-lazy-load
.js-code-placeholder
%td.js-error-lazy-load-diff.hidden.diff-loading-error-block
- - button = button_tag(_("Try again"), class: "btn-link gl-button btn-link-retry btn-no-padding js-toggle-lazy-diff-retry-button")
+ - button = button_tag(_("Try again"), class: "btn-link gl-button btn-link-retry gl-p-0 js-toggle-lazy-diff-retry-button")
= _("Unable to load the diff. %{button_try_again}").html_safe % { button_try_again: button}
= render "discussions/diff_discussion", discussions: [discussion], expanded: true
- else
diff --git a/app/views/discussions/_notes.html.haml b/app/views/discussions/_notes.html.haml
index beac4946fd7..a35ba12dd52 100644
--- a/app/views/discussions/_notes.html.haml
+++ b/app/views/discussions/_notes.html.haml
@@ -9,9 +9,9 @@
-# to the first note position when we click on a badge diff discussion
%ul.notes{ id: "discussion_#{discussion.id}", data: { discussion_id: discussion.id, position: discussion.notes[0].position.to_json } }
- if discussion.try(:on_image?) && show_toggle
- %button.gl-button.diff-notes-collapse.js-diff-notes-toggle{ type: 'button' }
+ %button.comment-indicator.gl-display-flex.gl-align-items-center.gl-justify-content-center.gl-font-sm.diff-notes-collapse.js-diff-notes-toggle{ type: 'button' }
= sprite_icon('collapse', css_class: 'collapse-icon')
- %button.gl-button.btn-transparent.badge.badge-pill.js-diff-notes-toggle{ type: 'button' }
+ %button.gl-align-items-center.gl-justify-content-center.gl-font-sm.small.gl-translate-x-n50.design-note-pin.js-diff-notes-toggle.diff-notes-expand{ type: 'button' }
= badge_counter
= render partial: "shared/notes/note", collection: discussion.notes, as: :note, locals: { badge_counter: badge_counter, show_image_comment_badge: show_image_comment_badge }
diff --git a/app/views/doorkeeper/authorized_applications/_delete_form.html.haml b/app/views/doorkeeper/authorized_applications/_delete_form.html.haml
index d73d171798e..fcd52f33121 100644
--- a/app/views/doorkeeper/authorized_applications/_delete_form.html.haml
+++ b/app/views/doorkeeper/authorized_applications/_delete_form.html.haml
@@ -5,4 +5,4 @@
= form_tag path do
%input{ :name => "_method", :type => "hidden", :value => "delete" }/
- = submit_tag _('Revoke'), class: 'gl-button btn btn-danger btn-sm', data: { confirm: _('Are you sure?') }
+ = submit_tag _('Revoke'), class: 'gl-button btn btn-danger btn-sm', aria: { label: s_('AuthorizedApplication|Revoke application') }, data: { confirm: s_('AuthorizedApplication|Are you sure you want to revoke this application?'), confirm_btn_variant: 'danger' }
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index e5d67831c71..9b3a8c31d54 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -31,7 +31,7 @@
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('admin')
- if @notification_setting
- .js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-mx-2 gl-mt-3 gl-vertical-align-top' } }
+ .js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-mx-2 gl-mt-3 gl-vertical-align-top', no_flip: 'true' } }
- if can_create_subgroups
.gl-px-2.gl-sm-w-auto.gl-w-full
= link_to _("New subgroup"), new_group_path(parent_id: @group.id), class: "btn btn-default gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_subgroup_button' }
diff --git a/app/views/groups/_import_group_from_file_panel.html.haml b/app/views/groups/_import_group_from_file_panel.html.haml
index 0644910dd3e..ee0967f708a 100644
--- a/app/views/groups/_import_group_from_file_panel.html.haml
+++ b/app/views/groups/_import_group_from_file_panel.html.haml
@@ -11,10 +11,7 @@
.gl-alert-body
- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
- link_end = '</a>'.html_safe
- = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
- - if Feature.enabled?(:bulk_import, default_enabled: :yaml)
- - enable_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md', anchor: 'enable-or-disable-gitlab-group-migration') }
- = s_('GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration.').html_safe % { enable_link_start: enable_link_start, enable_link_end: link_end }
+ = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
.form-group.gl-display-flex.gl-flex-direction-column.gl-mt-5
= f.label :name, _('New group name'), for: 'import_group_name'
diff --git a/app/views/groups/_invite_groups_modal.html.haml b/app/views/groups/_invite_groups_modal.html.haml
new file mode 100644
index 00000000000..22ef319348a
--- /dev/null
+++ b/app/views/groups/_invite_groups_modal.html.haml
@@ -0,0 +1,3 @@
+- return unless can_admin_group_member?(group)
+
+.js-invite-groups-modal{ data: common_invite_group_modal_data(group, GroupMember, 'false').merge(group_select_data(group)) }
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index 78f079df158..786034fd2e7 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -2,5 +2,4 @@
.js-invite-members-modal{ data: { is_project: 'false',
access_levels: GroupMember.access_level_roles.to_json,
- default_access_level: Gitlab::Access::GUEST,
- help_link: help_page_url('user/permissions') }.merge(group_select_data(group)).merge(common_invite_modal_dataset(group)).merge(users_filter_data(group)) }
+ help_link: help_page_url('user/permissions') }.merge(common_invite_modal_dataset(group)).merge(users_filter_data(group)) }
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 97867e312af..d1f56a50907 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -11,7 +11,7 @@
= _('Group members')
%p
= html_escape(_('You can invite a new member to %{strong_start}%{group_name}%{strong_end}.')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- - if Feature.enabled?(:invite_members_group_modal, @group)
+ - if Feature.enabled?(:invite_members_group_modal, @group, default_enabled: :yaml)
.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') } }
@@ -19,8 +19,9 @@
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_groups_modal', group: @group
= render 'groups/invite_members_modal', group: @group
- - if can_admin_group_member?(@group) && Feature.disabled?(:invite_members_group_modal, @group)
+ - if can_admin_group_member?(@group) && Feature.disabled?(:invite_members_group_modal, @group, default_enabled: :yaml)
%hr.gl-mt-4
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index a9258a4e0d0..8afa6316c56 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -6,7 +6,7 @@
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
- if Feature.enabled?(:vue_issues_list, @group, default_enabled: :yaml)
- .js-issues-list{ data: group_issues_list_data(@group, current_user, @issues, @projects) }
+ .js-issues-list{ data: group_issues_list_data(@group, current_user) }
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
- else
diff --git a/app/views/groups/runners/index.html.haml b/app/views/groups/runners/index.html.haml
index f904b34d29e..a67a4f28c93 100644
--- a/app/views/groups/runners/index.html.haml
+++ b/app/views/groups/runners/index.html.haml
@@ -1,6 +1,3 @@
- page_title s_('Runners|Runners')
-%h2.page-title
- = s_('Runners|Group Runners')
-
#js-group-runners{ data: group_runners_data_attributes(@group).merge( { group_runners_limited_count: @group_runners_limited_count } ) }
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
index ff00ff1f6e8..81403fd88b2 100644
--- a/app/views/groups/settings/_export.html.haml
+++ b/app/views/groups/settings/_export.html.haml
@@ -10,7 +10,7 @@
.gl-alert-body
- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
- docs_link_end = '</a>'.html_safe
- = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
+ = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
%p
- export_information = _('After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance.') % { strong_text_start: '<strong>'.html_safe, strong_text_end: '</strong>'.html_safe}
= export_information.html_safe
@@ -27,10 +27,10 @@
%li= _('Runner tokens')
%li= _('SAML discovery tokens')
- if group.export_file_exists?
- = link_to _('Regenerate export'), export_group_path(group),
- method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'regenerate_export_group_link' }
= link_to _('Download export'), download_export_group_path(group),
rel: 'nofollow', method: :get, class: 'btn gl-button btn-default', data: { qa_selector: 'download_export_link' }
+ = link_to _('Regenerate export'), export_group_path(group),
+ method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'regenerate_export_group_link' }
- else
= link_to _('Export group'), export_group_path(group),
method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'export_group_link' }
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index ed76a9fe253..ad0780e869c 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -5,29 +5,31 @@
%fieldset
.row
.form-group.col-md-5
- = f.label :name, _('Group name'), class: 'label-bold'
+ = f.label :name, s_('Groups|Group name'), class: 'label-bold'
= f.text_field :name, class: 'form-control', data: { qa_selector: 'group_name_field' }
+ .text-muted
+ = s_('Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
.form-group.col-md-7
- = f.label :id, _('Group ID'), class: 'label-bold'
+ = f.label :id, s_('Groups|Group ID'), class: 'label-bold'
= f.text_field :id, class: 'form-control w-auto', readonly: true
.row.gl-mt-3
.form-group.col-md-9
- = f.label :description, _('Group description'), class: 'label-bold'
+ = f.label :description, s_('Groups|Group description (optional)'), class: 'label-bold'
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
- .form-text.text-muted= _('Optional.')
+ = render 'shared/repository_size_limit_setting_registration_features_cta', form: f
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
.form-group.gl-mt-3.gl-mb-6
.avatar-container.rect-avatar.s90
= group_icon(@group, alt: '', class: 'avatar group-avatar s90')
- = f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
+ = f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold d-block'
= render 'shared/choose_avatar_button', f: f
- if @group.avatar?
%hr
- = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'gl-button btn btn-danger-secondary'
+ = link_to s_('Groups|Remove avatar'), group_avatar_path(@group.to_param), aria: { label: s_('Groups|Remove avatar') }, data: { confirm: s_('Groups|Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, class: 'gl-button btn btn-danger-secondary'
= render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' }
+ = f.submit s_('Groups|Save changes'), class: 'btn gl-button btn-confirm mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' }
diff --git a/app/views/groups/settings/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml
index 59d52e99dec..d52d9d59ab3 100644
--- a/app/views/groups/settings/_transfer.html.haml
+++ b/app/views/groups/settings/_transfer.html.haml
@@ -1,23 +1,20 @@
+- form_id = "transfer-group-form"
+- initial_data = { button_text: s_('GroupSettings|Transfer group'), group_name: @group.name, target_form_id: form_id, parent_groups: parent_group_options(group), is_paid_group: group.paid?.to_s }
+
.sub-section
%h4.warning-title= s_('GroupSettings|Transfer group')
%p= _('Transfer group to another parent group.')
- = form_for group, url: transfer_group_path(group), method: :put, html: { class: 'js-group-transfer-form' } do |f|
-
+ = form_for group, url: transfer_group_path(group), method: :put, html: { id: form_id, class: 'js-group-transfer-form' } do |f|
%ul
- learn_more_link_start = '<a href="https://docs.gitlab.com/ee/user/project/index.html#redirects-when-changing-repository-paths" target="_blank" rel="noopener noreferrer">'.html_safe
- warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_link_end}") % { learn_more_link_start: learn_more_link_start, learn_more_link_end: '</a>'.html_safe }
%li= warning_text.html_safe
%li= s_('GroupSettings|You can only transfer the group to a group you manage.')
%li= s_('GroupSettings|You will need to update your local repositories to point to the new location.')
- %li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
-
- .form-group
- = dropdown_tag(s_('GroupSettings|Select parent group'), options: { toggle_class: 'js-groups-dropdown', title: s_('GroupSettings|Parent Group'), filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: s_('GroupSettings|Search groups'), disabled: group.paid?, data: { data: parent_group_options(group), qa_selector: 'select_group_dropdown' } })
- = hidden_field_tag 'new_parent_group_id'
+ %li= s_("GroupSettings|If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
- if group.paid?
.gl-alert.gl-alert-info.gl-mb-5
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= html_escape(_("This group can't be transfered because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
-
- = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning', data: { qa_selector: "transfer_group_button" }
+ .js-transfer-group-form{ data: initial_data }
diff --git a/app/views/jira_connect/branches/new.html.haml b/app/views/jira_connect/branches/new.html.haml
index 74d547e6bb8..482012b2848 100644
--- a/app/views/jira_connect/branches/new.html.haml
+++ b/app/views/jira_connect/branches/new.html.haml
@@ -1,6 +1,6 @@
- @hide_breadcrumbs = true
- @hide_top_links = true
- @content_class = 'limit-container-width'
-- page_title _('New branch')
+- page_title _('Create branch')
.js-jira-connect-create-branch{ data: @new_branch_data }
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index d92c30c8840..3319137551b 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -4,14 +4,6 @@
%main.jira-connect-app.gl-px-5.gl-pt-7.gl-mx-auto
.js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
- %p.jira-connect-app-body.gl-px-5.gl-font-base.gl-text-center.gl-mx-auto
- %strong= s_('Integrations|Browser limitations')
- - browser_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'
- - firefox_link_start = browser_link_start.html_safe % { url: 'https://www.mozilla.org/en-US/firefox/' }
- - chrome_link_start = browser_link_start.html_safe % { url: 'https://www.google.com/chrome/' }
- = s_('Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace.').html_safe % { firefox_link_start: firefox_link_start, chrome_link_start: chrome_link_start, link_end: '</a>'.html_safe }
- = link_to _('Learn more'), 'https://gitlab.com/gitlab-org/gitlab/-/issues/284211', target: '_blank', rel: 'noopener noreferrer'
-
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
= webpack_bundle_tag 'jira_connect_app'
diff --git a/app/views/layouts/_bizible.html.haml b/app/views/layouts/_bizible.html.haml
new file mode 100644
index 00000000000..a2b28c138e5
--- /dev/null
+++ b/app/views/layouts/_bizible.html.haml
@@ -0,0 +1,14 @@
+- if bizible_enabled?
+ <!-- Bizible -->
+ = javascript_include_tag "https://cdn.bizible.com/scripts/bizible.js"
+ = javascript_tag nonce: content_security_policy_nonce do
+ :plain
+ const bizibleScript = document.createElement('script');
+ bizibleScript.src = 'https://cdn.bizible.com/scripts/bizible.js';
+ bizibleScript.nonce = '#{content_security_policy_nonce}'
+ bizibleScript.charset = 'UTF-8';
+ bizibleScript.defer = true;
+ document.head.appendChild(bizibleScript);
+
+ function OptanonWrapper() { }
+
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index dded5ba76b0..21cccb86398 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,5 +1,6 @@
-# We currently only support `alert`, `notice`, `success`, 'toast', and 'raw'
- icons = {'alert' => 'error', 'notice' => 'information-o', 'success' => 'check-circle'}
+- type_to_variant = {'alert' => 'danger', 'notice' => 'info', 'success' => 'success'}
.flash-container.flash-container-page.sticky{ data: { qa_selector: 'flash_container' } }
- flash.each do |key, value|
- if key == 'toast' && value
@@ -9,7 +10,7 @@
- elsif value == I18n.t('devise.failure.unconfirmed')
= render 'shared/confirm_your_email_alert'
- elsif value
- %div{ class: "flash-#{key} mb-2" }
+ %div{ class: "flash-#{key} mb-2", data: { testid: "alert-#{type_to_variant[key]}" } }
= sprite_icon(icons[key], css_class: 'align-middle mr-1') unless icons[key].nil?
%span= value
- if %w(alert notice success).include?(key)
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 3e875a0eb24..b7299df1bc1 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -4,7 +4,6 @@
.content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
.mobile-overlay
= render_if_exists 'layouts/header/verification_reminder'
- = yield :group_invite_members_banner
.alert-wrapper.gl-force-block-formatting-context
= render 'shared/outdated_browser'
= render_if_exists "layouts/header/licensed_user_count_threshold"
@@ -17,10 +16,12 @@
= render "shared/service_ping_consent"
= render_two_factor_auth_recovery_settings_check
= render_if_exists "layouts/header/ee_subscribable_banner"
+ = render_if_exists "layouts/header/seats_count_alert"
= render_if_exists "shared/namespace_storage_limit_alert"
= render_if_exists "shared/namespace_user_cap_reached_alert"
= render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
+ = yield :group_invite_members_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index d0a06c7d5bf..871d1213c0e 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -16,7 +16,7 @@
= logo_text
- if Gitlab.com_and_canary?
= link_to Gitlab::Saas.canary_toggle_com_url, class: 'canary-badge bg-transparent', data: { qa_selector: 'canary_badge_link' }, target: :_blank, rel: 'noopener noreferrer' do
- %span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
+ = gl_badge_tag({ variant: :success, size: :sm }) do
= _('Next')
- if current_user
@@ -41,7 +41,7 @@
%li.nav-item.d-none.d-lg-block.m-auto
- unless current_controller?(:search)
- if Feature.enabled?(:new_header_search)
- #js-header-search.header-search{ data: { 'search-context' => search_context.to_json,
+ #js-header-search.header-search{ data: { 'search-context' => header_search_context.to_json,
'search-path' => search_path,
'issues-path' => issues_dashboard_path,
'mr-path' => merge_requests_dashboard_path,
@@ -64,7 +64,7 @@
container: 'body' } do
= sprite_icon('issues')
- issues_count = assigned_issuables_count(:issues)
- %span.badge.badge-pill.issues-count.green-badge{ class: ('hidden' if issues_count == 0) }
+ = gl_badge_tag({ size: :sm, variant: :success }, { class: "gl-ml-n2 #{(' gl-display-none' if issues_count == 0)}", "aria-label": n_("%d assigned issue", "%d assigned issues", issues_count) % issues_count }) do
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter dropdown" }) do
@@ -77,7 +77,7 @@
track_property: 'navigation',
container: 'body' } do
= sprite_icon('git-merge')
- %span.badge.badge-pill.merge-requests-count.js-merge-requests-count{ class: ('hidden' if user_merge_requests_counts[:total] == 0) }
+ = gl_badge_tag({ size: :sm, variant: :warning }, { class: "js-merge-requests-count gl-ml-n2#{(' gl-display-none' if user_merge_requests_counts[:total] == 0)}", "aria-label": n_("%d merge request", "%d merge requests", user_merge_requests_counts[:total]) % user_merge_requests_counts[:total] }) do
= number_with_delimiter(user_merge_requests_counts[:total])
= sprite_icon('chevron-down', css_class: 'caret-down gl-mx-0!')
.dropdown-menu.dropdown-menu-right
@@ -87,12 +87,12 @@
%li
= link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
= _('Assigned to you')
- %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-assigned-mr-count{ class: "" }
+ = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-assigned-mr-count gl-ml-auto" }) do
= user_merge_requests_counts[:assigned]
%li
= link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
= _('Review requests for you')
- %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-reviewer-mr-count{ class: "" }
+ = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-reviewer-mr-count gl-ml-auto" }) do
= user_merge_requests_counts[:review_requested]
- if header_link?(:todos)
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
@@ -103,9 +103,11 @@
track_property: 'navigation',
container: 'body' } do
= sprite_icon('todo-done')
- %span.badge.badge-pill.todos-count.js-todos-count{ class: ('hidden' if todos_pending_count == 0) }
+ -# The todos' counter badge's visibility is being toggled by adding or removing the .hidden class in Js.
+ -# We'll eventually migrate to .gl-display-none: https://gitlab.com/gitlab-org/gitlab/-/issues/351792.
+ = gl_badge_tag({ size: :sm, variant: :info }, { class: "js-todos-count gl-ml-n2#{(' hidden' if todos_pending_count == 0)}", "aria-label": _("Todos count") }) do
= todos_count_format(todos_pending_count)
- %li.nav-item.header-help.dropdown.d-none.d-md-block{ **tracking_attrs('main_navigation', 'click_question_mark_link', 'navigation') }
+ %li.nav-item.header-help.dropdown.d-none.d-md-block{ data: { track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation', track_experiment: 'cross_stage_fdm' } }
= link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown" } do
%span.gl-sr-only
= s_('Nav|Help')
@@ -139,15 +141,15 @@
- experiment(:logged_out_marketing_header, actor: nil) do |e|
- e.candidate do
%li.nav-item.gl-display-none.gl-sm-display-block
- = link_to _('Sign up now'), new_user_registration_path, class: 'gl-button btn btn-default btn-sign-in'
+ = link_to _('Sign up now'), new_user_registration_path, class: 'gl-button btn btn-default btn-sign-in', data: { track_action: 'click_button', track_experiment: e.name, track_label: 'sign_up_now' }
%li.nav-item.gl-display-none.gl-sm-display-block
= link_to _('Login'), new_session_path(:user, redirect_to_referer: 'yes')
= render 'layouts/header/sign_in_register_button', class: 'gl-sm-display-none'
- e.try(:trial_focused) do
%li.nav-item.gl-display-none.gl-sm-display-block
- = link_to _('Get a free trial'), 'https://about.gitlab.com/free-trial/', class: 'gl-button btn btn-default btn-sign-in'
+ = link_to _('Get a free trial'), 'https://about.gitlab.com/free-trial/', class: 'gl-button btn btn-default btn-sign-in', data: { track_action: 'click_button', track_experiment: e.name, track_label: 'get_a_free_trial' }
%li.nav-item.gl-display-none.gl-sm-display-block
- = link_to _('Sign up'), new_user_registration_path
+ = link_to _('Sign up'), new_user_registration_path, data: { track_action: 'click_button', track_experiment: e.name, track_label: 'sign_up' }
%li.nav-item.gl-display-none.gl-sm-display-block
= link_to _('Login'), new_session_path(:user, redirect_to_referer: 'yes')
= render 'layouts/header/sign_in_register_button', class: 'gl-sm-display-none'
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 738bca2f2cc..3a8f9c1ae8d 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -1,6 +1,7 @@
%ul
- if current_user_menu?(:help)
= render 'layouts/header/gitlab_version'
+ = render_if_exists 'layouts/header/help_dropdown/cross_stage_fdm'
= render 'layouts/header/whats_new_dropdown_item'
%li
= link_to _("Help"), help_path
diff --git a/app/views/layouts/header/_whats_new_dropdown_item.html.haml b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
index 377f0f3271d..6473d9c8dd4 100644
--- a/app/views/layouts/header/_whats_new_dropdown_item.html.haml
+++ b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
@@ -2,5 +2,4 @@
%li
%button.gl-justify-content-space-between.gl-align-items-center.js-whats-new-trigger{ type: 'button', class: 'gl-display-flex!' }
= _("What's new")
- %span.js-whats-new-notification-count.gl-badge.badge.sm.badge-dark.badge-pill
- = whats_new_most_recent_release_items_count
+ = gl_badge_tag whats_new_most_recent_release_items_count, { size: :sm }, { class: 'js-whats-new-notification-count' }
diff --git a/app/views/layouts/nav/_classification_level_banner.html.haml b/app/views/layouts/nav/_classification_level_banner.html.haml
index d76fb50aa0b..b36111df99c 100644
--- a/app/views/layouts/nav/_classification_level_banner.html.haml
+++ b/app/views/layouts/nav/_classification_level_banner.html.haml
@@ -1,5 +1,3 @@
- if ::Gitlab::ExternalAuthorization.enabled? && @project
= content_for :header_content do
- %span.badge.color-label.gl-bg-red-500.has-tooltip{ title: s_('ExternalAuthorizationService|Classification label') }
- = sprite_icon('lock-open', size: 8, css_class: 'inline')
- = @project.external_authorization_classification_label
+ = gl_badge_tag(@project.external_authorization_classification_label, { variant: :danger, icon: 'lock-open' }, { class: 'has-tooltip', title: s_('ExternalAuthorizationService|Classification label') })
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index f820f911d61..52eea73ecd2 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -156,13 +156,13 @@
= sprite_icon('slight-frown')
%span.nav-item-name
= _('Abuse Reports')
- %span.badge.badge-pill.count= number_with_delimiter(AbuseReport.count(:all))
+ = gl_badge_tag number_with_delimiter(AbuseReport.count(:all)), variant: :info, size: :sm
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(controller: :abuse_reports, html_options: { class: "fly-out-top-item" } ) do
= link_to admin_abuse_reports_path do
%strong.fly-out-top-item-name
= _('Abuse Reports')
- %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(AbuseReport.count(:all))
+ = gl_badge_tag number_with_delimiter(AbuseReport.count(:all)), variant: :info, size: :sm
= render_if_exists 'layouts/nav/sidebar/licenses_link'
@@ -269,6 +269,11 @@
= link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), class: 'qa-admin-settings-metrics-and-profiling-item' do
%span
= _('Metrics and profiling')
+ - if Feature.enabled?(:admin_application_settings_service_usage_data_center, default_enabled: :yaml)
+ = nav_link(path: ['application_settings#service_usage_data']) do
+ = link_to service_usage_data_admin_application_settings_path, title: _('Service usage data') do
+ %span
+ = _('Service usage data')
= nav_link(path: 'application_settings#network') do
= link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do
%span
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index 73a437a0702..6c6fa32f736 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -2,7 +2,7 @@
%label.label-bold
= s_('Profiles|Connected Accounts')
- %p= s_('Profiles|Click on icon to activate signin with one of the following services')
+ %p= s_('Profiles|Select a service to sign in with.')
- providers.each do |provider|
- unlink_allowed = unlink_provider_allowed?(provider)
- link_allowed = link_provider_allowed?(provider)
diff --git a/app/views/projects/_bitbucket_import_modal.html.haml b/app/views/projects/_bitbucket_import_modal.html.haml
deleted file mode 100644
index 1379a339feb..00000000000
--- a/app/views/projects/_bitbucket_import_modal.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-#bitbucket_import_modal.modal
- .modal-dialog
- .modal-content
- .modal-header
- %h3.modal-title Import projects from Bitbucket
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": "true" } &times;
- .modal-body
- To enable importing projects from Bitbucket,
- - if current_user.admin?
- as administrator you need to configure
- - else
- ask your GitLab administrator to configure
- = link_to 'OAuth integration', help_page_path("integration/bitbucket")
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 7e8daea5651..8e6cc6da65d 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -37,7 +37,7 @@
= sprite_icon('admin')
.gl-display-flex.gl-align-items-start.gl-mr-3
- if @notification_setting
- .js-vue-notification-dropdown{ data: { button_size: "small", disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), project_id: @project.id } }
+ .js-vue-notification-dropdown{ data: { button_size: "small", disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), project_id: @project.id, no_flip: 'true' } }
.count-buttons.gl-display-flex.gl-align-items-flex-start
= render 'projects/buttons/star'
@@ -71,11 +71,13 @@
= render_if_exists "projects/home_mirror"
- if @project.badges.present?
- .project-badges.mb-2
+ .project-badges.mb-2{ data: { qa_selector: 'project_badges_content' } }
- @project.badges.each do |badge|
- %a.gl-mr-3{ href: badge.rendered_link_url(@project),
+ - badge_link_url = badge.rendered_link_url(@project)
+ %a.gl-mr-3{ href: badge_link_url,
target: '_blank',
- rel: 'noopener noreferrer' }>
+ rel: 'noopener noreferrer',
+ data: { qa_selector: 'badge_image_link', qa_link_url: badge_link_url } }>
%img.project-badge{ src: badge.rendered_image_url(@project),
'aria-hidden': true,
alt: 'Project badge' }>
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 63f09a065df..aca7b73267b 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -22,13 +22,11 @@
- if bitbucket_import_enabled?
%div
- = link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'how_to_import_link' unless bitbucket_import_configured?}",
- data: { platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do
+ = link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'js-how-to-import-link' unless bitbucket_import_configured?}",
+ data: { modal_title: _("Import projects from Bitbucket"), modal_message: import_from_bitbucket_message, platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do
.gl-button-icon
= sprite_icon('bitbucket')
Bitbucket Cloud
- - unless bitbucket_import_configured?
- = render 'projects/bitbucket_import_modal'
- if bitbucket_server_import_enabled?
%div
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn", data: { platform: 'bitbucket_server', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_server') } do
@@ -82,7 +80,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 gl-show-field-errors js-project-import' } 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_groups_modal.html.haml b/app/views/projects/_invite_groups_modal.html.haml
new file mode 100644
index 00000000000..d16e87d1c26
--- /dev/null
+++ b/app/views/projects/_invite_groups_modal.html.haml
@@ -0,0 +1,3 @@
+- return unless can_admin_project_member?(project)
+
+.js-invite-groups-modal{ data: common_invite_group_modal_data(project, ProjectMember, 'true') }
diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml
index 6b25c5ddaef..4f9af40f711 100644
--- a/app/views/projects/_merge_request_merge_checks_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml
@@ -8,9 +8,7 @@
= form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do
= s_('ProjectSettings|Pipelines must succeed')
.text-secondary
- - configuring_pipelines_for_merge_requests_help_link_url = help_page_path('ci/pipelines/merge_request_pipelines.md', anchor: 'prerequisites')
- - configuring_pipelines_for_merge_requests_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configuring_pipelines_for_merge_requests_help_link_url }
- = s_('ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}').html_safe % { link_start: configuring_pipelines_for_merge_requests_help_link_start, link_end: '</a>'.html_safe }
+ = s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.")
.form-check.mb-2
.gl-pl-6
= form.check_box :allow_merge_on_skipped_pipeline, class: 'form-check-input'
diff --git a/app/views/projects/_merge_request_merge_commit_template.html.haml b/app/views/projects/_merge_request_merge_commit_template.html.haml
index 1c023ae6ceb..502014b7279 100644
--- a/app/views/projects/_merge_request_merge_commit_template.html.haml
+++ b/app/views/projects/_merge_request_merge_commit_template.html.haml
@@ -5,10 +5,10 @@
%p.text-secondary
= s_('ProjectSettings|The commit message used when merging, if the merge method creates a merge commit.')
.mb-2
- - default_merge_commit_template = "Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{title}\n\n%{issues}\n\nSee merge request %{reference}"
- = form.text_area :merge_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: default_merge_commit_template
+ = form.text_area :merge_commit_template_or_default, class: 'form-control gl-form-input', rows: 8, maxlength: Project::MAX_COMMIT_TEMPLATE_LENGTH, placeholder: s_('ProjectSettings|The default template will be applied on save.')
%p.form-text.text-muted
- = s_('ProjectSettings|Maximum 500 characters.')
+ = s_('ProjectSettings|Leave empty to use default template.')
+ = sprintf(s_('ProjectSettings|Maximum %{maxLength} characters.'), { maxLength: Project::MAX_COMMIT_TEMPLATE_LENGTH })
- configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_merge_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_merge_commit_message_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_merge_commit_message_help_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/_merge_request_merge_method_settings.html.haml b/app/views/projects/_merge_request_merge_method_settings.html.haml
index b0e3bda2b4f..778586a592e 100644
--- a/app/views/projects/_merge_request_merge_method_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_method_settings.html.haml
@@ -2,7 +2,9 @@
.form-group
%b= s_('ProjectSettings|Merge method')
- %p.text-secondary= s_('ProjectSettings|Determine what happens to the commit history when you merge a merge request.')
+ %p.text-secondary
+ = s_('ProjectSettings|Determine what happens to the commit history when you merge a merge request.')
+ = link_to s_('ProjectSettings|Learn about commit history.'), help_page_path('user/project/merge_requests/commits.md'), target: '_blank', rel: 'noopener noreferrer'
.form-check.mb-2
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio form-check-input"
= label_tag :project_merge_method_merge, class: 'form-check-label' do
@@ -33,4 +35,4 @@
= s_('ProjectSettings|When there is a merge conflict, the user is given the option to rebase.')
%div
= s_('ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts.')
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/merge_trains.md', anchor: 'enable-merge-trains'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to s_('ProjectSettings|What are merge trains?'), help_page_path('ci/pipelines/merge_trains.md', anchor: 'enable-merge-trains'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/_merge_request_merge_suggestions_settings.html.haml b/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
index 9ed21593203..eb2fc05686c 100644
--- a/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
@@ -7,6 +7,8 @@
.mb-2
= form.text_field :suggestion_commit_message, class: 'form-control mb-2', placeholder: Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
%p.form-text.text-muted
+ = s_('ProjectSettings|Leave empty to use default template.')
+ = sprintf(s_('ProjectSettings|Maximum %{maxLength} characters.'), { maxLength: Project::MAX_SUGGESTIONS_TEMPLATE_LENGTH })
- configure_the_commit_message_for_applied_suggestions_help_link_url = help_page_path('user/project/merge_requests/reviews/suggestions.md', anchor: 'configure-the-commit-message-for-applied-suggestions')
- configure_the_commit_message_for_applied_suggestions_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_commit_message_for_applied_suggestions_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_commit_message_for_applied_suggestions_help_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/_merge_request_squash_commit_template.html.haml b/app/views/projects/_merge_request_squash_commit_template.html.haml
index be1d78154c6..4d1b89bea83 100644
--- a/app/views/projects/_merge_request_squash_commit_template.html.haml
+++ b/app/views/projects/_merge_request_squash_commit_template.html.haml
@@ -5,9 +5,10 @@
%p.text-secondary
= s_('ProjectSettings|The commit message used when squashing commits.')
.mb-2
- = form.text_area :squash_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: '%{title}'
+ = form.text_area :squash_commit_template_or_default, class: 'form-control gl-form-input', rows: 8, maxlength: Project::MAX_COMMIT_TEMPLATE_LENGTH, placeholder: s_('ProjectSettings|The default template will be applied on save.')
%p.form-text.text-muted
- = s_('ProjectSettings|Maximum 500 characters.')
+ = s_('ProjectSettings|Leave empty to use default template.')
+ = sprintf(s_('ProjectSettings|Maximum %{maxLength} characters.'), { maxLength: Project::MAX_COMMIT_TEMPLATE_LENGTH })
- configure_the_squash_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_squash_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_squash_commit_message_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_squash_commit_message_help_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 0b5da84e4e3..966587a9210 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -46,6 +46,8 @@
= s_('ProjectsNew|Project description %{tag_start}(optional)%{tag_end}').html_safe % { tag_start: '<span>'.html_safe, tag_end: '</span>'.html_safe }
= f.text_area :description, placeholder: s_('ProjectsNew|Description format'), class: "form-control gl-form-input", rows: 3, maxlength: 250, data: { track_label: "#{track_label}", track_action: "activate_form_input", track_property: "project_description", track_value: "" }
+.js-deployment-target-select
+
= f.label :visibility_level, class: 'label-bold' do
= s_('ProjectsNew|Visibility Level')
= link_to sprite_icon('question-o'), help_page_path('public_access/public_access'), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
@@ -63,44 +65,14 @@
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
- experiment(:new_project_sast_enabled, user: current_user) do |e|
- - e.try(:candidate) do
- .form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
- = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- .form-text.text-muted
- = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
- = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
- - e.try(:unchecked_candidate) do
- .form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
- = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- .form-text.text-muted
- = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
- = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
- - e.try(:free_indicator) do
- .form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
- = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- = gl_badge_tag _('Free'), variant: :info, size: :sm
- .form-text.text-muted
- = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
- = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
- - e.try(:unchecked_free_indicator) do
- .form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
- = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- = gl_badge_tag _('Free'), variant: :info, size: :sm
- .form-text.text-muted
- = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
- = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
+ - e.variant(:candidate) do
+ = render 'new_project_initialize_with_sast', experiment_name: e.name, track_label: track_label, checked: true, with_free_badge: false
+ - e.variant(:unchecked_candidate) do
+ = render 'new_project_initialize_with_sast', experiment_name: e.name, track_label: track_label, checked: false, with_free_badge: false
+ - e.variant(:free_indicator) do
+ = render 'new_project_initialize_with_sast', experiment_name: e.name, track_label: track_label, checked: true, with_free_badge: true
+ - e.variant(:unchecked_free_indicator) do
+ = render 'new_project_initialize_with_sast', experiment_name: e.name, track_label: track_label, checked: false, with_free_badge: true
= f.submit _('Create project'), class: "btn gl-button btn-confirm", data: { track_label: "#{track_label}", track_action: "click_button", track_property: "create_project", track_value: "" }
= link_to _('Cancel'), dashboard_projects_path, class: 'btn gl-button btn-default btn-cancel', data: { track_label: "#{track_label}", track_action: "click_button", track_property: "cancel", track_value: "" }
diff --git a/app/views/projects/_new_project_initialize_with_sast.html.haml b/app/views/projects/_new_project_initialize_with_sast.html.haml
new file mode 100644
index 00000000000..ec12abbf789
--- /dev/null
+++ b/app/views/projects/_new_project_initialize_with_sast.html.haml
@@ -0,0 +1,16 @@
+- experiment_name = local_assigns.fetch(:experiment_name)
+- track_label = local_assigns.fetch(:track_label)
+
+- with_free_badge = local_assigns.fetch(:with_free_badge, false)
+- checked = local_assigns.fetch(:checked, false)
+
+.form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_sast]', '1', checked, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: experiment_name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ - if with_free_badge
+ = gl_badge_tag _('Free'), variant: :info, size: :sm
+ .form-text.text-muted
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: experiment_name }
diff --git a/app/views/projects/_remove.html.haml b/app/views/projects/_remove.html.haml
index 815e76ebcb9..d0dfbb89ca7 100644
--- a/app/views/projects/_remove.html.haml
+++ b/app/views/projects/_remove.html.haml
@@ -1,6 +1,7 @@
- return unless can?(current_user, :remove_project, project)
- merge_requests_count = Projects::AllMergeRequestsCountService.new(project).count
- issues_count = Projects::AllIssuesCountService.new(project).count
+- forks_count = Projects::ForksCountService.new(project).count
.sub-section
%h4.danger-title= _('Delete project')
@@ -9,4 +10,4 @@
= link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
%p
%strong= _('Deleted projects cannot be restored!')
- #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project), is_fork: project.forked?.to_s, issues_count: number_with_delimiter(issues_count), merge_requests_count: number_with_delimiter(merge_requests_count), forks_count: number_with_delimiter(project.forks_count), stars_count: number_with_delimiter(project.star_count) } }
+ #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project), is_fork: project.forked?.to_s, issues_count: number_with_delimiter(issues_count), merge_requests_count: number_with_delimiter(merge_requests_count), forks_count: number_with_delimiter(forks_count), stars_count: number_with_delimiter(project.star_count) } }
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 9fa65f27651..919cafe7ce8 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -1,6 +1,7 @@
= render "projects/blob/breadcrumb", blob: blob
- project = @project.present(current_user: current_user)
- ref = local_assigns[:ref] || @ref
+- expanded = params[:expanded].present?
.info-well.d-none.d-sm-block
.well-segment
@@ -13,7 +14,7 @@
#blob-content-holder.blob-content-holder
- 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)
+ - if Feature.enabled?(:refactor_blob_viewer, @project, default_enabled: :yaml) && !expanded
-# 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,
diff --git a/app/views/projects/blob/_header_content.html.haml b/app/views/projects/blob/_header_content.html.haml
index 95a5d63e07f..9cd2f583fdd 100644
--- a/app/views/projects/blob/_header_content.html.haml
+++ b/app/views/projects/blob/_header_content.html.haml
@@ -9,9 +9,9 @@
= copy_file_path_button(blob.path)
%small.mr-1
- - if blob.mode == Blob::MODE_SYMLINK
+ - if blob.symlink?
= _('Symbolic link') << ' ·'
= number_to_human_size(blob.raw_size)
- if blob.stored_externally? && blob.external_storage == :lfs
- %span.badge.label-lfs.gl-mr-2 LFS
+ = gl_badge_tag(_('LFS'), variant: :neutral)
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 2121d15643c..96acd863a4c 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -16,7 +16,9 @@
class: 'gl-button btn btn-danger btn-danger-secondary has-tooltip qa-delete-merged-branches',
title: s_("Branches|Delete all branches that are merged into '%{default_branch}'") % { default_branch: @project.repository.root_ref },
method: :delete,
+ aria: { label: s_('Branches|Delete merged branches') },
data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'),
+ confirm_btn_variant: 'danger',
container: 'body' } do
= s_('Branches|Delete merged branches')
= link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml
index 4463220e951..b48e69c2c23 100644
--- a/app/views/projects/ci/lints/show.html.haml
+++ b/app/views/projects/ci/lints/show.html.haml
@@ -3,4 +3,4 @@
%h4.pt-3.pb-3= _("Validate your GitLab CI configuration")
-#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') , lint_help_page_path: help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax') } }
+#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'simulate-a-pipeline') , lint_help_page_path: help_page_path('ci/lint', anchor: 'check-cicd-syntax') } }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 62ed50f5a0c..4442f62b221 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -34,7 +34,7 @@
&middot;
= commit.short_id
- if commit.description? && collapsible
- %button.gl-button.btn.btn-default.button-ellipsis-horizontal.btn-sm.gl-ml-2.text-expander.js-toggle-button
+ %button.gl-button.btn.btn-default.button-ellipsis-horizontal.btn-sm.gl-ml-2.text-expander.js-toggle-button{ data: { toggle: 'tooltip', container: 'body' }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") } }
= sprite_icon('ellipsis_h', size: 12)
.committer
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 8ca41941e07..12d3f28dc20 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -13,4 +13,4 @@
= html_escape(_("Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision.")) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
.prepend-top-20
- #js-compare-selector{ data: project_compare_selector_data(@project, @merge_request, params) }
+ #js-compare-selector{ data: project_compare_selector_data(@project, @merge_request, @compare_params) }
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index aa9a3ea61f7..f32514141c5 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,5 +1,6 @@
- breadcrumb_title _("General Settings")
- page_title _("General")
+- add_page_specific_style 'page_bundles/projects_edit'
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
- reduce_visibility_form_id = 'reduce-visibility-form'
@@ -40,7 +41,7 @@
= render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
-%section.settings.no-animate{ class: ('expanded' if expanded) }
+%section.settings.no-animate{ class: ('expanded' if expanded), data: { qa_selector: 'badges_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
@@ -62,7 +63,7 @@
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
- %p= _('Housekeeping, export, path, transfer, remove, archive.')
+ %p= s_('ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete.')
.settings-content
.sub-section
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 72ccc8d830c..2b05ffe3eea 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -1,4 +1,5 @@
- page_title _("Environments")
+- add_page_specific_style 'page_bundles/environments'
- if Feature.enabled?(:new_environments_table)
#environments-table{ data: { endpoint: project_environments_path(@project, format: :json),
@@ -9,7 +10,6 @@
"project-path" => @project.full_path,
"default-branch-name" => @project.default_branch_or_main } }
- else
- - add_page_specific_style 'page_bundles/environments'
#environments-list-view{ data: { environments_data: environments_list_data,
"can-read-environment" => can?(current_user, :read_environment, @project).to_s,
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index b123b81b89c..6d60ef92d86 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -14,7 +14,7 @@
.text-content
%h4.state-title
= _("You don't have any deployments right now.")
- %p.blank-state-text
+ %p
= html_escape(_("Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
.text-center
= link_to _("Read more"), help_page_path("ci/environments/index.md"), class: "gl-button btn btn-confirm"
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index 7d696a988d4..4df109dbb61 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -14,7 +14,7 @@
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mr-3'
= render 'shared/web_hooks/test_button', hook: @hook
- = link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn gl-button btn-danger float-right', data: { confirm: _('Are you sure?') }
+ = link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn gl-button btn-danger float-right', aria: { label: s_('Webhooks|Delete webhook') }, data: { confirm: s_('Webhooks|Are you sure you want to delete this project hook?'), confirm_btn_variant: 'danger' }
%hr
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index 77c715aa376..b021087c394 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -12,8 +12,8 @@
:preserve
#{h(@project.import_state.last_error)}
-= form_for @project, url: project_import_path(@project), method: :post do |f|
+= form_for @project, url: project_import_path(@project), method: :post, html: { class: 'js-project-import' } do |f|
= render "shared/import_form", f: f
.form-actions
- = f.submit 'Start import', class: "gl-button btn btn-confirm"
+ = f.submit 'Start import', class: "gl-button btn btn-confirm", data: { disable_with: false }
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 1cf0551535b..8d6c0e29b6a 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -6,8 +6,8 @@
- create_mr_text = can_create_confidential_merge_request? ? _('Create confidential merge request') : _('Create merge request')
- can_create_path = can_create_branch_project_issue_path(@project, @issue)
- - create_mr_path = create_merge_request_project_issue_path(@project, @issue, branch_name: @issue.to_branch_name, ref: @project.default_branch)
- - create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid)
+ - create_mr_path = project_new_merge_request_path(@project, merge_request: { source_branch: @issue.to_branch_name, target_branch: @project.default_branch })
+ - create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid, format: :json)
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
.create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }
diff --git a/app/views/projects/learn_gitlab/index.html.haml b/app/views/projects/learn_gitlab/index.html.haml
index 6bca145dc18..9924b172875 100644
--- a/app/views/projects/learn_gitlab/index.html.haml
+++ b/app/views/projects/learn_gitlab/index.html.haml
@@ -2,7 +2,6 @@
- page_title _("Learn GitLab")
- add_page_specific_style 'page_bundles/learn_gitlab'
- data = learn_gitlab_data(@project)
-- invite_members_open = session.delete(:confetti_post_signup)
= render 'projects/invite_members_modal', project: @project
@@ -10,4 +9,4 @@
- e.control do
#js-learn-gitlab-app{ data: data }
- e.candidate do
- #js-learn-gitlab-app{ data: data.merge(invite_members_open: invite_members_open) }
+ #js-learn-gitlab-app{ data: data.merge(invite_members: 'true') }
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 9d5d1de1005..f2a271da771 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -2,7 +2,7 @@
- can_update_merge_request = can?(current_user, :update_merge_request, @merge_request)
- can_reopen_merge_request = can?(current_user, :reopen_merge_request, @merge_request)
- are_close_and_open_buttons_hidden = merge_request_button_hidden?(@merge_request, true) && merge_request_button_hidden?(@merge_request, false)
-- cache_key = [@project, @merge_request, can_update_merge_request, can_reopen_merge_request, are_close_and_open_buttons_hidden]
+- cache_key = [@project, @merge_request, can_update_merge_request, can_reopen_merge_request, are_close_and_open_buttons_hidden, current_user&.preferred_language]
= cache(cache_key, expires_in: 1.day) do
- if @merge_request.closed_or_merged_without_fork?
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index a0e78b7570a..a7667d03138 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -49,8 +49,6 @@
= render "projects/merge_requests/tabs/pane", id: "notes", class: "notes voting_notes" do
.row
%section.col-md-12
- -# haml-lint:disable InlineJavaScript
- %script.js-notes-data{ type: "application/json" }= initial_notes_data(true).to_json.html_safe
.issuable-discussion.js-vue-notes-event
- if @merge_request.description.present?
.detail-page-description
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
index c88ea313287..e3f46d601a3 100644
--- a/app/views/projects/no_repo.html.haml
+++ b/app/views/projects/no_repo.html.haml
@@ -23,4 +23,4 @@
- if can? current_user, :remove_project, @project
.prepend-top-20
- = link_to _('Delete project'), project_path(@project), data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn gl-button btn-danger float-right"
+ = link_to _('Delete project'), project_path(@project), data: { confirm: remove_project_message(@project), confirm_btn_variant: 'danger' }, aria: { label: _('Delete project') }, method: :delete, class: "btn gl-button btn-danger float-right"
diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml
index d11b61466e2..31c14aaad50 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -6,36 +6,6 @@
- elsif note.contributor?
%span{ class: 'note-role user-access-role has-tooltip', title: _("This user has previously committed to the %{name} project.") % { name: note.project_name } }= _("Contributor")
-- if note.resolvable?
- - can_resolve = can?(current_user, :resolve_note, note)
- %resolve-btn{ "project-path" => project_path(note.project),
- "discussion-id" => note.discussion_id(@noteable),
- ":note-id" => note.id,
- ":resolved" => note.resolved?,
- ":can-resolve" => can_resolve,
- ":author-name" => "'#{j(note.author.name)}'",
- "author-avatar" => note.author.avatar_url,
- ":note-truncated" => "'#{j(truncate(note.note, length: 17))}'",
- ":resolved-by" => "'#{j(note.resolved_by.try(:name))}'",
- "v-show" => "#{can_resolve || note.resolved?}",
- "inline-template" => true,
- "ref" => "note_#{note.id}" }
-
- .note-actions-item
- %button.note-action-button.line-resolve-btn{ type: "button",
- class: ("is-disabled" unless can_resolve),
- ":class" => "{ 'is-active': isResolved }",
- ":aria-label" => "buttonText",
- "@click" => "resolve",
- ":title" => "buttonText",
- ":ref" => "'button'" }
-
- %div
- %template{ 'v-if' => 'isResolved' }
- = render 'shared/icons/icon_status_success_solid.svg'
- %template{ 'v-else' => '' }
- = render 'shared/icons/icon_resolve_discussion.svg'
-
- if can?(current_user, :award_emoji, note)
- if note.emoji_awardable?
.note-actions-item
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index c81a3683e90..5385c6a4cc6 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -13,6 +13,6 @@
= _('Report abuse to admin')
- if note_editable
%li
- = link_to note_url(note), method: :delete, data: { confirm: 'Are you sure you want to delete this comment?', qa_selector: 'delete_comment_button' }, remote: true, class: 'js-note-delete' do
+ = link_to note_url(note), method: :delete, data: { confirm: _('Are you sure you want to delete this comment?'), confirm_btn_variant: 'danger', qa_selector: 'delete_comment_button' }, aria: { label: _('Delete comment') }, remote: true, class: 'js-note-delete' do
%span.text-danger
= _('Delete comment')
diff --git a/app/views/projects/pages/_pages_settings.html.haml b/app/views/projects/pages/_pages_settings.html.haml
index 2db44528d51..15fb5755b61 100644
--- a/app/views/projects/pages/_pages_settings.html.haml
+++ b/app/views/projects/pages/_pages_settings.html.haml
@@ -1,11 +1,12 @@
+- can_edit_max_page_size=can?(current_user, :update_max_pages_size)
+- can_enforce_https_only=Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
+
+- return unless can_edit_max_page_size || can_enforce_https_only
= form_for @project, url: project_pages_path(@project), html: { class: 'inline', title: pages_https_only_title } do |f|
- - if can?(current_user, :update_max_pages_size)
+ - if can_edit_max_page_size
= render_if_exists 'shared/pages/max_pages_size_input', form: f
- .gl-mt-3
- = f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
-
- - if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
+ - if can_enforce_https_only
.form-group
.form-check
= f.check_box :pages_https_only, class: 'form-check-input', disabled: pages_https_only_disabled?
@@ -17,5 +18,5 @@
%p
= s_("GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}").html_safe % { docs_link_start: docs_link_start, link_end: link_end }
- .gl-mt-3
- = f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
+ .gl-mt-3
+ = f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
diff --git a/app/views/projects/pages_domains/_dns.html.haml b/app/views/projects/pages_domains/_dns.html.haml
index 2732463020e..6943469aaac 100644
--- a/app/views/projects/pages_domains/_dns.html.haml
+++ b/app/views/projects/pages_domains/_dns.html.haml
@@ -20,10 +20,9 @@
= _("Verification status")
.col-sm-10
.status-badge
- - text, status = domain_presenter.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success']
- .badge{ class: status }
- = text
- = link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, domain_presenter), method: :post, class: "gl-button btn btn-default has-tooltip", title: _("Retry verification")
+ - text, status = domain_presenter.unverified? ? [_('Unverified'), :danger] : [_('Verified'), :success]
+ = gl_badge_tag text, variant: status
+ = link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, domain_presenter), method: :post, class: "gl-ml-2 gl-button btn btn-default has-tooltip", title: _("Retry verification")
.input-group
= text_field_tag :domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
.input-group-append
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index f6a0638ccd0..908de68f825 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -36,5 +36,5 @@
= link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-button btn-default btn-icon' do
= sprite_icon('pencil')
- if can?(current_user, :admin_pipeline_schedule, pipeline_schedule)
- = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn gl-button btn-danger btn-icon', data: { confirm: _("Are you sure you want to delete this pipeline schedule?") } do
+ = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn gl-button btn-danger btn-icon', aria: { label: _('Delete pipeline schedule') }, data: { confirm: _("Are you sure you want to delete this pipeline schedule?"), confirm_btn_variant: 'danger' } do
= sprite_icon('remove')
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 13a77dbf2fd..4e93d7a04e7 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -38,7 +38,7 @@
- popover_content_text = _('Learn more about Auto DevOps')
= gl_badge_tag s_('Pipelines|Auto DevOps'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-autodevops', href: "#", tabindex: "0", role: "button", data: { container: 'body', toggle: 'popover', placement: 'top', html: 'true', triggers: 'focus', title: "<div class='gl-font-weight-normal gl-line-height-normal'>#{popover_title_text}</div>", content: "<a href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>" } }
- if @pipeline.detached_merge_request_pipeline?
- = gl_badge_tag s_('Pipelines|detached'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-mergerequest has-tooltip', title: _('Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.') }
+ = gl_badge_tag s_('Pipelines|detached'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-mergerequest has-tooltip', title: _('Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines.') }
- if @pipeline.stuck?
= gl_badge_tag s_('Pipelines|stuck'), { variant: :warning, size: :sm }, { class: 'js-pipeline-url-stuck has-tooltip' }
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index d654d0e04d7..70815dbe7a7 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -26,6 +26,7 @@
- lint_link_start = '<a href="%{url}" class="gl-text-blue-500!">'.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: { deprecated_keywords_doc_path: help_page_path('ci/yaml/index.md', anchor: 'deprecated-keywords'), full_path: @project.full_path, pipeline_iid: @pipeline.iid } }
= render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { 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 12b2b33e364..220e44679cd 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -21,6 +21,7 @@
.js-import-a-project-modal{ data: { project_id: @project.id, project_name: @project.name } }
- 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') } }
+ = render 'projects/invite_groups_modal', project: @project
- if can_admin_project_member?(@project)
.js-invite-members-trigger{ data: { variant: 'success',
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
@@ -38,7 +39,7 @@
%p
= html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe }
- - if Feature.disabled?(:invite_members_group_modal, @project.group) && can?(current_user, :admin_project_member, @project) && project_can_be_shared?
+ - if Feature.disabled?(:invite_members_group_modal, @project.group, default_enabled: :yaml) && can?(current_user, :admin_project_member, @project) && project_can_be_shared?
- if !membership_locked? && @project.allowed_to_share_with_group?
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
@@ -61,7 +62,7 @@
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 }
+ groups_select_tag_data: { min_access_level: Gitlab::Access::GUEST, skip_groups: @skip_groups }
- elsif !membership_locked?
.invite-member
= render 'shared/members/invite_member',
@@ -78,7 +79,7 @@
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 }
+ groups_select_tag_data: { min_access_level: Gitlab::Access::GUEST, 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,
diff --git a/app/views/projects/protected_branches/shared/_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
index f3bb2a66a4c..c9e964b2984 100644
--- a/app/views/projects/protected_branches/shared/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
@@ -20,4 +20,4 @@
- if can_admin_project
%td
- = link_to s_('ProtectedBranch|Unprotect'), [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], data: { confirm: s_('ProtectedBranch|Branch will be writable for developers. Are you sure?') }, method: :delete, class: "btn gl-button btn-warning"
+ = link_to s_('ProtectedBranch|Unprotect'), [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], aria: { label: s_('ProtectedBranch|Unprotect branch') }, data: { confirm: s_('ProtectedBranch|Branch will be writable for developers. Are you sure?'), confirm_btn_variant: 'danger' }, method: :delete, class: "btn gl-button btn-warning"
diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml
index fe63f921780..8f5ce798dc7 100644
--- a/app/views/projects/protected_tags/shared/_index.html.haml
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -11,7 +11,7 @@
= link_to s_("ProtectedTag|What are protected tags?"), help_page_path("user/project/protected_tags")
.settings-content
%p
- = s_("ProtectedTag|By default, protected branches restrict who can modify the tag.")
+ = s_("ProtectedTag|By default, protected tags restrict who can modify the tag.")
= link_to s_("ProtectedTag|Learn more."), help_page_path("user/project/protected_tags", anchor: "who-can-modify-a-protected-tag")
- if can? current_user, :admin_project, @project
diff --git a/app/views/projects/protected_tags/shared/_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
index b312a09aadd..ed5b5b17942 100644
--- a/app/views/projects/protected_tags/shared/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
@@ -19,4 +19,4 @@
- if can? current_user, :admin_project, @project
%td
- = link_to 'Unprotect', [@project, protected_tag, { update_section: 'js-protected-tags-settings' }], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'gl-button btn btn-danger-secondary'
+ = link_to 'Unprotect', [@project, protected_tag, { update_section: 'js-protected-tags-settings' }], aria: { label: s_('ProtectedTags|Unprotect tag') }, data: { confirm: 'Tag will be writable for developers. Are you sure?', confirm_btn_variant: 'danger' }, method: :delete, class: 'gl-button btn btn-danger-secondary'
diff --git a/app/views/projects/readme_templates/default.md.tt b/app/views/projects/readme_templates/default.md.tt
new file mode 100644
index 00000000000..d5fef29b290
--- /dev/null
+++ b/app/views/projects/readme_templates/default.md.tt
@@ -0,0 +1,93 @@
+# <%= project.name %>
+
+<%= project.description %>
+
+
+## Getting started
+
+To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+
+Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
+
+## Add your files
+
+- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
+- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+
+```
+cd existing_repo
+git remote add origin <%= project.http_url_to_repo %>
+git branch -M <%= project.default_branch_or_main %>
+git push -uf origin <%= project.default_branch_or_main %>
+```
+
+## Integrate with your tools
+
+- [ ] [Set up project integrations](<%= project_settings_integrations_url(project) %>)
+
+## Collaborate with your team
+
+- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
+- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
+- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
+- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
+- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
+
+## Test and Deploy
+
+Use the built-in continuous integration in GitLab.
+
+- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
+- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
+- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
+- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
+- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
+
+***
+
+# Editing this README
+
+When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
+
+## Suggestions for a good README
+Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
+
+## Name
+Choose a self-explaining name for your project.
+
+## Description
+Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
+
+## Badges
+On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
+
+## Visuals
+Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
+
+## Installation
+Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
+
+## Usage
+Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
+
+## Support
+Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+
+## Roadmap
+If you have ideas for releases in the future, it is a good idea to list them in the README.
+
+## Contributing
+State if you are open to contributions and what your requirements are for accepting them.
+
+For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
+
+You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
+
+## Authors and acknowledgment
+Show your appreciation to those who have contributed to the project.
+
+## License
+For open source projects, say how it is licensed.
+
+## Project status
+If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
diff --git a/app/views/projects/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml
index e8ac572df1d..df14bd09a4d 100644
--- a/app/views/projects/security/configuration/show.html.haml
+++ b/app/views/projects/security/configuration/show.html.haml
@@ -2,4 +2,6 @@
- page_title _("Security Configuration")
- @content_class = "limit-container-width" unless fluid_layout
-#js-security-configuration-static{ data: { project_path: @project.full_path, upgrade_path: security_upgrade_path } }
+#js-security-configuration{ data: { **@configuration.to_html_data_attribute,
+ upgrade_path: security_upgrade_path,
+ project_full_path: @project.full_path } }
diff --git a/app/views/projects/serverless/functions/index.html.haml b/app/views/projects/serverless/functions/index.html.haml
index b17e6df1e8e..03a1b0ee7bb 100644
--- a/app/views/projects/serverless/functions/index.html.haml
+++ b/app/views/projects/serverless/functions/index.html.haml
@@ -10,8 +10,6 @@
help_path: help_page_path('user/project/clusters/serverless/index'),
empty_image_path: image_path('illustrations/empty-state/empty-serverless-lg.svg') } }
-.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
-
.js-serverless-functions-notice
.flash-container
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 419dd827e49..65b93dc930a 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -6,13 +6,7 @@
- if integration.operating?
= sprite_icon('check', css_class: 'gl-text-green-500')
-- if vue_integration_form_enabled?
- = render 'shared/integration_settings', integration: integration
-- else
- = form_for(integration, as: :service, url: scoped_integration_path(integration, project: @project, group: @group), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_integration_path(@project, integration), testid: 'integration-form' } }) do |form|
- = render 'shared/integration_settings', form: form, integration: integration
- %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referer }
-
+= render 'shared/integration_settings', integration: integration
- if lookup_context.template_exists?('show', "projects/services/#{integration.to_param}", true)
%hr
= render "projects/services/#{integration.to_param}/show", integration: integration
diff --git a/app/views/projects/settings/_archive.html.haml b/app/views/projects/settings/_archive.html.haml
index be9bd3dfc01..12cb1c3574a 100644
--- a/app/views/projects/settings/_archive.html.haml
+++ b/app/views/projects/settings/_archive.html.haml
@@ -10,11 +10,13 @@
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'unarchiving-a-project') }
%p= _("Unarchiving the project will restore its members' ability to make changes to it. The repository can be committed to, and issues, comments, and other entities can be created. %{strong_start}Once active, this project shows up in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
= link_to _('Unarchive project'), unarchive_project_path(@project),
+ aria: { label: _('Unarchive project') },
data: { confirm: _("Are you sure that you want to unarchive this project?"), qa_selector: 'unarchive_project_link' },
method: :post, class: "gl-button btn btn-confirm"
- else
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'archiving-a-project') }
%p= _("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}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
= link_to _('Archive project'), archive_project_path(@project),
- data: { confirm: _("Are you sure that you want to archive this project?"), qa_selector: 'archive_project_link' },
+ aria: { label: _('Archive project') },
+ data: { confirm: _("Are you sure that you want to archive this project?"), qa_selector: 'archive_project_link', 'confirm-btn-variant': 'warning' },
method: :post, class: "gl-button btn btn-warning"
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index 0f4d5869cea..960b1d67610 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -27,6 +27,7 @@
.row= render_if_exists 'projects/classification_policy_settings', f: f
+ = render 'shared/repository_size_limit_setting_registration_features_cta', form: f
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group.gl-mt-3.gl-mb-3
@@ -36,6 +37,6 @@
= render 'shared/choose_avatar_button', f: f
- if @project.avatar?
%hr
- = link_to _('Remove avatar'), project_avatar_path(@project), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'gl-button btn btn-danger-secondary'
+ = link_to _('Remove avatar'), project_avatar_path(@project), aria: { label: _('Remove avatar') }, data: { confirm: _('Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, class: 'gl-button btn btn-danger-secondary'
= f.submit _('Save changes'), class: "gl-button btn btn-confirm gl-mt-6", data: { qa_selector: 'save_naming_topics_avatar_button' }
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index d3cdfc4f7c9..c70e153ae41 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -94,7 +94,7 @@
.input-group-text /
%p.form-text.text-muted
= html_escape(_('The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable.')) % { regex: '<code>\(\d+.\d+%\)</code>'.html_safe }
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'add-test-coverage-results-to-a-merge-request'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'add-test-coverage-results-to-a-merge-request-deprecated'), target: '_blank', rel: 'noopener noreferrer'
= f.submit _('Save changes'), class: "btn gl-button btn-confirm", data: { qa_selector: 'save_general_pipelines_changes_button' }
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 215448be3d6..4e94c96fdde 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -2,6 +2,21 @@
- page_title _('Monitor Settings')
- breadcrumb_title _('Monitor Settings')
+.gl-alert.gl-alert-danger.gl-mb-5
+ - removal_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/7188'
+ - removal_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: removal_epic_link_url }
+ - opstrace_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/6976'
+ - opstrace_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: opstrace_link_url }
+ - link_end = '</a>'.html_safe
+ .gl-alert-container
+ = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-title
+ = s_('Deprecations|Feature deprecation and removal')
+ .gl-alert-body
+ %p
+ = html_escape(s_('Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
+
= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/tracing'
= render 'projects/settings/operations/error_tracking'
diff --git a/app/views/projects/starrers/index.html.haml b/app/views/projects/starrers/index.html.haml
index 618c4c249a1..fe8a6508dd7 100644
--- a/app/views/projects/starrers/index.html.haml
+++ b/app/views/projects/starrers/index.html.haml
@@ -12,21 +12,13 @@
= search_field_tag :search, params[:search], { placeholder: _('Search'), class: 'form-control', spellcheck: false }
%button.user-search-btn{ type: "submit", "aria-label" => _("Submit search") }
= sprite_icon('search')
- .dropdown.inline.gl-ml-3
- = dropdown_toggle(starrers_sort_options_hash[@sort], { toggle: 'dropdown' })
- %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
- %li.dropdown-header
- = _("Sort by")
- - starrers_sort_options_hash.each do |value, title|
- %li
- = link_to filter_starrer_path(sort: value), class: ("is-active" if @sort == value) do
- = title
+ - starrers_sort_options = starrers_sort_options_hash.map { |value, text| { value: value, text: text, href: filter_starrer_path(sort: value) } }
+ = gl_redirect_listbox_tag starrers_sort_options, @sort, class: 'gl-ml-3', data: { right: true }
- if @starrers.size > 0
.row.gl-mt-3
= render partial: 'starrer', collection: @starrers, as: :starrer
= paginate @starrers, theme: 'gitlab'
+- elsif params[:search].present?
+ .nothing-here-block= _('No starrers matched your search')
- else
- - if params[:search].present?
- .nothing-here-block= _('No starrers matched your search')
- - else
- .nothing-here-block= _('Nobody has starred this repository yet')
+ .nothing-here-block= _('Nobody has starred this repository yet')
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index d3cc409df1d..4a44ad2337f 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -1,4 +1,3 @@
-- @sort ||= sort_value_recently_updated
- page_title s_('TagsPage|Tags')
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_tags_url(@project, rss_url_options), title: "#{@project.name} tags")
@@ -9,7 +8,7 @@
= s_('TagsPage|Tags give the ability to mark specific points in history as being important')
.nav-controls
- #js-tags-sort-dropdown{ data: { filter_tags_path: filter_tags_path, sort_options: tags_sort_options_hash.to_json } }
+ #js-tags-sort-dropdown{ data: { filter_tags_path: filter_tags_path(search: @search, sort: @sort), sort_options: tags_sort_options_hash.to_json } }
= link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn gl-button btn-default btn-icon has-tooltip gl-ml-auto' do
= sprite_icon('rss', css_class: 'gl-icon qa-rss-icon')
- if can?(current_user, :admin_tag, @project)
diff --git a/app/views/projects/tracings/show.html.haml b/app/views/projects/tracings/show.html.haml
index 813908e5a57..a7a02ab917e 100644
--- a/app/views/projects/tracings/show.html.haml
+++ b/app/views/projects/tracings/show.html.haml
@@ -1,6 +1,21 @@
- @content_class = "limit-container-width" unless fluid_layout
- page_title _("Tracing")
+.gl-alert.gl-alert-danger.gl-mb-5
+ - removal_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/7188'
+ - removal_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: removal_epic_link_url }
+ - opstrace_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/6976'
+ - opstrace_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: opstrace_link_url }
+ - link_end = '</a>'.html_safe
+ .gl-alert-container
+ = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-title
+ = s_('Deprecations|Feature deprecation and removal')
+ .gl-alert-body
+ %p
+ = html_escape(s_('Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
+
- if @project.tracing_external_url.present?
%h3.page-title= _('Tracing')
.gl-alert.gl-alert-info.gl-mb-5
diff --git a/app/views/projects/triggers/_trigger.html.haml b/app/views/projects/triggers/_trigger.html.haml
index 081afacdaa6..9d082436aa7 100644
--- a/app/views/projects/triggers/_trigger.html.haml
+++ b/app/views/projects/triggers/_trigger.html.haml
@@ -8,7 +8,7 @@
.label-container
- unless trigger.can_access_project?
- %span.badge.badge-danger.has-tooltip{ title: "Trigger user has insufficient permissions to project" } invalid
+ = gl_badge_tag s_('Trigger|invalid'), { variant: :danger }, { title: s_('Trigger|Trigger user has insufficient permissions to project'), data: { toggle: 'tooltip', container: 'body' } }
%td
- if trigger.description? && trigger.description.length > 15
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index de1135cf928..5b4edc92d1d 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -9,11 +9,10 @@
%a{ href: help_page_path('user/usage_quotas.md'), target: '_blank', rel: 'noopener noreferrer' }
= s_('UsageQuota|Learn more about usage quotas') + '.'
-.top-area.scrolling-tabs-container.inner-page-scroll-tabs
- %ul.nav.nav-tabs.nav-links.scrolling-tabs.separator.js-usage-quota-tabs{ role: 'tablist' }
- %li.nav-item
- %a.nav-link#storage-quota{ data: { toggle: "tab", action: '#storage-quota-tab' }, href: '#storage-quota-tab', 'aria-controls': '#storage-quota-tab', 'aria-selected': 'true' }
- = s_('UsageQuota|Storage')
+= gl_tabs_nav do
+ = gl_tab_link_to '#storage-quota-tab', item_active: true do
+ = s_('UsageQuota|Storage')
+
.tab-content
- .tab-pane#storage-quota-tab
+ .tab-pane.active#storage-quota-tab
#js-project-storage-count-app{ data: { project_path: @project.full_path } }
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index ca2f225a2d8..44dffdbf70a 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -5,6 +5,7 @@
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
+ = render "layouts/bizible"
= render "layouts/google_tag_manager_body"
.row.gl-flex-grow-1
diff --git a/app/views/shared/_confirm_fork_modal.html.haml b/app/views/shared/_confirm_fork_modal.html.haml
deleted file mode 100644
index 96b128eb2ec..00000000000
--- a/app/views/shared/_confirm_fork_modal.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-.modal{ data: { qa_selector: 'confirm_fork_modal'}, id: "modal-confirm-fork-#{type}" }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.page-title= _('Fork project?')
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %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
- = link_to _('Cancel'), '#', class: "btn gl-button btn-default", "data-dismiss" => "modal"
- = link_to _('Fork project'), fork_path, class: 'btn gl-button btn-confirm', data: { qa_selector: 'fork_project_button' }, method: :post
diff --git a/app/views/shared/_gl_toggle.html.haml b/app/views/shared/_gl_toggle.html.haml
new file mode 100644
index 00000000000..afaa6b6df92
--- /dev/null
+++ b/app/views/shared/_gl_toggle.html.haml
@@ -0,0 +1,28 @@
+-# This partial renders a GlToggle root element.
+-# To actually initialize the component, make sure to call the initToggle helper from ~/toggles.
+
+- classes = local_assigns.fetch(:classes)
+- name = local_assigns.fetch(:name, nil)
+- is_checked = local_assigns.fetch(:is_checked, false).to_s
+- disabled = local_assigns.fetch(:disabled, false).to_s
+- is_loading = local_assigns.fetch(:is_loading, false).to_s
+- label = local_assigns.fetch(:label, nil)
+- help = local_assigns.fetch(:help, nil)
+- label_position = local_assigns.fetch(:label_position, nil)
+- data = local_assigns.fetch(:data, {})
+
+%span{ class: classes,
+ data: { name: name,
+ is_checked: is_checked,
+ disabled: disabled,
+ is_loading: is_loading,
+ label: label,
+ help: help,
+ label_position: label_position,
+ **data } }
+
+-# Leverage this block to render a rich help text. To render a plain text help text,
+-# prefer the `help` parameter.
+- if yield.present?
+ .gl-text-secondary.gl-mt-1
+ = yield
diff --git a/app/views/shared/_global_alert.html.haml b/app/views/shared/_global_alert.html.haml
index ea83f5c1656..1eaf21fc568 100644
--- a/app/views/shared/_global_alert.html.haml
+++ b/app/views/shared/_global_alert.html.haml
@@ -8,10 +8,9 @@
- close_button_class = local_assigns.fetch(:close_button_class, nil)
- close_button_data = local_assigns.fetch(:close_button_data, nil)
- icon = icons[variant]
-- alert_root_class = 'gl-alert-layout-limited' if fluid_layout
- alert_container_class = [container_class, @content_class] unless fluid_layout || local_assigns.fetch(:is_contained, false)
-%div{ role: 'alert', class: [alert_root_class, 'gl-alert-max-content', 'gl-alert', "gl-alert-#{variant}", alert_class], data: alert_data }
+%div{ role: 'alert', class: ['gl-alert', "gl-alert-#{variant}", alert_class], data: alert_data }
.gl-alert-container{ class: alert_container_class }
= sprite_icon(icon, size: 16, css_class: "gl-alert-icon#{' gl-alert-icon-no-title' if title.nil?}")
- if dismissible
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index 63468340992..ee8cfe3abb6 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -5,16 +5,18 @@
.row
.form-group.group-name-holder.col-sm-12
= f.label :name, class: 'label-bold' do
- = _("Group name")
- = f.text_field :name, placeholder: _('My Awesome Group'), class: 'js-autofill-group-name form-control input-lg', data: { qa_selector: 'group_name_field' },
+ = s_('Groups|Group name')
+ = f.text_field :name, placeholder: _('My awesome group'), class: 'js-autofill-group-name form-control input-lg', data: { qa_selector: 'group_name_field' },
required: true,
- title: _('Please fill in a descriptive name for your group.'),
+ title: s_('Groups|Enter a descriptive name for your group.'),
autofocus: true
+ .text-muted
+ = s_('Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
.row
.form-group.col-xs-12.col-sm-8
= f.label :path, class: 'label-bold' do
- = _("Group URL")
+ = s_('Groups|Group URL')
.input-group.gl-field-error-anchor
.group-root-path.input-group-prepend.has-tooltip{ title: group_path, :'data-placement' => 'bottom' }
.input-group-text
@@ -29,21 +31,21 @@
maxlength: ::Namespace::URL_MAX_LENGTH,
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
%p.validation-error.gl-field-error.field-validation.hide
- = _("Group path is already taken. We've suggested one that is available.")
- %p.validation-success.gl-field-success.field-validation.hide= _('Group path is available.')
- %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking group URL availability...')
+ = s_('Groups|Group path is unavailable. Path has been replaced with a suggested available path.')
+ %p.validation-success.gl-field-success.field-validation.hide= s_('Groups|Group path is available.')
+ %p.validation-pending.gl-field-error-ignore.field-validation.hide= s_('Groups|Checking group URL availability...')
- if @group.persisted?
.gl-alert.gl-alert-warning.gl-mt-3.gl-mb-3
= sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
- = _('Changing group URL can have unintended side effects.')
+ = s_('Groups|Changing group URL can have unintended side effects.')
= succeed '.' do
- = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank', class: 'gl-link'
+ = link_to s_('Groups|Learn more'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank', class: 'gl-link'
- if @group.persisted?
.row
.form-group.group-name-holder.col-sm-8
= f.label :id, class: 'label-bold' do
- = _("Group ID")
+ = s_('Groups|Group ID')
= f.text_field :id, class: 'form-control', readonly: true
diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml
index 4e3b1e02f16..42a146a4f65 100644
--- a/app/views/shared/_issues.html.haml
+++ b/app/views/shared/_issues.html.haml
@@ -1,7 +1,7 @@
= render 'shared/alerts/positioning_disabled' if @sort == 'relative_position'
- if @issues.to_a.any?
- %ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class, data: { group_full_path: @group&.full_path } }
+ %ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class }
= render partial: 'projects/issues/issue', collection: @issues
= paginate @issues, theme: "gitlab"
- else
diff --git a/app/views/shared/_registration_features_discovery_message.html.haml b/app/views/shared/_registration_features_discovery_message.html.haml
index 8a16d36b836..e5b1ad88a7f 100644
--- a/app/views/shared/_registration_features_discovery_message.html.haml
+++ b/app/views/shared/_registration_features_discovery_message.html.haml
@@ -1,9 +1,8 @@
- feature_title = local_assigns.fetch(:feature_title, s_('RegistrationFeatures|use this feature'))
- registration_features_docs_path = help_page_path('development/service_ping/index.md', anchor: 'registration-features-program')
-- service_ping_settings_path = metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings')
+- registration_features_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: registration_features_docs_path }
%div
%span= sprintf(s_('RegistrationFeatures|Want to %{feature_title} for free?'), { feature_title: feature_title })
- - if Gitlab.ee?
- = link_to s_('RegistrationFeatures|Enable Service Ping and register for this feature.'), service_ping_settings_path
- = sprintf(s_('RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}.') , { linkStart: "<a href=\"#{registration_features_docs_path}\" target=\"_blank\">", label: s_('RegistrationFeatures|Registration Features Program'), linkEnd: "</a>" }).html_safe
+ = render_if_exists 'shared/registration_features_discovery_settings_link'
+ = html_escape(s_('RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}.')) % { link_start: registration_features_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/shared/_repository_size_limit_setting_registration_features_cta.html.haml b/app/views/shared/_repository_size_limit_setting_registration_features_cta.html.haml
new file mode 100644
index 00000000000..9fe1e3087f6
--- /dev/null
+++ b/app/views/shared/_repository_size_limit_setting_registration_features_cta.html.haml
@@ -0,0 +1,9 @@
+- return unless registration_features_can_be_prompted?
+
+.row
+ .form-group.col-md-9
+ = form.label :disabled_repository_size_limit, class: 'label-bold' do
+ = _('Repository size limit (MB)')
+ = form.number_field :disabled_repository_size_limit, value: '', class: 'form-control', disabled: true
+ %span.form-text.text-muted
+ = render 'shared/registration_features_discovery_message'
diff --git a/app/views/shared/_web_ide_button.html.haml b/app/views/shared/_web_ide_button.html.haml
index 82af52cdd59..83646a3c92e 100644
--- a/app/views/shared/_web_ide_button.html.haml
+++ b/app/views/shared/_web_ide_button.html.haml
@@ -1,8 +1,5 @@
- type = blob ? 'blob' : 'tree'
+- button_data = web_ide_button_data({ blob: blob })
+- fork_options = fork_modal_options(@project, @ref, @path, blob)
-.d-inline-block{ data: { options: web_ide_button_data({ blob: blob }).to_json }, id: "js-#{type}-web-ide-link" }
-
-- if show_edit_button?({ blob: blob })
- = render 'shared/confirm_fork_modal', fork_path: fork_and_edit_path(@project, @ref, @path), type: 'edit'
-- if show_web_ide_button?
- = render 'shared/confirm_fork_modal', fork_path: ide_fork_and_edit_path(@project, @ref, @path), type: 'webide'
+.gl-display-inline-block{ data: { options: button_data.merge(fork_options).to_json }, id: "js-#{type}-web-ide-link" }
diff --git a/app/views/shared/access_tokens/_table.html.haml b/app/views/shared/access_tokens/_table.html.haml
index aa579b4a672..7f7dafbe5b0 100644
--- a/app/views/shared/access_tokens/_table.html.haml
+++ b/app/views/shared/access_tokens/_table.html.haml
@@ -56,7 +56,7 @@
%span.token-never-expires-label= _('Never')
- if resource
%td= resource.member(token.user).human_access
- %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: "gl-button btn btn-danger btn-sm float-right qa-revoke-button #{'btn-danger-secondary' unless token.expires?}", data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type } }
+ %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: "gl-button btn btn-danger btn-sm float-right qa-revoke-button #{'btn-danger-secondary' unless token.expires?}", aria: { label: _('Revoke') }, data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type }, 'confirm-btn-variant': 'danger' }
- else
.settings-message.text-center
= no_active_tokens_message
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index 902a0cad483..7289121d9eb 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -38,7 +38,7 @@
%fieldset.form-group.form-check
= f.check_box :write_registry, class: 'form-check-input', data: { qa_selector: 'deploy_token_write_registry_checkbox' }
= f.label :write_registry, 'write_registry', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows read and write access to registry images.')
+ .text-secondary= s_('DeployTokens|Allows write access to registry images.')
- if packages_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
diff --git a/app/views/shared/hook_logs/_content.html.haml b/app/views/shared/hook_logs/_content.html.haml
index d358340814c..95590d6e515 100644
--- a/app/views/shared/hook_logs/_content.html.haml
+++ b/app/views/shared/hook_logs/_content.html.haml
@@ -15,7 +15,7 @@
.gl-alert-container
= sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-content
- %h4.gl-alert-title= _('Internal error occured while delivering this webhook.')
+ %h4.gl-alert-title= _('Internal error occurred while delivering this webhook.')
.gl-alert-body
= _('Error: %{error}') % { error: hook_log.internal_error_message }
diff --git a/app/views/shared/icons/_icon_resolve_discussion.svg b/app/views/shared/icons/_icon_resolve_discussion.svg
deleted file mode 100644
index 845562e9320..00000000000
--- a/app/views/shared/icons/_icon_resolve_discussion.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill-rule="evenodd"/><path d="M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_success_solid.svg b/app/views/shared/icons/_icon_status_success_solid.svg
deleted file mode 100644
index 0aac6d933e1..00000000000
--- a/app/views/shared/icons/_icon_status_success_solid.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_mr_widget_empty_state.svg b/app/views/shared/icons/_mr_widget_empty_state.svg
index 6a811893b2d..a75eee846c9 100644
--- a/app/views/shared/icons/_mr_widget_empty_state.svg
+++ b/app/views/shared/icons/_mr_widget_empty_state.svg
@@ -1 +1 @@
-<svg width="256" height="146" viewBox="0 0 256 146" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>illustration</title><defs><rect id="a" width="178.714" height="115.389" rx="10"/><mask id="d" x="0" y="0" width="178.714" height="115.389" fill="#fff"><use xlink:href="#a"/></mask><path d="M8.796 31.515c.395.047.8.072 1.207.072h23.065c5.536 0 10.003-4.475 10.003-9.994v-11.6C43.07 4.476 38.594 0 33.07 0H10.003C4.467 0 0 4.475 0 9.994v11.6c0 1.248.23 2.444.65 3.547H0v7.414c0 4.094 2.394 5.113 5.342 2.28l3.454-3.32z" id="b"/><mask id="e" x="0" y="0" width="43.071" height="36.437" fill="#fff"><use xlink:href="#b"/></mask><path d="M8.796 31.515c.395.047.8.072 1.207.072h23.065c5.536 0 10.003-4.475 10.003-9.994v-11.6C43.07 4.476 38.594 0 33.07 0H10.003C4.467 0 0 4.475 0 9.994v11.6c0 1.248.23 2.444.65 3.547H0v7.414c0 4.094 2.394 5.113 5.342 2.28l3.454-3.32z" id="c"/><mask id="f" x="0" y="0" width="43.071" height="36.437" fill="#fff"><use xlink:href="#c"/></mask></defs><g fill="none" fill-rule="evenodd"><g transform="translate(0 3.868)" fill="#F9F9F9"><rect x="19.286" width="77.143" height="14.182" rx="7.091"/><rect y="28.364" width="84.857" height="14.182" rx="7.091"/><rect x="133.714" y="42.546" width="122.143" height="14.182" rx="7.091"/><rect x="82.929" y="126.992" width="101.571" height="14.182" rx="7.091"/><rect x="42.429" y="99.273" width="101.571" height="14.182" rx="7.091"/><rect x="19.929" y="70.909" width="225" height="14.182" rx="7.091"/><path d="M98.37 14.182H13.488h13.81a7.098 7.098 0 0 1 7.094 7.09 7.09 7.09 0 0 1-7.094 7.092h-13.81 84.88-23.452a7.098 7.098 0 0 1-7.095-7.09 7.09 7.09 0 0 1 7.096-7.092h23.452zm162 42.545h-75.238 23.452a7.098 7.098 0 0 1 7.095 7.09 7.09 7.09 0 0 1-7.096 7.092h-23.452 75.237-23.453a7.098 7.098 0 0 1-7.095-7.09 7.09 7.09 0 0 1 7.095-7.093h23.452zM103.512 85.09H28.275h23.452a7.098 7.098 0 0 1 7.095 7.092 7.09 7.09 0 0 1-7.095 7.09H28.275h75.237H80.06a7.098 7.098 0 0 1-7.095-7.09 7.09 7.09 0 0 1 7.095-7.09h23.452zm48.215 28.365H76.49 90.3a7.098 7.098 0 0 1 7.093 7.09 7.09 7.09 0 0 1-7.094 7.092H76.49h75.237-33.096a7.098 7.098 0 0 1-7.094-7.09 7.09 7.09 0 0 1 7.095-7.092h33.097z"/></g><g transform="translate(38.57 12.248)"><use stroke="#EEE" mask="url(#d)" stroke-width="8" fill="#FFF" xlink:href="#a"/><path fill="#EEE" d="M2.57 18.694h174.215v2.58H2.57z"/><g transform="translate(21.857 38.678)"><rect fill="#B5A7DD" y=".645" width="3.857" height="1.289" rx=".645"/><rect fill="#EEE" x="9.643" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="46.286" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="25.071" y="14.182" width="9.643" height="2.579" rx="1.289"/><rect fill="#FC6D26" x="34.071" y="7.091" width="9.643" height="2.579" rx="1.289"/><rect fill="#FC6D26" opacity=".5" x="30.857" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="14.182" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="18.643" y="7.091" width="12.857" height="2.579" rx="1.289"/><rect fill="#FC6D26" x="21.857" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="7.091" width="6.429" height="2.579" rx="1.289"/><rect fill="#B5A7DD" y="7.736" width="3.857" height="1.289" rx=".645"/><rect fill="#B5A7DD" y="14.826" width="3.857" height="1.289" rx=".645"/></g><g transform="translate(21.857 59.95)"><rect fill="#B5A7DD" y=".645" width="3.857" height="1.289" rx=".645"/><rect fill="#FC6D26" x="9.643" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="46.286" width="9.643" height="2.579" rx="1.289"/><rect fill="#FC6D26" opacity=".5" x="25.071" y="14.182" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="34.071" y="7.091" width="9.643" height="2.579" rx="1.289"/><rect fill="#FC6D26" x="30.857" width="12.857" height="2.579" rx="1.289"/><rect fill="#FC6D26" x="9.643" y="14.182" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="18.643" y="7.091" width="12.857" height="2.579" rx="1.289"/><rect fill="#FC6D26" opacity=".5" x="21.857" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="7.091" width="6.429" height="2.579" rx="1.289"/><rect fill="#B5A7DD" y="7.736" width="3.857" height="1.289" rx=".645"/><rect fill="#B5A7DD" y="14.826" width="3.857" height="1.289" rx=".645"/></g><g transform="translate(21.857 81.223)"><rect fill="#B5A7DD" y=".645" width="3.857" height="1.289" rx=".645"/><rect fill="#EEE" x="9.643" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="46.286" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="25.071" y="14.182" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="34.071" y="7.091" width="9.643" height="2.579" rx="1.289"/><rect fill="#FC6D26" x="30.857" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="14.182" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="18.643" y="7.091" width="12.857" height="2.579" rx="1.289"/><rect fill="#FC6D26" opacity=".5" x="21.857" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="7.091" width="6.429" height="2.579" rx="1.289"/><rect fill="#B5A7DD" y="7.736" width="3.857" height="1.289" rx=".645"/><rect fill="#B5A7DD" y="14.826" width="3.857" height="1.289" rx=".645"/></g><g transform="translate(100.93 38.033)"><rect fill="#FDE5D8" y=".645" width="3.857" height="1.289" rx=".645"/><rect fill="#EEE" x="9.643" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="46.286" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" opacity=".5" x="25.071" y="14.182" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="34.071" y="7.091" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" opacity=".5" x="30.857" width="12.857" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="9.643" y="14.182" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="18.643" y="7.091" width="12.857" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="21.857" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="7.091" width="6.429" height="2.579" rx="1.289"/><rect fill="#FDE5D8" y="7.736" width="3.857" height="1.289" rx=".645"/><rect fill="#FDE5D8" y="14.826" width="3.857" height="1.289" rx=".645"/><rect fill="#FDE5D8" y="21.917" width="3.857" height="1.289" rx=".645"/><rect fill="#EEE" x="9.643" y="21.273" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="37.286" y="14.182" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" opacity=".5" x="25.071" y="35.455" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="18.643" y="28.364" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="30.857" y="21.273" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="35.455" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="21.857" y="21.273" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="28.364" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="30.857" y="28.364" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="39.857" y="28.364" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="49.5" y="14.182" width="6.429" height="2.579" rx="1.289"/><rect fill="#FDE5D8" y="29.008" width="3.857" height="1.289" rx=".645"/><rect fill="#FDE5D8" y="36.099" width="3.857" height="1.289" rx=".645"/><rect fill="#FDE5D8" y="43.19" width="3.857" height="1.289" rx=".645"/><rect fill="#6B4FBB" x="9.643" y="42.546" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="25.071" y="56.727" width="9.643" height="2.579" rx="1.289"/><rect fill="#6B4FBB" opacity=".5" x="34.071" y="49.636" width="9.643" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="56.727" width="12.857" height="2.579" rx="1.289"/><rect fill="#6B4FBB" x="18.643" y="49.636" width="12.857" height="2.579" rx="1.289"/><rect fill="#EEE" x="21.857" y="42.546" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="46.286" y="49.636" width="6.429" height="2.579" rx="1.289"/><rect fill="#EEE" x="9.643" y="49.636" width="6.429" height="2.579" rx="1.289"/><rect fill="#FDE5D8" y="50.281" width="3.857" height="1.289" rx=".645"/><rect fill="#FDE5D8" y="57.372" width="3.857" height="1.289" rx=".645"/></g></g><g transform="translate(196.07)"><use stroke="#FDE5D8" mask="url(#e)" stroke-width="8" fill="#FFF" xlink:href="#b"/><rect fill="#FDB692" x="9" y="9.025" width="18.643" height="1.934" rx=".967"/><rect fill="#FDB692" x="9" y="14.826" width="25.071" height="1.934" rx=".967"/><rect fill="#FDB692" x="9" y="20.628" width="18.643" height="1.934" rx=".967"/></g><g transform="translate(189 41.256)"><ellipse stroke="#FC6D26" stroke-width="3" fill="#FFF7F4" cx="10.286" cy="9.669" rx="9.643" ry="9.669"/><path d="M.023 9.002a8.352 8.352 0 0 0 7.94-4.308M9 .644c0-.21-.008-.416-.023-.62" stroke="#FC6D26" stroke-width="2"/><path d="M5.045 2.008A10.266 10.266 0 0 0 13.5 6.446c2.112 0 4.076-.638 5.71-1.733" stroke="#FC6D26" stroke-width="2"/><ellipse fill="#FC6D26" cx="6.75" cy="11.281" rx=".964" ry=".967"/><ellipse fill="#FC6D26" cx="13.821" cy="11.281" rx=".964" ry=".967"/></g><g transform="translate(46.93 96.05)"><ellipse stroke="#6B4FBB" stroke-width="3" fill="#F4F1FA" cx="9.643" cy="10.314" rx="9.643" ry="9.669"/><path d="M12.86 4.51h-.005L11.25 2.58 9.645 4.51H9.64L8.036 2.58 6.43 4.51h-.002L4.82 2.58 3.215 4.512h-1.75A9.646 9.646 0 0 1 9.642 0c3.447 0 6.47 1.8 8.176 4.508h-1.75l-1.605-1.93L12.86 4.51z" fill="#6B4FBB"/><ellipse fill="#6B4FBB" cx="6.107" cy="11.281" rx=".964" ry=".967"/><ellipse fill="#6B4FBB" cx="13.179" cy="11.281" rx=".964" ry=".967"/></g><g transform="matrix(-1 0 0 1 56.57 54.794)"><use stroke="#E2DCF2" mask="url(#f)" stroke-width="8" fill="#FFF" xlink:href="#c"/><rect fill="#6B4FBB" opacity=".5" x="15.429" y="9.025" width="18.643" height="1.934" rx=".967"/><rect fill="#6B4FBB" opacity=".5" x="21.857" y="14.826" width="12.214" height="1.934" rx=".967"/><rect fill="#6B4FBB" opacity=".5" x="21.857" y="20.628" width="12.214" height="1.934" rx=".967"/></g></g></svg>
+<svg width="256" height="146" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><mask id="d" x="0" y="0" width="178.7" height="115.4" fill="#FFF"><use xlink:href="#a"/></mask><mask id="e" x="0" y="0" width="43.1" height="36.4" fill="#FFF"><use xlink:href="#b"/></mask><mask id="f" x="0" y="0" width="43.1" height="36.4" fill="#FFF"><use xlink:href="#c"/></mask><path d="M8.8 31.5H33a10 10 0 0 0 10-10V10A10 10 0 0 0 33 0H10A10 10 0 0 0 0 10v11.6c0 1.2.2 2.4.7 3.5H0v7.5c0 4 2.4 5 5.3 2.2l3.5-3.3z" id="b"/><path d="M8.8 31.5H33a10 10 0 0 0 10-10V10A10 10 0 0 0 33 0H10A10 10 0 0 0 0 10v11.6c0 1.2.2 2.4.7 3.5H0v7.5c0 4 2.4 5 5.3 2.2l3.5-3.3z" id="c"/><rect id="a" width="178.7" height="115.4" rx="10"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(0 3.9)" fill="var(--gray-10, #f9f9f9)"><rect x="19.3" width="77.1" height="14.2" rx="7.1"/><rect y="28.4" width="84.9" height="14.2" rx="7.1"/><rect x="133.7" y="42.5" width="122.1" height="14.2" rx="7.1"/><rect x="82.9" y="127" width="101.6" height="14.2" rx="7.1"/><rect x="42.4" y="99.3" width="101.6" height="14.2" rx="7.1"/><rect x="19.9" y="70.9" width="225" height="14.2" rx="7.1"/><path d="M98.4 14.2h-85 13.9a7.1 7.1 0 0 1 7 7 7 7 0 0 1-7 7.2H13.5h84.9-23.5a7.1 7.1 0 0 1-7-7.1 7 7 0 0 1 7-7.1h23.5zm162 42.5H185h23.5a7.1 7.1 0 0 1 7 7.1 7 7 0 0 1-7 7.1H185h75.3-23.5a7.1 7.1 0 0 1-7-7 7 7 0 0 1 7-7.2h23.5zM103.5 85.1H28.3h23.4a7.1 7.1 0 0 1 7.1 7 7 7 0 0 1-7 7.2H28.2h75.2H80a7.1 7.1 0 0 1-7.1-7.1 7 7 0 0 1 7-7.1h23.5zm48.2 28.4H76.5h13.8a7.1 7.1 0 0 1 7 7 7 7 0 0 1-7 7.1H76.5h75.2-33a7.1 7.1 0 0 1-7.2-7 7 7 0 0 1 7.1-7.1h33.1z"/></g><g transform="translate(38.6 12.2)"><use stroke="var(--gray-200, #EEE)" mask="url(#d)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#a"/><path fill="var(--gray-200, #EEE)" d="M2.6 18.7h174.2v2.6H2.6z"/><g fill="var(--gray-100, #EEE)"><g transform="translate(21.9 38.7)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(21.9 60)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect fill="#FC6D26" x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(21.9 81.2)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(101 38)"><g fill="var(--dark-icon-color-purple-3, #6B4FBB)"><rect opacity=".5" x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect opacity=".5" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" width="6.4" height="2.6" rx="1.3"/><rect opacity=".5" x="25.1" y="35.5" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="28.4" width="9.6" height="2.6" rx="1.3"/><rect x="30.9" y="21.3" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="42.5" width="9.6" height="2.6" rx="1.3"/><rect opacity=".5" x="34.1" y="49.6" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="49.6" width="12.9" height="2.6" rx="1.3"/></g><g fill="var(--dark-icon-color-orange-1, #FDE5D8)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/><rect y="21.9" width="3.9" height="1.3" rx=".6"/><rect y="29" width="3.9" height="1.3" rx=".6"/><rect y="36.1" width="3.9" height="1.3" rx=".6"/><rect y="43.2" width="3.9" height="1.3" rx=".6"/><rect y="50.3" width="3.9" height="1.3" rx=".6"/><rect y="57.4" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="21.3" width="9.6" height="2.6" rx="1.3"/><rect x="37.3" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="9.6" y="35.5" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" y="21.3" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="30.9" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="39.9" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="49.5" y="14.2" width="6.4" height="2.6" rx="1.3"/><rect x="25.1" y="56.7" width="9.6" height="2.6" rx="1.3"/><rect x="9.6" y="56.7" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" y="42.5" width="6.4" height="2.6" rx="1.3"/><rect x="46.3" y="49.6" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="49.6" width="6.4" height="2.6" rx="1.3"/></g></g></g><g transform="translate(196)"><use stroke="var(--dark-icon-color-orange-1, #FDE5D8)" mask="url(#e)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#b"/><g fill="var(--dark-icon-color-orange-2, #FDB692)"><rect x="9" y="9" width="18.6" height="1.9" rx="1"/><rect x="9" y="14.8" width="25.1" height="1.9" rx="1"/><rect x="9" y="20.6" width="18.6" height="1.9" rx="1"/></g></g><g transform="translate(189 41.3)"><ellipse stroke="#FC6D26" stroke-width="3" fill="#fde5d8" cx="10.3" cy="9.7" rx="9.6" ry="9.7"/><path d="M0 9a8.4 8.4 0 0 0 8-4.3m1-4V0" stroke="#FC6D26" stroke-width="2"/><path d="M5 2a10.3 10.3 0 0 0 8.5 4.4c2.1 0 4-.6 5.7-1.7" stroke="#FC6D26" stroke-width="2"/><circle fill="#FC6D26" cx="6.8" cy="11.3" r="1"/><circle fill="#FC6D26" cx="13.8" cy="11.3" r="1"/></g><g transform="translate(47 96)"><ellipse stroke="var(--dark-icon-color-purple-3, #6B4FBB)" stroke-width="3" fill="#F4F1FA" cx="9.6" cy="10.3" rx="9.6" ry="9.7"/><path d="m12.9 4.5-1.7-2-1.6 2-1.6-2-1.6 2-1.6-2-1.6 2H1.5A9.6 9.6 0 0 1 9.6 0c3.5 0 6.5 1.8 8.2 4.5h-1.7l-1.6-2-1.6 2z" fill="var(--dark-icon-color-purple-3, #6B4FBB)"/><circle fill="var(--dark-icon-color-purple-3, #6B4FBB)" cx="6.1" cy="11.3" r="1"/><circle fill="var(--dark-icon-color-purple-3, #6B4FBB)" cx="13.2" cy="11.3" r="1"/></g><g transform="matrix(-1 0 0 1 56.6 54.8)" fill="var(--dark-icon-color-purple-2, #b5a8dd)"><use stroke="var(--dark-icon-color-purple-1, #E2DCF2)" mask="url(#f)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#c"/><rect x="15.4" y="9" width="18.6" height="1.9" rx="1"/><rect x="21.9" y="14.8" width="12.2" height="1.9" rx="1"/><rect x="21.9" y="20.6" width="12.2" height="1.9" rx="1"/></g></g></svg>
diff --git a/app/views/shared/integrations/_form.html.haml b/app/views/shared/integrations/_form.html.haml
deleted file mode 100644
index e2457bc0632..00000000000
--- a/app/views/shared/integrations/_form.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- integration = local_assigns.fetch(:integration)
-
-= form_for integration, as: :service, url: scoped_integration_path(integration, group: @group), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration, group: @group), testid: 'integration-form' } } do |form|
- = render 'shared/integration_settings', form: form, integration: integration
diff --git a/app/views/shared/integrations/edit.html.haml b/app/views/shared/integrations/edit.html.haml
index 4ceaedc2a69..f2a31400698 100644
--- a/app/views/shared/integrations/edit.html.haml
+++ b/app/views/shared/integrations/edit.html.haml
@@ -7,7 +7,4 @@
= @integration.title
= render 'shared/integrations/tabs', integration: @integration, active_tab: 'edit' do
- - if vue_integration_form_enabled?
- = render 'shared/integration_settings', integration: @integration
- - else
- = render 'shared/integrations/form', integration: @integration
+ = render 'shared/integration_settings', integration: @integration
diff --git a/app/views/shared/issuable/_assignees.html.haml b/app/views/shared/issuable/_assignees.html.haml
index 196d0417fb8..e6d722cb08d 100644
--- a/app/views/shared/issuable/_assignees.html.haml
+++ b/app/views/shared/issuable/_assignees.html.haml
@@ -3,8 +3,11 @@
- render_count = assignees_rendering_overflow ? max_render - 1 : max_render
- more_assignees_count = issuable.assignees.size - render_count
-- issuable.assignees.take(render_count).each do |assignee| # rubocop: disable CodeReuse/ActiveRecord
- = link_to_member(@project, assignee, name: false, title: _("Assigned to %{name}") % { name: assignee.name})
+- if issuable.instance_of?(MergeRequest) && Feature.enabled?(:mr_attention_requests, default_enabled: :yaml)
+ = render 'shared/issuable/merge_request_assignees', issuable: issuable, count: render_count
+- else
+ - issuable.assignees.take(render_count).each do |assignee| # rubocop: disable CodeReuse/ActiveRecord
+ = link_to_member(@project, assignee, name: false, title: s_("MrList|Assigned to %{name}, go to their profile.") % { name: assignee.name})
- if more_assignees_count > 0
%span{ class: 'avatar-counter has-tooltip', data: { container: 'body', placement: 'bottom', 'line-type' => 'old', qa_selector: 'avatar_counter_content' }, title: _("+%{more_assignees_count} more assignees") % { more_assignees_count: more_assignees_count} }
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 16301789b65..ae896b7348d 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -75,8 +75,6 @@
- if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project)
= link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: _('%{issuableType} will be removed! Are you sure?') % { issuableType: issuable.human_class_name } }, method: :delete, class: 'btn gl-button btn-danger btn-danger-secondary gl-float-right'
-= render_if_exists 'shared/issuable/remove_approver'
-
- if issuable.respond_to?(:issue_type)
= form.hidden_field :issue_type
diff --git a/app/views/shared/issuable/_merge_request_assignees.html.haml b/app/views/shared/issuable/_merge_request_assignees.html.haml
new file mode 100644
index 00000000000..13dc6ae4abb
--- /dev/null
+++ b/app/views/shared/issuable/_merge_request_assignees.html.haml
@@ -0,0 +1,8 @@
+- issuable.merge_request_assignees.take(count).each do |merge_request_assignee| # rubocop: disable CodeReuse/ActiveRecord
+ - assignee = merge_request_assignee.assignee
+ - assignee_tooltip = ( merge_request_assignee.attention_requested? ? s_("MrList|Attention requested from assignee %{name}, go to their profile.") : s_("MrList|Assigned to %{name}, go to their profile.") ) % { name: assignee.name}
+
+ = link_to_member(@project, assignee, name: false, title: assignee_tooltip, extra_class: "gl-flex-direction-row-reverse") do
+ - if merge_request_assignee.attention_requested?
+ %span.gl-display-inline-flex
+ = sprite_icon('attention-solid-sm', css_class: 'gl-text-orange-500 icon-overlap-and-shadow')
diff --git a/app/views/shared/issuable/_merge_request_reviewers.html.haml b/app/views/shared/issuable/_merge_request_reviewers.html.haml
new file mode 100644
index 00000000000..df5c69e309f
--- /dev/null
+++ b/app/views/shared/issuable/_merge_request_reviewers.html.haml
@@ -0,0 +1,8 @@
+- issuable.merge_request_reviewers.take(count).each do |merge_request_reviewer| # rubocop: disable CodeReuse/ActiveRecord
+ - reviewer = merge_request_reviewer.reviewer
+ - reviewer_tooltip = ( merge_request_reviewer.attention_requested? ? s_("MrList|Attention requested from reviewer %{name}, go to their profile.") : s_("MrList|Review requested from %{name}, go to their profile.") ) % { name: reviewer.name}
+
+ = link_to_member(@project, reviewer, name: false, title: reviewer_tooltip, extra_class: "gl-flex-direction-row-reverse") do
+ - if merge_request_reviewer.attention_requested?
+ %span.gl-display-inline-flex
+ = sprite_icon('attention-solid-sm', css_class: 'gl-text-orange-500 icon-overlap-and-shadow')
diff --git a/app/views/shared/issuable/_reviewers.html.haml b/app/views/shared/issuable/_reviewers.html.haml
index 8e66135a20b..0bb0faa0bb8 100644
--- a/app/views/shared/issuable/_reviewers.html.haml
+++ b/app/views/shared/issuable/_reviewers.html.haml
@@ -3,8 +3,11 @@
- render_count = reviewers_rendering_overflow ? max_render - 1 : max_render
- more_reviewers_count = issuable.reviewers.size - render_count
-- issuable.reviewers.take(render_count).each do |reviewer| # rubocop: disable CodeReuse/ActiveRecord
- = link_to_member(@project, reviewer, name: false, title: _("Review requested from %{name}") % { name: reviewer.name})
+- if issuable.instance_of?(MergeRequest) && Feature.enabled?(:mr_attention_requests, default_enabled: :yaml)
+ = render 'shared/issuable/merge_request_reviewers', issuable: issuable, count: render_count
+- else
+ - issuable.reviewers.take(render_count).each do |reviewer| # rubocop: disable CodeReuse/ActiveRecord
+ = link_to_member(@project, reviewer, name: false, title: s_("MrList|Review requested from %{name}, go to their profile.") % { name: reviewer.name})
- if more_reviewers_count > 0
%span{ class: 'avatar-counter has-tooltip', data: { container: 'body', placement: 'bottom', 'line-type' => 'old' }, title: _("+%{more_reviewers_count} more reviewers") % { more_reviewers_count: more_reviewers_count} }
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 3975748ba57..b02c6b65359 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -31,7 +31,7 @@
= check_box_tag checkbox_id, nil, false, class: "check-all-issues left"
- if is_epic_board
#js-board-filtered-search{ data: { full_path: @group&.full_path } }
- - elsif Feature.enabled?(:issue_boards_filtered_search, ff_resource) && board
+ - elsif Feature.enabled?(:issue_boards_filtered_search, ff_resource, default_enabled: :yaml) && board
#js-issue-board-filtered-search
- else
.issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
@@ -107,6 +107,16 @@
= render 'shared/issuable/user_dropdown_item',
user: User.new(username: '{{username}}', name: '{{name}}'),
avatar: { lazy: true, url: '{{avatar_url}}' }
+ - if Feature.enabled?(:mr_attention_requests, default_enabled: :yaml)
+ #js-dropdown-attention-requested.filtered-search-input-dropdown-menu.dropdown-menu
+ - if current_user
+ %ul{ data: { dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: current_user
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: User.new(username: '{{username}}', name: '{{name}}'),
+ avatar: { lazy: true, url: '{{avatar_url}}' }
= render_if_exists 'shared/issuable/approver_dropdown'
= render_if_exists 'shared/issuable/approved_by_dropdown'
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
@@ -206,7 +216,7 @@
%button.clear-search.hidden{ type: 'button' }
= sprite_icon('close', size: 16, css_class: 'clear-search-icon')
- .filter-dropdown-container.d-flex.flex-column.flex-md-row
+ .filter-dropdown-container.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-align-items-flex-start
- if type == :boards
#js-board-labels-toggle
- if current_user
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 9a703b9d355..7787e5dd660 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -25,6 +25,11 @@
.block.reviewer.qa-reviewer-block
= render "shared/issuable/sidebar_reviewers", issuable_sidebar: issuable_sidebar, reviewers: reviewers, signed_in: signed_in
+ - if issuable_sidebar[:supports_escalation]
+ .block.escalation-status{ data: { testid: 'escalation_status_container' } }
+ #js-escalation-status{ data: { can_edit: issuable_sidebar.dig(:current_user, :can_update_escalation_status).to_s, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid] } }
+ = render_if_exists 'shared/issuable/sidebar_escalation_policy', 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
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index 5742f22ce05..f6d7ed6764d 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -21,6 +21,6 @@
= sortable_item(sort_title_merged_date, page_filter_path(sort: sort_value_merged_date), sort_title) if viewing_merge_requests
= sortable_item(sort_title_closed_date, page_filter_path(sort: sort_value_closed_date), sort_title) if viewing_merge_requests
= sortable_item(sort_title_relative_position, page_filter_path(sort: sort_value_relative_position), sort_title) if viewing_issues
- = sortable_item(sort_title_title, page_filter_path(sort: sort_value_title), sort_title) if viewing_issues
+ = sortable_item(sort_title_title, page_filter_path(sort: sort_value_title), sort_title)
= render_if_exists('shared/ee/issuable/sort_dropdown', viewing_issues: viewing_issues, sort_title: sort_title)
= issuable_sort_direction_button(sort_value)
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index c0a6322eb1b..257ad7a8518 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -14,13 +14,15 @@
- if issuable.respond_to?(:work_in_progress?)
.form-text.text-muted
- .js-wip-explanation
+ .js-wip-explanation{ style: "display: none;" }
= remove_wip_text
.js-no-wip-explanation
- if has_wip_commits
= _('It looks like you have some draft commits in this branch.')
%br
- = add_wip_text
+ .invisible
+ .js-unwrap-on-load
+ = add_wip_text
- if no_issuable_templates && can?(current_user, :push_code, issuable.project)
= render 'shared/issuable/form/default_templates'
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
index 0bf002fbbc5..e5197acf06f 100644
--- a/app/views/shared/issue_type/_details_content.html.haml
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -3,7 +3,7 @@
.issue-details.issuable-details
.detail-page-description.content-block
- #js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json} }
+ #js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json, full_path: @project.full_path } }
.title-container
%h2.title= markdown_field(issuable, :title)
- if issuable.description.present?
diff --git a/app/views/shared/members/_access_request_links.html.haml b/app/views/shared/members/_access_request_links.html.haml
index 8600db25e65..7af946377be 100644
--- a/app/views/shared/members/_access_request_links.html.haml
+++ b/app/views/shared/members/_access_request_links.html.haml
@@ -4,7 +4,8 @@
- link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
= link_to link_text, polymorphic_path([:leave, source, :members]),
method: :delete,
- data: { confirm: leave_confirmation_message(source), qa_selector: 'leave_group_link' },
+ aria: { label: link_text },
+ data: { confirm: leave_confirmation_message(source), confirm_btn_variant: 'danger', qa_selector: 'leave_group_link' },
class: 'js-leave-link'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
= link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index 6549c86ab29..3ab8514aebf 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -25,7 +25,7 @@
- elsif note_counter == 0
- counter = badge_counter if local_assigns[:badge_counter]
- badge_class = "hidden" if @fresh_discussion || counter.nil?
- %span.badge.badge-pill{ class: badge_class }
+ %span.gl-display-flex.gl-align-items-center.gl-justify-content-center.gl-font-sm.design-note-pin.small.user-avatar{ class: badge_class }
= counter
.timeline-content
.note-header
diff --git a/app/views/shared/planning_hierarchy.html.haml b/app/views/shared/planning_hierarchy.html.haml
new file mode 100644
index 00000000000..7ab5347b33d
--- /dev/null
+++ b/app/views/shared/planning_hierarchy.html.haml
@@ -0,0 +1,5 @@
+- page_title _("Planning hierarchy")
+- has_sub_epics = @project&.licensed_feature_available?(:subepics)
+- has_epics = @project&.licensed_feature_available?(:epics)
+
+#js-work-items-hierarchy{ data: { has_sub_epics: has_sub_epics.to_s, has_epics: has_epics.to_s, illustration_path: image_path('illustrations/rocket-launch-md.svg') } }
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index c5a03ef4dc1..529ef47a2cf 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -22,4 +22,4 @@
.col-md-4.col-lg-5.text-right-md.gl-mt-2
%span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm btn-default gl-mr-3'
%span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn gl-button btn-default btn-sm gl-mr-3'
- = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn gl-button btn-secondary btn-danger-secondary btn-sm'
+ = link_to _('Delete'), destroy_hook_path(hook), aria: { label: s_('Webhooks|Delete webhook') }, data: { confirm_btn_variant: "danger", confirm: s_('Webhooks|Are you sure you want to delete this webhook?') }, method: :delete, class: 'btn gl-button btn-secondary btn-danger-secondary btn-sm'
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index 7e745efd069..c0a6ab44a26 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -8,7 +8,6 @@
= _('There was an error loading users activity calendar.')
%a.js-retry-load{ href: '#' }
= s_('UserProfile|Retry')
- .user-calendar-activities
- if @user.user_readme&.rich_viewer
.row.justify-content-center
.col-12.col-md-10.col-lg-8.gl-my-6
@@ -25,6 +24,8 @@
= link_to _('Edit'), edit_blob_path(@user.user_project, @user.user_project.default_branch, @user.user_readme.path)
= render 'projects/blob/viewer', viewer: @user.user_readme.rich_viewer, load_async: false
.row
+ .col-12.user-calendar-activities
+.row
%div{ class: activity_pane_class }
- if can?(current_user, :read_cross_project)
.activities-block
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index d5a1f3884c9..88eacaefcb0 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -50,8 +50,8 @@
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder
- = link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: '', itemprop: 'image'
+ = link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer' do
+ = image_tag avatar_icon_for_user(@user, 90, current_user: current_user), class: "avatar s90", alt: '', itemprop: 'image'
- if @user.blocked? || !@user.confirmed?
.user-info
@@ -112,7 +112,7 @@
- if Feature.enabled?(:security_auto_fix) && @user.bot?
= sprite_icon('question', css_class: 'gl-text-blue-600')
= link_to @user.short_website_url, @user.full_website_url, target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
- - unless @user.public_email.blank?
+ - if display_public_email?(@user)
= render 'middle_dot_divider', stacking: true do
= link_to @user.public_email, "mailto:#{@user.public_email}", itemprop: 'email'
.gl-text-gray-900
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index c461250fc9b..afe257c2fc2 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -1,6 +1,7 @@
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
+ = render "layouts/bizible"
= render "layouts/google_tag_manager_body"
#js-terms-of-service{ data: { terms_data: terms_data(@term, @redirect) } }
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 239b66bdeb0..fb1fcb7937c 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -273,6 +273,33 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:container_registry_migration_enqueuer
+ :worker_name: ContainerRegistry::Migration::EnqueuerWorker
+ :feature_category: :container_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: cronjob:container_registry_migration_guard
+ :worker_name: ContainerRegistry::Migration::GuardWorker
+ :feature_category: :container_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: cronjob:container_registry_migration_observer
+ :worker_name: ContainerRegistry::Migration::ObserverWorker
+ :feature_category: :container_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:database_batched_background_migration
:worker_name: Database::BatchedBackgroundMigrationWorker
:feature_category: :database
@@ -1100,8 +1127,7 @@
:resource_boundary: :unknown
:weight: 1
:idempotent:
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: hashed_storage:hashed_storage_project_migrate
:worker_name: HashedStorage::ProjectMigrateWorker
:feature_category: :source_code_management
@@ -1110,8 +1136,7 @@
:resource_boundary: :unknown
:weight: 1
:idempotent:
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: hashed_storage:hashed_storage_project_rollback
:worker_name: HashedStorage::ProjectRollbackWorker
:feature_category: :source_code_management
@@ -1120,8 +1145,7 @@
:resource_boundary: :unknown
:weight: 1
:idempotent:
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: hashed_storage:hashed_storage_rollbacker
:worker_name: HashedStorage::RollbackerWorker
:feature_category: :source_code_management
@@ -1130,8 +1154,7 @@
:resource_boundary: :unknown
:weight: 1
:idempotent:
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: incident_management:incident_management_add_severity_system_note
:worker_name: IncidentManagement::AddSeveritySystemNoteWorker
:feature_category: :incident_management
@@ -1960,6 +1983,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: background_migration_ci_database
+ :worker_name: BackgroundMigration::CiDatabaseWorker
+ :feature_category: :database
+ :has_external_dependencies:
+ :urgency: :throttled
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: bulk_import
:worker_name: BulkImportWorker
:feature_category: :importers
@@ -2303,6 +2335,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: groups_update_statistics
+ :worker_name: Groups::UpdateStatisticsWorker
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: import_issues_csv
:worker_name: ImportIssuesCsvWorker
:feature_category: :team_planning
@@ -2564,6 +2605,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: namespaces_update_root_statistics
+ :worker_name: Namespaces::UpdateRootStatisticsWorker
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: new_issue
:worker_name: NewIssueWorker
:feature_category: :team_planning
@@ -2636,15 +2686,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: pages_update_configuration
- :worker_name: PagesUpdateConfigurationWorker
- :feature_category: :pages
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: phabricator_import_import_tasks
:worker_name: Gitlab::PhabricatorImport::ImportTasksWorker
:feature_category: :importers
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 f5327449242..8452f2a7821 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
@@ -20,7 +20,6 @@ module AuthorizedProjectUpdate
urgency :low
queue_namespace :authorized_project_update
- deduplicate :until_executing, including_scheduled: true
data_consistency :delayed
idempotent!
diff --git a/app/workers/auto_devops/disable_worker.rb b/app/workers/auto_devops/disable_worker.rb
index 9ec3e5490c2..03613db3f29 100644
--- a/app/workers/auto_devops/disable_worker.rb
+++ b/app/workers/auto_devops/disable_worker.rb
@@ -32,8 +32,12 @@ module AutoDevops
def email_receivers_for(pipeline, project)
recipients = [pipeline.user&.email]
- recipients << project.owner.email unless project.group
- recipients.uniq.compact
+
+ if project.personal?
+ recipients << project.owners.map(&:email)
+ end
+
+ recipients.flatten.uniq.compact
end
end
end
diff --git a/app/workers/background_migration/ci_database_worker.rb b/app/workers/background_migration/ci_database_worker.rb
new file mode 100644
index 00000000000..901d16681fd
--- /dev/null
+++ b/app/workers/background_migration/ci_database_worker.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module BackgroundMigration
+ class CiDatabaseWorker # rubocop:disable Scalability/IdempotentWorker
+ include SingleDatabaseWorker
+
+ def self.tracking_database
+ @tracking_database ||= Gitlab::Database::CI_DATABASE_NAME
+ end
+ end
+end
diff --git a/app/workers/background_migration/single_database_worker.rb b/app/workers/background_migration/single_database_worker.rb
index b6661d4fd14..f3a2165c41e 100644
--- a/app/workers/background_migration/single_database_worker.rb
+++ b/app/workers/background_migration/single_database_worker.rb
@@ -32,10 +32,6 @@ module BackgroundMigration
def tracking_database
raise NotImplementedError, "#{self.name} does not implement #{__method__}"
end
-
- def unhealthy_metric_name
- raise NotImplementedError, "#{self.name} does not implement #{__method__}"
- end
end
# Performs the background migration.
@@ -55,8 +51,12 @@ module BackgroundMigration
private
+ def tracking_database
+ self.class.tracking_database
+ end
+
def job_coordinator
- @job_coordinator ||= Gitlab::BackgroundMigration.coordinator_for_database(self.class.tracking_database)
+ @job_coordinator ||= Gitlab::BackgroundMigration.coordinator_for_database(tracking_database)
end
def perform_with_connection(class_name, arguments, lease_attempts)
@@ -91,7 +91,7 @@ module BackgroundMigration
healthy_db = healthy_database?
perform = lease_obtained && healthy_db
- database_unhealthy_counter.increment if lease_obtained && !healthy_db
+ database_unhealthy_counter.increment(db_config_name: tracking_database) if lease_obtained && !healthy_db
# When the DB is unhealthy or the lease can't be obtained after several tries,
# then give up on the job and log a warning. Otherwise we could end up in
@@ -140,7 +140,7 @@ module BackgroundMigration
def database_unhealthy_counter
Gitlab::Metrics.counter(
- self.class.unhealthy_metric_name,
+ :background_migration_database_health_reschedules,
'The number of times a background migration is rescheduled because the database is unhealthy.'
)
end
diff --git a/app/workers/background_migration_worker.rb b/app/workers/background_migration_worker.rb
index dea0d467eca..6145f34b693 100644
--- a/app/workers/background_migration_worker.rb
+++ b/app/workers/background_migration_worker.rb
@@ -6,8 +6,4 @@ class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
def self.tracking_database
@tracking_database ||= Gitlab::BackgroundMigration::DEFAULT_TRACKING_DATABASE
end
-
- def self.unhealthy_metric_name
- @unhealthy_metric_name ||= :background_migration_database_health_reschedules
- end
end
diff --git a/app/workers/ci/delete_objects_worker.rb b/app/workers/ci/delete_objects_worker.rb
index cbcad3e8838..32c57750076 100644
--- a/app/workers/ci/delete_objects_worker.rb
+++ b/app/workers/ci/delete_objects_worker.rb
@@ -22,13 +22,7 @@ module Ci
end
def max_running_jobs
- if ::Feature.enabled?(:ci_delete_objects_medium_concurrency)
- 20
- elsif ::Feature.enabled?(:ci_delete_objects_high_concurrency)
- 50
- else
- 2
- end
+ 20
end
private
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 83261d9e42e..c1fec4f0196 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -13,7 +13,6 @@ module ApplicationWorker
include Gitlab::SidekiqVersioning::Worker
LOGGING_EXTRA_KEY = 'extra'
- DEFAULT_DELAY_INTERVAL = 1
SAFE_PUSH_BULK_LIMIT = 1000
included do
@@ -92,18 +91,6 @@ module ApplicationWorker
validate_worker_attributes!
end
- def perform_async(*args)
- return super if Gitlab::Database::LoadBalancing.primary_only?
-
- # Worker execution for workers with data_consistency set to :delayed or :sticky
- # will be delayed to give replication enough time to complete
- if utilizes_load_balancing_capabilities? && Feature.disabled?(:skip_scheduling_workers_for_replicas, default_enabled: :yaml)
- perform_in(delay_interval, *args)
- else
- super
- end
- end
-
def set_queue
queue_name = ::Gitlab::SidekiqConfig::WorkerRouter.global.route(self)
sidekiq_options queue: queue_name # rubocop:disable Cop/SidekiqOptionsQueue
@@ -194,12 +181,6 @@ module ApplicationWorker
end
end
- protected
-
- def delay_interval
- DEFAULT_DELAY_INTERVAL.seconds
- end
-
private
def do_push_bulk(args_list)
diff --git a/app/workers/container_expiration_policy_worker.rb b/app/workers/container_expiration_policy_worker.rb
index 5fcbd74ddad..16ac61976eb 100644
--- a/app/workers/container_expiration_policy_worker.rb
+++ b/app/workers/container_expiration_policy_worker.rb
@@ -57,7 +57,7 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
def perform_unthrottled
with_runnable_policy(preloaded: true) do |policy|
with_context(project: policy.project,
- user: policy.project.owner) do |project:, user:|
+ user: nil) do |project:, user:|
ContainerExpirationPolicyService.new(project, user)
.execute(policy)
end
diff --git a/app/workers/container_registry/migration/enqueuer_worker.rb b/app/workers/container_registry/migration/enqueuer_worker.rb
new file mode 100644
index 00000000000..5feaba870e6
--- /dev/null
+++ b/app/workers/container_registry/migration/enqueuer_worker.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Migration
+ class EnqueuerWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+ include Gitlab::Utils::StrongMemoize
+
+ data_consistency :always
+ feature_category :container_registry
+ urgency :low
+ deduplicate :until_executing, including_scheduled: true
+ idempotent!
+
+ def perform
+ return unless migration.enabled?
+ return unless below_capacity?
+ return unless waiting_time_passed?
+
+ re_enqueue_if_capacity if handle_aborted_migration || handle_next_migration
+ rescue StandardError => e
+ Gitlab::ErrorTracking.log_exception(
+ e,
+ next_repository_id: next_repository&.id,
+ next_aborted_repository_id: next_aborted_repository&.id
+ )
+
+ next_repository&.abort_import
+ end
+
+ private
+
+ def handle_aborted_migration
+ return unless next_aborted_repository&.retry_aborted_migration
+
+ log_extra_metadata_on_done(:container_repository_id, next_aborted_repository.id)
+ log_extra_metadata_on_done(:import_type, 'retry')
+
+ true
+ end
+
+ def handle_next_migration
+ return unless next_repository
+ # We return true because the repository was successfully processed (migration_state is changed)
+ return true if tag_count_too_high?
+ return unless next_repository.start_pre_import
+
+ log_extra_metadata_on_done(:container_repository_id, next_repository.id)
+ log_extra_metadata_on_done(:import_type, 'next')
+
+ true
+ end
+
+ def tag_count_too_high?
+ return false unless next_repository.tags_count > migration.max_tags_count
+
+ next_repository.skip_import(reason: :too_many_tags)
+
+ true
+ end
+
+ def below_capacity?
+ current_capacity <= maximum_capacity
+ end
+
+ def waiting_time_passed?
+ delay = migration.enqueue_waiting_time
+ return true if delay == 0
+ return true unless last_step_completed_repository
+
+ last_step_completed_repository.last_import_step_done_at < Time.zone.now - delay
+ end
+
+ def current_capacity
+ strong_memoize(:current_capacity) do
+ ContainerRepository.with_migration_states(
+ %w[pre_importing pre_import_done importing]
+ ).count
+ end
+ end
+
+ def maximum_capacity
+ migration.capacity
+ end
+
+ def next_repository
+ strong_memoize(:next_repository) do
+ ContainerRepository.ready_for_import.take # rubocop:disable CodeReuse/ActiveRecord
+ end
+ end
+
+ def next_aborted_repository
+ strong_memoize(:next_aborted_repository) do
+ ContainerRepository.with_migration_state('import_aborted').take # rubocop:disable CodeReuse/ActiveRecord
+ end
+ end
+
+ def last_step_completed_repository
+ strong_memoize(:last_step_completed_repository) do
+ ContainerRepository.recently_done_migration_step.first
+ end
+ end
+
+ def migration
+ ::ContainerRegistry::Migration
+ end
+
+ def re_enqueue_if_capacity
+ return unless current_capacity < maximum_capacity
+
+ self.class.perform_async
+ end
+ end
+ end
+end
diff --git a/app/workers/container_registry/migration/guard_worker.rb b/app/workers/container_registry/migration/guard_worker.rb
new file mode 100644
index 00000000000..77ae111c1cb
--- /dev/null
+++ b/app/workers/container_registry/migration/guard_worker.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Migration
+ class GuardWorker
+ include ApplicationWorker
+ # This is a general worker with no context.
+ # It is not scoped to a project, user or group.
+ # We don't have a context.
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ data_consistency :always
+ feature_category :container_registry
+ urgency :low
+ worker_resource_boundary :unknown
+ deduplicate :until_executed
+ idempotent!
+
+ def perform
+ return unless Gitlab.com?
+
+ repositories = ::ContainerRepository.with_stale_migration(step_before_timestamp)
+ .limit(max_capacity)
+ aborts_count = 0
+ long_running_migration_ids = []
+
+ # the #to_a is safe as the amount of entries is limited.
+ # In addition, we're calling #each in the next line and we don't want two different SQL queries for these two lines
+ log_extra_metadata_on_done(:stale_migrations_count, repositories.to_a.size)
+
+ repositories.each do |repository|
+ if abortable?(repository)
+ repository.abort_import
+ aborts_count += 1
+ else
+ long_running_migration_ids << repository.id if long_running_migration?(repository)
+ end
+ end
+
+ log_extra_metadata_on_done(:aborted_stale_migrations_count, aborts_count)
+
+ if long_running_migration_ids.any?
+ log_extra_metadata_on_done(:long_running_stale_migration_container_repository_ids, long_running_migration_ids)
+ end
+ end
+
+ private
+
+ # This can ping the Container Registry API.
+ # We loop on a set of repositories to calls this function (see #perform)
+ # In the worst case scenario, we have a n+1 API calls situation here.
+ #
+ # This is reasonable because the maximum amount of repositories looped
+ # on is `25`. See ::ContainerRegistry::Migration.capacity.
+ #
+ # TODO We can remove this n+1 situation by having a Container Registry API
+ # endpoint that accepts multiple repository paths at once. This is issue
+ # https://gitlab.com/gitlab-org/container-registry/-/issues/582
+ def abortable?(repository)
+ # early return to save one Container Registry API request
+ return true unless repository.importing? || repository.pre_importing?
+ return true unless external_migration_in_progress?(repository)
+
+ false
+ end
+
+ def long_running_migration?(repository)
+ migration_start_timestamp(repository).before?(long_running_migration_threshold)
+ end
+
+ def external_migration_in_progress?(repository)
+ status = repository.external_import_status
+
+ (status == 'pre_import_in_progress' && repository.pre_importing?) ||
+ (status == 'import_in_progress' && repository.importing?)
+ end
+
+ def migration_start_timestamp(repository)
+ if repository.pre_importing?
+ repository.migration_pre_import_started_at
+ else
+ repository.migration_import_started_at
+ end
+ end
+
+ def step_before_timestamp
+ ::ContainerRegistry::Migration.max_step_duration.seconds.ago
+ end
+
+ def max_capacity
+ # doubling the actual capacity to prevent issues in case the capacity
+ # is not properly applied
+ ::ContainerRegistry::Migration.capacity * 2
+ end
+
+ def long_running_migration_threshold
+ @threshold ||= 30.minutes.ago
+ end
+ end
+ end
+end
diff --git a/app/workers/container_registry/migration/observer_worker.rb b/app/workers/container_registry/migration/observer_worker.rb
new file mode 100644
index 00000000000..757c4fd11a5
--- /dev/null
+++ b/app/workers/container_registry/migration/observer_worker.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Migration
+ class ObserverWorker
+ include ApplicationWorker
+ # This worker does not perform work scoped to a context
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ COUNT_BATCH_SIZE = 50000
+
+ data_consistency :sticky
+ feature_category :container_registry
+ urgency :low
+ deduplicate :until_executed, including_scheduled: true
+ idempotent!
+
+ def perform
+ return unless ::ContainerRegistry::Migration.enabled?
+
+ use_replica_if_available do
+ ContainerRepository::MIGRATION_STATES.each do |state|
+ relation = ContainerRepository.with_migration_state(state)
+ count = ::Gitlab::Database::BatchCount.batch_count(
+ relation, batch_size: COUNT_BATCH_SIZE
+ )
+ name = "#{state}_count".to_sym
+ log_extra_metadata_on_done(name, count)
+ end
+ end
+ end
+
+ private
+
+ def use_replica_if_available(&block)
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries(&block)
+ end
+ end
+ end
+end
diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb
index 49f0222e9c9..eaa8810a78e 100644
--- a/app/workers/expire_job_cache_worker.rb
+++ b/app/workers/expire_job_cache_worker.rb
@@ -10,8 +10,6 @@ class ExpireJobCacheWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_cache
urgency :high
-
- deduplicate :until_executing, including_scheduled: true
idempotent!
def perform(job_id)
diff --git a/app/workers/groups/update_statistics_worker.rb b/app/workers/groups/update_statistics_worker.rb
new file mode 100644
index 00000000000..40b9e883dbb
--- /dev/null
+++ b/app/workers/groups/update_statistics_worker.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# Worker for updating group statistics.
+module Groups
+ class UpdateStatisticsWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ worker_resource_boundary :cpu
+
+ feature_category :source_code_management
+ idempotent!
+ loggable_arguments 0, 1
+
+ # group_id - The ID of the group for which to flush the cache.
+ # statistics - An Array containing columns from NamespaceStatistics to
+ # refresh, if empty all columns will be refreshed
+ def perform(group_id, statistics = [])
+ group = Group.find_by_id(group_id)
+
+ return unless group
+
+ Groups::UpdateStatisticsService.new(group, statistics: statistics).execute
+ end
+ end
+end
diff --git a/app/workers/hashed_storage/migrator_worker.rb b/app/workers/hashed_storage/migrator_worker.rb
index 03019ae3131..5f90b8f1009 100644
--- a/app/workers/hashed_storage/migrator_worker.rb
+++ b/app/workers/hashed_storage/migrator_worker.rb
@@ -11,9 +11,6 @@ module HashedStorage
queue_namespace :hashed_storage
feature_category :source_code_management
- # https://gitlab.com/gitlab-org/gitlab/-/issues/340629
- tags :needs_own_queue
-
# @param [Integer] start initial ID of the batch
# @param [Integer] finish last ID of the batch
def perform(start, finish)
diff --git a/app/workers/hashed_storage/project_migrate_worker.rb b/app/workers/hashed_storage/project_migrate_worker.rb
index 460aac3f2f2..01e2d6307de 100644
--- a/app/workers/hashed_storage/project_migrate_worker.rb
+++ b/app/workers/hashed_storage/project_migrate_worker.rb
@@ -11,9 +11,6 @@ module HashedStorage
queue_namespace :hashed_storage
loggable_arguments 1
- # https://gitlab.com/gitlab-org/gitlab/-/issues/340629
- tags :needs_own_queue
-
attr_reader :project_id
def perform(project_id, old_disk_path = nil)
diff --git a/app/workers/hashed_storage/project_rollback_worker.rb b/app/workers/hashed_storage/project_rollback_worker.rb
index 91ea3dd9189..2ec323248ab 100644
--- a/app/workers/hashed_storage/project_rollback_worker.rb
+++ b/app/workers/hashed_storage/project_rollback_worker.rb
@@ -11,9 +11,6 @@ module HashedStorage
queue_namespace :hashed_storage
loggable_arguments 1
- # https://gitlab.com/gitlab-org/gitlab/-/issues/340629
- tags :needs_own_queue
-
attr_reader :project_id
def perform(project_id, old_disk_path = nil)
diff --git a/app/workers/hashed_storage/rollbacker_worker.rb b/app/workers/hashed_storage/rollbacker_worker.rb
index d6a16b4d083..c6c4990d799 100644
--- a/app/workers/hashed_storage/rollbacker_worker.rb
+++ b/app/workers/hashed_storage/rollbacker_worker.rb
@@ -11,9 +11,6 @@ module HashedStorage
queue_namespace :hashed_storage
feature_category :source_code_management
- # https://gitlab.com/gitlab-org/gitlab/-/issues/340629
- tags :needs_own_queue
-
# @param [Integer] start initial ID of the batch
# @param [Integer] finish last ID of the batch
def perform(start, finish)
diff --git a/app/workers/loose_foreign_keys/cleanup_worker.rb b/app/workers/loose_foreign_keys/cleanup_worker.rb
index c3492fed77b..ecece92ec1b 100644
--- a/app/workers/loose_foreign_keys/cleanup_worker.rb
+++ b/app/workers/loose_foreign_keys/cleanup_worker.rb
@@ -12,8 +12,6 @@ module LooseForeignKeys
idempotent!
def perform
- return if Feature.disabled?(:loose_foreign_key_cleanup, default_enabled: :yaml)
-
in_lock(self.class.name.underscore, ttl: ModificationTracker::MAX_RUNTIME, retries: 0) do
stats = {}
diff --git a/app/workers/merge_requests/update_head_pipeline_worker.rb b/app/workers/merge_requests/update_head_pipeline_worker.rb
index c8dc9d1f7c8..acebf5fc767 100644
--- a/app/workers/merge_requests/update_head_pipeline_worker.rb
+++ b/app/workers/merge_requests/update_head_pipeline_worker.rb
@@ -2,7 +2,6 @@
module MergeRequests
class UpdateHeadPipelineWorker
- include ApplicationWorker
include Gitlab::EventStore::Subscriber
feature_category :code_review
diff --git a/app/workers/namespaces/process_sync_events_worker.rb b/app/workers/namespaces/process_sync_events_worker.rb
index f3c4f5bebb1..269710dd804 100644
--- a/app/workers/namespaces/process_sync_events_worker.rb
+++ b/app/workers/namespaces/process_sync_events_worker.rb
@@ -16,7 +16,13 @@ module Namespaces
deduplicate :until_executing
def perform
- ::Ci::ProcessSyncEventsService.new(::Namespaces::SyncEvent, ::Ci::NamespaceMirror).execute
+ results = ::Ci::ProcessSyncEventsService.new(
+ ::Namespaces::SyncEvent, ::Ci::NamespaceMirror
+ ).execute
+
+ results.each do |key, value|
+ log_extra_metadata_on_done(key, value)
+ end
end
end
end
diff --git a/app/workers/namespaces/update_root_statistics_worker.rb b/app/workers/namespaces/update_root_statistics_worker.rb
new file mode 100644
index 00000000000..9fdf8e2506b
--- /dev/null
+++ b/app/workers/namespaces/update_root_statistics_worker.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class UpdateRootStatisticsWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :always
+
+ idempotent!
+
+ feature_category :source_code_management
+
+ def handle_event(event)
+ ScheduleAggregationWorker.perform_async(event.data[:namespace_id])
+ end
+ end
+end
diff --git a/app/workers/pages_update_configuration_worker.rb b/app/workers/pages_update_configuration_worker.rb
deleted file mode 100644
index 9c58b40e098..00000000000
--- a/app/workers/pages_update_configuration_worker.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-# TODO: remove this in 14.7 https://gitlab.com/gitlab-org/gitlab/-/issues/348582
-class PagesUpdateConfigurationWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 1
-
- idempotent!
- feature_category :pages
-
- def perform(_project_id)
- # Do nothing
- end
-end
diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb
index ebda30f57d8..5a53d53ccf9 100644
--- a/app/workers/pipeline_schedule_worker.rb
+++ b/app/workers/pipeline_schedule_worker.rb
@@ -13,6 +13,8 @@ class PipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
def perform
Ci::PipelineSchedule.runnable_schedules.preloaded.find_in_batches do |schedules|
schedules.each do |schedule|
+ next unless schedule.project
+
with_context(project: schedule.project, user: schedule.owner) do
Ci::PipelineScheduleService.new(schedule.project, schedule.owner).execute(schedule)
end
diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb
index 4dd9a9c6fcb..e3f8c4bcd9d 100644
--- a/app/workers/project_export_worker.rb
+++ b/app/workers/project_export_worker.rb
@@ -24,8 +24,15 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
::Projects::ImportExport::ExportService.new(project, current_user, params).execute(after_export)
export_job&.finish
- rescue ActiveRecord::RecordNotFound, Gitlab::ImportExport::AfterExportStrategyBuilder::StrategyNotFoundError => e
- logger.error("Failed to export project #{project_id}: #{e.message}")
+ rescue ActiveRecord::RecordNotFound => e
+ log_failure(project_id, e)
+ rescue Gitlab::ImportExport::AfterExportStrategyBuilder::StrategyNotFoundError => e
+ log_failure(project_id, e)
+ export_job&.finish
+ rescue StandardError => e
+ log_failure(project_id, e)
+ export_job&.fail_op
+ raise
end
private
@@ -35,4 +42,8 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
Gitlab::ImportExport::AfterExportStrategyBuilder.build!(strategy_klass, after_export_strategy)
end
+
+ def log_failure(project_id, ex)
+ logger.error("Failed to export project #{project_id}: #{ex.message}")
+ end
end
diff --git a/app/workers/projects/git_garbage_collect_worker.rb b/app/workers/projects/git_garbage_collect_worker.rb
index cf236f8b660..d16583975fc 100644
--- a/app/workers/projects/git_garbage_collect_worker.rb
+++ b/app/workers/projects/git_garbage_collect_worker.rb
@@ -16,7 +16,15 @@ module Projects
def before_gitaly_call(task, resource)
return unless gc?(task)
- ::Projects::GitDeduplicationService.new(resource).execute
+ # Don't block garbage collection if we can't fetch into an object pool
+ # due to some gRPC error because we don't want to accumulate cruft.
+ # See https://gitlab.com/gitlab-org/gitaly/-/issues/4022.
+ begin
+ ::Projects::GitDeduplicationService.new(resource).execute
+ rescue Gitlab::Git::CommandTimedOut, GRPC::Internal => e
+ Gitlab::ErrorTracking.track_exception(e)
+ end
+
cleanup_orphan_lfs_file_references(resource)
end
diff --git a/app/workers/projects/process_sync_events_worker.rb b/app/workers/projects/process_sync_events_worker.rb
index b7c4b4de3d0..1330ae47a68 100644
--- a/app/workers/projects/process_sync_events_worker.rb
+++ b/app/workers/projects/process_sync_events_worker.rb
@@ -16,7 +16,13 @@ module Projects
deduplicate :until_executing
def perform
- ::Ci::ProcessSyncEventsService.new(::Projects::SyncEvent, ::Ci::ProjectMirror).execute
+ results = ::Ci::ProcessSyncEventsService.new(
+ ::Projects::SyncEvent, ::Ci::ProjectMirror
+ ).execute
+
+ results.each do |key, value|
+ log_extra_metadata_on_done(key, value)
+ end
end
end
end
diff --git a/app/workers/run_pipeline_schedule_worker.rb b/app/workers/run_pipeline_schedule_worker.rb
index f08d8231e43..35e3e633c70 100644
--- a/app/workers/run_pipeline_schedule_worker.rb
+++ b/app/workers/run_pipeline_schedule_worker.rb
@@ -15,7 +15,7 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
schedule = Ci::PipelineSchedule.find_by_id(schedule_id)
user = User.find_by_id(user_id)
- return unless schedule && user
+ return unless schedule && schedule.project && user
run_pipeline_schedule(schedule, user)
end
diff --git a/app/workers/web_hook_worker.rb b/app/workers/web_hook_worker.rb
index 952ac94d5e6..fdcd22128a3 100644
--- a/app/workers/web_hook_worker.rb
+++ b/app/workers/web_hook_worker.rb
@@ -6,14 +6,14 @@ class WebHookWorker
include ApplicationWorker
feature_category :integrations
- loggable_arguments 2
+ loggable_arguments 2, 3
data_consistency :delayed
sidekiq_options retry: 4, dead: false
urgency :low
worker_has_external_dependencies!
- # Webhook recursion detection properties are passed through the `data` arg.
+ # Webhook recursion detection properties may be passed through the `data` arg.
# This will be migrated to the `params` arg over the next few releases.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/347389.
def perform(hook_id, data, hook_name, params = {})
@@ -21,12 +21,14 @@ class WebHookWorker
return unless hook
data = data.with_indifferent_access
+ params.symbolize_keys!
- # Before executing the hook, reapply any recursion detection UUID that was
- # initially present in the request header so the hook can pass this same header
- # value in its request.
- recursion_detection_uuid = data.delete(:_gitlab_recursion_detection_request_uuid)
- Gitlab::WebHooks::RecursionDetection.set_request_uuid(recursion_detection_uuid)
+ # TODO: Remove in 14.9 https://gitlab.com/gitlab-org/gitlab/-/issues/347389
+ params[:recursion_detection_request_uuid] ||= data.delete(:_gitlab_recursion_detection_request_uuid)
+
+ # Before executing the hook, reapply any recursion detection UUID that was initially
+ # present in the request header so the hook can pass this same header value in its request.
+ Gitlab::WebHooks::RecursionDetection.set_request_uuid(params[:recursion_detection_request_uuid])
WebHookService.new(hook, data, hook_name, jid).execute
end
diff --git a/bin/feature-flag b/bin/feature-flag
index 06387d12eb5..be32c80aeab 100755
--- a/bin/feature-flag
+++ b/bin/feature-flag
@@ -9,6 +9,7 @@ require 'optparse'
require 'yaml'
require 'fileutils'
require 'uri'
+require 'readline'
require_relative '../lib/feature/shared' unless defined?(Feature::Shared)
@@ -114,8 +115,7 @@ class FeatureFlagOptionParser
$stdout.puts ">> Specify the group introducing the feature flag, like `group::apm`:"
loop do
- $stdout.print "?> "
- group = $stdin.gets.strip
+ group = Readline.readline('?> ', false)&.strip
group = nil if group.empty?
return group if group.nil? || group.start_with?('group::')
@@ -137,9 +137,7 @@ class FeatureFlagOptionParser
end
loop do
- $stdout.print "?> "
-
- type = $stdin.gets.strip.to_sym
+ type = Readline.readline('?> ', false)&.strip&.to_sym
return type if TYPES[type] && !TYPES[type][:deprecated]
$stderr.puts "Invalid type specified '#{type}'"
@@ -151,8 +149,7 @@ class FeatureFlagOptionParser
$stdout.puts ">> URL of the MR introducing the feature flag (enter to skip):"
loop do
- $stdout.print "?> "
- introduced_by_url = $stdin.gets.strip
+ introduced_by_url = Readline.readline('?> ', false)&.strip
introduced_by_url = nil if introduced_by_url.empty?
return introduced_by_url if introduced_by_url.nil? || introduced_by_url.start_with?('https://')
@@ -184,8 +181,7 @@ class FeatureFlagOptionParser
$stdout.puts ">> URL of the rollout issue (enter to skip):"
loop do
- $stdout.print "?> "
- created_url = $stdin.gets.strip
+ created_url = Readline.readline('?> ', false)&.strip
created_url = nil if created_url.empty?
return created_url if created_url.nil? || created_url.start_with?('https://')
@@ -218,7 +214,7 @@ class FeatureFlagCreator
assert_name!
assert_existing_feature_flag!
- # Read type from $stdin unless is already set
+ # Read type from stdin unless is already set
options.type ||= FeatureFlagOptionParser.read_type
options.ee ||= FeatureFlagOptionParser.read_ee_only(options)
options.group ||= FeatureFlagOptionParser.read_group
diff --git a/bin/metrics-server b/bin/metrics-server
index d8f2ed9faa4..f8eca93908e 100755
--- a/bin/metrics-server
+++ b/bin/metrics-server
@@ -9,4 +9,5 @@ raise "METRICS_SERVER_TARGET cannot be blank" if target.blank?
metrics_dir = ENV["prometheus_multiproc_dir"] || File.absolute_path("tmp/prometheus_multiproc_dir/#{target}")
wipe_metrics_dir = Gitlab::Utils.to_boolean(ENV['WIPE_METRICS_DIR']) || false
-Process.wait(MetricsServer.spawn(target, metrics_dir: metrics_dir, wipe_metrics_dir: wipe_metrics_dir))
+server = MetricsServer.new(target, metrics_dir, wipe_metrics_dir)
+server.start
diff --git a/config/application.rb b/config/application.rb
index 68b68c1c886..8d795e6bc4e 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -257,6 +257,7 @@ module Gitlab
config.assets.precompile << "page_bundles/build.css"
config.assets.precompile << "page_bundles/ci_status.css"
config.assets.precompile << "page_bundles/cycle_analytics.css"
+ config.assets.precompile << "page_bundles/dashboard_projects.css"
config.assets.precompile << "page_bundles/dev_ops_reports.css"
config.assets.precompile << "page_bundles/environments.css"
config.assets.precompile << "page_bundles/epics.css"
@@ -284,6 +285,7 @@ module Gitlab
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/projects_edit.css"
config.assets.precompile << "page_bundles/reports.css"
config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/security_dashboard.css"
@@ -508,5 +510,15 @@ module Gitlab
end
end
end
+
+ # DO NOT PLACE ANY INITIALIZERS AFTER THIS.
+ config.after_initialize do
+ # on_master_start yields immediately in unclustered environments and runs
+ # when the primary process is done initializing otherwise.
+ Gitlab::Cluster::LifecycleEvents.on_master_start do
+ Gitlab::Metrics::BootTimeTracker.instance.track_boot_time!
+ Gitlab::Console.welcome!
+ end
+ end
end
end
diff --git a/config/events/1643968255_projectsnew_select_deployment_target.yml b/config/events/1643968255_projectsnew_select_deployment_target.yml
new file mode 100644
index 00000000000..834d13968d0
--- /dev/null
+++ b/config/events/1643968255_projectsnew_select_deployment_target.yml
@@ -0,0 +1,20 @@
+---
+description: Deployment target option selected from new project creation form
+category: projects:new
+action: select_deployment_target
+label_description: new_project_deployment_target
+property_description: selected option (string)
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category:
+milestone: "14.8"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79873
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/events/202109151015_notes__create_service_execute.yml b/config/events/202109151015_notes__create_service_execute.yml
index e42e9856cd5..12da6da02f0 100644
--- a/config/events/202109151015_notes__create_service_execute.yml
+++ b/config/events/202109151015_notes__create_service_execute.yml
@@ -8,7 +8,7 @@ extra_properties:
identifiers:
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category:
milestone: "12.5"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18890
diff --git a/config/events/20211215022206_default_review_app_open_review_app.yml b/config/events/20211215022206_default_review_app_open_review_app.yml
index 8ba726e4708..c77b904bc01 100644
--- a/config/events/20211215022206_default_review_app_open_review_app.yml
+++ b/config/events/20211215022206_default_review_app_open_review_app.yml
@@ -8,7 +8,7 @@ extra_properties:
identifiers:
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category:
milestone: "12.6"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18141
diff --git a/config/feature_flags/development/api_caching_rate_limit_branches.yml b/config/feature_flags/development/admin_application_settings_service_usage_data_center.yml
index a48e4660342..465f9061eb4 100644
--- a/config/feature_flags/development/api_caching_rate_limit_branches.yml
+++ b/config/feature_flags/development/admin_application_settings_service_usage_data_center.yml
@@ -1,8 +1,8 @@
---
-name: api_caching_rate_limit_branches
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61688
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330876
-milestone: '13.12'
+name: admin_application_settings_service_usage_data_center
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78747
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351268
+milestone: '14.8'
type: development
-group: group::source code
+group: group::product intelligence
default_enabled: true
diff --git a/config/feature_flags/development/artifacts_management_page.yml b/config/feature_flags/development/artifacts_management_page.yml
index fd85b374909..94ef885f4b9 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::pipeline execution
+group: group::pipeline insights
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 a3ecbdeb695..5e0c037bf23 100644
--- a/config/feature_flags/development/auto_devops_banner_disabled.yml
+++ b/config/feature_flags/development/auto_devops_banner_disabled.yml
@@ -1,7 +1,7 @@
---
name: auto_devops_banner_disabled
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14218
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350882
milestone: '10.0'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/ban_user_feature_flag.yml b/config/feature_flags/development/ban_user_feature_flag.yml
index 6765e82e252..d06a0668549 100644
--- a/config/feature_flags/development/ban_user_feature_flag.yml
+++ b/config/feature_flags/development/ban_user_feature_flag.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330667
milestone: '13.12'
type: development
group: group::access
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/block_external_fork_network_mirrors.yml b/config/feature_flags/development/block_external_fork_network_mirrors.yml
deleted file mode 100644
index 8c313bc9273..00000000000
--- a/config/feature_flags/development/block_external_fork_network_mirrors.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: block_external_fork_network_mirrors
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60735
-rollout_issue_url:
-milestone: '14.0'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/bulk_expire_project_artifacts.yml b/config/feature_flags/development/bulk_expire_project_artifacts.yml
index 609f87847fa..9f1949e3dd2 100644
--- a/config/feature_flags/development/bulk_expire_project_artifacts.yml
+++ b/config/feature_flags/development/bulk_expire_project_artifacts.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75488
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347405
milestone: '14.6'
type: development
-group: group::testing
+group: group::pipeline insights
default_enabled: true
diff --git a/config/feature_flags/development/cache_shared_runners_enabled.yml b/config/feature_flags/development/cache_shared_runners_enabled.yml
index a5ff0df5aca..4dde6c852a6 100644
--- a/config/feature_flags/development/cache_shared_runners_enabled.yml
+++ b/config/feature_flags/development/cache_shared_runners_enabled.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338267
milestone: '14.2'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_bulk_insert_tags.yml b/config/feature_flags/development/ci_bulk_insert_tags.yml
index 6b8ad4ef39d..52a3e22379c 100644
--- a/config/feature_flags/development/ci_bulk_insert_tags.yml
+++ b/config/feature_flags/development/ci_bulk_insert_tags.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346124
milestone: '14.6'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
index b064e6bf09f..dd7192f0bc8 100644
--- a/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
+++ b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72406
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338165
milestone: '14.5'
type: development
-group: group::testing
+group: group::pipeline insights
default_enabled: false
diff --git a/config/feature_flags/development/ci_enable_live_trace.yml b/config/feature_flags/development/ci_enable_live_trace.yml
index f6f44dd1309..62ee0673f98 100644
--- a/config/feature_flags/development/ci_enable_live_trace.yml
+++ b/config/feature_flags/development/ci_enable_live_trace.yml
@@ -1,7 +1,7 @@
---
name: ci_enable_live_trace
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5255
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350883
milestone: '10.8'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/ci_order_subsequent_jobs_by_stage.yml b/config/feature_flags/development/ci_order_subsequent_jobs_by_stage.yml
deleted file mode 100644
index dfc4ab3bad3..00000000000
--- a/config/feature_flags/development/ci_order_subsequent_jobs_by_stage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_order_subsequent_jobs_by_stage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77528
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349977
-milestone: '14.7'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_queue_source.yml b/config/feature_flags/development/ci_pending_builds_queue_source.yml
index 19672aff290..f6edd0e98ea 100644
--- a/config/feature_flags/development/ci_pending_builds_queue_source.yml
+++ b/config/feature_flags/development/ci_pending_builds_queue_source.yml
@@ -1,7 +1,7 @@
---
name: ci_pending_builds_queue_source
introduced_by_url:
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350884
milestone: '14.0'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml b/config/feature_flags/development/ci_pipeline_merge_request_presence_check.yml
index 55fc2d9fc94..19f674aa27c 100644
--- a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
+++ b/config/feature_flags/development/ci_pipeline_merge_request_presence_check.yml
@@ -1,8 +1,8 @@
---
-name: ci_delete_objects_medium_concurrency
-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'
+name: ci_pipeline_merge_request_presence_check
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78574
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350734
+milestone: '14.8'
type: development
group: group::pipeline execution
-default_enabled: false
+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
deleted file mode 100644
index 5bac8fc9615..00000000000
--- a/config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_runners_short_circuit_assignable_for
-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::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/deployment_approvals.yml b/config/feature_flags/development/ci_secure_files.yml
index 5083ccd28bf..a1aa82fe298 100644
--- a/config/feature_flags/development/deployment_approvals.yml
+++ b/config/feature_flags/development/ci_secure_files.yml
@@ -1,8 +1,8 @@
---
-name: deployment_approvals
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74932
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347342
-milestone: '14.6'
+name: ci_secure_files
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78227
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350748
+milestone: '14.8'
type: development
-group: group::release
+group: group::incubation
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 0db9e683929..223024d9a50 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
@@ -1,7 +1,7 @@
---
name: ci_skip_persistent_ref_existence_check
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32391
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350885
milestone: '13.1'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/ci_skip_require_credit_card_for_addon_ci_minutes.yml b/config/feature_flags/development/ci_skip_require_credit_card_for_addon_ci_minutes.yml
deleted file mode 100644
index e9c355bd119..00000000000
--- a/config/feature_flags/development/ci_skip_require_credit_card_for_addon_ci_minutes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_skip_require_credit_card_for_addon_ci_minutes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77829
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349841
-milestone: '14.7'
-type: development
-group: group::fulfillment
-default_enabled: false
diff --git a/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
index 9157928f352..f756de86efb 100644
--- a/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
+++ b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70235
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343465
milestone: '14.5'
type: development
-group: group::testing
+group: group::pipeline insights
default_enabled: false
diff --git a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml b/config/feature_flags/development/ci_variables_builder_memoize_secret_variables.yml
index a14861beb59..a35b06f9907 100644
--- a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
+++ b/config/feature_flags/development/ci_variables_builder_memoize_secret_variables.yml
@@ -1,8 +1,8 @@
---
-name: ci_delete_objects_high_concurrency
-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'
+name: ci_variables_builder_memoize_secret_variables
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79850
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351995
+milestone: '14.8'
type: development
group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/cluster_vulnerabilities.yml b/config/feature_flags/development/cluster_vulnerabilities.yml
index 919cdc1d009..9d7f3228d66 100644
--- a/config/feature_flags/development/cluster_vulnerabilities.yml
+++ b/config/feature_flags/development/cluster_vulnerabilities.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343917
milestone: '14.5'
type: development
group: group::container security
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/contacts_autocomplete.yml b/config/feature_flags/development/contacts_autocomplete.yml
new file mode 100644
index 00000000000..9d6960f6713
--- /dev/null
+++ b/config/feature_flags/development/contacts_autocomplete.yml
@@ -0,0 +1,8 @@
+---
+name: contacts_autocomplete
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79639
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352123
+milestone: '14.8'
+type: development
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_limit_gitlab_org.yml b/config/feature_flags/development/container_registry_migration_limit_gitlab_org.yml
new file mode 100644
index 00000000000..8b952b79f9b
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_limit_gitlab_org.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_limit_gitlab_org
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78613
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_phase2_capacity_1.yml b/config/feature_flags/development/container_registry_migration_phase2_capacity_1.yml
new file mode 100644
index 00000000000..846bc8b690b
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_capacity_1.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_capacity_1
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_phase2_capacity_10.yml b/config/feature_flags/development/container_registry_migration_phase2_capacity_10.yml
new file mode 100644
index 00000000000..fcbcc5bfb48
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_capacity_10.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_capacity_10
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_phase2_capacity_25.yml b/config/feature_flags/development/container_registry_migration_phase2_capacity_25.yml
new file mode 100644
index 00000000000..b52693e0aba
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_capacity_25.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_capacity_25
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_cdn_redirect.yml b/config/feature_flags/development/container_registry_migration_phase2_enabled.yml
index 5cc2bf7a342..c48cbdb435e 100644
--- a/config/feature_flags/development/container_registry_cdn_redirect.yml
+++ b/config/feature_flags/development/container_registry_migration_phase2_enabled.yml
@@ -1,8 +1,8 @@
---
-name: container_registry_cdn_redirect
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77705
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349717
-milestone: '14.7'
+name: container_registry_migration_phase2_enabled
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
type: development
group: group::package
default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_fast.yml b/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_fast.yml
new file mode 100644
index 00000000000..9a312161824
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_fast.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_enqueue_speed_fast
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_slow.yml b/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_slow.yml
new file mode 100644
index 00000000000..f02259be928
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_enqueue_speed_slow.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_enqueue_speed_slow
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '14.8'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/create_deployment_in_separate_transaction.yml b/config/feature_flags/development/create_deployment_in_separate_transaction.yml
deleted file mode 100644
index 96cda772beb..00000000000
--- a/config/feature_flags/development/create_deployment_in_separate_transaction.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: create_deployment_in_separate_transaction
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75604
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346879
-milestone: '14.6'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/custom_preloader_for_deployments.yml b/config/feature_flags/development/custom_preloader_for_deployments.yml
deleted file mode 100644
index f8abcb4ba4a..00000000000
--- a/config/feature_flags/development/custom_preloader_for_deployments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: custom_preloader_for_deployments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75767
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348289
-milestone: '14.7'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
index 6f4235acaac..6adfba96e10 100644
--- a/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
+++ b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37195
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229841
milestone: '13.2'
type: development
-group: group::monitor
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/early_prepare_for_mergeability.yml b/config/feature_flags/development/enforce_auth_checks_on_uploads.yml
index c6377bd9a60..d0cbe123a8f 100644
--- a/config/feature_flags/development/early_prepare_for_mergeability.yml
+++ b/config/feature_flags/development/enforce_auth_checks_on_uploads.yml
@@ -1,8 +1,8 @@
---
-name: early_prepare_for_mergeability
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75402
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346667
-milestone: '14.6'
+name: enforce_auth_checks_on_uploads
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80117
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352291
+milestone: '14.8'
type: development
group: group::code review
default_enabled: false
diff --git a/config/feature_flags/development/ci_find_runners_by_ci_mirrors.yml b/config/feature_flags/development/enforce_runner_token_expires_at.yml
index 337e6b11408..a1cb3bdcfdd 100644
--- a/config/feature_flags/development/ci_find_runners_by_ci_mirrors.yml
+++ b/config/feature_flags/development/enforce_runner_token_expires_at.yml
@@ -1,8 +1,8 @@
---
-name: ci_find_runners_by_ci_mirrors
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74900
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347226
-milestone: '14.7'
+name: enforce_runner_token_expires_at
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78557
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352008
+milestone: '14.8'
type: development
group: group::runner
default_enabled: false
diff --git a/config/feature_flags/development/security_finding_build_disable_joins.yml b/config/feature_flags/development/enforce_security_report_validation.yml
index 7432882eca8..ada5863b4d7 100644
--- a/config/feature_flags/development/security_finding_build_disable_joins.yml
+++ b/config/feature_flags/development/enforce_security_report_validation.yml
@@ -1,8 +1,8 @@
---
-name: security_finding_build_disable_joins
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72738
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342380
-milestone: '14.4'
+name: enforce_security_report_validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79798
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351000
+milestone: '14.8'
type: development
group: group::threat insights
-default_enabled: true
+default_enabled: false
diff --git a/config/feature_flags/development/export_reduce_relation_batch_size.yml b/config/feature_flags/development/export_reduce_relation_batch_size.yml
deleted file mode 100644
index 63164b6e9fe..00000000000
--- a/config/feature_flags/development/export_reduce_relation_batch_size.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: export_reduce_relation_batch_size
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34057
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
-milestone: '13.1'
-type: development
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/development/force_no_sharing_primary_model.yml b/config/feature_flags/development/force_no_sharing_primary_model.yml
new file mode 100644
index 00000000000..5732f39fdee
--- /dev/null
+++ b/config/feature_flags/development/force_no_sharing_primary_model.yml
@@ -0,0 +1,8 @@
+---
+name: force_no_sharing_primary_model
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76188
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347286
+milestone: '14.8'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/geo_token_user_authentication.yml b/config/feature_flags/development/geo_token_user_authentication.yml
new file mode 100644
index 00000000000..779e9b92351
--- /dev/null
+++ b/config/feature_flags/development/geo_token_user_authentication.yml
@@ -0,0 +1,8 @@
+---
+name: geo_token_user_authentication
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351450
+milestone: '14.8'
+type: development
+group: group::geo
+default_enabled: false
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 db0bcde251f..ba1f12ea4a8 100644
--- a/config/feature_flags/development/git_push_create_all_pipelines.yml
+++ b/config/feature_flags/development/git_push_create_all_pipelines.yml
@@ -1,7 +1,7 @@
---
name: git_push_create_all_pipelines
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27205
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350886
milestone: '11.10'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml b/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml
deleted file mode 100644
index c7f8d9f4943..00000000000
--- a/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_importer_use_diff_note_with_suggestions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71765
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344309
-milestone: '14.5'
-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 5e4af60016e..d89e549cdea 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
@@ -1,7 +1,7 @@
---
name: gitlab_ci_archived_trace_consistent_reads
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53716
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350887
milestone: '13.9'
type: development
group: group::pipeline execution
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 5551e249053..d23cc852d49 100644
--- a/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml
+++ b/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml
@@ -1,7 +1,7 @@
---
name: gitlab_ci_builds_queuing_metrics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54909
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350888
milestone: '13.10'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/gitlab_shell_upload_pack_sidechannel.yml b/config/feature_flags/development/gitlab_shell_upload_pack_sidechannel.yml
new file mode 100644
index 00000000000..e329959d36f
--- /dev/null
+++ b/config/feature_flags/development/gitlab_shell_upload_pack_sidechannel.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_shell_upload_pack_sidechannel
+introduced_by_url:
+rollout_issue_url:
+milestone: '14.8'
+type: development
+group: group::scalability
+default_enabled: false
diff --git a/config/feature_flags/development/linear_mirrors_worker_roots.yml b/config/feature_flags/development/group_project_api_preload_plans.yml
index 5595cea6504..3854bed461a 100644
--- a/config/feature_flags/development/linear_mirrors_worker_roots.yml
+++ b/config/feature_flags/development/group_project_api_preload_plans.yml
@@ -1,7 +1,7 @@
---
-name: linear_mirrors_worker_roots
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76735
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348415
+name: group_project_api_preload_plans
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77538
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350176
milestone: '14.7'
type: development
group: group::authentication and authorization
diff --git a/config/feature_flags/development/vue_integration_form.yml b/config/feature_flags/development/header_read_timeout_buffered_io.yml
index a11c42b8d4a..552052e2d9b 100644
--- a/config/feature_flags/development/vue_integration_form.yml
+++ b/config/feature_flags/development/header_read_timeout_buffered_io.yml
@@ -1,8 +1,8 @@
---
-name: vue_integration_form
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77934
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350444
-milestone: '14.7'
+name: header_read_timeout_buffered_io
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78065
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350233
+milestone: '14.8'
type: development
group: group::integrations
default_enabled: false
diff --git a/config/feature_flags/development/hide_public_email_on_profile.yml b/config/feature_flags/development/hide_public_email_on_profile.yml
new file mode 100644
index 00000000000..87ed700c359
--- /dev/null
+++ b/config/feature_flags/development/hide_public_email_on_profile.yml
@@ -0,0 +1,8 @@
+---
+name: hide_public_email_on_profile
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79717
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351731
+milestone: '14.8'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/import_project_from_remote_file.yml b/config/feature_flags/development/import_project_from_remote_file.yml
index 9a44491172c..09f40a92ad1 100644
--- a/config/feature_flags/development/import_project_from_remote_file.yml
+++ b/config/feature_flags/development/import_project_from_remote_file.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330039
milestone: '13.12'
type: development
group: group::import
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/import_redis_increment_by.yml b/config/feature_flags/development/import_redis_increment_by.yml
deleted file mode 100644
index 9932c8e868e..00000000000
--- a/config/feature_flags/development/import_redis_increment_by.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: import_redis_increment_by
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65773
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336226
-milestone: '14.1'
-type: development
-group: group::import
-default_enabled: true
diff --git a/config/feature_flags/development/incident_escalations.yml b/config/feature_flags/development/incident_escalations.yml
index ea823f573aa..3853a8be2de 100644
--- a/config/feature_flags/development/incident_escalations.yml
+++ b/config/feature_flags/development/incident_escalations.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74337
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345769
milestone: '14.6'
type: development
-group: group::monitor
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/invite_members_group_modal.yml b/config/feature_flags/development/invite_members_group_modal.yml
index 444cc79ff57..ab28a2c6e24 100644
--- a/config/feature_flags/development/invite_members_group_modal.yml
+++ b/config/feature_flags/development/invite_members_group_modal.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247208
milestone: '13.5'
type: development
group: group::expansion
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/issue_boards_filtered_search.yml b/config/feature_flags/development/issue_boards_filtered_search.yml
index 38cf723d69e..dadbbd1b2fc 100644
--- a/config/feature_flags/development/issue_boards_filtered_search.yml
+++ b/config/feature_flags/development/issue_boards_filtered_search.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331649
milestone: '14.1'
type: development
group: group::product planning
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/jobs_tab_vue.yml b/config/feature_flags/development/jobs_tab_vue.yml
index 2958532922a..d6e797f66a5 100644
--- a/config/feature_flags/development/jobs_tab_vue.yml
+++ b/config/feature_flags/development/jobs_tab_vue.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347371
milestone: '14.6'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/json_limited_encoder.yml b/config/feature_flags/development/json_limited_encoder.yml
deleted file mode 100644
index 409bae16b90..00000000000
--- a/config/feature_flags/development/json_limited_encoder.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: json_limited_encoder
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38687
-rollout_issue_url:
-milestone: '13.3'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/ci_namespace_project_mirrors.yml b/config/feature_flags/development/lfk_fair_queueing.yml
index a2d674c3770..ac67ffa14f0 100644
--- a/config/feature_flags/development/ci_namespace_project_mirrors.yml
+++ b/config/feature_flags/development/lfk_fair_queueing.yml
@@ -1,8 +1,8 @@
---
-name: ci_namespace_project_mirrors
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75517
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346786
-milestone: '14.6'
+name: lfk_fair_queueing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79116
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351082
+milestone: '14.8'
type: development
group: group::sharding
default_enabled: false
diff --git a/config/feature_flags/development/lfs_auto_link_fork_source.yml b/config/feature_flags/development/lfs_auto_link_fork_source.yml
deleted file mode 100644
index e14daa6b30b..00000000000
--- a/config/feature_flags/development/lfs_auto_link_fork_source.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: lfs_auto_link_fork_source
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75972
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348243
-milestone: '14.6'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/ci_decompose_for_namespace_monthly_usage_query.yml b/config/feature_flags/development/linear_group_descendants_finder_upto.yml
index 7b90c3e19b2..ef045ebfa7a 100644
--- a/config/feature_flags/development/ci_decompose_for_namespace_monthly_usage_query.yml
+++ b/config/feature_flags/development/linear_group_descendants_finder_upto.yml
@@ -1,8 +1,8 @@
---
-name: ci_decompose_for_namespace_monthly_usage_query
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77952
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350146
-milestone: '14.7'
+name: linear_group_descendants_finder_upto
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78991
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350972
+milestone: '14.8'
type: development
-group: group::pipeline execution
+group: group::authentication and authorization
default_enabled: false
diff --git a/config/feature_flags/development/loose_foreign_key_cleanup.yml b/config/feature_flags/development/loose_foreign_key_cleanup.yml
deleted file mode 100644
index 915ed662333..00000000000
--- a/config/feature_flags/development/loose_foreign_key_cleanup.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: loose_foreign_key_cleanup
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69165
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343545
-milestone: '14.4'
-type: development
-group: group::sharding
-default_enabled: true
diff --git a/config/feature_flags/development/tribute_autocomplete.yml b/config/feature_flags/development/markdown_continue_lists.yml
index 02094350b32..8be9a3008da 100644
--- a/config/feature_flags/development/tribute_autocomplete.yml
+++ b/config/feature_flags/development/markdown_continue_lists.yml
@@ -1,8 +1,8 @@
---
-name: tribute_autocomplete
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32671
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292804
-milestone: '13.2'
+name: markdown_continue_lists
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79161
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351386
+milestone: '14.8'
type: development
group: group::project management
default_enabled: false
diff --git a/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml b/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
index 1fe4c51b6ec..5c3c76dd252 100644
--- a/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
+++ b/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40103
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241697
milestone: '13.4'
type: development
-group: group::apm
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/mr_changes_fluid_layout.yml b/config/feature_flags/development/mr_changes_fluid_layout.yml
deleted file mode 100644
index dcb9dee2ece..00000000000
--- a/config/feature_flags/development/mr_changes_fluid_layout.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: mr_changes_fluid_layout
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70815
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341809
-milestone: '14.4'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/new_route_ci_minutes_purchase.yml b/config/feature_flags/development/new_route_ci_minutes_purchase.yml
deleted file mode 100644
index 06fbfab255c..00000000000
--- a/config/feature_flags/development/new_route_ci_minutes_purchase.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_route_ci_minutes_purchase
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54934
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322582
-milestone: '13.10'
-type: development
-group: group::purchase
-default_enabled: true
diff --git a/config/feature_flags/development/notes_create_service_tracking.yml b/config/feature_flags/development/notes_create_service_tracking.yml
index 5601088b25f..578c1e2a707 100644
--- a/config/feature_flags/development/notes_create_service_tracking.yml
+++ b/config/feature_flags/development/notes_create_service_tracking.yml
@@ -1,8 +1,8 @@
---
name: notes_create_service_tracking
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18890
-rollout_issue_url:
+rollout_issue_url:
milestone: '12.5'
type: development
-group: group::testing
+group: group::pipeline insights
default_enabled: false
diff --git a/config/feature_flags/development/omniauth_login_minimal_scopes.yml b/config/feature_flags/development/omniauth_login_minimal_scopes.yml
new file mode 100644
index 00000000000..b2ca3484a98
--- /dev/null
+++ b/config/feature_flags/development/omniauth_login_minimal_scopes.yml
@@ -0,0 +1,8 @@
+---
+name: omniauth_login_minimal_scopes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78556
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351331
+milestone: '14.8'
+type: development
+group: 'group::authentication and authorization'
+default_enabled: false
diff --git a/config/feature_flags/development/new_route_storage_purchase.yml b/config/feature_flags/development/overage_members_modal.yml
index b248a5f7d09..16810f1acd2 100644
--- a/config/feature_flags/development/new_route_storage_purchase.yml
+++ b/config/feature_flags/development/overage_members_modal.yml
@@ -1,8 +1,8 @@
---
-name: new_route_storage_purchase
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68834
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327896
-milestone: '14.3'
+name: overage_members_modal
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79644/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350265
+milestone: '14.8'
type: development
group: group::purchase
default_enabled: false
diff --git a/config/feature_flags/development/packages_installable_package_files.yml b/config/feature_flags/development/packages_installable_package_files.yml
deleted file mode 100644
index ed0091f41e2..00000000000
--- a/config/feature_flags/development/packages_installable_package_files.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: packages_installable_package_files
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76767
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348677
-milestone: '14.6'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/check_mergeability_async_in_widget.yml b/config/feature_flags/development/permit_all_shared_groups_for_approval.yml
index ff8116c3a65..4ea3b7f696b 100644
--- a/config/feature_flags/development/check_mergeability_async_in_widget.yml
+++ b/config/feature_flags/development/permit_all_shared_groups_for_approval.yml
@@ -1,8 +1,8 @@
---
-name: check_mergeability_async_in_widget
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58178
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326567
-milestone: '13.11'
+name: permit_all_shared_groups_for_approval
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80655
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352766
+milestone: '14.8'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
deleted file mode 100644
index 916312b1005..00000000000
--- a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: prohibit_hexadecimal_branch_names
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/28439ca4b1dd14f22a5a6ad14530f6bf1046f8bc
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/project_import_schedule_worker_job_tracker.yml b/config/feature_flags/development/project_import_schedule_worker_job_tracker.yml
new file mode 100644
index 00000000000..5dae4ddc60c
--- /dev/null
+++ b/config/feature_flags/development/project_import_schedule_worker_job_tracker.yml
@@ -0,0 +1,8 @@
+---
+name: project_import_schedule_worker_job_tracker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79097
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351408
+milestone: '14.8'
+type: development
+group: group::scalability
+default_enabled: false
diff --git a/config/feature_flags/development/project_overwrite_service_tracking.yml b/config/feature_flags/development/project_overwrite_service_tracking.yml
index 02c26d82654..1a0c4fed4cd 100644
--- a/config/feature_flags/development/project_overwrite_service_tracking.yml
+++ b/config/feature_flags/development/project_overwrite_service_tracking.yml
@@ -1,7 +1,7 @@
---
name: project_overwrite_service_tracking
introduced_by_url:
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350889
milestone: '14.1'
type: development
group: group::pipeline execution
diff --git a/config/feature_flags/development/prometheus_computed_alerts.yml b/config/feature_flags/development/prometheus_computed_alerts.yml
index 5a9a989d544..97912685fb5 100644
--- a/config/feature_flags/development/prometheus_computed_alerts.yml
+++ b/config/feature_flags/development/prometheus_computed_alerts.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13443
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255304
milestone: '12.0'
type: development
-group: group::monitor
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/publish_project_deleted_event.yml b/config/feature_flags/development/publish_project_deleted_event.yml
new file mode 100644
index 00000000000..1287ebe9f66
--- /dev/null
+++ b/config/feature_flags/development/publish_project_deleted_event.yml
@@ -0,0 +1,8 @@
+---
+name: publish_project_deleted_event
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78862
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351073
+milestone: '14.8'
+type: development
+group: group::pipeline insights
+default_enabled: false
diff --git a/config/feature_flags/development/rate_limit_gitlab_shell.yml b/config/feature_flags/development/rate_limit_gitlab_shell.yml
index ceb9e86b01c..3c29a71af6e 100644
--- a/config/feature_flags/development/rate_limit_gitlab_shell.yml
+++ b/config/feature_flags/development/rate_limit_gitlab_shell.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350465
milestone: '14.7'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/read_from_vulnerability_finding_evidence.yml b/config/feature_flags/development/read_from_vulnerability_finding_evidence.yml
new file mode 100644
index 00000000000..076339c4f32
--- /dev/null
+++ b/config/feature_flags/development/read_from_vulnerability_finding_evidence.yml
@@ -0,0 +1,8 @@
+---
+name: read_from_vulnerability_finding_evidence
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79883
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352632
+milestone: '14.8'
+type: development
+group: group::threat insights
+default_enabled: false
diff --git a/config/feature_flags/development/ci_use_variables_builder_definitions.yml b/config/feature_flags/development/rearrange_pipelines_table.yml
index c01e4e9958e..4f16d6651b6 100644
--- a/config/feature_flags/development/ci_use_variables_builder_definitions.yml
+++ b/config/feature_flags/development/rearrange_pipelines_table.yml
@@ -1,8 +1,8 @@
---
-name: ci_use_variables_builder_definitions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75254
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349049
-milestone: '14.7'
+name: rearrange_pipelines_table
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72545
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343286
+milestone: '14.8'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/redirect_to_latest_template_jobs_build.yml b/config/feature_flags/development/redirect_to_latest_template_jobs_build.yml
deleted file mode 100644
index df03505afc5..00000000000
--- a/config/feature_flags/development/redirect_to_latest_template_jobs_build.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: redirect_to_latest_template_jobs_build
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67782
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337990
-milestone: '14.2'
-type: development
-group: group::configure
-default_enabled: false
diff --git a/config/feature_flags/development/api_caching_merge_requests.yml b/config/feature_flags/development/remove_import_data_on_failure.yml
index 53e170a6847..5fa82eee981 100644
--- a/config/feature_flags/development/api_caching_merge_requests.yml
+++ b/config/feature_flags/development/remove_import_data_on_failure.yml
@@ -1,8 +1,8 @@
---
-name: api_caching_merge_requests
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61067
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330342
-milestone: '13.12'
+name: remove_import_data_on_failure
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80074
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352156
+milestone: '14.8'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/ci_preload_runner_tags.yml b/config/feature_flags/development/roadmap_settings.yml
index 8d3ab2a95d6..78704a90d06 100644
--- a/config/feature_flags/development/ci_preload_runner_tags.yml
+++ b/config/feature_flags/development/roadmap_settings.yml
@@ -1,8 +1,8 @@
---
-name: ci_preload_runner_tags
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55543
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323243
-milestone: '13.10'
+name: roadmap_settings
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78626
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350830
+milestone: '14.8'
type: development
-group: group::memory
+group: group::product planning
default_enabled: true
diff --git a/config/feature_flags/development/runner_read_only_admin_view.yml b/config/feature_flags/development/runner_read_only_admin_view.yml
index 8053c31df6a..7a412e70dd9 100644
--- a/config/feature_flags/development/runner_read_only_admin_view.yml
+++ b/config/feature_flags/development/runner_read_only_admin_view.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350164
milestone: '14.7'
type: development
group: group::runner
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/s3_multithreaded_uploads.yml b/config/feature_flags/development/s3_multithreaded_uploads.yml
index f80510a4c64..6c3ecac4143 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::testing
+group: group::pipeline insights
default_enabled: true
diff --git a/config/feature_flags/development/security_report_ingestion_framework.yml b/config/feature_flags/development/security_report_ingestion_framework.yml
index 490fd03c677..6c146b7073d 100644
--- a/config/feature_flags/development/security_report_ingestion_framework.yml
+++ b/config/feature_flags/development/security_report_ingestion_framework.yml
@@ -1,8 +1,8 @@
---
name: security_report_ingestion_framework
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66735
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343332
milestone: '14.4'
type: development
group: group::threat insights
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/settings_operations_prometheus_service.yml b/config/feature_flags/development/settings_operations_prometheus_service.yml
index 27ccaf782c2..93afe504b21 100644
--- a/config/feature_flags/development/settings_operations_prometheus_service.yml
+++ b/config/feature_flags/development/settings_operations_prometheus_service.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24296
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258560
milestone: '12.8'
type: development
-group: group::monitor
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml b/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
deleted file mode 100644
index 494bec1e665..00000000000
--- a/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: skip_scheduling_workers_for_replicas
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74532
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1380
-milestone: '14.5'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/api_caching_tags.yml b/config/feature_flags/development/strong_parameters_for_project_controller.yml
index 142291bf975..458bfc4c485 100644
--- a/config/feature_flags/development/api_caching_tags.yml
+++ b/config/feature_flags/development/strong_parameters_for_project_controller.yml
@@ -1,8 +1,8 @@
---
-name: api_caching_tags
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54975
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324391
-milestone: '13.10'
+name: strong_parameters_for_project_controller
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79956
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352251
+milestone: '14.8'
type: development
group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/sync_traversal_ids_before_commit.yml b/config/feature_flags/development/sync_traversal_ids_before_commit.yml
new file mode 100644
index 00000000000..f8f1e854fa5
--- /dev/null
+++ b/config/feature_flags/development/sync_traversal_ids_before_commit.yml
@@ -0,0 +1,8 @@
+---
+name: sync_traversal_ids_before_commit
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79964
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352499
+group: group::workspace
+type: development
+default_enabled: false
+milestone: '14.8'
diff --git a/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml b/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml
new file mode 100644
index 00000000000..a4685732f27
--- /dev/null
+++ b/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml
@@ -0,0 +1,8 @@
+---
+name: track_gitlab_schema_in_current_transaction
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76717
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349944
+milestone: '14.8'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/update_all_mirrors_job_tracker.yml b/config/feature_flags/development/update_all_mirrors_job_tracker.yml
new file mode 100644
index 00000000000..507f32550c3
--- /dev/null
+++ b/config/feature_flags/development/update_all_mirrors_job_tracker.yml
@@ -0,0 +1,8 @@
+---
+name: update_all_mirrors_job_tracker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79097
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351420
+milestone: '14.8'
+type: development
+group: group::scalability
+default_enabled: false
diff --git a/config/feature_flags/development/diff_searching_usage_data.yml b/config/feature_flags/development/usage_data_diff_searches.yml
index 27bd2c4959e..1fa0d2b934c 100644
--- a/config/feature_flags/development/diff_searching_usage_data.yml
+++ b/config/feature_flags/development/usage_data_diff_searches.yml
@@ -1,5 +1,5 @@
---
-name: diff_searching_usage_data
+name: usage_data_diff_searches
introduced_by_url:
rollout_issue_url:
milestone: '14.2'
diff --git a/config/feature_flags/development/diffs_virtual_scrolling.yml b/config/feature_flags/development/usage_data_i_code_review_user_jetbrains_api_request.yml
index add1297d8b8..3ab01c78a28 100644
--- a/config/feature_flags/development/diffs_virtual_scrolling.yml
+++ b/config/feature_flags/development/usage_data_i_code_review_user_jetbrains_api_request.yml
@@ -1,8 +1,8 @@
---
-name: diffs_virtual_scrolling
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60312
+name: usage_data_i_code_review_user_jetbrains_api_request
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
rollout_issue_url:
-milestone: '13.12'
+milestone: '14.8'
type: development
group: group::code review
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml b/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml
index 3b8d02cc2d4..558232ca1bd 100644
--- a/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml
+++ b/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58606
rollout_issue_url:
milestone: '13.11'
type: development
-group: group::monitor
+group: group::respond
default_enabled: true
diff --git a/config/feature_flags/development/api_caching_rate_limit_repository_compare.yml b/config/feature_flags/development/use_traversal_ids_for_descendants_scopes.yml
index 81200aff786..b2262c9707e 100644
--- a/config/feature_flags/development/api_caching_rate_limit_repository_compare.yml
+++ b/config/feature_flags/development/use_traversal_ids_for_descendants_scopes.yml
@@ -1,8 +1,8 @@
---
-name: api_caching_rate_limit_repository_compare
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64407
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334264
-milestone: '14.1'
+name: use_traversal_ids_for_descendants_scopes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78542
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350637
+milestone: '14.8'
type: development
-group: group::source code
+group: group::authentication and authorization
default_enabled: true
diff --git a/config/feature_flags/development/use_traversal_ids_for_self_and_hierarchy_scopes.yml b/config/feature_flags/development/use_traversal_ids_for_self_and_hierarchy_scopes.yml
new file mode 100644
index 00000000000..bdbfe33b16d
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids_for_self_and_hierarchy_scopes.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids_for_self_and_hierarchy_scopes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80045
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352120
+milestone: '14.8'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/vulnerability_report_pagination.yml b/config/feature_flags/development/vulnerability_report_pagination.yml
new file mode 100644
index 00000000000..71639f6790b
--- /dev/null
+++ b/config/feature_flags/development/vulnerability_report_pagination.yml
@@ -0,0 +1,8 @@
+---
+name: vulnerability_report_pagination
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79834
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351975
+milestone: '14.8'
+type: development
+group: group::threat insights
+default_enabled: false
diff --git a/config/feature_flags/experiment/new_project_readme_content.yml b/config/feature_flags/experiment/new_project_readme_content.yml
deleted file mode 100644
index 16ad0204ec0..00000000000
--- a/config/feature_flags/experiment/new_project_readme_content.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_project_readme_content
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323641
-milestone: '14.0'
-type: experiment
-group: group::adoption
-default_enabled: false
diff --git a/config/feature_flags/experiment/redirect_trial_user_to_feature.yml b/config/feature_flags/experiment/redirect_trial_user_to_feature.yml
deleted file mode 100644
index c653b886a04..00000000000
--- a/config/feature_flags/experiment/redirect_trial_user_to_feature.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: redirect_trial_user_to_feature
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65450
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335824
-milestone: '14.1'
-type: experiment
-group: group::conversion
-default_enabled: false
diff --git a/config/feature_flags/experiment/require_verification_for_group_creation.yml b/config/feature_flags/experiment/require_verification_for_group_creation.yml
deleted file mode 100644
index 767d5f55bce..00000000000
--- a/config/feature_flags/experiment/require_verification_for_group_creation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: require_verification_for_group_creation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77569
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349857
-milestone: '14.7'
-type: experiment
-group: group::activation
-default_enabled: false
diff --git a/config/feature_flags/development/track_geo_proxy_events.yml b/config/feature_flags/ops/elastic_migration_worker.yml
index 29e8d771adf..7be2f181edb 100644
--- a/config/feature_flags/development/track_geo_proxy_events.yml
+++ b/config/feature_flags/ops/elastic_migration_worker.yml
@@ -1,8 +1,8 @@
---
-name: track_geo_proxy_events
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76587
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348414
-milestone: '14.7'
-type: development
-group: group::geo
+name: elastic_migration_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80310
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352424
+milestone: '14.8'
+type: ops
+group: group::global search
default_enabled: true
diff --git a/config/feature_flags/ops/legacy_open_source_license_available.yml b/config/feature_flags/ops/legacy_open_source_license_available.yml
new file mode 100644
index 00000000000..2408e31633a
--- /dev/null
+++ b/config/feature_flags/ops/legacy_open_source_license_available.yml
@@ -0,0 +1,8 @@
+---
+name: legacy_open_source_license_available
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79855
+rollout_issue_url:
+milestone: '14.8'
+type: ops
+group: 'group::authentication and authorization'
+default_enabled: true
diff --git a/config/feature_flags/ops/prometheus_notify_max_alerts.yml b/config/feature_flags/ops/prometheus_notify_max_alerts.yml
index 2861299d9bf..bc08787e8ec 100644
--- a/config/feature_flags/ops/prometheus_notify_max_alerts.yml
+++ b/config/feature_flags/ops/prometheus_notify_max_alerts.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77168
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6086
milestone: '14.7'
type: ops
-group: group::monitor
+group: group::respond
default_enabled: false
diff --git a/config/feature_flags/development/grape_gitlab_json.yml b/config/feature_flags/ops/show_gitlab_agent_feedback.yml
index e29496c917d..2e2af65fea8 100644
--- a/config/feature_flags/development/grape_gitlab_json.yml
+++ b/config/feature_flags/ops/show_gitlab_agent_feedback.yml
@@ -1,8 +1,8 @@
---
-name: grape_gitlab_json
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36472
+name: show_gitlab_agent_feedback
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78567
rollout_issue_url:
-milestone: '13.2'
-type: development
-group: group::source code
+milestone: '14.8'
+type: ops
+group: group::configure
default_enabled: true
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index f5755591da7..6758afc91c4 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -404,6 +404,23 @@ production: &base
# aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
# path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
+ ## CI Secure Files
+ ci_secure_files:
+ enabled: true
+ # storage_path: shared/ci_secure_files
+ object_store:
+ enabled: false
+ remote_directory: ci-secure-files # The bucket name
+ connection:
+ provider: AWS
+ aws_access_key_id: AWS_ACCESS_KEY_ID
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ region: us-east-1
+ # host: 'localhost' # default: s3.amazonaws.com
+ # endpoint: 'http://127.0.0.1:9000' # default: nil
+ # aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ # path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
+
## GitLab Pages
pages:
enabled: false
@@ -1315,6 +1332,9 @@ production: &base
## OneTrust
# one_trust_id: '_your_one_trust_id'
+ ## Bizible.
+ # bizible: true
+
## Matomo analytics.
# matomo_url: '_your_matomo_url'
# matomo_site_id: '_your_matomo_site_id'
@@ -1432,7 +1452,7 @@ test:
storage_path: tmp/tests/ci_secure_files
object_store:
enabled: false
- remote_directory: ci_secure_files
+ remote_directory: ci-secure-files
connection:
provider: AWS # Only AWS supported at the moment
aws_access_key_id: AWS_ACCESS_KEY_ID
diff --git a/lib/gitlab/database/gitlab_loose_foreign_keys.yml b/config/gitlab_loose_foreign_keys.yml
index d694165574d..f46e005dacf 100644
--- a/lib/gitlab/database/gitlab_loose_foreign_keys.yml
+++ b/config/gitlab_loose_foreign_keys.yml
@@ -1,36 +1,20 @@
+# Make sure that this file has the keys sorted
---
-dast_site_profiles_pipelines:
- - table: ci_pipelines
- column: ci_pipeline_id
+ci_build_report_results:
+ - table: projects
+ column: project_id
on_delete: async_delete
-vulnerability_feedback:
- - table: ci_pipelines
- column: pipeline_id
+ci_builds:
+ - table: users
+ column: user_id
on_delete: async_nullify
-ci_pipeline_chat_data:
- - table: chat_names
- column: chat_name_id
- on_delete: async_delete
-dast_scanner_profiles_builds:
- - table: ci_builds
- column: ci_build_id
- on_delete: async_delete
-dast_site_profiles_builds:
- - table: ci_builds
- column: ci_build_id
+ - table: projects
+ column: project_id
on_delete: async_delete
-dast_profiles_pipelines:
- - table: ci_pipelines
- column: ci_pipeline_id
+ci_builds_metadata:
+ - table: projects
+ column: project_id
on_delete: async_delete
-clusters_applications_runners:
- - table: ci_runners
- column: runner_id
- on_delete: async_nullify
-ci_job_token_project_scope_links:
- - table: users
- column: added_by_id
- on_delete: async_nullify
ci_daily_build_group_report_results:
- table: namespaces
column: group_id
@@ -42,37 +26,54 @@ ci_freeze_periods:
- table: projects
column: project_id
on_delete: async_delete
-ci_pending_builds:
+ci_group_variables:
- table: namespaces
- column: namespace_id
+ column: group_id
on_delete: async_delete
+ci_job_artifacts:
- table: projects
column: project_id
on_delete: async_delete
-ci_resource_groups:
+ci_job_token_project_scope_links:
+ - table: users
+ column: added_by_id
+ on_delete: async_nullify
- table: projects
- column: project_id
+ column: source_project_id
on_delete: async_delete
-ci_runner_namespaces:
+ - table: projects
+ column: target_project_id
+ on_delete: async_delete
+ci_minutes_additional_packs:
- table: namespaces
column: namespace_id
on_delete: async_delete
-ci_running_builds:
- - table: projects
- column: project_id
- on_delete: async_delete
ci_namespace_mirrors:
- table: namespaces
column: namespace_id
on_delete: async_delete
-ci_build_report_results:
+ci_pending_builds:
+ - table: namespaces
+ column: namespace_id
+ on_delete: async_delete
- table: projects
column: project_id
on_delete: async_delete
-ci_builds:
+ci_pipeline_artifacts:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_pipeline_chat_data:
+ - table: chat_names
+ column: chat_name_id
+ on_delete: async_delete
+ci_pipeline_schedules:
- table: users
- column: user_id
+ column: owner_id
on_delete: async_nullify
+ - table: projects
+ column: project_id
+ on_delete: async_delete
ci_pipelines:
- table: merge_requests
column: merge_request_id
@@ -83,6 +84,9 @@ ci_pipelines:
- table: users
column: user_id
on_delete: async_nullify
+ - table: projects
+ column: project_id
+ on_delete: async_delete
ci_project_mirrors:
- table: projects
column: project_id
@@ -90,22 +94,107 @@ ci_project_mirrors:
- table: namespaces
column: namespace_id
on_delete: async_delete
+ci_project_monthly_usages:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_refs:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_resource_groups:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_runner_namespaces:
+ - table: namespaces
+ column: namespace_id
+ on_delete: async_delete
+ci_runner_projects:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_running_builds:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_secure_files:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_sources_pipelines:
+ - table: projects
+ column: source_project_id
+ on_delete: async_delete
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_sources_projects:
+ - table: projects
+ column: source_project_id
+ on_delete: async_delete
+ci_stages:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ci_subscriptions_projects:
+ - table: projects
+ column: downstream_project_id
+ on_delete: async_delete
+ - table: projects
+ column: upstream_project_id
+ on_delete: async_delete
+ci_triggers:
+ - table: users
+ column: owner_id
+ on_delete: async_delete
+ - table: projects
+ column: project_id
+ on_delete: async_delete
ci_unit_tests:
- table: projects
column: project_id
on_delete: async_delete
+ci_variables:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+clusters_applications_runners:
+ - table: ci_runners
+ column: runner_id
+ on_delete: async_nullify
+dast_profiles_pipelines:
+ - table: ci_pipelines
+ column: ci_pipeline_id
+ on_delete: async_delete
+dast_scanner_profiles_builds:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_delete
+dast_site_profiles_builds:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_delete
+dast_site_profiles_pipelines:
+ - table: ci_pipelines
+ column: ci_pipeline_id
+ on_delete: async_delete
+external_pull_requests:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+merge_request_metrics:
+ - table: ci_pipelines
+ column: pipeline_id
+ on_delete: async_delete
merge_requests:
- table: ci_pipelines
column: head_pipeline_id
on_delete: async_nullify
-vulnerability_statistics:
- - table: ci_pipelines
- column: latest_pipeline_id
- on_delete: async_nullify
-vulnerability_occurrence_pipelines:
+merge_trains:
- table: ci_pipelines
column: pipeline_id
- on_delete: async_delete
+ on_delete: async_nullify
packages_build_infos:
- table: ci_pipelines
column: pipeline_id
@@ -118,30 +207,10 @@ pages_deployments:
- table: ci_builds
column: ci_build_id
on_delete: async_nullify
-terraform_state_versions:
- - table: ci_builds
- column: ci_build_id
- on_delete: async_nullify
-merge_request_metrics:
- - table: ci_pipelines
- column: pipeline_id
- on_delete: async_delete
project_pages_metadata:
- table: ci_job_artifacts
column: artifacts_archive_id
on_delete: async_nullify
-ci_pipeline_schedules:
- - table: users
- column: owner_id
- on_delete: async_nullify
-ci_group_variables:
- - table: namespaces
- column: group_id
- on_delete: async_delete
-ci_minutes_additional_packs:
- - table: namespaces
- column: namespace_id
- on_delete: async_delete
requirements_management_test_reports:
- table: ci_builds
column: build_id
@@ -150,11 +219,19 @@ security_scans:
- table: ci_builds
column: build_id
on_delete: async_delete
-ci_secure_files:
- - table: projects
- column: project_id
- on_delete: async_delete
-ci_pipeline_artifacts:
- - table: projects
- column: project_id
+terraform_state_versions:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_nullify
+vulnerability_feedback:
+ - table: ci_pipelines
+ column: pipeline_id
+ on_delete: async_nullify
+vulnerability_occurrence_pipelines:
+ - table: ci_pipelines
+ column: pipeline_id
on_delete: async_delete
+vulnerability_statistics:
+ - table: ci_pipelines
+ column: latest_pipeline_id
+ on_delete: async_nullify
diff --git a/config/helpers/incremental_webpack_compiler/compiler.js b/config/helpers/incremental_webpack_compiler/compiler.js
index 480d7fa3263..0ef090bce24 100644
--- a/config/helpers/incremental_webpack_compiler/compiler.js
+++ b/config/helpers/incremental_webpack_compiler/compiler.js
@@ -4,8 +4,8 @@ const path = require('path');
const { History, HistoryWithTTL } = require('./history');
const log = require('./log');
-const onRequestEntryPoint = (app, callback) => {
- app.use((req, res, next) => {
+const onRequestEntryPoint = (callback) => {
+ return (req, res, next) => {
const fileName = path.basename(req.url);
/**
@@ -20,7 +20,7 @@ const onRequestEntryPoint = (app, callback) => {
}
next();
- });
+ };
};
/**
@@ -40,7 +40,9 @@ class NoopCompiler {
logStatus() {}
// eslint-disable-next-line class-methods-use-this
- setupMiddleware() {}
+ createMiddleware() {
+ return null;
+ }
}
/**
@@ -55,8 +57,8 @@ class HistoryOnlyCompiler extends NoopCompiler {
this.history = new History(historyFilePath);
}
- setupMiddleware(app) {
- onRequestEntryPoint(app, (entryPoint) => {
+ createMiddleware() {
+ return onRequestEntryPoint((entryPoint) => {
this.history.onRequestEntryPoint(entryPoint);
});
}
@@ -92,16 +94,16 @@ class IncrementalWebpackCompiler {
log(`Currently compiling route entrypoints: ${this.history.size} of ${totalCount}`);
}
- setupMiddleware(app, server) {
- onRequestEntryPoint(app, (entryPoint) => {
+ createMiddleware(devServer) {
+ return onRequestEntryPoint((entryPoint) => {
const wasVisitedRecently = this.history.onRequestEntryPoint(entryPoint);
if (!wasVisitedRecently) {
log(`Have not visited ${entryPoint} recently. Adding to compilation.`);
setTimeout(() => {
- server.middleware.invalidate(() => {
- if (server.sockets) {
- server.sockWrite(server.sockets, 'content-changed');
+ devServer.invalidate(() => {
+ if (devServer.sockets) {
+ devServer.sendMessage(devServer.webSocketServer.clients, 'static-changed');
}
});
}, TIMEOUT);
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 8244f570a18..07d6e8e4882 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -539,6 +539,15 @@ Settings.cron_jobs['namespaces_prune_aggregation_schedules_worker']['job_class']
Settings.cron_jobs['container_expiration_policy_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['container_expiration_policy_worker']['cron'] ||= '50 * * * *'
Settings.cron_jobs['container_expiration_policy_worker']['job_class'] = 'ContainerExpirationPolicyWorker'
+Settings.cron_jobs['container_registry_migration_guard_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['container_registry_migration_guard_worker']['cron'] ||= '*/10 * * * *'
+Settings.cron_jobs['container_registry_migration_guard_worker']['job_class'] = 'ContainerRegistry::Migration::GuardWorker'
+Settings.cron_jobs['container_registry_migration_observer_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['container_registry_migration_observer_worker']['cron'] ||= '*/30 * * * *'
+Settings.cron_jobs['container_registry_migration_observer_worker']['job_class'] = 'ContainerRegistry::Migration::ObserverWorker'
+Settings.cron_jobs['container_registry_migration_enqueuer_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['container_registry_migration_enqueuer_worker']['cron'] ||= '45 */1 * * *'
+Settings.cron_jobs['container_registry_migration_enqueuer_worker']['job_class'] = 'ContainerRegistry::Migration::EnqueuerWorker'
Settings.cron_jobs['image_ttl_group_policy_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['image_ttl_group_policy_worker']['cron'] ||= '40 0 * * *'
Settings.cron_jobs['image_ttl_group_policy_worker']['job_class'] = 'DependencyProxy::ImageTtlGroupPolicyWorker'
@@ -548,7 +557,6 @@ Settings.cron_jobs['cleanup_dependency_proxy_worker']['job_class'] = 'Dependency
Settings.cron_jobs['cleanup_package_registry_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['cleanup_package_registry_worker']['cron'] ||= '20 0,12 * * *'
Settings.cron_jobs['cleanup_package_registry_worker']['job_class'] = 'Packages::CleanupPackageRegistryWorker'
-
Settings.cron_jobs['x509_issuer_crl_check_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['x509_issuer_crl_check_worker']['cron'] ||= '30 1 * * *'
Settings.cron_jobs['x509_issuer_crl_check_worker']['job_class'] = 'X509IssuerCrlCheckWorker'
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 15757c05bd0..17ce2a30d66 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -95,13 +95,6 @@ if Gitlab::Runtime.web_server?
Gitlab::Metrics::Exporter::WebExporter.instance.start
end
- # DEPRECATED: TO BE REMOVED
- # This is needed to implement blackout period of `web_exporter`
- # https://gitlab.com/gitlab-org/gitlab/issues/35343#note_238479057
- Gitlab::Cluster::LifecycleEvents.on_before_blackout_period do
- Gitlab::Metrics::Exporter::WebExporter.instance.mark_as_not_running!
- end
-
Gitlab::Cluster::LifecycleEvents.on_before_graceful_shutdown do
# We need to ensure that before we re-exec or shutdown server
# we do stop the exporter
diff --git a/config/initializers/console_message.rb b/config/initializers/console_message.rb
index 3f98568c500..ccb5dc51f66 100644
--- a/config/initializers/console_message.rb
+++ b/config/initializers/console_message.rb
@@ -1,28 +1,6 @@
# frozen_string_literal: true
-# rubocop:disable Rails/Output
if Gitlab::Runtime.console?
- # note that this will not print out when using `spring`
- justify = 15
-
- puts '-' * 80
- puts " Ruby:".ljust(justify) + RUBY_DESCRIPTION
- puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision}) #{Gitlab.ee? ? 'EE' : 'FOSS'}"
- puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.version)}"
-
- if ApplicationRecord.database.exists?
- puts " #{ApplicationRecord.database.human_adapter_name}:".ljust(justify) + ApplicationRecord.database.version
-
- Gitlab.ee do
- if Gitlab::Geo.connected? && Gitlab::Geo.enabled?
- puts " Geo enabled:".ljust(justify) + 'yes'
- puts " Geo server:".ljust(justify) + EE::GeoHelper.current_node_human_status
- end
- end
- end
-
- puts '-' * 80
-
# Stop irb from writing a history file by default.
module IrbNoHistory
def init_config(*)
diff --git a/config/initializers/gitlab_experiment.rb b/config/initializers/gitlab_experiment.rb
index 5878b8702b9..fdb21d90c28 100644
--- a/config/initializers/gitlab_experiment.rb
+++ b/config/initializers/gitlab_experiment.rb
@@ -10,6 +10,11 @@ Gitlab::Experiment.configure do |config|
#
config.base_class = 'ApplicationExperiment'
+ # Customize the logic of our default rollout, which shouldn't include
+ # assigning the control yet -- we specifically set it to false for now.
+ #
+ config.default_rollout = Gitlab::Experiment::Rollout::Feature.new
+
# Mount the engine and middleware at a gitlab friendly style path.
#
# The middleware currently focuses only on handling redirection logic, which
@@ -66,4 +71,31 @@ Gitlab::Experiment.configure do |config|
)
))
end
+
+ # Deprecation warnings resolution for 0.7.0
+ #
+ # We're working through deprecation warnings one by one in:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350944
+ #
+ config.singleton_class.prepend(Module.new do
+ # Disable all deprecations in non dev/test environments.
+ #
+ def deprecated(*args, version:, stack: 0)
+ super if Gitlab.dev_or_test_env?
+ end
+
+ # Maintain a list of resolved deprecations to ensure that no new uses appear.
+ #
+ # Once a resolved deprecation warning has been added here, any future use will
+ # raise an exception.
+ #
+ ActiveSupport::Deprecation.disallowed_warnings += [
+ # 'Gitlab::Experiment 0.8 (instead use `control`)', # don't use `use`
+ # 'Gitlab::Experiment 0.8 (instead use `candidate`)', # don't use `try`
+ # 'Gitlab::Experiment 0.8 (instead use `variant(:variant_name)`)', # don't use `try(:variant_name)`
+ # 'Gitlab::Experiment 0.8 (instead use `assigned(:candidate)`)', # don't use variant(:variant_name) to assign
+ # 'Gitlab::Experiment 0.8 (instead use `assigned`)', # don't use variant.name to get the assigned variant
+ # 'Gitlab::Experiment 0.8, instead register variants using:', # don't use public `*_behavior` methods
+ ]
+ end)
end
diff --git a/config/initializers/google_api_client.rb b/config/initializers/google_api_client.rb
index 49a35e5bd7c..ab469e5b0a1 100644
--- a/config/initializers/google_api_client.rb
+++ b/config/initializers/google_api_client.rb
@@ -10,3 +10,14 @@ require 'signet/errors'
# enabling retries is strongly encouraged but disabled by default. Large uploads
# that may hit timeouts will mainly benefit from this.
Google::Apis::RequestOptions.default.retries = 3 if Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_GOOGLE_API_RETRIES', true))
+
+# By default, httpclient will set a send timeout of 120 seconds (https://github.com/nahi/httpclient/blob/82929c4baae14c2319c3f9aba49488c6f6def875/lib/httpclient/session.rb#L147),
+# which causes any request to be interrupted every 2 minutes (https://github.com/nahi/httpclient/blob/82929c4baae14c2319c3f9aba49488c6f6def875/lib/httpclient/session.rb#L515).
+#
+# The Google API client uses resumable uploads so that if a transfer
+# request is interrupted, it can retry where it left off. The client
+# will retry at most N + 1 times, which means transfers can only last as
+# long as this (N + 1) * send timeout. We raise this timeout to an hour
+# since otherwise transfers can only last 8 minutes (4 * 2 min) before
+# being interrupted.
+Google::Apis::ClientOptions.default.send_timeout_sec = 3600
diff --git a/config/initializers/google_api_client_patch.rb b/config/initializers/google_api_client_patch.rb
new file mode 100644
index 00000000000..1408dcb0501
--- /dev/null
+++ b/config/initializers/google_api_client_patch.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'google/apis/core/http_command'
+
+raise 'This patch is only tested with google-api-client-ruby v0.50.0' unless Google::Apis::VERSION == "0.50.0"
+
+# The google-api-ruby-client does not have a way to increase or disable
+# the maximum allowed time for a request to be retried. By default, it
+# is using the Retriable gem's 15-minute timeout, which appears to be
+# too low for uploads over 10 GB. This patches the gem with the upstream
+# changes:
+# https://github.com/googleapis/google-api-ruby-client/pull/8106
+module Google
+ module Apis
+ module Core
+ # Command for HTTP request/response.
+ class HttpCommand
+ MAX_ELAPSED_TIME = 3600
+
+ # Execute the command, retrying as necessary
+ #
+ # @param [HTTPClient] client
+ # HTTP client
+ # @yield [result, err] Result or error if block supplied
+ # @return [Object]
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
+ def execute(client)
+ prepare!
+ opencensus_begin_span
+ begin
+ Retriable.retriable tries: options.retries + 1,
+ max_elapsed_time: MAX_ELAPSED_TIME,
+ base_interval: 1,
+ multiplier: 2,
+ on: RETRIABLE_ERRORS do |try|
+ # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
+ # auth to be re-attempted without having to retry all sorts of other failures like
+ # NotFound, etc
+ auth_tries = (try == 1 && authorization_refreshable? ? 2 : 1)
+ Retriable.retriable tries: auth_tries,
+ on: [Google::Apis::AuthorizationError, Signet::AuthorizationError, Signet::RemoteServerError, Signet::UnexpectedStatusError],
+ on_retry: proc { |*| refresh_authorization } do
+ execute_once(client).tap do |result|
+ if block_given?
+ yield result, nil
+ end
+ end
+ end
+ end
+ rescue => e # rubocop:disable Style/RescueStandardError
+ if block_given?
+ yield nil, e
+ else
+ raise e
+ end
+ end
+ ensure
+ opencensus_end_span
+ @http_res = nil
+ release!
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb
index f99333f7c82..4de6e706f16 100644
--- a/config/initializers/postgres_partitioning.rb
+++ b/config/initializers/postgres_partitioning.rb
@@ -3,7 +3,8 @@
Gitlab::Database::Partitioning.register_models([
AuditEvent,
WebHookLog,
- LooseForeignKeys::DeletedRecord
+ LooseForeignKeys::DeletedRecord,
+ Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog
])
if Gitlab.ee?
@@ -14,10 +15,12 @@ if Gitlab.ee?
else
Gitlab::Database::Partitioning.register_tables([
{
+ limit_connection_names: %i[main],
table_name: 'incident_management_pending_alert_escalations',
partitioned_column: :process_at, strategy: :monthly
},
{
+ limit_connection_names: %i[main],
table_name: 'incident_management_pending_issue_escalations',
partitioned_column: :process_at, strategy: :monthly
}
@@ -28,8 +31,9 @@ end
unless Gitlab.jh?
Gitlab::Database::Partitioning.register_tables([
# This should be synchronized with the following model:
- # https://gitlab.com/gitlab-jh/gitlab/-/blob/main-jh/jh/app/models/phone/verification_code.rb
+ # https://jihulab.com/gitlab-cn/gitlab/-/blob/main-jh/jh/app/models/phone/verification_code.rb
{
+ limit_connection_names: %i[main],
table_name: 'verification_codes',
partitioned_column: :created_at, strategy: :monthly
}
diff --git a/config/initializers/request_profiler.rb b/config/initializers/request_profiler.rb
index 2eb9f53d2a3..c368568ec51 100644
--- a/config/initializers/request_profiler.rb
+++ b/config/initializers/request_profiler.rb
@@ -3,4 +3,5 @@
Rails.application.configure do |config|
config.middleware.use(Gitlab::RequestProfiler::Middleware)
config.middleware.use(Gitlab::Middleware::Speedscope)
+ config.middleware.use(Gitlab::Middleware::MemoryReport)
end
diff --git a/config/initializers/rspec_profiling.rb b/config/initializers/rspec_profiling.rb
index 5edea6489ed..2ab7bdade31 100644
--- a/config/initializers/rspec_profiling.rb
+++ b/config/initializers/rspec_profiling.rb
@@ -62,7 +62,7 @@ RspecProfiling.configure do |config|
config.collector = RspecProfilingExt::Collectors::CSVWithTimestamps
config.csv_path = -> do
prefix = "#{ENV['CI_JOB_NAME']}-".gsub(%r{[ /]}, '-') if ENV['CI_JOB_NAME']
- "rspec_profiling/#{prefix}#{Time.now.to_i}-#{SecureRandom.hex(8)}-rspec-data.csv"
+ "#{ENV['RSPEC_PROFILING_FOLDER_PATH']}/#{prefix}#{Time.now.to_i}-#{SecureRandom.hex(8)}-rspec-data.csv"
end
end
end
diff --git a/config/initializers/rubyzip.rb b/config/initializers/rubyzip.rb
new file mode 100644
index 00000000000..622abc2e9d8
--- /dev/null
+++ b/config/initializers/rubyzip.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+#
+# Zip64 is needed to support archives with more than 65535 entries.
+Zip.write_zip64_support = true
diff --git a/config/initializers_before_autoloader/004_zeitwerk.rb b/config/initializers_before_autoloader/004_zeitwerk.rb
index 4d8dcf4de6b..60cc57c3282 100644
--- a/config/initializers_before_autoloader/004_zeitwerk.rb
+++ b/config/initializers_before_autoloader/004_zeitwerk.rb
@@ -4,6 +4,7 @@ Rails.autoloaders.each do |autoloader|
# We need to ignore these since these are non-Ruby files
# that do not define Ruby classes / modules
autoloader.ignore(Rails.root.join('lib/support'))
+ autoloader.ignore(Rails.root.join('lib/gitlab/ci/parsers/security/validators/schemas'))
autoloader.ignore(Rails.root.join('ee/lib/ee/gitlab/ci/parsers/security/validators/schemas')) if Gitlab.ee?
# Mailer previews are loaded manually by Rails
@@ -39,6 +40,7 @@ Rails.autoloaders.each do |autoloader|
'hangouts_chat_http_override' => 'HangoutsChatHTTPOverride',
'chunked_io' => 'ChunkedIO',
'http_io' => 'HttpIO',
+ 'jetbrains_plugin_activity_unique_counter' => 'JetBrainsPluginActivityUniqueCounter',
'json_formatter' => 'JSONFormatter',
'json_web_token' => 'JSONWebToken',
'as_json' => 'AsJSON',
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
index 04a0b5e34e9..aee0e602e7b 100644
--- a/config/metrics/aggregates/code_review.yml
+++ b/config/metrics/aggregates/code_review.yml
@@ -73,6 +73,7 @@
- 'i_code_review_post_merge_click_cherry_pick'
- 'i_code_review_post_merge_submit_revert_modal'
- 'i_code_review_post_merge_submit_cherry_pick_modal'
+ - 'i_code_review_user_jetbrains_api_request'
- name: code_review_category_monthly_active_users
operator: OR
source: redis
@@ -144,3 +145,4 @@
time_frame: [7d, 28d]
events:
- 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_jetbrains_api_request'
diff --git a/config/metrics/aggregates/common.yml b/config/metrics/aggregates/common.yml
index beabb72dd72..50d5122e806 100644
--- a/config/metrics/aggregates/common.yml
+++ b/config/metrics/aggregates/common.yml
@@ -1,6 +1,6 @@
# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/config/metrics/aggregates/common.yml
# instead of this file.
-#- name: unique name of aggregated metric
+# - name: unique name of aggregated metric
# operator: aggregation operator. Valid values are:
# - "OR": counts unique elements that were observed triggering any of following events
# - "AND": counts unique elements that were observed triggering all of following events
diff --git a/config/metrics/counts_28d/20210201124930_deployments.yml b/config/metrics/counts_28d/20210201124930_deployments.yml
index fc8c37f5a21..385bdb47484 100644
--- a/config/metrics/counts_28d/20210201124930_deployments.yml
+++ b/config/metrics/counts_28d/20210201124930_deployments.yml
@@ -5,7 +5,7 @@ description: Total deployments count for recent 28 days
product_section: ops
product_stage: release
product_group: group::ops release
-product_category:
+product_category:
value_type: number
status: active
milestone: "13.2"
diff --git a/config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml b/config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml
index 75871428fab..0b235a98677 100644
--- a/config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml
+++ b/config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml
@@ -1,7 +1,7 @@
---
data_category: optional
key_path: redis_hll_counters.analytics.i_analytics_cohorts_monthly
-description: "Unique visitors to /-/instance_statistics/cohorts"
+description: "Unique visitors to /-/instance_statistics/cohorts"
product_section: fulfillment
product_stage: fulfillment
product_group: group::utilization
diff --git a/config/metrics/counts_28d/20210216182125_user_sast_jobs.yml b/config/metrics/counts_28d/20210216182125_user_sast_jobs.yml
deleted file mode 100644
index e8d8b469b2e..00000000000
--- a/config/metrics/counts_28d/20210216182125_user_sast_jobs.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-data_category: operational
-key_path: usage_activity_by_stage_monthly.secure.user_sast_jobs
-description: Users who run a SAST job
-product_section: sec
-product_stage: secure
-product_group: group::static analysis
-product_category: static_application_security_testing
-value_type: number
-status: active
-time_frame: 28d
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-performance_indicator_type:
-- gmau
-- paid_gmau
-milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216182127_user_secret_detection_jobs.yml b/config/metrics/counts_28d/20210216182127_user_secret_detection_jobs.yml
deleted file mode 100644
index 67a1c63b528..00000000000
--- a/config/metrics/counts_28d/20210216182127_user_secret_detection_jobs.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-data_category: operational
-key_path: usage_activity_by_stage_monthly.secure.user_secret_detection_jobs
-description: Users who run a Secret Detection job
-product_section: sec
-product_stage: secure
-product_group: group::static analysis
-product_category: secret_detection
-value_type: number
-status: active
-time_frame: 28d
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-performance_indicator_type:
-- gmau
-- paid_gmau
-milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml b/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
index 72abf0b2165..ad5bba69a67 100644
--- a/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
+++ b/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
@@ -5,7 +5,7 @@ description: Internal Tracking to count number of unit tests parsed for planning
future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: code_testing
value_type: number
status: active
diff --git a/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
index 14042fc25f7..fc007008b87 100644
--- a/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
@@ -2,7 +2,6 @@
data_category: optional
key_path: redis_hll_counters.testing.testing_total_unique_counts_monthly
description: Total users for events under testing category
-product_section: devops
product_section: growth
product_stage: growth
product_group: group::product intelligence
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 1e3d07ed1da..05603ec14e0 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
@@ -91,6 +91,8 @@ options:
- p_ci_templates_jobs_secret_detection
- p_ci_templates_jobs_code_intelligence
- p_ci_templates_jobs_code_quality
+ - p_ci_templates_jobs_dependency_scanning
+ - p_ci_templates_jobs_license_scanning
- p_ci_templates_jobs_deploy_ecs
- p_ci_templates_jobs_deploy_ec2
- p_ci_templates_jobs_deploy
@@ -135,6 +137,8 @@ options:
- p_ci_templates_implicit_jobs_secret_detection
- p_ci_templates_implicit_jobs_code_intelligence
- p_ci_templates_implicit_jobs_code_quality
+ - p_ci_templates_implicit_jobs_dependency_scanning
+ - p_ci_templates_implicit_jobs_license_scanning
- p_ci_templates_implicit_jobs_deploy_ecs
- p_ci_templates_implicit_jobs_deploy_ec2
- p_ci_templates_implicit_auto_devops_deploy
@@ -162,6 +166,7 @@ options:
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
+ - p_ci_templates_qualys_iac_security
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml b/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
index bd178cb07bc..034eda07221 100644
--- a/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
+++ b/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
@@ -20,7 +20,5 @@ distribution:
- ce
tier:
- free
-tier:
-- free
- premium
- ultimate
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 2a4023c2e8a..7d8b1753990 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report
description: Count of expanding the code quality widget
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: code_quality
value_type: number
status: active
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 2332bce99a8..d0c8c0404fb 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_repor
description: Count of expanding the accessibility report widget
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: accessibility_testing
value_type: number
status: active
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 41be8f98889..1edc5ce21df 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.i_testing_summary_widget_total_monthly
description: Unique users that expand the test summary merge request widget by month
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: testing
value_type: number
status: active
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 1e196ab49c4..faa452f73a6 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
@@ -5,7 +5,7 @@ description: Number of users performing i_code_review_user_vs_code_api_request e
product_section: dev
product_stage: devops::create
product_group: group::code review
-product_category:
+product_category:
value_type: number
status: active
milestone: "13.12"
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 3d66f1cdf8c..5cbdd9afa54 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
@@ -5,7 +5,7 @@ description: Number of users performing at least one of the code review events
product_section: dev
product_stage: devops::create
product_group: group::code review
-product_category:
+product_category:
value_type: number
status: active
milestone: "13.12"
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
index 29ec7855453..c854fe7e34d 100644
--- 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
@@ -3,7 +3,6 @@ data_category: optional
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
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
index dceee0cc3ff..49500d88646 100644
--- 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
@@ -3,7 +3,6 @@ data_category: optional
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
diff --git a/config/metrics/counts_28d/20210902191057_i_quickactions_unapprove_monthly.yml b/config/metrics/counts_28d/20210902191057_i_quickactions_unapprove_monthly.yml
index ccefa1f5dd3..6cd2704b058 100644
--- a/config/metrics/counts_28d/20210902191057_i_quickactions_unapprove_monthly.yml
+++ b/config/metrics/counts_28d/20210902191057_i_quickactions_unapprove_monthly.yml
@@ -15,10 +15,6 @@ instrumentation_class: RedisHLLMetric
options:
events:
- i_quickactions_unapprove
-instrumentation_class: RedisHLLMetric
-options:
- events:
- - i_quickactions_unapprove
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml b/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml
index f8f7f9933cf..75e9fb02788 100644
--- a/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml
+++ b/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_expanding_testing_license_compliance_report
distribution:
- ce
diff --git a/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml b/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml
index 638a64b20ce..96e1bc1f949 100644
--- a/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml
+++ b/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_visiting_testing_license_compliance_full_report
distribution:
- ce
diff --git a/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml b/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml
index 81b728a5ebd..dc4bc631759 100644
--- a/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml
+++ b/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_visiting_testing_manage_license_compliance
distribution:
- ce
diff --git a/config/metrics/counts_28d/20211216083832_users_clicking_license_testing_visiting_external_website_monthly.yml b/config/metrics/counts_28d/20211216083832_users_clicking_license_testing_visiting_external_website_monthly.yml
index 24f062f9a10..99b64d7a379 100644
--- a/config/metrics/counts_28d/20211216083832_users_clicking_license_testing_visiting_external_website_monthly.yml
+++ b/config/metrics/counts_28d/20211216083832_users_clicking_license_testing_visiting_external_website_monthly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76917
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_clicking_license_testing_visiting_external_website
distribution:
- ce
@@ -22,4 +22,4 @@ distribution:
tier:
- free
- premium
- - ultimate \ No newline at end of file
+ - ultimate
diff --git a/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml b/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml
new file mode 100644
index 00000000000..e26732ec916
--- /dev/null
+++ b/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_qualys_iac_security_monthly
+description: ""
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category: ""
+value_type: number
+status: active
+milestone: "14.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77362
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_qualys_iac_security
diff --git a/config/metrics/counts_28d/20220121140644_user_jetbrains_api_request_monthly.yml b/config/metrics/counts_28d/20220121140644_user_jetbrains_api_request_monthly.yml
new file mode 100644
index 00000000000..deae309753a
--- /dev/null
+++ b/config/metrics/counts_28d/20220121140644_user_jetbrains_api_request_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_jetbrains_api_request_monthly
+description: Count of unique users per month who use GitLab plugin for JetBrains
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: editor_extension
+value_type: number
+status: active
+milestone: "14.8"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_user_jetbrains_api_request
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220131143209_i_quickactions_attention_monthly.yml b/config/metrics/counts_28d/20220131143209_i_quickactions_attention_monthly.yml
new file mode 100644
index 00000000000..a7ae893ebe9
--- /dev/null
+++ b/config/metrics/counts_28d/20220131143209_i_quickactions_attention_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_attention_monthly
+description: Count of MAU using the `/attention` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_attention
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220131153230_i_quickactions_remove_attention_monthly.yml b/config/metrics/counts_28d/20220131153230_i_quickactions_remove_attention_monthly.yml
new file mode 100644
index 00000000000..3f6fe27c6e4
--- /dev/null
+++ b/config/metrics/counts_28d/20220131153230_i_quickactions_remove_attention_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_attention_monthly
+description: Count of MAU using the `/remove_attention` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_remove_attention
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_monthly.yml b/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_monthly.yml
new file mode 100644
index 00000000000..8f913307356
--- /dev/null
+++ b/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_monthly
+description: Monthly counts for implicit use of Dependency Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_dependency_scanning
diff --git a/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_monthly.yml b/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_monthly.yml
new file mode 100644
index 00000000000..2b776b28c5d
--- /dev/null
+++ b/config/metrics/counts_28d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_monthly
+description: Monthly counts for implicit use of License Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: license_compliance
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_license_scanning
diff --git a/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_dependency_scanning_monthly.yml b/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_dependency_scanning_monthly.yml
new file mode 100644
index 00000000000..6d166725a67
--- /dev/null
+++ b/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_dependency_scanning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_dependency_scanning_monthly
+description: Monthly counts for Dependency Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_dependency_scanning
diff --git a/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_license_scanning_monthly.yml b/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_license_scanning_monthly.yml
new file mode 100644
index 00000000000..db215d242e0
--- /dev/null
+++ b/config/metrics/counts_28d/20220210134101_p_ci_templates_jobs_license_scanning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_license_scanning_monthly
+description: Monthly counts for License Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: license_compliance
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_license_scanning
diff --git a/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml b/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
index 94748444af5..1dd4cc50c09 100644
--- a/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
+++ b/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
@@ -5,7 +5,7 @@ description: Internal Tracking to count number of unit tests parsed for planning
future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: code_testing
value_type: number
status: active
diff --git a/config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml b/config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml
index 2a70231dcac..b5d9e4f7992 100644
--- a/config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml
+++ b/config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml
@@ -15,7 +15,6 @@ options:
events:
- p_ci_templates_implicit_security_sast
distribution:
-distribution:
- ce
- ee
tier:
diff --git a/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml b/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
index b06a4fa5577..408c03894fd 100644
--- a/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
+++ b/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
@@ -25,4 +25,3 @@ tier:
- premium
- ultimate
performance_indicator_type: []
-milestone: "<13.9"
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
index 8d545b91d1f..290ceb5754a 100644
--- 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
@@ -91,6 +91,8 @@ options:
- p_ci_templates_jobs_secret_detection
- p_ci_templates_jobs_code_intelligence
- p_ci_templates_jobs_code_quality
+ - p_ci_templates_jobs_dependency_scanning
+ - p_ci_templates_jobs_license_scanning
- p_ci_templates_jobs_deploy_ecs
- p_ci_templates_jobs_deploy_ec2
- p_ci_templates_jobs_deploy
@@ -135,6 +137,8 @@ options:
- p_ci_templates_implicit_jobs_secret_detection
- p_ci_templates_implicit_jobs_code_intelligence
- p_ci_templates_implicit_jobs_code_quality
+ - p_ci_templates_implicit_jobs_dependency_scanning
+ - p_ci_templates_implicit_jobs_license_scanning
- p_ci_templates_implicit_jobs_deploy_ecs
- p_ci_templates_implicit_jobs_deploy_ec2
- p_ci_templates_implicit_auto_devops_deploy
@@ -162,6 +166,7 @@ options:
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
+ - p_ci_templates_qualys_iac_security
distribution:
- ce
- ee
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 e4f3d64e93c..2a26794ed92 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report
description: Count of expanding the code quality widget
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: code_quality
value_type: number
status: active
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 6a4d2184190..87e8873ed00 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_repor
description: Count of expanding the accessibility report widget
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: accessibility_testing
value_type: number
status: active
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 6adf4d0c092..2b378da8347 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
@@ -4,7 +4,7 @@ key_path: redis_hll_counters.testing.i_testing_summary_widget_total_weekly
description: Unique users that expand the test summary merge request widget by week
product_section: ops
product_stage: verify
-product_group: group::testing
+product_group: group::pipeline insights
product_category: testing
value_type: number
status: active
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 112e8655d37..fa58494cc05 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
@@ -18,4 +18,3 @@ tier:
- free
- premium
- ultimate
-
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 8680e59f141..e1c61db272b 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
@@ -19,4 +19,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_7d/20210902191054_i_quickactions_unapprove_weekly.yml b/config/metrics/counts_7d/20210902191054_i_quickactions_unapprove_weekly.yml
index 38659cdba82..b3a4699307e 100644
--- a/config/metrics/counts_7d/20210902191054_i_quickactions_unapprove_weekly.yml
+++ b/config/metrics/counts_7d/20210902191054_i_quickactions_unapprove_weekly.yml
@@ -15,10 +15,6 @@ instrumentation_class: RedisHLLMetric
options:
events:
- i_quickactions_unapprove
-instrumentation_class: RedisHLLMetric
-options:
- events:
- - i_quickactions_unapprove
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml
index e7e2c096902..4fb9a64a234 100644
--- a/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml
+++ b/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml
@@ -12,7 +12,6 @@ milestone: "14.5"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
time_frame: 7d
data_source: redis_hll
-data_category: optional
instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
diff --git a/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml b/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml
index b96d0fff1bd..ae251b65362 100644
--- a/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml
+++ b/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_expanding_testing_license_compliance_report
distribution:
- ce
diff --git a/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml b/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml
index 4a6ee19fffe..96c2fb4ced9 100644
--- a/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml
+++ b/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_visiting_testing_license_compliance_full_report
distribution:
- ce
diff --git a/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml b/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml
index 9bff8263121..831ec2509b1 100644
--- a/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml
+++ b/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_visiting_testing_manage_license_compliance
distribution:
- ce
diff --git a/config/metrics/counts_7d/20211216084934_users_clicking_license_testing_visiting_external_website_weekly.yml b/config/metrics/counts_7d/20211216084934_users_clicking_license_testing_visiting_external_website_weekly.yml
index aaa5a4f2675..cfdbc345ef9 100644
--- a/config/metrics/counts_7d/20211216084934_users_clicking_license_testing_visiting_external_website_weekly.yml
+++ b/config/metrics/counts_7d/20211216084934_users_clicking_license_testing_visiting_external_website_weekly.yml
@@ -13,8 +13,8 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76917
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
-options:
- events:
+options:
+ events:
- users_clicking_license_testing_visiting_external_website
distribution:
- ce
diff --git a/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml b/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml
new file mode 100644
index 00000000000..e5003f969eb
--- /dev/null
+++ b/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_qualys_iac_security_weekly
+description: ""
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category: ""
+value_type: number
+status: active
+milestone: "14.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77362
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_qualys_iac_security
diff --git a/config/metrics/counts_7d/20220121140634_user_jetbrains_api_request_weekly.yml b/config/metrics/counts_7d/20220121140634_user_jetbrains_api_request_weekly.yml
new file mode 100644
index 00000000000..40e7b3ba04f
--- /dev/null
+++ b/config/metrics/counts_7d/20220121140634_user_jetbrains_api_request_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_jetbrains_api_request_weekly
+description: Count of unique users per month who use GitLab plugin for JetBrains
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: editor_extension
+value_type: number
+status: active
+milestone: "14.8"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_user_jetbrains_api_request
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220131143201_i_quickactions_attention_weekly.yml b/config/metrics/counts_7d/20220131143201_i_quickactions_attention_weekly.yml
new file mode 100644
index 00000000000..2bd6c25281d
--- /dev/null
+++ b/config/metrics/counts_7d/20220131143201_i_quickactions_attention_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_attention_weekly
+description: Count of WAU using the `/attention` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_attention
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20220131153223_i_quickactions_remove_attention_weekly.yml b/config/metrics/counts_7d/20220131153223_i_quickactions_remove_attention_weekly.yml
new file mode 100644
index 00000000000..38f9841f447
--- /dev/null
+++ b/config/metrics/counts_7d/20220131153223_i_quickactions_remove_attention_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_attention_weekly
+description: Count of WAU using the `/remove_attention` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_remove_attention
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_weekly.yml b/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_weekly.yml
new file mode 100644
index 00000000000..cc04ade9317
--- /dev/null
+++ b/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_dependency_scanning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_weekly
+description: Weekly counts for implicit use of Dependency Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_dependency_scanning
diff --git a/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_weekly.yml b/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_weekly.yml
new file mode 100644
index 00000000000..78256aeeea8
--- /dev/null
+++ b/config/metrics/counts_7d/20220210134101_p_ci_templates_implicit_jobs_license_scanning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_weekly
+description: Weekly counts for implicit use of License Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: license_compliance
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_license_scanning
diff --git a/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_dependency_scanning_weekly.yml b/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_dependency_scanning_weekly.yml
new file mode 100644
index 00000000000..19bf2cf65ba
--- /dev/null
+++ b/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_dependency_scanning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_dependency_scanning_weekly
+description: Weekly counts for Dependency Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_dependency_scanning
diff --git a/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_license_scanning_weekly.yml b/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_license_scanning_weekly.yml
new file mode 100644
index 00000000000..c8977d75e9c
--- /dev/null
+++ b/config/metrics/counts_7d/20220210134101_p_ci_templates_jobs_license_scanning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_license_scanning_weekly
+description: Weekly counts for License Scanning CI template (Jobs folder)
+product_section: sec
+product_stage: secure
+product_group: composition_analysis
+product_category: license_compliance
+value_type: number
+status: active
+milestone: '14.8'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79454
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_license_scanning
diff --git a/config/metrics/counts_all/20210216175206_merged_merge_requests_using_approval_rules.yml b/config/metrics/counts_all/20210216175206_merged_merge_requests_using_approval_rules.yml
deleted file mode 100644
index d71c35ef2e2..00000000000
--- a/config/metrics/counts_all/20210216175206_merged_merge_requests_using_approval_rules.yml
+++ /dev/null
@@ -1,21 +0,0 @@
----
-data_category: optional
-key_path: counts.merged_merge_requests_using_approval_rules
-description: Count of merge requests merged using approval rules
-product_section: dev
-product_stage: manage
-product_group: group::compliance
-product_category: compliance_management
-value_type: number
-status: active
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-performance_indicator_type: []
-milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210216180451_incident_labeled_issues.yml b/config/metrics/counts_all/20210216180451_incident_labeled_issues.yml
index cc38c8e75ad..635dcd57168 100644
--- a/config/metrics/counts_all/20210216180451_incident_labeled_issues.yml
+++ b/config/metrics/counts_all/20210216180451_incident_labeled_issues.yml
@@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: incident_management
value_type: number
-status: active
+status: removed
time_frame: all
data_source: database
distribution:
@@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
+milestone_removed: "14.8"
diff --git a/config/metrics/counts_all/20210216182116_user_sast_jobs.yml b/config/metrics/counts_all/20210216182116_user_sast_jobs.yml
deleted file mode 100644
index b4822d0d89b..00000000000
--- a/config/metrics/counts_all/20210216182116_user_sast_jobs.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-data_category: operational
-key_path: usage_activity_by_stage.secure.user_sast_jobs
-description: Count of SAST jobs per user
-product_section: sec
-product_stage: secure
-product_group: group::static analysis
-product_category: static_application_security_testing
-value_type: number
-status: active
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210216182118_user_secret_detection_jobs.yml b/config/metrics/counts_all/20210216182118_user_secret_detection_jobs.yml
deleted file mode 100644
index 6dde13f823b..00000000000
--- a/config/metrics/counts_all/20210216182118_user_secret_detection_jobs.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-data_category: operational
-key_path: usage_activity_by_stage.secure.user_secret_detection_jobs
-description: Count of Secret Detection Jobs per user
-product_section: sec
-product_stage: secure
-product_group: group::static analysis
-product_category: secret_detection
-value_type: number
-status: active
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210216183023_wiki_pages_view.yml b/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
index c4cc4bfcf9c..16cec4839a5 100644
--- a/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
+++ b/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
@@ -20,4 +20,3 @@ tier:
- premium
- ultimate
performance_indicator_type: []
-milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml b/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml
index 0ba6d527e3a..73b2e4a5a25 100644
--- a/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml
+++ b/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml
@@ -19,4 +19,3 @@ tier:
- free
- premium
- ultimate
-
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 b769b5d47f1..5a7073d3525 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
@@ -18,4 +18,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
index e558763e2a0..a1a49a1a07e 100644
--- a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
+++ b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
@@ -9,7 +9,7 @@ product_category: kubernetes_management
value_type: number
status: active
milestone: '13.12'
-introduced_by_url:
+introduced_by_url:
time_frame: all
data_source: redis
distribution:
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 cb5f3185eb0..92209dffa2d 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
@@ -20,4 +20,3 @@ tier:
- free
- premium
- ultimate
-
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 ab50a629468..a864858ae3a 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
@@ -20,4 +20,3 @@ tier:
- free
- premium
- ultimate
-
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 2b08899e228..6675c6e9a0b 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
@@ -20,4 +20,3 @@ tier:
- free
- premium
- ultimate
-
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 67543b98020..0b68b88570c 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
@@ -20,4 +20,3 @@ tier:
- free
- premium
- ultimate
-
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 3d5150f6042..7bb67a87c75 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
@@ -20,4 +20,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml b/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml
index 8edd10b3a42..7d390649020 100644
--- a/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml
+++ b/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml
@@ -19,4 +19,4 @@ distribution:
tier:
- free
- premium
-- ultimate \ No newline at end of file
+- ultimate
diff --git a/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml b/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml
index 33b164a9653..c80ddea659f 100644
--- a/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml
+++ b/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml
@@ -19,4 +19,4 @@ distribution:
tier:
- free
- premium
-- ultimate \ No newline at end of file
+- ultimate
diff --git a/config/metrics/counts_all/20220122022215_web_ide_previews_success.yml b/config/metrics/counts_all/20220122022215_web_ide_previews_success.yml
new file mode 100644
index 00000000000..4042e892a61
--- /dev/null
+++ b/config/metrics/counts_all/20220122022215_web_ide_previews_success.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.web_ide_previews_success
+description: Count of Live Preview tab successful initializations in the Web IDE
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: web_ide
+value_type: number
+status: active
+time_frame: all
+data_source: redis
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+performance_indicator_type: []
+milestone: "14.8"
diff --git a/config/metrics/settings/20210323120839_topology.yml b/config/metrics/settings/20210323120839_topology.yml
index a254ad36dfe..d07de69e530 100644
--- a/config/metrics/settings/20210323120839_topology.yml
+++ b/config/metrics/settings/20210323120839_topology.yml
@@ -5,7 +5,7 @@ description: Topology data
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category:
+product_category:
value_type: object
status: active
milestone: "13.11"
diff --git a/config/routes.rb b/config/routes.rb
index 5d20d070c20..a57795bea0c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -170,7 +170,6 @@ Rails.application.routes.draw do
Gitlab.ee do
draw :security
draw :smartcard
- draw :username
draw :trial
draw :trial_registration
draw :country
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index ed1afc9efa3..6b786fc82b3 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -145,6 +145,8 @@ namespace :admin do
delete :delete_self_monitoring_project
get :status_delete_self_monitoring_project
+ get :service_usage_data
+
resource :appearances, only: [:show, :create, :update], path: 'appearance', module: 'application_settings' do
member do
get :preview_sign_in
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 702ef64a2ca..8536ec9fc05 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -158,6 +158,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'milestones'
get 'commands'
get 'snippets'
+ get 'contacts'
end
end
@@ -464,6 +465,16 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
namespace :integrations do
resource :shimo, only: [:show]
end
+
+ get :planning_hierarchy
+
+ resources :badges, only: [] do
+ collection do
+ constraints format: /svg/ do
+ get :release
+ end
+ end
+ end
end
# End of the /-/ scope.
@@ -580,6 +591,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
scope :service_ping, controller: :service_ping do
post :web_ide_clientside_preview # rubocop:todo Cop/PutProjectRoutesUnderScope
+ post :web_ide_clientside_preview_success # rubocop:todo Cop/PutProjectRoutesUnderScope
post :web_ide_pipelines_count # rubocop:todo Cop/PutProjectRoutesUnderScope
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index bf84527bc5f..401471d02d9 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -35,14 +35,20 @@
- 1
- - analytics_usage_trends_counter_job
- 1
+- - app_sec_dast_scanner_profiles_builds_consistency
+ - 1
- - app_sec_dast_scans_consistency
- 1
+- - app_sec_dast_site_profiles_builds_consistency
+ - 1
- - approval_rules_external_approval_rule_payload
- 1
- - approve_blocked_pending_approval_users
- 1
- - audit_events_audit_event_streaming
- 1
+- - audit_events_user_impersonation_event_create
+ - 1
- - authorized_keys
- 2
- - authorized_project_update
@@ -55,6 +61,8 @@
- 3
- - background_migration
- 1
+- - background_migration_ci_database
+ - 1
- - bulk_import
- 1
- - bulk_imports_entity
@@ -79,6 +87,8 @@
- 1
- - cluster_agent
- 1
+- - compliance_management_merge_requests_compliance_violations
+ - 1
- - container_repository
- 1
- - create_commit_signature
@@ -175,6 +185,8 @@
- 1
- - gitlab_shell
- 2
+- - gitlab_subscriptions_notify_seats_exceeded
+ - 1
- - group_destroy
- 1
- - group_export
@@ -285,6 +297,8 @@
- 1
- - namespaces_sync_namespace_name
- 1
+- - namespaces_update_root_statistics
+ - 1
- - new_epic
- 2
- - new_issue
@@ -311,8 +325,6 @@
- 1
- - pages_transfer
- 1
-- - pages_update_configuration
- - 1
- - personal_access_tokens
- 1
- - phabricator_import_import_tasks
@@ -401,6 +413,8 @@
- 1
- - security_auto_fix
- 1
+- - security_findings_delete_by_job_id
+ - 1
- - security_scans
- 2
- - self_monitoring_project_create
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 912c2fe5c45..7b559c8881b 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -38,11 +38,10 @@ const SUPPORTED_BROWSERS_HASH = crypto
const VENDOR_DLL = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_DLL !== 'false';
const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
-const IS_DEV_SERVER = process.env.WEBPACK_DEV_SERVER === 'true';
+const IS_DEV_SERVER = process.env.WEBPACK_SERVE === 'true';
-const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
-const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
-const { DEV_SERVER_PUBLIC_ADDR } = process.env;
+const { DEV_SERVER_HOST, DEV_SERVER_PUBLIC_ADDR } = process.env;
+const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10);
const DEV_SERVER_ALLOWED_HOSTS =
process.env.DEV_SERVER_ALLOWED_HOSTS && process.env.DEV_SERVER_ALLOWED_HOSTS.split(',');
const DEV_SERVER_HTTPS = process.env.DEV_SERVER_HTTPS && process.env.DEV_SERVER_HTTPS !== 'false';
@@ -144,12 +143,15 @@ function generateEntries() {
performance_bar: './performance_bar/index.js',
jira_connect_app: './jira_connect/subscriptions/index.js',
sandboxed_mermaid: './lib/mermaid.js',
+ redirect_listbox: './entrypoints/behaviors/redirect_listbox.js',
};
return Object.assign(manualEntries, incrementalCompiler.filterEntryPoints(autoEntries));
}
const alias = {
+ // Map Apollo client to apollo/client/core to prevent react related imports from being loaded
+ '@apollo/client$': '@apollo/client/core',
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
empty_states: path.join(ROOT_PATH, 'app/views/shared/empty_states'),
@@ -260,8 +262,7 @@ module.exports = {
{
test: /\.js$/,
exclude: (modulePath) =>
- /node_modules\/(?!tributejs)|node_modules|vendor[\\/]assets/.test(modulePath) &&
- !/\.vue\.js/.test(modulePath),
+ /node_modules|vendor[\\/]assets/.test(modulePath) && !/\.vue\.js/.test(modulePath),
loader: 'babel-loader',
options: {
cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
@@ -655,9 +656,6 @@ module.exports = {
},
},
- // enable HMR only in webpack-dev-server
- DEV_SERVER_LIVERELOAD && new webpack.HotModuleReplacementPlugin(),
-
// optionally generate webpack bundle analysis
WEBPACK_REPORT &&
new BundleAnalyzerPlugin({
@@ -690,19 +688,38 @@ module.exports = {
*/
new webpack.IgnorePlugin(/moment/, /pikaday/),
].filter(Boolean),
+
devServer: {
- before(app, server) {
- incrementalCompiler.setupMiddleware(app, server);
+ setupMiddlewares: (middlewares, devServer) => {
+ if (!devServer) {
+ throw new Error('webpack-dev-server is not defined');
+ }
+
+ const incrementalCompilerMiddleware = incrementalCompiler.createMiddleware(devServer);
+
+ if (incrementalCompilerMiddleware) {
+ middlewares.unshift(incrementalCompilerMiddleware);
+ }
+
+ return middlewares;
},
- host: DEV_SERVER_HOST,
- port: DEV_SERVER_PORT,
- public: DEV_SERVER_PUBLIC_ADDR,
- allowedHosts: DEV_SERVER_ALLOWED_HOSTS,
+ // Only print errors to CLI
+ devMiddleware: {
+ stats: 'errors-only',
+ },
+ host: DEV_SERVER_HOST || 'localhost',
+ port: DEV_SERVER_PORT || 3808,
https: DEV_SERVER_HTTPS,
- contentBase: false,
- stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD,
- inline: DEV_SERVER_LIVERELOAD,
+ // The following settings are mainly needed for HMR support in gitpod.
+ // Per default only local hosts are allowed, but here we could
+ // allow different hosts (e.g. ['.gitpod'], all of gitpod),
+ // as the webpack server will run on a different subdomain than
+ // the rails application
+ ...(DEV_SERVER_ALLOWED_HOSTS ? { allowedHosts: DEV_SERVER_ALLOWED_HOSTS } : {}),
+ client: {
+ ...(DEV_SERVER_PUBLIC_ADDR ? { webSocketURL: DEV_SERVER_PUBLIC_ADDR } : {}),
+ },
},
devtool: NO_SOURCEMAPS ? false : devtool,
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index 84fd993ed14..30d60c0b5e6 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -47,7 +47,7 @@ module.exports = {
'bootstrap/dist/js/bootstrap.js',
'sortablejs/modular/sortable.esm.js',
'popper.js',
- 'apollo-client',
+ '@apollo/client/core',
'source-map',
'mousetrap',
],
diff --git a/danger/sidekiq_queues/Dangerfile b/danger/sidekiq_queues/Dangerfile
index b40be7a486e..de98af3cab2 100644
--- a/danger/sidekiq_queues/Dangerfile
+++ b/danger/sidekiq_queues/Dangerfile
@@ -3,7 +3,7 @@
SCALABILITY_REVIEW_MESSAGE = <<~MSG
## Sidekiq queue changes
-This merge request contains changes to Sidekiq queues. Please follow the [documentation on changing a queue's urgency](https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#changing-a-queues-urgency).
+This merge request contains changes to Sidekiq queues. Please follow the [documentation on changing a queue's urgency](https://docs.gitlab.com/ee/development/sidekiq/worker_attributes.html#job-urgency).
MSG
ADDED_QUEUES_MESSAGE = <<~MSG
diff --git a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
index 7e2d8338dfd..fd5db7f8835 100644
--- a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
+++ b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
@@ -1,4 +1,4 @@
-- name: "NFS for Git repository storage deprecated" # The name of the feature to be deprecated
+- name: "NFS for Git repository storage" # The name of the feature to be deprecated
announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-3-repository-push-audit-events.yml b/data/deprecations/14-3-repository-push-audit-events.yml
index 72281be5e97..97a7a01b593 100644
--- a/data/deprecations/14-3-repository-push-audit-events.yml
+++ b/data/deprecations/14-3-repository-push-audit-events.yml
@@ -5,7 +5,7 @@
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: | # Do not modify this line, instead modify the lines below.
- Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push) are now deprecated and will be removed in GitLab 15.0.
+ Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push-deprecated) are now deprecated and will be removed in GitLab 15.0.
These events have always been disabled by default and had to be manually enabled with a
feature flag. Enabling them can cause too many events to be generated which can
@@ -13,4 +13,4 @@
stage: Manage
tiers: Premium
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337993
- documentation_url: https://docs.gitlab.com/ee/administration/audit_events.html#repository-push
+ documentation_url: https://docs.gitlab.com/ee/administration/audit_events.html#repository-push-deprecated
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
index 60664f785b2..698d8b0dc69 100644
--- a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
@@ -1,19 +1,23 @@
- name: "Certificate-based integration with Kubernetes"
announcement_milestone: "14.5"
announcement_date: "2021-11-15"
- removal_milestone: "15.0"
- removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
+ removal_milestone: "15.6"
+ removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: |
[We are deprecating the certificate-based integration with Kubernetes](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
- The timeline of removal of the integration from the product is not yet planned and we will communicate
- more details as they emerge. The certificate-based integration will continue to receive security and
+ The timeline of removal of the integration from the product is planned to happen in two steps, starting with milestone 15.0 and finishing in GitLab version 15.6.
+
+ In 15.0, we plan to introduce a feature flag that will allow GitLab Self-Managed customers to keep the certificate-based integration enabled, it will be disabled by default. We plan to remove this feature flag together with the underlying code in GitLab version 15.6.
+ The certificate-based integration will continue to receive security and
critical fixes, and features built on the integration will continue to work with supported Kubernetes
- versions. We will provide migration plans in a future iteration. See [the list of features affected by this deprecation](https://docs.gitlab.com/ee/user/infrastructure/clusters/#deprecated-features).
- For updates and details, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+ versions until the final removal in 15.6.
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend the use of the
- [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
+ [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
+ We provide [migration plans](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) in the documentation.
+
+ For updates and details around this deprecation, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
stage: Configure
tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'
diff --git a/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
index b33f2cc88f1..9cf806da021 100644
--- a/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
+++ b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
@@ -1,4 +1,4 @@
-- name: "Converting an instance (shared) runner to a project (specific) runner is deprecated"
+- name: "Converting an instance (shared) runner to a project (specific) runner"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml b/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
index 6fb97cbc7f4..af172f47ed1 100644
--- a/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
+++ b/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
@@ -1,4 +1,4 @@
-- name: "Removal of `defaultMergeCommitMessageWithDescription` GraphQL API field" # The name of the feature to be deprecated
+- name: "`defaultMergeCommitMessageWithDescription` GraphQL API field" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-deprecate-sles-12sp2.yml b/data/deprecations/14-5-deprecate-sles-12sp2.yml
index 61e989defd3..9c6d1f6da52 100644
--- a/data/deprecations/14-5-deprecate-sles-12sp2.yml
+++ b/data/deprecations/14-5-deprecate-sles-12sp2.yml
@@ -1,4 +1,4 @@
-- name: "Deprecate support for SLES 12 SP2" # The name of the feature to be deprecated
+- name: "Support for SLES 12 SP2" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-deprecation-versions-packagetype.yml b/data/deprecations/14-5-deprecation-versions-packagetype.yml
index 78db5c0d414..92188b1b21d 100644
--- a/data/deprecations/14-5-deprecation-versions-packagetype.yml
+++ b/data/deprecations/14-5-deprecation-versions-packagetype.yml
@@ -1,4 +1,4 @@
-- name: "Deprecate `Versions` on base `PackageType`"
+- name: "`Versions` on base `PackageType`"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-geo-deprecate-promote-db.yml b/data/deprecations/14-5-geo-deprecate-promote-db.yml
index 113ddc53165..81a2d10e35b 100644
--- a/data/deprecations/14-5-geo-deprecate-promote-db.yml
+++ b/data/deprecations/14-5-geo-deprecate-promote-db.yml
@@ -1,4 +1,4 @@
-- name: "Removal of `promote-db` command from `gitlab-ctl`" # The name of the feature to be deprecated
+- name: "`promote-db` command from `gitlab-ctl`" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml b/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml
index 591ca6f6a87..bbecfcd65ec 100644
--- a/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml
+++ b/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml
@@ -1,4 +1,4 @@
-- name: "Removal of `promote-to-primary-node` command from `gitlab-ctl`" # The name of the feature to be deprecated
+- name: "`promote-to-primary-node` command from `gitlab-ctl`" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-remove-dependency-proxy-permissions-flag.yml b/data/deprecations/14-5-remove-dependency-proxy-permissions-flag.yml
index 1e6a4e7d378..098be766942 100644
--- a/data/deprecations/14-5-remove-dependency-proxy-permissions-flag.yml
+++ b/data/deprecations/14-5-remove-dependency-proxy-permissions-flag.yml
@@ -1,4 +1,4 @@
-- name: "Remove the `:dependency_proxy_for_private_groups` feature flag" # The name of the feature to be deprecated
+- name: "`dependency_proxy_for_private_groups` feature flag" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-remove-pipelines-from-version-field.yml b/data/deprecations/14-5-remove-pipelines-from-version-field.yml
index 917442219e5..fc8ec519fa7 100644
--- a/data/deprecations/14-5-remove-pipelines-from-version-field.yml
+++ b/data/deprecations/14-5-remove-pipelines-from-version-field.yml
@@ -1,4 +1,4 @@
-- name: "Remove the `pipelines` field from the `version` field" # The name of the feature to be deprecated
+- name: "`pipelines` field from the `version` field" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
index dd2e6e7a6fb..c3fbe553706 100644
--- a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
+++ b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
@@ -1,4 +1,4 @@
-- name: "REST API Runner will not contain `paused`"
+- name: "REST and GraphQL API Runner status will not return `paused`"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
@@ -11,7 +11,7 @@
`online`, `offline`, or `not_connected`. Status `paused` or `active` will no longer appear.
When checking if a runner is `paused`, API users are advised to check the boolean attribute
- `active` to be `false` instead. When checking if a runner is `active`, check if `active` is `true`.
+ `paused` to be `true` instead. When checking if a runner is `active`, check if `paused` is `false`.
stage: Verify
tiers: [Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344648
diff --git a/data/deprecations/14-6-deprecate-types.yml b/data/deprecations/14-6-deprecate-types.yml
index 3e04ad1d6fe..f8886eeef37 100644
--- a/data/deprecations/14-6-deprecate-types.yml
+++ b/data/deprecations/14-6-deprecate-types.yml
@@ -1,4 +1,4 @@
-- name: "Remove `type` and `types` keyword in CI/CD configuration" # The name of the feature to be deprecated
+- name: "`type` and `types` keyword in CI/CD configuration" # The name of the feature to be deprecated
announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml b/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml
index 55c74ddfabd..e09205f2d9b 100644
--- a/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml
+++ b/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml
@@ -1,4 +1,4 @@
-- name: "Deprecate legacy approval status names from License Compliance API" # The name of the feature to be deprecated
+- name: "Legacy approval status names from License Compliance API" # The name of the feature to be deprecated
announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml b/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml
index 8cf0ddc49f4..4f4a2ad8a7d 100644
--- a/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml
+++ b/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml
@@ -1,4 +1,4 @@
-- name: "Deprecation of bundler-audit Dependency Scanning tool" # The name of the feature to be deprecated
+- name: "bundler-audit Dependency Scanning tool" # The name of the feature to be deprecated
announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-6-pipeline-fields-package-deprecation.yml b/data/deprecations/14-6-pipeline-fields-package-deprecation.yml
index b9140a84cdd..897886d2d0b 100644
--- a/data/deprecations/14-6-pipeline-fields-package-deprecation.yml
+++ b/data/deprecations/14-6-pipeline-fields-package-deprecation.yml
@@ -1,4 +1,4 @@
-- name: "Deprecate `pipelines` fields in the Package GraphQL types"
+- name: "`pipelines` fields in the Package GraphQL types"
announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-6-runner-api-status-renames-not_connected.yml b/data/deprecations/14-6-runner-api-status-renames-not_connected.yml
index 5654d3227eb..a535cfbf7a7 100644
--- a/data/deprecations/14-6-runner-api-status-renames-not_connected.yml
+++ b/data/deprecations/14-6-runner-api-status-renames-not_connected.yml
@@ -1,4 +1,4 @@
-- name: "Deprecation of Runner status `not_connected` API value"
+- name: "Runner status `not_connected` API value"
announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
removal_date: "2022-05-22"
diff --git a/data/deprecations/14-7-deprecate-artifacts-keyword.yml b/data/deprecations/14-7-deprecate-artifacts-keyword.yml
index cbd1a6d41e5..20be00ef6d0 100644
--- a/data/deprecations/14-7-deprecate-artifacts-keyword.yml
+++ b/data/deprecations/14-7-deprecate-artifacts-keyword.yml
@@ -1,4 +1,4 @@
-- name: "Removal of `artifacts:report:cobertura` keyword"
+- name: "`artifacts:report:cobertura` keyword"
announcement_milestone: "14.7"
announcement_date: "2022-01-22"
removal_milestone: "15.0"
diff --git a/data/deprecations/14-7-deprecate-merged_by-api-field.yml b/data/deprecations/14-7-deprecate-merged_by-api-field.yml
index 31b2d9c9244..e2ecef1aa6a 100644
--- a/data/deprecations/14-7-deprecate-merged_by-api-field.yml
+++ b/data/deprecations/14-7-deprecate-merged_by-api-field.yml
@@ -15,7 +15,7 @@
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
- breaking_change: false # If this deprecation is a breaking change, set this value to true
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below.
The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `merge_user` field (already present in GraphQL) which more correctly identifies who merged a merge request when performing actions (merge when pipeline succeeds, add to merge train) other than a simple merge.
# The following items are not published on the docs page, but may be used in the future.
diff --git a/data/deprecations/14-7-deprecate-static-site-editor.yml b/data/deprecations/14-7-deprecate-static-site-editor.yml
index d8acfbf8ab3..e522699e823 100644
--- a/data/deprecations/14-7-deprecate-static-site-editor.yml
+++ b/data/deprecations/14-7-deprecate-static-site-editor.yml
@@ -1,4 +1,4 @@
-- name: "Removal of Static Site Editor" # The name of the feature to be deprecated
+- name: "Static Site Editor" # The name of the feature to be deprecated
announcement_milestone: "14.7" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
diff --git a/data/deprecations/14-8-Elasticsearch-6-8.yml b/data/deprecations/14-8-Elasticsearch-6-8.yml
new file mode 100644
index 00000000000..20f32966f24
--- /dev/null
+++ b/data/deprecations/14-8-Elasticsearch-6-8.yml
@@ -0,0 +1,18 @@
+- name: "Elasticsearch 6.8"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ body: |
+ Elasticsearch 6.8 is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
+ Customers using Elasticsearch 6.8 need to upgrade their Elasticsearch version to 7.x prior to upgrading to GitLab 15.0.
+ We recommend using the latest version of Elasticsearch 7 to benefit from all Elasticsearch improvements.
+
+ Elasticsearch 6.8 is also incompatible with Amazon OpenSearch, which we [plan to support in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/327560).
+
+ stage: Enablement
+ tiers: [Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350275
+ documentation_url: https://docs.gitlab.com/ee/integration/elasticsearch.html#version-requirements
+
diff --git a/data/deprecations/14-8-ci-build-variables.yml b/data/deprecations/14-8-ci-build-variables.yml
new file mode 100644
index 00000000000..52c7ecf6c52
--- /dev/null
+++ b/data/deprecations/14-8-ci-build-variables.yml
@@ -0,0 +1,16 @@
+- name: "`CI_BUILD_*` predefined variables"
+ announcement_milestone: "14.8"
+ announcement_date: "2021-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: dhershkovitch
+ body: |
+ The predefined CI/CD variables that start with `CI_BUILD_*` were deprecated in GitLab 9.0, and will be removed in GitLab 15.0. If you still use these variables, be sure to change to the current [`CI_JOB_*` predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) which are identical (except for the updated name).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Verify
+ tiers: [Free, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352957
+ documentation_url: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-compliance-required-pipeline-configuration-premium.yml b/data/deprecations/14-8-compliance-required-pipeline-configuration-premium.yml
new file mode 100644
index 00000000000..73ba7d8011a
--- /dev/null
+++ b/data/deprecations/14-8-compliance-required-pipeline-configuration-premium.yml
@@ -0,0 +1,16 @@
+- name: "Required pipeline configurations in Premium tier"
+ announcement_milestone: "14.8"
+ announcement_date: "2021-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: sam.white
+ body: | # Do not modify this line, instead modify the lines below.
+ The [required pipeline configuration](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#required-pipeline-configuration) feature is deprecated in GitLab 14.8 for Premium customers and is scheduled for removal in GitLab 15.0. This feature is not deprecated for GitLab Ultimate customers.
+
+ This change to move the feature to GitLab's Ultimate tier is intended to help our features better align with our [pricing philosophy](https://about.gitlab.com/company/pricing/#three-tiers) as we see demand for this feature originating primarily from executives.
+
+ This change will also help GitLab remain consistent in its tiering strategy with the other related Ultimate-tier features of:
+ [Security policies](https://docs.gitlab.com/ee/user/application_security/policies/) and [compliance framework pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: "Manage"
diff --git a/data/deprecations/14-8-compliance-status-check-api-field.yml b/data/deprecations/14-8-compliance-status-check-api-field.yml
new file mode 100644
index 00000000000..f32a8379481
--- /dev/null
+++ b/data/deprecations/14-8-compliance-status-check-api-field.yml
@@ -0,0 +1,25 @@
+- name: "External status check API breaking changes"
+ announcement_milestone: "14.8"
+ announcement_date: "2021-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: sam.white
+ body: | # Do not modify this line, instead modify the lines below.
+ The [external status check API](https://docs.gitlab.com/ee/api/status_checks.html) was originally implemented to
+ support pass-by-default requests to mark a status check as passing. Pass-by-default requests are now deprecated.
+ Specifically, the following are deprecated:
+
+ - Requests that do not contain the `status` field.
+ - Requests that have the `status` field set to `approved`.
+
+ Beginning in GitLab 15.0, status checks will only be updated to a passing state if the `status` field is both present
+ and set to `pass`. Requests that:
+
+ - Do not contain the `status` field will be rejected with a `422` error. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338827).
+ - Contain any value other than `pass` will cause the status check to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/339039).
+
+ To align with this change, API calls to list external status checks will also return the value of `pass` rather than
+ `approved` for status checks that have passed.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: "Manage"
diff --git a/data/deprecations/14-8-deprecate-projectFingerprint-from-PipelineSecurityReportFinding-GraphQL.yml b/data/deprecations/14-8-deprecate-projectFingerprint-from-PipelineSecurityReportFinding-GraphQL.yml
new file mode 100644
index 00000000000..ea75e70afe3
--- /dev/null
+++ b/data/deprecations/14-8-deprecate-projectFingerprint-from-PipelineSecurityReportFinding-GraphQL.yml
@@ -0,0 +1,19 @@
+- name: "`projectFingerprint` in `PipelineSecurityReportFinding` GraphQL" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: matt_wilson # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The `projectFingerprint` field in the [PipelineSecurityReportFinding](https://docs.gitlab.com/ee/api/graphql/reference/index.html#pipelinesecurityreportfinding)
+ GraphQL object is being deprecated. This field contains a "fingerprint" of security findings used to determine uniqueness.
+ The method for calculating fingerprints has changed, resulting in different values. Going forward, the new values will be
+ exposed in the UUID field. Data previously available in the projectFingerprint field will eventually be removed entirely.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-deprecation-secure-dependency-scanning-retire-js.yml b/data/deprecations/14-8-deprecation-secure-dependency-scanning-retire-js.yml
new file mode 100644
index 00000000000..a5e5ce6e9ea
--- /dev/null
+++ b/data/deprecations/14-8-deprecation-secure-dependency-scanning-retire-js.yml
@@ -0,0 +1,17 @@
+- name: "Retire-JS Dependency Scanning tool" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ breaking_change: true
+ body: | # Do not modify this line, instead modify the lines below.
+ As of 14.8 the retire.js job is being deprecated from Dependency Scanning. It will continue to be included in our CI/CD template while deprecated. We are removing retire.js from Dependency Scanning on May 22, 2022 in GitLab 15.0. JavaScript scanning functionality will not be affected as it is still being covered by Gemnasium.
+
+ If you have explicitly excluded retire.js using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration related to the `retire-js-dependency_scanning` job you will want to switch to gemnasium-dependency_scanning before the removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference retire.js, or customized your template specifically for retire.js, you will not need to take action.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350510 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-8-enforce-pat-expiration.yml b/data/deprecations/14-8-enforce-pat-expiration.yml
new file mode 100644
index 00000000000..6c6fdf31fe6
--- /dev/null
+++ b/data/deprecations/14-8-enforce-pat-expiration.yml
@@ -0,0 +1,13 @@
+- name: "Optional enforcement of PAT expiration" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: djensen # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The feature to disable enforcement of PAT expiration is unusual from a security perspective.
+ We have become concerned that this unusual feature could create unexpected behavior for users.
+ Unexpected behavior in a security feature is inherently dangerous, so we have decided to remove this feature.
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/351962" # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: "https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html#allow-expired-personal-access-tokens-to-be-used-deprecated" # (optional) This is a link to the current documentation page
diff --git a/data/deprecations/14-8-enforce-ssh-expiration.yml b/data/deprecations/14-8-enforce-ssh-expiration.yml
new file mode 100644
index 00000000000..815d592a2a9
--- /dev/null
+++ b/data/deprecations/14-8-enforce-ssh-expiration.yml
@@ -0,0 +1,13 @@
+- name: "Optional enforcement of SSH expiration" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: djensen # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The feature to disable enforcement of SSH expiration is unusual from a security perspective.
+ We have become concerned that this unusual feature could create unexpected behavior for users.
+ Unexpected behavior in a security feature is inherently dangerous, so we have decided to remove this feature.
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/351963" # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: "https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html#allow-expired-ssh-keys-to-be-used-deprecated" # (optional) This is a link to the current documentation page
diff --git a/data/deprecations/14-8-geo-deprecate-db-rake-tasks.yml b/data/deprecations/14-8-geo-deprecate-db-rake-tasks.yml
new file mode 100644
index 00000000000..137ae01f63b
--- /dev/null
+++ b/data/deprecations/14-8-geo-deprecate-db-rake-tasks.yml
@@ -0,0 +1,34 @@
+- name: "Deprecate custom Geo:db:* Rake tasks"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: false
+ reporter: nhxnguyen
+ body: |
+ In GitLab 14.8, we are [replacing the `geo:db:*` Rake tasks with built-in tasks](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77269/diffs) that are now possible after [switching the Geo tracking database to use Rails' 6 support of multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6458).
+ The following `geo:db:*` tasks will be replaced with their corresponding `db:*:geo` tasks:
+
+ - `geo:db:drop` -> `db:drop:geo`
+ - `geo:db:create` -> `db:create:geo`
+ - `geo:db:setup` -> `db:setup:geo`
+ - `geo:db:migrate` -> `db:migrate:geo`
+ - `geo:db:rollback` -> `db:rollback:geo`
+ - `geo:db:version` -> `db:version:geo`
+ - `geo:db:reset` -> `db:reset:geo`
+ - `geo:db:seed` -> `db:seed:geo`
+ - `geo:schema:load:geo` -> `db:schema:load:geo`
+ - `geo:db:schema:dump` -> `db:schema:dump:geo`
+ - `geo:db:migrate:up` -> `db:migrate:up:geo`
+ - `geo:db:migrate:down` -> `db:migrate:down:geo`
+ - `geo:db:migrate:redo` -> `db:migrate:redo:geo`
+ - `geo:db:migrate:status` -> `db:migrate:status:geo`
+ - `geo:db:test:prepare` -> `db:test:prepare:geo`
+ - `geo:db:test:load` -> `db:test:load:geo`
+ - `geo:db:test:purge` -> `db:test:purge:geo`
+ stage: "Enablement"
+ tiers: ["Premium", "Ultimate"]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/351945"
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-geo-deprecate-replication-detail-routes.yml b/data/deprecations/14-8-geo-deprecate-replication-detail-routes.yml
new file mode 100644
index 00000000000..94a026edd81
--- /dev/null
+++ b/data/deprecations/14-8-geo-deprecate-replication-detail-routes.yml
@@ -0,0 +1,15 @@
+- name: "Deprecate Geo Admin UI Routes"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: false
+ reporter: nhxnguyen
+ body: |
+ In GitLab 13.0, we introduced new project and design replication details routes in the Geo Admin UI. These routes are `/admin/geo/replication/projects` and `/admin/geo/replication/designs`. We kept the legacy routes and redirected them to the new routes. In GitLab 15.0, we will remove support for the legacy routes `/admin/geo/projects` and `/admin/geo/designs`. Please update any bookmarks or scripts that may use the legacy routes.
+ stage: "Enablement"
+ tiers: ["Premium", "Ultimate"]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/351345"
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-gitaly-deprecate-legacy-config-options.yml b/data/deprecations/14-8-gitaly-deprecate-legacy-config-options.yml
new file mode 100644
index 00000000000..861bed1e976
--- /dev/null
+++ b/data/deprecations/14-8-gitaly-deprecate-legacy-config-options.yml
@@ -0,0 +1,20 @@
+- name: "Deprecate legacy Gitaly configuration methods" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: mjwood # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ Using environment variables `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configure Gitaly is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352609).
+ These variables are being replaced with standard [`config.toml` Gitaly configuration](https://docs.gitlab.com/ee/administration/gitaly/reference.html).
+
+ GitLab instances that use `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configure Gitaly should switch to configuring using
+ `config.toml`.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: "Create" # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/352609" # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: "https://docs.gitlab.com/ee/administration/gitaly/reference.html" # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-gitaly-remove-per-repository-election.yml b/data/deprecations/14-8-gitaly-remove-per-repository-election.yml
new file mode 100644
index 00000000000..334da51c4a0
--- /dev/null
+++ b/data/deprecations/14-8-gitaly-remove-per-repository-election.yml
@@ -0,0 +1,19 @@
+- name: "Configurable Gitaly `per_repository` election strategy" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "14.9" # The milestone when this feature is planned to be removed
+ removal_date: "2022-03-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: false # If this deprecation is a breaking change, set this value to true
+ reporter: mjwood # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ Configuring the `per_repository` Gitaly election strategy is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352612).
+ `per_repository` has been the only option since GitLab 14.0.
+
+ This change is part of regular maintenance to keep our codebase clean.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/352612" # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-graphql-ids.yml b/data/deprecations/14-8-graphql-ids.yml
new file mode 100644
index 00000000000..dd73f310335
--- /dev/null
+++ b/data/deprecations/14-8-graphql-ids.yml
@@ -0,0 +1,66 @@
+- name: "GraphQL ID and GlobalID compatibility"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-04-22"
+ breaking_change: true
+ reporter: alexkalderimis
+ body: | # Do not modify this line, instead modify the lines below.
+ We are removing a non-standard extension to our GraphQL processor, which we added for backwards compatibility. This extension modifies the validation of GraphQL queries, allowing the use of the `ID` type for arguments where it would normally be rejected.
+ Some arguments originally had the type `ID`. These were changed to specific
+ kinds of `ID`. This change may be a breaking change if you:
+
+ - Use GraphQL.
+ - Use the `ID` type for any argument in your query signatures.
+
+ Some field arguments still have the `ID` type. These are typically for
+ IID values, or namespace paths. An example is `Query.project(fullPath: ID!)`.
+
+ For a list of affected and unaffected field arguments,
+ see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352832).
+
+ You can test if this change affects you by validating
+ your queries locally, using schema data fetched from a GitLab server.
+ You can do this by using the GraphQL explorer tool for the relevant GitLab
+ instance. For example: `https://gitlab.com/-/graphql-explorer`.
+
+ For example, the following query illustrates the breaking change:
+
+ ```graphql
+ # a query using the deprecated type of Query.issue(id:)
+ # WARNING: This will not work after GitLab 15.0
+ query($id: ID!) {
+ deprecated: issue(id: $id) {
+ title, description
+ }
+ }
+ ```
+
+ The query above will not work after GitLab 15.0 is released, because the type
+ of `Query.issue(id:)` is actually `IssueID!`.
+
+ Instead, you should use one of the following two forms:
+
+ ```graphql
+ # This will continue to work
+ query($id: IssueID!) {
+ a: issue(id: $id) {
+ title, description
+ }
+ b: issue(id: "gid://gitlab/Issue/12345") {
+ title, description
+ }
+ }
+ ```
+
+ This query works now, and will continue to work after GitLab 15.0.
+ You should convert any queries in the first form (using `ID` as a named type in the signature)
+ to one of the other two forms (using the correct appropriate type in the signature, or using
+ an inline argument expression).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257883'
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-grpc-proxy.yml b/data/deprecations/14-8-grpc-proxy.yml
new file mode 100644
index 00000000000..353c0abc901
--- /dev/null
+++ b/data/deprecations/14-8-grpc-proxy.yml
@@ -0,0 +1,26 @@
+- name: "Support for gRPC-aware proxy deployed between Gitaly and rest of GitLab"
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: 2022-05-22 # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: jacobvosmaer-gitlab # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ Although not recommended or documented, it was possible to deploy a gRPC-aware proxy between Gitaly and
+ the rest of GitLab. For example, NGINX and Envoy. The ability to deploy a gRPC-aware proxy is
+ [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352517). If you currently use a gRPC-aware proxy for
+ Gitaly connections, you should change your proxy configuration to use TCP or TLS proxying (OSI layer 4) instead.
+
+ Gitaly Cluster became incompatible with gRPC-aware proxies in GitLab 13.12. Now all GitLab installations will be incompatible with
+ gRPC-aware proxies, even without Gitaly Cluster.
+
+ By sending some of our internal RPC traffic through a custom protocol (instead of gRPC) we
+ increase throughput and reduce Go garbage collection latency. For more information, see
+ the [relevant epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/463).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-iteration-started-field.yml b/data/deprecations/14-8-iteration-started-field.yml
new file mode 100644
index 00000000000..590c9800db6
--- /dev/null
+++ b/data/deprecations/14-8-iteration-started-field.yml
@@ -0,0 +1,15 @@
+- name: "`started` iterations API field" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ body: | # Do not modify this line, instead modify the lines below.
+ The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: plan
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334018
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-nfs_support.yml b/data/deprecations/14-8-nfs_support.yml
new file mode 100644
index 00000000000..832b309e979
--- /dev/null
+++ b/data/deprecations/14-8-nfs_support.yml
@@ -0,0 +1,28 @@
+- name: "Reminder: support for NFS repository storage" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: mjwood # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ As [announced](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#nfs-for-git-repository-storage-deprecated) at the
+ release of GitLab 14.0, technical support for NFS storage for Git repositories is being removed. Please see our official
+ [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for additional information.
+
+ We encourage customers currently using NFS for Git repositories to plan their migration by reviewing our documentation on
+ [migrating to Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/#migrating-to-gitaly-cluster).
+
+ Gitaly Cluster offers tremendous benefits for our customers such as:
+
+ - [Variable replication factors](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#configure-replication-factor)
+ - [Strong consistency](https://docs.gitlab.com/ee/administration/gitaly/#strong-consistency)
+ - [Distributed read capabilities](https://docs.gitlab.com/ee/administration/gitaly/#distributed-reads)
+
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Gitaly # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-protect-cns-chs.yml b/data/deprecations/14-8-protect-cns-chs.yml
new file mode 100644
index 00000000000..b3a4cc8c1e8
--- /dev/null
+++ b/data/deprecations/14-8-protect-cns-chs.yml
@@ -0,0 +1,20 @@
+- name: "Container Network and Host Security"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: sam.white
+ body: | # Do not modify this line, instead modify the lines below.
+ All functionality related to GitLab's Container Network Security and Container Host Security categories is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to evaluate the following open source projects as potential solutions that can be installed and managed outside of GitLab: [AppArmor](https://gitlab.com/apparmor/apparmor), [Cilium](https://github.com/cilium/cilium), [Falco](https://github.com/falcosecurity/falco), [FluentD](https://github.com/fluent/fluentd), [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/). To integrate these technologies into GitLab, add the desired Helm charts into your copy of the [Cluster Management Project Template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Deploy these Helm charts in production by calling commands through the GitLab [Secure CI/CD Tunnel](https://docs.gitlab.com/ee/user/clusters/agent/repository.html#run-kubectl-commands-using-the-cicd-tunnel).
+
+ As part of this change, the following specific capabilities within GitLab are now deprecated, and are scheduled for removal in GitLab 15.0:
+
+ - The **Security & Compliance > Threat Monitoring** page.
+ - The `Network Policy` security policy type, as found on the **Security & Compliance > Policies** page.
+ - The ability to manage integrations with the following technologies through GitLab: AppArmor, Cilium, Falco, FluentD, and Pod Security Policies.
+ - All APIs related to the above functionality.
+
+ For additional context, or to provide feedback regarding this change, please reference our open [deprecation issue](https://gitlab.com/groups/gitlab-org/-/epics/7476).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: "Protect"
diff --git a/data/deprecations/14-8-protect-vulnerability-check.yml b/data/deprecations/14-8-protect-vulnerability-check.yml
new file mode 100644
index 00000000000..0f8fb44081a
--- /dev/null
+++ b/data/deprecations/14-8-protect-vulnerability-check.yml
@@ -0,0 +1,18 @@
+- name: "Vulnerability Check"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: sam.white
+ body: | # Do not modify this line, instead modify the lines below.
+ The vulnerability check feature is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. We encourage you to migrate to the new security approvals feature instead. You can do so by navigating to **Security & Compliance > Policies** and creating a new Scan Result Policy.
+
+ The new security approvals feature is similar to vulnerability check. For example, both can require approvals for MRs that contain security vulnerabilities. However, security approvals improve the previous experience in several ways:
+
+ - Users can choose who is allowed to edit security approval rules. An independent security or compliance team can therefore manage rules in a way that prevents development project maintainers from modifying the rules.
+ - Multiple rules can be created and chained together to allow for filtering on different severity thresholds for each scanner type.
+ - A two-step approval process can be enforced for any desired changes to security approval rules.
+ - A single set of security policies can be applied to multiple development projects to allow for ease in maintaining a single, centralized ruleset.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: "Protect"
diff --git a/data/deprecations/14-8-remove_ff_push_rules_supersede_code_owners.yml b/data/deprecations/14-8-remove_ff_push_rules_supersede_code_owners.yml
new file mode 100644
index 00000000000..b93b25c00d0
--- /dev/null
+++ b/data/deprecations/14-8-remove_ff_push_rules_supersede_code_owners.yml
@@ -0,0 +1,16 @@
+- name: "Deprecate feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: sarahwaldner # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-request-profiling.yml b/data/deprecations/14-8-request-profiling.yml
new file mode 100644
index 00000000000..8b549a6002f
--- /dev/null
+++ b/data/deprecations/14-8-request-profiling.yml
@@ -0,0 +1,19 @@
+- name: "Request profiling"
+ announcement_milestone: "14.8"
+ announcement_date: "2021-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: iroussos
+ body: | # Do not modify this line, instead modify the lines below.
+ [Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
+
+ We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
+ We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.
+ It also depends on a few third-party gems that are not actively maintained anymore, have not been updated for the latest version of Ruby, or crash frequently when profiling heavy page loads.
+
+ For more information, check the [summary section of the deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352488#deprecation-summary).
+ stage: Monitor
+ tiers: [Free, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352488
+ documentation_url: https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html
diff --git a/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml b/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml
new file mode 100644
index 00000000000..63178061aae
--- /dev/null
+++ b/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml
@@ -0,0 +1,33 @@
+- name: "REST and GraphQL API Runner usage of `active` replaced by `paused`"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "16.0"
+ removal_date: "2023-04-22"
+ breaking_change: true
+ reporter: pedropombeiro
+ body: |
+ Occurrences of the `active` identifier in the GitLab Runner REST and GraphQL API endpoints will be
+ renamed to `paused` in GitLab 16.0, namely:
+
+ - GraphQL API:
+ - the `CiRunner` property;
+ - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation;
+ - the `runners` and `Group.runners` queries.
+ - REST API:
+ - endpoints taking or returning `active` properties, such as:
+ - `GET /runners`
+ - `GET /runners/all`
+ - `GET /runners/:id` / `PUT /runners/:id`
+ - `PUT --form "active=false" /runners/:runner_id`
+ - `GET /projects/:id/runners` / `POST /projects/:id/runners`
+ - `GET /groups/:id/runners`
+
+ The 16.0 release of the GitLab Runner will start using the `paused` property when registering runners, and therefore
+ will only be compatible with GitLab 16.0 and later. Until 16.0, GitLab will accept the deprecated `active` flag from
+ existing runners.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347211
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-runner-api-project_type-breaking-change.yml b/data/deprecations/14-8-runner-api-project_type-breaking-change.yml
new file mode 100644
index 00000000000..67cd854aa89
--- /dev/null
+++ b/data/deprecations/14-8-runner-api-project_type-breaking-change.yml
@@ -0,0 +1,15 @@
+- name: "REST API endpoint to list group runners no longer accepts `project_type` value for `type` argument"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "16.0"
+ removal_date: "2023-04-22"
+ breaking_change: true
+ reporter: pedropombeiro
+ body: |
+ The `GET /groups/:id/runners?type=project_type` endpoint will be removed in GitLab 16.0. The endpoint always returned an empty collection.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351466
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml b/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml
new file mode 100644
index 00000000000..51472b3cd28
--- /dev/null
+++ b/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml
@@ -0,0 +1,18 @@
+- name: "REST API Runner will not accept `status` filter values of `active` or `paused`"
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22"
+ removal_milestone: "16.0"
+ removal_date: "2023-04-22"
+ breaking_change: true
+ body: | # Do not modify this line, instead modify the lines below.
+ The GitLab Runner REST endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
+
+ A runner's status will only relate to runner contact status, such as: `online`, `offline`.
+ Status values `paused` or `active` will no longer be accepted and will be replaced by the `paused` query parameter.
+
+ When checking for paused runners, API users are advised to specify `paused=true` as the query parameter.
+ When checking for active runners, specify `paused=false`.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351109
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
diff --git a/data/deprecations/14-8-sast-analyzer-removals.yml b/data/deprecations/14-8-sast-analyzer-removals.yml
new file mode 100644
index 00000000000..6bbeee0cd6b
--- /dev/null
+++ b/data/deprecations/14-8-sast-analyzer-removals.yml
@@ -0,0 +1,32 @@
+- name: "SAST analyzer consolidation and CI/CD template changes"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: connorgilbert
+ body: | # Do not modify this line, instead modify the lines below.
+ GitLab SAST uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/sast/analyzers/) to scan code for vulnerabilities.
+
+ We are reducing the number of analyzers used in GitLab SAST as part of our long-term strategy to deliver a better and more consistent user experience.
+ Streamlining the set of analyzers will also enable faster [iteration](https://about.gitlab.com/handbook/values/#iteration), better [results](https://about.gitlab.com/handbook/values/#results), and greater [efficiency](https://about.gitlab.com/handbook/values/#results) (including a reduction in CI runner usage in most cases).
+
+ In GitLab 15.0, GitLab SAST will no longer use the following analyzers:
+
+ - [ESLint](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) (JavaScript, TypeScript, React)
+ - [Gosec](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) (Go)
+ - [Bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Python)
+
+ These analyzers will be removed from the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) and replaced with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
+ They will no longer receive routine updates, except for security issues.
+ We will not delete container images previously published for these analyzers; any such change would be announced as a [deprecation, removal, or breaking change announcement](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes).
+
+ We will also remove Java from the scope of the [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) analyzer and replace it with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
+ This change will make it simpler to scan Java code; compilation will no longer be required.
+ This change will be reflected in the automatic language detection portion of the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml).
+
+ If you applied customizations to any of the affected analyzers, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352554#breaking-change).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Secure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352554
diff --git a/data/deprecations/14-8-sast-dotnet-21.yml b/data/deprecations/14-8-sast-dotnet-21.yml
new file mode 100644
index 00000000000..ab1b3c16b23
--- /dev/null
+++ b/data/deprecations/14-8-sast-dotnet-21.yml
@@ -0,0 +1,31 @@
+- name: "SAST support for .NET 2.1"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: connorgilbert
+ body: | # Do not modify this line, instead modify the lines below.
+ The GitLab SAST Security Code Scan analyzer scans .NET code for security vulnerabilities.
+ For technical reasons, the analyzer must first build the code to scan it.
+
+ In GitLab versions prior to 15.0, the default analyzer image (version 2) includes support for:
+
+ - .NET 2.1
+ - .NET 3.0 and .NET Core 3.0
+ - .NET Core 3.1
+ - .NET 5.0
+
+ In GitLab 15.0, we will change the default major version for this analyzer from version 2 to version 3. This change:
+
+ - Adds [severity values for vulnerabilities](https://gitlab.com/gitlab-org/gitlab/-/issues/350408) along with [other new features and improvements](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/blob/master/CHANGELOG.md).
+ - Removes .NET 2.1 support.
+ - Adds support for .NET 6.0, Visual Studio 2019, and Visual Studio 2022.
+
+ Version 3 was [announced in GitLab 14.6](https://about.gitlab.com/releases/2021/12/22/gitlab-14-6-released/#sast-support-for-net-6) and made available as an optional upgrade.
+
+ If you rely on .NET 2.1 support being present in the analyzer image by default, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352553#breaking-change).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Secure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352553
diff --git a/data/deprecations/14-8-sast-secret-analyzer-image.yml b/data/deprecations/14-8-sast-secret-analyzer-image.yml
new file mode 100644
index 00000000000..b1cb5c82764
--- /dev/null
+++ b/data/deprecations/14-8-sast-secret-analyzer-image.yml
@@ -0,0 +1,27 @@
+- name: "Secure and Protect analyzer images published in new location"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: connorgilbert
+ body: | # Do not modify this line, instead modify the lines below.
+ GitLab uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/terminology/#analyzer) to [scan for security vulnerabilities](https://docs.gitlab.com/ee/user/application_security/).
+ Each analyzer is distributed as a container image.
+
+ Starting in GitLab 14.8, new versions of GitLab Secure and Protect analyzers are published to a new registry location under `registry.gitlab.com/security-products`.
+
+ We will update the default value of [GitLab-managed CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security) to reflect this change:
+
+ - For all analyzers except Container Scanning, we will update the variable `SECURE_ANALYZERS_PREFIX` to the new image registry location.
+ - For Container Scanning, the default image address is already updated. There is no `SECURE_ANALYZERS_PREFIX` variable for Container Scanning.
+
+ In a future release, we will stop publishing images to `registry.gitlab.com/gitlab-org/security-products/analyzers`.
+ Once this happens, you must take action if you manually pull images and push them into a separate registry. This is commonly the case for [offline deployments](https://docs.gitlab.com/ee/user/application_security/offline_deployments/index.html).
+ Otherwise, you won't receive further updates.
+
+ See the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352564) for more details.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Secure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352564
diff --git a/data/deprecations/14-8-sast-spotbugs-java-8.yml b/data/deprecations/14-8-sast-spotbugs-java-8.yml
new file mode 100644
index 00000000000..3e3672eeb63
--- /dev/null
+++ b/data/deprecations/14-8-sast-spotbugs-java-8.yml
@@ -0,0 +1,24 @@
+- name: "Out-of-the-box SAST support for Java 8"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ reporter: connorgilbert
+ body: | # Do not modify this line, instead modify the lines below.
+ The [GitLab SAST SpotBugs analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) scans [Java, Scala, Groovy, and Kotlin code](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) for security vulnerabilities.
+ For technical reasons, the analyzer must first compile the code before scanning.
+ Unless you use the [pre-compilation strategy](https://docs.gitlab.com/ee/user/application_security/sast/#pre-compilation), the analyzer attempts to automatically compile your project's code.
+
+ In GitLab versions prior to 15.0, the analyzer image includes Java 8 and Java 11 runtimes to facilitate compilation.
+
+ In GitLab 15.0, we will:
+
+ - Remove Java 8 from the analyzer image to reduce the size of the image.
+ - Add Java 17 to the analyzer image to make it easier to compile with Java 17.
+
+ If you rely on Java 8 being present in the analyzer environment, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352549#breaking-change).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Secure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352549
diff --git a/data/deprecations/14-8-secret-detection-configurations.yml b/data/deprecations/14-8-secret-detection-configurations.yml
new file mode 100644
index 00000000000..f9103c1cea3
--- /dev/null
+++ b/data/deprecations/14-8-secret-detection-configurations.yml
@@ -0,0 +1,28 @@
+- name: "Secret Detection configuration variables deprecated"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: false
+ reporter: connorgilbert
+ body: | # Do not modify this line, instead modify the lines below.
+ To make it simpler and more reliable to [customize GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings), we're deprecating some of the variables that you could previously set in your CI/CD configuration.
+
+ The following variables currently allow you to customize the options for historical scanning, but interact poorly with the [GitLab-managed CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) and are now deprecated:
+
+ - `SECRET_DETECTION_COMMIT_FROM`
+ - `SECRET_DETECTION_COMMIT_TO`
+ - `SECRET_DETECTION_COMMITS`
+ - `SECRET_DETECTION_COMMITS_FILE`
+
+ The `SECRET_DETECTION_ENTROPY_LEVEL` previously allowed you to configure rules that only considered the entropy level of strings in your codebase, and is now deprecated.
+ This type of entropy-only rule created an unacceptable number of incorrect results (false positives) and is no longer supported.
+
+ In GitLab 15.0, we'll update the Secret Detection [analyzer](https://docs.gitlab.com/ee/user/application_security/terminology/#analyzer) to ignore these deprecated options.
+ You'll still be able to configure historical scanning of your commit history by setting the [`SECRET_DETECTION_HISTORIC_SCAN` CI/CD variable](https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-cicd-variables).
+
+ For further details, see [the deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352565).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Secure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352565
diff --git a/data/deprecations/14-8-secure-ca-python-deprecation.yml b/data/deprecations/14-8-secure-ca-python-deprecation.yml
new file mode 100644
index 00000000000..c4b5c2e36b7
--- /dev/null
+++ b/data/deprecations/14-8-secure-ca-python-deprecation.yml
@@ -0,0 +1,33 @@
+- name: "Dependency Scanning Python 3.9 and 3.6 image deprecation" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: 2021-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ body: | # Do not modify this line, instead modify the lines below.
+ For those using Dependency Scanning for Python projects, we are deprecating the default `gemnasium-python:2` image which uses Python 3.6 as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).
+
+ For users using Python 3.9 or 3.9-compatible projects, you should not need to take action and dependency scanning should begin to work in GitLab 15.0. If you wish to test the new container now please run a test pipeline in your project with this container (which will be removed in 15.0). Use the Python 3.9 image:
+
+ ```yaml
+ gemnasium-python-dependency_scanning:
+ image:
+ name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
+ ```
+
+ For users using Python 3.6, as of GitLab 15.0 you will no longer be able to use the default template for dependency scanning. You will need to switch to use the deprecated `gemnasium-python:2` analyzer image. If you are impacted by this please comment in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351503) so we can extend the removal if needed.
+
+ For users using the 3.9 special exception image, you must instead use the default value and no longer override your container. To verify if you are using the 3.9 special exception image, check your `.gitlab-ci.yml` file for the following reference:
+
+ ```yaml
+ gemnasium-python-dependency_scanning:
+ image:
+ name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
+ ```
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334060 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-9-deprecate-testcoveragesetting.yml b/data/deprecations/14-9-deprecate-testcoveragesetting.yml
new file mode 100644
index 00000000000..19bc6004b02
--- /dev/null
+++ b/data/deprecations/14-9-deprecate-testcoveragesetting.yml
@@ -0,0 +1,14 @@
+- name: "Test coverage project CI/CD setting" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: jreporter # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ To simplify setting a test coverage pattern, in GitLab 15.0 the
+ [project setting for test coverage parsing](https://docs.gitlab.com/ee/ci/pipelines/settings.html#add-test-coverage-results-to-a-merge-request-deprecated)
+ is being removed.
+
+ Instead, using the project’s `.gitlab-ci.yml`, provide a regular expression with the `coverage` keyword to set
+ testing coverage results in merge requests.
diff --git a/data/deprecations/15-0-deprecate-monitor-tracing.yml b/data/deprecations/15-0-deprecate-monitor-tracing.yml
index 126ada081f4..448404a5c70 100644
--- a/data/deprecations/15-0-deprecate-monitor-tracing.yml
+++ b/data/deprecations/15-0-deprecate-monitor-tracing.yml
@@ -13,4 +13,3 @@
documentation_url: https://docs.gitlab.com/ee/operations/tracing.html#tracing # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
-
diff --git a/data/deprecations/15-0-instance-statistics-graphql-node-removal.yml b/data/deprecations/15-0-instance-statistics-graphql-node-removal.yml
new file mode 100644
index 00000000000..c617a6cc478
--- /dev/null
+++ b/data/deprecations/15-0-instance-statistics-graphql-node-removal.yml
@@ -0,0 +1,13 @@
+- name: "Querying Usage Trends via the `instanceStatisticsMeasurements` GraphQL node"
+ announcement_milestone: "14.8"
+ announcement_date: "2022-02-22"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22"
+ breaking_change: true
+ body: | # Do not modify this line, instead modify the lines below.
+ The `instanceStatisticsMeasurements` GraphQL node has been renamed to `usageTrendsMeasurements` in 13.10 and the old field name has been marked as deprecated. To fix the existing GraphQL queries, replace `instanceStatisticsMeasurements` with `usageTrendsMeasurements`.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: Manage
+ tiers: [FREE]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332323
+ documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/index.html#queryusagetrendsmeasurements
diff --git a/data/deprecations/15-0-oauth-noexpiry.yml b/data/deprecations/15-0-oauth-noexpiry.yml
new file mode 100644
index 00000000000..2e1e4a35f7b
--- /dev/null
+++ b/data/deprecations/15-0-oauth-noexpiry.yml
@@ -0,0 +1,24 @@
+- name: "OAuth tokens without expiration" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: 2022-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ body: | # Do not modify this line, instead modify the lines below.
+ By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and earlier, OAuth access tokens
+ had no expiration. In GitLab 15.0, an expiry will be automatically generated for any existing token that does not
+ already have one.
+
+ You should [opt in](https://docs.gitlab.com/ee/integration/oauth_provider.html#expiring-access-tokens) to expiring
+ tokens before GitLab 15.0 is released:
+
+ 1. Edit the application.
+ 1. Select **Expire access tokens** to enable them. Tokens must be revoked or they don’t expire.
+
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # Manage
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # https://gitlab.com/gitlab-org/gitlab/-/issues/21745
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/15-0-oauth.yml b/data/deprecations/15-0-oauth.yml
new file mode 100644
index 00000000000..5ca30d9f330
--- /dev/null
+++ b/data/deprecations/15-0-oauth.yml
@@ -0,0 +1,15 @@
+- name: "OAuth implicit grant" # The name of the feature to be deprecated
+ announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: 2022-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: yes # If this deprecation is a breaking change, set this value to true
+ body: | # Do not modify this line, instead modify the lines below.
+ The OAuth implicit grant authorization flow will be removed in our next major release, GitLab 15.0. Any applications that use OAuth implicit grant should switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # Manage
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # https://gitlab.com/gitlab-org/gitlab/-/issues/344609
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/JTW_v2_update.yml b/data/deprecations/JTW_v2_update.yml
new file mode 100644
index 00000000000..53aa9ca2c19
--- /dev/null
+++ b/data/deprecations/JTW_v2_update.yml
@@ -0,0 +1,28 @@
+# This is a template for a feature deprecation
+# A deprecation typically occurs when a feature or capability is planned to be removed in a future release.
+# Deprecations should be announced at least two releases prior to removal. Any breaking changes should only be done in major releases.
+#
+# Below is an example of what a single entry should look like, it's required attributes,
+# and what types we expect those attribute values to be.
+#
+# For more information please refer to the handbook documentation here:
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations
+#
+# Please delete this line and above before submitting your merge request.
+
+- name: "Changes to the `CI_JOB_JWT`" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: dhershkovitch # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The `CI_JOB_JWT` will be updated to support a wider variety of cloud providers. It will be changed to match [`CI_JOB_JWT_V2`](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html), but this change may not be backwards compatible for all users, including Hashicorp Vault users. To maintain the current behavior, users can switch to using `CI_JOB_JWT_V1`, or update their configuration in GitLab 15.0 to use the improved `CI_JOB_JWT`.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/data/deprecations/14-9-secure-and-protect-analyzer-bump.yml.yml b/data/deprecations/data/deprecations/14-9-secure-and-protect-analyzer-bump.yml.yml
new file mode 100644
index 00000000000..8f1d030f47c
--- /dev/null
+++ b/data/deprecations/data/deprecations/14-9-secure-and-protect-analyzer-bump.yml.yml
@@ -0,0 +1,44 @@
+- name: "Secure and Protect analyzer major version update" # The name of the feature to be deprecated
+ announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.00" # The milestone when this feature is planned to be removed
+ removal_date: # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # If this deprecation is a breaking change, set this value to true
+ reporter: NicoleSchwartz # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
+ The Secure and Protect stages will be bumping the major versions of their analyzers in tandem with the GitLab 15.0 release. This major bump will enable a clear delineation for analyzers, between:
+
+ - Those released prior to May 22, 2022, which generate reports that _are not_ subject to stringent schema validation.
+ - Those released after May 22, 2022, which generate reports that _are_ subject to stringent schema validation.
+
+ If you are not using the default inclusion templates, or have pinned your analyzer version(s) you will need to update your CI/CD job definition to either remove the pinned version or to update the latest major version.
+ Users of GitLab 12.0-14.10 will continue to experience analyzer updates as normal until the release of GitLab 15.0, following which all newly fixed bugs and newly released features in the new major versions of the analyzers will not be available in the deprecated versions because we do not backport bugs and new features as per our [maintenance policy](https://docs.gitlab.com/ee/policy/maintenance.html). As required security patches will be backported within the latest 3 minor releases.
+ Specifically, the following are being deprecated and will no longer be updated after 15.0 GitLab release:
+
+ - API Security: version 1
+ - Container Scanning: version 4
+ - Coverage-guided fuzz testing: version 2
+ - Dependency Scanning: version 2
+ - Dynamic Application Security Testing (DAST): version 2
+ - License Scanning: version 3
+ - Secret Detection: version 3
+ - Static Application Security Testing (SAST): version 2, except security-code-scan which is version 3
+ - `bandit`: version 2
+ - `brakeman`: version 2
+ - `eslint`: version 2
+ - `flawfinder`: version 2
+ - `gosec`: version 3
+ - `kubesec`: version 2
+ - `mobsf`: version 2
+ - `nodejs-scan`: version 2
+ - `phpcs-security-audit`: version 2
+ - `pmd-apex`: version 2
+ - `security-code-scan`: version 3
+ - `semgrep`: version 2
+ - `sobelow`: version 2
+ - `spotbugs`: version 2
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure, protect # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: Free, Silver, Gold, Core, Premium, Ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350936 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
diff --git a/data/deprecations/templates/_deprecation_template.md.erb b/data/deprecations/templates/_deprecation_template.md.erb
index 70169ef5c5c..1ef2af67a98 100644
--- a/data/deprecations/templates/_deprecation_template.md.erb
+++ b/data/deprecations/templates/_deprecation_template.md.erb
@@ -49,8 +49,10 @@ Before updating GitLab, review the details carefully to determine if you need to
changes to your code, settings, or workflow.
<%= deprecation["body"] -%><% else %>
-<%= deprecation["body"] -%><% end %>
+<%= deprecation["body"] -%><% end %><%- if deprecation["removal_milestone"] -%>
+
**Planned removal milestone: <%= deprecation["removal_milestone"]%> (<%= deprecation["removal_date"]%>)**
+ <%- end -%>
<%- end -%>
<%- end -%>
<%- else -%>
diff --git a/data/deprecations/templates/example.yml b/data/deprecations/templates/example.yml
index 3097db557b8..06e53084ed2 100644
--- a/data/deprecations/templates/example.yml
+++ b/data/deprecations/templates/example.yml
@@ -10,13 +10,14 @@
#
# Please delete this line and above before submitting your merge request.
-- name: "Feature name" # The name of the feature to be deprecated
- announcement_milestone: "XX.YY" # The milestone when this feature was first announced as deprecated.
- announcement_date: "YYYY-MM-DD" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
- removal_milestone: "XX.YY" # The milestone when this feature is planned to be removed
- removal_date: # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
- breaking_change: false # If this deprecation is a breaking change, set this value to true
- body: | # Do not modify this line, instead modify the lines below.
+- name: "Feature name" # The name of the feature to be deprecated
+ announcement_milestone: "XX.YY" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "YYYY-MM-DD" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "XX.YY" # The milestone when this feature is planned to be removed
+ removal_date: # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: false # If this deprecation is a breaking change, set this value to true
+ reporter: exampleuser # GitLab username of the person reporting the deprecation
+ body: | # Do not modify this line, instead modify the lines below.
<!-- START OF BODY COMMENT
This area supports markdown. Delete this entire comment and replace it with your markdown content.
@@ -25,9 +26,9 @@
END OF BODY COMMENT -->
# The following items are not published on the docs page, but may be used in the future.
- stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
- tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
- issue_url: # (optional) This is a link to the deprecation issue in GitLab
- documentation_url: # (optional) This is a link to the current documentation page
- image_url: # (optional) This is a link to a thumbnail image depicting the feature
- video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/removals/14_0/14_0-ds-deprecations.yml b/data/removals/14_0/14_0-ds-deprecations.yml
index c9eefe65c91..91da10097ed 100644
--- a/data/removals/14_0/14_0-ds-deprecations.yml
+++ b/data/removals/14_0/14_0-ds-deprecations.yml
@@ -1,7 +1,8 @@
-- name: "Deprecations for Dependency Scanning"
+- name: "Dependency Scanning"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: nicoleschwartz
+ breaking_change: true
body: |
As mentioned in [13.9](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#deprecations-for-dependency-scanning) and [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/) several removals for Dependency Scanning take effect.
diff --git a/data/removals/14_0/14_0-lc-deprecations.yml b/data/removals/14_0/14_0-lc-deprecations.yml
index 8f59fdbb557..6322b102ec5 100644
--- a/data/removals/14_0/14_0-lc-deprecations.yml
+++ b/data/removals/14_0/14_0-lc-deprecations.yml
@@ -1,6 +1,7 @@
-- name: "Removals for License Compliance"
+- name: "License Compliance"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: nicoleschwartz
+ breaking_change: true
body: |
In 13.0, we deprecated the License-Management CI template and renamed it License-Scanning. We have been providing backward compatibility by warning users of the old template to switch. Now in 14.0, we are completely removing the License-Management CI template. Read about it in [issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261) or [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/).
diff --git a/data/removals/14_0/change_default_branch_name_to_main.yml b/data/removals/14_0/change_default_branch_name_to_main.yml
index d2c0128daa5..1c47f99870b 100644
--- a/data/removals/14_0/change_default_branch_name_to_main.yml
+++ b/data/removals/14_0/change_default_branch_name_to_main.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: sarahwaldner
+ breaking_change: true
body: |
Every Git repository has an initial branch, which is named `master` by default. It's the first branch to be created automatically when you create a new repository. Future [Git versions](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/) will change the default branch name in Git from `master` to `main`. In coordination with the Git project and the broader community, [GitLab has changed the default branch name](https://gitlab.com/gitlab-org/gitlab/-/issues/223789) for new projects on both our SaaS (GitLab.com) and self-managed offerings starting with GitLab 14.0. This will not affect existing projects.
diff --git a/data/removals/14_0/create-code-review-draft-wip.yml b/data/removals/14_0/create-code-review-draft-wip.yml
index addd6c400a6..20eaaf3cd02 100644
--- a/data/removals/14_0/create-code-review-draft-wip.yml
+++ b/data/removals/14_0/create-code-review-draft-wip.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: phikai
+ breaking_change: true
body: |
The WIP (work in progress) status for merge requests signaled to reviewers that the merge request in question wasn't ready to merge. We've renamed the WIP feature to **Draft**, a more inclusive and self-explanatory term. **Draft** clearly communicates the merge request in question isn't ready for review, and makes no assumptions about the progress being made toward it. **Draft** also reduces the cognitive load for new users, non-English speakers, and anyone unfamiliar with the WIP acronym.
diff --git a/data/removals/14_0/create-code-review-w-parameter-removal.yml b/data/removals/14_0/create-code-review-w-parameter-removal.yml
index 471df85b540..3adec30a1e7 100644
--- a/data/removals/14_0/create-code-review-w-parameter-removal.yml
+++ b/data/removals/14_0/create-code-review-w-parameter-removal.yml
@@ -1,6 +1,7 @@
-- name: "Remove `?w=1` URL parameter to ignore whitespace changes"
+- name: "`?w=1` URL parameter to ignore whitespace changes"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: phikai
+ breaking_change: true
body: |
To create a consistent experience for users based on their preferences, support for toggling whitespace changes via URL parameter has been removed in GitLab 14.0.
diff --git a/data/removals/14_0/deprecate_ci_project_config_path_variable.yml b/data/removals/14_0/deprecate_ci_project_config_path_variable.yml
deleted file mode 100644
index c262a641bd1..00000000000
--- a/data/removals/14_0/deprecate_ci_project_config_path_variable.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-- name: "`CI_PROJECT_CONFIG_PATH` removed in GitLab 14.0"
- removal_date: "2021-06-22"
- removal_milestone: "14.0"
- reporter: stkerr
- body: |
- GitLab 14.0 removes the `CI_PROJECT_CONFIG_PATH` pre-defined project variable in favor of `CI_CONFIG_PATH`, which is functionally the same. If you are using `CI_PROJECT_CONFIG_PATH` in your pipeline configurations, update them to use `CI_CONFIG_PATH` instead.
diff --git a/data/removals/14_0/deprecation_bump_terraform_template_version.yml b/data/removals/14_0/deprecation_bump_terraform_template_version.yml
index a2e4bad9913..253dd81e9ea 100644
--- a/data/removals/14_0/deprecation_bump_terraform_template_version.yml
+++ b/data/removals/14_0/deprecation_bump_terraform_template_version.yml
@@ -1,8 +1,9 @@
-- name: "New Terraform template version"
+- name: "Terraform template version"
removal_date: "2021-06-22"
removal_milestone: "14.0" # example
issue_url: ""
reporter: nagyv-gitlab
+ breaking_change: true
body: |
As we continuously [develop GitLab's Terraform integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/325312), to minimize customer disruption, we maintain two GitLab CI/CD templates for Terraform:
diff --git a/data/removals/14_0/deprecation_manage_access_14_0.yml b/data/removals/14_0/deprecation_manage_access_14_0.yml
index bc82067821f..30167d23d60 100644
--- a/data/removals/14_0/deprecation_manage_access_14_0.yml
+++ b/data/removals/14_0/deprecation_manage_access_14_0.yml
@@ -3,15 +3,17 @@
removal_milestone: "14.0"
reporter: ogolowisnki
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257829
+ breaking_change: true
body: |
To improve performance, we are limiting the number of projects returned from the `GET /groups/:id/` API call to 100. A complete list of projects can still be retrieved with the `GET /groups/:id/projects` API call.
-- name: "GitLab OAuth implicit grant deprecation"
+- name: "GitLab OAuth implicit grant"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: ogolowinski
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/288516'
+ breaking_change: true
body: |
GitLab is deprecating the [OAuth 2 implicit grant flow](https://docs.gitlab.com/ee/api/oauth2.html#implicit-grant-flow) as it has been removed for [OAuth 2.1](https://oauth.net/2.1/).
- Beginning in 14.0, new applications can't be created with the OAuth 2 implicit grant flow. Existing OAuth implicit grant flows are no longer supported in 14.4. Migrate your existing applications to other supported [OAuth2 flows](https://docs.gitlab.com/ee/api/oauth2.html#supported-oauth2-flows) before release 14.4.
+ Migrate your existing applications to other supported [OAuth2 flows](https://docs.gitlab.com/ee/api/oauth2.html#supported-oauth2-flows).
diff --git a/data/removals/14_0/deprecation_update_cicd_templates_to_stop_using_hardcode_master.yml b/data/removals/14_0/deprecation_update_cicd_templates_to_stop_using_hardcode_master.yml
index 97adc4bb050..4df59321bc5 100644
--- a/data/removals/14_0/deprecation_update_cicd_templates_to_stop_using_hardcode_master.yml
+++ b/data/removals/14_0/deprecation_update_cicd_templates_to_stop_using_hardcode_master.yml
@@ -1,6 +1,7 @@
-- name: "Update CI/CD templates to stop using hardcoded `master`"
+- name: "Hardcoded `master` in CI/CD templates"
reporter: dhershkovitch
removal_date: "2021-06-22"
removal_milestone: "14.0"
+ breaking_change: true
body: |
Our CI/CD templates have been updated to no longer use hard-coded references to a `master` branch. In 14.0, they all use a variable that points to your project's configured default branch instead. If your CI/CD pipeline relies on our built-in templates, verify that this change works with your current configuration. For example, if you have a `master` branch and a different default branch, the updates to the templates may cause changes to your pipeline behavior. For more information, [read the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324131).
diff --git a/data/removals/14_0/deuley_servicetemplates_removal.yml b/data/removals/14_0/deuley_servicetemplates_removal.yml
index 94816bbee4a..bbc70d98562 100644
--- a/data/removals/14_0/deuley_servicetemplates_removal.yml
+++ b/data/removals/14_0/deuley_servicetemplates_removal.yml
@@ -1,7 +1,8 @@
-- name: "Service Templates removed"
+- name: "Service Templates"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deuley
+ breaking_change: true
body: |
Service Templates are [removed in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/5672). They were used to apply identical settings to a large number of projects, but they only did so at the time of project creation.
diff --git a/data/removals/14_0/release_announce_deprecation_of_release_notes_api.yml b/data/removals/14_0/release_announce_deprecation_of_release_notes_api.yml
index 066022dae87..d7e12a89f14 100644
--- a/data/removals/14_0/release_announce_deprecation_of_release_notes_api.yml
+++ b/data/removals/14_0/release_announce_deprecation_of_release_notes_api.yml
@@ -1,7 +1,8 @@
-- name: "Removal of release description in the Tags API"
+- name: "Release description in the Tags API"
reporter: kbychu
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/300887'
+ breaking_change: true
body: |
GitLab 14.0 removes support for the release description in the Tags API. You can no longer add a release description when [creating a new tag](https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag). You also can no longer [create](https://docs.gitlab.com/ee/api/tags.html#create-a-new-release) or [update](https://docs.gitlab.com/ee/api/tags.html#update-a-release) a release through the Tags API. Please migrate to use the [Releases API](https://docs.gitlab.com/ee/api/releases/#create-a-release) instead.
diff --git a/data/removals/14_0/release_deprecation_auto-deploy-image.yml b/data/removals/14_0/release_deprecation_auto-deploy-image.yml
index 7a8f0e598c4..d6cd9ac23ca 100644
--- a/data/removals/14_0/release_deprecation_auto-deploy-image.yml
+++ b/data/removals/14_0/release_deprecation_auto-deploy-image.yml
@@ -1,9 +1,10 @@
-- name: "Update Auto Deploy template version"
+- name: "Auto Deploy CI template v1"
reporter: kbychu
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/300862'
+ breaking_change: true
body: |
- In GitLab 14.0, we will update the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the v2 [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). Auto Deploy CI tempalte v1 will is deprecated going forward.
+ In GitLab 14.0, we will update the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the v2 [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). Auto Deploy CI template v1 is deprecated going forward.
Since the v1 and v2 versions are not backward-compatible, your project might encounter an unexpected failure if you already have a deployed application. Follow the [upgrade guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#upgrade-guide) to upgrade your environments. You can also start using the latest template today by following the [early adoption guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#early-adopters).
diff --git a/data/removals/14_0/release_domainsource_configuration_for_gitlab_pages_deprecation.yml b/data/removals/14_0/release_domainsource_configuration_for_gitlab_pages_deprecation.yml
index 694c168fb93..bb10ab8a2ab 100644
--- a/data/removals/14_0/release_domainsource_configuration_for_gitlab_pages_deprecation.yml
+++ b/data/removals/14_0/release_domainsource_configuration_for_gitlab_pages_deprecation.yml
@@ -1,7 +1,8 @@
-- name: "Remove disk source configuration for GitLab Pages"
+- name: "Disk source configuration for GitLab Pages"
reporter: kbychu
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993'
+ breaking_change: true
body: |
GitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration) has been available since GitLab 13.0. It replaces the unsupported `disk` source configuration removed in GitLab 14.0, which can no longer be chosen. You should stop using `disk` source configuration, and move to `gitlab` for an API-based configuration. To migrate away from the 'disk' source configuration, set `gitlab_pages['domain_config_source'] = "gitlab"` in your `/etc/gitlab/gitlab.rb` file. We recommend you migrate before updating to GitLab 14.0, to identify and troubleshoot any potential problems before upgrading.
diff --git a/data/removals/14_0/release_legacy_feature_flags_deprecation.yml b/data/removals/14_0/release_legacy_feature_flags_deprecation.yml
index aa62be7eb1d..bf0075faa1e 100644
--- a/data/removals/14_0/release_legacy_feature_flags_deprecation.yml
+++ b/data/removals/14_0/release_legacy_feature_flags_deprecation.yml
@@ -1,7 +1,8 @@
-- name: "Legacy feature flags removed"
+- name: "Legacy feature flags"
reporter: kbychu
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/254324'
+ breaking_change: true
body: |
Legacy feature flags became read-only in GitLab 13.4. GitLab 14.0 removes support for legacy feature flags, so you must migrate them to the [new version](https://docs.gitlab.com/ee/operations/feature_flags.html). You can do this by first taking a note (screenshot) of the legacy flag, then deleting the flag through the API or UI (you don't need to alter the code), and finally create a new Feature Flag with the same name as the legacy flag you deleted. Also, make sure the strategies and environments match the deleted flag. We created a [video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) to help with this migration.
diff --git a/data/removals/14_0/release_remove_redundant_keyvalue_pair_from_the_payload_of_dora.yml b/data/removals/14_0/release_remove_redundant_keyvalue_pair_from_the_payload_of_dora.yml
index 48e79230297..47c58bcb143 100644
--- a/data/removals/14_0/release_remove_redundant_keyvalue_pair_from_the_payload_of_dora.yml
+++ b/data/removals/14_0/release_remove_redundant_keyvalue_pair_from_the_payload_of_dora.yml
@@ -1,7 +1,8 @@
-- name: "Remove redundant timestamp field from DORA metrics API payload"
+- name: "Redundant timestamp field from DORA metrics API payload"
reporter: kbychu
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325931'
+ breaking_change: true
body: |
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
diff --git a/data/removals/14_0/removal-geo-fdw-settings.yml b/data/removals/14_0/removal-geo-fdw-settings.yml
index c2066269cb8..5997705bf30 100644
--- a/data/removals/14_0/removal-geo-fdw-settings.yml
+++ b/data/removals/14_0/removal-geo-fdw-settings.yml
@@ -1,7 +1,8 @@
-- name: "Geo Foreign Data Wrapper settings removed"
+- name: "Geo Foreign Data Wrapper settings"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: fzimmer
+ breaking_change: true
body: |
As [announced in GitLab 13.3](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#geo-foreign-data-wrapper-settings-deprecated), the following configuration settings in `/etc/gitlab/gitlab.rb` have been removed in 14.0:
diff --git a/data/removals/14_0/removal-graphql-fields.yml b/data/removals/14_0/removal-graphql-fields.yml
index 24d2bb4a4eb..71d277bd6fc 100644
--- a/data/removals/14_0/removal-graphql-fields.yml
+++ b/data/removals/14_0/removal-graphql-fields.yml
@@ -1,7 +1,8 @@
-- name: "Deprecated GraphQL fields have been removed"
+- name: "Deprecated GraphQL fields"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: gweaver
+ breaking_change: true
body: |
In accordance with our [GraphQL deprecation and removal process](https://docs.gitlab.com/ee/api/graphql/#deprecation-process), the following fields that were deprecated prior to 13.7 are [fully removed in 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/267966):
diff --git a/data/removals/14_0/removal-legacy-storage.yml b/data/removals/14_0/removal-legacy-storage.yml
index 677ec7b8512..28b6ffeb0d1 100644
--- a/data/removals/14_0/removal-legacy-storage.yml
+++ b/data/removals/14_0/removal-legacy-storage.yml
@@ -1,6 +1,7 @@
-- name: "Legacy storage removed"
+- name: "Legacy storage"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: fzimmer
+ breaking_change: true
body: |
As [announced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#planned-removal-of-legacy-storage-in-14.0), [legacy storage](https://docs.gitlab.com/ee/administration/repository_storage_types.html#legacy-storage) has been removed in GitLab 14.0.
diff --git a/data/removals/14_0/removal-protect-features.yml b/data/removals/14_0/removal-protect-features.yml
index 8e50925f6db..e8e71f7bbcd 100644
--- a/data/removals/14_0/removal-protect-features.yml
+++ b/data/removals/14_0/removal-protect-features.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: sam.white
+ breaking_change: true
body: |
Clair, the default container scanning engine, was deprecated in GitLab 13.9 and is removed from GitLab 14.0 and replaced by Trivy. We advise customers who are customizing variables for their container scanning job to [follow these instructions](https://docs.gitlab.com/ee/user/application_security/container_scanning/#change-scanners) to ensure that their container scanning jobs continue to work.
@@ -9,5 +10,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: sam.white
+ breaking_change: true
body: |
The Web Application Firewall (WAF) was deprecated in GitLab 13.6 and is removed from GitLab 14.0. The WAF had limitations inherent in the architectural design that made it difficult to meet the requirements traditionally expected of a WAF. By removing the WAF, GitLab is able to focus on improving other areas in the product where more value can be provided to users. Users who currently rely on the WAF can continue to use the free and open source [ModSecurity](https://github.com/SpiderLabs/ModSecurity) project, which is independent from GitLab. Additional details are available in the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271276).
diff --git a/data/removals/14_0/removal-sidekiq_experimental_queue_selector.yml b/data/removals/14_0/removal-sidekiq_experimental_queue_selector.yml
index 442c0e97cde..9995e5a2b55 100644
--- a/data/removals/14_0/removal-sidekiq_experimental_queue_selector.yml
+++ b/data/removals/14_0/removal-sidekiq_experimental_queue_selector.yml
@@ -1,7 +1,8 @@
-- name: Sidekiq queue selector options no longer accept the 'experimental' prefix
+- name: Experimental prefix in Sidekiq queue selector options
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: smcgivern
+ breaking_change: true
body: |
GitLab supports a [queue selector](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html#queue-selector) to run only a subset of background jobs for a given process. When it was introduced, this option had an 'experimental' prefix (`experimental_queue_selector` in Omnibus, `experimentalQueueSelector` in Helm charts).
diff --git a/data/removals/14_0/removal-unicorn.yml b/data/removals/14_0/removal-unicorn.yml
index af0bed0f3ec..d5062aa0eea 100644
--- a/data/removals/14_0/removal-unicorn.yml
+++ b/data/removals/14_0/removal-unicorn.yml
@@ -1,6 +1,7 @@
-- name: "Unicorn removed in favor of Puma for GitLab self-managed"
+- name: "Unicorn in GitLab self-managed"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: fzimmer
+ breaking_change: true
body: |
[Support for Unicorn](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6078) has been removed in GitLab 14.0 in favor of Puma. [Puma has a multi-threaded architecture](https://docs.gitlab.com/ee/administration/operations/puma.html) which uses less memory than a multi-process application server like Unicorn. On GitLab.com, we saw a 40% reduction in memory consumption by using Puma.
diff --git a/data/removals/14_0/removal_ci_project_config_path.yml b/data/removals/14_0/removal_ci_project_config_path.yml
index 8e90c83c7c4..64fe187c505 100644
--- a/data/removals/14_0/removal_ci_project_config_path.yml
+++ b/data/removals/14_0/removal_ci_project_config_path.yml
@@ -1,7 +1,8 @@
-- name: "`CI_PROJECT_CONFIG_PATH` variable has been removed"
+- name: "`CI_PROJECT_CONFIG_PATH` variable"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: stkerr
+ breaking_change: true
body: |
The `CI_PROJECT_CONFIG_PATH` [predefined project variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
has been removed in favor of `CI_CONFIG_PATH`, which is functionally the same.
diff --git a/data/removals/14_0/removal_enablement_helm2.yml b/data/removals/14_0/removal_enablement_helm2.yml
index 323b22fd3b4..09136bead3e 100644
--- a/data/removals/14_0/removal_enablement_helm2.yml
+++ b/data/removals/14_0/removal_enablement_helm2.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: joshlambert
+ breaking_change: true
body: |
Helm v2 was [officially deprecated](https://helm.sh/blog/helm-v2-deprecation-timeline/) in November of 2020, with the `stable` repository being [de-listed from the Helm Hub](https://about.gitlab.com/blog/2020/11/09/ensure-auto-devops-work-after-helm-stable-repo/) shortly thereafter. With the release of GitLab 14.0, which will include the 5.0 release of the [GitLab Helm chart](https://docs.gitlab.com/charts/), Helm v2 will no longer be supported.
diff --git a/data/removals/14_0/removal_enablement_opensuse_15_1.yml b/data/removals/14_0/removal_enablement_opensuse_15_1.yml
index cff442d7b92..2e0333c3b88 100644
--- a/data/removals/14_0/removal_enablement_opensuse_15_1.yml
+++ b/data/removals/14_0/removal_enablement_opensuse_15_1.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: dorrino
+ breaking_change: true
body: |
Support for [OpenSUSE Leap 15.1 is being deprecated](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5135). Support for 15.1 will be dropped in 14.0. We are now providing support for openSUSE Leap 15.2 packages.
diff --git a/data/removals/14_0/removal_enablement_pg11.yml b/data/removals/14_0/removal_enablement_pg11.yml
index c7b9f8b528b..7c5738b7ff9 100644
--- a/data/removals/14_0/removal_enablement_pg11.yml
+++ b/data/removals/14_0/removal_enablement_pg11.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: joshlambert
+ breaking_change: true
body: |
PostgreSQL 12 will be the minimum required version in GitLab 14.0. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits.
diff --git a/data/removals/14_0/removal_enablement_ubuntu_16.yml b/data/removals/14_0/removal_enablement_ubuntu_16.yml
index 65457db8c68..593bac720c1 100644
--- a/data/removals/14_0/removal_enablement_ubuntu_16.yml
+++ b/data/removals/14_0/removal_enablement_ubuntu_16.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: joshlambert
+ breaking_change: true
body: |
Ubuntu 16.04 [reached end-of-life in April 2021](https://ubuntu.com/about/release-cycle), and no longer receives maintenance updates. We strongly recommend users to upgrade to a newer release, such as 20.04.
diff --git a/data/removals/14_0/removal_repost_static_analysis_notices.yml b/data/removals/14_0/removal_repost_static_analysis_notices.yml
index 1105f21e3fd..1a2ae93a902 100644
--- a/data/removals/14_0/removal_repost_static_analysis_notices.yml
+++ b/data/removals/14_0/removal_repost_static_analysis_notices.yml
@@ -3,34 +3,37 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/229974'
+ breaking_change: true
body: |
Until GitLab 13.9, if you wanted to avoid running one particular GitLab SAST analyzer, you needed to remove it from the [long string of analyzers in the `SAST.gitlab-ci.yml` file](https://gitlab.com/gitlab-org/gitlab/-/blob/390afc431e7ce1ac253b35beb39f19e49c746bff/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L12) and use that to set the [`SAST_DEFAULT_ANALYZERS`](https://docs.gitlab.com/ee/user/application_security/sast/#docker-images) variable in your project's CI file. If you did this, it would exclude you from future new analyzers because this string hard codes the list of analyzers to execute. We avoid this problem by inverting this variable's logic to exclude, rather than choose default analyzers.
Beginning with 13.9, [we migrated](https://gitlab.com/gitlab-org/gitlab/-/blob/14fed7a33bfdbd4663d8928e46002a5ef3e3282c/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L13) to `SAST_EXCLUDED_ANALYZERS` in our `SAST.gitlab-ci.yml` file. We encourage anyone who uses a [customized SAST configuration](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) in their project CI file to migrate to this new variable. If you have not overridden `SAST_DEFAULT_ANALYZERS`, no action is needed. The CI/CD variable `SAST_DEFAULT_ANALYZERS` has been removed in GitLab 14.0, which released on June 22, 2021.
-- name: "Remove `secret_detection_default_branch` job"
+- name: "`secret_detection_default_branch` job"
reporter: tmccaslin
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297269'
+ breaking_change: true
body: |
To ensure Secret Detection was scanning both default branches and feature branches, we introduced two separate secret detection CI jobs (`secret_detection_default_branch` and `secret_detection`) in our managed [`Secret-Detection.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) template. These two CI jobs created confusion and complexity in the CI rules logic. This deprecation moves the `rule` logic into the `script` section, which then determines how the `secret_detection` job is run (historic, on a branch, commits, etc).
If you override or maintain custom versions of `SAST.gitlab-ci.yml` or `Secret-Detection.gitlab-ci.yml`, you must update your CI templates. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/secret_detection/#custom-settings-example) to future-proof your CI templates. GitLab 14.0 no longer supports the old `secret_detection_default_branch` job.
-- name: "Remove SAST analyzer `SAST_GOSEC_CONFIG` variable in favor of
- custom rulesets"
+- name: "SAST analyzer `SAST_GOSEC_CONFIG` variable"
reporter: tmccaslin
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/301215'
+ breaking_change: true
body: |
With the release of [SAST Custom Rulesets](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) in GitLab 13.5 we allow greater flexibility in configuration options for our Go analyzer (GoSec). As a result we no longer plan to support our less flexible [`SAST_GOSEC_CONFIG`](https://docs.gitlab.com/ee/user/application_security/sast/#analyzer-settings) analyzer setting. This variable was deprecated in GitLab 13.10.
GitLab 14.0 removes the old `SAST_GOSEC_CONFIG variable`. If you use or override `SAST_GOSEC_CONFIG` in your CI file, update your SAST CI configuration or pin to an older version of the GoSec analyzer. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs) to future-proof your CI templates.
-- name: "Removed Global `SAST_ANALYZER_IMAGE_TAG` in SAST CI template"
+- name: "Global `SAST_ANALYZER_IMAGE_TAG` in SAST CI template"
reporter: tmccaslin
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/301216'
+ breaking_change: true
body: |
With the maturity of GitLab Secure scanning tools, we've needed to add more granularity to our release process. Previously, GitLab shared a major version number for [all analyzers and tools](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). This requires all tools to share a major version, and prevents the use of [semantic version numbering](https://semver.org/). In GitLab 14.0, SAST removes the `SAST_ANALYZER_IMAGE_TAG` global variable in our [managed `SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml) CI template, in favor of the analyzer job variable setting the `major.minor` tag in the SAST vendored template.
diff --git a/data/removals/14_0/removal_runner_25555.yml b/data/removals/14_0/removal_runner_25555.yml
index f317eaab846..706614618ce 100644
--- a/data/removals/14_0/removal_runner_25555.yml
+++ b/data/removals/14_0/removal_runner_25555.yml
@@ -1,7 +1,8 @@
-- name: "Remove off peak time mode configuration for Docker Machine autoscaling"
+- name: "Off peak time mode configuration for Docker Machine autoscaling"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In GitLab Runner 13.0, [issue #5069](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/5069), we introduced new timing options for the GitLab Docker Machine executor. In GitLab Runner 14.0, we have removed the old configuration option, [off peak time mode](https://docs.gitlab.com/runner/configuration/autoscale.html#off-peak-time-mode-configuration-deprecated).
diff --git a/data/removals/14_0/removal_runner_26036.yml b/data/removals/14_0/removal_runner_26036.yml
index 564143fda82..5f391909a2d 100644
--- a/data/removals/14_0/removal_runner_26036.yml
+++ b/data/removals/14_0/removal_runner_26036.yml
@@ -1,6 +1,7 @@
-- name: "Remove Ubuntu 19.10 (Eoan Ermine) package"
+- name: "Ubuntu 19.10 (Eoan Ermine) package"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
Ubuntu 19.10 (Eoan Ermine) reached end of life on Friday, July 17, 2020. In GitLab Runner 14.0, Ubuntu 19.10 (Eoan Ermine) is no longer available from our package distribution. Refer to [issue #26036](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26036) for details.
diff --git a/data/removals/14_0/removal_runner_26419.yml b/data/removals/14_0/removal_runner_26419.yml
index 8b0f3846c7a..85d57de763e 100644
--- a/data/removals/14_0/removal_runner_26419.yml
+++ b/data/removals/14_0/removal_runner_26419.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In GitLab Runner 13.2, PowerShell Core support was added to the Shell executor. In 14.0, PowerShell Core, `pwsh` is now the default shell for newly-registered Windows runners. Windows `CMD` will still be available as a shell option for Windows runners. Refer to [issue #26419](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26419) for details.
diff --git a/data/removals/14_0/removal_runner_4845.yml b/data/removals/14_0/removal_runner_4845.yml
index 92e4e0172f2..db25c0741cb 100644
--- a/data/removals/14_0/removal_runner_4845.yml
+++ b/data/removals/14_0/removal_runner_4845.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In GitLab Runner 14.0, the installation process will ignore the `skel` directory by default when creating the user home directory. Refer to [issue #4845](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4845) for details.
diff --git a/data/removals/14_0/removal_runner_6413.yml b/data/removals/14_0/removal_runner_6413.yml
index f08b1091cca..514cb254d8d 100644
--- a/data/removals/14_0/removal_runner_6413.yml
+++ b/data/removals/14_0/removal_runner_6413.yml
@@ -1,6 +1,7 @@
-- name: "Remove `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL` feature flag"
+- name: "`FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL` feature flag"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In [GitLab Runner 13.1](https://docs.gitlab.com/runner/executors/shell.html#gitlab-131-and-later), [issue #3376](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3376), we introduced `sigterm` and then `sigkill` to a process in the Shell executor. We also introduced a new feature flag, `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL`, so you can use the previous process termination sequence. In GitLab Runner 14.0, [issue #6413](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6413), the feature flag has been removed.
diff --git a/data/removals/14_0/removals-14-testing-team.yml b/data/removals/14_0/removals-14-testing-team.yml
index d76de564cdd..2012f8738b8 100644
--- a/data/removals/14_0/removals-14-testing-team.yml
+++ b/data/removals/14_0/removals-14-testing-team.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: jheimbuck_gl
+ breaking_change: true
body: |
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
@@ -10,6 +11,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: jheimbuck_gl
+ breaking_change: true
body: |
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#rubocop-errors).
@@ -18,6 +20,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: jheimbuck_gl
+ breaking_change: true
body: |
By default, the `Ruby.gitlab-ci.yml` file has included Ruby 2.5.
diff --git a/data/removals/14_0/removals_runner_26651.yml b/data/removals/14_0/removals_runner_26651.yml
index a22f8dfc9ac..8a35996c81a 100644
--- a/data/removals/14_0/removals_runner_26651.yml
+++ b/data/removals/14_0/removals_runner_26651.yml
@@ -1,6 +1,7 @@
-- name: "Remove `/usr/lib/gitlab-runner` symlink from package"
+- name: "`/usr/lib/gitlab-runner` symlink from package"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In GitLab Runner 13.3, a symlink was added from `/user/lib/gitlab-runner/gitlab-runner` to `/usr/bin/gitlab-runner`. In 14.0, the symlink has been removed and the runner is now installed in `/usr/bin/gitlab-runner`. Refer to [issue #26651](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26651) for details.
diff --git a/data/removals/14_0/removals_runner_26679.yml b/data/removals/14_0/removals_runner_26679.yml
index 816bd8f37d5..e99a551a293 100644
--- a/data/removals/14_0/removals_runner_26679.yml
+++ b/data/removals/14_0/removals_runner_26679.yml
@@ -1,6 +1,7 @@
-- name: "Remove `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag"
+- name: "`FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In 14.0, we have deactivated the `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag. Refer to issue [#26679](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26679) for details.
diff --git a/data/removals/14_0/removals_runner_26900.yml b/data/removals/14_0/removals_runner_26900.yml
index bdba368eee8..addf11c86ad 100644
--- a/data/removals/14_0/removals_runner_26900.yml
+++ b/data/removals/14_0/removals_runner_26900.yml
@@ -1,6 +1,7 @@
-- name: "Remove success and failure for finished build metric conversion"
+- name: "Success and failure for finished build metric conversion"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In GitLab Runner 13.5, we introduced `failed` and `success` states for a job. To support Prometheus rules, we chose to convert `success/failure` to `finished` for the metric. In 14.0, the conversion has now been removed. Refer to [issue #26900](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26900) for details.
diff --git a/data/removals/14_0/removals_runner_27175.yml b/data/removals/14_0/removals_runner_27175.yml
index 33629084073..a31c4e757e7 100644
--- a/data/removals/14_0/removals_runner_27175.yml
+++ b/data/removals/14_0/removals_runner_27175.yml
@@ -1,6 +1,7 @@
-- name: "Remove `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag"
+- name: "`FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
GitLab Runner 14.0 removes the `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag. Refer to [issue #27175](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27175) for details.
diff --git a/data/removals/14_0/removals_runner_27218.yml b/data/removals/14_0/removals_runner_27218.yml
index fb1e27c3f91..8fb7e800b0b 100644
--- a/data/removals/14_0/removals_runner_27218.yml
+++ b/data/removals/14_0/removals_runner_27218.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In 14.0, we are now pulling the GitLab Runner [helper image](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#helper-image) from the GitLab Container Registry instead of Docker Hub. Refer to [issue #27218](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27218) for details.
diff --git a/data/removals/14_0/removals_runner_27551.yml b/data/removals/14_0/removals_runner_27551.yml
index 6f4ee52749c..43ecf3d72f6 100644
--- a/data/removals/14_0/removals_runner_27551.yml
+++ b/data/removals/14_0/removals_runner_27551.yml
@@ -1,6 +1,7 @@
-- name: "Remove support for Windows Server 1903 image"
+- name: "Windows Server 1903 image support"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In 14.0, we have removed Windows Server 1903. Microsoft ended support for this version on 2020-08-12. Refer to [issue #27551](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27551) for details.
diff --git a/data/removals/14_0/removals_runner_27899.yml b/data/removals/14_0/removals_runner_27899.yml
index 226520abda4..468e04dc677 100644
--- a/data/removals/14_0/removals_runner_27899.yml
+++ b/data/removals/14_0/removals_runner_27899.yml
@@ -1,6 +1,7 @@
-- name: "Remove support for Windows Server 1909 image"
+- name: "Windows Server 1909 image support"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: deastman
+ breaking_change: true
body: |
In 14.0, we have removed Windows Server 1909. Microsoft ended support for this version on 2021-05-11. Refer to [issue #27899](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27899) for details.
diff --git a/data/removals/14_0/remove-sql-elector.yml b/data/removals/14_0/remove-sql-elector.yml
index d35fac0786c..6a306569d9f 100644
--- a/data/removals/14_0/remove-sql-elector.yml
+++ b/data/removals/14_0/remove-sql-elector.yml
@@ -1,7 +1,8 @@
-- name: "Gitaly Cluster SQL primary elector has been removed"
+- name: "Gitaly Cluster SQL primary elector"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: mjwood
+ breaking_change: true
body: |
Now that Praefect supports a [primary election strategy](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#repository-specific-primary-nodes) for each repository, we have removed the `sql` election strategy.
The `per_repository` election strategy is the new default, which is automatically used if no election strategy was specified.
diff --git a/data/removals/14_0/remove_dast_env_variables.yml b/data/removals/14_0/remove_dast_env_variables.yml
index f2bbe748af5..3a40c6518e0 100644
--- a/data/removals/14_0/remove_dast_env_variables.yml
+++ b/data/removals/14_0/remove_dast_env_variables.yml
@@ -2,6 +2,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: derekferguson
+ breaking_change: true
body: |
GitLab 13.8 renamed multiple environment variables to support their broader usage in different workflows. In GitLab 14.0, the old variables have been permanently removed and will no longer work. Any configurations using these variables must be updated to the new variable names. Any scans using these variables in GitLab 14.0 and later will fail to be configured correctly. These variables are:
diff --git a/data/removals/14_0/remove_dast_legacy_domain_validation.yml b/data/removals/14_0/remove_dast_legacy_domain_validation.yml
index 61fb9002880..39acc3e7188 100644
--- a/data/removals/14_0/remove_dast_legacy_domain_validation.yml
+++ b/data/removals/14_0/remove_dast_legacy_domain_validation.yml
@@ -1,7 +1,8 @@
-- name: "Remove legacy DAST domain validation"
+- name: "Legacy DAST domain validation"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: derekferguson
+ breaking_change: true
body: |
The legacy method of DAST Domain Validation for CI/CD scans was deprecated in GitLab 13.8, and is removed in GitLab 14.0. This method of domain validation only disallows scans if the `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` environment variable is set to `true` in the `gitlab-ci.yml` file, and a `Gitlab-DAST-Permission` header on the site is not set to `allow`. This two-step method required users to opt in to using the variable before they could opt out from using the header.
diff --git a/data/removals/14_0/remove_dast_legacy_report_fields.yml b/data/removals/14_0/remove_dast_legacy_report_fields.yml
index ec98b173a24..e5fca1fa256 100644
--- a/data/removals/14_0/remove_dast_legacy_report_fields.yml
+++ b/data/removals/14_0/remove_dast_legacy_report_fields.yml
@@ -1,7 +1,8 @@
-- name: "Removal of legacy fields from DAST report"
+- name: "Legacy fields from DAST report"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: derekferguson
+ breaking_change: true
body: |
As a part of the migration to a common report format for all of the Secure scanners in GitLab, DAST is making changes to the DAST JSON report. Certain legacy fields were deprecated in 13.8 and have been completely removed in 14.0. These fields are `@generated`, `@version`, `site`, and `spider`. This should not affect any normal DAST operation, but does affect users who consume the JSON report in an automated way and use these fields. Anyone affected by these changes, and needs these fields for business reasons, is encouraged to open a new GitLab issue and explain the need.
diff --git a/data/removals/14_0/remove_dast_spider_host_reset.yml b/data/removals/14_0/remove_dast_spider_host_reset.yml
index de334618b88..53122f6071f 100644
--- a/data/removals/14_0/remove_dast_spider_host_reset.yml
+++ b/data/removals/14_0/remove_dast_spider_host_reset.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: derekferguson
+ breaking_change: true
body: |
In GitLab 14.0, DAST has removed the current method of resetting the scan to the hostname when starting to spider. Prior to GitLab 14.0, the spider would not begin at the specified target path for the URL but would instead reset the URL to begin crawling at the host root. GitLab 14.0 changes the default for the new variable `DAST_SPIDER_START_AT_HOST` to `false` to better support users' intention of beginning spidering and scanning at the specified target URL, rather than the host root URL. This change has an added benefit: scans can take less time, if the specified path does not contain links to the entire site. This enables easier scanning of smaller sections of an application, rather than crawling the entire app during every scan.
diff --git a/data/removals/14_0/remove_dast_template_stages.yml b/data/removals/14_0/remove_dast_template_stages.yml
index 0f72091735d..0995e09c3ed 100644
--- a/data/removals/14_0/remove_dast_template_stages.yml
+++ b/data/removals/14_0/remove_dast_template_stages.yml
@@ -1,6 +1,7 @@
-- name: "Remove DAST default template stages"
+- name: "DAST default template stages"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: derekferguson
+ breaking_change: true
body: |
In GitLab 14.0, we've removed the stages defined in the current `DAST.gitlab-ci.yml` template to avoid the situation where the template overrides manual changes made by DAST users. We're making this change in response to customer issues where the stages in the template cause problems when used with customized DAST configurations. Because of this removal, `gitlab-ci.yml` configurations that do not specify a `dast` stage must be updated to include this stage.
diff --git a/data/removals/14_0/remove_optimize_api.yml b/data/removals/14_0/remove_optimize_api.yml
index 5df120858c6..a472e6a0d59 100644
--- a/data/removals/14_0/remove_optimize_api.yml
+++ b/data/removals/14_0/remove_optimize_api.yml
@@ -1,6 +1,7 @@
-- name: "Segments removed from DevOps Adoption API"
+- name: "DevOps Adoption API Segments"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: ljlane
+ breaking_change: true
body: |
The first release of the DevOps Adoption report had a concept of **Segments**. Segments were [quickly removed from the report](https://gitlab.com/groups/gitlab-org/-/epics/5251) because they introduced an additional layer of complexity on top of **Groups** and **Projects**. Subsequent iterations of the DevOps Adoption report focus on comparing adoption across groups rather than segments. GitLab 14.0 removes all references to **Segments** [from the GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/324414) and replaces them with **Enabled groups**.
diff --git a/data/removals/14_0/remove_terraform_template.yml b/data/removals/14_0/remove_terraform_template.yml
index bc3b529f630..2d78eb1f59c 100644
--- a/data/removals/14_0/remove_terraform_template.yml
+++ b/data/removals/14_0/remove_terraform_template.yml
@@ -3,6 +3,7 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/328500'
+ breaking_change: true
body: |
GitLab 14.0 renews the Terraform CI template to the latest version. The new template is set up for the GitLab Managed Terraform state, with a dependency on the GitLab `terraform-images` image, to provide a good user experience around GitLab's Infrastructure-as-Code features.
diff --git a/data/removals/14_0/verify-ci-removal-parametertrace.yml b/data/removals/14_0/verify-ci-removal-parametertrace.yml
index c37497c1a35..67d52827485 100644
--- a/data/removals/14_0/verify-ci-removal-parametertrace.yml
+++ b/data/removals/14_0/verify-ci-removal-parametertrace.yml
@@ -1,7 +1,8 @@
-- name: "Removal of deprecated `trace` parameter from `jobs` API endpoint"
+- name: "`trace` parameter in `jobs` API"
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: jreporter
+ breaking_change: true
body: |
GitLab Runner was updated in GitLab 13.4 to internally stop passing the `trace` parameter to the `/api/jobs/:id` endpoint. GitLab 14.0 deprecates the `trace` parameter entirely for all other requests of this endpoint. Make sure your [GitLab Runner version matches your GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions) to ensure consistent behavior.
diff --git a/data/removals/14_0/verify-ci-removalpipelineservice.yml b/data/removals/14_0/verify-ci-removalpipelineservice.yml
index f3583bd0498..fe3d3f224d1 100644
--- a/data/removals/14_0/verify-ci-removalpipelineservice.yml
+++ b/data/removals/14_0/verify-ci-removalpipelineservice.yml
@@ -2,5 +2,6 @@
removal_date: "2021-06-22"
removal_milestone: "14.0"
reporter: jreporter
+ breaking_change: true
body: |
For self-managed instances using the experimental [external pipeline validation service](https://docs.gitlab.com/ee/administration/external_pipeline_validation.html), the range of error codes GitLab accepts will be reduced. Currently, pipelines are invalidated when the validation service returns a response code from `400` to `499`. In GitLab 14.0 and later, pipelines will be invalidated for the `406: Not Accepted` response code only.
diff --git a/data/removals/14_1/removal-memory-prometheus-options-source.yml b/data/removals/14_1/removal-memory-prometheus-options-source.yml
index afef081c348..57a5dfa5d69 100644
--- a/data/removals/14_1/removal-memory-prometheus-options-source.yml
+++ b/data/removals/14_1/removal-memory-prometheus-options-source.yml
@@ -2,6 +2,7 @@
removal_date: July 22, 2021
removal_milestone: "14.1"
reporter: fzimmer
+ breaking_change: false
body: |
The support for `prometheus.listen_address` and `prometheus.enable` has been removed from `gitlab.yml`. Use `prometheus.enabled` and `prometheus.server_address` to set up Prometheus server that GitLab instance connects to. Refer to [our documentation](https://docs.gitlab.com/ee/install/installation.html#prometheus-server-setup) for details.
diff --git a/data/removals/14_1/removal-outdated-browser-support.yml b/data/removals/14_1/removal-outdated-browser-support.yml
index 1019b8fe2f3..281b8d65686 100644
--- a/data/removals/14_1/removal-outdated-browser-support.yml
+++ b/data/removals/14_1/removal-outdated-browser-support.yml
@@ -2,6 +2,7 @@
removal_date: July 22, 2021
removal_milestone: "14.1"
reporter: leipert
+ breaking_change: false
body: |
In GitLab 14.1, we are cleaning up and [removing old code](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63994) that was specific for browsers that we no longer support. This has no impact on users when one of our [supported web browsers](https://docs.gitlab.com/ee/install/requirements.html#supported-web-browsers) is used.
diff --git a/data/removals/14_2/removal-verify-build-log.yml b/data/removals/14_2/removal-verify-build-log.yml
index 6b4e37c7c6e..10ffe8b7242 100644
--- a/data/removals/14_2/removal-verify-build-log.yml
+++ b/data/removals/14_2/removal-verify-build-log.yml
@@ -2,6 +2,7 @@
removal_date: August 22, 2021 # day the removal was released
removal_milestone: "14.2"
reporter: jreporter # GitLab username of the person reporting the removal
+ breaking_change: false
body: |
GitLab values efficiency for all users in our wider community of contributors, so we're always working hard to make sure the application performs at a high level with a lovable UX.
In GitLab 14.2, we have introduced a [job log file size limit](https://docs.gitlab.com/ee/administration/instance_limits.html#maximum-file-size-for-job-logs), set to 100 megabytes by default. Administrators of self-managed GitLab instances can customize this to any value. All jobs that exceed this limit are dropped and marked as failed, helping prevent performance impacts or over-use of resources. This ensures that everyone using GitLab has the best possible experience.
diff --git a/data/removals/14_3/removal-limit-tags-to-50.yml b/data/removals/14_3/removal-limit-tags-to-50.yml
index db624656e6e..3395fc9b6ce 100644
--- a/data/removals/14_3/removal-limit-tags-to-50.yml
+++ b/data/removals/14_3/removal-limit-tags-to-50.yml
@@ -1,6 +1,7 @@
- name: "Introduced limit of 50 tags for jobs"
removal_date: September 22nd, 2021
removal_milestone: "14.3"
- reporter: jreporter
+ reporter: jreporter
+ breaking_change: false
body: |
GitLab values efficiency and is prioritizing reliability for [GitLab.com in FY22](https://about.gitlab.com/direction/#gitlab-hosted-first). In 14.3, GitLab CI/CD jobs must have less than 50 [tags](https://docs.gitlab.com/ee/ci/yaml/index.html#tags). If a pipeline contains a job with 50 or more tags, you will receive an error and the pipeline will not be created.
diff --git a/data/removals/14_3/removal-verify-pe-pipelinefindername.yml b/data/removals/14_3/removal-verify-pe-pipelinefindername.yml
index 979317f99df..df39a6cec38 100644
--- a/data/removals/14_3/removal-verify-pe-pipelinefindername.yml
+++ b/data/removals/14_3/removal-verify-pe-pipelinefindername.yml
@@ -2,5 +2,6 @@
removal_date: September 22, 2021 # day the removal was released
removal_milestone: "14.3"
reporter: jreporter # GitLab username of the person reporting the removal
+ breaking_change: false
body: |
In GitLab 14.3, we will remove the ability to filter by `name` in the [list project pipelines API endpoint](https://docs.gitlab.com/ee/api/pipelines.html#list-project-pipelines) to improve performance. If you currently use this parameter with this endpoint, you must switch to `username`.
diff --git a/data/removals/14_3/removal_legacy_storage_setting.yml b/data/removals/14_3/removal_legacy_storage_setting.yml
index b1f98e47554..5241861bf5a 100644
--- a/data/removals/14_3/removal_legacy_storage_setting.yml
+++ b/data/removals/14_3/removal_legacy_storage_setting.yml
@@ -2,6 +2,7 @@
removal_date: September 22nd, 2021 # day the removal was released
removal_milestone: "14.3"
reporter: dorrino # GitLab username of the person reporting the removal
+ breaking_change: false
body: | # example (supports markdown)
The support for [`gitlab_pages['use_legacy_storage']` setting](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) in Omnibus installations has been removed.
diff --git a/data/removals/14_6/limit_trigger_pipelines.yml b/data/removals/14_6/limit_trigger_pipelines.yml
new file mode 100644
index 00000000000..c69b7feecd2
--- /dev/null
+++ b/data/removals/14_6/limit_trigger_pipelines.yml
@@ -0,0 +1,6 @@
+- name: "Limit the number of triggered pipeline to 25K in free tier"
+ removal_date: Dec 22, 2021 # day the removal was released
+ removal_milestone: "14.6"
+ reporter: dhershkovitch # GitLab username of the person reporting the removal
+ body: |
+ A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change.
diff --git a/data/removals/14_6/removal-release-cli-s3.yml b/data/removals/14_6/removal-release-cli-s3.yml
new file mode 100644
index 00000000000..b92d8bb60f8
--- /dev/null
+++ b/data/removals/14_6/removal-release-cli-s3.yml
@@ -0,0 +1,6 @@
+- name: "Release CLI distributed as a generic package"
+ removal_date: Dec 22, 2021 # day the removal was released
+ removal_milestone: "14.6"
+ reporter: kbychu # GitLab username of the person reporting the removal
+ body: |
+ The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
diff --git a/data/removals/templates/_removal_template.md.erb b/data/removals/templates/_removal_template.md.erb
index e227c6aa6e6..5243f4fdcd8 100644
--- a/data/removals/templates/_removal_template.md.erb
+++ b/data/removals/templates/_removal_template.md.erb
@@ -33,6 +33,7 @@ For removal reviewers (Technical Writers only):
<%- entries.select{|entry| entry["removal_milestone"] == milestone}.each do |removal| %>
### <%= removal["name"]%>
<% if removal["breaking_change"] -%>
+
WARNING:
This feature was changed or removed in <%= removal["removal_milestone"]%>
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
diff --git a/data/removals/templates/example.yml b/data/removals/templates/example.yml
index 78cbec2be28..0904c6a6d7a 100644
--- a/data/removals/templates/example.yml
+++ b/data/removals/templates/example.yml
@@ -9,13 +9,14 @@
#
# Please delete this line and above before submitting your merge request.
-- name: "Announcement headline" # The headline announcing the removal. i.e. "`CI_PROJECT_CONFIG_PATH` removed in Gitlab 14.0"
- announcement_milestone: "XX.YY" # The milestone when this feature was deprecated.
- announcement_date: "YYYY-MM-DD" # The date of the milestone release when this feature was deprecated. This should almost always be the 22nd of a month (YYYY-MM-DD), unless you did an out of band blog post.
- removal_milestone: "XX.YY" # The milestone when this feature is being removed.
- removal_date: "YYYY-MM-DD" # This should almost always be the 22nd of a month (YYYY-MM-DD), the date of the milestone release when this feature will be removed.
- breaking_change: false # Change to true if this removal is a breaking change.
- body: | # Do not modify this line, instead modify the lines below.
+- name: "Feature name" # the name of the feature being removed. Avoid the words `deprecation`, `deprecate`, `removal`, and `remove` in this field because these are implied.
+ announcement_milestone: "XX.YY" # The milestone when this feature was deprecated.
+ announcement_date: "YYYY-MM-DD" # The date of the milestone release when this feature was deprecated. This should almost always be the 22nd of a month (YYYY-MM-DD), unless you did an out of band blog post.
+ removal_milestone: "XX.YY" # The milestone when this feature is being removed.
+ removal_date: "YYYY-MM-DD" # This should almost always be the 22nd of a month (YYYY-MM-DD), the date of the milestone release when this feature will be removed.
+ breaking_change: false # Change to true if this removal is a breaking change.
+ reporter: exampleuser # GitLab username of the person reporting the removal
+ body: | # Do not modify this line, instead modify the lines below.
<!-- START OF BODY COMMENT
This area supports markdown. Delete this entire comment and replace it with your markdown content.
@@ -24,9 +25,9 @@
END OF BODY COMMENT -->
# The following items are not published on the docs page, but may be used in the future.
- stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
- tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
- issue_url: # (optional) This is a link to the deprecation issue in GitLab
- documentation_url: # (optional) This is a link to the current documentation page
- image_url: # (optional) This is a link to a thumbnail image depicting the feature
- video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/whats_new/2021111800001_14_05.yml b/data/whats_new/2021111800001_14_05.yml
index c38d4cfa9fa..5a7607478fc 100644
--- a/data/whats_new/2021111800001_14_05.yml
+++ b/data/whats_new/2021111800001_14_05.yml
@@ -16,7 +16,7 @@
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/profile/#user-profile-readme'
+ url: 'https://docs.gitlab.com/ee/user/profile/#add-details-to-your-profile-with-a-readme'
image_url: https://about.gitlab.com/images/14_5/user_profiles_readme.png
published_at: 2021-11-22
release: 14.5
diff --git a/db/migrate/20210316171009_create_packages_helm_file_metadata.rb b/db/migrate/20210316171009_create_packages_helm_file_metadata.rb
index f5a9c5f1146..47a9b808e63 100644
--- a/db/migrate/20210316171009_create_packages_helm_file_metadata.rb
+++ b/db/migrate/20210316171009_create_packages_helm_file_metadata.rb
@@ -5,7 +5,7 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0]
DOWNTIME = false
- def change
+ def up
create_table_with_constraints :packages_helm_file_metadata, id: false do |t|
t.timestamps_with_timezone
t.references :package_file, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_package_files, on_delete: :cascade }, type: :bigint
@@ -17,4 +17,10 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0]
t.index :channel
end
end
+
+ def down
+ with_lock_retries do
+ drop_table :packages_helm_file_metadata
+ end
+ end
end
diff --git a/db/migrate/20210504153354_create_clusters_integration_elasticstack.rb b/db/migrate/20210504153354_create_clusters_integration_elasticstack.rb
index 5868325e701..79680821060 100644
--- a/db/migrate/20210504153354_create_clusters_integration_elasticstack.rb
+++ b/db/migrate/20210504153354_create_clusters_integration_elasticstack.rb
@@ -3,7 +3,7 @@
class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- def change
+ def up
create_table_with_constraints :clusters_integration_elasticstack, id: false do |t|
t.timestamps_with_timezone null: false
t.references :cluster, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
@@ -12,4 +12,10 @@ class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0]
t.text_limit :chart_version, 10
end
end
+
+ def down
+ with_lock_retries do
+ drop_table :clusters_integration_elasticstack
+ end
+ end
end
diff --git a/db/migrate/20210628154900_create_detached_partitions_table.rb b/db/migrate/20210628154900_create_detached_partitions_table.rb
index 05290f4dfb9..cf31d71835a 100644
--- a/db/migrate/20210628154900_create_detached_partitions_table.rb
+++ b/db/migrate/20210628154900_create_detached_partitions_table.rb
@@ -3,7 +3,7 @@
class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
- def change
+ def up
create_table_with_constraints :detached_partitions do |t|
t.timestamps_with_timezone null: false
t.datetime_with_timezone :drop_after, null: false
@@ -14,4 +14,10 @@ class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1]
t.text_limit :table_name, 63
end
end
+
+ def down
+ with_lock_retries do
+ drop_table :detached_partitions
+ end
+ end
end
diff --git a/db/migrate/20210720140841_create_postgres_async_indexes_table.rb b/db/migrate/20210720140841_create_postgres_async_indexes_table.rb
index 707367e5f6c..99025149840 100644
--- a/db/migrate/20210720140841_create_postgres_async_indexes_table.rb
+++ b/db/migrate/20210720140841_create_postgres_async_indexes_table.rb
@@ -3,7 +3,7 @@
class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
- def change
+ def up
create_table_with_constraints :postgres_async_indexes do |t|
t.timestamps_with_timezone null: false
@@ -18,4 +18,10 @@ class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1]
t.index :name, unique: true
end
end
+
+ def down
+ with_lock_retries do
+ drop_table :postgres_async_indexes
+ end
+ end
end
diff --git a/db/migrate/20210729081351_create_topics.rb b/db/migrate/20210729081351_create_topics.rb
index c6fdc6bb98a..13ed2dc7ccc 100644
--- a/db/migrate/20210729081351_create_topics.rb
+++ b/db/migrate/20210729081351_create_topics.rb
@@ -3,7 +3,7 @@
class CreateTopics < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
- def change
+ def up
create_table_with_constraints :topics do |t|
t.text :name, null: false
t.text_limit :name, 255
@@ -13,4 +13,10 @@ class CreateTopics < ActiveRecord::Migration[6.1]
t.timestamps_with_timezone
end
end
+
+ def down
+ with_lock_retries do
+ drop_table :topics
+ end
+ end
end
diff --git a/db/migrate/20210811193033_add_unique_index_to_vulnerability_finding_links.rb b/db/migrate/20210811193033_add_unique_index_to_vulnerability_finding_links.rb
index 1bcee89ae57..cf51bca630a 100644
--- a/db/migrate/20210811193033_add_unique_index_to_vulnerability_finding_links.rb
+++ b/db/migrate/20210811193033_add_unique_index_to_vulnerability_finding_links.rb
@@ -1,18 +1,14 @@
# frozen_string_literal: true
class AddUniqueIndexToVulnerabilityFindingLinks < Gitlab::Database::Migration[1.0]
- disable_ddl_transaction!
-
- NAME_URL_INDEX_NAME = 'finding_link_name_url_idx'
- URL_INDEX_NAME = 'finding_link_url_idx'
+ # This migration has been moved to db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb
+ # Previously, this was causing an bug where there was a conflict between the table cleanup and the index creation.
def up
- add_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :name, :url], unique: true, name: NAME_URL_INDEX_NAME
- add_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :url], unique: true, where: 'name is null', name: URL_INDEX_NAME
+ # no op
end
def down
- remove_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :name, :url], name: NAME_URL_INDEX_NAME
- remove_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :url], name: URL_INDEX_NAME
+ # no op
end
end
diff --git a/db/migrate/20211119111006_create_job_artifact_states.rb b/db/migrate/20211119111006_create_job_artifact_states.rb
new file mode 100644
index 00000000000..44dffed58ee
--- /dev/null
+++ b/db/migrate/20211119111006_create_job_artifact_states.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class CreateJobArtifactStates < Gitlab::Database::Migration[1.0]
+ VERIFICATION_STATE_INDEX_NAME = "index_job_artifact_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_job_artifact_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_job_artifact_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_job_artifact_states_needs_verification"
+
+ enable_lock_retries!
+
+ def up
+ create_table :ci_job_artifact_states, id: false do |t|
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.references :job_artifact, primary_key: true, null: false, foreign_key: { on_delete: :cascade, to_table: :ci_job_artifacts }
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure, limit: 255
+
+ t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+ end
+
+ def down
+ drop_table :ci_job_artifact_states
+ end
+end
diff --git a/db/migrate/20211122103051_add_line_code_to_draft_notes.rb b/db/migrate/20211122103051_add_line_code_to_draft_notes.rb
new file mode 100644
index 00000000000..c78b75f3a33
--- /dev/null
+++ b/db/migrate/20211122103051_add_line_code_to_draft_notes.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddLineCodeToDraftNotes < Gitlab::Database::Migration[1.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in db/migrate/20211124095704_add_draft_notes_line_code_text_limit.rb
+ def change
+ add_column :draft_notes, :line_code, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20211123135255_create_batched_background_migration_job_transition_logs.rb b/db/migrate/20211123135255_create_batched_background_migration_job_transition_logs.rb
new file mode 100644
index 00000000000..280626c5d3b
--- /dev/null
+++ b/db/migrate/20211123135255_create_batched_background_migration_job_transition_logs.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class CreateBatchedBackgroundMigrationJobTransitionLogs < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ def up
+ execute(<<~SQL)
+ CREATE TABLE batched_background_migration_job_transition_logs (
+ id bigserial NOT NULL,
+ batched_background_migration_job_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ previous_status smallint NOT NULL,
+ next_status smallint NOT NULL,
+ exception_class text,
+ exception_message text,
+ CONSTRAINT check_50e580811a CHECK ((char_length(exception_message) <= 1000)),
+ CONSTRAINT check_76e202c37a CHECK ((char_length(exception_class) <= 100)),
+ PRIMARY KEY (id, created_at)
+ ) PARTITION BY RANGE (created_at);
+
+ CREATE INDEX i_batched_background_migration_job_transition_logs_on_job_id
+ ON batched_background_migration_job_transition_logs USING btree (batched_background_migration_job_id);
+
+ ALTER TABLE batched_background_migration_job_transition_logs ADD CONSTRAINT fk_rails_b7523a175b
+ FOREIGN KEY (batched_background_migration_job_id) REFERENCES batched_background_migration_jobs(id) ON DELETE CASCADE;
+ SQL
+
+ min_date = Date.today
+ max_date = Date.today + 6.months
+
+ create_daterange_partitions('batched_background_migration_job_transition_logs', 'created_at', min_date, max_date)
+ end
+
+ def down
+ drop_table :batched_background_migration_job_transition_logs
+ end
+end
diff --git a/db/migrate/20211124095704_add_draft_notes_line_code_text_limit.rb b/db/migrate/20211124095704_add_draft_notes_line_code_text_limit.rb
new file mode 100644
index 00000000000..b3567d6b873
--- /dev/null
+++ b/db/migrate/20211124095704_add_draft_notes_line_code_text_limit.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddDraftNotesLineCodeTextLimit < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :draft_notes, :line_code, 255
+ end
+
+ def down
+ remove_text_limit :draft_notes, :line_code
+ end
+end
diff --git a/db/migrate/20220105082217_add_verification_token_to_external_ae_destinations.rb b/db/migrate/20220105082217_add_verification_token_to_external_ae_destinations.rb
new file mode 100644
index 00000000000..046a628b8ae
--- /dev/null
+++ b/db/migrate/20220105082217_add_verification_token_to_external_ae_destinations.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddVerificationTokenToExternalAeDestinations < Gitlab::Database::Migration[1.0]
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ add_column :audit_events_external_audit_event_destinations, :verification_token, :text
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ remove_column :audit_events_external_audit_event_destinations, :verification_token
+ end
+end
diff --git a/db/migrate/20220106111958_add_insert_or_update_vulnerability_reads_trigger.rb b/db/migrate/20220106111958_add_insert_or_update_vulnerability_reads_trigger.rb
new file mode 100644
index 00000000000..0049f4e00a2
--- /dev/null
+++ b/db/migrate/20220106111958_add_insert_or_update_vulnerability_reads_trigger.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+class AddInsertOrUpdateVulnerabilityReadsTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ FUNCTION_NAME = 'insert_or_update_vulnerability_reads'
+ TRIGGER_NAME = 'trigger_insert_or_update_vulnerability_reads_from_occurrences'
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{FUNCTION_NAME}()
+ RETURNS TRIGGER
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ severity smallint;
+ state smallint;
+ report_type smallint;
+ resolved_on_default_branch boolean;
+ BEGIN
+ IF (NEW.vulnerability_id IS NULL AND (TG_OP = 'INSERT' OR TG_OP = 'UPDATE')) THEN
+ RETURN NULL;
+ END IF;
+
+ IF (TG_OP = 'UPDATE' AND OLD.vulnerability_id IS NOT NULL AND NEW.vulnerability_id IS NOT NULL) THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT
+ vulnerabilities.severity, vulnerabilities.state, vulnerabilities.report_type, vulnerabilities.resolved_on_default_branch
+ INTO
+ severity, state, report_type, resolved_on_default_branch
+ FROM
+ vulnerabilities
+ WHERE
+ vulnerabilities.id = NEW.vulnerability_id;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id)
+ VALUES (NEW.vulnerability_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id')
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+ END
+ $$;
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_NAME}
+ AFTER INSERT OR UPDATE ON vulnerability_occurrences
+ FOR EACH ROW
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:vulnerability_occurrences, TRIGGER_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220106112043_add_update_vulnerability_reads_trigger.rb b/db/migrate/20220106112043_add_update_vulnerability_reads_trigger.rb
new file mode 100644
index 00000000000..940ec638924
--- /dev/null
+++ b/db/migrate/20220106112043_add_update_vulnerability_reads_trigger.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class AddUpdateVulnerabilityReadsTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ TRIGGER_NAME = 'trigger_update_vulnerability_reads_on_vulnerability_update'
+ FUNCTION_NAME = 'update_vulnerability_reads_from_vulnerability'
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE
+ vulnerability_reads
+ SET
+ severity = NEW.severity,
+ state = NEW.state,
+ resolved_on_default_branch = NEW.resolved_on_default_branch
+ WHERE vulnerability_id = NEW.id;
+ RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_NAME}
+ AFTER UPDATE ON vulnerabilities
+ FOR EACH ROW
+ WHEN (
+ OLD.severity IS DISTINCT FROM NEW.severity OR
+ OLD.state IS DISTINCT FROM NEW.state OR
+ OLD.resolved_on_default_branch IS DISTINCT FROM NEW.resolved_on_default_branch
+ )
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:vulnerabilities, TRIGGER_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220106112085_add_update_vulnerability_reads_location_trigger.rb b/db/migrate/20220106112085_add_update_vulnerability_reads_location_trigger.rb
new file mode 100644
index 00000000000..a863fe8b7b8
--- /dev/null
+++ b/db/migrate/20220106112085_add_update_vulnerability_reads_location_trigger.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class AddUpdateVulnerabilityReadsLocationTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ TRIGGER_NAME = 'trigger_update_location_on_vulnerability_occurrences_update'
+ FUNCTION_NAME = 'update_location_from_vulnerability_occurrences'
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE
+ vulnerability_reads
+ SET
+ location_image = NEW.location->>'image',
+ cluster_agent_id = NEW.location->'kubernetes_resource'->>'agent_id'
+ WHERE
+ vulnerability_id = NEW.vulnerability_id;
+ RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_NAME}
+ AFTER UPDATE ON vulnerability_occurrences
+ FOR EACH ROW
+ WHEN (
+ NEW.report_type IN (2, 7) AND (
+ OLD.location->>'image' IS DISTINCT FROM NEW.location->>'image' OR
+ OLD.location->'kubernetes_resource'->>'agent_id' IS DISTINCT FROM NEW.location->'kubernetes_resource'->>'agent_id'
+ )
+ )
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:vulnerability_occurrences, TRIGGER_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220106163326_add_has_issues_on_vulnerability_reads_trigger.rb b/db/migrate/20220106163326_add_has_issues_on_vulnerability_reads_trigger.rb
new file mode 100644
index 00000000000..b3023a1f915
--- /dev/null
+++ b/db/migrate/20220106163326_add_has_issues_on_vulnerability_reads_trigger.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+class AddHasIssuesOnVulnerabilityReadsTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ TRIGGER_ON_INSERT = 'trigger_update_has_issues_on_vulnerability_issue_links_update'
+ INSERT_FUNCTION_NAME = 'set_has_issues_on_vulnerability_reads'
+
+ TRIGGER_ON_DELETE = 'trigger_update_has_issues_on_vulnerability_issue_links_delete'
+ DELETE_FUNCTION_NAME = 'unset_has_issues_on_vulnerability_reads'
+
+ def up
+ create_trigger_function(INSERT_FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE
+ vulnerability_reads
+ SET
+ has_issues = true
+ WHERE
+ vulnerability_id = NEW.vulnerability_id AND has_issues IS FALSE;
+ RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{DELETE_FUNCTION_NAME}()
+ RETURNS TRIGGER
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ has_issue_links integer;
+ BEGIN
+ PERFORM 1
+ FROM
+ vulnerability_reads
+ WHERE
+ vulnerability_id = OLD.vulnerability_id
+ FOR UPDATE;
+
+ SELECT 1 INTO has_issue_links FROM vulnerability_issue_links WHERE vulnerability_id = OLD.vulnerability_id LIMIT 1;
+
+ IF (has_issue_links = 1) THEN
+ RETURN NULL;
+ END IF;
+
+ UPDATE
+ vulnerability_reads
+ SET
+ has_issues = false
+ WHERE
+ vulnerability_id = OLD.vulnerability_id;
+
+ RETURN NULL;
+ END
+ $$;
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_ON_INSERT}
+ AFTER INSERT ON vulnerability_issue_links
+ FOR EACH ROW
+ EXECUTE FUNCTION #{INSERT_FUNCTION_NAME}();
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_ON_DELETE}
+ AFTER DELETE ON vulnerability_issue_links
+ FOR EACH ROW
+ EXECUTE FUNCTION #{DELETE_FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:vulnerability_issue_links, TRIGGER_ON_INSERT)
+ drop_function(INSERT_FUNCTION_NAME)
+ drop_trigger(:vulnerability_issue_links, TRIGGER_ON_DELETE)
+ drop_function(DELETE_FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220111154950_add_token_expires_at_to_ci_runners.rb b/db/migrate/20220111154950_add_token_expires_at_to_ci_runners.rb
new file mode 100644
index 00000000000..b4d7c63d24b
--- /dev/null
+++ b/db/migrate/20220111154950_add_token_expires_at_to_ci_runners.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddTokenExpiresAtToCiRunners < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :ci_runners, :token_expires_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20220111154951_add_index_to_ci_runners_token_expires_at.rb b/db/migrate/20220111154951_add_index_to_ci_runners_token_expires_at.rb
new file mode 100644
index 00000000000..53623198f51
--- /dev/null
+++ b/db/migrate/20220111154951_add_index_to_ci_runners_token_expires_at.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToCiRunnersTokenExpiresAt < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, [:token_expires_at, :id], order: { token_expires_at: :asc, id: :desc }, name: 'index_ci_runners_on_token_expires_at_and_id_desc'
+ add_concurrent_index :ci_runners, [:token_expires_at, :id], order: { token_expires_at: :desc, id: :desc }, name: 'index_ci_runners_on_token_expires_at_desc_and_id_desc'
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, 'index_ci_runners_on_token_expires_at_desc_and_id_desc'
+ remove_concurrent_index_by_name :ci_runners, 'index_ci_runners_on_token_expires_at_and_id_desc'
+ end
+end
diff --git a/db/migrate/20220117082611_add_text_limit_to_exad_verification_tokens.rb b/db/migrate/20220117082611_add_text_limit_to_exad_verification_tokens.rb
new file mode 100644
index 00000000000..9978e87a1e3
--- /dev/null
+++ b/db/migrate/20220117082611_add_text_limit_to_exad_verification_tokens.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToExadVerificationTokens < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :audit_events_external_audit_event_destinations, :verification_token, 24
+ end
+
+ def down
+ remove_text_limit :audit_events_external_audit_event_destinations, :verification_token
+ end
+end
diff --git a/db/migrate/20220118015633_add_url_text_to_issuable_metric_images.rb b/db/migrate/20220118015633_add_url_text_to_issuable_metric_images.rb
new file mode 100644
index 00000000000..55d820c1256
--- /dev/null
+++ b/db/migrate/20220118015633_add_url_text_to_issuable_metric_images.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddUrlTextToIssuableMetricImages < Gitlab::Database::Migration[1.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20220118020026_add_url_text_limit_to_issuable_metric_images
+ def change
+ add_column :issuable_metric_images, :url_text, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20220118020026_add_url_text_limit_to_issuable_metric_images.rb b/db/migrate/20220118020026_add_url_text_limit_to_issuable_metric_images.rb
new file mode 100644
index 00000000000..2f0f27681cd
--- /dev/null
+++ b/db/migrate/20220118020026_add_url_text_limit_to_issuable_metric_images.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddUrlTextLimitToIssuableMetricImages < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :issuable_metric_images, :url_text, 128
+ end
+
+ def down
+ remove_text_limit :issuable_metric_images, :url_text
+ end
+end
diff --git a/db/migrate/20220119094023_add_unique_index_to_aed_verification_token.rb b/db/migrate/20220119094023_add_unique_index_to_aed_verification_token.rb
new file mode 100644
index 00000000000..bd40fe2203e
--- /dev/null
+++ b/db/migrate/20220119094023_add_unique_index_to_aed_verification_token.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexToAedVerificationToken < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_audit_events_external_audit_on_verification_token'
+
+ def up
+ add_concurrent_index :audit_events_external_audit_event_destinations, :verification_token, unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :audit_events_external_audit_event_destinations, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220119141407_add_dependency_proxy_size_to_namespace_statistics.rb b/db/migrate/20220119141407_add_dependency_proxy_size_to_namespace_statistics.rb
new file mode 100644
index 00000000000..d8107ad8e21
--- /dev/null
+++ b/db/migrate/20220119141407_add_dependency_proxy_size_to_namespace_statistics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddDependencyProxySizeToNamespaceStatistics < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :namespace_statistics, :dependency_proxy_size, :bigint, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20220119144253_add_dependency_proxy_size_to_namespace_root_storage_statistics.rb b/db/migrate/20220119144253_add_dependency_proxy_size_to_namespace_root_storage_statistics.rb
new file mode 100644
index 00000000000..8218f869ce6
--- /dev/null
+++ b/db/migrate/20220119144253_add_dependency_proxy_size_to_namespace_root_storage_statistics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddDependencyProxySizeToNamespaceRootStorageStatistics < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :namespace_root_storage_statistics, :dependency_proxy_size, :bigint, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20220119170426_remove_temporary_vulnerability_occurrences_deduplication_index.rb b/db/migrate/20220119170426_remove_temporary_vulnerability_occurrences_deduplication_index.rb
new file mode 100644
index 00000000000..26859beb671
--- /dev/null
+++ b/db/migrate/20220119170426_remove_temporary_vulnerability_occurrences_deduplication_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveTemporaryVulnerabilityOccurrencesDeduplicationIndex < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'RecalculateVulnerabilitiesOccurrencesUuid'
+ INDEX_NAME = 'tmp_idx_deduplicate_vulnerability_occurrences'
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_background_migration(MIGRATION)
+
+ remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :vulnerability_occurrences,
+ %i[project_id report_type location_fingerprint primary_identifier_id id],
+ name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220119220620_add_scan_method_to_dast_site_profile.rb b/db/migrate/20220119220620_add_scan_method_to_dast_site_profile.rb
new file mode 100644
index 00000000000..f7b7580d673
--- /dev/null
+++ b/db/migrate/20220119220620_add_scan_method_to_dast_site_profile.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddScanMethodToDastSiteProfile < Gitlab::Database::Migration[1.0]
+ def up
+ add_column :dast_site_profiles, :scan_method, :integer, limit: 2, default: 0, null: false
+ end
+
+ def down
+ remove_column :dast_site_profiles, :scan_method
+ end
+end
diff --git a/db/migrate/20220120033115_create_alert_management_alert_metric_images.rb b/db/migrate/20220120033115_create_alert_management_alert_metric_images.rb
new file mode 100644
index 00000000000..e98392190f4
--- /dev/null
+++ b/db/migrate/20220120033115_create_alert_management_alert_metric_images.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateAlertManagementAlertMetricImages < Gitlab::Database::Migration[1.0]
+ def up
+ create_table :alert_management_alert_metric_images do |t|
+ t.references :alert, null: false, index: true, foreign_key: { to_table: :alert_management_alerts, on_delete: :cascade }
+ t.timestamps_with_timezone
+ t.integer :file_store, limit: 2
+ t.text :file, limit: 255, null: false
+ t.text :url, limit: 255
+ t.text :url_text, limit: 128
+ end
+ end
+
+ def down
+ drop_table :alert_management_alert_metric_images, if_exists: true
+ end
+end
diff --git a/db/migrate/20220120085655_add_ci_runner_project_index_to_runner_id_and_project_id.rb b/db/migrate/20220120085655_add_ci_runner_project_index_to_runner_id_and_project_id.rb
new file mode 100644
index 00000000000..bcf32d2abd0
--- /dev/null
+++ b/db/migrate/20220120085655_add_ci_runner_project_index_to_runner_id_and_project_id.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCiRunnerProjectIndexToRunnerIdAndProjectId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ OLD_INDEX_NAME = 'index_ci_runner_projects_on_runner_id'
+ NEW_INDEX_NAME = 'index_ci_runner_projects_on_runner_id_and_project_id'
+ TABLE_NAME = :ci_runner_projects
+
+ def up
+ add_concurrent_index(TABLE_NAME, [:runner_id, :project_id], name: NEW_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, :runner_id, name: OLD_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, NEW_INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20220125084127_add_cleanup_attempts_to_loose_foreign_keys_deleted_records.rb b/db/migrate/20220125084127_add_cleanup_attempts_to_loose_foreign_keys_deleted_records.rb
new file mode 100644
index 00000000000..e0c80ad79e5
--- /dev/null
+++ b/db/migrate/20220125084127_add_cleanup_attempts_to_loose_foreign_keys_deleted_records.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddCleanupAttemptsToLooseForeignKeysDeletedRecords < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ add_column :loose_foreign_keys_deleted_records, :cleanup_attempts, :smallint, default: 0
+ end
+
+ def down
+ remove_column :loose_foreign_keys_deleted_records, :cleanup_attempts
+ end
+end
diff --git a/db/migrate/20220125122228_add_topics_non_private_projects_count.rb b/db/migrate/20220125122228_add_topics_non_private_projects_count.rb
new file mode 100644
index 00000000000..8c7b750d5ff
--- /dev/null
+++ b/db/migrate/20220125122228_add_topics_non_private_projects_count.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddTopicsNonPrivateProjectsCount < Gitlab::Database::Migration[1.0]
+ def up
+ add_column :topics, :non_private_projects_count, :bigint, null: false, default: 0
+ end
+
+ def down
+ remove_column :topics, :non_private_projects_count
+ end
+end
diff --git a/db/migrate/20220125122725_add_topics_non_private_projects_count_index.rb b/db/migrate/20220125122725_add_topics_non_private_projects_count_index.rb
new file mode 100644
index 00000000000..46b4d298a2e
--- /dev/null
+++ b/db/migrate/20220125122725_add_topics_non_private_projects_count_index.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddTopicsNonPrivateProjectsCountIndex < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_topics_non_private_projects_count'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :topics, [:non_private_projects_count, :id], order: { non_private_projects_count: :desc }, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :topics, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220125230538_add_compound_index_on_project_id_and_id_for_vulnerabilities.rb b/db/migrate/20220125230538_add_compound_index_on_project_id_and_id_for_vulnerabilities.rb
new file mode 100644
index 00000000000..c745fa51328
--- /dev/null
+++ b/db/migrate/20220125230538_add_compound_index_on_project_id_and_id_for_vulnerabilities.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddCompoundIndexOnProjectIdAndIdForVulnerabilities < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb b/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb
new file mode 100644
index 00000000000..1acd9599da4
--- /dev/null
+++ b/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddEcdsaSkAndEd25519SkKeyRestrictionsToApplicationSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :application_settings, :ecdsa_sk_key_restriction, :integer, default: 0, null: false
+ add_column :application_settings, :ed25519_sk_key_restriction, :integer, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20220128194722_add_index_on_migration_state_and_import_done_at_to_container_repositories.rb b/db/migrate/20220128194722_add_index_on_migration_state_and_import_done_at_to_container_repositories.rb
new file mode 100644
index 00000000000..6c9fb20bbbd
--- /dev/null
+++ b/db/migrate/20220128194722_add_index_on_migration_state_and_import_done_at_to_container_repositories.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddIndexOnMigrationStateAndImportDoneAtToContainerRepositories < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_container_repositories_on_migration_state_import_done_at'
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :container_repositories, [:migration_state, :migration_import_done_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :container_repositories, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220131135725_add_severity_level_to_merge_requests_compliance_violations.rb b/db/migrate/20220131135725_add_severity_level_to_merge_requests_compliance_violations.rb
new file mode 100644
index 00000000000..50aa0121055
--- /dev/null
+++ b/db/migrate/20220131135725_add_severity_level_to_merge_requests_compliance_violations.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddSeverityLevelToMergeRequestsComplianceViolations < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :merge_requests_compliance_violations, :severity_level, :integer, limit: 2, null: false, default: 0
+ end
+end
diff --git a/db/migrate/20220131192643_add_show_diff_preview_in_email_to_project_settings.rb b/db/migrate/20220131192643_add_show_diff_preview_in_email_to_project_settings.rb
new file mode 100644
index 00000000000..1811bf04ee4
--- /dev/null
+++ b/db/migrate/20220131192643_add_show_diff_preview_in_email_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddShowDiffPreviewInEmailToProjectSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :show_diff_preview_in_email, :boolean, default: true, null: false
+ end
+end
diff --git a/db/migrate/20220201205300_remove_index_for_vulnerability_occurrences.rb b/db/migrate/20220201205300_remove_index_for_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..89591d14aae
--- /dev/null
+++ b/db/migrate/20220201205300_remove_index_for_vulnerability_occurrences.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexForVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_vulnerability_occurrences_on_unique_keys'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+
+ def down
+ # no-op
+
+ # The index is UNIQUE so we cannot add it back again
+ end
+end
diff --git a/db/migrate/20220202034409_add_tmp_index_on_id_and_migration_state_to_container_repositories.rb b/db/migrate/20220202034409_add_tmp_index_on_id_and_migration_state_to_container_repositories.rb
new file mode 100644
index 00000000000..b999c871a3e
--- /dev/null
+++ b/db/migrate/20220202034409_add_tmp_index_on_id_and_migration_state_to_container_repositories.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddTmpIndexOnIdAndMigrationStateToContainerRepositories < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'tmp_index_container_repositories_on_id_migration_state'
+
+ disable_ddl_transaction!
+
+ # Temporary index to be removed https://gitlab.com/gitlab-org/gitlab/-/issues/351783
+ def up
+ add_concurrent_index :container_repositories, [:id, :migration_state], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :container_repositories, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220202115350_add_migration_indexes_to_container_repositories.rb b/db/migrate/20220202115350_add_migration_indexes_to_container_repositories.rb
new file mode 100644
index 00000000000..673d066e3c0
--- /dev/null
+++ b/db/migrate/20220202115350_add_migration_indexes_to_container_repositories.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddMigrationIndexesToContainerRepositories < Gitlab::Database::Migration[1.0]
+ PRE_IMPORTING_INDEX = 'idx_container_repos_on_pre_import_started_at_when_pre_importing'
+ PRE_IMPORT_DONE_INDEX = 'idx_container_repos_on_pre_import_done_at_when_pre_import_done'
+ IMPORTING_INDEX = 'idx_container_repos_on_import_started_at_when_importing'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :container_repositories, :migration_pre_import_started_at, name: PRE_IMPORTING_INDEX, where: "migration_state = 'pre_importing'"
+ add_concurrent_index :container_repositories, :migration_pre_import_done_at, name: PRE_IMPORT_DONE_INDEX, where: "migration_state = 'pre_import_done'"
+ add_concurrent_index :container_repositories, :migration_import_started_at, name: IMPORTING_INDEX, where: "migration_state = 'importing'"
+ end
+
+ def down
+ remove_concurrent_index_by_name :container_repositories, IMPORTING_INDEX
+ remove_concurrent_index_by_name :container_repositories, PRE_IMPORT_DONE_INDEX
+ remove_concurrent_index_by_name :container_repositories, PRE_IMPORTING_INDEX
+ end
+end
diff --git a/db/migrate/20220203123333_add_batched_migration_max_batch.rb b/db/migrate/20220203123333_add_batched_migration_max_batch.rb
new file mode 100644
index 00000000000..d16c6dd4110
--- /dev/null
+++ b/db/migrate/20220203123333_add_batched_migration_max_batch.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddBatchedMigrationMaxBatch < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :batched_background_migrations, :max_batch_size, :integer
+ end
+end
diff --git a/db/migrate/20220203133652_add_legacy_open_source_license_available_to_project_settings.rb b/db/migrate/20220203133652_add_legacy_open_source_license_available_to_project_settings.rb
new file mode 100644
index 00000000000..47f92fae496
--- /dev/null
+++ b/db/migrate/20220203133652_add_legacy_open_source_license_available_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddLegacyOpenSourceLicenseAvailableToProjectSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :legacy_open_source_license_available, :boolean, default: true, null: false
+ end
+end
diff --git a/db/migrate/20220204154220_add_index_on_greatest_done_at_to_container_repositories.rb b/db/migrate/20220204154220_add_index_on_greatest_done_at_to_container_repositories.rb
new file mode 100644
index 00000000000..455a8478cc4
--- /dev/null
+++ b/db/migrate/20220204154220_add_index_on_greatest_done_at_to_container_repositories.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexOnGreatestDoneAtToContainerRepositories < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_container_repositories_on_greatest_done_at'
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :container_repositories,
+ 'GREATEST(migration_pre_import_done_at, migration_import_done_at, migration_aborted_at)',
+ where: "migration_state IN ('import_done', 'pre_import_done', 'import_aborted')",
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :container_repositories, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220207083129_add_users_get_by_id_limit_to_application_setting.rb b/db/migrate/20220207083129_add_users_get_by_id_limit_to_application_setting.rb
new file mode 100644
index 00000000000..cdf2aced213
--- /dev/null
+++ b/db/migrate/20220207083129_add_users_get_by_id_limit_to_application_setting.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUsersGetByIdLimitToApplicationSetting < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ add_column :application_settings, :users_get_by_id_limit, :integer, null: false, default: 300
+ add_column :application_settings, :users_get_by_id_limit_allowlist, :text, array: true, limit: 255, null: false, default: []
+ end
+
+ def down
+ remove_column :application_settings, :users_get_by_id_limit
+ remove_column :application_settings, :users_get_by_id_limit_allowlist
+ end
+end
diff --git a/db/migrate/20220208170445_add_not_valid_foreign_key_to_ci_builds_runner_id.rb b/db/migrate/20220208170445_add_not_valid_foreign_key_to_ci_builds_runner_id.rb
new file mode 100644
index 00000000000..9b2ba17e068
--- /dev/null
+++ b/db/migrate/20220208170445_add_not_valid_foreign_key_to_ci_builds_runner_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddNotValidForeignKeyToCiBuildsRunnerId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ci_builds, :ci_runners, column: :runner_id, on_delete: :nullify, validate: false
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :ci_builds, column: :runner_id
+ end
+ end
+end
diff --git a/db/migrate/20220208171826_update_default_scan_method_of_dast_site_profile.rb b/db/migrate/20220208171826_update_default_scan_method_of_dast_site_profile.rb
new file mode 100644
index 00000000000..b01dbe642e2
--- /dev/null
+++ b/db/migrate/20220208171826_update_default_scan_method_of_dast_site_profile.rb
@@ -0,0 +1,24 @@
+# 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 UpdateDefaultScanMethodOfDastSiteProfile < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 500
+
+ disable_ddl_transaction!
+
+ def up
+ each_batch_range('dast_site_profiles', scope: ->(table) { table.where(target_type: 1) }, of: BATCH_SIZE) do |min, max|
+ execute <<~SQL
+ UPDATE dast_site_profiles
+ SET scan_method = 1
+ WHERE id BETWEEN #{min} AND #{max}
+ SQL
+ end
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/migrate/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe.rb b/db/migrate/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe.rb
new file mode 100644
index 00000000000..7a60ea48f40
--- /dev/null
+++ b/db/migrate/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class UpdateIntegrationsTriggerTypeNewOnInsertNullSafe < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ FUNCTION_NAME = 'integrations_set_type_new'
+
+ def up
+ # Update `type_new` dynamically based on `type`, if `type_new` is null
+ # and `type` dynamically based on `type_new`, if `type` is null.
+ #
+ # The old class names are in the format `AbcService`, and the new ones `Integrations::Abc`.
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL.squish
+ UPDATE integrations
+ SET type_new = COALESCE(NEW.type_new, regexp_replace(NEW.type, '\\A(.+)Service\\Z', 'Integrations::\\1'))
+ , type = COALESCE(NEW.type, regexp_replace(NEW.type_new, '\\AIntegrations::(.+)\\Z', '\\1Service'))
+ WHERE integrations.id = NEW.id;
+ RETURN NULL;
+ SQL
+ end
+ end
+
+ def down
+ # Update `type_new` dynamically based on `type`.
+ #
+ # The old class names are in the format `AbcService`, and the new ones `Integrations::Abc`.
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE integrations SET type_new = regexp_replace(NEW.type, '\\A(.+)Service\\Z', 'Integrations::\\1')
+ WHERE integrations.id = NEW.id;
+ RETURN NULL;
+ SQL
+ end
+ end
+end
diff --git a/db/post_migrate/20210415155043_move_container_registry_enabled_to_project_features3.rb b/db/post_migrate/20210415155043_move_container_registry_enabled_to_project_features3.rb
index 6fd8d280c97..f63d7c5138b 100644
--- a/db/post_migrate/20210415155043_move_container_registry_enabled_to_project_features3.rb
+++ b/db/post_migrate/20210415155043_move_container_registry_enabled_to_project_features3.rb
@@ -2,7 +2,6 @@
class MoveContainerRegistryEnabledToProjectFeatures3 < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- include Gitlab::Database::DynamicModelHelpers
BATCH_SIZE = 21_000
MIGRATION = 'MoveContainerRegistryEnabledToProjectFeature'
diff --git a/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb b/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb
index c380f15188a..59b41dd2008 100644
--- a/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb
+++ b/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb
@@ -10,7 +10,7 @@ class CleanUpPendingBuildsTable < ActiveRecord::Migration[6.0]
def up
return unless Gitlab.dev_or_test_env? || Gitlab.com?
- each_batch_range('ci_pending_builds', of: BATCH_SIZE) do |min, max|
+ each_batch_range('ci_pending_builds', connection: connection, of: BATCH_SIZE) do |min, max|
execute <<~SQL
DELETE FROM ci_pending_builds
USING ci_builds
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
index f47ff244d7a..47a6e39e87a 100644
--- a/db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb
+++ b/db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb
@@ -8,7 +8,7 @@ class MigrateProtectedAttributeToPendingBuilds < ActiveRecord::Migration[6.1]
def up
return unless Gitlab.dev_or_test_env? || Gitlab.com?
- each_batch_range('ci_pending_builds', of: 1000) do |min, max|
+ each_batch_range('ci_pending_builds', connection: connection, of: 1000) do |min, max|
execute <<~SQL
UPDATE ci_pending_builds
SET protected = true
diff --git a/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb b/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb
index bccbc4e3209..105d5ec98f4 100644
--- a/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb
+++ b/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb
@@ -8,15 +8,7 @@ class ScheduleRecalculateVulnerabilityFindingSignaturesForFindings < Gitlab::Dat
disable_ddl_transaction!
def up
- return unless Gitlab.ee?
-
- queue_background_migration_jobs_by_range_at_intervals(
- define_batchable_model('vulnerability_finding_signatures'),
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- track_jobs: true
- )
+ # no-op based on https://docs.gitlab.com/ee/development/background_migrations.html#rescheduling-background-migrations
end
def down
diff --git a/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb b/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb
index fc50aa812a7..1625d24ef92 100644
--- a/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb
+++ b/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb
@@ -1,21 +1,14 @@
# frozen_string_literal: true
class RemoveVulnerabilityFindingLinks < Gitlab::Database::Migration[1.0]
- BATCH_SIZE = 50_000
- MIGRATION = 'RemoveVulnerabilityFindingLinks'
-
- disable_ddl_transaction!
+ # This migration has been moved to a TRUNCATE in db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb
+ # Previously, this was causing an bug where there was a conflict between the table cleanup and the index creation.
def up
- queue_background_migration_jobs_by_range_at_intervals(
- define_batchable_model('vulnerability_finding_links'),
- MIGRATION,
- 2.minutes,
- batch_size: BATCH_SIZE
- )
+ # no op
end
def down
- # no ops
+ # no op
end
end
diff --git a/db/post_migrate/20211209103048_backfill_project_namespaces_for_group.rb b/db/post_migrate/20211209103048_backfill_project_namespaces_for_group.rb
new file mode 100644
index 00000000000..0b65db7aab4
--- /dev/null
+++ b/db/post_migrate/20211209103048_backfill_project_namespaces_for_group.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class BackfillProjectNamespacesForGroup < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'ProjectNamespaces::BackfillProjectNamespaces'
+ DELAY_INTERVAL = 2.minutes
+ GROUP_ID = 9970 # picking gitlab-org group.
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.com? || Gitlab.staging?
+
+ projects_table = ::Gitlab::BackgroundMigration::ProjectNamespaces::Models::Project.arel_table
+ hierarchy_cte_sql = Arel.sql(::Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces.hierarchy_cte(GROUP_ID))
+ group_projects = ::Gitlab::BackgroundMigration::ProjectNamespaces::Models::Project.where(projects_table[:namespace_id].in(hierarchy_cte_sql))
+
+ min_id = group_projects.minimum(:id)
+ max_id = group_projects.maximum(:id)
+
+ return if min_id.blank? || max_id.blank?
+
+ queue_batched_background_migration(
+ MIGRATION,
+ :projects,
+ :id,
+ GROUP_ID,
+ 'up',
+ job_interval: DELAY_INTERVAL,
+ batch_min_value: min_id,
+ batch_max_value: max_id,
+ sub_batch_size: 25,
+ batch_class_name: 'BackfillProjectNamespacePerGroupBatchingStrategy'
+ )
+ end
+
+ def down
+ return unless Gitlab.com? || Gitlab.staging?
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .for_configuration(MIGRATION, :projects, :id, [GROUP_ID, 'up']).delete_all
+ end
+end
diff --git a/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb b/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb
index 98ac4433193..ffe8bf0d794 100644
--- a/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb
+++ b/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb
@@ -1,21 +1,14 @@
# frozen_string_literal: true
class RemoveVulnerabilityFindingLinksAgain < Gitlab::Database::Migration[1.0]
- BATCH_SIZE = 50_000
- MIGRATION = 'RemoveVulnerabilityFindingLinks'
-
- disable_ddl_transaction!
+ # This migration has been moved to a TRUNCATE in db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb
+ # Previously, this was causing an bug where there was a conflict between the table cleanup and the index creation.
def up
- queue_background_migration_jobs_by_range_at_intervals(
- define_batchable_model('vulnerability_finding_links'),
- MIGRATION,
- 2.minutes,
- batch_size: BATCH_SIZE
- )
+ # no op
end
def down
- # no ops
+ # no op
end
end
diff --git a/db/post_migrate/20220106185033_remove_finding_evidence_summary.rb b/db/post_migrate/20220106185033_remove_finding_evidence_summary.rb
new file mode 100644
index 00000000000..d28e8bb81f6
--- /dev/null
+++ b/db/post_migrate/20220106185033_remove_finding_evidence_summary.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveFindingEvidenceSummary < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ remove_column :vulnerability_finding_evidences, :summary, :text
+ end
+
+ def down
+ add_column :vulnerability_finding_evidences, :summary, :text
+
+ add_text_limit :vulnerability_finding_evidences, :summary, 8_000_000
+ end
+end
diff --git a/db/post_migrate/20220107064845_populate_vulnerability_reads.rb b/db/post_migrate/20220107064845_populate_vulnerability_reads.rb
new file mode 100644
index 00000000000..58826c5f929
--- /dev/null
+++ b/db/post_migrate/20220107064845_populate_vulnerability_reads.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class PopulateVulnerabilityReads < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 10_000
+ DELAY_INTERVAL = 2.minutes
+ MIGRATION_NAME = 'PopulateVulnerabilityReads'
+ SUB_BATCH_SIZE = 1_000
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerabilities'),
+ MIGRATION_NAME,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true,
+ other_job_arguments: [SUB_BATCH_SIZE]
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220111093534_remove_index_on_auto_stop_in.rb b/db/post_migrate/20220111093534_remove_index_on_auto_stop_in.rb
new file mode 100644
index 00000000000..bcb78b28376
--- /dev/null
+++ b/db/post_migrate/20220111093534_remove_index_on_auto_stop_in.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexOnAutoStopIn < Gitlab::Database::Migration[1.0]
+ TABLE = :environments
+ INDEX_NAME = 'index_environments_on_auto_stop_at'
+ COLUMN = :auto_stop_at
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index TABLE, COLUMN, where: 'auto_stop_at IS NOT NULL', name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index TABLE, COLUMN, where: 'auto_stop_at IS NOT NULL', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220111101421_remove_index_on_merge_request_id.rb b/db/post_migrate/20220111101421_remove_index_on_merge_request_id.rb
new file mode 100644
index 00000000000..38cc259312d
--- /dev/null
+++ b/db/post_migrate/20220111101421_remove_index_on_merge_request_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexOnMergeRequestId < Gitlab::Database::Migration[1.0]
+ TABLE = :merge_request_context_commits
+ INDEX_NAME = 'index_merge_request_context_commits_on_merge_request_id'
+ COLUMN = :merge_request_id
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index TABLE, COLUMN, name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index TABLE, COLUMN, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220113111440_schedule_fix_incorrect_max_seats_used.rb b/db/post_migrate/20220113111440_schedule_fix_incorrect_max_seats_used.rb
new file mode 100644
index 00000000000..f39b026bd77
--- /dev/null
+++ b/db/post_migrate/20220113111440_schedule_fix_incorrect_max_seats_used.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ScheduleFixIncorrectMaxSeatsUsed < Gitlab::Database::Migration[1.0]
+ DOWNTIME = false
+ TMP_IDX_NAME = 'tmp_gitlab_subscriptions_max_seats_used_migration'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :gitlab_subscriptions, :id, where: "start_date >= '2021-08-02' AND start_date <= '2021-11-20' AND max_seats_used != 0 AND max_seats_used > seats_in_use AND max_seats_used > seats", name: TMP_IDX_NAME
+
+ return unless Gitlab.com?
+
+ migrate_in(1.hour, 'FixIncorrectMaxSeatsUsed')
+ end
+
+ def down
+ remove_concurrent_index_by_name :gitlab_subscriptions, TMP_IDX_NAME
+ end
+end
diff --git a/db/post_migrate/20220117034056_remove_index_cluster_agent_tokens_on_agent_id_and_last_used_at.rb b/db/post_migrate/20220117034056_remove_index_cluster_agent_tokens_on_agent_id_and_last_used_at.rb
new file mode 100644
index 00000000000..5e306be016a
--- /dev/null
+++ b/db/post_migrate/20220117034056_remove_index_cluster_agent_tokens_on_agent_id_and_last_used_at.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveIndexClusterAgentTokensOnAgentIdAndLastUsedAt < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX = 'index_cluster_agent_tokens_on_agent_id_and_last_used_at'
+
+ def up
+ remove_concurrent_index_by_name :cluster_agent_tokens, name: INDEX
+ end
+
+ def down
+ add_concurrent_index :cluster_agent_tokens, 'agent_id, last_used_at DESC NULLS LAST', name: INDEX
+ end
+end
diff --git a/db/post_migrate/20220118204039_self_managed_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb b/db/post_migrate/20220118204039_self_managed_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb
new file mode 100644
index 00000000000..18f68150e45
--- /dev/null
+++ b/db/post_migrate/20220118204039_self_managed_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class SelfManagedRescheduleRecalculateVulnerabilityFindingSignaturesForFindings < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'RecalculateVulnerabilityFindingSignaturesForFindings'
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ def up
+ # Only run migration for self-managed
+ return if ::Gitlab.com?
+
+ # Vulnerability Finding Signatures is an EE only feature
+ return unless Gitlab.ee?
+
+ delete_queued_jobs(MIGRATION)
+
+ requeue_background_migration_jobs_by_range_at_intervals(
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb b/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb
new file mode 100644
index 00000000000..482f873739a
--- /dev/null
+++ b/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class PopulateAuditEventStreamingVerificationToken < Gitlab::Database::Migration[1.0]
+ class ExternalAuditEventDestination < ActiveRecord::Base
+ self.table_name = 'audit_events_external_audit_event_destinations'
+
+ def regenerate_verification_token
+ update!(verification_token: SecureRandom.base58(24))
+ end
+ end
+
+ def up
+ ExternalAuditEventDestination.all.each { |destination| destination.regenerate_verification_token }
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220119143130_remove_projects_ci_sources_pipelines_source_project_id_fk.rb b/db/post_migrate/20220119143130_remove_projects_ci_sources_pipelines_source_project_id_fk.rb
new file mode 100644
index 00000000000..7fe9f1c856b
--- /dev/null
+++ b/db/post_migrate/20220119143130_remove_projects_ci_sources_pipelines_source_project_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiSourcesPipelinesSourceProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK projects, ci_sources_pipelines IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:ci_sources_pipelines, :projects, name: "fk_acd9737679")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_sources_pipelines, :projects, name: "fk_acd9737679", column: :source_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220119144458_remove_users_ci_triggers_owner_id_fk.rb b/db/post_migrate/20220119144458_remove_users_ci_triggers_owner_id_fk.rb
new file mode 100644
index 00000000000..9acf53a6ea2
--- /dev/null
+++ b/db/post_migrate/20220119144458_remove_users_ci_triggers_owner_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveUsersCiTriggersOwnerIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK users, ci_triggers IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:ci_triggers, :users, name: "fk_e8e10d1964")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_triggers, :users, name: "fk_e8e10d1964", column: :owner_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220119151221_remove_merge_requests_ci_pipelines_merge_request_id_fk.rb b/db/post_migrate/20220119151221_remove_merge_requests_ci_pipelines_merge_request_id_fk.rb
new file mode 100644
index 00000000000..c7ced0ae3b7
--- /dev/null
+++ b/db/post_migrate/20220119151221_remove_merge_requests_ci_pipelines_merge_request_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveMergeRequestsCiPipelinesMergeRequestIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_pipelines, :merge_requests, name: "fk_a23be95014")
+
+ with_lock_retries do
+ execute('LOCK merge_requests, ci_pipelines IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_pipelines, :merge_requests, name: "fk_a23be95014")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_pipelines, :merge_requests, name: "fk_a23be95014", column: :merge_request_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220119153706_remove_ci_pipelines_merge_trains_pipeline_id_fk.rb b/db/post_migrate/20220119153706_remove_ci_pipelines_merge_trains_pipeline_id_fk.rb
new file mode 100644
index 00000000000..92d68ff4fbb
--- /dev/null
+++ b/db/post_migrate/20220119153706_remove_ci_pipelines_merge_trains_pipeline_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesMergeTrainsPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK ci_pipelines, merge_trains IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:merge_trains, :ci_pipelines, name: "fk_rails_f90820cb08")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:merge_trains, :ci_pipelines, name: "fk_rails_f90820cb08", column: :pipeline_id, target_column: :id, on_delete: :nullify)
+ end
+end
diff --git a/db/post_migrate/20220119154442_remove_ci_pipelines_merge_requests_head_pipeline_id_fk.rb b/db/post_migrate/20220119154442_remove_ci_pipelines_merge_requests_head_pipeline_id_fk.rb
new file mode 100644
index 00000000000..6a978ce2ab1
--- /dev/null
+++ b/db/post_migrate/20220119154442_remove_ci_pipelines_merge_requests_head_pipeline_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesMergeRequestsHeadPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK ci_pipelines, merge_requests IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:merge_requests, :ci_pipelines, name: "fk_fd82eae0b9")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:merge_requests, :ci_pipelines, name: "fk_fd82eae0b9", column: :head_pipeline_id, target_column: :id, on_delete: :nullify)
+ end
+end
diff --git a/db/post_migrate/20220119193130_remove_ci_pipelines_dast_profiles_pipelines_ci_pipeline_id_fk.rb b/db/post_migrate/20220119193130_remove_ci_pipelines_dast_profiles_pipelines_ci_pipeline_id_fk.rb
new file mode 100644
index 00000000000..f4eedd0fa70
--- /dev/null
+++ b/db/post_migrate/20220119193130_remove_ci_pipelines_dast_profiles_pipelines_ci_pipeline_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesDastProfilesPipelinesCiPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK ci_pipelines, dast_profiles_pipelines IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:dast_profiles_pipelines, :ci_pipelines, name: "fk_a60cad829d")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:dast_profiles_pipelines, :ci_pipelines, name: "fk_a60cad829d", column: :ci_pipeline_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220119201340_remove_ci_pipelines_vulnerability_statistics_latest_pipeline_id_fk.rb b/db/post_migrate/20220119201340_remove_ci_pipelines_vulnerability_statistics_latest_pipeline_id_fk.rb
new file mode 100644
index 00000000000..bd80767cf6a
--- /dev/null
+++ b/db/post_migrate/20220119201340_remove_ci_pipelines_vulnerability_statistics_latest_pipeline_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesVulnerabilityStatisticsLatestPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK ci_pipelines, vulnerability_statistics IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:vulnerability_statistics, :ci_pipelines, name: "fk_e8b13c928f")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:vulnerability_statistics, :ci_pipelines, name: "fk_e8b13c928f", column: :latest_pipeline_id, target_column: :id, on_delete: :nullify)
+ end
+end
diff --git a/db/post_migrate/20220119203119_remove_ci_pipelines_vulnerability_occurrence_pipelines_pipeline_id_fk.rb b/db/post_migrate/20220119203119_remove_ci_pipelines_vulnerability_occurrence_pipelines_pipeline_id_fk.rb
new file mode 100644
index 00000000000..b6397486dd0
--- /dev/null
+++ b/db/post_migrate/20220119203119_remove_ci_pipelines_vulnerability_occurrence_pipelines_pipeline_id_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesVulnerabilityOccurrencePipelinesPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK ci_pipelines, vulnerability_occurrence_pipelines IN ACCESS EXCLUSIVE MODE')
+
+ remove_foreign_key_if_exists(:vulnerability_occurrence_pipelines, :ci_pipelines, name: "fk_rails_6421e35d7d")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:vulnerability_occurrence_pipelines, :ci_pipelines, name: "fk_rails_6421e35d7d", column: :pipeline_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220120094340_drop_position_from_security_findings.rb b/db/post_migrate/20220120094340_drop_position_from_security_findings.rb
new file mode 100644
index 00000000000..56af346ad1b
--- /dev/null
+++ b/db/post_migrate/20220120094340_drop_position_from_security_findings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class DropPositionFromSecurityFindings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :security_findings, :position, :integer
+ end
+end
diff --git a/db/post_migrate/20220120123700_add_tmp_index_routes_id_for_namespaces.rb b/db/post_migrate/20220120123700_add_tmp_index_routes_id_for_namespaces.rb
new file mode 100644
index 00000000000..2b8cecd0e57
--- /dev/null
+++ b/db/post_migrate/20220120123700_add_tmp_index_routes_id_for_namespaces.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTmpIndexRoutesIdForNamespaces < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'tmp_index_for_namespace_id_migration_on_routes'
+
+ disable_ddl_transaction!
+
+ def up
+ # Temporary index to be removed in 14.9
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/352353
+ add_concurrent_index :routes, :id, where: "routes.namespace_id is null and routes.source_type = 'Namespace'", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :routes, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220120123800_backfill_namespace_id_for_namespace_routes.rb b/db/post_migrate/20220120123800_backfill_namespace_id_for_namespace_routes.rb
new file mode 100644
index 00000000000..4aac0903502
--- /dev/null
+++ b/db/post_migrate/20220120123800_backfill_namespace_id_for_namespace_routes.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class BackfillNamespaceIdForNamespaceRoutes < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillNamespaceIdForNamespaceRoute'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 1_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 200
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :routes,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .for_configuration(MIGRATION, :routes, :id, [])
+ .delete_all
+ end
+end
diff --git a/db/post_migrate/20220121214752_remove_projects_ci_stages_project_id_fk.rb b/db/post_migrate/20220121214752_remove_projects_ci_stages_project_id_fk.rb
new file mode 100644
index 00000000000..93f0b30571a
--- /dev/null
+++ b/db/post_migrate/20220121214752_remove_projects_ci_stages_project_id_fk.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiStagesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return if Gitlab.com? # unsafe migration, skip on GitLab.com due to https://gitlab.com/groups/gitlab-org/-/epics/7249#note_819625526
+ return unless foreign_key_exists?(:ci_stages, :projects, name: "fk_2360681d1d")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_stages IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_stages, :projects, name: "fk_2360681d1d")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_stages, :projects, name: "fk_2360681d1d", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220121214753_re_remove_projects_ci_stages_project_id_fk.rb b/db/post_migrate/20220121214753_re_remove_projects_ci_stages_project_id_fk.rb
new file mode 100644
index 00000000000..45dec15a5a7
--- /dev/null
+++ b/db/post_migrate/20220121214753_re_remove_projects_ci_stages_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ReRemoveProjectsCiStagesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_stages, :projects, name: "fk_2360681d1d")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_stages IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_stages, :projects, name: "fk_2360681d1d")
+ end
+ end
+
+ def down
+ # no-op, since the FK will be added via rollback by prior-migration
+ end
+end
diff --git a/db/post_migrate/20220121221651_remove_projects_ci_variables_project_id_fk.rb b/db/post_migrate/20220121221651_remove_projects_ci_variables_project_id_fk.rb
new file mode 100644
index 00000000000..f647d4376ac
--- /dev/null
+++ b/db/post_migrate/20220121221651_remove_projects_ci_variables_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiVariablesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_variables, :projects, name: "fk_ada5eb64b3")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_variables IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_variables, :projects, name: "fk_ada5eb64b3")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_variables, :projects, name: "fk_ada5eb64b3", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124130028_dedup_runner_projects.rb b/db/post_migrate/20220124130028_dedup_runner_projects.rb
new file mode 100644
index 00000000000..1a4c895f1c4
--- /dev/null
+++ b/db/post_migrate/20220124130028_dedup_runner_projects.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+class DedupRunnerProjects < Gitlab::Database::Migration[1.0]
+ TABLE_NAME = :ci_runner_projects
+ TMP_INDEX_NAME = 'tmp_unique_ci_runner_projects_by_runner_id_and_project_id'
+ OLD_INDEX_NAME = 'index_ci_runner_projects_on_runner_id_and_project_id'
+ INDEX_NAME = 'index_unique_ci_runner_projects_on_runner_id_and_project_id'
+ BATCH_SIZE = 5000
+
+ disable_ddl_transaction!
+
+ module Ci
+ class RunnerProject < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'ci_runner_projects'
+ end
+ end
+
+ def up
+ last_runner_project_record_id = Ci::RunnerProject.maximum(:id) || 0
+
+ # This index will disallow further duplicates while we're deduplicating the data.
+ add_concurrent_index(TABLE_NAME, [:runner_id, :project_id], where: "id > #{Integer(last_runner_project_record_id)}", unique: true, name: TMP_INDEX_NAME)
+
+ Ci::RunnerProject.each_batch(of: BATCH_SIZE) do |relation|
+ duplicated_runner_projects = Ci::RunnerProject
+ .select('COUNT(*)', :runner_id, :project_id)
+ .where('(runner_id, project_id) IN (?)', relation.select(:runner_id, :project_id))
+ .group(:runner_id, :project_id)
+ .having('COUNT(*) > 1')
+
+ duplicated_runner_projects.each do |runner_project|
+ deduplicate_item(runner_project)
+ end
+ end
+
+ add_concurrent_index(TABLE_NAME, [:runner_id, :project_id], unique: true, name: INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, TMP_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, [:runner_id, :project_id], name: OLD_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, TMP_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+
+ private
+
+ def deduplicate_item(runner_project)
+ runner_projects_records = Ci::RunnerProject
+ .where(project_id: runner_project.project_id, runner_id: runner_project.runner_id)
+ .order(updated_at: :asc)
+ .to_a
+
+ attributes = {}
+ runner_projects_records.each do |runner_projects_record|
+ params = runner_projects_record.attributes.except('id')
+ attributes.merge!(params.compact)
+ end
+
+ ApplicationRecord.transaction do
+ record_to_keep = runner_projects_records.pop
+ records_to_delete = runner_projects_records
+
+ Ci::RunnerProject.where(id: records_to_delete.map(&:id)).delete_all
+ record_to_keep.update!(attributes)
+ end
+ end
+end
diff --git a/db/post_migrate/20220124145019_remove_projects_external_pull_requests_project_id_fk.rb b/db/post_migrate/20220124145019_remove_projects_external_pull_requests_project_id_fk.rb
new file mode 100644
index 00000000000..b16234fc812
--- /dev/null
+++ b/db/post_migrate/20220124145019_remove_projects_external_pull_requests_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsExternalPullRequestsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:external_pull_requests, :projects, name: "fk_rails_bcae9b5c7b")
+
+ with_lock_retries do
+ execute('LOCK projects, external_pull_requests IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:external_pull_requests, :projects, name: "fk_rails_bcae9b5c7b")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:external_pull_requests, :projects, name: "fk_rails_bcae9b5c7b", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124151456_remove_projects_ci_triggers_project_id_fk.rb b/db/post_migrate/20220124151456_remove_projects_ci_triggers_project_id_fk.rb
new file mode 100644
index 00000000000..684d363eb96
--- /dev/null
+++ b/db/post_migrate/20220124151456_remove_projects_ci_triggers_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiTriggersProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_triggers, :projects, name: "fk_e3e63f966e")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_triggers IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_triggers, :projects, name: "fk_e3e63f966e")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_triggers, :projects, name: "fk_e3e63f966e", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124151949_remove_projects_ci_runner_projects_project_id_fk.rb b/db/post_migrate/20220124151949_remove_projects_ci_runner_projects_project_id_fk.rb
new file mode 100644
index 00000000000..de8feb96a06
--- /dev/null
+++ b/db/post_migrate/20220124151949_remove_projects_ci_runner_projects_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiRunnerProjectsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_runner_projects, :projects, name: "fk_4478a6f1e4")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_runner_projects IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_runner_projects, :projects, name: "fk_4478a6f1e4")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_runner_projects, :projects, name: "fk_4478a6f1e4", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124152824_remove_projects_ci_subscriptions_projects_downstream_project_id_fk.rb b/db/post_migrate/20220124152824_remove_projects_ci_subscriptions_projects_downstream_project_id_fk.rb
new file mode 100644
index 00000000000..8596b1f14ba
--- /dev/null
+++ b/db/post_migrate/20220124152824_remove_projects_ci_subscriptions_projects_downstream_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiSubscriptionsProjectsDownstreamProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_subscriptions_projects, :projects, name: "fk_rails_0818751483")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_subscriptions_projects IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_subscriptions_projects, :projects, name: "fk_rails_0818751483")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_subscriptions_projects, :projects, name: "fk_rails_0818751483", column: :downstream_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124153233_remove_projects_ci_job_artifacts_project_id_fk.rb b/db/post_migrate/20220124153233_remove_projects_ci_job_artifacts_project_id_fk.rb
new file mode 100644
index 00000000000..1948a78916d
--- /dev/null
+++ b/db/post_migrate/20220124153233_remove_projects_ci_job_artifacts_project_id_fk.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiJobArtifactsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return if Gitlab.com? # unsafe migration, skip on GitLab.com due to https://gitlab.com/groups/gitlab-org/-/epics/7249#note_819625526
+ return unless foreign_key_exists?(:ci_job_artifacts, :projects, name: "fk_rails_9862d392f9")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_job_artifacts IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_job_artifacts, :projects, name: "fk_rails_9862d392f9")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_job_artifacts, :projects, name: "fk_rails_9862d392f9", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124153234_re_remove_projects_ci_job_artifacts_project_id_fk.rb b/db/post_migrate/20220124153234_re_remove_projects_ci_job_artifacts_project_id_fk.rb
new file mode 100644
index 00000000000..bb59134b927
--- /dev/null
+++ b/db/post_migrate/20220124153234_re_remove_projects_ci_job_artifacts_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ReRemoveProjectsCiJobArtifactsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_job_artifacts, :projects, name: "fk_rails_9862d392f9")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_job_artifacts IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_job_artifacts, :projects, name: "fk_rails_9862d392f9")
+ end
+ end
+
+ def down
+ # no-op, since the FK will be added via rollback by prior-migration
+ end
+end
diff --git a/db/post_migrate/20220124180704_remove_projects_ci_builds_metadata_project_id_fk.rb b/db/post_migrate/20220124180704_remove_projects_ci_builds_metadata_project_id_fk.rb
new file mode 100644
index 00000000000..fc9dc2cc6dc
--- /dev/null
+++ b/db/post_migrate/20220124180704_remove_projects_ci_builds_metadata_project_id_fk.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiBuildsMetadataProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return if Gitlab.com? # unsafe migration, skip on GitLab.com due to https://gitlab.com/groups/gitlab-org/-/epics/7249#note_819625526
+ return unless foreign_key_exists?(:ci_builds_metadata, :projects, name: "fk_rails_ffcf702a02")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_builds_metadata IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_builds_metadata, :projects, name: "fk_rails_ffcf702a02")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_builds_metadata, :projects, name: "fk_rails_ffcf702a02", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124180705_re_remove_projects_ci_builds_metadata_project_id_fk.rb b/db/post_migrate/20220124180705_re_remove_projects_ci_builds_metadata_project_id_fk.rb
new file mode 100644
index 00000000000..6483b8e0643
--- /dev/null
+++ b/db/post_migrate/20220124180705_re_remove_projects_ci_builds_metadata_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ReRemoveProjectsCiBuildsMetadataProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_builds_metadata, :projects, name: "fk_rails_ffcf702a02")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_builds_metadata IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_builds_metadata, :projects, name: "fk_rails_ffcf702a02")
+ end
+ end
+
+ def down
+ # no-op, since the FK will be added via rollback by prior-migration
+ end
+end
diff --git a/db/post_migrate/20220124184338_remove_projects_ci_subscriptions_projects_upstream_project_id_fk.rb b/db/post_migrate/20220124184338_remove_projects_ci_subscriptions_projects_upstream_project_id_fk.rb
new file mode 100644
index 00000000000..50448f4a884
--- /dev/null
+++ b/db/post_migrate/20220124184338_remove_projects_ci_subscriptions_projects_upstream_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiSubscriptionsProjectsUpstreamProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_subscriptions_projects, :projects, name: "fk_rails_7871f9a97b")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_subscriptions_projects IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_subscriptions_projects, :projects, name: "fk_rails_7871f9a97b")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_subscriptions_projects, :projects, name: "fk_rails_7871f9a97b", column: :upstream_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124204046_remove_projects_ci_sources_pipelines_project_id_fk.rb b/db/post_migrate/20220124204046_remove_projects_ci_sources_pipelines_project_id_fk.rb
new file mode 100644
index 00000000000..e15d337045e
--- /dev/null
+++ b/db/post_migrate/20220124204046_remove_projects_ci_sources_pipelines_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiSourcesPipelinesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_sources_pipelines, :projects, name: "fk_1e53c97c0a")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_sources_pipelines IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_sources_pipelines, :projects, name: "fk_1e53c97c0a")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_sources_pipelines, :projects, name: "fk_1e53c97c0a", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124214131_remove_projects_ci_refs_project_id_fk.rb b/db/post_migrate/20220124214131_remove_projects_ci_refs_project_id_fk.rb
new file mode 100644
index 00000000000..f90d477673a
--- /dev/null
+++ b/db/post_migrate/20220124214131_remove_projects_ci_refs_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiRefsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_refs, :projects, name: "fk_rails_4249db8cc3")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_refs IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_refs, :projects, name: "fk_rails_4249db8cc3")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_refs, :projects, name: "fk_rails_4249db8cc3", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124215857_remove_projects_ci_job_token_project_scope_links_source_project_id_fk.rb b/db/post_migrate/20220124215857_remove_projects_ci_job_token_project_scope_links_source_project_id_fk.rb
new file mode 100644
index 00000000000..8bfe9586a50
--- /dev/null
+++ b/db/post_migrate/20220124215857_remove_projects_ci_job_token_project_scope_links_source_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiJobTokenProjectScopeLinksSourceProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_job_token_project_scope_links, :projects, name: "fk_rails_4b2ee3290b")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_job_token_project_scope_links IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_job_token_project_scope_links, :projects, name: "fk_rails_4b2ee3290b")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_job_token_project_scope_links, :projects, name: "fk_rails_4b2ee3290b", column: :source_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220124221521_remove_projects_ci_project_monthly_usages_project_id_fk.rb b/db/post_migrate/20220124221521_remove_projects_ci_project_monthly_usages_project_id_fk.rb
new file mode 100644
index 00000000000..cff78342d21
--- /dev/null
+++ b/db/post_migrate/20220124221521_remove_projects_ci_project_monthly_usages_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiProjectMonthlyUsagesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_project_monthly_usages, :projects, name: "fk_rails_508bcd4aa6")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_project_monthly_usages IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_project_monthly_usages, :projects, name: "fk_rails_508bcd4aa6")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_project_monthly_usages, :projects, name: "fk_rails_508bcd4aa6", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220125083520_remove_ci_pipelines_dast_site_profiles_pipelines_ci_pipeline_id_fk.rb b/db/post_migrate/20220125083520_remove_ci_pipelines_dast_site_profiles_pipelines_ci_pipeline_id_fk.rb
new file mode 100644
index 00000000000..b111b95fccf
--- /dev/null
+++ b/db/post_migrate/20220125083520_remove_ci_pipelines_dast_site_profiles_pipelines_ci_pipeline_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesDastSiteProfilesPipelinesCiPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:dast_site_profiles_pipelines, :ci_pipelines, name: "fk_53849b0ad5")
+
+ with_lock_retries do
+ execute('LOCK ci_pipelines, dast_site_profiles_pipelines IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:dast_site_profiles_pipelines, :ci_pipelines, name: "fk_53849b0ad5")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:dast_site_profiles_pipelines, :ci_pipelines, name: "fk_53849b0ad5", column: :ci_pipeline_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220125084348_remove_ci_pipelines_vulnerability_feedback_pipeline_id_fk.rb b/db/post_migrate/20220125084348_remove_ci_pipelines_vulnerability_feedback_pipeline_id_fk.rb
new file mode 100644
index 00000000000..1b932d084bb
--- /dev/null
+++ b/db/post_migrate/20220125084348_remove_ci_pipelines_vulnerability_feedback_pipeline_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelinesVulnerabilityFeedbackPipelineIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:vulnerability_feedback, :ci_pipelines, name: "fk_rails_20976e6fd9")
+
+ with_lock_retries do
+ execute('LOCK ci_pipelines, vulnerability_feedback IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:vulnerability_feedback, :ci_pipelines, name: "fk_rails_20976e6fd9")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:vulnerability_feedback, :ci_pipelines, name: "fk_rails_20976e6fd9", column: :pipeline_id, target_column: :id, on_delete: :nullify)
+ end
+end
diff --git a/db/post_migrate/20220125122640_schedule_populate_topics_non_private_projects_count.rb b/db/post_migrate/20220125122640_schedule_populate_topics_non_private_projects_count.rb
new file mode 100644
index 00000000000..dee86a70553
--- /dev/null
+++ b/db/post_migrate/20220125122640_schedule_populate_topics_non_private_projects_count.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class SchedulePopulateTopicsNonPrivateProjectsCount < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'PopulateTopicsNonPrivateProjectsCount'
+ BATCH_SIZE = 10_000
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('topics'),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220126201752_remove_projects_ci_job_token_project_scope_links_target_project_id_fk.rb b/db/post_migrate/20220126201752_remove_projects_ci_job_token_project_scope_links_target_project_id_fk.rb
new file mode 100644
index 00000000000..a33e02f2408
--- /dev/null
+++ b/db/post_migrate/20220126201752_remove_projects_ci_job_token_project_scope_links_target_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiJobTokenProjectScopeLinksTargetProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_job_token_project_scope_links, :projects, name: "fk_rails_6904b38465")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_job_token_project_scope_links IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_job_token_project_scope_links, :projects, name: "fk_rails_6904b38465")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_job_token_project_scope_links, :projects, name: "fk_rails_6904b38465", column: :target_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220126202654_remove_projects_ci_sources_projects_source_project_id_fk.rb b/db/post_migrate/20220126202654_remove_projects_ci_sources_projects_source_project_id_fk.rb
new file mode 100644
index 00000000000..a69cd43b921
--- /dev/null
+++ b/db/post_migrate/20220126202654_remove_projects_ci_sources_projects_source_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiSourcesProjectsSourceProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_sources_projects, :projects, name: "fk_rails_64b6855cbc")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_sources_projects IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_sources_projects, :projects, name: "fk_rails_64b6855cbc")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_sources_projects, :projects, name: "fk_rails_64b6855cbc", column: :source_project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220126203421_remove_projects_ci_pipeline_schedules_project_id_fk.rb b/db/post_migrate/20220126203421_remove_projects_ci_pipeline_schedules_project_id_fk.rb
new file mode 100644
index 00000000000..870127ab168
--- /dev/null
+++ b/db/post_migrate/20220126203421_remove_projects_ci_pipeline_schedules_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiPipelineSchedulesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_pipeline_schedules, :projects, name: "fk_8ead60fcc4")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_pipeline_schedules IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_pipeline_schedules, :projects, name: "fk_8ead60fcc4")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_pipeline_schedules, :projects, name: "fk_8ead60fcc4", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220126210021_remove_projects_ci_builds_project_id_fk.rb b/db/post_migrate/20220126210021_remove_projects_ci_builds_project_id_fk.rb
new file mode 100644
index 00000000000..8caa6db7507
--- /dev/null
+++ b/db/post_migrate/20220126210021_remove_projects_ci_builds_project_id_fk.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiBuildsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return if Gitlab.com? # unsafe migration, skip on GitLab.com due to https://gitlab.com/groups/gitlab-org/-/epics/7249#note_819625526
+ return unless foreign_key_exists?(:ci_builds, :projects, name: "fk_befce0568a")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_builds IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_builds, :projects, name: "fk_befce0568a")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_builds, :projects, name: "fk_befce0568a", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220126210022_re_remove_projects_ci_builds_project_id_fk.rb b/db/post_migrate/20220126210022_re_remove_projects_ci_builds_project_id_fk.rb
new file mode 100644
index 00000000000..2a026388bbf
--- /dev/null
+++ b/db/post_migrate/20220126210022_re_remove_projects_ci_builds_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ReRemoveProjectsCiBuildsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_builds, :projects, name: "fk_befce0568a")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_builds IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_builds, :projects, name: "fk_befce0568a")
+ end
+ end
+
+ def down
+ # no-op, since the FK will be added via rollback by prior-migration
+ end
+end
diff --git a/db/post_migrate/20220126210657_remove_projects_ci_pipelines_project_id_fk.rb b/db/post_migrate/20220126210657_remove_projects_ci_pipelines_project_id_fk.rb
new file mode 100644
index 00000000000..6867cf720f3
--- /dev/null
+++ b/db/post_migrate/20220126210657_remove_projects_ci_pipelines_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiPipelinesProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:ci_pipelines, :projects, name: "fk_86635dbd80")
+
+ with_lock_retries do
+ execute('LOCK projects, ci_pipelines IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:ci_pipelines, :projects, name: "fk_86635dbd80")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_pipelines, :projects, name: "fk_86635dbd80", column: :project_id, target_column: :id, on_delete: :cascade)
+ end
+end
diff --git a/db/post_migrate/20220127112243_add_index_to_merge_request_assignees_state.rb b/db/post_migrate/20220127112243_add_index_to_merge_request_assignees_state.rb
new file mode 100644
index 00000000000..e6bb43af760
--- /dev/null
+++ b/db/post_migrate/20220127112243_add_index_to_merge_request_assignees_state.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToMergeRequestAssigneesState < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_on_merge_request_assignees_state'
+
+ def up
+ add_concurrent_index :merge_request_assignees, :state, where: 'state = 2', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_request_assignees, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220127112412_add_index_to_merge_request_reviewers_state.rb b/db/post_migrate/20220127112412_add_index_to_merge_request_reviewers_state.rb
new file mode 100644
index 00000000000..13f4e05c15b
--- /dev/null
+++ b/db/post_migrate/20220127112412_add_index_to_merge_request_reviewers_state.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToMergeRequestReviewersState < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_on_merge_request_reviewers_state'
+
+ def up
+ add_concurrent_index :merge_request_reviewers, :state, where: 'state = 2', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_request_reviewers, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb b/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb
new file mode 100644
index 00000000000..65ec2f9a282
--- /dev/null
+++ b/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CleanupBackfillCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillCiNamespaceMirrors'
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_background_migration(MIGRATION)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb b/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb
new file mode 100644
index 00000000000..8c7d9a945ba
--- /dev/null
+++ b/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CleanupBackfillCiProjectMirrors < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillCiProjectMirrors'
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_background_migration(MIGRATION)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220128155251_remove_dangling_running_builds.rb b/db/post_migrate/20220128155251_remove_dangling_running_builds.rb
new file mode 100644
index 00000000000..f86a21ced00
--- /dev/null
+++ b/db/post_migrate/20220128155251_remove_dangling_running_builds.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class RemoveDanglingRunningBuilds < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 100
+
+ disable_ddl_transaction!
+
+ def up
+ each_batch_range('ci_running_builds', of: BATCH_SIZE) do |min, max|
+ execute <<~SQL
+ DELETE FROM ci_running_builds
+ USING ci_builds
+ WHERE ci_builds.id = ci_running_builds.build_id
+ AND ci_builds.status = 'failed'
+ AND ci_builds.type = 'Ci::Build'
+ AND ci_running_builds.id BETWEEN #{min} AND #{max}
+ SQL
+ end
+ end
+
+ def down
+ # no-op
+ # This migration deletes data and it can not be reversed
+ end
+end
diff --git a/db/post_migrate/20220128155814_fix_approval_rules_code_owners_rule_type_index.rb b/db/post_migrate/20220128155814_fix_approval_rules_code_owners_rule_type_index.rb
new file mode 100644
index 00000000000..eccfab25126
--- /dev/null
+++ b/db/post_migrate/20220128155814_fix_approval_rules_code_owners_rule_type_index.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class FixApprovalRulesCodeOwnersRuleTypeIndex < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_approval_rules_code_owners_rule_type'
+ OLD_INDEX_NAME = 'index_approval_rules_code_owners_rule_type_old'
+ TABLE = :approval_merge_request_rules
+ COLUMN = :merge_request_id
+ WHERE_CONDITION = 'rule_type = 2'
+
+ disable_ddl_transaction!
+
+ def up
+ rename_index TABLE, INDEX_NAME, OLD_INDEX_NAME if index_exists_by_name?(TABLE, INDEX_NAME) && !index_exists_by_name?(TABLE, OLD_INDEX_NAME)
+
+ add_concurrent_index TABLE, COLUMN, where: WHERE_CONDITION, name: INDEX_NAME
+
+ remove_concurrent_index_by_name TABLE, OLD_INDEX_NAME
+ end
+
+ def down
+ # No-op
+ end
+end
diff --git a/db/post_migrate/20220201034731_remove_index_clusters_kubernetes_namespaces_on_cluster_id.rb b/db/post_migrate/20220201034731_remove_index_clusters_kubernetes_namespaces_on_cluster_id.rb
new file mode 100644
index 00000000000..0e2ef3b3324
--- /dev/null
+++ b/db/post_migrate/20220201034731_remove_index_clusters_kubernetes_namespaces_on_cluster_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveIndexClustersKubernetesNamespacesOnClusterId < Gitlab::Database::Migration[1.0]
+ INDEX = 'index_clusters_kubernetes_namespaces_on_cluster_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :clusters_kubernetes_namespaces, INDEX
+ end
+
+ def down
+ add_concurrent_index :clusters_kubernetes_namespaces, :cluster_id, name: INDEX
+ end
+end
diff --git a/db/post_migrate/20220201141705_cleanup_background_migration_populate_test_reports_issue_id.rb b/db/post_migrate/20220201141705_cleanup_background_migration_populate_test_reports_issue_id.rb
new file mode 100644
index 00000000000..252b4a01d04
--- /dev/null
+++ b/db/post_migrate/20220201141705_cleanup_background_migration_populate_test_reports_issue_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CleanupBackgroundMigrationPopulateTestReportsIssueId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION = 'PopulateTestReportsIssueId'
+
+ def up
+ finalize_background_migration(MIGRATION)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220201173212_add_user_details_provisioning_index.rb b/db/post_migrate/20220201173212_add_user_details_provisioning_index.rb
new file mode 100644
index 00000000000..a864ec7e395
--- /dev/null
+++ b/db/post_migrate/20220201173212_add_user_details_provisioning_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddUserDetailsProvisioningIndex < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'idx_user_details_on_provisioned_by_group_id_user_id'
+ OLD_INDEX_NAME = 'index_user_details_on_provisioned_by_group_id'
+
+ def up
+ add_concurrent_index :user_details, [:provisioned_by_group_id, :user_id], name: INDEX_NAME
+ remove_concurrent_index_by_name :user_details, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :user_details, :provisioned_by_group_id, name: OLD_INDEX_NAME
+ remove_concurrent_index_by_name :user_details, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb b/db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb
new file mode 100644
index 00000000000..cc9dabdf624
--- /dev/null
+++ b/db/post_migrate/20220201193033_add_unique_index_to_vulnerability_finding_links_with_truncate.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexToVulnerabilityFindingLinksWithTruncate < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ NAME_URL_INDEX_NAME = 'finding_link_name_url_idx'
+ URL_INDEX_NAME = 'finding_link_url_idx'
+
+ def up
+ execute('TRUNCATE TABLE vulnerability_finding_links')
+
+ add_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :name, :url], unique: true, name: NAME_URL_INDEX_NAME
+ add_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :url], unique: true, where: 'name is null', name: URL_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :name, :url], name: NAME_URL_INDEX_NAME
+ remove_concurrent_index :vulnerability_finding_links, [:vulnerability_occurrence_id, :url], name: URL_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220202105733_delete_service_template_records.rb b/db/post_migrate/20220202105733_delete_service_template_records.rb
new file mode 100644
index 00000000000..b70bacc83aa
--- /dev/null
+++ b/db/post_migrate/20220202105733_delete_service_template_records.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DeleteServiceTemplateRecords < Gitlab::Database::Migration[1.0]
+ class Integration < ActiveRecord::Base
+ # Disable single-table inheritance
+ self.inheritance_column = :_type_disabled
+ end
+ def up
+ Integration.where(template: true).delete_all
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220204053655_remove_index_epic_issues_on_epic_id.rb b/db/post_migrate/20220204053655_remove_index_epic_issues_on_epic_id.rb
new file mode 100644
index 00000000000..7815829d36a
--- /dev/null
+++ b/db/post_migrate/20220204053655_remove_index_epic_issues_on_epic_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveIndexEpicIssuesOnEpicId < Gitlab::Database::Migration[1.0]
+ INDEX = 'index_epic_issues_on_epic_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :epic_issues, name: INDEX
+ end
+
+ def down
+ add_concurrent_index :epic_issues, :epic_id, name: INDEX
+ end
+end
diff --git a/db/post_migrate/20220208115439_start_backfill_ci_queuing_tables.rb b/db/post_migrate/20220208115439_start_backfill_ci_queuing_tables.rb
new file mode 100644
index 00000000000..82e36174290
--- /dev/null
+++ b/db/post_migrate/20220208115439_start_backfill_ci_queuing_tables.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class StartBackfillCiQueuingTables < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillCiQueuingTables'
+ BATCH_SIZE = 500
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ def up
+ return if Gitlab.com?
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ Gitlab::BackgroundMigration::BackfillCiQueuingTables::Ci::Build.pending,
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220209111007_add_partial_index_for_batching_active_cluster_image_scanning_vulnerabilities.rb b/db/post_migrate/20220209111007_add_partial_index_for_batching_active_cluster_image_scanning_vulnerabilities.rb
new file mode 100644
index 00000000000..d38509ed8c2
--- /dev/null
+++ b/db/post_migrate/20220209111007_add_partial_index_for_batching_active_cluster_image_scanning_vulnerabilities.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddPartialIndexForBatchingActiveClusterImageScanningVulnerabilities < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id_active_cis'
+ INDEX_FILTER_CONDITION = 'report_type = 7 AND state = ANY(ARRAY[1, 4])'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :id], where: INDEX_FILTER_CONDITION, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220212120735_schedule_fix_incorrect_max_seats_used2.rb b/db/post_migrate/20220212120735_schedule_fix_incorrect_max_seats_used2.rb
new file mode 100644
index 00000000000..c8a6bd0a15d
--- /dev/null
+++ b/db/post_migrate/20220212120735_schedule_fix_incorrect_max_seats_used2.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ScheduleFixIncorrectMaxSeatsUsed2 < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'FixIncorrectMaxSeatsUsed'
+ TMP_IDX_NAME = 'tmp_gitlab_subscriptions_max_seats_used_migration_2'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :gitlab_subscriptions, :id, where: "start_date < '2021-08-02' AND max_seats_used != 0 AND max_seats_used > seats_in_use AND max_seats_used > seats", name: TMP_IDX_NAME
+
+ return unless Gitlab.com?
+
+ migrate_in(1.hour, MIGRATION, ['batch_2_for_start_date_before_02_aug_2021'])
+ end
+
+ def down
+ remove_concurrent_index_by_name :gitlab_subscriptions, TMP_IDX_NAME
+ end
+end
diff --git a/db/post_migrate/20220213104531_create_indexes_on_integration_type_new.rb b/db/post_migrate/20220213104531_create_indexes_on_integration_type_new.rb
new file mode 100644
index 00000000000..3a9f48dec44
--- /dev/null
+++ b/db/post_migrate/20220213104531_create_indexes_on_integration_type_new.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+# Reproduce the indices on integrations.type on integrations.type_new
+class CreateIndexesOnIntegrationTypeNew < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :integrations
+ COLUMN = :type_new
+
+ def indices
+ [
+ {
+ name: "index_integrations_on_project_and_#{COLUMN}_where_inherit_null",
+ columns: [:project_id, COLUMN],
+ where: 'inherit_from_id IS NULL'
+ },
+ {
+ name: "index_integrations_on_project_id_and_#{COLUMN}_unique",
+ columns: [:project_id, COLUMN],
+ unique: true
+ },
+ {
+ name: "index_integrations_on_#{COLUMN}",
+ columns: [COLUMN]
+ },
+ {
+ name: "index_integrations_on_#{COLUMN}_and_instance_partial",
+ columns: [COLUMN, :instance],
+ where: 'instance = true'
+ },
+ {
+ name: "index_integrations_on_#{COLUMN}_and_template_partial",
+ columns: [COLUMN, :template],
+ where: 'template = true'
+ },
+ {
+ # column names are limited to 63 characters, so this one is re-worded for clarity
+ name: "index_integrations_on_#{COLUMN}_id_when_active_and_has_project",
+ columns: [COLUMN, :id],
+ where: '((active = true) AND (project_id IS NOT NULL))'
+ },
+ {
+ name: "index_integrations_on_unique_group_id_and_#{COLUMN}",
+ columns: [:group_id, COLUMN]
+ }
+ ]
+ end
+
+ def up
+ indices.each do |index|
+ add_concurrent_index TABLE_NAME, index[:columns], index.except(:columns)
+ end
+ end
+
+ def down
+ indices.each do |index|
+ remove_concurrent_index_by_name TABLE_NAME, index[:name]
+ end
+ end
+end
diff --git a/db/schema_migrations/20211119111006 b/db/schema_migrations/20211119111006
new file mode 100644
index 00000000000..ebb8e460452
--- /dev/null
+++ b/db/schema_migrations/20211119111006
@@ -0,0 +1 @@
+d618c28360f7716807e9727566019e269963d85164cf2f306ec9692d3b037802 \ No newline at end of file
diff --git a/db/schema_migrations/20211122103051 b/db/schema_migrations/20211122103051
new file mode 100644
index 00000000000..eacca224329
--- /dev/null
+++ b/db/schema_migrations/20211122103051
@@ -0,0 +1 @@
+674a44e70291d6ed04318a5f6b639d216f2c26c43d15cb00e59b06cc6f6cc401 \ No newline at end of file
diff --git a/db/schema_migrations/20211123135255 b/db/schema_migrations/20211123135255
new file mode 100644
index 00000000000..e151abb0e33
--- /dev/null
+++ b/db/schema_migrations/20211123135255
@@ -0,0 +1 @@
+cf6b9bb5711b6a097e399e79fdabe01a237581d99de7fed3c2b69c65ffd23a06 \ No newline at end of file
diff --git a/db/schema_migrations/20211124095704 b/db/schema_migrations/20211124095704
new file mode 100644
index 00000000000..db18301ecd9
--- /dev/null
+++ b/db/schema_migrations/20211124095704
@@ -0,0 +1 @@
+1f5ed9e7af3f56d0e11d1a2bb78a7430ce05af49c8102d1c75c8ff84ae4e1c6d \ No newline at end of file
diff --git a/db/schema_migrations/20211209103048 b/db/schema_migrations/20211209103048
new file mode 100644
index 00000000000..133d5fc1ed4
--- /dev/null
+++ b/db/schema_migrations/20211209103048
@@ -0,0 +1 @@
+d2d270a335b3a2441a20673bf19d47553f607533d4503e3a01bc3d6d108bcdb3 \ No newline at end of file
diff --git a/db/schema_migrations/20220105082217 b/db/schema_migrations/20220105082217
new file mode 100644
index 00000000000..a6232406be6
--- /dev/null
+++ b/db/schema_migrations/20220105082217
@@ -0,0 +1 @@
+448481ec9f7dd58d267e3660a49161c0e14baca35e640c59b27f2ebc4367b62a \ No newline at end of file
diff --git a/db/schema_migrations/20220106111958 b/db/schema_migrations/20220106111958
new file mode 100644
index 00000000000..954db532950
--- /dev/null
+++ b/db/schema_migrations/20220106111958
@@ -0,0 +1 @@
+c1af9546bdfa0f32c3c2faf362062cd300800514e5b1efd1fa8a1770753d00e5 \ No newline at end of file
diff --git a/db/schema_migrations/20220106112043 b/db/schema_migrations/20220106112043
new file mode 100644
index 00000000000..34c8c5152da
--- /dev/null
+++ b/db/schema_migrations/20220106112043
@@ -0,0 +1 @@
+8b51ae2b13066a56d2131efb7ea746335513031e751fb231e43121552d6f2b1d \ No newline at end of file
diff --git a/db/schema_migrations/20220106112085 b/db/schema_migrations/20220106112085
new file mode 100644
index 00000000000..171f893a0ab
--- /dev/null
+++ b/db/schema_migrations/20220106112085
@@ -0,0 +1 @@
+f385631d0317630661d487011a228501a6cbc71de25ca457d75e6a815c598045 \ No newline at end of file
diff --git a/db/schema_migrations/20220106163326 b/db/schema_migrations/20220106163326
new file mode 100644
index 00000000000..dbfb9079dc1
--- /dev/null
+++ b/db/schema_migrations/20220106163326
@@ -0,0 +1 @@
+4726d84ff42e64b1c47c5ba454ff5be05f434a86bb2af4bbe27dd00e5e3da5cb \ No newline at end of file
diff --git a/db/schema_migrations/20220106185033 b/db/schema_migrations/20220106185033
new file mode 100644
index 00000000000..be45c8bab6f
--- /dev/null
+++ b/db/schema_migrations/20220106185033
@@ -0,0 +1 @@
+5304bc3dada6794c8f6e1082861e12fdfb059effdcd5a17e11af5300e67708bd \ No newline at end of file
diff --git a/db/schema_migrations/20220107064845 b/db/schema_migrations/20220107064845
new file mode 100644
index 00000000000..bd63da88355
--- /dev/null
+++ b/db/schema_migrations/20220107064845
@@ -0,0 +1 @@
+c7c645787aadc95c77df6420f437f78aed4e7e862ea2b66e7824766b1d9f3cb5 \ No newline at end of file
diff --git a/db/schema_migrations/20220111093534 b/db/schema_migrations/20220111093534
new file mode 100644
index 00000000000..5999dbdf49a
--- /dev/null
+++ b/db/schema_migrations/20220111093534
@@ -0,0 +1 @@
+ff0127967c3ee6e4f4af528b84024a6a838f8dbeb19cf78d7d913d4fc8e155e7 \ No newline at end of file
diff --git a/db/schema_migrations/20220111101421 b/db/schema_migrations/20220111101421
new file mode 100644
index 00000000000..16d47665734
--- /dev/null
+++ b/db/schema_migrations/20220111101421
@@ -0,0 +1 @@
+abbba4ccacebb825c3f9cb5b0463d457fd4a7b4396a2184a995e496aebaf4521 \ No newline at end of file
diff --git a/db/schema_migrations/20220111154950 b/db/schema_migrations/20220111154950
new file mode 100644
index 00000000000..6070beb76e9
--- /dev/null
+++ b/db/schema_migrations/20220111154950
@@ -0,0 +1 @@
+4719c533acaac3234ac0e131c70be49d0f98642e29e7d2e31519cc6c372056bc \ No newline at end of file
diff --git a/db/schema_migrations/20220111154951 b/db/schema_migrations/20220111154951
new file mode 100644
index 00000000000..9d18e4c4d44
--- /dev/null
+++ b/db/schema_migrations/20220111154951
@@ -0,0 +1 @@
+48d6eaa68912f702be2bd38609bea4fa807eab7131f7c5e2261416820df9836a \ No newline at end of file
diff --git a/db/schema_migrations/20220113111440 b/db/schema_migrations/20220113111440
new file mode 100644
index 00000000000..e6188a9616f
--- /dev/null
+++ b/db/schema_migrations/20220113111440
@@ -0,0 +1 @@
+faf899c1aa99e596eb386935ee6ff17a51b7942ee4f6d4cbd1ad2283dd0d40c0 \ No newline at end of file
diff --git a/db/schema_migrations/20220117034056 b/db/schema_migrations/20220117034056
new file mode 100644
index 00000000000..acf76bfb9d6
--- /dev/null
+++ b/db/schema_migrations/20220117034056
@@ -0,0 +1 @@
+afc54500374602edcdc4fce5acf3673b84882da1afbb5598a6684a5ef480a2d7 \ No newline at end of file
diff --git a/db/schema_migrations/20220117082611 b/db/schema_migrations/20220117082611
new file mode 100644
index 00000000000..9dead593ffb
--- /dev/null
+++ b/db/schema_migrations/20220117082611
@@ -0,0 +1 @@
+28df9a8b5bf73bc33275cfe47f260788fa3263680a97128e086fd1698ccac1d8 \ No newline at end of file
diff --git a/db/schema_migrations/20220118015633 b/db/schema_migrations/20220118015633
new file mode 100644
index 00000000000..8ba4a376bcd
--- /dev/null
+++ b/db/schema_migrations/20220118015633
@@ -0,0 +1 @@
+6a73f49306de7c799a39afa3ac1f761840860833a96f1a91cf992c9a3ebfef9b \ No newline at end of file
diff --git a/db/schema_migrations/20220118020026 b/db/schema_migrations/20220118020026
new file mode 100644
index 00000000000..fe9dcccbc0c
--- /dev/null
+++ b/db/schema_migrations/20220118020026
@@ -0,0 +1 @@
+77374c81456f235d3afeb45cdda14552e1ef8047de5aaa3f5bb0a82e4aebe849 \ No newline at end of file
diff --git a/db/schema_migrations/20220118204039 b/db/schema_migrations/20220118204039
new file mode 100644
index 00000000000..209204054ff
--- /dev/null
+++ b/db/schema_migrations/20220118204039
@@ -0,0 +1 @@
+9b33f6e0c13acbf1adfc1b70f75418ceabc000a748c9216328ef36f1b8716ded \ No newline at end of file
diff --git a/db/schema_migrations/20220119094023 b/db/schema_migrations/20220119094023
new file mode 100644
index 00000000000..c2bf5ce88d6
--- /dev/null
+++ b/db/schema_migrations/20220119094023
@@ -0,0 +1 @@
+4eddd356d87ce8fc8168dabe678211239e8d4051804d51d3bdce8cc137fa5a0d \ No newline at end of file
diff --git a/db/schema_migrations/20220119094503 b/db/schema_migrations/20220119094503
new file mode 100644
index 00000000000..840a4d82593
--- /dev/null
+++ b/db/schema_migrations/20220119094503
@@ -0,0 +1 @@
+1048b3a9744f212297c0a3aba176556e92e85f199ac861eb3ee4183eff002860 \ No newline at end of file
diff --git a/db/schema_migrations/20220119141407 b/db/schema_migrations/20220119141407
new file mode 100644
index 00000000000..0ff56c63dd6
--- /dev/null
+++ b/db/schema_migrations/20220119141407
@@ -0,0 +1 @@
+18b3ef459c3633ebd4b418b4436d3d50b0dc697fa7c4ef4d2e1f62b01d656bce \ No newline at end of file
diff --git a/db/schema_migrations/20220119143130 b/db/schema_migrations/20220119143130
new file mode 100644
index 00000000000..8c9092fd187
--- /dev/null
+++ b/db/schema_migrations/20220119143130
@@ -0,0 +1 @@
+a375f82fe0c1ef87aa6abb2142387b852b135be6e2158fd8456b23dc9bcf2a0e \ No newline at end of file
diff --git a/db/schema_migrations/20220119144253 b/db/schema_migrations/20220119144253
new file mode 100644
index 00000000000..ee59402bbcc
--- /dev/null
+++ b/db/schema_migrations/20220119144253
@@ -0,0 +1 @@
+723db0d234a4dadfdad68a92c249ec0b42e519297f48bcb843e89c1ad97032c7 \ No newline at end of file
diff --git a/db/schema_migrations/20220119144458 b/db/schema_migrations/20220119144458
new file mode 100644
index 00000000000..c5eb43a3730
--- /dev/null
+++ b/db/schema_migrations/20220119144458
@@ -0,0 +1 @@
+85227d2aa0e984f12362484b23554a4feb1304d055d54da40e20812f2d8c5b9e \ No newline at end of file
diff --git a/db/schema_migrations/20220119151221 b/db/schema_migrations/20220119151221
new file mode 100644
index 00000000000..377170d9cb1
--- /dev/null
+++ b/db/schema_migrations/20220119151221
@@ -0,0 +1 @@
+7865f26c43c79681f37ceb6e4fecf6153282856907ddfd8211d6d1d57d1fb7f3 \ No newline at end of file
diff --git a/db/schema_migrations/20220119153706 b/db/schema_migrations/20220119153706
new file mode 100644
index 00000000000..446fee12b44
--- /dev/null
+++ b/db/schema_migrations/20220119153706
@@ -0,0 +1 @@
+f87eec3c61cfc9dc860fe77af1fbe98c1ea2a9b0dc1b2dbdaaee4276b518af73 \ No newline at end of file
diff --git a/db/schema_migrations/20220119154442 b/db/schema_migrations/20220119154442
new file mode 100644
index 00000000000..78880a0164c
--- /dev/null
+++ b/db/schema_migrations/20220119154442
@@ -0,0 +1 @@
+7cb06f695c7e8e733ea50f0b2e8fbb115d5ac0d7e7f000228bd5ced58ab362c9 \ No newline at end of file
diff --git a/db/schema_migrations/20220119170426 b/db/schema_migrations/20220119170426
new file mode 100644
index 00000000000..51274ac5979
--- /dev/null
+++ b/db/schema_migrations/20220119170426
@@ -0,0 +1 @@
+a488fecd8e6e99b8d32ac27f72c6a3575b0ed29baaf242133e5d1abbd5b64314 \ No newline at end of file
diff --git a/db/schema_migrations/20220119193130 b/db/schema_migrations/20220119193130
new file mode 100644
index 00000000000..5305ff9465e
--- /dev/null
+++ b/db/schema_migrations/20220119193130
@@ -0,0 +1 @@
+c991eda1b3a972a7da9bdbd5e1f9957394c52246b78d793b4b35fdec9daf6acd \ No newline at end of file
diff --git a/db/schema_migrations/20220119201340 b/db/schema_migrations/20220119201340
new file mode 100644
index 00000000000..0dc36b2dfba
--- /dev/null
+++ b/db/schema_migrations/20220119201340
@@ -0,0 +1 @@
+62b35cc5bd0abc5b7bcf4347346de832bbbed723fee7860ec649185d4d5fb53c \ No newline at end of file
diff --git a/db/schema_migrations/20220119203119 b/db/schema_migrations/20220119203119
new file mode 100644
index 00000000000..43bdb5b0391
--- /dev/null
+++ b/db/schema_migrations/20220119203119
@@ -0,0 +1 @@
+c0f29fd7f960ffd92a65a00e8dce123b91a604f4d89b7cf0bc419fa80495e2e5 \ No newline at end of file
diff --git a/db/schema_migrations/20220119220620 b/db/schema_migrations/20220119220620
new file mode 100644
index 00000000000..a6a9abb2acc
--- /dev/null
+++ b/db/schema_migrations/20220119220620
@@ -0,0 +1 @@
+535f476a358dcb3f3472f1e0ec1afef738f995197b5d1f4fcd61e58a9c9e8e75 \ No newline at end of file
diff --git a/db/schema_migrations/20220120033115 b/db/schema_migrations/20220120033115
new file mode 100644
index 00000000000..ef71ca650cd
--- /dev/null
+++ b/db/schema_migrations/20220120033115
@@ -0,0 +1 @@
+41b67585574f6309d8e32fe695e65fc43f15f6738db713c1a11e04558a5ec515 \ No newline at end of file
diff --git a/db/schema_migrations/20220120085655 b/db/schema_migrations/20220120085655
new file mode 100644
index 00000000000..534108786ec
--- /dev/null
+++ b/db/schema_migrations/20220120085655
@@ -0,0 +1 @@
+966c42749e9d200f2b7295fdbb86e596c33510f0abbf431d40b09629e5e4a6aa \ No newline at end of file
diff --git a/db/schema_migrations/20220120094340 b/db/schema_migrations/20220120094340
new file mode 100644
index 00000000000..423adf5cc94
--- /dev/null
+++ b/db/schema_migrations/20220120094340
@@ -0,0 +1 @@
+69d8283501ba6a4946a60e3812fe2cf3031fc4a915d6e7c6fac3bf272423f2f2 \ No newline at end of file
diff --git a/db/schema_migrations/20220120123700 b/db/schema_migrations/20220120123700
new file mode 100644
index 00000000000..263901fff19
--- /dev/null
+++ b/db/schema_migrations/20220120123700
@@ -0,0 +1 @@
+9e274eae18520821dd890a11c8c6192da82a6051dce9ec2934b1365e57a10fdb \ No newline at end of file
diff --git a/db/schema_migrations/20220120123800 b/db/schema_migrations/20220120123800
new file mode 100644
index 00000000000..6d271f75c08
--- /dev/null
+++ b/db/schema_migrations/20220120123800
@@ -0,0 +1 @@
+9d2f0b0d2cb1a5844bdca5bcb4b82fa5cc6b465fa19177f9f6ca16574128fdc8 \ No newline at end of file
diff --git a/db/schema_migrations/20220121214752 b/db/schema_migrations/20220121214752
new file mode 100644
index 00000000000..84c03a6ed90
--- /dev/null
+++ b/db/schema_migrations/20220121214752
@@ -0,0 +1 @@
+c56983a489b56eb6b4a5cd5ae6947a322fd58b8e96bcdee1e38634d99727c432 \ No newline at end of file
diff --git a/db/schema_migrations/20220121214753 b/db/schema_migrations/20220121214753
new file mode 100644
index 00000000000..5142044be97
--- /dev/null
+++ b/db/schema_migrations/20220121214753
@@ -0,0 +1 @@
+b7b9f5e516664e7eb3f7a5307d1871bb4f58a31f4807e0298fbf9414bad567fa \ No newline at end of file
diff --git a/db/schema_migrations/20220121221651 b/db/schema_migrations/20220121221651
new file mode 100644
index 00000000000..562751c6084
--- /dev/null
+++ b/db/schema_migrations/20220121221651
@@ -0,0 +1 @@
+a1681c1c619db7f4e7e5a760cee7d06a931aa1f02dccfce46be81d75a03ce8ac \ No newline at end of file
diff --git a/db/schema_migrations/20220124130028 b/db/schema_migrations/20220124130028
new file mode 100644
index 00000000000..5ee8e463a55
--- /dev/null
+++ b/db/schema_migrations/20220124130028
@@ -0,0 +1 @@
+7f2b3e70e33273d75f68bd1fa33103f24a4e4cfc3f2e5777dfd258b5a2e7bf4e \ No newline at end of file
diff --git a/db/schema_migrations/20220124145019 b/db/schema_migrations/20220124145019
new file mode 100644
index 00000000000..8de01024798
--- /dev/null
+++ b/db/schema_migrations/20220124145019
@@ -0,0 +1 @@
+3b1f7a7b6481a960ac25523e5e1b5abc6c1436332d64d4319d9e4112b0fa765e \ No newline at end of file
diff --git a/db/schema_migrations/20220124151456 b/db/schema_migrations/20220124151456
new file mode 100644
index 00000000000..10a7b978e2f
--- /dev/null
+++ b/db/schema_migrations/20220124151456
@@ -0,0 +1 @@
+5ec73b28adb027a4462ec9b268ef9c505e281f1afedce3c592d431cd90808dac \ No newline at end of file
diff --git a/db/schema_migrations/20220124151949 b/db/schema_migrations/20220124151949
new file mode 100644
index 00000000000..2d6305b9789
--- /dev/null
+++ b/db/schema_migrations/20220124151949
@@ -0,0 +1 @@
+4eb33deb4c2d5ff587f8af57b8296e46911f24a6ed0b2f7ff1f36243f1a9013d \ No newline at end of file
diff --git a/db/schema_migrations/20220124152824 b/db/schema_migrations/20220124152824
new file mode 100644
index 00000000000..5a0db5859f0
--- /dev/null
+++ b/db/schema_migrations/20220124152824
@@ -0,0 +1 @@
+acf680cbf06d6eb2c0da44d416ff947e0460593cad74499acda91eb4bec63894 \ No newline at end of file
diff --git a/db/schema_migrations/20220124153233 b/db/schema_migrations/20220124153233
new file mode 100644
index 00000000000..bfb0d6f3c38
--- /dev/null
+++ b/db/schema_migrations/20220124153233
@@ -0,0 +1 @@
+f62f3d4cc6f4704e7b4e7d0b6b8e46ed3de4407f0db4282e2ce845aa6c0b3f3f \ No newline at end of file
diff --git a/db/schema_migrations/20220124153234 b/db/schema_migrations/20220124153234
new file mode 100644
index 00000000000..dfca9995395
--- /dev/null
+++ b/db/schema_migrations/20220124153234
@@ -0,0 +1 @@
+0e8559121504f1a34394b5f613ef2c5554261f6aeaeaaf5a15d018803c4e5452 \ No newline at end of file
diff --git a/db/schema_migrations/20220124180704 b/db/schema_migrations/20220124180704
new file mode 100644
index 00000000000..ef59507a2e8
--- /dev/null
+++ b/db/schema_migrations/20220124180704
@@ -0,0 +1 @@
+5b5f47f1d7038518fef71dd8c0758b234bb890be9aab57b78918f7b2dc39bdc4 \ No newline at end of file
diff --git a/db/schema_migrations/20220124180705 b/db/schema_migrations/20220124180705
new file mode 100644
index 00000000000..c1600192af1
--- /dev/null
+++ b/db/schema_migrations/20220124180705
@@ -0,0 +1 @@
+6c147287ba8436bd0231dc22195c95a71d19987d23741c1291a117407f493184 \ No newline at end of file
diff --git a/db/schema_migrations/20220124184338 b/db/schema_migrations/20220124184338
new file mode 100644
index 00000000000..860b47090c2
--- /dev/null
+++ b/db/schema_migrations/20220124184338
@@ -0,0 +1 @@
+ae696157794bcbe3ebd0dc41d7b3fe4dc61982ad4a96fa503fd7857e0d3dab16 \ No newline at end of file
diff --git a/db/schema_migrations/20220124204046 b/db/schema_migrations/20220124204046
new file mode 100644
index 00000000000..f8de3adc215
--- /dev/null
+++ b/db/schema_migrations/20220124204046
@@ -0,0 +1 @@
+90115936ede32bbf9a299582409cb0686e8072c204c4f91364dfb13195155929 \ No newline at end of file
diff --git a/db/schema_migrations/20220124214131 b/db/schema_migrations/20220124214131
new file mode 100644
index 00000000000..7454bd8b3d1
--- /dev/null
+++ b/db/schema_migrations/20220124214131
@@ -0,0 +1 @@
+af60c6df0fb178a4820ea8cb40b402178da7fb4b6ebeabb8739dc45b96225f89 \ No newline at end of file
diff --git a/db/schema_migrations/20220124215857 b/db/schema_migrations/20220124215857
new file mode 100644
index 00000000000..495e428d2c4
--- /dev/null
+++ b/db/schema_migrations/20220124215857
@@ -0,0 +1 @@
+785c2404175faef7d3d6f81ae8652ca0ced0f4b01def8d6364a4450f0db49ecf \ No newline at end of file
diff --git a/db/schema_migrations/20220124221521 b/db/schema_migrations/20220124221521
new file mode 100644
index 00000000000..8400dcbc1e2
--- /dev/null
+++ b/db/schema_migrations/20220124221521
@@ -0,0 +1 @@
+4b1dad4fc34717c9b89a770e4e0682b0cee7d421da68223011bb9fde9460d1f8 \ No newline at end of file
diff --git a/db/schema_migrations/20220125083520 b/db/schema_migrations/20220125083520
new file mode 100644
index 00000000000..c3fbb6beda5
--- /dev/null
+++ b/db/schema_migrations/20220125083520
@@ -0,0 +1 @@
+2c3f7c587b2a20de1d8581584f7392fd81643af4eb7e25ffc8e08514b6ad83ab \ No newline at end of file
diff --git a/db/schema_migrations/20220125084127 b/db/schema_migrations/20220125084127
new file mode 100644
index 00000000000..f9ba7a4628b
--- /dev/null
+++ b/db/schema_migrations/20220125084127
@@ -0,0 +1 @@
+c50a21430e52fc6ccbe7ab4aba99ae3a48d1c69858f7886da115f54e19fc27ea \ No newline at end of file
diff --git a/db/schema_migrations/20220125084348 b/db/schema_migrations/20220125084348
new file mode 100644
index 00000000000..9d4cbd7c5ed
--- /dev/null
+++ b/db/schema_migrations/20220125084348
@@ -0,0 +1 @@
+75eb050fc789eb5775a5d3a88c2573dca5c38e16b63cd342bf46dca55d1adaef \ No newline at end of file
diff --git a/db/schema_migrations/20220125122228 b/db/schema_migrations/20220125122228
new file mode 100644
index 00000000000..2add72978c6
--- /dev/null
+++ b/db/schema_migrations/20220125122228
@@ -0,0 +1 @@
+26600e01d8b31a4308d0e23564e4d4c52488ec87ad7990a410b7cc0c031f12e7 \ No newline at end of file
diff --git a/db/schema_migrations/20220125122640 b/db/schema_migrations/20220125122640
new file mode 100644
index 00000000000..fdb85bb480a
--- /dev/null
+++ b/db/schema_migrations/20220125122640
@@ -0,0 +1 @@
+51c7ab860b952281bd7f65d68e7a539a8eee57cac3bbdaf439ff5593f5b065ed \ No newline at end of file
diff --git a/db/schema_migrations/20220125122725 b/db/schema_migrations/20220125122725
new file mode 100644
index 00000000000..7a6ef38bfbc
--- /dev/null
+++ b/db/schema_migrations/20220125122725
@@ -0,0 +1 @@
+7740d1e71571576a709ae5bfd46f60ea3fb4be3f48cddec2cca53f148096cdd7 \ No newline at end of file
diff --git a/db/schema_migrations/20220125230538 b/db/schema_migrations/20220125230538
new file mode 100644
index 00000000000..45bd8bfb04c
--- /dev/null
+++ b/db/schema_migrations/20220125230538
@@ -0,0 +1 @@
+6f3a3712288c3316042426d60f087817eb57a3246b750831aa72f95f30269a5d \ No newline at end of file
diff --git a/db/schema_migrations/20220126201752 b/db/schema_migrations/20220126201752
new file mode 100644
index 00000000000..e5a1970ec9e
--- /dev/null
+++ b/db/schema_migrations/20220126201752
@@ -0,0 +1 @@
+7731772dfac065a60c1626707913ddf6ff632bb69dd5ed6534e8d29e4e03c573 \ No newline at end of file
diff --git a/db/schema_migrations/20220126202654 b/db/schema_migrations/20220126202654
new file mode 100644
index 00000000000..341e2c6b8bf
--- /dev/null
+++ b/db/schema_migrations/20220126202654
@@ -0,0 +1 @@
+6067e4e22e49548496454b48171f8168f7d5bf626fedab4351e2a37a3f85731b \ No newline at end of file
diff --git a/db/schema_migrations/20220126203421 b/db/schema_migrations/20220126203421
new file mode 100644
index 00000000000..32469cd40ee
--- /dev/null
+++ b/db/schema_migrations/20220126203421
@@ -0,0 +1 @@
+07f837ddde21e36d1ca6a471dd96350d3020bd30204fca0e093983810c94e54d \ No newline at end of file
diff --git a/db/schema_migrations/20220126210021 b/db/schema_migrations/20220126210021
new file mode 100644
index 00000000000..edb9d9c779d
--- /dev/null
+++ b/db/schema_migrations/20220126210021
@@ -0,0 +1 @@
+fd7940bb6f077c91d7f9928f574443ba4bf33bb90cb702c0a2ecad14398ab1cc \ No newline at end of file
diff --git a/db/schema_migrations/20220126210022 b/db/schema_migrations/20220126210022
new file mode 100644
index 00000000000..32cb73ee3ee
--- /dev/null
+++ b/db/schema_migrations/20220126210022
@@ -0,0 +1 @@
+80a75bf72b40ee791bebd9ae97a793ce41fbd352841d83421525b6ad78e1c5e8 \ No newline at end of file
diff --git a/db/schema_migrations/20220126210657 b/db/schema_migrations/20220126210657
new file mode 100644
index 00000000000..a3301b46756
--- /dev/null
+++ b/db/schema_migrations/20220126210657
@@ -0,0 +1 @@
+853209f3babe2856481591790d9bb67145c4c0c919ed4d8365bb8d498e4f6b8e \ No newline at end of file
diff --git a/db/schema_migrations/20220127112243 b/db/schema_migrations/20220127112243
new file mode 100644
index 00000000000..2c591bdde58
--- /dev/null
+++ b/db/schema_migrations/20220127112243
@@ -0,0 +1 @@
+7707b9bcdcd7ec28af31b90355905eb8971c12a90c4334b0ae214e45fac9645a \ No newline at end of file
diff --git a/db/schema_migrations/20220127112412 b/db/schema_migrations/20220127112412
new file mode 100644
index 00000000000..af58ff48473
--- /dev/null
+++ b/db/schema_migrations/20220127112412
@@ -0,0 +1 @@
+350409be3f491b61a1d757dbd839b48d088339883e8e019d00ad90e6adc350e6 \ No newline at end of file
diff --git a/db/schema_migrations/20220127132200 b/db/schema_migrations/20220127132200
new file mode 100644
index 00000000000..8dc7ac4ddbd
--- /dev/null
+++ b/db/schema_migrations/20220127132200
@@ -0,0 +1 @@
+394f1fa34ccf9188f25102ac963829ebee07dddaf02f1d5958ec14d701fb6fe8 \ No newline at end of file
diff --git a/db/schema_migrations/20220127132201 b/db/schema_migrations/20220127132201
new file mode 100644
index 00000000000..f2c9cbbe38f
--- /dev/null
+++ b/db/schema_migrations/20220127132201
@@ -0,0 +1 @@
+f8ce7c183352ce08585eda83eb1e22c800b1b2044b93bc11858a74a8bd9a99d4 \ No newline at end of file
diff --git a/db/schema_migrations/20220128093756 b/db/schema_migrations/20220128093756
new file mode 100644
index 00000000000..fd24b6cd4cd
--- /dev/null
+++ b/db/schema_migrations/20220128093756
@@ -0,0 +1 @@
+787b1be4b69ef0eeb049ee6a3d7126dc75094b79fba18f469fffe78b16fce6a3 \ No newline at end of file
diff --git a/db/schema_migrations/20220128155251 b/db/schema_migrations/20220128155251
new file mode 100644
index 00000000000..11fa6807ed5
--- /dev/null
+++ b/db/schema_migrations/20220128155251
@@ -0,0 +1 @@
+0d121aeecdd6ace1516c2e9b84fefd47d963c4cbe22a0448728241d83da3742e \ No newline at end of file
diff --git a/db/schema_migrations/20220128155814 b/db/schema_migrations/20220128155814
new file mode 100644
index 00000000000..209b0874a84
--- /dev/null
+++ b/db/schema_migrations/20220128155814
@@ -0,0 +1 @@
+77cc8fc86f2c6a5ed017dde40dd4db796821a35e6ce4d8dcbe24b2cdaccbb5d9 \ No newline at end of file
diff --git a/db/schema_migrations/20220128194722 b/db/schema_migrations/20220128194722
new file mode 100644
index 00000000000..9c06f452c1e
--- /dev/null
+++ b/db/schema_migrations/20220128194722
@@ -0,0 +1 @@
+087338f0b438d2aa33bc22bd3973d818c5d1f40948525d95181751722158605b \ No newline at end of file
diff --git a/db/schema_migrations/20220131135725 b/db/schema_migrations/20220131135725
new file mode 100644
index 00000000000..d63b24d5d6c
--- /dev/null
+++ b/db/schema_migrations/20220131135725
@@ -0,0 +1 @@
+a0e9bb92512b9ddb3fd718e086b0fd116ec307be6acc5789a872b1d3004fdebd \ No newline at end of file
diff --git a/db/schema_migrations/20220131192643 b/db/schema_migrations/20220131192643
new file mode 100644
index 00000000000..e947bf0cfbe
--- /dev/null
+++ b/db/schema_migrations/20220131192643
@@ -0,0 +1 @@
+3b9068f109685dcfa8a0a1fda886cca3909d29cbc280cf70ed9f3d927def12ac \ No newline at end of file
diff --git a/db/schema_migrations/20220201034731 b/db/schema_migrations/20220201034731
new file mode 100644
index 00000000000..59e4fd59720
--- /dev/null
+++ b/db/schema_migrations/20220201034731
@@ -0,0 +1 @@
+873ff811d4f70c012785297ee8c07eb496994af69d5ae4b266e8f675c88daca4 \ No newline at end of file
diff --git a/db/schema_migrations/20220201141705 b/db/schema_migrations/20220201141705
new file mode 100644
index 00000000000..92835993156
--- /dev/null
+++ b/db/schema_migrations/20220201141705
@@ -0,0 +1 @@
+9eb0c4609fbec79370215d05a9a1faf4208b9dcc2bfeb861feeb7c9f354489ab \ No newline at end of file
diff --git a/db/schema_migrations/20220201173212 b/db/schema_migrations/20220201173212
new file mode 100644
index 00000000000..b07c8e371a5
--- /dev/null
+++ b/db/schema_migrations/20220201173212
@@ -0,0 +1 @@
+7a48d49d576d183198df370593642419da5707d8b018a23f541c448e2aa7ad65 \ No newline at end of file
diff --git a/db/schema_migrations/20220201193033 b/db/schema_migrations/20220201193033
new file mode 100644
index 00000000000..e40840c66fa
--- /dev/null
+++ b/db/schema_migrations/20220201193033
@@ -0,0 +1 @@
+92bbe74c6c3627dd26f709acd2a20f442212eab933f719be815701a3bc429539 \ No newline at end of file
diff --git a/db/schema_migrations/20220201205300 b/db/schema_migrations/20220201205300
new file mode 100644
index 00000000000..86f6dd234fd
--- /dev/null
+++ b/db/schema_migrations/20220201205300
@@ -0,0 +1 @@
+79a636f33f70327206356abd1793b73a5ef5e920a41662e35cbff5597b03a365 \ No newline at end of file
diff --git a/db/schema_migrations/20220202034409 b/db/schema_migrations/20220202034409
new file mode 100644
index 00000000000..4eb359f45e6
--- /dev/null
+++ b/db/schema_migrations/20220202034409
@@ -0,0 +1 @@
+0efe482aa626cf80912feaa1176837253b094fc434f273bee35b5fe3e8ce4243 \ No newline at end of file
diff --git a/db/schema_migrations/20220202105733 b/db/schema_migrations/20220202105733
new file mode 100644
index 00000000000..473b03d6210
--- /dev/null
+++ b/db/schema_migrations/20220202105733
@@ -0,0 +1 @@
+6f2919091a6998f2f18f8dbff3c968e68dc218ab0e51341164d1fc5b8abf72ae \ No newline at end of file
diff --git a/db/schema_migrations/20220202115350 b/db/schema_migrations/20220202115350
new file mode 100644
index 00000000000..9b8148ca2d1
--- /dev/null
+++ b/db/schema_migrations/20220202115350
@@ -0,0 +1 @@
+3bcc97592e8e329e39917deffae6619e69215930a688bebad2949f69155b53f9 \ No newline at end of file
diff --git a/db/schema_migrations/20220203123333 b/db/schema_migrations/20220203123333
new file mode 100644
index 00000000000..9cc146c4ed7
--- /dev/null
+++ b/db/schema_migrations/20220203123333
@@ -0,0 +1 @@
+87cccb30bb6f27a1acb0dd0cb905040e2a0291cefc5f26bb9a08c8be18034ca3 \ No newline at end of file
diff --git a/db/schema_migrations/20220203133652 b/db/schema_migrations/20220203133652
new file mode 100644
index 00000000000..7deda2292b4
--- /dev/null
+++ b/db/schema_migrations/20220203133652
@@ -0,0 +1 @@
+5642cf604a1aaf8bef6098a9918b582e0e336d79ca3b2a005cf90bb8eab0ca13 \ No newline at end of file
diff --git a/db/schema_migrations/20220204053655 b/db/schema_migrations/20220204053655
new file mode 100644
index 00000000000..e096dae0c07
--- /dev/null
+++ b/db/schema_migrations/20220204053655
@@ -0,0 +1 @@
+d6b7fa6e5be83aa67bb479604bf6ddb9d8caae82fc8ea1ab7f34d5c534174ecf \ No newline at end of file
diff --git a/db/schema_migrations/20220204154220 b/db/schema_migrations/20220204154220
new file mode 100644
index 00000000000..42da4e82258
--- /dev/null
+++ b/db/schema_migrations/20220204154220
@@ -0,0 +1 @@
+efecc3c6468d8a5036352f5b62e8d70de835d1beb4e45ba6d3906906d0317848 \ No newline at end of file
diff --git a/db/schema_migrations/20220207083129 b/db/schema_migrations/20220207083129
new file mode 100644
index 00000000000..25dca4578f4
--- /dev/null
+++ b/db/schema_migrations/20220207083129
@@ -0,0 +1 @@
+01cc0139097235991fa2caf8b780ccd1c3ce580647197418424ade83ce9be77e \ No newline at end of file
diff --git a/db/schema_migrations/20220208115439 b/db/schema_migrations/20220208115439
new file mode 100644
index 00000000000..72230321625
--- /dev/null
+++ b/db/schema_migrations/20220208115439
@@ -0,0 +1 @@
+dbe6760198b8fa068c30871a439298e56802867044a178baa6b8b009f8da13e6 \ No newline at end of file
diff --git a/db/schema_migrations/20220208170445 b/db/schema_migrations/20220208170445
new file mode 100644
index 00000000000..3a486a586a8
--- /dev/null
+++ b/db/schema_migrations/20220208170445
@@ -0,0 +1 @@
+e00dd618ca393596f3ff05b44b1a9a36183729a864a5cf4b8f1a262dfcdb932b \ No newline at end of file
diff --git a/db/schema_migrations/20220208171826 b/db/schema_migrations/20220208171826
new file mode 100644
index 00000000000..75ae0dcef61
--- /dev/null
+++ b/db/schema_migrations/20220208171826
@@ -0,0 +1 @@
+e48473172d7561fb7474e16e291e555843c0ec4543300b007f86cd4a5923db85 \ No newline at end of file
diff --git a/db/schema_migrations/20220209111007 b/db/schema_migrations/20220209111007
new file mode 100644
index 00000000000..f10e05b8918
--- /dev/null
+++ b/db/schema_migrations/20220209111007
@@ -0,0 +1 @@
+9462258bcbe45ab80f7ef5a02f8b8d5c0ed6ac69bf04b8934ae3dee2261ba458 \ No newline at end of file
diff --git a/db/schema_migrations/20220211214605 b/db/schema_migrations/20220211214605
new file mode 100644
index 00000000000..89dbee18ee7
--- /dev/null
+++ b/db/schema_migrations/20220211214605
@@ -0,0 +1 @@
+add5ee0b8e090ba740ce738f66ea4f741485a0c84728fecfa5b0488564d55536 \ No newline at end of file
diff --git a/db/schema_migrations/20220212120735 b/db/schema_migrations/20220212120735
new file mode 100644
index 00000000000..1ec5f9af681
--- /dev/null
+++ b/db/schema_migrations/20220212120735
@@ -0,0 +1 @@
+c075ee9d6efeae4b7a9b6e310f0c3d0bdd0ac6a58dc214427d4de9ae579db50d \ No newline at end of file
diff --git a/db/schema_migrations/20220213104531 b/db/schema_migrations/20220213104531
new file mode 100644
index 00000000000..72656d85fb0
--- /dev/null
+++ b/db/schema_migrations/20220213104531
@@ -0,0 +1 @@
+9ce8aa469b9469d25fbba52147e24c95f6242c2ab1e114df8baaf5a45268d2fd \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 8d0c7b3d693..aef55d04486 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -45,6 +45,39 @@ RETURN NULL;
END
$$;
+CREATE FUNCTION insert_or_update_vulnerability_reads() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+DECLARE
+ severity smallint;
+ state smallint;
+ report_type smallint;
+ resolved_on_default_branch boolean;
+BEGIN
+ IF (NEW.vulnerability_id IS NULL AND (TG_OP = 'INSERT' OR TG_OP = 'UPDATE')) THEN
+ RETURN NULL;
+ END IF;
+
+ IF (TG_OP = 'UPDATE' AND OLD.vulnerability_id IS NOT NULL AND NEW.vulnerability_id IS NOT NULL) THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT
+ vulnerabilities.severity, vulnerabilities.state, vulnerabilities.report_type, vulnerabilities.resolved_on_default_branch
+ INTO
+ severity, state, report_type, resolved_on_default_branch
+ FROM
+ vulnerabilities
+ WHERE
+ vulnerabilities.id = NEW.vulnerability_id;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id)
+ VALUES (NEW.vulnerability_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id')
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+END
+$$;
+
CREATE FUNCTION insert_projects_sync_event() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -60,10 +93,7 @@ CREATE FUNCTION integrations_set_type_new() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
-UPDATE integrations SET type_new = regexp_replace(NEW.type, '\A(.+)Service\Z', 'Integrations::\1')
-WHERE integrations.id = NEW.id;
-RETURN NULL;
-
+UPDATE integrations SET type_new = COALESCE(NEW.type_new, regexp_replace(NEW.type, '\A(.+)Service\Z', 'Integrations::\1')) , type = COALESCE(NEW.type, regexp_replace(NEW.type_new, '\AIntegrations::(.+)\Z', '\1Service')) WHERE integrations.id = NEW.id; RETURN NULL;
END
$$;
@@ -107,6 +137,83 @@ RETURN NULL;
END
$$;
+CREATE FUNCTION set_has_issues_on_vulnerability_reads() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+UPDATE
+ vulnerability_reads
+SET
+ has_issues = true
+WHERE
+ vulnerability_id = NEW.vulnerability_id AND has_issues IS FALSE;
+RETURN NULL;
+
+END
+$$;
+
+CREATE FUNCTION unset_has_issues_on_vulnerability_reads() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+DECLARE
+ has_issue_links integer;
+BEGIN
+ PERFORM 1
+ FROM
+ vulnerability_reads
+ WHERE
+ vulnerability_id = OLD.vulnerability_id
+ FOR UPDATE;
+
+ SELECT 1 INTO has_issue_links FROM vulnerability_issue_links WHERE vulnerability_id = OLD.vulnerability_id LIMIT 1;
+
+ IF (has_issue_links = 1) THEN
+ RETURN NULL;
+ END IF;
+
+ UPDATE
+ vulnerability_reads
+ SET
+ has_issues = false
+ WHERE
+ vulnerability_id = OLD.vulnerability_id;
+
+ RETURN NULL;
+END
+$$;
+
+CREATE FUNCTION update_location_from_vulnerability_occurrences() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+UPDATE
+ vulnerability_reads
+SET
+ location_image = NEW.location->>'image',
+ cluster_agent_id = NEW.location->'kubernetes_resource'->>'agent_id'
+WHERE
+ vulnerability_id = NEW.vulnerability_id;
+RETURN NULL;
+
+END
+$$;
+
+CREATE FUNCTION update_vulnerability_reads_from_vulnerability() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+UPDATE
+ vulnerability_reads
+SET
+ severity = NEW.severity,
+ state = NEW.state,
+ resolved_on_default_branch = NEW.resolved_on_default_branch
+WHERE vulnerability_id = NEW.id;
+RETURN NULL;
+
+END
+$$;
+
CREATE TABLE audit_events (
id bigint NOT NULL,
author_id integer NOT NULL,
@@ -127,6 +234,20 @@ CREATE TABLE audit_events (
)
PARTITION BY RANGE (created_at);
+CREATE TABLE batched_background_migration_job_transition_logs (
+ id bigint NOT NULL,
+ batched_background_migration_job_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ previous_status smallint NOT NULL,
+ next_status smallint NOT NULL,
+ exception_class text,
+ exception_message text,
+ CONSTRAINT check_50e580811a CHECK ((char_length(exception_message) <= 1000)),
+ CONSTRAINT check_76e202c37a CHECK ((char_length(exception_class) <= 100))
+)
+PARTITION BY RANGE (created_at);
+
CREATE TABLE incident_management_pending_alert_escalations (
id bigint NOT NULL,
rule_id bigint NOT NULL,
@@ -155,6 +276,7 @@ CREATE TABLE loose_foreign_keys_deleted_records (
created_at timestamp with time zone DEFAULT now() NOT NULL,
fully_qualified_table_name text NOT NULL,
consume_after timestamp with time zone DEFAULT now(),
+ cleanup_attempts smallint DEFAULT 0,
CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
)
PARTITION BY LIST (partition);
@@ -9792,6 +9914,29 @@ CREATE SEQUENCE alert_management_alert_assignees_id_seq
ALTER SEQUENCE alert_management_alert_assignees_id_seq OWNED BY alert_management_alert_assignees.id;
+CREATE TABLE alert_management_alert_metric_images (
+ id bigint NOT NULL,
+ alert_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ file_store smallint,
+ file text NOT NULL,
+ url text,
+ url_text text,
+ CONSTRAINT check_2587666252 CHECK ((char_length(url_text) <= 128)),
+ CONSTRAINT check_4d811d9007 CHECK ((char_length(url) <= 255)),
+ CONSTRAINT check_70fafae519 CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE alert_management_alert_metric_images_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE alert_management_alert_metric_images_id_seq OWNED BY alert_management_alert_metric_images.id;
+
CREATE TABLE alert_management_alert_user_mentions (
id bigint NOT NULL,
alert_management_alert_id bigint NOT NULL,
@@ -10493,6 +10638,10 @@ CREATE TABLE application_settings (
runner_token_expiration_interval integer,
group_runner_token_expiration_interval integer,
project_runner_token_expiration_interval integer,
+ ecdsa_sk_key_restriction integer DEFAULT 0 NOT NULL,
+ ed25519_sk_key_restriction integer DEFAULT 0 NOT NULL,
+ users_get_by_id_limit integer DEFAULT 300 NOT NULL,
+ users_get_by_id_limit_allowlist text[] DEFAULT '{}'::text[] 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_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
@@ -10777,7 +10926,9 @@ CREATE TABLE audit_events_external_audit_event_destinations (
destination_url text NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- CONSTRAINT check_2feafb9daf CHECK ((char_length(destination_url) <= 255))
+ verification_token text,
+ CONSTRAINT check_2feafb9daf CHECK ((char_length(destination_url) <= 255)),
+ CONSTRAINT check_8ec80a7d06 CHECK ((char_length(verification_token) <= 24))
);
CREATE SEQUENCE audit_events_external_audit_event_destinations_id_seq
@@ -10894,6 +11045,15 @@ CREATE TABLE banned_users (
user_id bigint NOT NULL
);
+CREATE SEQUENCE batched_background_migration_job_transition_logs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE batched_background_migration_job_transition_logs_id_seq OWNED BY batched_background_migration_job_transition_logs.id;
+
CREATE TABLE batched_background_migration_jobs (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -10937,6 +11097,7 @@ CREATE TABLE batched_background_migrations (
job_arguments jsonb DEFAULT '"[]"'::jsonb NOT NULL,
total_tuple_count bigint,
pause_ms integer DEFAULT 100 NOT NULL,
+ max_batch_size integer,
CONSTRAINT check_5bb0382d6f CHECK ((char_length(column_name) <= 63)),
CONSTRAINT check_6b6a06254a CHECK ((char_length(table_name) <= 63)),
CONSTRAINT check_batch_size_in_range CHECK ((batch_size >= sub_batch_size)),
@@ -11702,6 +11863,27 @@ CREATE SEQUENCE ci_instance_variables_id_seq
ALTER SEQUENCE ci_instance_variables_id_seq OWNED BY ci_instance_variables.id;
+CREATE TABLE ci_job_artifact_states (
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ job_artifact_id bigint NOT NULL,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_df832b66ea CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE ci_job_artifact_states_job_artifact_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_job_artifact_states_job_artifact_id_seq OWNED BY ci_job_artifact_states.job_artifact_id;
+
CREATE TABLE ci_job_artifacts (
project_id integer NOT NULL,
file_type integer NOT NULL,
@@ -12193,6 +12375,7 @@ CREATE TABLE ci_runners (
config jsonb DEFAULT '{}'::jsonb NOT NULL,
executor_type smallint,
maintainer_note text,
+ token_expires_at timestamp with time zone,
CONSTRAINT check_56f5ea8804 CHECK ((char_length(maintainer_note) <= 255))
);
@@ -13249,6 +13432,7 @@ CREATE TABLE dast_site_profiles (
auth_password_field text,
auth_username text,
target_type smallint DEFAULT 0 NOT NULL,
+ scan_method smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_5203110fee CHECK ((char_length(auth_username_field) <= 255)),
CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_c329dffdba CHECK ((char_length(auth_password_field) <= 255)),
@@ -13687,7 +13871,9 @@ CREATE TABLE draft_notes (
"position" text,
original_position text,
change_position text,
- commit_id bytea
+ commit_id bytea,
+ line_code text,
+ CONSTRAINT check_c497a94a0e CHECK ((char_length(line_code) <= 255))
);
CREATE SEQUENCE draft_notes_id_seq
@@ -15350,6 +15536,8 @@ CREATE TABLE issuable_metric_images (
file_store smallint,
file text NOT NULL,
url text,
+ url_text text,
+ CONSTRAINT check_3bc6d47661 CHECK ((char_length(url_text) <= 128)),
CONSTRAINT check_5b3011e234 CHECK ((char_length(url) <= 255)),
CONSTRAINT check_7ed527062f CHECK ((char_length(file) <= 255))
);
@@ -16347,7 +16535,8 @@ CREATE TABLE merge_requests_compliance_violations (
id bigint NOT NULL,
violating_user_id bigint NOT NULL,
merge_request_id bigint NOT NULL,
- reason smallint NOT NULL
+ reason smallint NOT NULL,
+ severity_level smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE merge_requests_compliance_violations_id_seq
@@ -16511,7 +16700,8 @@ CREATE TABLE namespace_root_storage_statistics (
packages_size bigint DEFAULT 0 NOT NULL,
snippets_size bigint DEFAULT 0 NOT NULL,
pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
- uploads_size bigint DEFAULT 0 NOT NULL
+ uploads_size bigint DEFAULT 0 NOT NULL,
+ dependency_proxy_size bigint DEFAULT 0 NOT NULL
);
CREATE TABLE namespace_settings (
@@ -16541,7 +16731,8 @@ CREATE TABLE namespace_statistics (
shared_runners_seconds integer DEFAULT 0 NOT NULL,
shared_runners_seconds_last_reset timestamp without time zone,
storage_size bigint DEFAULT 0 NOT NULL,
- wiki_size bigint DEFAULT 0 NOT NULL
+ wiki_size bigint DEFAULT 0 NOT NULL,
+ dependency_proxy_size bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE namespace_statistics_id_seq
@@ -18551,6 +18742,8 @@ CREATE TABLE project_settings (
merge_commit_template text,
has_shimo boolean DEFAULT false NOT NULL,
squash_commit_template text,
+ show_diff_preview_in_email boolean DEFAULT true NOT NULL,
+ legacy_open_source_license_available boolean DEFAULT true NOT NULL,
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
CONSTRAINT check_b09644994b CHECK ((char_length(squash_commit_template) <= 500)),
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)),
@@ -19396,7 +19589,6 @@ CREATE TABLE security_findings (
confidence smallint NOT NULL,
project_fingerprint text,
deduplicated boolean DEFAULT false NOT NULL,
- "position" integer,
uuid uuid,
overridden_uuid uuid,
CONSTRAINT check_b9508c6df8 CHECK ((char_length(project_fingerprint) <= 40))
@@ -20123,6 +20315,7 @@ CREATE TABLE topics (
avatar text,
description text,
total_projects_count bigint DEFAULT 0 NOT NULL,
+ non_private_projects_count bigint DEFAULT 0 NOT NULL,
CONSTRAINT check_26753fb43a CHECK ((char_length(avatar) <= 255)),
CONSTRAINT check_5d1a07c8c8 CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_7a90d4c757 CHECK ((char_length(name) <= 255))
@@ -20761,9 +20954,7 @@ CREATE TABLE vulnerability_finding_evidences (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
vulnerability_occurrence_id bigint NOT NULL,
- summary text,
- data jsonb DEFAULT '{}'::jsonb NOT NULL,
- CONSTRAINT check_5773b236fb CHECK ((char_length(summary) <= 8000000))
+ data jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE vulnerability_finding_evidences_id_seq
@@ -21347,6 +21538,8 @@ ALTER TABLE ONLY agent_project_authorizations ALTER COLUMN id SET DEFAULT nextva
ALTER TABLE ONLY alert_management_alert_assignees ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_assignees_id_seq'::regclass);
+ALTER TABLE ONLY alert_management_alert_metric_images ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_metric_images_id_seq'::regclass);
+
ALTER TABLE ONLY alert_management_alert_user_mentions ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_user_mentions_id_seq'::regclass);
ALTER TABLE ONLY alert_management_alerts ALTER COLUMN id SET DEFAULT nextval('alert_management_alerts_id_seq'::regclass);
@@ -21413,6 +21606,8 @@ ALTER TABLE ONLY background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('
ALTER TABLE ONLY badges ALTER COLUMN id SET DEFAULT nextval('badges_id_seq'::regclass);
+ALTER TABLE ONLY batched_background_migration_job_transition_logs ALTER COLUMN id SET DEFAULT nextval('batched_background_migration_job_transition_logs_id_seq'::regclass);
+
ALTER TABLE ONLY batched_background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('batched_background_migration_jobs_id_seq'::regclass);
ALTER TABLE ONLY batched_background_migrations ALTER COLUMN id SET DEFAULT nextval('batched_background_migrations_id_seq'::regclass);
@@ -21487,6 +21682,8 @@ ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_grou
ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_job_artifact_states ALTER COLUMN job_artifact_id SET DEFAULT nextval('ci_job_artifact_states_job_artifact_id_seq'::regclass);
+
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);
@@ -22715,6 +22912,9 @@ ALTER TABLE ONLY agent_project_authorizations
ALTER TABLE ONLY alert_management_alert_assignees
ADD CONSTRAINT alert_management_alert_assignees_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY alert_management_alert_metric_images
+ ADD CONSTRAINT alert_management_alert_metric_images_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY alert_management_alert_user_mentions
ADD CONSTRAINT alert_management_alert_user_mentions_pkey PRIMARY KEY (id);
@@ -22829,6 +23029,9 @@ ALTER TABLE ONLY badges
ALTER TABLE ONLY banned_users
ADD CONSTRAINT banned_users_pkey PRIMARY KEY (user_id);
+ALTER TABLE ONLY batched_background_migration_job_transition_logs
+ ADD CONSTRAINT batched_background_migration_job_transition_logs_pkey PRIMARY KEY (id, created_at);
+
ALTER TABLE ONLY batched_background_migration_jobs
ADD CONSTRAINT batched_background_migration_jobs_pkey PRIMARY KEY (id);
@@ -22958,6 +23161,9 @@ ALTER TABLE ONLY ci_group_variables
ALTER TABLE ONLY ci_instance_variables
ADD CONSTRAINT ci_instance_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_job_artifact_states
+ ADD CONSTRAINT ci_job_artifact_states_pkey PRIMARY KEY (job_artifact_id);
+
ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
@@ -25071,6 +25277,8 @@ CREATE UNIQUE INDEX finding_link_url_idx ON vulnerability_finding_links USING bt
CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
+CREATE INDEX i_batched_background_migration_job_transition_logs_on_job_id ON ONLY batched_background_migration_job_transition_logs USING btree (batched_background_migration_job_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);
@@ -25089,6 +25297,12 @@ CREATE INDEX idx_container_exp_policies_on_project_id_next_run_at_enabled ON con
CREATE INDEX idx_container_repos_on_exp_cleanup_status_project_id_start_date ON container_repositories USING btree (expiration_policy_cleanup_status, project_id, expiration_policy_started_at);
+CREATE INDEX idx_container_repos_on_import_started_at_when_importing ON container_repositories USING btree (migration_import_started_at) WHERE (migration_state = 'importing'::text);
+
+CREATE INDEX idx_container_repos_on_pre_import_done_at_when_pre_import_done ON container_repositories USING btree (migration_pre_import_done_at) WHERE (migration_state = 'pre_import_done'::text);
+
+CREATE INDEX idx_container_repos_on_pre_import_started_at_when_pre_importing ON container_repositories USING btree (migration_pre_import_started_at) WHERE (migration_state = 'pre_importing'::text);
+
CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
CREATE INDEX idx_devops_adoption_segments_namespace_end_time ON analytics_devops_adoption_snapshots USING btree (namespace_id, end_time);
@@ -25207,6 +25421,8 @@ CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan
CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
+CREATE INDEX idx_user_details_on_provisioned_by_group_id_user_id ON user_details USING btree (provisioned_by_group_id, user_id);
+
CREATE UNIQUE INDEX idx_vuln_signatures_on_occurrences_id_and_signature_sha ON vulnerability_finding_signatures USING btree (finding_id, signature_sha);
CREATE UNIQUE INDEX idx_vuln_signatures_uniqueness_signature_sha ON vulnerability_finding_signatures USING btree (finding_id, algorithm_type, signature_sha);
@@ -25245,6 +25461,8 @@ CREATE INDEX index_alert_assignees_on_alert_id ON alert_management_alert_assigne
CREATE UNIQUE INDEX index_alert_assignees_on_user_id_and_alert_id ON alert_management_alert_assignees USING btree (user_id, alert_id);
+CREATE INDEX index_alert_management_alert_metric_images_on_alert_id ON alert_management_alert_metric_images USING btree (alert_id);
+
CREATE INDEX index_alert_management_alerts_on_domain ON alert_management_alerts USING btree (domain);
CREATE INDEX index_alert_management_alerts_on_environment_id ON alert_management_alerts USING btree (environment_id) WHERE (environment_id IS NOT NULL);
@@ -25363,6 +25581,8 @@ CREATE INDEX index_approvers_on_user_id ON approvers USING btree (user_id);
CREATE UNIQUE INDEX index_atlassian_identities_on_extern_uid ON atlassian_identities USING btree (extern_uid);
+CREATE UNIQUE INDEX index_audit_events_external_audit_on_verification_token ON audit_events_external_audit_event_destinations USING btree (verification_token);
+
CREATE INDEX index_authentication_events_on_provider ON authentication_events USING btree (provider);
CREATE INDEX index_authentication_events_on_provider_user_id_created_at ON authentication_events USING btree (provider, user_id, created_at) WHERE (result = 1);
@@ -25573,6 +25793,8 @@ CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key_and_environment
CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables USING btree (key);
+CREATE INDEX index_ci_job_artifact_states_on_job_artifact_id ON ci_job_artifact_states USING btree (job_artifact_id);
+
CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18);
CREATE INDEX index_ci_job_artifacts_id_for_terraform_reports ON ci_job_artifacts USING btree (id) WHERE (file_type = 18);
@@ -25713,8 +25935,6 @@ CREATE UNIQUE INDEX index_ci_runner_namespaces_on_runner_id_and_namespace_id ON
CREATE INDEX index_ci_runner_projects_on_project_id ON ci_runner_projects USING btree (project_id);
-CREATE INDEX index_ci_runner_projects_on_runner_id ON ci_runner_projects USING btree (runner_id);
-
CREATE INDEX index_ci_runners_on_active ON ci_runners USING btree (active, id);
CREATE INDEX index_ci_runners_on_contacted_at_and_id_desc ON ci_runners USING btree (contacted_at, id DESC);
@@ -25739,6 +25959,10 @@ 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 INDEX index_ci_runners_on_token_expires_at_and_id_desc ON ci_runners USING btree (token_expires_at, id DESC);
+
+CREATE INDEX index_ci_runners_on_token_expires_at_desc_and_id_desc ON ci_runners USING btree (token_expires_at DESC, id DESC);
+
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);
@@ -25791,8 +26015,6 @@ CREATE INDEX index_ci_variables_on_key ON ci_variables USING btree (key);
CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON ci_variables USING btree (project_id, key, environment_scope);
-CREATE INDEX index_cluster_agent_tokens_on_agent_id_and_last_used_at ON cluster_agent_tokens USING btree (agent_id, last_used_at DESC NULLS LAST);
-
CREATE INDEX index_cluster_agent_tokens_on_agent_id_status_last_used_at ON cluster_agent_tokens USING btree (agent_id, status, last_used_at DESC NULLS LAST);
CREATE INDEX index_cluster_agent_tokens_on_created_by_user_id ON cluster_agent_tokens USING btree (created_by_user_id);
@@ -25849,8 +26071,6 @@ CREATE INDEX index_clusters_integration_elasticstack_enabled ON clusters_integra
CREATE INDEX index_clusters_integration_prometheus_enabled ON clusters_integration_prometheus USING btree (enabled, created_at, cluster_id);
-CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_id ON clusters_kubernetes_namespaces USING btree (cluster_id);
-
CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_project_id ON clusters_kubernetes_namespaces USING btree (cluster_project_id);
CREATE INDEX index_clusters_kubernetes_namespaces_on_environment_id ON clusters_kubernetes_namespaces USING btree (environment_id);
@@ -25873,6 +26093,10 @@ CREATE INDEX index_composer_cache_files_where_namespace_id_is_null ON packages_c
CREATE INDEX index_container_expiration_policies_on_next_run_at_and_enabled ON container_expiration_policies USING btree (next_run_at, enabled);
+CREATE INDEX index_container_repositories_on_greatest_done_at ON container_repositories USING btree (GREATEST(migration_pre_import_done_at, migration_import_done_at, migration_aborted_at)) WHERE (migration_state = ANY (ARRAY['import_done'::text, 'pre_import_done'::text, 'import_aborted'::text]));
+
+CREATE INDEX index_container_repositories_on_migration_state_import_done_at ON container_repositories USING btree (migration_state, migration_import_done_at);
+
CREATE INDEX index_container_repositories_on_project_id ON container_repositories USING btree (project_id);
CREATE INDEX index_container_repositories_on_project_id_and_id ON container_repositories USING btree (project_id, id);
@@ -26081,8 +26305,6 @@ CREATE INDEX index_emails_on_user_id ON emails USING btree (user_id);
CREATE INDEX index_enabled_clusters_on_id ON clusters USING btree (id) WHERE (enabled = true);
-CREATE INDEX index_environments_on_auto_stop_at ON environments USING btree (auto_stop_at) WHERE (auto_stop_at IS NOT NULL);
-
CREATE INDEX index_environments_on_name_varchar_pattern_ops ON environments USING btree (name varchar_pattern_ops);
CREATE UNIQUE INDEX index_environments_on_project_id_and_name ON environments USING btree (project_id, name);
@@ -26101,8 +26323,6 @@ CREATE UNIQUE INDEX index_epic_board_list_preferences_on_user_and_list ON boards
CREATE UNIQUE INDEX index_epic_board_recent_visits_on_user_group_and_board ON boards_epic_board_recent_visits USING btree (user_id, group_id, epic_board_id);
-CREATE INDEX index_epic_issues_on_epic_id ON epic_issues USING btree (epic_id);
-
CREATE INDEX index_epic_issues_on_epic_id_and_issue_id ON epic_issues USING btree (epic_id, issue_id);
CREATE UNIQUE INDEX index_epic_issues_on_issue_id ON epic_issues USING btree (issue_id);
@@ -26445,8 +26665,12 @@ CREATE INDEX index_insights_on_project_id ON insights USING btree (project_id);
CREATE INDEX index_integrations_on_inherit_from_id ON integrations USING btree (inherit_from_id);
+CREATE INDEX index_integrations_on_project_and_type_new_where_inherit_null ON integrations USING btree (project_id, type_new) WHERE (inherit_from_id IS NULL);
+
CREATE INDEX index_integrations_on_project_and_type_where_inherit_null ON integrations USING btree (project_id, type) WHERE (inherit_from_id IS NULL);
+CREATE UNIQUE INDEX index_integrations_on_project_id_and_type_new_unique ON integrations USING btree (project_id, type_new);
+
CREATE UNIQUE INDEX index_integrations_on_project_id_and_type_unique ON integrations USING btree (project_id, type);
CREATE INDEX index_integrations_on_template ON integrations USING btree (template);
@@ -26459,8 +26683,18 @@ CREATE UNIQUE INDEX index_integrations_on_type_and_template_partial ON integrati
CREATE INDEX index_integrations_on_type_id_when_active_and_project_id_not_nu ON integrations USING btree (type, id) WHERE ((active = true) AND (project_id IS NOT NULL));
+CREATE INDEX index_integrations_on_type_new ON integrations USING btree (type_new);
+
+CREATE INDEX index_integrations_on_type_new_and_instance_partial ON integrations USING btree (type_new, instance) WHERE (instance = true);
+
+CREATE INDEX index_integrations_on_type_new_and_template_partial ON integrations USING btree (type_new, template) WHERE (template = true);
+
+CREATE INDEX index_integrations_on_type_new_id_when_active_and_has_project ON integrations USING btree (type_new, id) WHERE ((active = true) AND (project_id IS NOT NULL));
+
CREATE UNIQUE INDEX index_integrations_on_unique_group_id_and_type ON integrations USING btree (group_id, type);
+CREATE INDEX index_integrations_on_unique_group_id_and_type_new ON integrations USING btree (group_id, type_new);
+
CREATE INDEX index_internal_ids_on_namespace_id ON internal_ids USING btree (namespace_id);
CREATE INDEX index_internal_ids_on_project_id ON internal_ids USING btree (project_id);
@@ -26563,6 +26797,14 @@ CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id)
CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
+CREATE INDEX index_job_artifact_states_failed_verification ON ci_job_artifact_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_job_artifact_states_needs_verification ON ci_job_artifact_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX index_job_artifact_states_on_verification_state ON ci_job_artifact_states USING btree (verification_state);
+
+CREATE INDEX index_job_artifact_states_pending_verification ON ci_job_artifact_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
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);
@@ -26935,6 +27177,10 @@ CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON a
CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
+CREATE INDEX index_on_merge_request_assignees_state ON merge_request_assignees USING btree (state) WHERE (state = 2);
+
+CREATE INDEX index_on_merge_request_reviewers_state ON merge_request_reviewers USING btree (state) WHERE (state = 2);
+
CREATE INDEX index_on_merge_requests_for_latest_diffs ON merge_requests USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id);
COMMENT ON INDEX index_on_merge_requests_for_latest_diffs IS 'Index used to efficiently obtain the oldest merge request for a commit SHA';
@@ -27555,8 +27801,6 @@ CREATE INDEX index_security_findings_on_project_fingerprint ON security_findings
CREATE INDEX index_security_findings_on_scan_id_and_deduplicated ON security_findings USING btree (scan_id, deduplicated);
-CREATE UNIQUE INDEX index_security_findings_on_scan_id_and_position ON security_findings USING btree (scan_id, "position");
-
CREATE INDEX index_security_findings_on_scanner_id ON security_findings USING btree (scanner_id);
CREATE INDEX index_security_findings_on_severity ON security_findings USING btree (severity);
@@ -27779,6 +28023,8 @@ CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_plaintext_token ON token_with
CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_token ON token_with_ivs USING btree (hashed_token);
+CREATE INDEX index_topics_non_private_projects_count ON topics USING btree (non_private_projects_count DESC, id);
+
CREATE UNIQUE INDEX index_topics_on_name ON topics USING btree (name);
CREATE INDEX index_topics_on_name_trigram ON topics USING gin (name gin_trgm_ops);
@@ -27793,6 +28039,8 @@ CREATE INDEX index_u2f_registrations_on_user_id ON u2f_registrations USING btree
CREATE UNIQUE INDEX index_uniq_im_issuable_escalation_statuses_on_issue_id ON incident_management_issuable_escalation_statuses USING btree (issue_id);
+CREATE UNIQUE INDEX index_unique_ci_runner_projects_on_runner_id_and_project_id ON ci_runner_projects USING btree (runner_id, project_id);
+
CREATE UNIQUE INDEX index_unique_issue_metrics_issue_id ON issue_metrics USING btree (issue_id);
CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING btree (failed_at DESC);
@@ -27843,8 +28091,6 @@ CREATE UNIQUE INDEX index_user_details_on_phone ON user_details USING btree (pho
COMMENT ON INDEX index_user_details_on_phone IS 'JiHu-specific index';
-CREATE INDEX index_user_details_on_provisioned_by_group_id ON user_details USING btree (provisioned_by_group_id);
-
CREATE UNIQUE INDEX index_user_details_on_user_id ON user_details USING btree (user_id);
CREATE INDEX index_user_group_callouts_on_group_id ON user_group_callouts USING btree (group_id);
@@ -27949,6 +28195,10 @@ CREATE INDEX index_vulnerabilities_on_last_edited_by_id ON vulnerabilities USING
CREATE INDEX index_vulnerabilities_on_milestone_id ON vulnerabilities USING btree (milestone_id);
+CREATE INDEX index_vulnerabilities_on_project_id_and_id ON vulnerabilities USING btree (project_id, id);
+
+CREATE INDEX index_vulnerabilities_on_project_id_and_id_active_cis ON vulnerabilities USING btree (project_id, id) WHERE ((report_type = 7) AND (state = ANY (ARRAY[1, 4])));
+
CREATE INDEX index_vulnerabilities_on_project_id_and_state_and_severity ON vulnerabilities USING btree (project_id, state, severity);
CREATE INDEX index_vulnerabilities_on_resolved_by_id ON vulnerabilities USING btree (resolved_by_id);
@@ -28027,8 +28277,6 @@ CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerabi
CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id);
-CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);
-
CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON vulnerability_occurrences USING btree (uuid);
CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerability_occurrences USING btree (vulnerability_id);
@@ -28155,10 +28403,16 @@ CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, t
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
-CREATE INDEX tmp_idx_deduplicate_vulnerability_occurrences ON vulnerability_occurrences USING btree (project_id, report_type, location_fingerprint, primary_identifier_id, id);
+CREATE INDEX tmp_gitlab_subscriptions_max_seats_used_migration ON gitlab_subscriptions USING btree (id) WHERE ((start_date >= '2021-08-02'::date) AND (start_date <= '2021-11-20'::date) AND (max_seats_used <> 0) AND (max_seats_used > seats_in_use) AND (max_seats_used > seats));
+
+CREATE INDEX tmp_gitlab_subscriptions_max_seats_used_migration_2 ON gitlab_subscriptions USING btree (id) WHERE ((start_date < '2021-08-02'::date) AND (max_seats_used <> 0) AND (max_seats_used > seats_in_use) AND (max_seats_used > seats));
CREATE INDEX tmp_idx_vulnerability_occurrences_on_id_where_report_type_7_99 ON vulnerability_occurrences USING btree (id) WHERE (report_type = ANY (ARRAY[7, 99]));
+CREATE INDEX tmp_index_container_repositories_on_id_migration_state ON container_repositories USING btree (id, migration_state);
+
+CREATE INDEX tmp_index_for_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Namespace'::text));
+
CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
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[]));
@@ -29125,6 +29379,8 @@ CREATE TRIGGER trigger_has_external_wiki_on_type_new_updated AFTER UPDATE OF typ
CREATE TRIGGER trigger_has_external_wiki_on_update AFTER UPDATE ON integrations FOR EACH ROW WHEN (((new.type_new = 'Integrations::ExternalWiki'::text) AND (old.active <> new.active) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_wiki();
+CREATE TRIGGER trigger_insert_or_update_vulnerability_reads_from_occurrences AFTER INSERT OR UPDATE ON vulnerability_occurrences FOR EACH ROW EXECUTE FUNCTION insert_or_update_vulnerability_reads();
+
CREATE TRIGGER trigger_namespaces_parent_id_on_insert AFTER INSERT ON namespaces FOR EACH ROW EXECUTE FUNCTION insert_namespaces_sync_event();
CREATE TRIGGER trigger_namespaces_parent_id_on_update AFTER UPDATE ON namespaces FOR EACH ROW WHEN ((old.parent_id IS DISTINCT FROM new.parent_id)) EXECUTE FUNCTION insert_namespaces_sync_event();
@@ -29135,6 +29391,14 @@ CREATE TRIGGER trigger_projects_parent_id_on_update AFTER UPDATE ON projects FOR
CREATE TRIGGER trigger_type_new_on_insert AFTER INSERT ON integrations FOR EACH ROW EXECUTE FUNCTION integrations_set_type_new();
+CREATE TRIGGER trigger_update_has_issues_on_vulnerability_issue_links_delete AFTER DELETE ON vulnerability_issue_links FOR EACH ROW EXECUTE FUNCTION unset_has_issues_on_vulnerability_reads();
+
+CREATE TRIGGER trigger_update_has_issues_on_vulnerability_issue_links_update AFTER INSERT ON vulnerability_issue_links FOR EACH ROW EXECUTE FUNCTION set_has_issues_on_vulnerability_reads();
+
+CREATE TRIGGER trigger_update_location_on_vulnerability_occurrences_update AFTER UPDATE ON vulnerability_occurrences FOR EACH ROW WHEN (((new.report_type = ANY (ARRAY[2, 7])) AND (((old.location ->> 'image'::text) IS DISTINCT FROM (new.location ->> 'image'::text)) OR (((old.location -> 'kubernetes_resource'::text) ->> 'agent_id'::text) IS DISTINCT FROM ((new.location -> 'kubernetes_resource'::text) ->> 'agent_id'::text))))) EXECUTE FUNCTION update_location_from_vulnerability_occurrences();
+
+CREATE TRIGGER trigger_update_vulnerability_reads_on_vulnerability_update AFTER UPDATE ON vulnerabilities FOR EACH ROW WHEN (((old.severity IS DISTINCT FROM new.severity) OR (old.state IS DISTINCT FROM new.state) OR (old.resolved_on_default_branch IS DISTINCT FROM new.resolved_on_default_branch))) EXECUTE FUNCTION update_vulnerability_reads_from_vulnerability();
+
CREATE TRIGGER users_loose_fk_trigger AFTER DELETE ON users REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
ALTER TABLE ONLY chat_names
@@ -29236,9 +29500,6 @@ ALTER TABLE ONLY agent_project_authorizations
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_1d37cddf91 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER TABLE ONLY ci_sources_pipelines
- ADD CONSTRAINT fk_1e53c97c0a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_1e9a074a35 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -29260,9 +29521,6 @@ ALTER TABLE ONLY users_star_projects
ALTER TABLE ONLY alert_management_alerts
ADD CONSTRAINT fk_2358b75436 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
-ALTER TABLE ONLY ci_stages
- ADD CONSTRAINT fk_2360681d1d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY import_failures
ADD CONSTRAINT fk_24b824da43 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -29371,9 +29629,6 @@ ALTER TABLE ONLY remote_mirrors
ALTER TABLE ONLY incident_management_timeline_events
ADD CONSTRAINT fk_4432fc4d78 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_runner_projects
- ADD CONSTRAINT fk_4478a6f1e4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_45054f9c45 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -29392,9 +29647,6 @@ ALTER TABLE ONLY alert_management_alerts
ALTER TABLE ONLY path_locks
ADD CONSTRAINT fk_5265c98f24 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY dast_site_profiles_pipelines
- ADD CONSTRAINT fk_53849b0ad5 FOREIGN KEY (ci_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY clusters_applications_prometheus
ADD CONSTRAINT fk_557e773639 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
@@ -29548,9 +29800,6 @@ ALTER TABLE ONLY merge_request_diffs
ALTER TABLE ONLY requirements
ADD CONSTRAINT fk_85044baef0 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_pipelines
- ADD CONSTRAINT fk_86635dbd80 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_86c84214ec FOREIGN KEY (repository_renamed_event_id) REFERENCES geo_repository_renamed_events(id) ON DELETE CASCADE;
@@ -29584,9 +29833,6 @@ ALTER TABLE ONLY releases
ALTER TABLE ONLY protected_tags
ADD CONSTRAINT fk_8e4af87648 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_pipeline_schedules
- ADD CONSTRAINT fk_8ead60fcc4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_91d1f47b13 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -29653,9 +29899,6 @@ ALTER TABLE ONLY issues
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_a2141b1522 FOREIGN KEY (auto_canceled_by_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY ci_pipelines
- ADD CONSTRAINT fk_a23be95014 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY bulk_import_entities
ADD CONSTRAINT fk_a44ff95be5 FOREIGN KEY (parent_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE;
@@ -29665,9 +29908,6 @@ ALTER TABLE ONLY users
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;
-
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_a6963e8447 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -29692,15 +29932,9 @@ ALTER TABLE ONLY boards
ALTER TABLE ONLY member_tasks
ADD CONSTRAINT fk_ab636303dd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_sources_pipelines
- ADD CONSTRAINT fk_acd9737679 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_ad525e1f87 FOREIGN KEY (merge_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY ci_variables
- ADD CONSTRAINT fk_ada5eb64b3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_ae440388cc FOREIGN KEY (latest_closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -29770,9 +30004,6 @@ ALTER TABLE ONLY ci_sources_pipelines
ALTER TABLE ONLY packages_maven_metadata
ADD CONSTRAINT fk_be88aed360 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_builds
- ADD CONSTRAINT fk_befce0568a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY design_management_versions
ADD CONSTRAINT fk_c1440b4896 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -29908,8 +30139,8 @@ ALTER TABLE ONLY ci_builds_metadata
ALTER TABLE ONLY gitlab_subscriptions
ADD CONSTRAINT fk_e2595d00a1 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_triggers
- ADD CONSTRAINT fk_e3e63f966e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_e4ef9c2f27 FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE SET NULL NOT VALID;
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -29932,12 +30163,6 @@ 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;
-
ALTER TABLE ONLY integrations
ADD CONSTRAINT fk_e8fe908a34 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -30007,9 +30232,6 @@ ALTER TABLE ONLY system_note_metadata
ALTER TABLE ONLY vulnerability_remediations
ADD CONSTRAINT fk_fc61a535a0 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY merge_requests
- ADD CONSTRAINT fk_fd82eae0b9 FOREIGN KEY (head_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY project_import_data
ADD CONSTRAINT fk_ffb9ee3a10 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -30064,9 +30286,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 ci_subscriptions_projects
- ADD CONSTRAINT fk_rails_0818751483 FOREIGN KEY (downstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY trending_projects
ADD CONSTRAINT fk_rails_09feecd872 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -30229,9 +30448,6 @@ ALTER TABLE ONLY boards_epic_lists
ALTER TABLE ONLY approval_merge_request_rules_groups
ADD CONSTRAINT fk_rails_2020a7124a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY vulnerability_feedback
- ADD CONSTRAINT fk_rails_20976e6fd9 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY work_item_types
ADD CONSTRAINT fk_rails_20f694a960 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -30346,6 +30562,9 @@ ALTER TABLE ONLY container_repositories
ALTER TABLE ONLY clusters_applications_jupyter
ADD CONSTRAINT fk_rails_331f0aff78 FOREIGN KEY (oauth_application_id) REFERENCES oauth_applications(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alert_metric_images
+ ADD CONSTRAINT fk_rails_338e55b408 FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY suggestions
ADD CONSTRAINT fk_rails_33b03a535c FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -30433,9 +30652,6 @@ ALTER TABLE ONLY geo_node_namespace_links
ALTER TABLE ONLY epic_issues
ADD CONSTRAINT fk_rails_4209981af6 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_refs
- ADD CONSTRAINT fk_rails_4249db8cc3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_resources
ADD CONSTRAINT fk_rails_430336af2d FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE CASCADE;
@@ -30481,9 +30697,6 @@ ALTER TABLE ONLY user_custom_attributes
ALTER TABLE ONLY upcoming_reconciliations
ADD CONSTRAINT fk_rails_497b4938ac FOREIGN KEY (namespace_id) REFERENCES namespaces(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;
@@ -30529,9 +30742,6 @@ ALTER TABLE ONLY resource_iteration_events
ALTER TABLE ONLY status_page_settings
ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_project_monthly_usages
- ADD CONSTRAINT fk_rails_508bcd4aa6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY project_repository_storage_moves
ADD CONSTRAINT fk_rails_5106dbd44a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -30643,9 +30853,6 @@ ALTER TABLE ONLY evidences
ALTER TABLE ONLY jira_imports
ADD CONSTRAINT fk_rails_63cbe52ada FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY vulnerability_occurrence_pipelines
- ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY group_deploy_tokens
ADD CONSTRAINT fk_rails_6477b01f6b FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
@@ -30655,9 +30862,6 @@ ALTER TABLE ONLY reviews
ALTER TABLE ONLY operations_feature_flags
ADD CONSTRAINT fk_rails_648e241be7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_sources_projects
- ADD CONSTRAINT fk_rails_64b6855cbc FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY board_group_recent_visits
ADD CONSTRAINT fk_rails_64bfc19bc5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -30697,9 +30901,6 @@ ALTER TABLE ONLY resource_iteration_events
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;
@@ -30793,9 +30994,6 @@ ALTER TABLE ONLY boards_epic_user_preferences
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;
-
ALTER TABLE ONLY terraform_states
ADD CONSTRAINT fk_rails_78f54ca485 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -30823,6 +31021,9 @@ ALTER TABLE ONLY application_settings
ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT fk_rails_7e7688ecaf FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_artifact_states
+ ADD CONSTRAINT fk_rails_80a9cba3b2 FOREIGN KEY (job_artifact_id) REFERENCES ci_job_artifacts(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
@@ -30964,9 +31165,6 @@ ALTER TABLE ONLY group_repository_storage_moves
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_9851a00031 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_job_artifacts
- ADD CONSTRAINT fk_rails_9862d392f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY board_project_recent_visits
ADD CONSTRAINT fk_rails_98f8843922 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -31150,6 +31348,9 @@ ALTER TABLE ONLY packages_debian_project_component_files
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT fk_rails_b565c8d16c FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE batched_background_migration_job_transition_logs
+ ADD CONSTRAINT fk_rails_b7523a175b FOREIGN KEY (batched_background_migration_job_id) REFERENCES batched_background_migration_jobs(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_project_rules_protected_branches
ADD CONSTRAINT fk_rails_b7567b031b FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
@@ -31180,9 +31381,6 @@ ALTER TABLE ONLY projects_sync_events
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY external_pull_requests
- ADD CONSTRAINT fk_rails_bcae9b5c7b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY elasticsearch_indexed_projects
ADD CONSTRAINT fk_rails_bd13bbdc3d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -31540,9 +31738,6 @@ ALTER TABLE ONLY security_trainings
ALTER TABLE ONLY merge_requests_closing_issues
ADD CONSTRAINT fk_rails_f8540692be FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY merge_trains
- ADD CONSTRAINT fk_rails_f90820cb08 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY banned_users
ADD CONSTRAINT fk_rails_fa5bb598e5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -31585,9 +31780,6 @@ ALTER TABLE ONLY resource_label_events
ALTER TABLE ONLY pages_deployment_states
ADD CONSTRAINT fk_rails_ff6ca551a4 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_builds_metadata
- ADD CONSTRAINT fk_rails_ffcf702a02 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY security_orchestration_policy_configurations
ADD CONSTRAINT fk_security_policy_configurations_management_project_id FOREIGN KEY (security_policy_management_project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/BadPlurals.yml b/doc/.vale/gitlab/BadPlurals.yml
new file mode 100644
index 00000000000..81e2a0e563d
--- /dev/null
+++ b/doc/.vale/gitlab/BadPlurals.yml
@@ -0,0 +1,14 @@
+---
+# Suggestion: gitlab.BadPlurals
+#
+# Don't write plural words with the '(s)' construction. "HTTP(S)" is acceptable.
+#
+# For a list of all options, see https://docs.errata.ai/vale/styles
+extends: existence
+message: 'Rewrite "%s" to be plural, without parentheses.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/word_list.html
+level: warning
+scope: raw
+ignorecase: true
+raw:
+ - '\w*\(s\)(?<!http\(s\))'
diff --git a/doc/.vale/gitlab/SubstitutionSuggestions.yml b/doc/.vale/gitlab/SubstitutionSuggestions.yml
index e7c0cc04244..df132d89637 100644
--- a/doc/.vale/gitlab/SubstitutionSuggestions.yml
+++ b/doc/.vale/gitlab/SubstitutionSuggestions.yml
@@ -17,6 +17,7 @@ swap:
e-mail: '"email"'
GFM: '"GitLab Flavored Markdown"'
it is recommended: '"we recommend"'
+ navigate: go
OAuth2: '"OAuth 2.0"'
once that: '"after that"'
once the: '"after the"'
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 8000328a20c..7ee32e41ade 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -22,6 +22,3 @@ swap:
repo: repository
timezone: time zone
utilize: use
- administrator permission: the administrator access level
- administrator permissions: the administrator access level
- administrator role: the administrator access level
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index dde05b993ec..1cc5a60ac91 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -38,6 +38,12 @@ swap:
can sign-in: can sign in
x509: X.509
yaml: YAML
+ admin user: administrator
+ admin users: administrators
+ administrator permission: administrator access
+ administrator permissions: administrator access
+ administrator role: administrator access
+ the administrator access level: administrator access
developer access: the Developer role
developer permission: the Developer role
developer permissions: the Developer role
diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md
index eac54416924..3bdc67e5a69 100644
--- a/doc/administration/audit_event_streaming.md
+++ b/doc/administration/audit_event_streaming.md
@@ -8,12 +8,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. On GitLab.com, this feature is available.
+> - [Feature flag `ff_external_audit_events_namespace`](https://gitlab.com/gitlab-org/gitlab/-/issues/349588) removed in GitLab 14.8.
Event streaming allows owners of top-level groups to set an HTTP endpoint to receive **all** audit events about the group, and its
-subgroups and projects.
+subgroups and projects as structured JSON.
Top-level group owners can manage their audit logs in third-party systems such as Splunk, using the Splunk
[HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/8.2.2/Data/UsetheHTTPEventCollector). Any service that can receive
@@ -37,6 +35,7 @@ mutation {
externalAuditEventDestination {
destinationUrl
group {
+ verificationToken
name
}
}
@@ -60,6 +59,7 @@ query {
externalAuditEventDestinations {
nodes {
destinationUrl
+ verificationToken
id
}
}
@@ -68,3 +68,13 @@ query {
```
If the resulting list is empty, then audit event streaming is not enabled for that group.
+
+## Verify event authenticity
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345424) in GitLab 14.8.
+
+Each streaming destination has a unique verification token (`verificationToken`) that can be used to verify the authenticity of the event. This
+token is generated when the event destination is created and cannot be changed.
+
+Each streamed event contains a random alphanumeric identifier for the `X-Gitlab-Event-Streaming-Token` HTTP header that can be verified against
+the destination's value when [listing streaming destinations](#list-currently-enabled-streaming-destinations).
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 06ad16bbcba..d4902a18cac 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -51,7 +51,10 @@ There are two kinds of events logged:
When a user is being [impersonated](../user/admin_area/index.md#user-impersonation), their actions are logged as audit events as usual, with two additional details:
1. Usual audit events include information about the impersonating administrator. These are visible in their respective Audit Event pages depending on their type (Group/Project/User).
-1. Extra audit events are recorded for the start and stop of the administrator's impersonation session. These are visible in the instance Audit Events.
+1. Extra audit events are recorded for the start and stop of the administrator's impersonation session. These are visible in
+ the:
+ - Instance audit events.
+ - Group audit events for all groups the user belongs to (GitLab 14.8 and later). This is limited to 20 groups for performance reasons.
![audit events](img/impersonated_audit_events_v13_8.png)
@@ -103,6 +106,7 @@ From there, you can see the following actions:
- Group CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
- Compliance framework created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340649) in GitLab 14.5.
- Event streaming destination created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344664) in GitLab 14.6.
+- Instance administrator started or stopped impersonation of a group member. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300961) in GitLab 14.8.
Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
@@ -236,10 +240,13 @@ Don't see the event you want in any of the epics linked above? You can either:
### Disabled events
-#### Repository push
+#### Repository push (DEPRECATED)
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/337993) in GitLab 14.3.
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/337993) in GitLab 14.3.
+
The current architecture of audit events is not prepared to receive a very high amount of records.
It may make the user interface for your project or audit events very busy, and the disk space consumed by the
`audit_events` PostgreSQL table may increase considerably. It's disabled by default
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index 5498ea9d4be..12e222290e7 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -64,7 +64,7 @@ To create an Auditor user:
1. Select **Create user** or **Save changes** if you created a new user or
edited an existing one respectively.
-To revoke Auditor permissions from a user, make them a regular user by
+To revoke Auditor permissions from a user, make them a Regular user by
following the previous steps.
Additionally users can be set as an Auditor using [SAML groups](../integration/saml.md#auditor-groups).
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
index 08d07b13e22..7c6aee2c2da 100644
--- a/doc/administration/auth/atlassian.md
+++ b/doc/administration/auth/atlassian.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 23735b75991..a4a085a494c 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index 2509bbb73d7..66f8407894c 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -1,7 +1,7 @@
---
type: concepts, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 9a5f6b0a642..8dfa832a103 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/index.md b/doc/administration/auth/index.md
index d469988e719..d09344629e2 100644
--- a/doc/administration/auth/index.md
+++ b/doc/administration/auth/index.md
@@ -2,7 +2,7 @@
comments: false
type: index
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -50,3 +50,31 @@ For more information, see the links shown on this page for each external provide
| **Authentication** | SAML at top-level group (1 provider) | LDAP (multiple providers)<br>Generic OAuth2<br>SAML (only 1 permitted per unique provider)<br>Kerberos<br>JWT<br>Smartcard<br>OmniAuth Providers (only 1 permitted per unique provider) |
| **Provider-to-GitLab Role Sync** | SAML Group Sync | LDAP Group Sync |
| **User Removal** | SCIM (remove user from top-level group) | LDAP (Blocking User from Instance) |
+
+## Change apps or configuration
+
+When GitLab doesn't support having multiple providers (such as OAuth), GitLab configuration and user identification must be
+updated at the same time if the provider or app is changed.
+
+These instructions apply to all methods of authentication where GitLab stores an `extern_uid` and it is the only data used
+for user authentication.
+
+When changing apps within a provider, if the user `extern_uid` does not change, only the GitLab configuration must be
+updated.
+
+To swap configurations:
+
+1. Change provider configuration in your `gitlab.rb` file.
+1. Update `extern_uid` for all users that have an identity in GitLab for the previous provider.
+
+To find the `extern_uid`, look at an existing user's current `extern_uid` for an ID that matches the appropriate field in
+your current provider for the same user.
+
+There are two methods to update the `extern_uid`:
+
+- Using the [Users API](../../api/users.md#user-modification). Pass the provider name and the new `extern_uid`.
+- Using the [Rails console](../operations/rails_console.md):
+
+ ```ruby
+ Identity.where(extern_uid: 'old-id').update!(extern_uid: 'new-id')`
+ ```
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index ac2f699dd5d..98f928fd7ee 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index 6b8e699e861..10745c5e2bf 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index b773281b216..2a396c4d53a 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -468,7 +468,7 @@ If initially your LDAP configuration looked like:
password: '123'
```
-1. Edit `/etc/gitlab/gitlab.rb` and remove the settings for `user_bn` and `password`.
+1. Edit `/etc/gitlab/gitlab.rb` and remove the settings for `user_dn` and `password`.
1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -502,7 +502,7 @@ If initially your LDAP configuration looked like:
password: '123'
```
-1. Edit `config/gitlab.yaml` and remove the settings for `user_bn` and `password`.
+1. Edit `config/gitlab.yaml` and remove the settings for `user_dn` and `password`.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 97a626f4a40..06fe579e101 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -382,7 +382,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 only grants the Administrator role to the users whose
+ credentials. GitLab only grants 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,
diff --git a/doc/administration/auth/ldap/ldap_synchronization.md b/doc/administration/auth/ldap/ldap_synchronization.md
index 3329ea8e9cc..d7ce54a47c0 100644
--- a/doc/administration/auth/ldap/ldap_synchronization.md
+++ b/doc/administration/auth/ldap/ldap_synchronization.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -347,3 +347,7 @@ These metrics are meant to provide a baseline and performance may vary based on
any number of factors. This benchmark was extreme and most instances don't
have near this many users or groups. Disk speed, database performance,
network and LDAP server response time affects these metrics.
+
+## Troubleshooting
+
+See our [administrator guide to troubleshooting LDAP](ldap-troubleshooting.md).
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index efe4b7440ee..a099b9c76f8 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -461,6 +461,65 @@ To use symmetric key encryption:
If after reconfiguring, you see the error `JSON::JWS::VerificationFailed` error message, this means
the incorrect secret was specified.
+#### Casdoor
+
+GitLab works with OpenID providers that use HTTPS. To connect to GitLab using OpenID with Casdoor, use HTTPS instead of HTTP.
+
+For your app, complete the following steps on Casdoor:
+
+1. Get a client ID and a client secret.
+1. Add your GitLab redirect URL. For example, if your GitLab domain is `gitlab.example.com`, ensure the Casdoor app has the following
+ `Redirect URI`: `https://gitlab.example.com/users/auth/openid_connect/callback`.
+
+See the [Casdoor documentation](https://casdoor.org/docs/integration/gitlab) for more details.
+
+Example Omnibus GitLab configuration (file path: `/etc/gitlab/gitlab.rb`):
+
+```ruby
+gitlab_rails['omniauth_providers'] = [
+ {
+ name: "openid_connect",
+ label: "Casdoor", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://<CASDOOR_HOSTNAME>",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "sub",
+ client_options: {
+ identifier: "<YOUR CLIENT ID>",
+ secret: "<YOUR CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
+ }
+ }
+ }
+]
+```
+
+Example installations from source configuration (file path: `config/gitlab.yml`):
+
+```yaml
+ - { name: 'openid_connect',
+ label: 'Casdoor', # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: 'openid_connect',
+ scope: ['openid','profile','email'],
+ response_type: 'code',
+ issuer: 'https://<CASDOOR_HOSTNAME>',
+ discovery: true,
+ client_auth_method: 'query',
+ uid_field: 'sub',
+ client_options: {
+ identifier: '<YOUR CLIENT ID>',
+ secret: '<YOUR CLIENT SECRET>',
+ redirect_uri: 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ }
+ }
+ }
+```
+
## General troubleshooting
If you're having trouble, here are some tips:
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
index f77d3a36a7b..3f0d95967bf 100644
--- a/doc/administration/auth/smartcard.md
+++ b/doc/administration/auth/smartcard.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/clusters/kas.md b/doc/administration/clusters/kas.md
index ba0d7280b74..192b636e246 100644
--- a/doc/administration/clusters/kas.md
+++ b/doc/administration/clusters/kas.md
@@ -4,13 +4,15 @@ 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
---
-# Install the GitLab Agent Server (KAS) **(FREE SELF)**
+# Install the GitLab Agent Server for Kubernetes (KAS) **(FREE SELF)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.10, the GitLab Agent Server (KAS) became available on GitLab.com under `wss://kas.gitlab.com`.
-> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
-The GitLab Agent Server (KAS) is a GitLab backend service dedicated to
-managing the [GitLab Agent](../../user/clusters/agent/index.md).
+The GitLab Agent Server for Kubernetes is a GitLab backend service dedicated to
+managing the [GitLab Agent for Kubernetes](../../user/clusters/agent/index.md).
+
+The KAS acronym refers to the former name, Kubernetes Agent Server.
The KAS is already installed and available in GitLab.com under `wss://kas.gitlab.com`.
This document describes how to install a KAS for GitLab self-managed instances.
@@ -94,8 +96,8 @@ For GitLab instances installed through Omnibus packages:
## Troubleshooting
-If you face any issues with KAS, you can read the service logs
-with the following command:
+If you have issues while using the GitLab Agent Server for Kubernetes, view the
+service logs by running the following command:
```shell
kubectl logs -f -l=app=kas -n <YOUR-GITLAB-NAMESPACE>
@@ -103,8 +105,7 @@ kubectl logs -f -l=app=kas -n <YOUR-GITLAB-NAMESPACE>
In Omnibus GitLab, find the logs in `/var/log/gitlab/gitlab-kas/`.
-See also the [user documentation](../../user/clusters/agent/index.md#troubleshooting)
-for troubleshooting problems with individual agents.
+You can also [troubleshoot issues with individual Agents](../../user/clusters/agent/troubleshooting.md).
### KAS logs - GitOps: failed to get project information
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 843d5d0930a..7c3f36c71c2 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -16,7 +16,7 @@ relevant compliance standards.
## Policy management
Organizations have unique policy requirements, either due to organizational
-standards or mandates from regulatory bodies. The following features help you
+standards or mandates from regulatory bodies. The following features help you
define rules and policies to adhere to workflow requirements, separation of duties,
and secure supply chain best practices:
@@ -31,7 +31,7 @@ and secure supply chain best practices:
- [**Merge request approvals**](../user/project/merge_requests/approvals/index.md)
(for instances, groups, and projects): Configure approvals required for
merge requests.
-- [**Push rules**](../push_rules/push_rules.md) (for instances, groups, and
+- [**Push rules**](../user/project/repository/push_rules.md) (for instances, groups, and
projects): Control pushes to your repositories.
- Separation of duties using [**protected branches**](../user/project/protected_branches.md#require-code-owner-approval-on-a-protected-branch)
and [**custom CI/CD configuration paths**](../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file) (for projects): Users can leverage the GitLab cross-project YAML configurations
diff --git a/doc/administration/docs_self_host.md b/doc/administration/docs_self_host.md
index 007055b5de7..3a4511e5aa4 100644
--- a/doc/administration/docs_self_host.md
+++ b/doc/administration/docs_self_host.md
@@ -4,77 +4,69 @@ 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
---
-# How to self-host the docs site **(FREE SELF)**
-
-If you have a self-managed instance of GitLab, you may not be able to access the
-product documentation as hosted on `docs.gitlab.com` from your GitLab instance.
-
-Be aware of the following items if you self-host the product documentation:
-
-- You must host the product documentation site under a subdirectory that matches
- your installed GitLab version (for example, `14.5/`). The
- [Docker images](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635)
- hosted by the GitLab Docs team provide this by default. We use a
- [script](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/2995d1378175803b22fb8806ba77adf63e79f32c/scripts/normalize-links.sh#L28-82)
- to normalize the links and prefix them with the respective version.
-- The version dropdown will display additional versions that don't exist, selecting
- those versions will display a 404 Not Found page.
-- Results when using the search box will display results from `docs.gitlab.com`
- and not the local documentation.
-- When you use the Docker images to serve the product documentation site, by
- default the landing page redirects to the respective version (for example, `/14.5/`),
- which causes the landing page <https://docs.gitlab.com> to not be displayed.
+# How to host the GitLab product documentation **(FREE SELF)**
+
+If you are not able to access the GitLab product documentation at `docs.gitlab.com`,
+you can host the documentation yourself instead.
## Documentation self-hosting options
-You can self-host the GitLab product documentation locally using one of these
-methods:
+To host the GitLab product documentation, you can use:
-- Docker
+- A Docker container
- GitLab Pages
-- From your own webserver
+- Your own web server
+
+After you create a website by using one of these methods, you redirect the UI links
+in the product to point to your website.
-The examples on this page are based on GitLab 14.5.
+NOTE:
+The website you create must be hosted under a subdirectory that matches
+your installed GitLab version (for example, `14.5/`). The
+[Docker images](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635)
+use this version by default.
+
+The following examples use GitLab 14.5.
### Self-host the product documentation with Docker
-The Docker images use a built-in webserver listening on port `4000`, so you need
-to expose that.
+You can run the GitLab product documentation website in a Docker container:
-In the server that you host GitLab, or any other server that your GitLab instance
-can talk to, you can use Docker to pull the docs site:
+1. Expose port `4000`. The Docker image uses this port for the web server.
+1. On the server where you host GitLab, or on any other server that your GitLab instance
+ can communicate with, pull the docs site:
-```shell
-docker run -it --rm -p 4000:4000 registry.gitlab.com/gitlab-org/gitlab-docs:14.5
-```
+ ```shell
+ docker run -it --rm -p 4000:4000 registry.gitlab.com/gitlab-org/gitlab-docs:14.5
+ ```
-If you use [Docker compose](../install/docker.md#install-gitlab-using-docker-compose)
-to host your GitLab instance, add the following to `docker-compose.yaml`:
-
-```yaml
-version: '3.6'
-services:
- docs:
- image: registry.gitlab.com/gitlab-org/gitlab-docs:14.5
- hostname: 'https://gitlab.example.com'
- ports:
- - '4000:4000'
-```
+ If you host your GitLab instance using [Docker compose](../install/docker.md#install-gitlab-using-docker-compose),
+ add the following to `docker-compose.yaml`:
+
+ ```yaml
+ version: '3.6'
+ services:
+ docs:
+ image: registry.gitlab.com/gitlab-org/gitlab-docs:14.5
+ hostname: 'https://gitlab.example.com'
+ ports:
+ - '4000:4000'
+ ```
### Self-host the product documentation with GitLab Pages
-You use GitLab Pages to host the GitLab product documentation locally.
+You can use GitLab Pages to host the GitLab product documentation.
Prerequisite:
-- The Pages site URL must not use a subfolder. Due to the nature of how the docs
+- Ensure the Pages site URL does not use a subfolder. Because of how the docs
site is pre-compiled, the CSS and JavaScript files are relative to the
main domain or subdomain. For example, URLs like `https://example.com/docs/`
are not supported.
To host the product documentation site with GitLab Pages:
-1. [Create a new blank project](../user/project/working_with_projects.md#create-a-blank-project).
+1. [Create a blank project](../user/project/working_with_projects.md#create-a-blank-project).
1. Create a new or edit your existing `.gitlab-ci.yml` file, and add the following
`pages` job, while ensuring the version is the same as your GitLab installation:
@@ -97,13 +89,13 @@ To host the product documentation site with GitLab Pages:
| [Project website](../user/project/pages/getting_started_part_one.md#project-website-examples) | Not supported | Supported |
| [User or group website](../user/project/pages/getting_started_part_one.md#user-and-group-website-examples) | Supported | Supported |
-### Self-host the product documentation on your own webserver
+### Self-host the product documentation on your own web server
-Because the product documentation site is static, you can grab the directory from
-the container (in `/usr/share/nginx/html`) and use your own web server to host
-it wherever you want.
+Because the product documentation site is static, from the container, you can take the contents
+of `/usr/share/nginx/html` and use your own web server to host
+the docs wherever you want.
-Use the following commands, and replace `<destination>` with the directory where the
+Run the following commands, replacing `<destination>` with the directory where the
documentation files will be copied to:
```shell
@@ -114,18 +106,30 @@ docker rm -f gitlab-docs
## Redirect the `/help` links to the new docs page
-After your local product documentation site is running, [redirect the help
-links](../user/admin_area/settings/help_page.md#redirect-help-pages) in the GitLab
-application to your local site.
+After your local product documentation site is running,
+[redirect the help links](../user/admin_area/settings/help_page.md#redirect-help-pages)
+in the GitLab application to your local site.
Be sure to use the fully qualified domain name as the docs URL. For example, if you
used the [Docker method](#self-host-the-product-documentation-with-docker), enter `http://0.0.0.0:4000`.
-You don't need to append the version, as GitLab will detect it and append it to
-any documentation URL requests, as needed. For example, if your GitLab version is
-14.5, the GitLab Docs URL becomes `http://0.0.0.0:4000/14.5/`. The link
-inside GitLab displays as `<instance_url>/help/user/admin_area/settings/help_page#destination-requirements`,
-but when you select it, you are redirected to
+You don't need to append the version. GitLab detects it and appends it to
+documentation URL requests as needed. For example, if your GitLab version is
+14.5:
+
+- The GitLab Docs URL becomes `http://0.0.0.0:4000/14.5/`.
+- The link in GitLab displays as `<instance_url>/help/user/admin_area/settings/help_page#destination-requirements`.
+- When you select the link, you are redirected to
`http://0.0.0.0:4000/14.5/ee/user/admin_area/settings/help_page/#destination-requirements`.
To test the setting, select a **Learn more** link within the GitLab application.
+
+## Known issues
+
+If you self-host the product documentation:
+
+- The version dropdown displays additional versions that don't exist. Selecting
+ these versions displays a `404 Not Found` page.
+- The search displays results from `docs.gitlab.com` and not the local site.
+- By default, the landing page redirects to the
+ respective version (for example, `/14.5/`). This causes the landing page <https://docs.gitlab.com> to not be displayed.
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index afbf0759452..85a7304b5e8 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -36,7 +36,7 @@ For example, data is not recorded and services do not run.
If you used a certain feature and identified a bug, a misbehavior, or an
error, it's very important that you [**provide feedback**](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Docs%20-%20feature%20flag%20feedback%3A%20Feature%20Name&issue[description]=Describe%20the%20problem%20you%27ve%20encountered.%0A%0A%3C!--%20Don%27t%20edit%20below%20this%20line%20--%3E%0A%0A%2Flabel%20~%22docs%5C-comments%22%20) to GitLab as soon
as possible so we can improve or fix it while behind a flag. When you upgrade
-GitLab to an earlier version, the feature flag status may change.
+GitLab, the feature flag status may change.
## Risks when enabling features still in development
@@ -130,11 +130,15 @@ irb(main):001:0> Feature.enable(:my_awesome_feature)
=> nil
```
-To check if a flag is enabled or disabled you can use `Feature.enabled?` or `Feature.disabled?`. For example, for a fictional feature flag named `my_awesome_feature`:
+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.
+
+### Check if a feature flag is enabled
+
+To check if a flag is enabled or disabled, use `Feature.enabled?` or `Feature.disabled?`.
+For example, for a feature flag named `my_awesome_feature` that is already enabled:
```ruby
-Feature.enable(:my_awesome_feature)
-=> nil
Feature.enabled?(:my_awesome_feature)
=> true
Feature.disabled?(:my_awesome_feature)
@@ -143,3 +147,21 @@ Feature.disabled?(:my_awesome_feature)
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.
+
+### View set feature flags
+
+You can view all GitLab administrator set feature flags:
+
+```ruby
+Feature.all
+=> [#<Flipper::Feature:198220 name="my_awesome_feature", state=:on, enabled_gate_names=[:boolean], adapter=:memoizable>]
+```
+
+### Unset feature flag
+
+You can unset a feature flag so that GitLab will fall back to the current defaults for that flag:
+
+```ruby
+Feature.remove(:my_awesome_feature)
+=> true
+```
diff --git a/doc/administration/geo/glossary.md b/doc/administration/geo/glossary.md
index f8769d31ec7..a18e78a5e01 100644
--- a/doc/administration/geo/glossary.md
+++ b/doc/administration/geo/glossary.md
@@ -25,8 +25,8 @@ these definitions yet.
| Site | One or a collection of nodes running a single GitLab application. A site can be single-node or multi-node. | GitLab | deployment, installation instance |
| Single-node site | A specific configuration of GitLab that uses exactly one node. | GitLab | single-server, single-instance
| Multi-node site | A specific configuration of GitLab that uses more than one node. | GitLab | multi-server, multi-instance, high availability |
-| Primary site | A GitLab site that is configured to be read and writable. There can only be a single primary site. | Geo-specific | Geo deployment, Primary node |
-| Secondary site(s) | GitLab site that is configured to be read-only. There can be one or more secondary sites. | Geo-specific | Geo deployment, Secondary node |
+| Primary site | A GitLab site whose data is being replicated by at least one secondary site. There can only be a single primary site. | Geo-specific | Geo deployment, Primary node |
+| Secondary site(s) | A GitLab site that is configured to replicate the data of a primary site. There can be one or more secondary sites. | Geo-specific | Geo deployment, Secondary node |
| Geo deployment | A collection of two or more GitLab sites with exactly one primary site being replicated by one or more secondary sites. | Geo-specific | |
| Reference architecture(s) | A [specified configuration of GitLab for a number of users](../reference_architectures/index.md), possibly including multiple nodes and multiple sites. | GitLab | |
| Promoting | Changing the role of a site from secondary to primary. | Geo-specific | |
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index b5eb0ba5841..c4164284e97 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -204,6 +204,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
- Real-time updates of issues/merge requests (for example, via long polling) doesn't work 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).
- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories and files are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases.
+- [Pages access control](../../user/project/pages/pages_access_control.md) doesn't work on secondaries. See [GitLab issue #9336](https://gitlab.com/gitlab-org/gitlab/-/issues/9336) for details.
### Limitations on replication/verification
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index 0fa08dcc9e0..5beb2479c57 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -39,7 +39,7 @@ verification methods:
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | LFS objects _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | CI job artifacts _(file system)_ | Geo with API | _Not implemented_ |
+| Blobs | CI job artifacts _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | Archived CI build traces _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index ce1bd8a9d3c..70b3eaf5fea 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -118,7 +118,7 @@ The following are PostgreSQL upgrade validation tests we performed.
[Verify Geo installation with PostgreSQL 13](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6131):
- Description: With PostgreSQL 13 available as an opt-in version in GitLab 14.1, we tested fresh installations of GitLab with Geo when PostgreSQL 13 is enabled.
-- Outcome: Successfully built an environment with Geo and PostgreSQL 13 using [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) and performed Geo QA tests against the environment without failures.
+- Outcome: Successfully built an environment with Geo and PostgreSQL 13 using [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) and performed Geo QA tests against the environment without failures.
### September 2020
@@ -200,3 +200,12 @@ The following are additional validation tests we performed.
- Description: Tested a Geo deployment with Gitaly clusters configured on both the primary and secondary Geo sites. Triggered automatic Gitaly cluster failover on the primary Geo site, and ran end-to-end Geo tests. Then triggered Gitaly cluster failover on the secondary Geo site, and re-ran the end-to-end Geo tests.
- Outcome: Successful end-to-end tests before and after Gitaly cluster failover on the primary site, and before and after Gitaly cluster failover on the secondary site.
+
+### January 2022
+
+[Validate Object storage replication using Azure based object storage](https://gitlab.com/gitlab-org/gitlab/-/issues/348804#note_821294631):
+
+- Description: Tested the average time it takes for a single image to replicate from the primary object storage location to the secondary when using Azure based object storage replication and [GitLab based object storage replication](object_storage.md#enabling-gitlab-managed-object-storage-replication). This was tested by uploading a 1mb image to a project on the primary site every second for 60 seconds. The time was then measured until a image was available on the secondary site. This was achieved using a [Ruby Script](https://gitlab.com/gitlab-org/quality/geo-replication-tester).
+- Outcome: When using Azure based replication the average time for an image to replicate from the primary object storage to the secondary was recorded as 40 seconds, the longest replication time was 70 seconds and the quickest was 11 seconds. When using GitLab based replication the average time for replication to complete was 5 seconds, the longest replication time was 10 seconds and the quickest was 3 seconds.
+- Follow up issue:
+ - [Test and validate object storage replication performance on reference architectures](https://gitlab.com/gitlab-org/gitlab/-/issues/347314)
diff --git a/doc/administration/geo/replication/location_aware_git_url.md b/doc/administration/geo/replication/location_aware_git_url.md
index ce1af27611e..8689fac987f 100644
--- a/doc/administration/geo/replication/location_aware_git_url.md
+++ b/doc/administration/geo/replication/location_aware_git_url.md
@@ -7,6 +7,12 @@ type: howto
# Location-aware Git remote URL with AWS Route53 **(PREMIUM SELF)**
+NOTE:
+Since GitLab 14.6,
+[GitLab Geo supports a location-aware URL including web UI and API traffic.](../secondary_proxy/location_aware_external_url.md)
+This configuration is recommended over the location-aware Git remote URL
+described in this document.
+
You can provide GitLab users with a single remote URL that automatically uses
the Geo site closest to them. This means users don't need to update their Git
configuration to take advantage of closer Geo sites as they move.
@@ -18,12 +24,6 @@ Though these instructions use [AWS Route53](https://aws.amazon.com/route53/),
other services such as [Cloudflare](https://www.cloudflare.com/) could be used
as well.
-NOTE:
-You can also use a load balancer to distribute web UI or API traffic to
-[multiple Geo **secondary** sites](../../../user/admin_area/geo_nodes.md#multiple-secondary-sites-behind-a-load-balancer).
-Importantly, the **primary** site cannot yet be included. See the feature request
-[Support putting the **primary** behind a Geo node load balancer](https://gitlab.com/gitlab-org/gitlab/-/issues/10888).
-
## Prerequisites
In this example, we have already set up:
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index a6ea41171a9..1371e5d84c8 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -115,35 +115,39 @@ http://secondary.example.com/
To check if PostgreSQL replication is working, check if:
-- [Nodes are pointing to the correct database instance](#are-nodes-pointing-to-the-correct-database-instance).
-- [Geo can detect the current node correctly](#can-geo-detect-the-current-node-correctly).
+- [Sites are pointing to the correct database node](#are-sites-pointing-to-the-correct-database-node).
+- [Geo can detect the current site correctly](#can-geo-detect-the-current-site-correctly).
-#### Are nodes pointing to the correct database instance?
+#### Are sites pointing to the correct database node?
-You should make sure your **primary** Geo node points to the instance with
-writing permissions.
+You should make sure your **primary** Geo [site](../glossary.md) points to
+the database node that has write permissions.
-Any **secondary** nodes should point only to read-only instances.
+Any **secondary** sites should point only to read-only database nodes.
-#### Can Geo detect the current node correctly?
+#### Can Geo detect the current site correctly?
-Geo finds the current machine's Geo node name in `/etc/gitlab/gitlab.rb` by:
+Geo finds the current Puma or Sidekiq node's Geo [site](../glossary.md) name in
+`/etc/gitlab/gitlab.rb` with the following logic:
-- Using the `gitlab_rails['geo_node_name']` setting.
-- If that is not defined, using the `external_url` setting.
+1. Get the "Geo node name" (there is
+ [an issue to rename the settings to "Geo site name"](https://gitlab.com/gitlab-org/gitlab/-/issues/335944)):
+ - Omnibus GitLab: Get the `gitlab_rails['geo_node_name']` setting.
+ - GitLab Helm Charts: Get the `global.geo.nodeName` setting (see [Charts with GitLab Geo](https://docs.gitlab.com/charts/advanced/geo/index.html)).
+1. If that is not defined, then get the `external_url` setting.
-This name is used to look up the node with the same **Name** in the **Geo Nodes**
+This name is used to look up the Geo site with the same **Name** in the **Geo Sites**
dashboard.
-To check if the current machine has a node name that matches a node in the
+To check if the current machine has a site name that matches a site in the
database, run the check task:
```shell
sudo gitlab-rake gitlab:geo:check
```
-It displays the current machine's node name and whether the matching database
-record is a **primary** or **secondary** node.
+It displays the current machine's site name and whether the matching database
+record is a **primary** or **secondary** site.
```plaintext
This machine's Geo node name matches a database record ... yes, found a secondary node named "Shanghai"
@@ -158,6 +162,9 @@ This machine's Geo node name matches a database record ... no
doc/administration/geo/replication/troubleshooting.md#can-geo-detect-the-current-node-correctly
```
+Learn more about recommended site names in the description of the Name field in
+[Geo Admin Area Common Settings](../../../user/admin_area/geo_nodes.md#common-settings).
+
### Message: `WARNING: oldest xmin is far in the past` and `pg_wal` size growing
If a replication slot is inactive,
@@ -692,6 +699,8 @@ determine the actual replication status of Design repositories.
### Sync failure message: "Verification failed with: Error during verification: File is not checksummable"
+#### Missing files on the Geo primary site
+
In GitLab 14.5 and earlier, certain data types which were missing on the Geo primary site were marked as "synced" on Geo secondary sites. This was because from the perspective of Geo secondary sites, the state matched the primary site and nothing more could be done on secondary sites.
Secondaries would regularly try to sync these files again by using the "verification" feature:
@@ -745,6 +754,32 @@ This behavior affects only the following data types through GitLab 14.6:
to make Geo visibly surface data loss risks. The sync/verification loop is
therefore short-circuited. `last_sync_failure` is now set to `The file is missing on the Geo primary site`.
+#### Failed syncs with GitLab-managed object storage replication
+
+There is [an issue in GitLab 14.2 through 14.7](https://gitlab.com/gitlab-org/gitlab/-/issues/299819#note_822629467)
+that affects Geo when the GitLab-managed object storage replication is used, causing blob object types to fail synchronization.
+
+Since GitLab 14.2, verification failures result in synchronization failures and cause
+a re-synchronization of these objects.
+
+As verification is not implemented for files stored in object storage (see
+[issue 13845](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) for more details), this
+results in a loop that consistently fails for all objects stored in object storage.
+
+You can work around this by marking the objects as synced and succeeded verification, however
+be aware that can also mark objects that may be
+[missing from the primary](#missing-files-on-the-geo-primary-site).
+
+To do that, enter the [Rails console](../../troubleshooting/navigating_gitlab_via_rails_console.md)
+and run:
+
+```ruby
+Gitlab::Geo.verification_enabled_replicator_classes.each do |klass|
+ updated = klass.registry_class.failed.where(last_sync_failure: "Verification failed with: Error during verification: File is not checksummable").update_all(verification_checksum: '0000000000000000000000000000000000000000', verification_state: 2, verification_failure: nil, verification_retry_at: nil, state: 2, last_sync_failure: nil, retry_at: nil, verification_retry_count: 0, retry_count: 0)
+ pp "Updated #{updated} #{klass.replicable_name_plural}"
+end
+```
+
## Fixing errors during a failover or when promoting a secondary to a primary node
The following are possible error messages that might be encountered during failover or
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index 04c30514a89..62562a1149d 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -1,9 +1,9 @@
---
redirect_to: '../../geo/replication/usage.md'
-remove_date: '2022-06-01'
+remove_date: '2022-02-01'
---
This document was moved to [another location](../../geo/replication/usage.md).
-<!-- This redirect file can be deleted after 2022-06-01 -->
+<!-- This redirect file can be deleted after 2022-02-01 -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index d3a132a6666..95833a290dd 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -8,7 +8,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_sites.md#general-update-steps)
-for updating Geo nodes.
+for updating Geo sites.
+
+## Updating to 14.2 through 14.7
+
+There is [an issue in GitLab 14.2 through 14.7](https://gitlab.com/gitlab-org/gitlab/-/issues/299819#note_822629467)
+that affects Geo when the GitLab-managed object storage replication is used, causing blob object types to fail synchronization.
+
+Since GitLab 14.2, verification failures result in synchronization failures and cause
+a resynchronization of these objects.
+
+As verification is not yet implemented for files stored in object storage (see
+[issue 13845](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) for more details), this
+results in a loop that consistently fails for all objects stored in object storage.
+
+For information on how to fix this, see
+[Troubleshooting - Failed syncs with GitLab-managed object storage replication](troubleshooting.md#failed-syncs-with-gitlab-managed-object-storage-replication).
## Updating to 14.4
@@ -18,7 +33,7 @@ There is [an issue in GitLab 14.4.0 through 14.4.2](../../../update/index.md#144
### Multi-arch images
-We found an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/336013) where the Container Registry replication wasn't fully working if you used multi-arch images. In case of a multi-arch image, only the primary architecture (for example `amd64`) would be replicated to the secondary node. This has been [fixed in GitLab 14.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67624) and was backported to 14.2 and 14.1, but manual steps are required to force a re-sync.
+We found an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/336013) where the Container Registry replication wasn't fully working if you used multi-arch images. In case of a multi-arch image, only the primary architecture (for example `amd64`) would be replicated to the secondary site. This has been [fixed in GitLab 14.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67624) and was backported to 14.2 and 14.1, but manual steps are required to force a re-sync.
You can check if you are affected by running:
@@ -26,12 +41,12 @@ You can check if you are affected by running:
docker manifest inspect <SECONDARY_IMAGE_LOCATION> | jq '.mediaType'
```
-Where `<SECONDARY_IMAGE_LOCATION>` is a container image on your secondary node.
+Where `<SECONDARY_IMAGE_LOCATION>` is a container image on your secondary site.
If the output matches `application/vnd.docker.distribution.manifest.list.v2+json`
(there can be a `mediaType` entry at several levels, we only care about the top level entry),
then you don't need to do anything.
-Otherwise, on all your **secondary** nodes, in a [Rails console](../../operations/rails_console.md), run the following:
+Otherwise, for each **secondary** site, on a Rails application node, open a [Rails console](../../operations/rails_console.md), and run the following:
```ruby
list_type = 'application/vnd.docker.distribution.manifest.list.v2+json'
@@ -63,7 +78,7 @@ We found an issue where [Primary sites can not be removed from the UI](https://g
This bug only exists in the UI and does not block the removal of Primary sites using any other method.
-If you are running an affected version and need to remove your Primary site, you can manually remove the Primary site by using the [Geo Nodes API](../../../api/geo_nodes.md#delete-a-geo-node).
+If you are running an affected version and need to remove your Primary site, you can manually remove the Primary site by using the [Geo Sites API](../../../api/geo_nodes.md#delete-a-geo-node).
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
@@ -71,9 +86,9 @@ GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab
## Updating to GitLab 13.12
-### Secondary nodes re-download all LFS files upon update
+### Secondary sites re-download all LFS files upon update
-We found an issue where [secondary nodes re-download all LFS files](https://gitlab.com/gitlab-org/gitlab/-/issues/334550) upon update. This bug:
+We found an issue where [secondary sites re-download all LFS files](https://gitlab.com/gitlab-org/gitlab/-/issues/334550) upon update. This bug:
- Only applies to Geo secondary sites that have replicated LFS objects.
- Is _not_ a data loss risk.
@@ -172,7 +187,7 @@ In GitLab 13.3, Geo removed the PostgreSQL [Foreign Data Wrapper](https://www.po
dependency for the tracking database.
The FDW server, user, and the extension is removed during the upgrade
-process on each secondary node. The GitLab settings related to the FDW in the
+process on each secondary site. The GitLab settings related to the FDW in the
`/etc/gitlab/gitlab.rb` have been deprecated and can be safely removed.
There are some scenarios like using an external PostgreSQL instance for the
@@ -185,9 +200,9 @@ DROP EXTENSION IF EXISTS postgres_fdw;
```
WARNING:
-In GitLab 13.3, promoting a secondary node to a primary while the secondary is
+In GitLab 13.3, promoting a secondary site to a primary while the secondary is
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,
+site is paused, be sure to resume before promoting. To avoid this issue,
upgrade to GitLab 13.4 or later.
WARNING:
@@ -198,9 +213,9 @@ 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
+In GitLab 13.2, promoting a secondary site to a primary while the secondary is
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,
+site is paused, be sure to resume before promoting. To avoid this issue,
upgrade to GitLab 13.4 or later.
## Updating to GitLab 13.0
@@ -375,5 +390,5 @@ For the recommended procedure, see the
WARNING:
This version is affected by a [bug that results in new LFS objects not being
-replicated to Geo secondary nodes](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
+replicated to Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
The issue is fixed in GitLab 12.1. Be sure to upgrade to GitLab 12.1 or later.
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index ebd71757e91..c8dcbb81312 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -140,6 +140,18 @@ for details.
To use TLS certificates with Let's Encrypt, you can manually point the domain to one of the Geo sites, generate
the certificate, then copy it to all other sites.
+## Behavior of secondary sites when the primary Geo site is down
+
+Considering that web traffic is proxied to the primary, the behavior of the secondary sites differs when the primary
+site is inaccessible:
+
+- UI and API traffic return the same errors as the primary (or fail if the primary is not accessible at all), since they are proxied.
+- For repositories that already exist on the specific secondary site being accessed, Git read operations still work as expected,
+ including authentication through HTTP(s) or SSH.
+- Git operations for repositories that are not replicated to the secondary site return the same errors
+ as the primary site, since they are proxied.
+- All Git write operations return the same errors as the primary site, since they are proxied.
+
## Features accelerated by secondary Geo sites
Most HTTP traffic sent to a secondary Geo site can be proxied to the primary Geo site. With this architecture,
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 7f4c771c962..a8bebef8f44 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -40,7 +40,7 @@ instructions on setting up replication with a Patroni cluster.
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).
+connect to their own database servers (which are read-only).
We recommend using [PostgreSQL replication slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
to ensure that the **primary** node retains all the data necessary for the **secondary** nodes to
@@ -893,6 +893,9 @@ Instead, follow the instructions below.
A production-ready and secure setup requires at least three Consul nodes, two
Patroni nodes and one PgBouncer node on the secondary site.
+Because of [omnibus-6587](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6587), Consul can't track multiple
+services, so these need to be different than the nodes used for the Standby Cluster database.
+
Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni)
and other database best practices.
diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md
index 3be3c11947e..f3b4400c8c3 100644
--- a/doc/administration/get_started.md
+++ b/doc/administration/get_started.md
@@ -62,7 +62,7 @@ You may need to import projects from external sources like GitHub, Bitbucket, or
### Popular project imports
-- [GitHub Enterprise to self-managed GitLab](../integration/github.md#enabling-github-oauth): Enabling OAuth makes it easier for developers to find and import their projects.
+- [GitHub Enterprise to self-managed GitLab](../integration/github.md): Enabling OAuth makes it easier for developers to find and import their projects.
- [Bitbucket Server](../user/project/import/bitbucket_server.md#limitations): There are certain data limitations.
For assistance with these data types, contact your GitLab account manager or GitLab Support about our professional migration services.
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index a0c959d5de9..88efd1885db 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -28,6 +28,12 @@ The following configuration options are also available:
- Configuring the [number of `gitaly-ruby` workers](#configure-number-of-gitaly-ruby-workers).
- Limiting [RPC concurrency](#limit-rpc-concurrency).
+## About the Gitaly token
+
+The token referred to throughout the Gitaly documentation is just an arbitrary password selected by
+the administrator. It is unrelated to tokens created for the GitLab API or other similar web API
+tokens.
+
## Run Gitaly on its own server
By default, Gitaly is run on the same server as Gitaly clients and is
@@ -116,11 +122,6 @@ We assume your GitLab installation has three repository storages:
You can use as few as one server with one repository storage if desired.
-NOTE:
-The token referred to throughout the Gitaly documentation is just an arbitrary password selected by
-the administrator. It is unrelated to tokens created for the GitLab API or other similar web API
-tokens.
-
### Install Gitaly
Install Gitaly on each Gitaly server using either Omnibus GitLab or install it from source:
@@ -476,7 +477,7 @@ example:
```ruby
git_data_dirs({
'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
- # Address of the GitLab server that has Gitaly running on it
+ # Address of the GitLab server that also has Gitaly running on it
'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075', 'path' => '/mnt/gitlab/git-data' },
'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
})
@@ -565,12 +566,6 @@ Note the following:
- You can configure Gitaly servers with both an unencrypted listening address `listen_addr` and an
encrypted listening address `tls_listen_addr` at the same time. This allows you to gradually
transition from unencrypted to encrypted traffic if necessary.
-- When running Praefect sub-commands such as `dial-nodes` and `list-untracked-repositories` from the command line with Gitaly TLS enabled, you must set
- the `SSL_CERT_DIR` or `SSL_CERT_FILE` environment variable so that the Gitaly certificate is trusted. For example:
-
- ```shell
- sudo SSL_CERT_DIR=/etc/gitlab/trusted_certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
- ```
To configure Gitaly with TLS:
diff --git a/doc/administration/gitaly/faq.md b/doc/administration/gitaly/faq.md
index f79b9555c10..b0a88e8adc9 100644
--- a/doc/administration/gitaly/faq.md
+++ b/doc/administration/gitaly/faq.md
@@ -23,10 +23,10 @@ Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the r
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](index.md#strong-consistency) | Data storage in Git |
-| Geo | Multiple | Multiple | Up to one minute | [Manual](../geo/disaster_recovery/index.md) | Eventual | Entire GitLab instance |
+| Tool | Nodes | Locations | Latency tolerance | Failover | Consistency | Provides redundancy for |
+|:---------------|:---------|:----------|:------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------|:--------------------------------------|:------------------------|
+| Gitaly Cluster | Multiple | Single | [Less than 1 second, ideally single-digit milliseconds](praefect.md#network-latency-and-connectivity) | [Automatic](praefect.md#automatic-failover-and-primary-election-strategies) | [Strong](index.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:
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 4d60832720b..ea24e901943 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -290,7 +290,7 @@ including [horizontally distributing reads](https://gitlab.com/groups/gitlab-org
#### Distributed reads
-> - Introduced in GitLab 13.1 in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) with feature flag `gitaly_distributed_reads` set to disabled.
+> - Introduced in GitLab 13.1 in [beta](../../policy/alpha-beta-support.md#beta-features) with feature flag `gitaly_distributed_reads` set to disabled.
> - [Made generally available and enabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/2951) in GitLab 13.3.
> - [Disabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/3178) in GitLab 13.5.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/3334) in GitLab 13.8.
@@ -316,8 +316,8 @@ You can [monitor distribution of reads](#monitor-gitaly-cluster) using Prometheu
#### Strong consistency
-> - Introduced in GitLab 13.1 in [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga), disabled by default.
-> - Entered [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) in GitLab 13.2, disabled by default.
+> - Introduced in GitLab 13.1 in [alpha](../../policy/alpha-beta-support.md#alpha-features), disabled by default.
+> - Entered [beta](../../policy/alpha-beta-support.md#beta-features) in GitLab 13.2, disabled by default.
> - In GitLab 13.3, disabled unless primary-wins voting strategy is disabled.
> - From GitLab 13.4, enabled by default.
> - From GitLab 13.5, you must use Git v2.28.0 or higher on Gitaly nodes to enable strong consistency.
@@ -529,6 +529,10 @@ To monitor [strong consistency](#strong-consistency), you can use the following
- `gitaly_hook_transaction_voting_delay_seconds`, the client-side delay introduced by waiting for
the transaction to be committed.
+To monitor the number of repositories that have no healthy, up-to-date replicas:
+
+- `gitaly_praefect_unavailable_repositories`
+
You can also monitor the [Praefect logs](../logs.md#praefect-logs).
#### Database metrics `/db_metrics` endpoint
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index e2db30b8358..8f17835b8a3 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -39,10 +39,26 @@ NOTE:
If not set in GitLab, feature flags are read as false from the console and Praefect uses their
default value. The default value depends on the GitLab version.
-### Network connectivity
+### Network latency and connectivity
-Gitaly Cluster [components](index.md#components) need to communicate with each other over many
-routes. Your firewall rules must allow the following for Gitaly Cluster to function properly:
+Network latency for Gitaly Cluster should ideally be measurable in single-digit milliseconds. Latency is particularly
+important for:
+
+- Gitaly node health checks. Nodes must be able to respond within 1 second.
+- Reference transactions that enforce [strong consistency](index.md#strong-consistency). Lower latencies mean Gitaly
+ nodes can agree on changes faster.
+
+Achieving acceptable latency between Gitaly nodes:
+
+- On physical networks generally means high bandwidth, single location connections.
+- On the cloud generally means within the same region, including allowing cross availability zone replication. These links
+ are designed for this type of synchronization. Latency of less than 2ms should be sufficient for Gitaly Cluster.
+
+If you can't provide low network latencies for replication (for example, between distant locations), consider Geo. For
+more information, see [How does Gitaly Cluster compare to Geo](faq.md#how-does-gitaly-cluster-compare-to-geo).
+
+Gitaly Cluster [components](index.md#components) communicate with each other over many routes. Your firewall rules must
+allow the following for Gitaly Cluster to function properly:
| From | To | Default port | TLS port |
|:-----------------------|:-----------------------|:-------------|:---------|
@@ -254,11 +270,11 @@ reads distribution caching is enabled by configuration
To reduce PostgreSQL resource consumption, we recommend setting up and configuring
[PgBouncer](https://www.pgbouncer.org/) in front of the PostgreSQL instance. To do
-this, you must point Praefect to PgBouncer by setting Praefect database parameters:
+this, you must point Praefect to PgBouncer by setting database parameters on Praefect configuration:
```ruby
praefect['database_host'] = PGBOUNCER_HOST
-praefect['database_port'] = 5432
+praefect['database_port'] = 6432
praefect['database_user'] = 'praefect'
praefect['database_password'] = PRAEFECT_SQL_PASSWORD
praefect['database_dbname'] = 'praefect_production'
@@ -273,40 +289,21 @@ Praefect requires an additional connection to the PostgreSQL that supports the
this feature is only available with `session` pool mode (`pool_mode = session`).
It is not supported in `transaction` pool mode (`pool_mode = transaction`).
-For the additional connection, you must either:
+To configure the additional connection, you must either:
-- Connect Praefect directly to PostgreSQL and bypass PgBouncer.
- Configure a new PgBouncer database that uses to the same PostgreSQL database endpoint,
but with different pool mode. That is, `pool_mode = session`.
+- Connect Praefect directly to PostgreSQL and bypass PgBouncer.
-Praefect can be configured to use different connection parameters for direct access
-to PostgreSQL. This is the connection that supports the `LISTEN` feature.
-
-Here is an example of Praefect that bypasses PgBouncer and directly connects to PostgreSQL:
-
-```ruby
-praefect['database_direct_host'] = POSTGRESQL_HOST
-praefect['database_direct_port'] = 5432
-
-# Use the following to override parameters of direct database connection.
-# Comment out where the parameters are the same for both connections.
-
-praefect['database_direct_user'] = 'praefect'
-praefect['database_direct_password'] = PRAEFECT_SQL_PASSWORD
-praefect['database_direct_dbname'] = 'praefect_production'
-#praefect['database_direct_sslmode'] = '...'
-#praefect['database_direct_sslcert'] = '...'
-#praefect['database_direct_sslkey'] = '...'
-#praefect['database_direct_sslrootcert'] = '...'
-```
+#### Configure a new PgBouncer database with `pool_mode = session`
-We recommend using PgBouncer with `session` pool mode instead. You can use the
+We recommend using PgBouncer with `session` pool mode. You can use the
[bundled PgBouncer](../postgresql/pgbouncer.md) or use an external PgBouncer and [configure it
manually](https://www.pgbouncer.org/config.html).
-The following example uses the bundled PgBouncer and sets up two separate connection pools,
+The following example uses the bundled PgBouncer and sets up two separate connection pools on PostgreSQL host,
one in `session` pool mode and the other in `transaction` pool mode. For this example to work,
-you need to prepare PostgreSQL server with [setup instruction](#manual-database-setup):
+you need to prepare PostgreSQL server as documented in [in the setup instructions](#manual-database-setup):
```ruby
pgbouncer['databases'] = {
@@ -373,6 +370,29 @@ your databases manually and configuring an external PgBouncer, you must include
its password in the file used by PgBouncer. For example, `userlist.txt` if the [`auth_file`](https://www.pgbouncer.org/config.html#auth_file)
configuration option is set. For more details, consult the PgBouncer documentation.
+#### Configure Praefect to connect directly to PostgreSQL
+
+As an alternative to configuring PgBouncer with `session` pool mode, Praefect can be configured to use different connection parameters for direct access
+to PostgreSQL. This is the connection that supports the `LISTEN` feature.
+
+An example of Praefect configuration that bypasses PgBouncer and directly connects to PostgreSQL:
+
+```ruby
+praefect['database_direct_host'] = POSTGRESQL_HOST
+praefect['database_direct_port'] = 5432
+
+# Use the following to override parameters of direct database connection.
+# Comment out where the parameters are the same for both connections.
+
+praefect['database_direct_user'] = 'praefect'
+praefect['database_direct_password'] = PRAEFECT_SQL_PASSWORD
+praefect['database_direct_dbname'] = 'praefect_production'
+#praefect['database_direct_sslmode'] = '...'
+#praefect['database_direct_sslcert'] = '...'
+#praefect['database_direct_sslkey'] = '...'
+#praefect['database_direct_sslrootcert'] = '...'
+```
+
### Praefect
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) in GitLab 13.4, Praefect nodes can no longer be designated as `primary`.
@@ -570,15 +590,15 @@ On the **Praefect** node:
edit `/etc/gitlab/gitlab.rb`, remember to run `sudo gitlab-ctl reconfigure`
again before trying the `sql-ping` command.
-#### Enabling TLS support
+#### Enable TLS support
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/1698) in GitLab 13.2.
Praefect supports TLS encryption. To communicate with a Praefect instance that listens
for secure connections, you must:
-- Use a `tls://` URL scheme in the `gitaly_address` of the corresponding storage entry
- in the GitLab configuration.
+- Ensure Gitaly is [configured for TLS](configure_gitaly.md#enable-tls-support) and use a `tls://` URL scheme in the `gitaly_address`
+ of the corresponding storage entry in the GitLab configuration.
- Bring your own certificates because this isn't provided automatically. The certificate
corresponding to each Praefect server must be installed on that Praefect server.
@@ -594,6 +614,13 @@ Note the following:
- Hostname, you can either use the Common Name field for this, or add it as a Subject
Alternative Name.
- IP address, you must add it as a Subject Alternative Name to the certificate.
+- When running Praefect sub-commands such as `dial-nodes` and `list-untracked-repositories` from the command line with
+ [Gitaly TLS enabled](configure_gitaly.md#enable-tls-support), you must set the `SSL_CERT_DIR` or `SSL_CERT_FILE`
+ environment variable so that the Gitaly certificate is trusted. For example:
+
+ ```shell
+ sudo SSL_CERT_DIR=/etc/gitlab/trusted_certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
+ ```
- You can configure Praefect servers with both an unencrypted listening address
`listen_addr` and an encrypted listening address `tls_listen_addr` at the same time.
@@ -639,7 +666,7 @@ To configure Praefect with TLS:
```ruby
git_data_dirs({
"default" => {
- "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:2305',
+ "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:3305',
"gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
}
})
@@ -957,7 +984,10 @@ Particular attention should be shown to:
balancer.
- `PRAEFECT_EXTERNAL_TOKEN` with the real secret
- If you are using TLS, the `gitaly_address` should begin with `tls://`.
+ If you are using TLS:
+
+ - The `gitaly_address` should begin with `tls://` instead.
+ - The port should be changed to `3305`.
```ruby
git_data_dirs({
diff --git a/doc/administration/gitaly/recovery.md b/doc/administration/gitaly/recovery.md
index e1b9a73908d..9210c8f08d3 100644
--- a/doc/administration/gitaly/recovery.md
+++ b/doc/administration/gitaly/recovery.md
@@ -28,7 +28,7 @@ To minimize data loss in GitLab 13.0 to 14.0, Gitaly Cluster:
### Read-only mode
-> - Introduced in GitLab 13.0 as [generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+> - Introduced in GitLab 13.0 as [generally available](../../policy/alpha-beta-support.md#generally-available-ga).
> - Between GitLab 13.0 and GitLab 13.2, read-only mode applied to the whole virtual storage and occurred whenever failover occurred.
> - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/2862), read-only mode applies on a per-repository basis and only occurs if a new primary is out of date.
new primary. If the failed primary contained unreplicated writes, [data loss can occur](#check-for-data-loss).
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index fdd281c1a90..ff136b44340 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -435,6 +435,15 @@ Here are common errors and potential causes:
- Praefect cannot reach one or more of its child Gitaly nodes. Try running
the Praefect connection checker to diagnose.
+### Praefect database experiencing high CPU load
+
+Some common reasons for the Praefect database to experience elevated CPU usage include:
+
+- Prometheus metrics scrapes [running an expensive query](https://gitlab.com/gitlab-org/gitaly/-/issues/3796). If you have GitLab 14.2
+ or above, set `praefect['separate_database_metrics'] = true` in `gitlab.rb`.
+- [Read distribution caching](praefect.md#reads-distribution-caching) is disabled, increasing the number of queries made to the
+ database when user traffic is high. Ensure read distribution caching is enabled.
+
### Determine primary Gitaly node
To determine the primary node of a repository:
diff --git a/doc/administration/img/custom_hooks_error_msg.png b/doc/administration/img/custom_hooks_error_msg.png
deleted file mode 100644
index e7d5c157d08..00000000000
--- a/doc/administration/img/custom_hooks_error_msg.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 84b30724dff..cd1f39b1295 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -62,8 +62,8 @@ can reserve your catch-all mailbox for other purposes.
### Dedicated email address
-This solution is relatively simple to set up: you just need to create an email
-address dedicated to receive your users' replies to GitLab notifications. However,
+To set up this solution, you must create a dedicated email
+address to receive your users' replies to GitLab notifications. However,
this method only supports replies, and not the other features of [incoming email](#incoming-email).
## Accepted headers
@@ -75,7 +75,7 @@ Email is processed correctly when a configured email address is present in one o
- `Envelope-To` or `X-Envelope-To`
In GitLab 14.6 and later, [Service Desk](../user/project/service_desk.md)
-also checks these additional headers.
+also checks accepted headers.
Usually, the "To" field contains the email address of the primary receiver.
However, it might not include the configured GitLab email address if:
@@ -84,6 +84,14 @@ However, it might not include the configured GitLab email address if:
- The address was included when using "Reply all".
- The email was forwarded.
+## Rejected headers
+
+To prevent unwanted issue creation from automatic email systems, GitLab ignores all incoming email
+containing the following headers:
+
+- `Auto-Submitted` with a value other than `no`
+- `X-Autoreply` with a value of `yes`
+
## Set it up
If you want to use Gmail / Google Apps for incoming email, make sure you have
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 3bedb6b01bd..614ab5278c5 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -214,7 +214,7 @@ or `git push --mirror` is used.
This limit does not affect any of the updated merge request pipelines.
All updated merge requests have a pipeline created when using
-[pipelines for merge requests](../ci/pipelines/merge_request_pipelines.md).
+[merge request pipelines](../ci/pipelines/merge_request_pipelines.md).
## Retention of activity history
@@ -228,7 +228,11 @@ There is a limit when embedding metrics in GitLab Flavored Markdown (GFM) for pe
- **Max limit**: 100 embeds.
-## Number of webhooks
+## Webhook limits
+
+Also see [Webhook rate limits](#webhook-rate-limit).
+
+### Number of webhooks
To set the maximum number of group or project webhooks for a self-managed installation,
run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
@@ -246,11 +250,33 @@ Plan.default.actual_limits.update!(group_hooks: 100)
Set the limit to `0` to disable it.
-- **Default maximum number of webhooks**: `100` per project, `50` per group
-- **Maximum payload size**: 25 MB
+The default maximum number of webhooks is `100` per project, `50` per group.
For GitLab.com, see the [webhook limits for GitLab.com](../user/gitlab_com/index.md#webhooks).
+### Webhook payload size
+
+The maximum webhook payload size is 25 MB.
+
+### Recursive webhooks
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329743) in GitLab 14.8.
+
+GitLab detects and blocks webhooks that are recursive or that exceed the limit
+of webhooks that can be triggered from other webhooks. This enables GitLab to
+continue to support workflows that use webhooks to call the API non-recursively, or that
+do not trigger an unreasonable number of other webhooks.
+
+Recursion can happen when a webhook is configured to make a call
+to its own GitLab instance (for example, the API). The call then triggers the same
+webhook and creates an infinite loop.
+
+The maximum number of requests to an instance made by a series of webhooks that
+trigger other webhooks is 100. When the limit is reached, GitLab blocks any further
+webhooks that would be triggered by the series.
+
+Blocked recursive webhook calls are logged in `auth.log` with the message `"Recursive webhook blocked from executing"`.
+
## Pull Mirroring Interval
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/237891) in GitLab 13.7.
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 62c403bfe43..8f824fcefb3 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
---
@@ -440,10 +440,7 @@ To change the number of projects listed, change the number in `limit(50)`.
#### Delete job artifacts from jobs completed before a specific date
WARNING:
-These commands remove data permanently from the database and from disk. We
-highly recommend running them only under the guidance of a Support Engineer, or
-running them in a test environment with a backup of the instance ready to be
-restored, just in case.
+These commands remove data permanently from both the database and from disk. Before running them, we highly recommend seeking guidance from a Support Engineer, or running them in a test environment with a backup of the instance ready to be restored, just in case.
If you need to manually remove job artifacts associated with multiple jobs while
**retaining their job logs**, this can be done from the Rails console (`sudo gitlab-rails console`):
@@ -490,10 +487,7 @@ If you need to manually remove job artifacts associated with multiple jobs while
#### Delete job artifacts and logs from jobs completed before a specific date
WARNING:
-These commands remove data permanently from both the database and from disk. We
-highly recommend running them only under the guidance of a Support Engineer, or
-running them in a test environment with a backup of the instance ready to be
-restored, just in case.
+These commands remove data permanently from both the database and from disk. Before running them, we highly recommend seeking guidance from a Support Engineer, or running them in a test environment with a backup of the instance ready to be restored, just in case.
If you need to manually remove **all** job artifacts associated with multiple jobs,
**including job logs**, this can be done from the Rails console (`sudo gitlab-rails console`):
diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md
index 60293e56202..45fd6e65078 100644
--- a/doc/administration/load_balancer.md
+++ b/doc/administration/load_balancer.md
@@ -2,7 +2,6 @@
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
---
# Load Balancer for multi-node GitLab **(FREE SELF)**
@@ -21,38 +20,38 @@ How do you want to handle SSL in your multi-node environment? There are several
options:
- Each application node terminates SSL
-- The load balancer(s) terminate SSL and communication is not secure between
- the load balancer(s) and the application nodes
-- The load balancer(s) terminate SSL and communication is *secure* between the
- load balancer(s) and the application nodes
+- The load balancers terminate SSL and communication is not secure between
+ the load balancers and the application nodes
+- The load balancers terminate SSL and communication is *secure* between the
+ load balancers and the application nodes
### Application nodes terminate SSL
-Configure your load balancer(s) to pass connections on port 443 as 'TCP' rather
+Configure your load balancers to pass connections on port 443 as 'TCP' rather
than 'HTTP(S)' protocol. This passes the connection to the application nodes
NGINX service untouched. NGINX has the SSL certificate and listen on port 443.
See [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
-### Load Balancer(s) terminate SSL without backend SSL
+### Load Balancers terminate SSL without backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) is be responsible for managing SSL certificates and
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers is be responsible for managing SSL certificates and
terminating SSL.
-Since communication between the load balancer(s) and GitLab isn't secure,
+Since communication between the load balancers and GitLab isn't secure,
there is some additional configuration needed. See
[NGINX Proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
for details.
-### Load Balancer(s) terminate SSL with backend SSL
+### Load Balancers terminate SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) is responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers is responsible for managing SSL certificates that
end users see.
-Traffic is secure between the load balancer(s) and NGINX in this
+Traffic is secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection is secure all the way. However, configuration must be
added to GitLab to configure SSL certificates. See
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 0d7635405d6..c4e9642d048 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md
index e91483eb79d..e16e9bb0336 100644
--- a/doc/administration/monitoring/github_imports.md
+++ b/doc/administration/monitoring/github_imports.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index 1cf4e5a25ba..911d76a89e3 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -1,13 +1,17 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
-# Self monitoring project **(FREE SELF)**
+# Self-monitoring project (DEPRECATED) **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32351) in GitLab 12.7, behind a disabled feature flag (`self_monitoring_project`).
-> - The feature flag was removed and the self monitoring project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/198511) in GitLab 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32351) in GitLab 12.7 [with a flag](../../feature_flags.md) named `self_monitoring_project`. Disabled by default.
+> - Generally available in GitLab 12.8. [Feature flag `self_monitoring_project`](https://gitlab.com/gitlab-org/gitlab/-/issues/198511) removed.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/348909) in GitLab 14.8.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/348909) in GitLab 14.8.
GitLab provides administrators insights into the health of their GitLab instance.
diff --git a/doc/administration/monitoring/index.md b/doc/administration/monitoring/index.md
index 4c49efd6bd5..df655053723 100644
--- a/doc/administration/monitoring/index.md
+++ b/doc/administration/monitoring/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/ip_whitelist.md b/doc/administration/monitoring/ip_whitelist.md
index 75b09f8a366..b8347ba3f0d 100644
--- a/doc/administration/monitoring/ip_whitelist.md
+++ b/doc/administration/monitoring/ip_whitelist.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index f316a75a868..128ddad6555 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index c37a264938e..79612145327 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index f3db6ac9f03..20fad8baf91 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 14a560223f9..e93dbd3a2d6 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -108,7 +108,7 @@ appears next to requests with warnings.
The performance bar is disabled by default for non-administrators. To enable it
for a given group:
-1. Sign in as a user with Administrator [role](../../../user/permissions.md).
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**
(`admin/application_settings/metrics_and_profiling`), and expand
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index ebdca8d3960..f8a66f6f48f 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -1,10 +1,16 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
-# Request Profiling **(FREE SELF)**
+# Request profiling (DEPRECATED) **(FREE SELF)**
+
+> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352488) in GitLab 14.8, and planned for removal in GitLab 15.0.
+
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352488)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0.
To profile a request:
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index d9852524aec..15ec880533e 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index c5b87afd94b..a1bfae678c7 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To enable the GitLab Prometheus metrics:
-1. Log in to GitLab as a user with Administrator [role](../../../user/permissions.md).
+1. Log in to GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Find the **Metrics - Prometheus** section, and select **Add link to Prometheus**.
@@ -48,6 +48,7 @@ The following metrics are available:
| `gitlab_database_transaction_seconds` | Histogram | 12.1 | Time spent in database transactions, in seconds | |
| `gitlab_method_call_duration_seconds` | Histogram | 10.2 | Method calls real duration | `controller`, `action`, `module`, `method` |
| `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | `controller`, `action`, `bot` |
+| `gitlab_rails_boot_time_seconds` | Gauge | 14.8 | Time elapsed for Rails primary process to finish startup | |
| `gitlab_rails_queue_duration_seconds` | Histogram | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | |
| `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding `SCHEMA` operations and `BEGIN` / `COMMIT` | |
| `gitlab_sql_<role>_duration_seconds` | Histogram | 13.10 | SQL execution time, excluding `SCHEMA` operations and `BEGIN` / `COMMIT`, grouped by database roles (primary/replica) | |
@@ -269,6 +270,16 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_pages_deployments_verification_total` | Gauge | 14.6 | Number of pages deployments verifications tried on secondary | `url` |
| `geo_pages_deployments_verified` | Gauge | 14.6 | Number of pages deployments verified on secondary | `url` |
| `geo_pages_deployments_verification_failed` | Gauge | 14.6 | Number of pages deployments verifications failed on secondary | `url` |
+| `geo_job_artifacts` | Gauge | 14.8 | Number of job artifacts on primary | `url` |
+| `geo_job_artifacts_checksum_total` | Gauge | 14.8 | Number of job artifacts tried to checksum on primary | `url` |
+| `geo_job_artifacts_checksummed` | Gauge | 14.8 | Number of job artifacts successfully checksummed on primary | `url` |
+| `geo_job_artifacts_checksum_failed` | Gauge | 14.8 | Number of job artifacts failed to calculate the checksum on primary | `url` |
+| `geo_job_artifacts_synced` | Gauge | 14.8 | Number of syncable job artifacts synced on secondary | `url` |
+| `geo_job_artifacts_failed` | Gauge | 14.8 | Number of syncable job artifacts failed to sync on secondary | `url` |
+| `geo_job_artifacts_registry` | Gauge | 14.8 | Number of job artifacts in the registry | `url` |
+| `geo_job_artifacts_verification_total` | Gauge | 14.8 | Number of job artifacts verifications tried on secondary | `url` |
+| `geo_job_artifacts_verified` | Gauge | 14.8 | Number of job artifacts verified on secondary | `url` |
+| `geo_job_artifacts_verification_failed` | Gauge | 14.8 | Number of job artifacts verifications failed on secondary | `url` |
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index acdcdb41dca..9d90c4f3cc7 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -295,6 +295,36 @@ To use an external Prometheus server:
1. Reload the Prometheus server.
+### Configure the storage retention size
+
+Prometheus has several custom flags to configure local storage:
+
+- `storage.tsdb.retention.time`: when to remove old data. Defaults to `15d`. Overrides
+ `storage.tsdb.retention` if this flag is set to anything other than the default.
+- `storage.tsdb.retention.size`: [EXPERIMENTAL] the maximum number of bytes of storage blocks to
+ retain. The oldest data is removed first. Defaults to `0` (disabled). This flag is experimental
+ and may change in future releases. Units supported: `B`, `KB`, `MB`, `GB`, `TB`, `PB`, `EB`. For
+ example, `512MB`.
+
+To configure the storage retention size:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ prometheus['flags'] = {
+ 'storage.tsdb.path' => "/var/opt/gitlab/prometheus/data",
+ 'storage.tsdb.retention.time' => "7d",
+ 'storage.tsdb.retention.size' => "2GB",
+ 'config.file' => "/var/opt/gitlab/prometheus/prometheus.yml"
+ }
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
## Viewing performance metrics
You can visit `http://localhost:9090` for the dashboard that Prometheus offers by default.
@@ -402,3 +432,35 @@ To disable the monitoring of Kubernetes:
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to
take effect.
+
+## Troubleshooting
+
+### `/var/opt/gitlab/prometheus` consumes too much disk space
+
+If you are **not** using Prometheus monitoring:
+
+1. [Disable Prometheus](index.md#configuring-prometheus).
+1. Delete the data under `/var/opt/gitlab/prometheus`.
+
+If you are using Prometheus monitoring:
+
+1. Stop Prometheus (deleting data while it's running can cause data corruption):
+
+ ```shell
+ gitlab-ctl stop prometheus
+ ```
+
+1. Delete the data under `/var/opt/gitlab/prometheus/data`.
+1. Start the service again:
+
+ ```shell
+ gitlab-ctl start prometheus
+ ```
+
+1. Verify the service is up and running:
+
+ ```shell
+ gitlab-ctl status prometheus
+ ```
+
+1. Optional. [Configure the storage retention size](index.md#configure-the-storage-retention-size).
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index 68d997d7596..d7a4a96cd9a 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index aba1561500a..979a6bcd232 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 8a851afe35b..95a6540bd19 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/puma_exporter.md b/doc/administration/monitoring/prometheus/puma_exporter.md
index 804c4243cfa..794e2c10b25 100644
--- a/doc/administration/monitoring/prometheus/puma_exporter.md
+++ b/doc/administration/monitoring/prometheus/puma_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index 6cc262842a1..a5f12bbc52f 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/monitoring/prometheus/registry_exporter.md b/doc/administration/monitoring/prometheus/registry_exporter.md
index 3a2acd47338..f4fa35c206e 100644
--- a/doc/administration/monitoring/prometheus/registry_exporter.md
+++ b/doc/administration/monitoring/prometheus/registry_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/administration/nfs.md b/doc/administration/nfs.md
index 87a10a0ec04..50c8102f366 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -24,11 +24,9 @@ file system performance, see
Starting with GitLab version 14.0, support for NFS to store Git repository data is deprecated. Technical customer support and engineering support is available for the 14.x releases. Engineering is fixing bugs and security vulnerabilities consistent with our [release and maintenance policy](../policy/maintenance.md#security-releases).
-At the end of the 14.12 milestone (tentatively June 22nd, 2022) technical and engineering support for using NFS to store Git repository data will be officially at end-of-life. There will be no product changes or troubleshooting provided via Engineering, Security or Paid Support channels.
+Upon the release of GitLab 15.0 (tentatively May 22nd, 2022) technical and engineering support for using NFS to store Git repository data will be officially at end-of-life. There will be no product changes or troubleshooting provided via Engineering, Security or Paid Support channels after the release date of 15.0, regardless of your GitLab version.
-For those customers still running earlier versions of GitLab, [our support eligibility and maintenance policy applies](https://about.gitlab.com/support/statement-of-support.html#version-support).
-
-For the 14.x releases, we continue to help with Git related tickets from customers running one or more Gitaly servers with its data stored on NFS. Examples may include:
+Until the release of 15.0, for customers running 14.x releases, we continue to help with Git related tickets from customers running one or more Gitaly servers with its data stored on NFS. Examples may include:
- Performance issues or timeouts accessing Git data
- Commits or branches vanish
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 0976fc3684e..420f2191ef2 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -526,7 +526,7 @@ To migrate existing local data to object storage see the following guides:
- [Uploads](raketasks/uploads/migrate.md#migrate-to-object-storage)
- [Merge request diffs](merge_request_diffs.md#using-object-storage)
- [Packages](packages/index.md#migrating-local-packages-to-object-storage) (optional feature)
-- Dependency Proxy - [migration not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/343064)
+- [Dependency Proxy](packages/dependency_proxy.md#migrate-local-dependency-proxy-blobs-and-manifests-to-object-storage)
- [Terraform state files](terraform_state.md#migrate-to-object-storage)
- [Pages content](pages/index.md#migrate-pages-deployments-to-object-storage)
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 1c9b98041dc..fd04efe8473 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -296,7 +296,7 @@ Instead of a queue, a queue namespace can also be provided, to have the process
automatically listen on all queues in that namespace without needing to
explicitly list all the queue names. For more information about queue namespaces,
see the relevant section in the
-[Sidekiq style guide](../../development/sidekiq_style_guide.md#queue-namespaces).
+[Sidekiq development documentation](../../development/sidekiq/index.md#queue-namespaces).
For example, say you want to start 2 extra processes: one to process the
`process_commit` queue, and one to process the `post_receive` queue. This can be
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index ddedb3fe76a..dca99879cc3 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -138,7 +138,7 @@ This is a brief overview. Please refer to the above instructions for more contex
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299109) in GitLab 14.5.
WARNING:
-`gitlab-sshd` is in [**Alpha**](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga).
+`gitlab-sshd` is in [**Alpha**](../../policy/alpha-beta-support.md#alpha-features).
It is not ready for production use.
`gitlab-sshd` is [a standalone SSH server](https://gitlab.com/gitlab-org/gitlab-shell/-/tree/main/internal/sshd)
@@ -178,3 +178,22 @@ GitLab supports `authorized_keys` database lookups with [SELinux](https://en.wik
Because the SELinux policy is static, GitLab doesn't support the ability to change
internal webserver ports at the moment. Administrators would have to create a special `.te`
file for the environment, since it isn't generated dynamically.
+
+## Troubleshooting
+
+If your SSH traffic is [slow](https://github.com/linux-pam/linux-pam/issues/270)
+or causing high CPU load, be sure to check the size of `/var/log/btmp`, and ensure it is rotated on a regular basis.
+If this file is very large, GitLab SSH fast lookup can cause the bottleneck to be hit more frequently, thus decreasing performance even further.
+If you are able to, you may consider disabling [`UsePAM` in your `sshd_config`](https://linux.die.net/man/5/sshd_config) to avoid reading `/var/log/btmp` altogether.
+
+Running `strace` and `lsof` on a running `sshd: git` process can return useful debugging information. To get an `strace` on an in-progress Git over SSH connection for IP `x.x.x.x`, run:
+
+```plaintext
+sudo strace -s 10000 -p $(sudo netstat -tp | grep x.x.x.x | egrep 'ssh.*: git' | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')
+```
+
+Or get an `lsof` for a running Git over SSH process:
+
+```plaintext
+sudo lsof -p $(sudo netstat -tp | egrep 'ssh.*: git' | head -1 | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')
+```
diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md
index 78f496a3998..71ebc4d3647 100644
--- a/doc/administration/package_information/supported_os.md
+++ b/doc/administration/package_information/supported_os.md
@@ -23,7 +23,6 @@ The following lists the currently supported OSs and their possible EOL dates.
| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | 2022 | <https://wiki.debian.org/LTS> |
| Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | 2024 | <https://wiki.debian.org/LTS> |
| Debian 11 | GitLab CE / GitLab EE 14.6.0 | amd64, arm64 | 2026 | <https://wiki.debian.org/LTS> |
-| OpenSUSE 15.2 | GitLab CE / GitLab EE 13.11.0 | x86_64, aarch64 | Dec 2021 | <https://en.opensuse.org/Lifetime> |
| OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | Nov 2022 | <https://en.opensuse.org/Lifetime> |
| SLES 12 | GitLab EE 9.0.0 | x86_64 | Oct 2027 | <https://www.suse.com/lifecycle/> |
| Ubuntu 18.04 | GitLab CE / GitLab EE 10.7.0 | amd64 | April 2023 | <https://wiki.ubuntu.com/Releases> |
@@ -81,8 +80,9 @@ release for them can be found below:
| Raspbian Stretch | [June 2020](https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_13.2&dist=raspbian%2Fstretch) 13.3 |
| Debian Jessie | [June 2020](https://www.debian.org/News/2020/20200709) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.2&dist=debian%2Fjessie) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.2&dist=debian%2Fjessie) 13.3 |
| CentOS 6 | [November 2020](https://wiki.centos.org/About/Product) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=13.6&filter=all&filter=all&dist=el%2F6) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=13.6&filter=all&filter=all&dist=el%2F6) 13.6 |
-| OpenSUSE 15.1 | [November 2020](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-13.12&dist=opensuse%2F15.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-13.12&dist=opensuse%2F15.2) 13.12 |
+| OpenSUSE 15.1 | [November 2020](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-13.12&dist=opensuse%2F15.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-13.12&dist=opensuse%2F15.1) 13.12 |
| Ubuntu 16.04 | [April 2021](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.12&dist=ubuntu%2Fxenial) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.12&dist=ubuntu%2Fxenial) 13.12 |
+| OpenSUSE 15.2 | [December 2021](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-14.7&dist=opensuse%2F15.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-14.7&dist=opensuse%2F15.2) 14.7 |
NOTE:
An exception to this deprecation policy is when we are unable to provide
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 43293385ed9..33a5311709f 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -662,14 +662,14 @@ configurable in future releases.
The Registry server listens on localhost at port `5000` by default,
which is the address for which the Registry server should accept connections.
-In the examples below we set the Registry's port to `5001`.
+In the examples below we set the Registry's port to `5010`.
**Omnibus GitLab**
1. Open `/etc/gitlab/gitlab.rb` and set `registry['registry_http_addr']`:
```ruby
- registry['registry_http_addr'] = "localhost:5001"
+ registry['registry_http_addr'] = "localhost:5010"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -681,7 +681,7 @@ In the examples below we set the Registry's port to `5001`.
```yaml
http:
- addr: localhost:5001
+ addr: localhost:5010
```
1. Save the file and restart the Registry server.
@@ -1379,7 +1379,7 @@ project or branch name. Special characters can include:
To get around this, you can [change the group path](../../user/group/index.md#change-a-groups-path),
[change the project path](../../user/project/settings/index.md#renaming-a-repository) or change the
-branch name. Another option is to create a [push rule](../../push_rules/push_rules.md) to prevent
+branch name. Another option is to create a [push rule](../../user/project/repository/push_rules.md) to prevent
this at the instance level.
### Image push errors
@@ -1548,6 +1548,46 @@ To fix this you can do one of two things:
We use a concrete example to illustrate how to
diagnose a problem with the S3 setup.
+#### Investigate a cleanup policy
+
+If you're unsure why your cleanup policy did or didn't delete a tag, execute the policy line by line
+by running the below script from the [Rails console](../../administration/operations/rails_console.md).
+This can help diagnose problems with the policy.
+
+```ruby
+repo = ContainerRepository.find(<project_id>)
+policy = repo.project.container_expiration_policy
+
+tags = repo.tags
+tags.map(&:name)
+
+tags.reject!(&:latest?)
+tags.map(&:name)
+
+regex_delete = ::Gitlab::UntrustedRegexp.new("\\A#{policy.name_regex}\\z")
+regex_retain = ::Gitlab::UntrustedRegexp.new("\\A#{policy.name_regex_keep}\\z")
+
+tags.select! { |tag| regex_delete.match?(tag.name) && !regex_retain.match?(tag.name) }
+
+tags.map(&:name)
+
+now = DateTime.current
+tags.sort_by! { |tag| tag.created_at || now }.reverse! # Lengthy operation
+
+tags = tags.drop(policy.keep_n)
+tags.map(&:name)
+
+older_than_timestamp = ChronicDuration.parse(policy.older_than).seconds.ago
+
+tags.select! { |tag| tag.created_at && tag.created_at < older_than_timestamp }
+
+tags.map(&:name)
+```
+
+- The script builds the list of tags to delete (`tags`).
+- `tags.map(&:name)` prints a list of tags to remove. This may be a lengthy operation.
+- After each filter, check the list of `tags` to see if it contains the intended tags to destroy.
+
#### Unexpected 403 error during push
A user attempted to enable an S3-backed Registry. The `docker login` step went
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index b3dc6ffc2b2..93c6585230f 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -199,6 +199,55 @@ This section describes the earlier configuration format.
1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect.
+#### Migrate local Dependency Proxy blobs and manifests to object storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79663) in GitLab 14.8.
+
+After [configuring object storage](#using-object-storage),
+use the following task to migrate existing Dependency Proxy blobs and manifests from local storage
+to remote storage. The processing is done in a background worker and requires no downtime.
+
+For Omnibus GitLab:
+
+```shell
+sudo gitlab-rake "gitlab:dependency_proxy:migrate"
+```
+
+For installations from source:
+
+```shell
+RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:dependency_proxy:migrate
+```
+
+You can optionally track progress and verify that all packages migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- For Omnibus GitLab instances: `sudo gitlab-rails dbconsole`
+- For installations from source: `sudo -u git -H psql -d gitlabhq_production`
+
+Verify that `objectstg` (where `file_store = '2'`) has the count of all Dependency Proxy blobs and
+manifests for each respective query:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM dependency_proxy_blobs;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 22 | 0 | 22
+
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM dependency_proxy_manifests;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 10 | 0 | 10
+```
+
+Verify that there are no files on disk in the `dependency_proxy` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/shared/dependency_proxy -type f | grep -v tmp | wc -l
+```
+
## Disabling Authentication
Authentication was introduced in 13.7 as part of [enabling private groups to use the
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index eea4964efbe..abf5c46114b 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -240,7 +240,7 @@ You can optionally track progress and verify that all packages migrated successf
- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
-Verify `objectstg` below (where `store=2`) has count of all packages:
+Verify `objectstg` below (where `file_store = '2'`) has count of all packages:
```shell
gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM packages_package_files;
diff --git a/doc/administration/pages/img/pages_deploy_failure_v14_8.png b/doc/administration/pages/img/pages_deploy_failure_v14_8.png
new file mode 100644
index 00000000000..ec502b86453
--- /dev/null
+++ b/doc/administration/pages/img/pages_deploy_failure_v14_8.png
Binary files differ
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 53510688794..f000824711f 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -238,6 +238,7 @@ control over how the Pages daemon runs and serves content in your environment.
| `artifacts_server_url` | API URL to proxy artifact requests to. Defaults to GitLab `external URL` + `/api/v4`, for example `https://gitlab.com/api/v4`. When running a [separate Pages server](#running-gitlab-pages-on-a-separate-server), this URL must point to the main GitLab server's API. |
| `auth_redirect_uri` | Callback URL for authenticating with GitLab. Defaults to project's subdomain of `pages_external_url` + `/auth`. |
| `auth_secret` | Secret key for signing authentication requests. Leave blank to pull automatically from GitLab during OAuth registration. |
+| `client_cert_key_pairs` | Client certificates and keys used for mutual TLS with the GitLab API. See [Support mutual TLS when calling the GitLab API](#support-mutual-tls-when-calling-the-gitlab-api) for details. [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) in GitLab 14.8. |
| `dir` | Working directory for configuration and secrets files. |
| `enable` | Enable or disable GitLab Pages on the current system. |
| `external_http` | Configure Pages to bind to one or more secondary IP addresses, serving HTTP requests. Multiple addresses can be given as an array, along with exact ports, for example `['1.2.3.4', '1.2.3.5:8063']`. Sets value for `listen_http`. |
@@ -511,6 +512,22 @@ Authority (CA) in the system certificate store.
For Omnibus, this is fixed by [installing a custom CA in Omnibus GitLab](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
+### Support mutual TLS when calling the GitLab API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) in GitLab 14.8.
+
+If GitLab has been [configured to require mutual TLS](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-2-way-ssl-client-authentication), you need to add the client certificates to Pages:
+
+1. Configure in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['client_cert_key_pairs'] = ['</path/to/cert>:</path/to/key>']
+ ```
+
+ Where `</path/to/cert>` and `</path/to/key>` are the file paths to the client certificate and its respective key file.
+ Both of these files must be encoded in PEM format.
+1. To configure Pages to validate the server certificates, [add the root CA to the system trust store](#using-a-custom-certificate-authority-ca).
+
### ZIP serving and cache configuration
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/392) in GitLab 13.7.
@@ -688,7 +705,7 @@ To override the global maximum pages size for a specific group:
## Running GitLab Pages on a separate server
You can run the GitLab Pages daemon on a separate server to decrease the load on
-your main application server. This configuration does not support mutual TLS (mTLS). See the [corresponding feature proposal](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) for more information.
+your main application server.
To configure GitLab Pages on a separate server:
@@ -1021,6 +1038,25 @@ Migrate your existing Pages deployments from local storage to object storage:
sudo gitlab-rake gitlab:pages:deployments:migrate_to_object_storage
```
+You can track progress and verify that all Pages deployments migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all Pages deployments:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM pages_deployments;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 10 | 0 | 10
+```
+
+After verifying everything is working correctly,
+[disable Pages local storage](#disable-pages-local-storage).
+
### Rolling Pages deployments back to local storage
After the migration to object storage is performed, you can choose to move your Pages deployments back to local storage:
@@ -1033,7 +1069,7 @@ sudo gitlab-rake gitlab:pages:deployments:migrate_to_local
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/301159) in GitLab 13.11.
-If you use [object storage](#using-object-storage), you can disable local storage:
+If you use [object storage](#using-object-storage), you can disable local storage to avoid unnecessary disk usage/writes:
1. Edit `/etc/gitlab/gitlab.rb`:
@@ -1064,6 +1100,8 @@ is the default starting from GitLab 14.0. Skip this step if you're already runni
1. If you want to store your pages content in [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. If you have configured GitLab to store your pages content in [object storage](#using-object-storage),
+ [migrate Pages deployments to object storage](#migrate-pages-deployments-to-object-storage)
1. Upgrade GitLab to 14.0.
## Backup
@@ -1077,8 +1115,6 @@ than GitLab to prevent XSS attacks.
### Rate limits
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/631) in GitLab 14.5.
-
You can enforce rate limits to help minimize the risk of a Denial of Service (DoS) attack. GitLab Pages
uses a [token bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket) to enforce rate limiting. By default,
requests that exceed the specified limits are reported but not rejected.
@@ -1098,6 +1134,8 @@ Rate limits are enforced using the following:
#### Enable source-IP rate limits
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/631) in GitLab 14.5.
+
1. Set rate limits in `/etc/gitlab/gitlab.rb`:
```ruby
@@ -1116,6 +1154,8 @@ Rate limits are enforced using the following:
#### Enable domain rate limits
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/630) in GitLab 14.7.
+
1. Set rate limits in `/etc/gitlab/gitlab.rb`:
```ruby
@@ -1495,3 +1535,20 @@ behavior:
NOTE:
`inplace_chroot` option might not work with the other features, such as [Pages Access Control](#access-control).
The [GitLab Pages README](https://gitlab.com/gitlab-org/gitlab-pages#caveats) has more information about caveats and workarounds.
+
+### GitLab Pages deploy job fails with error "is not a recognized provider"
+
+If the **pages** job succeeds but the **deploy** job gives the error "is not a recognized provider":
+
+![Pages Deploy Failure](img/pages_deploy_failure_v14_8.png)
+
+The error message `is not a recognized provider` could be coming from the `fog` gem that GitLab uses to connect to cloud providers for object storage.
+
+To fix that:
+
+1. Check your `gitlab.rb` file. If you have `gitlab_rails['pages_object_store_enabled']` enabled, but no bucket details have been configured, either:
+
+ - Configure object storage for your Pages deployments, following the [S3-compatible connection settings](#s3-compatible-connection-settings) guide.
+ - Store your deployments locally, by commenting out that line.
+
+1. Save the changes you made to your `gitlab.rb` file, then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md
index b83820dd0b6..1324666c32b 100644
--- a/doc/administration/postgresql/database_load_balancing.md
+++ b/doc/administration/postgresql/database_load_balancing.md
@@ -147,9 +147,9 @@ When the list of hosts is updated, it might take a while for the old connections
to be terminated. The `disconnect_timeout` setting can be used to enforce an
upper limit on the time it takes to terminate all old database connections.
-### Handling Stale Reads **(PREMIUM SELF)**
+### Handling stale reads
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3526) in GitLab 10.3.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/327902) from GitLab Premium to GitLab Free in 14.0.
To prevent reading from an outdated secondary the load balancer checks if it
is in sync with the primary. If the data is recent enough, the
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 5777f35bfcf..8c7151606a5 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -1029,7 +1029,7 @@ Considering these, you should carefully plan your PostgreSQL upgrade:
```
NOTE:
- `gitlab-ctl pg-upgrade` tries to detect the role of the node. If for any reason the auto-detection does not work or you believe it did not detect the role correctly, you can use the `--leader` or `--replica` arguments to manually override it.
+ On a Geo secondary site, the Patroni leader node is called `standby leader`.
1. Stop Patroni **only on replicas**.
@@ -1049,6 +1049,11 @@ Considering these, you should carefully plan your PostgreSQL upgrade:
sudo gitlab-ctl pg-upgrade -V 12
```
+ NOTE:
+ `gitlab-ctl pg-upgrade` tries to detect the role of the node. If for any reason the auto-detection
+ does not work or you believe it did not detect the role correctly, you can use the `--leader` or
+ `--replica` arguments to manually override it.
+
1. Check the status of the leader and cluster. You can proceed only if you have a healthy leader:
```shell
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index e6adb98a92a..cae2465fad8 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index a5c60af47b1..eb1127b5e99 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -12,7 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 10,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=e77713f6-dc0b-4bb3-bcef-cea904ac8efd)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested daily with the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
@@ -274,11 +274,11 @@ for details.
### Load balancer terminates SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) will be responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers will be responsible for managing SSL certificates that
end users will see.
-Traffic will also be secure between the load balancer(s) and NGINX in this
+Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
@@ -2234,7 +2234,7 @@ future with further specific cloud provider details.
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index ed6fbe84a48..0d0e7681ffd 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -18,6 +18,7 @@ many organizations.
> - **Supported users (approximate):** 1,000
> - **High Availability:** No. For a highly-available environment, you can
> follow a modified [3K reference architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid:** No. For a cloud native hybrid environment, you
> can follow a [modified hybrid reference architecture](#cloud-native-hybrid-reference-architecture-with-helm-charts).
> - **Performance tested daily with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 8cc355db951..86819024eeb 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -12,7 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 25,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=925386e1-c01c-4c0a-8d7d-ebde1824b7b0)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
@@ -277,11 +277,11 @@ for details.
### Load balancer terminates SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) will be responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers will be responsible for managing SSL certificates that
end users will see.
-Traffic will also be secure between the load balancer(s) and NGINX in this
+Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
@@ -2232,7 +2232,7 @@ future with further specific cloud provider details.
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 467c64b8279..f6c484b08b1 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -13,7 +13,7 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 2,000
> - **High Availability:** No. For a highly-available environment, you can
> follow a modified [3K reference architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=84d11491-d72a-493c-a16e-650931faa658)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested daily with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
@@ -1022,7 +1022,7 @@ future with further specific cloud provider details.
| Sidekiq | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | 1.9 vCPU, 5.5 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 01d9987739b..587303a1f8f 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -22,7 +22,7 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 3,000
> - **High Availability:** Yes, although [Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=ac4838e6-9c40-4a36-ac43-6d1bc1843e08)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
@@ -278,11 +278,11 @@ for details.
### Load balancer terminates SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) will be responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers will be responsible for managing SSL certificates that
end users will see.
-Traffic will also be secure between the load balancer(s) and NGINX in this
+Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
@@ -2191,7 +2191,7 @@ future with further specific cloud provider details.
| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index d5bb9c4ad64..f4bf232d548 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -12,7 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 50,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=8006396b-88ee-40cd-a1c8-77cdefa4d3c8)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
@@ -283,11 +283,11 @@ for details.
### Load balancer terminates SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) will be responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers will be responsible for managing SSL certificates that
end users will see.
-Traffic will also be secure between the load balancer(s) and NGINX in this
+Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
@@ -2248,7 +2248,7 @@ future with further specific cloud provider details.
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 33ca4e4899f..4014ec04904 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -19,7 +19,7 @@ costly-to-operate environment by using the
> - **Supported users (approximate):** 5,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=8742e8ea-c08f-4e0a-b058-02f3a1c38a2f)
+> - **Estimated Costs:** [See cost table](index.md#cost-to-run)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
@@ -276,11 +276,11 @@ for details.
### Load balancer terminates SSL with backend SSL
-Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
-The load balancer(s) will be responsible for managing SSL certificates that
+Configure your load balancers to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancers will be responsible for managing SSL certificates that
end users will see.
-Traffic will also be secure between the load balancer(s) and NGINX in this
+Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
@@ -2167,7 +2167,7 @@ future with further specific cloud provider details.
| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
-- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results)
+- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
- 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.
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index bd796600564..815155866e8 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -59,7 +59,9 @@ provided architecture.
## Available reference architectures
-The following reference architectures are available:
+The following reference architectures are available.
+
+### GitLab package (Omnibus)
- [Up to 1,000 users](1k_users.md)
- [Up to 2,000 users](2k_users.md)
@@ -69,6 +71,8 @@ The following reference architectures are available:
- [Up to 25,000 users](25k_users.md)
- [Up to 50,000 users](50k_users.md)
+### Cloud native hybrid
+
The following Cloud Native Hybrid reference architectures, where select recommended components can be run in Kubernetes, are available:
- [Up to 2,000 users](2k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
@@ -83,6 +87,204 @@ to get assistance from Support with troubleshooting the [2,000 users](2k_users.m
and higher reference architectures.
[Read more about our definition of scaled architectures](https://about.gitlab.com/support/#definition-of-scaled-architecture).
+### Validation and test results
+
+The [Quality Engineering - Enablement team](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/) does regular smoke and performance tests for the reference architectures to ensure they remain compliant.
+
+- Testing occurs against all reference architectures and cloud providers in an automated and ad-hoc fashion. This is done by two tools:
+ - The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) for building the environments.
+ - The [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) for performance testing.
+- Network latency on the test environments between components on all Cloud Providers were measured at <5ms. Note that this is shared as an observation and not as an implicit recommendation.
+- We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on 10k Omnibus on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids.
+- Testing is done publicly and all results are shared.
+- For more information about performance testing at GitLab, read [how our QA team leverages GitLab’s performance testing tool (and you can too)](https://about.gitlab.com/blog/2020/02/18/how-were-building-up-performance-testing-of-gitlab/).
+
+The following table details the testing done against the reference architectures along with the frequency and results. Additional testing is continuously evaluated, and the table is updated accordingly.
+
+<style>
+table.test-coverage td {
+ border-left: 1px solid #dbdbdb;
+ border-right: 1px solid #dbdbdb;
+ border-bottom: 1px solid #dbdbdb;
+}
+
+table.test-coverage th {
+ border-left: 1px solid #dbdbdb;
+ border-right: 1px solid #dbdbdb;
+ border-bottom: 1px solid #dbdbdb;
+}
+</style>
+
+<table class="test-coverage">
+ <col>
+ <colgroup span="2"></colgroup>
+ <colgroup span="2"></colgroup>
+ <tr>
+ <th rowspan="2">Reference<br/>Architecture</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">GCP (* also proxy for Bare-Metal)</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">AWS</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">Azure</th>
+ </tr>
+ <tr>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ </tr>
+ <tr>
+ <th scope="row">1k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k">Daily</a> (to be moved to Weekly)</td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">2k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k">Daily</a> (to be moved to Weekly)</td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">3k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k">Weekly</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">5k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k">Weekly</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">10k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k">Daily</a></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k-Cloud-Native-Hybrid">Ad-Hoc</a></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k">Ad-Hoc (inc Cloud Services)</a></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k-Cloud-Native-Hybrid">Ad-Hoc</a></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k">Ad-Hoc</a></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">25k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k">Weekly</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/25k">Ad-Hoc</a></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">50k</th>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k">Weekly</a></td>
+ <td></td>
+ <td><a href="https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/50k">Ad-Hoc (inc Cloud Services)</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+</table>
+
+The Standard Reference Architectures are designed to be platform agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
+
+### Cost to run
+
+<table class="test-coverage">
+ <col>
+ <colgroup span="2"></colgroup>
+ <colgroup span="2"></colgroup>
+ <tr>
+ <th rowspan="2">Reference<br/>Architecture</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">GCP</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">AWS</th>
+ <th style="text-align: center" colspan="2" scope="colgroup">Azure</th>
+ </tr>
+ <tr>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ <th scope="col">Omnibus</th>
+ <th scope="col">Cloud Native Hybrid</th>
+ </tr>
+ <tr>
+ <th scope="row">1k</th>
+ <td><a href="https://cloud.google.com/products/calculator#id=a6d6a94a-c7dc-4c22-85c4-7c5747f272ed">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">2k</th>
+ <td><a href="https://cloud.google.com/products/calculator#id=84d11491-d72a-493c-a16e-650931faa658">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">3k</th>
+ <td><a href="https://cloud.google.com/products/calculator/#id=ac4838e6-9c40-4a36-ac43-6d1bc1843e08">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">5k</th>
+ <td><a href="https://cloud.google.com/products/calculator/#id=8742e8ea-c08f-4e0a-b058-02f3a1c38a2f">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">10k</th>
+ <td><a href="https://cloud.google.com/products/calculator#id=e77713f6-dc0b-4bb3-bcef-cea904ac8efd">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">25k</th>
+ <td><a href="https://cloud.google.com/products/calculator#id=925386e1-c01c-4c0a-8d7d-ebde1824b7b0">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <th scope="row">50k</th>
+ <td><a href="https://cloud.google.com/products/calculator/#id=8006396b-88ee-40cd-a1c8-77cdefa4d3c8">Calculated cost</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+</table>
+
## Availability Components
GitLab comes with the following components for your use, listed from least to
@@ -191,33 +393,3 @@ The reference architectures for user counts [3,000](3k_users.md) and up support
In the specific case you have the requirement to achieve HA but have a lower user count, select modifications to the [3,000 user](3k_users.md) architecture are supported.
For more details, [refer to this section in the architecture's documentation](3k_users.md#supported-modifications-for-lower-user-counts-ha).
-
-## Testing process and results
-
-The [Quality Engineering - Enablement team](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/) does regular smoke and performance tests for the reference architectures to ensure they remain compliant.
-
-In this section, we detail some of the process as well as the results.
-
-Note the following about the testing process:
-
-- Testing occurs against all main reference architectures and cloud providers in an automated and ad-hoc fashion.
- This is achieved through two tools built by the team:
- - The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) for building the environments.
- - The [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) for performance testing.
-- Network latency on the test environments between components on all Cloud Providers were measured at <5ms. Note that this is shared as an observation and not as an implicit recommendation.
-- We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on 10k Omnibus on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids.
-- Testing is done publicly and all results are shared.
-
-Τhe following table details the testing done against the reference architectures along with the frequency and results. Note that this list above is non exhaustive. Additional testing is continuously evaluated and iterated on, and the table is updated accordingly.
-
-| Reference<br/>Architecture<br/>Size | Bare-Metal | GCP | AWS | Azure |
-|-----------------------------|------------|-----|-----|-------|
-| 1k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)<sup>1</sup> | - | - |
-| 2k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)<sup>1</sup> | - | - |
-| 3k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)<sup>1</sup> | - | - |
-| 5k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)<sup>1</sup> | - | - |
-| 10k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Daily](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)<sup>1</sup> <br/> [Standard (inc Cloud Services) - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k) <br/> [Cloud Native Hybrid - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k-Cloud-Native-Hybrid) | [Standard (inc Cloud Services) - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k) <br/> [Cloud Native Hybrid - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k-Cloud-Native-Hybrid) | [Standard - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k) |
-| 25k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)<sup>1</sup> | - | [Standard - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/25k) |
-| 50k | <i>Refer to GCP<sup>1</sup></i> | [Standard - Weekly](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)<sup>1</sup> | [Standard (inc Cloud Services) - Ad-Hoc](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/50k) | - |
-
-1. The Standard Reference Architectures are designed to be platform agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 9579d413bf8..88909b2b9d8 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# How to restart GitLab **(FREE SELF)**
Depending on how you installed GitLab, there are different methods to restart
-its service(s).
+its services.
## Omnibus installations
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 2a431d17774..9d8bc03e5e9 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -10,171 +10,135 @@ disqus_identifier: 'https://docs.gitlab.com/ee/administration/custom_hooks.html'
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196051) in GitLab 12.8 replacing Custom Hooks.
-Git supports hooks that are executed on different actions. These hooks run on the server and can be
-used to enforce specific commit policies or perform other tasks based on the state of the
-repository.
+Server hooks run custom logic on the GitLab server. Users can use them to run Git-related tasks such as:
-Git supports the following hooks:
+- Enforcing specific commit policies.
+- Performing tasks based on the state of the repository.
-- `pre-receive`
-- `post-receive`
-- `update`
+Server hooks use `pre-receive`, `post-receive`, and `update`
+[Git server-side hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_server_side_hooks).
-See [the Git documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_server_side_hooks)
-for more information about each hook type.
+GitLab administrators configure server hooks on the file system of the GitLab server. If you don't have file system access,
+alternatives to server hooks include:
-Server-side Git hooks can be configured for:
+- [Webhooks](../user/project/integrations/webhooks.md).
+- [GitLab CI/CD](../ci/index.md).
+- [Push rules](../push_rules/push_rules.md), for a user-configurable Git hook interface.
-- [A single repository](#create-a-server-hook-for-a-repository).
-- [All repositories](#create-a-global-server-hook-for-all-repositories).
+[Geo](geo/index.md) doesn't replicate server hooks to secondary nodes.
-Note the following about server hooks:
+## Create a server hook for a single repository
-- Server hooks must be configured on the file system of the GitLab server. Only GitLab server
- administrators are able to complete these tasks. If you don't have file system access, see
- possible alternatives such as:
- - [Webhooks](../user/project/integrations/webhooks.md).
- - [GitLab CI/CD](../ci/index.md).
- - [Push Rules](../push_rules/push_rules.md), for a user-configurable Git hook
- interface.
-- Server hooks aren't replicated to [Geo](geo/index.md) secondary nodes.
+To create a server hook for a single repository:
-## Create a server hook for a repository
+1. On the top bar, select **Menu > Admin**.
+1. Go to **Overview > Projects** and select the project you want to add a server hook to.
+1. On the page that appears, locate the value of **Gitaly relative path**. This path is where server hooks must be located.
+ - If you are using [hashed storage](repository_storage_types.md#hashed-storage), see
+ [Translate hashed storage paths](repository_storage_types.md#translate-hashed-storage-paths) for information on
+ interpreting the relative path.
+ - If you are not using [hashed storage](repository_storage_types.md#hashed-storage):
+ - For Omnibus GitLab installations, the path is usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
+ - For an installation from source, the path is usually `/home/git/repositories/<group>/<project>.git`.
+1. On the file system, create a new directory in the correct location called `custom_hooks`.
+1. In the new `custom_hooks` directory, create a file with a name that matches the hook type. For example, for a
+ `pre-receive` server hook, the filename should be `pre-receive` with no extension.
+1. Make the server hook file executable and ensure that it's owned by the Git user.
+1. Write the code to make the server hook function as expected. Server hooks can be in any programming language. Ensure
+ the [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top reflects the language type. For
+ example, if the script is in Ruby the shebang is probably `#!/usr/bin/env ruby`.
-If you are not using [hashed storage](repository_storage_types.md#hashed-storage), the project's
-repository directory might not exactly match the instructions below. In that case:
-
-- For an installation from source, the path is usually
- `/home/git/repositories/<group>/<project>.git`.
-- For Omnibus GitLab installs, the path is usually
- `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
-
-Follow the steps below to set up a server-side hook for a repository:
-
-1. Go to **Admin area > Projects** and select the project you want to add a server hook to.
-1. Locate the **Gitaly relative path** on the page that appears. This is where the server hook
- must be implemented. For information on interpreting the relative path, see
- [Translate hashed storage paths](repository_storage_types.md#translate-hashed-storage-paths).
-1. On the file system, create a new directory in this location called `custom_hooks`.
-1. Inside the new `custom_hooks` directory, create a file with a name matching the hook type. For
- example, for a pre-receive hook the filename should be `pre-receive` with no extension.
-1. Make the hook file executable and ensure that it's owned by the Git user.
-1. Write the code to make the server hook function as expected. Hooks can be in any language. Ensure
- the ["shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top properly reflects the
- language type. For example, if the script is in Ruby the shebang is probably
- `#!/usr/bin/env ruby`.
-
-Assuming the hook code is properly implemented, the hook code is executed as appropriate.
+If the server hook code is properly implemented, it should execute when the Git hook is next triggered.
## Create a global server hook for all repositories
-To create a Git hook that applies to all of the repositories in your instance, set a global server
-hook. The default global server hook directory is in the GitLab Shell directory. Any
-hook added there applies to all repositories, including:
+To create a Git hook that applies to all repositories, set a global server hook. The default global server hook directory
+is in the GitLab Shell directory. Any server hook added there applies to all repositories, including:
+
+- [Project and group wiki](../user/project/wiki/index.md) repositories. Their storage directory names are in the format
+ `<id>.wiki.git`.
+- [Design management](../user/project/issues/design_management.md) repositories under a project. Their storage directory
+ names are in the format `<id>.design.git`.
-- [Project and group wiki](../user/project/wiki/index.md) repositories,
- whose storage directory names are in the format `<id>.wiki.git`.
-- [Design management](../user/project/issues/design_management.md) repositories under a
- project, whose storage directory names are in the format `<id>.design.git`.
+### Choose a server hook directory
-The default directory:
+Before creating a global server hook, you must choose a directory for it. The default global server hook directory:
+- For Omnibus GitLab installations is usually `/opt/gitlab/embedded/service/gitlab-shell/hooks`.
- For an installation from source is usually `/home/git/gitlab-shell/hooks`.
-- For Omnibus GitLab installs is usually `/opt/gitlab/embedded/service/gitlab-shell/hooks`.
-To use a different directory for global server hooks, set `custom_hooks_dir` in Gitaly
-configuration:
+To use a different directory for global server hooks, set `custom_hooks_dir` in Gitaly configuration:
-- For Omnibus installations, this is set in `gitlab.rb`.
+- For Omnibus installations, set in `gitlab.rb`.
- For source installations, the configuration location depends on the GitLab version. For:
- - GitLab 13.0 and earlier, this is set in `gitlab-shell/config.yml`.
- - GitLab 13.1 and later, this is set in `gitaly/config.toml` under the `[hooks]` section.
-
-NOTE:
-The `custom_hooks_dir` value in `gitlab-shell/config.yml` is still honored in GitLab 13.1 and later
-if the value in `gitaly/config.toml` is blank or non-existent.
+ - GitLab 13.0 and earlier, set in `gitlab-shell/config.yml`.
+ - GitLab 13.1 and later, set in `gitaly/config.toml` under the `[hooks]` section. However, GitLab honors the
+ `custom_hooks_dir` value in `gitlab-shell/config.yml` if the value in `gitaly/config.toml` is blank or non-existent.
-Follow the steps below to set up a global server hook for all repositories:
+### Create the global server hook
-1. On the GitLab server, navigate to the configured global server hook directory.
-1. Create a new directory in this location. Depending on the type of hook, it can be either a
- `pre-receive.d`, `post-receive.d`, or `update.d` directory.
-1. Inside this new directory, add your hook. Hooks can be in any language. Ensure the
- ["shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top properly reflects the
- language type. For example, if the script is in Ruby the shebang is probably
- `#!/usr/bin/env ruby`.
-1. Make the hook file executable and ensure that it's owned by the Git user.
+To create a global server hook for all repositories:
-Now test the hook to check whether it is functioning properly.
+1. On the GitLab server, go to the configured global server hook directory.
+1. Create a new directory in this location called `pre-receive.d`, `post-receive.d`, or `update.d`, depending on the type
+ of server hook. Any other names are ignored.
+1. Inside this new directory, add your server hook. Server hooks can be in any programming language. Ensure the
+ [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top reflects the language type. For example, if the
+ script is in Ruby the shebang is probably `#!/usr/bin/env ruby`.
+1. Make the hook file executable, ensure that it's owned by the Git user, and ensure it does not match the backup file
+ pattern (`*~`).
-## Chained hooks
+If the server hook code is properly implemented, it should execute when the Git hook is next triggered.
-Server hooks set [per project](#create-a-server-hook-for-a-repository) or
-[globally](#create-a-global-server-hook-for-all-repositories) can be executed in a chain.
+## Chained server hooks
-Server hooks are searched for and executed in the following order of priority:
+GitLab can execute server hooks in a chain. GitLab searches for and executes server hooks in the following order:
-- Built-in GitLab server hooks. These are not user-customizable.
-- `<project>.git/custom_hooks/<hook_name>`: Per-project hooks. This was kept for backwards
- compatibility.
+- Built-in GitLab server hooks. These server hooks are not customizable by users.
+- `<project>.git/custom_hooks/<hook_name>`: Per-project hooks. This location is kept for backwards compatibility.
- `<project>.git/custom_hooks/<hook_name>.d/*`: Location for per-project hooks.
-- `<custom_hooks_dir>/<hook_name>.d/*`: Location for all executable global hook files
- except editor backup files.
+- `<custom_hooks_dir>/<hook_name>.d/*`: Location for all executable global hook files except editor backup files.
-Within a directory, server hooks:
+Within a server hooks directory, hooks:
- Are executed in alphabetical order.
- Stop executing when a hook exits with a non-zero value.
-`<hook_name>.d` must be either `pre-receive.d`, `post-receive.d`, or `update.d` to work properly.
-Any other names are ignored.
+## Environment variables available to server hooks
-Files in `.d` directories must be executable and not match the backup file pattern (`*~`).
+You can pass any environment variable to server hooks, but you should only rely on supported environment variables.
-For `<project>.git` you need to [translate](repository_storage_types.md#translate-hashed-storage-paths)
-your project name into the hashed storage format that GitLab uses.
+The following GitLab environment variables are supported for all server hooks:
-## Environment Variables
+| Environment variable | Description |
+|:---------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `GL_ID` | GitLab identifier of user that initiated the push. For example, `user-2234`. |
+| `GL_PROJECT_PATH` | (GitLab 13.2 and later) GitLab project path. |
+| `GL_PROTOCOL` | (GitLab 13.2 and later) Protocol used for this change. One of: `http` (Git `push` using HTTP), `ssh` (Git `push` using SSH), or `web` (all other actions). |
+| `GL_REPOSITORY` | `project-<id>` where `id` is the ID of the project. |
+| `GL_USERNAME` | GitLab username of the user that initiated the push. |
-The following set of environment variables are available to server hooks.
-
-| Environment variable | Description |
-|:---------------------|:----------------------------------------------------------------------------|
-| `GL_ID` | GitLab identifier of user that initiated the push. For example, `user-2234` |
-| `GL_PROJECT_PATH` | (GitLab 13.2 and later) GitLab project path |
-| `GL_PROTOCOL` | (GitLab 13.2 and later) Protocol used for this change. One of: `http` (Git Push using HTTP), `ssh` (Git Push using SSH), or `web` (all other actions). |
-| `GL_REPOSITORY` | `project-<id>` where `id` is the ID of the project |
-| `GL_USERNAME` | GitLab username of the user that initiated the push |
-
-Pre-receive and post-receive server hooks can also access the following Git environment variables.
+The following Git environment variables are supported for `pre-receive` and `post-receive` server hooks:
| Environment variable | Description |
|:-----------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `GIT_ALTERNATE_OBJECT_DIRECTORIES` | Alternate object directories in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). |
| `GIT_OBJECT_DIRECTORY` | GitLab project path in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). |
-| `GIT_PUSH_OPTION_COUNT` | Number of push options. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
-| `GIT_PUSH_OPTION_<i>` | Value of push options where `i` is from `0` to `GIT_PUSH_OPTION_COUNT - 1`. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
-
-NOTE:
-While other environment variables can be passed to server hooks, your application should not rely on
-them as they can change.
+| `GIT_PUSH_OPTION_COUNT` | Number of [push options](../user/project/push_options.md). See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
+| `GIT_PUSH_OPTION_<i>` | Value of [push options](../user/project/push_options.md) where `i` is from `0` to `GIT_PUSH_OPTION_COUNT - 1`. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
## Custom error messages
-To have custom error messages appear in the GitLab UI when a commit is declined or an error occurs
-during the Git hook, your script should:
+You can have custom error messages appear in the GitLab UI when a commit is declined or an error occurs during the Git
+hook. To display a custom error message, your script must:
- Send the custom error messages to either the script's `stdout` or `stderr`.
- Prefix each message with `GL-HOOK-ERR:` with no characters appearing before the prefix.
-### Example custom error message
-
-This hook script written in Bash generates the following message in the GitLab UI:
+For example:
```shell
#!/bin/sh
echo "GL-HOOK-ERR: My custom error message.";
exit 1
```
-
-![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md
index 989a024d6ab..fea6ac9e554 100644
--- a/doc/administration/sidekiq.md
+++ b/doc/administration/sidekiq.md
@@ -4,77 +4,131 @@ 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
---
-# Configuring Sidekiq **(FREE SELF)**
+# Configure an external Sidekiq instance **(FREE SELF)**
-This section discusses how to configure an external Sidekiq instance using the
-bundled Sidekiq in the GitLab package.
+You can configure an external Sidekiq instance by using the Sidekiq that's
+bundled in the GitLab package. Sidekiq requires connection to the Redis,
+PostgreSQL, and Gitaly instances.
-Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance.
-To configure the Sidekiq node:
+## Required configuration
+
+To configure Sidekiq:
1. SSH into the Sidekiq server.
-1. [Download/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. Open `/etc/gitlab/gitlab.rb` with your editor.
-1. Generate the Sidekiq configuration:
+1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab package
+ using steps 1 and 2. **Do not complete any other steps.**
+1. Edit `/etc/gitlab/gitlab.rb` with the following information and make sure
+ to replace with your values:
```ruby
- ## Optional: Enable extra Sidekiq processes
- sidekiq_cluster['enable'] = true
- sidekiq['queue_groups'] = [
- "elastic_commit_indexer",
- "*"
- ]
- ```
+ ##
+ ## To maintain uniformity of links across nodes, the
+ ##`external_url` on the Sidekiq server should point to the external URL that users
+ ## use to access GitLab. This can be either:
+ ##
+ ## - The `external_url` set on your application server.
+ ## - The URL of a external load balancer, which routes traffic to the GitLab application server.
+ ##
-1. Setup Sidekiq's connection to Redis:
+ external_url 'https://gitlab.example.com'
+
+ ## Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
+
+ ########################################
+ ##### Services Disabled ###
+ ########################################
+ #
+ # When running GitLab on just one server, you have a single `gitlab.rb`
+ # to enable all services you want to run.
+ # When running GitLab on N servers, you have N `gitlab.rb` files.
+ # Enable only the services you want to run on each
+ # specific server, while disabling all others.
+ #
+ nginx['enable'] = false
+ grafana['enable'] = false
+ prometheus['enable'] = false
+ gitlab_rails['auto_migrate'] = false
+ alertmanager['enable'] = false
+ gitaly['enable'] = false
+ gitlab_workhorse['enable'] = false
+ nginx['enable'] = false
+ postgres_exporter['enable'] = false
+ postgresql['enable'] = false
+ redis['enable'] = false
+ redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_exporter['enable'] = false
+
+ #######################################
+ ### Sidekiq configuration ###
+ #######################################
+ sidekiq['enable'] = true
+ sidekiq['listen_address'] = "0.0.0.0"
+
+ ## 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
+ sidekiq['max_concurrency'] = 10
+
+ ########################################
+ #### Redis ###
+ ########################################
- ```ruby
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis'
## The same password for Redis authentication you set up for the master node.
- redis['master_password'] = 'YOUR_PASSOWORD'
-
- ## A list of sentinels with `host` and `port`
- gitlab_rails['redis_sentinels'] = [
- {'host' => '10.10.1.34', 'port' => 26379},
- {'host' => '10.10.1.35', 'port' => 26379},
- {'host' => '10.10.1.36', 'port' => 26379},
- ]
- ```
+ redis['master_password'] = '<redis_master_password>'
-1. Set up Sidekiq's connection to Gitaly:
+ #######################################
+ ### Gitaly ###
+ #######################################
- ```ruby
+ ## Replace <gitaly_token> with the one you set up, see
+ ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token
git_data_dirs({
'default' => { 'gitaly_address' => 'tcp://gitaly:8075' },
})
- gitlab_rails['gitaly_token'] = 'YOUR_TOKEN'
- ```
+ gitlab_rails['gitaly_token'] = '<gitaly_token>'
-1. Set up Sidekiq's connection to PostgreSQL:
+ #######################################
+ ### Postgres ###
+ #######################################
- ```ruby
- gitlab_rails['db_host'] = '10.10.1.30'
- gitlab_rails['db_password'] = 'YOUR_PASSOWORD'
+ # Replace <database_host> and <database_password>
+ gitlab_rails['db_host'] = '<database_host>'
+ gitlab_rails['db_password'] = '<database_password>'
gitlab_rails['db_port'] = '5432'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
gitlab_rails['auto_migrate'] = false
+
+ # Add the Sidekiq nodes to PostgreSQL's trusted addresses.
+ # In the following example, 10.10.1.30/32 is the private IP
+ # of the Sidekiq server.
+ postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32)
```
- Remember to add the Sidekiq nodes to PostgreSQL's trusted addresses:
+1. Reconfigure GitLab:
- ```ruby
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32)
+ ```shell
+ sudo gitlab-ctl reconfigure
```
-1. If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
- specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
- and GIDs prevents permissions issues in the file system. This advice is similar to the
- [advice for Geo setups](geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site):
+1. Restart the Sidekiq nodes after completing the process and finishing the database migrations.
+
+## Configure multiple Sidekiq nodes with shared storage
+
+If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
+specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
+and GIDs prevents permissions issues in the file system. This advice is similar to the
+[advice for Geo setups](geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site).
+
+To set up multiple Sidekiq nodes:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
user['uid'] = 9000
@@ -85,180 +139,87 @@ you want using steps 1 and 2 from the GitLab downloads page.
registry['gid'] = 9002
```
-1. Disable other services:
+1. Reconfigure GitLab:
- ```ruby
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- gitlab_rails['auto_migrate'] = false
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_monitor['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- puma['enable'] = false
- gitlab_exporter['enable'] = false
+ ```shell
+ sudo gitlab-ctl reconfigure
```
-1. If you're using the Container Registry and it's running on a different node than Sidekiq, then
- configure the registry URL:
+## Configure the Container Registry when using an external Sidekiq
+
+If you're using the Container Registry and it's running on a different
+node than Sidekiq, follow the steps below.
+
+1. Edit `/etc/gitlab/gitlab.rb`, and configure the registry URL:
```ruby
registry_external_url 'https://registry.example.com'
gitlab_rails['registry_api_url'] = "https://registry.example.com"
```
-
- You must also copy the `registry.key` file to each Sidekiq node.
-1. Define the `external_url`. To maintain uniformity of links across nodes, the
- `external_url` on the Sidekiq server should point to the external URL that users
- will use to access GitLab. This will either be the `external_url` set on your
- application server or the URL of a external load balancer which will route traffic
- to the GitLab application server:
+1. Reconfigure GitLab:
- ```ruby
- external_url 'https://gitlab.example.com'
+ ```shell
+ sudo gitlab-ctl reconfigure
```
-1. (Optional) If you want to collect Sidekiq metrics, enable the Sidekiq metrics server.
- To make metrics available from `localhost:8082/metrics`, set the following values:
+1. In the instance where Container Registry is hosted, copy the `registry.key`
+ file to the Sidekiq node.
+
+## Configure the Sidekiq metrics server
+
+If you want to collect Sidekiq metrics, enable the Sidekiq metrics server.
+To make metrics available from `localhost:8082/metrics`:
+
+To configure the metrics server:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
sidekiq['metrics_enabled'] = true
sidekiq['listen_address'] = "localhost"
sidekiq['listen_port'] = "8082"
-
+
# Optionally log all the metrics server logs to log/sidekiq_exporter.log
sidekiq['exporter_log_enabled'] = true
```
-1. (Optional) If you use health check probes to observe Sidekiq,
- set a separate port for health checks.
- Configuring health checks is only necessary if there is something that actually probes them.
- For more information about health checks, see the [Sidekiq health check page](sidekiq_health_check.md).
- Enable health checks for Sidekiq:
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Configure health checks
+
+If you use health check probes to observe Sidekiq,
+you can set a separate port for health checks.
+Configuring health checks is only necessary if there is something that actually probes them.
+For more information about health checks, see the [Sidekiq health check page](sidekiq_health_check.md).
+
+To enable health checks for Sidekiq:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
- sidekiq['health_checks_enabled'] = true
- sidekiq['health_checks_listen_address'] = "localhost"
- sidekiq['health_checks_listen_port'] = "8092"
+ sidekiq['health_checks_enabled'] = true
+ sidekiq['health_checks_listen_address'] = "localhost"
+ sidekiq['health_checks_listen_port'] = "8092"
```
NOTE:
- If health check settings are not set, they will default to the metrics exporter settings.
+ If health check settings are not set, they default to the metrics exporter settings.
This default is deprecated and is set to be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/347509).
-1. Run `gitlab-ctl reconfigure`.
-
-You will need to restart the Sidekiq nodes after an update has occurred and database
-migrations performed.
-
-## Example configuration
-
-Here's what the ending `/etc/gitlab/gitlab.rb` would look like:
-
-```ruby
-########################################
-##### Services Disabled ###
-########################################
-
-nginx['enable'] = false
-grafana['enable'] = false
-prometheus['enable'] = false
-gitlab_rails['auto_migrate'] = false
-alertmanager['enable'] = false
-gitaly['enable'] = false
-gitlab_workhorse['enable'] = false
-nginx['enable'] = false
-postgres_exporter['enable'] = false
-postgresql['enable'] = false
-redis['enable'] = false
-redis_exporter['enable'] = false
-puma['enable'] = false
-gitlab_exporter['enable'] = false
-
-########################################
-#### Redis ###
-########################################
-
-## Must be the same in every sentinel node
-redis['master_name'] = 'gitlab-redis'
-
-## The same password for Redis authentication you set up for the master node.
-redis['master_password'] = 'YOUR_PASSOWORD'
-
-## A list of sentinels with `host` and `port`
-gitlab_rails['redis_sentinels'] = [
- {'host' => '10.10.1.34', 'port' => 26379},
- {'host' => '10.10.1.35', 'port' => 26379},
- {'host' => '10.10.1.36', 'port' => 26379},
- ]
-
-#######################################
-### Gitaly ###
-#######################################
-
-git_data_dirs({
- 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' },
-})
-gitlab_rails['gitaly_token'] = 'YOUR_TOKEN'
-
-#######################################
-### Postgres ###
-#######################################
-gitlab_rails['db_host'] = '10.10.1.30'
-gitlab_rails['db_password'] = 'YOUR_PASSOWORD'
-gitlab_rails['db_port'] = '5432'
-gitlab_rails['db_adapter'] = 'postgresql'
-gitlab_rails['db_encoding'] = 'unicode'
-gitlab_rails['auto_migrate'] = false
-
-#######################################
-### Sidekiq configuration ###
-#######################################
-sidekiq['metrics_enabled'] = true
-sidekiq['exporter_log_enabled'] = false
-sidekiq['listen_port'] = "8082"
-
-sidekiq['health_checks_enabled'] = true
-sidekiq['health_checks_listen_address'] = "localhost"
-sidekiq['health_checks_listen_port'] = "8092"
-
-#######################################
-### Monitoring configuration ###
-#######################################
-consul['enable'] = true
-consul['monitoring_service_discovery'] = true
-
-consul['configuration'] = {
- bind_addr: '10.10.1.48',
- retry_join: %w(10.10.1.34 10.10.1.35 10.10.1.36)
-}
-
-# Set the network addresses that the exporters will listen on
-node_exporter['listen_address'] = '10.10.1.48:9100'
-
-# Rails Status for prometheus
-gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1']
-
-# Container Registry URL for cleanup jobs
-registry_external_url 'https://registry.example.com'
-gitlab_rails['registry_api_url'] = "https://registry.example.com"
-
-# External URL (this should match the URL used to access your GitLab instance)
-external_url 'https://gitlab.example.com'
-```
-
-## Further reading
-
-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/)
-1. [Sidekiq health checks](sidekiq_health_check.md)
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Related topics
+
+- [Extra Sidekiq processes](operations/extra_sidekiq_processes.md)
+- [Extra Sidekiq routing](operations/extra_sidekiq_routing.md)
+- [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/)
+- [Sidekiq health checks](sidekiq_health_check.md)
diff --git a/doc/administration/troubleshooting/diagnostics_tools.md b/doc/administration/troubleshooting/diagnostics_tools.md
index 53d4810b920..d510df5976c 100644
--- a/doc/administration/troubleshooting/diagnostics_tools.md
+++ b/doc/administration/troubleshooting/diagnostics_tools.md
@@ -23,3 +23,7 @@ running on.
[strace-parser](https://gitlab.com/wchandler/strace-parser) is a small tool to analyze
and summarize raw `strace` data.
+
+## kubesos
+
+The [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) utiltity retrieves GitLab cluster configuration and logs from GitLab Cloud Native chart deployments.
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 33a81c12811..265c5278fd6 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -78,6 +78,43 @@ Notify.test_email(e, "Test email for #{n}", 'Test email').deliver_now
Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
```
+## Limiting output
+
+Adding a semicolon(`;`) and a follow-up statement at the end of a statement prevents the default implicit return output. This is useful if you are already explicitly printing details and potentially have a lot of return output:
+
+```ruby
+puts ActiveRecord::Base.descendants; :ok
+Project.select(&:pages_deployed?).each {|p| puts p.pages_url }; true
+```
+
+## Get or store the result of last operation
+
+Underscore(`_`) represents the implicit return of the previous statement. You can use this to quickly assign a variable from the output of the previous command:
+
+```ruby
+Project.last
+# => #<Project id:2537 root/discard>>
+project = _
+# => #<Project id:2537 root/discard>>
+project.id
+# => 2537
+```
+
+## Open object in irb
+
+Sometimes it is easier to navigate through a method if you are within the context of the object. You can shim into the namespace of `Object` to let you open `irb` within the context of any object:
+
+```ruby
+Object.define_method(:irb) { binding.irb }
+
+project = Project.last
+# => #<Project id:2537 root/discard>>
+project.irb
+# Notice new context
+irb(#<Project>)> web_url
+# => "https://gitlab-example/root/discard"
+```
+
## Query the database using an ActiveRecord Model
```ruby
@@ -818,7 +855,7 @@ conflicting_permanent_redirects = RedirectRoute.matching_path_and_descendants(pa
conflicting_permanent_redirects.destroy_all
```
-## Merge Requests
+## Merge requests
### Close a merge request properly (if merged but still marked as open)
@@ -1287,7 +1324,7 @@ has more information about Service Ping.
### Generate or get the cached Service Ping
```ruby
-Gitlab::UsageData.to_json
+Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true)
```
### Generate a fresh new Service Ping
@@ -1295,7 +1332,7 @@ Gitlab::UsageData.to_json
This also refreshes the cached Service Ping displayed in the Admin Area
```ruby
-Gitlab::UsageData.to_json(force_refresh: true)
+Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)
```
### Generate and print
@@ -1332,7 +1369,7 @@ cluster = Clusters::Cluster.find_by(name: 'cluster_name')
Delete cluster without associated resources:
```ruby
-# Find users with the Administrator role
+# Find users with the administrator access
user = User.find_by(username: 'admin_user')
# Find the cluster with the ID
@@ -1377,3 +1414,18 @@ Gitlab::CurrentSettings.elasticsearch_url
Gitlab::CurrentSettings.elasticsearch_indexing
```
+
+#### Changing the Elasticsearch password
+
+```ruby
+es_url = Gitlab::CurrentSettings.current_application_settings
+
+# Confirm the current ElasticSearch URL
+es_url.elasticsearch_url
+
+# Set the ElasticSearch URL
+es_url.elasticsearch_url = "http://<username>:<password>@your.es.host:<port>"
+
+# Save the change
+es_url.save!
+```
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 8ec6b35ec39..a30ade058f6 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -40,7 +40,8 @@ User claims and attributes:
SCIM mapping:
-![Azure AD SCIM](img/AzureAD-scim_attribute_mapping.png)
+![Azure AD SCIM Provisioning](img/AzureAD-scim_provisioning.png)
+![Azure AD SCIM Attribute Mapping](img/AzureAD-scim_attribute_mapping.png)
Group Sync:
diff --git a/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png b/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png
new file mode 100644
index 00000000000..b8edcfa31c2
--- /dev/null
+++ b/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png
Binary files differ
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index e4d1696ea93..47fd424b1fd 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -98,6 +98,15 @@ This section is for links to information elsewhere in the GitLab documentation.
- [Common Geo errors](../geo/replication/troubleshooting.md#fixing-common-errors).
+- Mismatch in `pg_dump` and `psql` versions:
+
+ ```plaintext
+ Dumping PostgreSQL database gitlabhq_production ... pg_dump: error: server version: 13.3; pg_dump version: 14.2
+ pg_dump: error: aborting because of server version mismatch
+ ```
+
+ To fix this, see [Backup and restore a non-packaged PostgreSQL database](https://docs.gitlab.com/omnibus/settings/database.html#backup-and-restore-a-non-packaged-postgresql-database).
+
## Support topics
### Database deadlocks
diff --git a/doc/administration/user_settings.md b/doc/administration/user_settings.md
index 2c1bb781882..2e879f8789d 100644
--- a/doc/administration/user_settings.md
+++ b/doc/administration/user_settings.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/access_requests.md b/doc/api/access_requests.md
index 9c217a98c3d..08f3b78787b 100644
--- a/doc/api/access_requests.md
+++ b/doc/api/access_requests.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/api_resources.md b/doc/api/api_resources.md
index 783823f80fb..3d54402ea0b 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -14,7 +14,6 @@ Available resources for the [GitLab REST API](index.md) can be grouped in the fo
See also:
-- [V3 to V4](v3_to_v4.md).
- Adding [deploy keys for multiple projects](deploy_keys.md#add-deploy-keys-to-multiple-projects).
- [API Resources for various templates](#templates-api-resources).
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index 5e7ffbff25c..7b98b226cde 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/applications.md b/doc/api/applications.md
index bbf12438f28..aeb6a0452c5 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/audit_events.md b/doc/api/audit_events.md
index 888323f9362..4ddd851ebda 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -312,7 +312,7 @@ Example response:
### Retrieve a specific project audit event
-Only available to users with at least the [Maintainer role](../user/permissions.md) for the project.
+Only available to users with at least the Maintainer role for the project.
```plaintext
GET /projects/:id/audit_events/:audit_event_id
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index 5db8c30cb9a..bc47d3a4d9e 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/commits.md b/doc/api/commits.md
index 6347af451a2..d7be9559527 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -8,6 +8,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
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.
+## Responses
+
+In commit responses, `created_at` and `committed_date` are identical.
+However, `committed_date` and `authored_date` are generated from different sources,
+and may not be identical.
+
## List repository commits
Get a list of repository commits in a project.
@@ -740,9 +746,9 @@ Example response:
}
```
-## List Merge Requests associated with a commit
+## List merge requests associated with a commit
-Get a list of Merge Requests related to the specified commit.
+Get a list of merge requests related to the specified commit.
```plaintext
GET /projects/:id/repository/commits/:sha/merge_requests
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 68d339837b2..b61ec34b882 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -372,7 +372,8 @@ DELETE /projects/:id/registry/repositories/:repository_id/tags
| `keep_n` | integer | no | The amount of latest tags of given name to keep. |
| `older_than` | string | no | Tags to delete that are older than the given time, written in human readable form `1h`, `1d`, `1month`. |
-This API call performs the following operations:
+This API returns [HTTP response status code 202](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202)
+if successful, and performs the following operations:
- It orders all tags by creation date. The creation date is the time of the
manifest creation, not the time of tag push.
@@ -396,10 +397,6 @@ If your Container Registry has a large number of tags to delete,
only some of them will be deleted, and you might need to call this API multiple times.
To schedule tags for automatic deletion, use a [cleanup policy](../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy) instead.
-NOTE:
-In GitLab 12.4 and later, individual tags are deleted.
-For more details, see the [discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/15737).
-
Examples:
1. Remove tag names that are matching the regex (Git SHA), keep always at least 5,
@@ -430,3 +427,29 @@ Examples:
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"
```
+
+## Instance-wide endpoints
+
+Beside the group- and project-specific GitLab APIs explained above,
+the Container Registry has its own endpoints.
+To query those, follow the Registry's built-in mechanism to obtain and use an
+[authentication token](https://docs.docker.com/registry/spec/auth/token/).
+
+NOTE:
+These are different from project or personal access tokens in the GitLab application.
+
+### Listing all container repositories
+
+```plaintext
+GET /v2/_catalog
+```
+
+To list all container repositories on your GitLab instance, admin credentials are required:
+
+```shell
+$ curl --request GET --user "<admin-username>:<admin-password>" "https://gitlab.example.com/jwt/auth?service=container_registry&scope=registry:catalog:*"
+{"token":" ... "}
+
+$ curl --header "Authorization: Bearer <token_from_above>" https://gitlab.example.com:5050/v2/_catalog
+{"repositories":["user/project1", "group/subgroup/project2", ... ]}
+```
diff --git a/doc/api/dependency_proxy.md b/doc/api/dependency_proxy.md
index 5401c007c0d..028584e69ff 100644
--- a/doc/api/dependency_proxy.md
+++ b/doc/api/dependency_proxy.md
@@ -12,8 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) from GitLab Premium to GitLab Free in 13.6.
Schedules for deletion the cached manifests and blobs for a group. This endpoint requires the
-[Owner role](../user/permissions.md)
-for the group.
+Owner role for the group.
```plaintext
DELETE /groups/:id/dependency_proxy/cache
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index b244384bd6a..ee6887e9d04 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## List all deploy keys **(FREE SELF)**
Get a list of all deploy keys across all projects of the GitLab instance. This
-endpoint requires an administrator role and is not available on GitLab.com.
+endpoint requires administrator access and is not available on GitLab.com.
```plaintext
GET /deploy_keys
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index 0f2b9a13a3f..77c2fe5e162 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21811) in GitLab 12.9.
-Get a list of all deploy tokens across the GitLab instance. This endpoint requires the Administrator role.
+Get a list of all deploy tokens across the GitLab instance. This endpoint requires administrator access.
```plaintext
GET /deploy_tokens
@@ -49,7 +49,7 @@ Example response:
## Project deploy tokens
-Project deploy token API endpoints require the [Maintainer role](../user/permissions.md) or higher
+Project deploy token API endpoints require the Maintainer role or higher
for the project.
### List project deploy tokens
@@ -165,7 +165,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
## Group deploy tokens
-Users with at least the [Maintainer role](../user/permissions.md) for the group can list group deploy
+Users with at least the Maintainer role for the group can list group deploy
tokens. Only group Owners can create and delete group deploy tokens.
### List group deploy tokens
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 70b3e76c3dd..29f9bd3e2ee 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -23,7 +23,7 @@ GET /projects/:id/deployments
| `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. One of `created`, `running`, `success`, `failed`, `canceled`.
+| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, `canceled`, `blocked`.
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
@@ -201,6 +201,7 @@ Example response:
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"created_at": "2016-08-11T11:32:35.444Z",
"updated_at": "2016-08-11T11:34:01.123Z",
+ "status": "success",
"user": {
"name": "Administrator",
"username": "root",
@@ -264,6 +265,29 @@ Example response:
}
```
+Deployments created by users on GitLab Premium or higher include the `approvals` and `pending_approval_count` properties:
+
+```json
+{
+ "status": "created",
+ "pending_approval_count": 0,
+ "approvals": [
+ {
+ "user": {
+ "id": 49,
+ "username": "project_6_bot",
+ "name": "****",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e83ac685f68ea07553ad3054c738c709?s=80&d=identicon",
+ "web_url": "http://localhost:3000/project_6_bot"
+ },
+ "status": "approved"
+ }
+ ],
+ ...
+}
+```
+
## Create a deployment
```plaintext
@@ -311,6 +335,29 @@ Example response:
}
```
+Deployments created by users on GitLab Premium or higher include the `approvals` and `pending_approval_count` properties:
+
+```json
+{
+ "status": "created",
+ "pending_approval_count": 0,
+ "approvals": [
+ {
+ "user": {
+ "id": 49,
+ "username": "project_6_bot",
+ "name": "****",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e83ac685f68ea07553ad3054c738c709?s=80&d=identicon",
+ "web_url": "http://localhost:3000/project_6_bot"
+ },
+ "status": "approved"
+ }
+ ],
+ ...
+}
+```
+
## Update a deployment
```plaintext
@@ -354,6 +401,29 @@ Example response:
}
```
+Deployments created by users on GitLab Premium or higher include the `approvals` and `pending_approval_count` properties:
+
+```json
+{
+ "status": "created",
+ "pending_approval_count": 0,
+ "approvals": [
+ {
+ "user": {
+ "id": 49,
+ "username": "project_6_bot",
+ "name": "****",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e83ac685f68ea07553ad3054c738c709?s=80&d=identicon",
+ "web_url": "http://localhost:3000/project_6_bot"
+ },
+ "status": "approved"
+ }
+ ],
+ ...
+}
+```
+
## List of merge requests associated with a deployment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) in GitLab 12.7.
@@ -378,7 +448,10 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
## Approve or reject a blocked deployment **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 [with a flag](../administration/feature_flags.md) named `deployment_approvals`. Disabled by default. This feature is not ready for production use.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 [with a flag](../administration/feature_flags.md) named `deployment_approvals`. Disabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/347342) in GitLab 14.8.
+
+See [Deployment Approvals](../ci/environments/deployment_approvals.md) for more information about this feature.
```plaintext
POST /projects/:id/deployments/:deployment_id/approval
diff --git a/doc/api/dora/metrics.md b/doc/api/dora/metrics.md
index 3e7b7800034..3f078945b0f 100644
--- a/doc/api/dora/metrics.md
+++ b/doc/api/dora/metrics.md
@@ -10,7 +10,7 @@ type: reference, api
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.10.
> - The legacy key/value pair `{ "<date>" => "<value>" }` was removed from the payload in GitLab 14.0.
-All methods require at least the Reporter [role](../../user/permissions.md).
+All methods require at least the Reporter role.
## Get project-level DORA metrics
diff --git a/doc/api/epics.md b/doc/api/epics.md
index f3137559220..deb74cf21e9 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -40,12 +40,13 @@ are paginated.
Read more on [pagination](index.md#pagination).
WARNING:
-> `reference` attribute in response is deprecated in favour of `references`.
-> Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)
+In [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) and later,
+the `reference` attribute in responses is deprecated in favor of `references`.
NOTE:
-> `references.relative` is relative to the group that the epic is being requested. When epic is fetched from its origin group
-> `relative` format would be the same as `short` format and when requested cross groups it is expected to be the same as `full` format.
+`references.relative` is relative to the group that the epic is being requested from. When an epic
+is fetched from its origin group, the `relative` format is the same as the `short` format.
+When an epic is requested across groups, the `relative` format is expected to be the same as the `full` format.
## List epics for a group
diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md
index c62d33f82f4..dbf832b301f 100644
--- a/doc/api/error_tracking.md
+++ b/doc/api/error_tracking.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Error Tracking project settings
The project settings API allows you to retrieve the [Error Tracking](../operations/error_tracking.md)
-settings for a project. Only for users with [Maintainer role](../user/permissions.md) for the project.
+settings for a project. Only for users with Maintainer role for the project.
### Get Error Tracking settings
@@ -42,7 +42,7 @@ Example response:
### Enable or disable the Error Tracking project settings
The API allows you to enable or disable the Error Tracking settings for a project. Only for users with the
-[Maintainer role](../user/permissions.md) for the project.
+Maintainer role for the project.
```plaintext
PATCH /projects/:id/error_tracking/settings
@@ -75,7 +75,7 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68384) in GitLab 14.3.
For [integrated error tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) feature. Only for users with the
-[Maintainer role](../user/permissions.md) for the project.
+Maintainer role for the project.
### List project client keys
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index fe1674649b6..a152c443902 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -467,6 +467,19 @@ Example response:
"uploads_verified_count": null,
"uploads_verification_failed_count": null,
"uploads_verified_in_percentage": "0.00%",
+ "job_artifacts_count": 5,
+ "job_artifacts_checksum_total_count": 5,
+ "job_artifacts_checksummed_count": 5,
+ "job_artifacts_checksum_failed_count": 0,
+ "job_artifacts_synced_count": 5,
+ "job_artifacts_failed_count": 0,
+ "job_artifacts_registry_count": 5,
+ "job_artifacts_verification_total_count": 5,
+ "job_artifacts_verified_count": 5,
+ "job_artifacts_verification_failed_count": 0,
+ "job_artifacts_synced_in_percentage": "100.00%",
+ "job_artifacts_verified_in_percentage": "100.00%",
+ "job_artifacts_synced_missing_on_primary_count": 0,
},
{
"geo_node_id": 2,
@@ -623,6 +636,19 @@ Example response:
"uploads_verified_count": null,
"uploads_verification_failed_count": null,
"uploads_verified_in_percentage": "0.00%",
+ "job_artifacts_count": 5,
+ "job_artifacts_checksum_total_count": 5,
+ "job_artifacts_checksummed_count": 5,
+ "job_artifacts_checksum_failed_count": 0,
+ "job_artifacts_synced_count": 5,
+ "job_artifacts_failed_count": 0,
+ "job_artifacts_registry_count": 5,
+ "job_artifacts_verification_total_count": 5,
+ "job_artifacts_verified_count": 5,
+ "job_artifacts_verification_failed_count": 0,
+ "job_artifacts_synced_in_percentage": "100.00%",
+ "job_artifacts_verified_in_percentage": "100.00%",
+ "job_artifacts_synced_missing_on_primary_count": 0,
}
]
```
@@ -776,6 +802,19 @@ Example response:
"uploads_verified_count": null,
"uploads_verification_failed_count": null,
"uploads_verified_in_percentage": "0.00%",
+ "job_artifacts_count": 5,
+ "job_artifacts_checksum_total_count": 5,
+ "job_artifacts_checksummed_count": 5,
+ "job_artifacts_checksum_failed_count": 0,
+ "job_artifacts_synced_count": 5,
+ "job_artifacts_failed_count": 0,
+ "job_artifacts_registry_count": 5,
+ "job_artifacts_verification_total_count": 5,
+ "job_artifacts_verified_count": 5,
+ "job_artifacts_verification_failed_count": 0,
+ "job_artifacts_synced_in_percentage": "100.00%",
+ "job_artifacts_verified_in_percentage": "100.00%",
+ "job_artifacts_synced_missing_on_primary_count": 0,
}
```
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 14512286ade..d0e65b8c4eb 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -152,7 +152,7 @@ Root-level queries are defined in
### Multiplex queries
GitLab supports batching queries into a single request using
-[apollo-link-batch-http](https://www.apollographql.com/docs/link/links/batch-http/). More
+[`@apollo/client/link/batch-http`](https://www.apollographql.com/docs/react/api/link/apollo-link-batch-http/). More
information about multiplexed queries is also available for
[GraphQL Ruby](https://graphql-ruby.org/queries/multiplex.html), the
library GitLab uses on the backend.
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 4ca40d1fa11..18c99b7d151 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -376,7 +376,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="queryrunnersactive"></a>`active` | [`Boolean`](#boolean) | Filter runners by active (true) or paused (false) status. |
+| <a id="queryrunnersactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 14.8. This was renamed. Use: `paused`. |
+| <a id="queryrunnerspaused"></a>`paused` | [`Boolean`](#boolean) | Filter runners by `paused` (true) or `active` (false) status. |
| <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. |
@@ -1017,6 +1018,30 @@ Input type: `CommitCreateInput`
| <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.configureContainerScanning`
+
+Configure Container Scanning for a project by enabling Container Scanning in a new or modified
+`.gitlab-ci.yml` file in a new branch. The new branch and a URL to
+create a merge request are part of the response.
+
+Input type: `ConfigureContainerScanningInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationconfigurecontainerscanningclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationconfigurecontainerscanningprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationconfigurecontainerscanningbranch"></a>`branch` | [`String`](#string) | Branch that has the new/modified `.gitlab-ci.yml` file. |
+| <a id="mutationconfigurecontainerscanningclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationconfigurecontainerscanningerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationconfigurecontainerscanningsuccesspath"></a>`successPath` | [`String`](#string) | Redirect path to use when the response is successful. |
+
### `Mutation.configureDependencyScanning`
Configure Dependency Scanning for a project by enabling Dependency Scanning in a new or modified
@@ -1118,7 +1143,7 @@ Input type: `ConfigureSecretDetectionInput`
### `Mutation.corpusCreate`
-Available only when feature flag `corpus_management` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+Available only when feature flag `corpus_management` is enabled. This flag is enabled by default.
Input type: `CorpusCreateInput`
@@ -1395,6 +1420,8 @@ Input type: `CreateIssueInput`
| <a id="mutationcreateissuelocked"></a>`locked` | [`Boolean`](#boolean) | Indicates discussion is locked on the issue. |
| <a id="mutationcreateissuemergerequesttoresolvediscussionsof"></a>`mergeRequestToResolveDiscussionsOf` | [`MergeRequestID`](#mergerequestid) | IID of a merge request for which to resolve discussions. |
| <a id="mutationcreateissuemilestoneid"></a>`milestoneId` | [`MilestoneID`](#milestoneid) | ID of the milestone to assign to the issue. On update milestone will be removed if set to null. |
+| <a id="mutationcreateissuemoveafterid"></a>`moveAfterId` | [`IssueID`](#issueid) | Global ID of issue that should be placed after the current issue. |
+| <a id="mutationcreateissuemovebeforeid"></a>`moveBeforeId` | [`IssueID`](#issueid) | Global ID of issue that should be placed before the current issue. |
| <a id="mutationcreateissueprojectpath"></a>`projectPath` | [`ID!`](#id) | Project full path the issue is associated with. |
| <a id="mutationcreateissuetitle"></a>`title` | [`String!`](#string) | Title of the issue. |
| <a id="mutationcreateissuetype"></a>`type` | [`IssueType`](#issuetype) | Type of the issue. |
@@ -1489,11 +1516,9 @@ Input type: `CreateSnippetInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcreatesnippetblobactions"></a>`blobActions` | [`[SnippetBlobActionInputType!]`](#snippetblobactioninputtype) | Actions to perform over the snippet repository and blobs. |
-| <a id="mutationcreatesnippetcaptcharesponse"></a>`captchaResponse` **{warning-solid}** | [`String`](#string) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationcreatesnippetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcreatesnippetdescription"></a>`description` | [`String`](#string) | Description of the snippet. |
| <a id="mutationcreatesnippetprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project the snippet is associated with. |
-| <a id="mutationcreatesnippetspamlogid"></a>`spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationcreatesnippettitle"></a>`title` | [`String!`](#string) | Title of the snippet. |
| <a id="mutationcreatesnippetuploadedfiles"></a>`uploadedFiles` | [`[String!]`](#string) | Paths to files uploaded in the snippet description. |
| <a id="mutationcreatesnippetvisibilitylevel"></a>`visibilityLevel` | [`VisibilityLevelsEnum!`](#visibilitylevelsenum) | Visibility level of the snippet. |
@@ -1502,13 +1527,9 @@ Input type: `CreateSnippetInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationcreatesnippetcaptchasitekey"></a>`captchaSiteKey` **{warning-solid}** | [`String`](#string) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationcreatesnippetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcreatesnippeterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationcreatesnippetneedscaptcharesponse"></a>`needsCaptchaResponse` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationcreatesnippetsnippet"></a>`snippet` | [`Snippet`](#snippet) | Snippet after mutation. |
-| <a id="mutationcreatesnippetspam"></a>`spam` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
-| <a id="mutationcreatesnippetspamlogid"></a>`spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
### `Mutation.createTestCase`
@@ -4157,12 +4178,13 @@ Input type: `RunnerUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <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="mutationrunnerupdateactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** This was renamed. Please use `paused`. Deprecated in 14.8. |
| <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="mutationrunnerupdatepaused"></a>`paused` | [`Boolean`](#boolean) | Indicates the runner is not allowed to receive jobs. |
| <a id="mutationrunnerupdateprivateprojectsminutescostfactor"></a>`privateProjectsMinutesCostFactor` | [`Float`](#float) | Private projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="mutationrunnerupdatepublicprojectsminutescostfactor"></a>`publicProjectsMinutesCostFactor` | [`Float`](#float) | Public projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="mutationrunnerupdaterununtagged"></a>`runUntagged` | [`Boolean`](#boolean) | Indicates the runner is able to run untagged jobs. |
@@ -4282,6 +4304,28 @@ Input type: `SecurityPolicyProjectUnassignInput`
| <a id="mutationsecuritypolicyprojectunassignclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsecuritypolicyprojectunassignerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.securityTrainingUpdate`
+
+Input type: `SecurityTrainingUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationsecuritytrainingupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationsecuritytrainingupdateisenabled"></a>`isEnabled` | [`Boolean!`](#boolean) | Sets the training provider as enabled for the project. |
+| <a id="mutationsecuritytrainingupdateisprimary"></a>`isPrimary` | [`Boolean`](#boolean) | Sets the training provider as primary for the project. |
+| <a id="mutationsecuritytrainingupdateprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
+| <a id="mutationsecuritytrainingupdateproviderid"></a>`providerId` | [`SecurityTrainingProviderID!`](#securitytrainingproviderid) | ID of the provider. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationsecuritytrainingupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationsecuritytrainingupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationsecuritytrainingupdatetraining"></a>`training` | [`ProjectSecurityTraining`](#projectsecuritytraining) | Represents the training entity subject to mutation. |
+
### `Mutation.terraformStateDelete`
Input type: `TerraformStateDeleteInput`
@@ -4336,6 +4380,27 @@ Input type: `TerraformStateUnlockInput`
| <a id="mutationterraformstateunlockclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationterraformstateunlockerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.timelineEventCreate`
+
+Input type: `TimelineEventCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelineeventcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelineeventcreateincidentid"></a>`incidentId` | [`IssueID!`](#issueid) | Incident ID of the timeline event. |
+| <a id="mutationtimelineeventcreatenote"></a>`note` | [`String!`](#string) | Text note of the timeline event. |
+| <a id="mutationtimelineeventcreateoccurredat"></a>`occurredAt` | [`Time!`](#time) | Timestamp of when the event occurred. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelineeventcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelineeventcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationtimelineeventcreatetimelineevent"></a>`timelineEvent` | [`TimelineEventType`](#timelineeventtype) | Timeline event. |
+
### `Mutation.timelineEventDestroy`
Input type: `TimelineEventDestroyInput`
@@ -4355,6 +4420,27 @@ Input type: `TimelineEventDestroyInput`
| <a id="mutationtimelineeventdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtimelineeventdestroytimelineevent"></a>`timelineEvent` | [`TimelineEventType`](#timelineeventtype) | Timeline event. |
+### `Mutation.timelineEventUpdate`
+
+Input type: `TimelineEventUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelineeventupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelineeventupdateid"></a>`id` | [`IncidentManagementTimelineEventID!`](#incidentmanagementtimelineeventid) | ID of the timeline event to update. |
+| <a id="mutationtimelineeventupdatenote"></a>`note` | [`String`](#string) | Text note of the timeline event. |
+| <a id="mutationtimelineeventupdateoccurredat"></a>`occurredAt` | [`Time`](#time) | Timestamp when the event occurred. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelineeventupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelineeventupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationtimelineeventupdatetimelineevent"></a>`timelineEvent` | [`TimelineEventType`](#timelineeventtype) | Timeline event. |
+
### `Mutation.todoCreate`
Input type: `TodoCreateInput`
@@ -4846,11 +4932,9 @@ Input type: `UpdateSnippetInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationupdatesnippetblobactions"></a>`blobActions` | [`[SnippetBlobActionInputType!]`](#snippetblobactioninputtype) | Actions to perform over the snippet repository and blobs. |
-| <a id="mutationupdatesnippetcaptcharesponse"></a>`captchaResponse` **{warning-solid}** | [`String`](#string) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationupdatesnippetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdatesnippetdescription"></a>`description` | [`String`](#string) | Description of the snippet. |
| <a id="mutationupdatesnippetid"></a>`id` | [`SnippetID!`](#snippetid) | Global ID of the snippet to update. |
-| <a id="mutationupdatesnippetspamlogid"></a>`spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationupdatesnippettitle"></a>`title` | [`String`](#string) | Title of the snippet. |
| <a id="mutationupdatesnippetvisibilitylevel"></a>`visibilityLevel` | [`VisibilityLevelsEnum`](#visibilitylevelsenum) | Visibility level of the snippet. |
@@ -4858,13 +4942,9 @@ Input type: `UpdateSnippetInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationupdatesnippetcaptchasitekey"></a>`captchaSiteKey` **{warning-solid}** | [`String`](#string) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationupdatesnippetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdatesnippeterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationupdatesnippetneedscaptcharesponse"></a>`needsCaptchaResponse` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
| <a id="mutationupdatesnippetsnippet"></a>`snippet` | [`Snippet`](#snippet) | Snippet after mutation. |
-| <a id="mutationupdatesnippetspam"></a>`spam` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
-| <a id="mutationupdatesnippetspamlogid"></a>`spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated:** Use spam protection with HTTP headers instead. Deprecated in 13.11. |
### `Mutation.userCalloutCreate`
@@ -4885,6 +4965,25 @@ Input type: `UserCalloutCreateInput`
| <a id="mutationusercalloutcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationusercalloutcreateusercallout"></a>`userCallout` | [`UserCallout!`](#usercallout) | User callout dismissed. |
+### `Mutation.userPreferencesUpdate`
+
+Input type: `UserPreferencesUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationuserpreferencesupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationuserpreferencesupdateissuessort"></a>`issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationuserpreferencesupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationuserpreferencesupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationuserpreferencesupdateuserpreferences"></a>`userPreferences` | [`UserPreferences`](#userpreferences) | User preferences after mutation. |
+
### `Mutation.vulnerabilityConfirm`
Input type: `VulnerabilityConfirmInput`
@@ -5057,7 +5156,7 @@ Input type: `VulnerabilityRevertToDetectedInput`
### `Mutation.workItemCreate`
-Available only when feature flag `work_items` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+Creates a work item. Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice.
Input type: `WorkItemCreateInput`
@@ -5079,6 +5178,50 @@ Input type: `WorkItemCreateInput`
| <a id="mutationworkitemcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationworkitemcreateworkitem"></a>`workItem` | [`WorkItem`](#workitem) | Created work item. |
+### `Mutation.workItemDelete`
+
+Deletes a work item. Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice.
+
+Input type: `WorkItemDeleteInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationworkitemdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemdeleteid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationworkitemdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationworkitemdeleteproject"></a>`project` | [`Project`](#project) | Project the deleted work item belonged to. |
+
+### `Mutation.workItemUpdate`
+
+Updates a work item by Global ID. Available only when feature flag `work_items` is enabled. The feature is experimental and is subject to change without notice.
+
+Input type: `WorkItemUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationworkitemupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemupdateid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
+| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
+| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationworkitemupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationworkitemupdateworkitem"></a>`workItem` | [`WorkItem`](#workitem) | Updated work item. |
+
## Connections
Some types in our schema are `Connection` types - they represent a paginated
@@ -6648,6 +6791,29 @@ The edge type for [`JiraProject`](#jiraproject).
| <a id="jiraprojectedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="jiraprojectedgenode"></a>`node` | [`JiraProject`](#jiraproject) | The item at the end of the edge. |
+#### `JobArtifactRegistryConnection`
+
+The connection type for [`JobArtifactRegistry`](#jobartifactregistry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="jobartifactregistryconnectionedges"></a>`edges` | [`[JobArtifactRegistryEdge]`](#jobartifactregistryedge) | A list of edges. |
+| <a id="jobartifactregistryconnectionnodes"></a>`nodes` | [`[JobArtifactRegistry]`](#jobartifactregistry) | A list of nodes. |
+| <a id="jobartifactregistryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `JobArtifactRegistryEdge`
+
+The edge type for [`JobArtifactRegistry`](#jobartifactregistry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="jobartifactregistryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="jobartifactregistryedgenode"></a>`node` | [`JobArtifactRegistry`](#jobartifactregistry) | The item at the end of the edge. |
+
#### `JobNeedUnionConnection`
The connection type for [`JobNeedUnion`](#jobneedunion).
@@ -8490,6 +8656,18 @@ Describes a rule for who can approve merge requests.
| <a id="approvalruletype"></a>`type` | [`ApprovalRuleType`](#approvalruletype) | Type of the rule. |
| <a id="approvalruleusers"></a>`users` | [`UserCoreConnection`](#usercoreconnection) | List of users added as approvers for the rule. (see [Connections](#connections)) |
+### `AssetType`
+
+Represents a vulnerability asset type.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="assettypename"></a>`name` | [`String!`](#string) | Name of the asset. |
+| <a id="assettypetype"></a>`type` | [`String!`](#string) | Type of the asset. |
+| <a id="assettypeurl"></a>`url` | [`String!`](#string) | URL of the asset. |
+
### `AwardEmoji`
An emoji awarded by a user.
@@ -8680,6 +8858,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <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="boardepicancestorscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="boardepicancestorscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <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. |
@@ -8696,6 +8876,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <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. |
+| <a id="boardepicancestorsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="boardepicancestorsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `BoardEpic.children`
@@ -8713,6 +8895,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="boardepicchildrenauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
| <a id="boardepicchildrenconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="boardepicchildrencreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="boardepicchildrencreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <a id="boardepicchildrenenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <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. |
@@ -8729,6 +8913,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="boardepicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="boardepicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
| <a id="boardepicchildrentimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+| <a id="boardepicchildrenupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="boardepicchildrenupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `BoardEpic.currentUserTodos`
@@ -9015,31 +9201,51 @@ Represents the total number of issues and their weights for a particular day.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="cirunneraccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel!`](#cirunneraccesslevel) | Access level of the runner. |
-| <a id="cirunneractive"></a>`active` | [`Boolean!`](#boolean) | Indicates the runner is allowed to receive jobs. |
+| <a id="cirunneractive"></a>`active` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in 14.8. Use paused. |
| <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. |
| <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Timestamp of last contact from this runner. |
| <a id="cirunnercreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of creation of this runner. |
| <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. |
| <a id="cirunnereditadminurl"></a>`editAdminUrl` | [`String`](#string) | Admin form URL of the runner. Only available for administrators. |
| <a id="cirunnerexecutorname"></a>`executorName` | [`String`](#string) | Executor last advertised by the runner. Available only when feature flag `graphql_ci_runner_executor` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
+| <a id="cirunnergroups"></a>`groups` | [`GroupConnection`](#groupconnection) | Groups the runner is associated with. For group runners only. (see [Connections](#connections)) |
| <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. |
| <a id="cirunneripaddress"></a>`ipAddress` | [`String`](#string) | IP address of the runner. |
| <a id="cirunnerjobcount"></a>`jobCount` | [`Int`](#int) | Number of jobs processed by the runner (limited to 1000, plus one to indicate that more items exist). |
| <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="cirunnerpaused"></a>`paused` | [`Boolean!`](#boolean) | Indicates the runner is paused and not available to run jobs. |
| <a id="cirunnerprivateprojectsminutescostfactor"></a>`privateProjectsMinutesCostFactor` | [`Float`](#float) | Private projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="cirunnerprojectcount"></a>`projectCount` | [`Int`](#int) | Number of projects that the runner is associated with. |
+| <a id="cirunnerprojects"></a>`projects` | [`ProjectConnection`](#projectconnection) | Projects the runner is associated with. For project runners only. (see [Connections](#connections)) |
| <a id="cirunnerpublicprojectsminutescostfactor"></a>`publicProjectsMinutesCostFactor` | [`Float`](#float) | Public projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="cirunnerrevision"></a>`revision` | [`String`](#string) | Revision of the runner. |
| <a id="cirunnerrununtagged"></a>`runUntagged` | [`Boolean!`](#boolean) | Indicates the runner is able to run untagged jobs. |
| <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. |
| <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
| <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
+| <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. |
| <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
| <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
#### Fields with arguments
+##### `CiRunner.jobs`
+
+Jobs assigned to the runner.
+
+Returns [`CiJobConnection`](#cijobconnection).
+
+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="cirunnerjobsstatuses"></a>`statuses` | [`[CiJobStatus!]`](#cijobstatus) | Filter jobs by status. |
+
##### `CiRunner.status`
Status of the runner.
@@ -9174,7 +9380,7 @@ Represents a code quality degradation on the pipeline.
| <a id="codequalitydegradationfingerprint"></a>`fingerprint` | [`String!`](#string) | Unique fingerprint to identify the code quality degradation. For example, an MD5 hash. |
| <a id="codequalitydegradationline"></a>`line` | [`Int!`](#int) | Line on which the code quality degradation occurred. |
| <a id="codequalitydegradationpath"></a>`path` | [`String!`](#string) | Relative path to the file containing the code quality degradation. |
-| <a id="codequalitydegradationseverity"></a>`severity` | [`CodeQualityDegradationSeverity!`](#codequalitydegradationseverity) | Status of the degradation (BLOCKER, CRITICAL, MAJOR, MINOR, INFO). |
+| <a id="codequalitydegradationseverity"></a>`severity` | [`CodeQualityDegradationSeverity!`](#codequalitydegradationseverity) | Status of the degradation (BLOCKER, CRITICAL, MAJOR, MINOR, INFO, UNKNOWN). |
### `Commit`
@@ -9518,6 +9724,7 @@ Represents a DAST profile schedule.
| <a id="dastprofileschedulecadence"></a>`cadence` | [`DastProfileCadence`](#dastprofilecadence) | Cadence of the DAST profile schedule. |
| <a id="dastprofilescheduleid"></a>`id` | [`DastProfileScheduleID!`](#dastprofilescheduleid) | ID of the DAST profile schedule. |
| <a id="dastprofileschedulenextrunat"></a>`nextRunAt` | [`Time`](#time) | Next run time of the DAST profile schedule in the given timezone. |
+| <a id="dastprofilescheduleownervalid"></a>`ownerValid` | [`Boolean`](#boolean) | Status of the current owner of the DAST profile schedule. |
| <a id="dastprofileschedulestartsat"></a>`startsAt` | [`Time`](#time) | Start time of the DAST profile schedule in the given timezone. |
| <a id="dastprofilescheduletimezone"></a>`timezone` | [`String`](#string) | Time zone of the start time of the DAST profile schedule. |
@@ -10177,6 +10384,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <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="epicancestorscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="epicancestorscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <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. |
@@ -10193,6 +10402,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <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. |
+| <a id="epicancestorsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="epicancestorsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `Epic.children`
@@ -10210,6 +10421,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="epicchildrenauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
| <a id="epicchildrenconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="epicchildrencreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="epicchildrencreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <a id="epicchildrenenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <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. |
@@ -10226,6 +10439,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="epicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="epicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
| <a id="epicchildrentimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+| <a id="epicchildrenupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="epicchildrenupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `Epic.currentUserTodos`
@@ -10531,6 +10746,7 @@ Represents an external resource to send audit events to.
| <a id="externalauditeventdestinationdestinationurl"></a>`destinationUrl` | [`String!`](#string) | External destination to send audit events to. |
| <a id="externalauditeventdestinationgroup"></a>`group` | [`Group!`](#group) | Group the destination belongs to. |
| <a id="externalauditeventdestinationid"></a>`id` | [`ID!`](#id) | ID of the destination. |
+| <a id="externalauditeventdestinationverificationtoken"></a>`verificationToken` | [`String!`](#string) | Verification token to validate source of event. |
### `ExternalIssue`
@@ -10588,6 +10804,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="geonodegroupwikirepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+##### `GeoNode.jobArtifactRegistries`
+
+Find Job Artifact registries on this Geo node Available only when feature flag `geo_job_artifact_replication` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+
+Returns [`JobArtifactRegistryConnection`](#jobartifactregistryconnection).
+
+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="geonodejobartifactregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+
##### `GeoNode.lfsObjectRegistries`
Find LFS object registries on this Geo node.
@@ -10770,6 +11002,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupparent"></a>`parent` | [`Group`](#group) | Parent group. |
| <a id="grouppath"></a>`path` | [`String!`](#string) | Path of the namespace. |
| <a id="groupprojectcreationlevel"></a>`projectCreationLevel` | [`String`](#string) | Permission level required to create projects in the group. |
+| <a id="grouprecentissueboards"></a>`recentIssueBoards` | [`BoardConnection`](#boardconnection) | List of recently visited boards of the group. Maximum size is 4. (see [Connections](#connections)) |
| <a id="grouprepositorysizeexcessprojectcount"></a>`repositorySizeExcessProjectCount` | [`Int!`](#int) | Number of projects in the root namespace where the repository size exceeds the limit. |
| <a id="grouprequestaccessenabled"></a>`requestAccessEnabled` | [`Boolean`](#boolean) | Indicates if users can request access to namespace. |
| <a id="grouprequiretwofactorauthentication"></a>`requireTwoFactorAuthentication` | [`Boolean`](#boolean) | Indicates if all users in this group are required to set up two-factor authentication. |
@@ -10898,6 +11131,8 @@ Returns [`Epic`](#epic).
| ---- | ---- | ----------- |
| <a id="groupepicauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
| <a id="groupepicconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="groupepiccreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="groupepiccreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <a id="groupepicenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <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. |
@@ -10914,6 +11149,8 @@ Returns [`Epic`](#epic).
| <a id="groupepicstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="groupepicstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
| <a id="groupepictimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+| <a id="groupepicupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="groupepicupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `Group.epicBoard`
@@ -10943,6 +11180,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupepicsauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
| <a id="groupepicsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="groupepicscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. |
+| <a id="groupepicscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. |
| <a id="groupepicsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <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. |
@@ -10959,6 +11198,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupepicsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="groupepicsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
| <a id="groupepicstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+| <a id="groupepicsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
+| <a id="groupepicsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
##### `Group.groupMembers`
@@ -11058,12 +11299,15 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupiterationsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <a id="groupiterationsid"></a>`id` | [`ID`](#id) | Global ID of the Iteration to look up. |
| <a id="groupiterationsiid"></a>`iid` | [`ID`](#id) | Internal ID of the Iteration to look up. |
+| <a id="groupiterationsin"></a>`in` | [`[IterationSearchableField!]`](#iterationsearchablefield) | Fields in which the fuzzy-search should be performed with the query given in the argument `search`. Defaults to `[title]`. |
| <a id="groupiterationsincludeancestors"></a>`includeAncestors` | [`Boolean`](#boolean) | Whether to include ancestor iterations. Defaults to true. |
| <a id="groupiterationsiterationcadenceids"></a>`iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. |
+| <a id="groupiterationssearch"></a>`search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. |
+| <a id="groupiterationssort"></a>`sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. |
| <a id="groupiterationsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="groupiterationsstate"></a>`state` | [`IterationState`](#iterationstate) | Filter iterations by state. |
| <a id="groupiterationstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
-| <a id="groupiterationstitle"></a>`title` | [`String`](#string) | Fuzzy search by title. |
+| <a id="groupiterationstitle"></a>`title` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.4. The argument will be removed in 15.4. Please use `search` and `in` fields instead. |
##### `Group.label`
@@ -11126,6 +11370,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="groupmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="groupmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="groupmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="groupmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `Group.milestones`
@@ -11208,8 +11454,9 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="grouprunnersactive"></a>`active` | [`Boolean`](#boolean) | Filter runners by active (true) or paused (false) status. |
+| <a id="grouprunnersactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 14.8. This was renamed. Use: `paused`. |
| <a id="grouprunnersmembership"></a>`membership` | [`RunnerMembershipFilter`](#runnermembershipfilter) | Control which runners to include in the results. |
+| <a id="grouprunnerspaused"></a>`paused` | [`Boolean`](#boolean) | Filter runners by `paused` (true) or `active` (false) status. |
| <a id="grouprunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="grouprunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
| <a id="grouprunnersstatus"></a>`status` | [`CiRunnerStatus`](#cirunnerstatus) | Filter runners by status. |
@@ -11331,6 +11578,20 @@ Represents a Group Membership.
| <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. |
+#### Fields with arguments
+
+##### `GroupMember.mergeRequestInteraction`
+
+Find a merge request.
+
+Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="groupmembermergerequestinteractionid"></a>`id` | [`MergeRequestID!`](#mergerequestid) | Global ID of the merge request. |
+
### `GroupPermissions`
#### Fields
@@ -11749,6 +12010,23 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="jirauserjiradisplayname"></a>`jiraDisplayName` | [`String!`](#string) | Display name of the Jira user. |
| <a id="jirauserjiraemail"></a>`jiraEmail` | [`String`](#string) | Email of the Jira user, returned only for users with public emails. |
+### `JobArtifactRegistry`
+
+Represents the Geo replication and verification state of a job_artifact.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="jobartifactregistryartifactid"></a>`artifactId` | [`ID!`](#id) | ID of the Job Artifact. |
+| <a id="jobartifactregistrycreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp when the JobArtifactRegistry was created. |
+| <a id="jobartifactregistryid"></a>`id` | [`ID!`](#id) | ID of the JobArtifactRegistry. |
+| <a id="jobartifactregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the JobArtifactRegistry. |
+| <a id="jobartifactregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the JobArtifactRegistry. |
+| <a id="jobartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the JobArtifactRegistry should be resynced. |
+| <a id="jobartifactregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the JobArtifactRegistry. |
+| <a id="jobartifactregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the JobArtifactRegistry. |
+
### `JobPermissions`
#### Fields
@@ -12022,7 +12300,7 @@ A user assigned to a merge request.
| <a id="mergerequestassigneeid"></a>`id` | [`ID!`](#id) | ID of the user. |
| <a id="mergerequestassigneelocation"></a>`location` | [`String`](#string) | Location of the user. |
| <a id="mergerequestassigneemergerequestinteraction"></a>`mergeRequestInteraction` | [`UserMergeRequestInteraction`](#usermergerequestinteraction) | Details of this user's interactions with the merge request. |
-| <a id="mergerequestassigneename"></a>`name` | [`String!`](#string) | Human-readable name of the user. Will return `****` if the user is a project bot and the requester does not have permission to read resource access tokens. |
+| <a id="mergerequestassigneename"></a>`name` | [`String!`](#string) | Human-readable name of the user. Returns `****` if the user is a project bot and the requester does not have permission to view the project. |
| <a id="mergerequestassigneenamespace"></a>`namespace` | [`Namespace`](#namespace) | Personal namespace of the user. |
| <a id="mergerequestassigneeprojectmemberships"></a>`projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. (see [Connections](#connections)) |
| <a id="mergerequestassigneepublicemail"></a>`publicEmail` | [`String`](#string) | User's public email. |
@@ -12066,6 +12344,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestassigneeassignedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestassigneeassignedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestassigneeassignedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestassigneeassignedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestassigneeassignedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestAssignee.authoredMergeRequests`
@@ -12098,6 +12378,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestassigneeauthoredmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestassigneeauthoredmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestassigneeauthoredmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestassigneeauthoredmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestassigneeauthoredmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestAssignee.groups`
@@ -12147,6 +12429,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestassigneereviewrequestedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestassigneereviewrequestedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestassigneereviewrequestedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestassigneereviewrequestedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestassigneereviewrequestedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestAssignee.snippets`
@@ -12277,7 +12561,7 @@ A user assigned to a merge request as a reviewer.
| <a id="mergerequestreviewerid"></a>`id` | [`ID!`](#id) | ID of the user. |
| <a id="mergerequestreviewerlocation"></a>`location` | [`String`](#string) | Location of the user. |
| <a id="mergerequestreviewermergerequestinteraction"></a>`mergeRequestInteraction` | [`UserMergeRequestInteraction`](#usermergerequestinteraction) | Details of this user's interactions with the merge request. |
-| <a id="mergerequestreviewername"></a>`name` | [`String!`](#string) | Human-readable name of the user. Will return `****` if the user is a project bot and the requester does not have permission to read resource access tokens. |
+| <a id="mergerequestreviewername"></a>`name` | [`String!`](#string) | Human-readable name of the user. Returns `****` if the user is a project bot and the requester does not have permission to view the project. |
| <a id="mergerequestreviewernamespace"></a>`namespace` | [`Namespace`](#namespace) | Personal namespace of the user. |
| <a id="mergerequestreviewerprojectmemberships"></a>`projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. (see [Connections](#connections)) |
| <a id="mergerequestreviewerpublicemail"></a>`publicEmail` | [`String`](#string) | User's public email. |
@@ -12321,6 +12605,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestreviewerassignedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestreviewerassignedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestreviewerassignedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestreviewerassignedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestreviewerassignedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestReviewer.authoredMergeRequests`
@@ -12353,6 +12639,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestreviewerauthoredmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestreviewerauthoredmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestreviewerauthoredmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestreviewerauthoredmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestreviewerauthoredmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestReviewer.groups`
@@ -12402,6 +12690,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="mergerequestreviewerreviewrequestedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="mergerequestreviewerreviewrequestedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="mergerequestreviewerreviewrequestedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="mergerequestreviewerreviewrequestedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `MergeRequestReviewer.snippets`
@@ -13157,6 +13447,19 @@ Represents the Geo sync and verification state of a pipeline artifact.
| <a id="pipelineartifactregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PipelineArtifactRegistry. |
| <a id="pipelineartifactregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PipelineArtifactRegistry. |
+### `PipelineCounts`
+
+Represents pipeline counts for the project.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pipelinecountsall"></a>`all` | [`Int`](#int) | Total number of pipelines for the project. |
+| <a id="pipelinecountsfinished"></a>`finished` | [`Int`](#int) | Number of pipelines with scope FINISHED for the project. |
+| <a id="pipelinecountspending"></a>`pending` | [`Int`](#int) | Number of pipelines with scope PENDING for the project. |
+| <a id="pipelinecountsrunning"></a>`running` | [`Int`](#int) | Number of pipelines with scope RUNNING for the project. |
+
### `PipelineMessage`
#### Fields
@@ -13184,10 +13487,13 @@ Represents vulnerability finding of a security report on the pipeline.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="pipelinesecurityreportfindingassets"></a>`assets` | [`[AssetType!]`](#assettype) | List of assets associated with the vulnerability. |
| <a id="pipelinesecurityreportfindingconfidence"></a>`confidence` | [`String`](#string) | Type of the security report that found the vulnerability. |
| <a id="pipelinesecurityreportfindingdescription"></a>`description` | [`String`](#string) | Description of the vulnerability finding. |
+| <a id="pipelinesecurityreportfindingevidence"></a>`evidence` | [`VulnerabilityEvidence`](#vulnerabilityevidence) | Evidence for the vulnerability. |
| <a id="pipelinesecurityreportfindingfalsepositive"></a>`falsePositive` | [`Boolean`](#boolean) | Indicates whether the vulnerability is a false positive. |
-| <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerabilit finding. |
+| <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerability finding. |
+| <a id="pipelinesecurityreportfindinglinks"></a>`links` | [`[VulnerabilityLink!]`](#vulnerabilitylink) | List of links associated with the vulnerability. |
| <a id="pipelinesecurityreportfindinglocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. |
| <a id="pipelinesecurityreportfindingname"></a>`name` | [`String`](#string) | Name of the vulnerability finding. |
| <a id="pipelinesecurityreportfindingproject"></a>`project` | [`Project`](#project) | Project on which the vulnerability finding was found. |
@@ -13197,6 +13503,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <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) | Finding status. |
+| <a id="pipelinesecurityreportfindingtitle"></a>`title` | [`String`](#string) | Title of the vulnerability finding. |
| <a id="pipelinesecurityreportfindinguuid"></a>`uuid` | [`String`](#string) | Name of the vulnerability finding. |
### `Project`
@@ -13213,6 +13520,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectautoclosereferencedissues"></a>`autocloseReferencedIssues` | [`Boolean`](#boolean) | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically. |
| <a id="projectavatarurl"></a>`avatarUrl` | [`String`](#string) | URL to avatar image file of the project. |
| <a id="projectcicdsettings"></a>`ciCdSettings` | [`ProjectCiCdSetting`](#projectcicdsetting) | CI/CD settings for the project. |
+| <a id="projectciconfigpathordefault"></a>`ciConfigPathOrDefault` | [`String!`](#string) | Path of the CI configuration file. |
| <a id="projectcijobtokenscope"></a>`ciJobTokenScope` | [`CiJobTokenScopeType`](#cijobtokenscopetype) | The CI Job Tokens scope of access. |
| <a id="projectclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with the project. (see [Connections](#connections)) |
| <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. |
@@ -13220,7 +13528,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | Container expiration policy of the project. |
| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if Container Registry is enabled for the current user. |
| <a id="projectcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the project. |
-| <a id="projectcorpuses"></a>`corpuses` | [`CoverageFuzzingCorpusConnection`](#coveragefuzzingcorpusconnection) | Find corpuses of the project. Available only when feature flag `corpus_management` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. (see [Connections](#connections)) |
+| <a id="projectcorpuses"></a>`corpuses` | [`CoverageFuzzingCorpusConnection`](#coveragefuzzingcorpusconnection) | Find corpuses of the project. Available only when feature flag `corpus_management` is enabled. This flag is enabled by default. (see [Connections](#connections)) |
| <a id="projectcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of the project creation. |
| <a id="projectdastscannerprofiles"></a>`dastScannerProfiles` | [`DastScannerProfileConnection`](#dastscannerprofileconnection) | DAST scanner profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastsiteprofiles"></a>`dastSiteProfiles` | [`DastSiteProfileConnection`](#dastsiteprofileconnection) | DAST Site Profiles associated with the project. (see [Connections](#connections)) |
@@ -13234,7 +13542,6 @@ 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)) |
@@ -13256,6 +13563,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectprintingmergerequestlinkenabled"></a>`printingMergeRequestLinkEnabled` | [`Boolean`](#boolean) | Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line. |
| <a id="projectpublicjobs"></a>`publicJobs` | [`Boolean`](#boolean) | Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts. |
| <a id="projectpushrules"></a>`pushRules` | [`PushRules`](#pushrules) | Project's push rules settings. |
+| <a id="projectrecentissueboards"></a>`recentIssueBoards` | [`BoardConnection`](#boardconnection) | List of recently visited boards of the project. Maximum size is 4. (see [Connections](#connections)) |
| <a id="projectremovesourcebranchaftermerge"></a>`removeSourceBranchAfterMerge` | [`Boolean`](#boolean) | Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project. |
| <a id="projectrepository"></a>`repository` | [`Repository`](#repository) | Git repository of the project. |
| <a id="projectrepositorysizeexcess"></a>`repositorySizeExcess` | [`Float`](#float) | Size of repository that exceeds the limit in bytes. |
@@ -13542,6 +13850,22 @@ 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.incidentManagementEscalationPolicies`
+
+Incident Management escalation policies of the project.
+
+Returns [`EscalationPolicyTypeConnection`](#escalationpolicytypeconnection).
+
+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="projectincidentmanagementescalationpoliciesname"></a>`name` | [`String`](#string) | Fuzzy search by escalation policy name. |
+
##### `Project.incidentManagementEscalationPolicy`
Incident Management escalation policy of the project.
@@ -13553,6 +13877,7 @@ Returns [`EscalationPolicyType`](#escalationpolicytype).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectincidentmanagementescalationpolicyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | ID of the escalation policy. |
+| <a id="projectincidentmanagementescalationpolicyname"></a>`name` | [`String`](#string) | Fuzzy search by escalation policy name. |
##### `Project.incidentManagementOncallSchedules`
@@ -13754,12 +14079,15 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectiterationsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| <a id="projectiterationsid"></a>`id` | [`ID`](#id) | Global ID of the Iteration to look up. |
| <a id="projectiterationsiid"></a>`iid` | [`ID`](#id) | Internal ID of the Iteration to look up. |
+| <a id="projectiterationsin"></a>`in` | [`[IterationSearchableField!]`](#iterationsearchablefield) | Fields in which the fuzzy-search should be performed with the query given in the argument `search`. Defaults to `[title]`. |
| <a id="projectiterationsincludeancestors"></a>`includeAncestors` | [`Boolean`](#boolean) | Whether to include ancestor iterations. Defaults to true. |
| <a id="projectiterationsiterationcadenceids"></a>`iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. |
+| <a id="projectiterationssearch"></a>`search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. |
+| <a id="projectiterationssort"></a>`sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. |
| <a id="projectiterationsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| <a id="projectiterationsstate"></a>`state` | [`IterationState`](#iterationstate) | Filter iterations by state. |
| <a id="projectiterationstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
-| <a id="projectiterationstitle"></a>`title` | [`String`](#string) | Fuzzy search by title. |
+| <a id="projectiterationstitle"></a>`title` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.4. The argument will be removed in 15.4. Please use `search` and `in` fields instead. |
##### `Project.jobs`
@@ -13848,6 +14176,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="projectmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="projectmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="projectmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="projectmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `Project.milestones`
@@ -13923,6 +14253,20 @@ Returns [`Pipeline`](#pipeline).
| <a id="projectpipelineiid"></a>`iid` | [`ID`](#id) | IID of the Pipeline. For example, "1". |
| <a id="projectpipelinesha"></a>`sha` | [`String`](#string) | SHA of the Pipeline. For example, "dyd0f15ay83993f5ab66k927w28673882x99100b". |
+##### `Project.pipelineCounts`
+
+Build pipeline counts of the project.
+
+Returns [`PipelineCounts`](#pipelinecounts).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectpipelinecountsref"></a>`ref` | [`String`](#string) | Filter pipelines by the ref they are run for. |
+| <a id="projectpipelinecountssha"></a>`sha` | [`String`](#string) | Filter pipelines by the SHA of the commit they are run for. |
+| <a id="projectpipelinecountssource"></a>`source` | [`String`](#string) | Filter pipelines by their source. |
+
##### `Project.pipelines`
Build pipelines of the project.
@@ -14229,6 +14573,20 @@ Represents a Project Membership.
| <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. |
+#### Fields with arguments
+
+##### `ProjectMember.mergeRequestInteraction`
+
+Find a merge request.
+
+Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectmembermergerequestinteractionid"></a>`id` | [`MergeRequestID!`](#mergerequestid) | Global ID of the merge request. |
+
### `ProjectPermissions`
#### Fields
@@ -14539,6 +14897,8 @@ Returns [`Tree`](#tree).
| <a id="repositoryblobcanmodifyblob"></a>`canModifyBlob` | [`Boolean`](#boolean) | Whether the current user can modify the blob. |
| <a id="repositoryblobcodeowners"></a>`codeOwners` | [`[UserCore!]`](#usercore) | List of code owners for the blob. |
| <a id="repositoryblobeditblobpath"></a>`editBlobPath` | [`String`](#string) | Web path to edit the blob in the old-style editor. |
+| <a id="repositoryblobenvironmentexternalurlforroutemap"></a>`environmentExternalUrlForRouteMap` | [`String`](#string) | Web path to blob on an environment. |
+| <a id="repositoryblobenvironmentformattedexternalurl"></a>`environmentFormattedExternalUrl` | [`String`](#string) | Environment on which the blob is available. |
| <a id="repositoryblobexternalstorage"></a>`externalStorage` | [`String`](#string) | External storage being used, if enabled (for instance, 'LFS'). |
| <a id="repositoryblobexternalstorageurl"></a>`externalStorageUrl` | [`String`](#string) | Web path to download the raw blob via external storage, if enabled. |
| <a id="repositoryblobfiletype"></a>`fileType` | [`String`](#string) | Expected format of the blob based on the extension. |
@@ -14548,6 +14908,7 @@ Returns [`Tree`](#tree).
| <a id="repositoryblobid"></a>`id` | [`ID!`](#id) | ID of the blob. |
| <a id="repositoryblobideeditpath"></a>`ideEditPath` | [`String`](#string) | Web path to edit this blob in the Web IDE. |
| <a id="repositoryblobideforkandeditpath"></a>`ideForkAndEditPath` | [`String`](#string) | Web path to edit this blob in the Web IDE using a forked project. |
+| <a id="repositorybloblanguage"></a>`language` | [`String`](#string) | Blob language. |
| <a id="repositorybloblfsoid"></a>`lfsOid` | [`String`](#string) | LFS OID of the blob. |
| <a id="repositoryblobmode"></a>`mode` | [`String`](#string) | Blob mode. |
| <a id="repositoryblobname"></a>`name` | [`String`](#string) | Blob name. |
@@ -14640,6 +15001,7 @@ Counts of requirements by their state.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="rootstoragestatisticsbuildartifactssize"></a>`buildArtifactsSize` | [`Float!`](#float) | CI artifacts size in bytes. |
+| <a id="rootstoragestatisticsdependencyproxysize"></a>`dependencyProxySize` | [`Float!`](#float) | Dependency Proxy sizes in bytes. |
| <a id="rootstoragestatisticslfsobjectssize"></a>`lfsObjectsSize` | [`Float!`](#float) | LFS objects size in bytes. |
| <a id="rootstoragestatisticspackagessize"></a>`packagesSize` | [`Float!`](#float) | Packages size in bytes. |
| <a id="rootstoragestatisticspipelineartifactssize"></a>`pipelineArtifactsSize` | [`Float!`](#float) | CI pipeline artifacts size in bytes. |
@@ -15497,7 +15859,7 @@ Core represention of a GitLab user.
| <a id="usercoregroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) |
| <a id="usercoreid"></a>`id` | [`ID!`](#id) | ID of the user. |
| <a id="usercorelocation"></a>`location` | [`String`](#string) | Location of the user. |
-| <a id="usercorename"></a>`name` | [`String!`](#string) | Human-readable name of the user. Will return `****` if the user is a project bot and the requester does not have permission to read resource access tokens. |
+| <a id="usercorename"></a>`name` | [`String!`](#string) | Human-readable name of the user. Returns `****` if the user is a project bot and the requester does not have permission to view the project. |
| <a id="usercorenamespace"></a>`namespace` | [`Namespace`](#namespace) | Personal namespace of the user. |
| <a id="usercoreprojectmemberships"></a>`projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. (see [Connections](#connections)) |
| <a id="usercorepublicemail"></a>`publicEmail` | [`String`](#string) | User's public email. |
@@ -15541,6 +15903,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="usercoreassignedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="usercoreassignedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="usercoreassignedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="usercoreassignedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="usercoreassignedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `UserCore.authoredMergeRequests`
@@ -15573,6 +15937,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="usercoreauthoredmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="usercoreauthoredmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="usercoreauthoredmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="usercoreauthoredmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="usercoreauthoredmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `UserCore.groups`
@@ -15622,6 +15988,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="usercorereviewrequestedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="usercorereviewrequestedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="usercorereviewrequestedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="usercorereviewrequestedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="usercorereviewrequestedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
##### `UserCore.snippets`
@@ -15726,6 +16094,14 @@ fields relate to interactions between the two entities.
| ---- | ---- | ----------- |
| <a id="userpermissionscreatesnippet"></a>`createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. |
+### `UserPreferences`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="userpreferencesissuessort"></a>`issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. |
+
### `UserStatus`
#### Fields
@@ -15988,6 +16364,44 @@ Represents the vulnerability details URL field.
| <a id="vulnerabilitydetailurlname"></a>`name` | [`String`](#string) | Name of the field. |
| <a id="vulnerabilitydetailurltext"></a>`text` | [`String`](#string) | Text of the URL. |
+### `VulnerabilityEvidence`
+
+Represents a Vulnerability Evidence.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityevidencerequest"></a>`request` | [`VulnerabilityRequest`](#vulnerabilityrequest) | HTTP request of the Vulnerability Evidence. |
+| <a id="vulnerabilityevidenceresponse"></a>`response` | [`VulnerabilityResponse`](#vulnerabilityresponse) | HTTP response of the Vulnerability Evidence. |
+| <a id="vulnerabilityevidencesource"></a>`source` | [`VulnerabilityEvidenceSource`](#vulnerabilityevidencesource) | Source of the Vulnerability Evidence. |
+| <a id="vulnerabilityevidencesummary"></a>`summary` | [`String`](#string) | Summary of the Vulnerability Evidence. |
+| <a id="vulnerabilityevidencesupportingmessages"></a>`supportingMessages` | [`[VulnerabilityEvidenceSupportingMessage!]`](#vulnerabilityevidencesupportingmessage) | Supporting messages of the Vulnerability Evidence. |
+
+### `VulnerabilityEvidenceSource`
+
+Represents a vulnerability evidence.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityevidencesourceidentifier"></a>`identifier` | [`String!`](#string) | ID of the Vulnerability Evidence Source. |
+| <a id="vulnerabilityevidencesourcename"></a>`name` | [`String!`](#string) | Name of the Vulnerability Evidence Source. |
+| <a id="vulnerabilityevidencesourceurl"></a>`url` | [`String`](#string) | URL of the Vulnerability Evidence Source. |
+
+### `VulnerabilityEvidenceSupportingMessage`
+
+Represents a vulnerability evidence supporting message.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityevidencesupportingmessagename"></a>`name` | [`String!`](#string) | Name of the vulnerability supporting message. |
+| <a id="vulnerabilityevidencesupportingmessagerequest"></a>`request` | [`VulnerabilityRequest`](#vulnerabilityrequest) | HTTP request of the vulnerability evidence supporting message. |
+| <a id="vulnerabilityevidencesupportingmessageresponse"></a>`response` | [`VulnerabilityResponse`](#vulnerabilityresponse) | HTTP response of the vulnerability evidence supporting message. |
+
### `VulnerabilityExternalIssueLink`
Represents an external issue link of a vulnerability.
@@ -16070,8 +16484,11 @@ Represents the location of a vulnerability found by a Coverage Fuzzing scan.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="vulnerabilitylocationcoveragefuzzingblobpath"></a>`blobPath` | [`String`](#string) | Blob path to the vulnerable file. |
+| <a id="vulnerabilitylocationcoveragefuzzingcrashaddress"></a>`crashAddress` | [`String`](#string) | Relative address in memory were the crash occurred. |
+| <a id="vulnerabilitylocationcoveragefuzzingcrashtype"></a>`crashType` | [`String`](#string) | Type of the crash. |
| <a id="vulnerabilitylocationcoveragefuzzingendline"></a>`endLine` | [`String`](#string) | Number of the last relevant line in the vulnerable file. |
| <a id="vulnerabilitylocationcoveragefuzzingfile"></a>`file` | [`String`](#string) | Path to the vulnerable file. |
+| <a id="vulnerabilitylocationcoveragefuzzingstacktracesnippet"></a>`stacktraceSnippet` | [`String`](#string) | Stack trace recorded during fuzzing resulting the crash. |
| <a id="vulnerabilitylocationcoveragefuzzingstartline"></a>`startLine` | [`String`](#string) | Number of the first relevant line in the vulnerable file. |
| <a id="vulnerabilitylocationcoveragefuzzingvulnerableclass"></a>`vulnerableClass` | [`String`](#string) | Class containing the vulnerability. |
| <a id="vulnerabilitylocationcoveragefuzzingvulnerablemethod"></a>`vulnerableMethod` | [`String`](#string) | Method containing the vulnerability. |
@@ -16159,6 +16576,43 @@ Check permissions for the current user on a vulnerability.
| <a id="vulnerabilitypermissionsreadvulnerabilityfeedback"></a>`readVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability_feedback` on this resource. |
| <a id="vulnerabilitypermissionsupdatevulnerabilityfeedback"></a>`updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `update_vulnerability_feedback` on this resource. |
+### `VulnerabilityRequest`
+
+Represents a Vulnerability Request.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityrequestbody"></a>`body` | [`String`](#string) | Body of the Vulnerability Request. |
+| <a id="vulnerabilityrequestheaders"></a>`headers` | [`[VulnerabilityRequestResponseHeader!]!`](#vulnerabilityrequestresponseheader) | HTTP headers of the Vulnerability Request. |
+| <a id="vulnerabilityrequestmethod"></a>`method` | [`String`](#string) | Method of the Vulnerability Request. |
+| <a id="vulnerabilityrequesturl"></a>`url` | [`String`](#string) | URL of the Vulnerability Request. |
+
+### `VulnerabilityRequestResponseHeader`
+
+Represents a Vulnerability Request/Response Header.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityrequestresponseheadername"></a>`name` | [`String`](#string) | Name of the Vulnerability Request/Response Header. |
+| <a id="vulnerabilityrequestresponseheadervalue"></a>`value` | [`String`](#string) | Value of the Vulnerability Request/Response Header. |
+
+### `VulnerabilityResponse`
+
+Represents a Vulnerability Response.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilityresponsebody"></a>`body` | [`String`](#string) | Body of the Vulnerability Response. |
+| <a id="vulnerabilityresponseheaders"></a>`headers` | [`[VulnerabilityRequestResponseHeader!]!`](#vulnerabilityrequestresponseheader) | HTTP headers of the Vulnerability Response. |
+| <a id="vulnerabilityresponsereasonphrase"></a>`reasonPhrase` | [`String`](#string) | Reason Phrase of the Vulnerability Response. |
+| <a id="vulnerabilityresponsestatuscode"></a>`statusCode` | [`Int`](#int) | Status Code of the Vulnerability Response. |
+
### `VulnerabilityScanner`
Represents a vulnerability scanner.
@@ -16246,6 +16700,7 @@ Represents vulnerability letter grades with associated projects.
| <a id="workitemdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| <a id="workitemid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
| <a id="workitemiid"></a>`iid` | [`ID!`](#id) | Internal ID of the work item. |
+| <a id="workitemstate"></a>`state` | [`WorkItemState!`](#workitemstate) | State of the work item. |
| <a id="workitemtitle"></a>`title` | [`String!`](#string) | Title of the work item. |
| <a id="workitemtitlehtml"></a>`titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| <a id="workitemworkitemtype"></a>`workItemType` | [`WorkItemType!`](#workitemtype) | Type assigned to the work item. |
@@ -16481,17 +16936,19 @@ Values for sorting runners.
| <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. |
+| <a id="cirunnersorttoken_expires_at_asc"></a>`TOKEN_EXPIRES_AT_ASC` | Ordered by token_expires_at in ascending order. |
+| <a id="cirunnersorttoken_expires_at_desc"></a>`TOKEN_EXPIRES_AT_DESC` | Ordered by token_expires_at in descending order. |
### `CiRunnerStatus`
| Value | Description |
| ----- | ----------- |
-| <a id="cirunnerstatusactive"></a>`ACTIVE` **{warning-solid}** | **Deprecated** in 14.6. Use CiRunnerType.active instead. |
+| <a id="cirunnerstatusactive"></a>`ACTIVE` **{warning-solid}** | **Deprecated** in 14.6. This was renamed. Use: [`CiRunner.paused`](#cirunnerpaused). |
| <a id="cirunnerstatusnever_contacted"></a>`NEVER_CONTACTED` | Runner that has never contacted this instance. Set legacyMode to null to utilize this value. Will replace NOT_CONNECTED starting in 15.0. |
| <a id="cirunnerstatusnot_connected"></a>`NOT_CONNECTED` **{warning-solid}** | **Deprecated** in 14.6. Use NEVER_CONTACTED instead. NEVER_CONTACTED will have a slightly different scope starting in 15.0, with STALE being returned instead after 3 months of no contact. |
| <a id="cirunnerstatusoffline"></a>`OFFLINE` **{warning-solid}** | **Deprecated** in 14.6. This field will have a slightly different scope starting in 15.0, with STALE being returned after a certain period offline. |
| <a id="cirunnerstatusonline"></a>`ONLINE` | Runner that contacted this instance within the last 2 hours. |
-| <a id="cirunnerstatuspaused"></a>`PAUSED` **{warning-solid}** | **Deprecated** in 14.6. Use CiRunnerType.active instead. |
+| <a id="cirunnerstatuspaused"></a>`PAUSED` **{warning-solid}** | **Deprecated** in 14.6. This was renamed. Use: [`CiRunner.paused`](#cirunnerpaused). |
| <a id="cirunnerstatusstale"></a>`STALE` | Runner that has not contacted this instance within the last 3 months. Only available if legacyMode is null. Will be a possible return value starting in 15.0. |
### `CiRunnerType`
@@ -16511,6 +16968,7 @@ Values for sorting runners.
| <a id="codequalitydegradationseverityinfo"></a>`INFO` | Code Quality degradation has a status of info. |
| <a id="codequalitydegradationseveritymajor"></a>`MAJOR` | Code Quality degradation has a status of major. |
| <a id="codequalitydegradationseverityminor"></a>`MINOR` | Code Quality degradation has a status of minor. |
+| <a id="codequalitydegradationseverityunknown"></a>`UNKNOWN` | Code Quality degradation has a status of unknown. |
### `CommitActionMode`
@@ -16776,12 +17234,16 @@ Roadmap sort values.
| Value | Description |
| ----- | ----------- |
+| <a id="epicsortcreated_at_asc"></a>`CREATED_AT_ASC` | Sort by created_at by ascending order. |
+| <a id="epicsortcreated_at_desc"></a>`CREATED_AT_DESC` | Sort by created_at by descending order. |
| <a id="epicsortend_date_asc"></a>`END_DATE_ASC` | Sort by end date in ascending order. |
| <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="epicsorttitle_asc"></a>`TITLE_ASC` | Sort by title in ascending order. |
| <a id="epicsorttitle_desc"></a>`TITLE_DESC` | Sort by title in descending order. |
+| <a id="epicsortupdated_at_asc"></a>`UPDATED_AT_ASC` | Sort by updated_at by ascending order. |
+| <a id="epicsortupdated_at_desc"></a>`UPDATED_AT_DESC` | Sort by updated_at by descending order. |
| <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. |
@@ -16992,6 +17454,23 @@ Issue type.
| <a id="issuetyperequirement"></a>`REQUIREMENT` | Requirement issue type. |
| <a id="issuetypetest_case"></a>`TEST_CASE` | Test Case issue type. |
+### `IterationSearchableField`
+
+Fields to perform the search in.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="iterationsearchablefieldcadence_title"></a>`CADENCE_TITLE` | Search in cadence_title field. |
+| <a id="iterationsearchablefieldtitle"></a>`TITLE` | Search in title field. |
+
+### `IterationSort`
+
+Iteration sort values.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="iterationsortcadence_and_due_date_asc"></a>`CADENCE_AND_DUE_DATE_ASC` | Sort by cadence id and due date in ascending order. |
+
### `IterationState`
State of a GitLab iteration.
@@ -17111,6 +17590,8 @@ Values for sorting merge requests.
| <a id="mergerequestsortmilestone_due_desc"></a>`MILESTONE_DUE_DESC` | Milestone due date by descending order. |
| <a id="mergerequestsortpriority_asc"></a>`PRIORITY_ASC` | Priority by ascending order. |
| <a id="mergerequestsortpriority_desc"></a>`PRIORITY_DESC` | Priority by descending order. |
+| <a id="mergerequestsorttitle_asc"></a>`TITLE_ASC` | Title by ascending order. |
+| <a id="mergerequestsorttitle_desc"></a>`TITLE_DESC` | Title 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** in 13.5. This was renamed. Use: `CREATED_ASC`. |
@@ -17663,6 +18144,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumsecurity_configuration_devops_alert"></a>`SECURITY_CONFIGURATION_DEVOPS_ALERT` | Callout feature name for security_configuration_devops_alert. |
| <a id="usercalloutfeaturenameenumsecurity_configuration_upgrade_banner"></a>`SECURITY_CONFIGURATION_UPGRADE_BANNER` | Callout feature name for security_configuration_upgrade_banner. |
| <a id="usercalloutfeaturenameenumsecurity_newsletter_callout"></a>`SECURITY_NEWSLETTER_CALLOUT` | Callout feature name for security_newsletter_callout. |
+| <a id="usercalloutfeaturenameenumsecurity_training_feature_promotion"></a>`SECURITY_TRAINING_FEATURE_PROMOTION` | Callout feature name for security_training_feature_promotion. |
| <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. |
| <a id="usercalloutfeaturenameenumtabs_position_highlight"></a>`TABS_POSITION_HIGHLIGHT` | Callout feature name for tabs_position_highlight. |
@@ -17832,6 +18314,24 @@ Weight ID wildcard values.
| <a id="weightwildcardidany"></a>`ANY` | Weight is assigned. |
| <a id="weightwildcardidnone"></a>`NONE` | No weight is assigned. |
+### `WorkItemState`
+
+State of a GitLab work item.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="workitemstateclosed"></a>`CLOSED` | In closed state. |
+| <a id="workitemstateopen"></a>`OPEN` | In open state. |
+
+### `WorkItemStateEvent`
+
+Values for work item state events.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="workitemstateeventclose"></a>`CLOSE` | Closes the work item. |
+| <a id="workitemstateeventreopen"></a>`REOPEN` | Reopens the work item. |
+
## Scalar types
Scalar values are atomic values, and do not have fields of their own.
@@ -18308,6 +18808,12 @@ A `ReleasesLinkID` is a global ID. It is encoded as a string.
An example `ReleasesLinkID` is: `"gid://gitlab/Releases::Link/1"`.
+### `SecurityTrainingProviderID`
+
+A `SecurityTrainingProviderID` is a global ID. It is encoded as a string.
+
+An example `SecurityTrainingProviderID` is: `"gid://gitlab/Security::TrainingProvider/1"`.
+
### `SnippetID`
A `SnippetID` is a global ID. It is encoded as a string.
@@ -18426,6 +18932,7 @@ One of:
- [`Epic`](#epic)
- [`Issue`](#issue)
- [`MergeRequest`](#mergerequest)
+- [`WorkItem`](#workitem)
#### `JobNeedUnion`
@@ -18614,6 +19121,20 @@ Implementations:
| <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. |
+##### Fields with arguments
+
+###### `MemberInterface.mergeRequestInteraction`
+
+Find a merge request.
+
+Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction).
+
+####### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="memberinterfacemergerequestinteractionid"></a>`id` | [`MergeRequestID!`](#mergerequestid) | Global ID of the merge request. |
+
#### `NoteableInterface`
Implementations:
@@ -18733,7 +19254,7 @@ Implementations:
| <a id="usergroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) |
| <a id="userid"></a>`id` | [`ID!`](#id) | ID of the user. |
| <a id="userlocation"></a>`location` | [`String`](#string) | Location of the user. |
-| <a id="username"></a>`name` | [`String!`](#string) | Human-readable name of the user. Will return `****` if the user is a project bot and the requester does not have permission to read resource access tokens. |
+| <a id="username"></a>`name` | [`String!`](#string) | Human-readable name of the user. Returns `****` if the user is a project bot and the requester does not have permission to view the project. |
| <a id="usernamespace"></a>`namespace` | [`Namespace`](#namespace) | Personal namespace of the user. |
| <a id="userprojectmemberships"></a>`projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. (see [Connections](#connections)) |
| <a id="userpublicemail"></a>`publicEmail` | [`String`](#string) | User's public email. |
@@ -18777,6 +19298,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="userassignedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="userassignedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="userassignedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="userassignedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="userassignedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
###### `User.authoredMergeRequests`
@@ -18809,6 +19332,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="userauthoredmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="userauthoredmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="userauthoredmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="userauthoredmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="userauthoredmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
###### `User.groups`
@@ -18858,6 +19383,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="userreviewrequestedmergerequestssourcebranches"></a>`sourceBranches` | [`[String!]`](#string) | Array of source branch names. All resolved merge requests will have one of these branches as their source. |
| <a id="userreviewrequestedmergerequestsstate"></a>`state` | [`MergeRequestState`](#mergerequeststate) | Merge request state. If provided, all resolved merge requests will have this state. |
| <a id="userreviewrequestedmergerequeststargetbranches"></a>`targetBranches` | [`[String!]`](#string) | Array of target branch names. All resolved merge requests will have one of these branches as their target. |
+| <a id="userreviewrequestedmergerequestsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Merge requests updated after this timestamp. |
+| <a id="userreviewrequestedmergerequestsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Merge requests updated before this timestamp. |
###### `User.snippets`
diff --git a/doc/api/group_access_tokens.md b/doc/api/group_access_tokens.md
index 37471b9d89d..45366885c5c 100644
--- a/doc/api/group_access_tokens.md
+++ b/doc/api/group_access_tokens.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -58,7 +58,7 @@ POST groups/:id/access_tokens
|-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `name` | String | yes | The name of the group access token |
-| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
+| `scopes` | `Array[String]` | yes | [List of scopes](../user/group/settings/group_access_tokens.md#scopes-for-a-group-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `expires_at` | Date | no | The token expires at midnight UTC on that date |
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index ecb73aa8a5e..360790daf8c 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/group_clusters.md b/doc/api/group_clusters.md
index eaecc74a96e..87829708d5e 100644
--- a/doc/api/group_clusters.md
+++ b/doc/api/group_clusters.md
@@ -17,7 +17,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 the [Maintainer role](../user/permissions.md) for the group to use these endpoints.
+Users need at least the Maintainer role for the group to use these endpoints.
## List group clusters
diff --git a/doc/api/groups.md b/doc/api/groups.md
index d7b4f0c8b54..2e0f9526e16 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -808,7 +808,7 @@ Parameters:
### Options for `default_branch_protection`
-The `default_branch_protection` attribute determines whether users with the Developer or [Maintainer role](../user/permissions.md) can push to the applicable [default branch](../user/project/repository/branches/default.md), as described in the following table:
+The `default_branch_protection` attribute determines whether users with the Developer or Maintainer role can push to the applicable [default branch](../user/project/repository/branches/default.md), as described in the following table:
| Value | Description |
|-------|-------------------------------------------------------------------------------------------------------------|
@@ -832,7 +832,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## Transfer project to group
-Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace) is available which does not require instance administrator role. Transferring projects may fail when tagged packages exist in the project's repository.
+Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace)
+is available which does not require administrator access on the instance. Transferring projects may fail when tagged packages exist in the project's repository.
```plaintext
POST /groups/:id/projects/:project_id
@@ -1089,6 +1090,79 @@ GET /groups?search=foobar
]
```
+## List provisioned users **(PREMIUM)**
+
+> Introduced in GitLab 14.8.
+
+Get a list of users provisioned by a given group. Does not include users provisioned by subgroups.
+
+Requires at least the Maintainer role on the group.
+
+```plaintext
+GET /groups/:id/provisioned_users
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:-----------------|:---------------|:---------|:-------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `username` | string | no | Return single user with a specific username |
+| `search` | string | no | Search users by name, email, username |
+| `active` | boolean | no | Return only active users |
+| `blocked` | boolean | no | Return only blocked users |
+| `created_after` | datetime | no | Return users created after the specified time |
+| `created_before` | datetime | no | Return users created before the specified time |
+
+Example response:
+
+```json
+[
+ {
+ id: 66,
+ username: "user22",
+ name: "John Doe22",
+ state: "active",
+ avatar_url: "https://www.gravatar.com/avatar/xxx?s=80&d=identicon",
+ web_url: "http://my.gitlab.com/user22",
+ created_at: "2021-09-10T12:48:22.381Z",
+ bio: "",
+ location: null,
+ public_email: "",
+ skype: "",
+ linkedin: "",
+ twitter: "",
+ website_url: "",
+ organization: null,
+ job_title: "",
+ pronouns: null,
+ bot: false,
+ work_information: null,
+ followers: 0,
+ following: 0,
+ local_time: null,
+ last_sign_in_at: null,
+ confirmed_at: "2021-09-10T12:48:22.330Z",
+ last_activity_on: null,
+ email: "user22@example.org",
+ theme_id: 1,
+ color_scheme_id: 1,
+ projects_limit: 100000,
+ current_sign_in_at: null,
+ identities: [ ],
+ can_create_group: true,
+ can_create_project: true,
+ two_factor_enabled: false,
+ external: false,
+ private_profile: false,
+ commit_email: "user22@example.org",
+ shared_runners_minutes_limit: null,
+ extra_shared_runners_minutes_limit: null
+ },
+ ...
+]
+```
+
## Hooks **(PREMIUM)**
Also called Group Hooks and Webhooks.
diff --git a/doc/api/index.md b/doc/api/index.md
index 69db971f58c..589bc0416a1 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -12,6 +12,9 @@ Use the GitLab APIs to automate GitLab.
A REST API is available in GitLab.
Usage instructions are below.
+
+For examples, see [How to use the API](#how-to-use-the-api).
+
For a list of the available resources and their endpoints, see
[REST API resources](api_resources.md).
@@ -31,7 +34,9 @@ GitLab provides an [SCIM API](scim.md) that both implements
## GraphQL API
-A [GraphQL API](graphql/index.md) is available in GitLab.
+A GraphQL API is available in GitLab.
+For a list of the available resources and their endpoints, see
+[GraphQL API resources](graphql/reference/index.md).
With GraphQL, you can make an API request for only what you need,
and it's versioned by default.
@@ -60,7 +65,7 @@ month. Major API version changes, and removal of entire API versions, are done i
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).
+For the changes between v3 and v4, see the [v3 to v4 documentation](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md).
### Current status
@@ -74,7 +79,7 @@ For example, the root of the v4 API is at `/api/v4`.
### Valid API request
-If you have a GitLab instance at `gitlab.example.com`:
+The following is a basic example of a request to the fictional `gitlab.example.com` endpoint:
```shell
curl "https://gitlab.example.com/api/v4/projects"
@@ -83,6 +88,10 @@ curl "https://gitlab.example.com/api/v4/projects"
The API uses JSON to serialize data. You don't need to specify `.json` at the
end of the API URL.
+NOTE:
+In the example above, replace `gitlab.example.com` with `gitlab.com` to query GitLab.com (GitLab SaaS).
+Access can be denied due to authentication. For more information, see [Authentication](#authentication).
+
### API request to expose HTTP response headers
If you want to expose HTTP response headers, use the `--include` option:
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index f29ac5cd7f2..ab631757eab 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -16,8 +16,7 @@ With [instance-level Kubernetes clusters](../user/instance/clusters/index.md),
you can connect a Kubernetes cluster to the GitLab instance and use the same cluster across all of
the projects within your instance.
-NOTE:
-Users need the Administrator role to use these endpoints.
+Users need administrator access to use these endpoints.
## List instance clusters
diff --git a/doc/api/integrations.md b/doc/api/integrations.md
index 4719fe69c7b..90bb26ffd3d 100644
--- a/doc/api/integrations.md
+++ b/doc/api/integrations.md
@@ -13,7 +13,7 @@ In GitLab 14.4, the `services` endpoint was [renamed](https://gitlab.com/gitlab-
Calls to the Integrations API can be made to both `/projects/:id/services` and `/projects/:id/integrations`.
The examples in this document refer to the endpoint at `/projects/:id/integrations`.
-This API requires an access token with the [Maintainer or Owner role](../user/permissions.md).
+This API requires an access token with the Maintainer or Owner role.
## List all active integrations
@@ -319,11 +319,12 @@ Parameters:
| ---------------------- | ------- | -------- | ----------- |
| `api_key` | string | true | API key used for authentication with Datadog |
| `api_url` | string | false | (Advanced) The full URL for your Datadog site |
-<!-- | `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.7) | -->
-<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. |
| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments |
| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` |
+| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) |
+<!-- | `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.7) | -->
+<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
### Disable Datadog integration
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 5d22952a876..5801f072062 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -29,7 +29,9 @@ When requested across groups or projects, it's expected to be the same as the `f
## List issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get all issues the authenticated user has access to. By default it
returns only issues created by the current user. To get all issues,
@@ -61,7 +63,7 @@ GET /issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
@@ -231,7 +233,9 @@ Please use `iid` of the `epic` attribute instead.
## List group issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a group's issues.
@@ -264,7 +268,7 @@ GET /groups/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
@@ -431,7 +435,9 @@ Please use `iid` of the `epic` attribute instead.
## List project issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a project's issues.
@@ -464,7 +470,7 @@ GET /projects/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
@@ -2422,10 +2428,11 @@ POST /projects/:id/issues/:issue_iid/metric_images
| `issue_iid` | integer | yes | The internal ID of a project's issue |
| `file` | file | yes | The image file to be uploaded |
| `url` | string | no | The URL to view more metric information |
+| `url_text` | string | no | A description of the image or URL |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" --form 'file=@/path/to/file.png' \
---form 'url=http://example.com' "https://gitlab.example.com/api/v4/projects/5/issues/93/metric_images"
+--form 'url=http://example.com' --form 'url_text=Example website' "https://gitlab.example.com/api/v4/projects/5/issues/93/metric_images"
```
Example response:
@@ -2436,7 +2443,8 @@ Example response:
"created_at": "2020-11-13T00:06:18.084Z",
"filename": "file.png",
"file_path": "/uploads/-/system/issuable_metric_image/file/23/file.png",
- "url": "http://example.com"
+ "url": "http://example.com",
+ "url_text": "Example website"
}
```
@@ -2478,6 +2486,39 @@ Example response:
]
```
+## Update metric image
+
+Available only for Incident issues.
+
+```plaintext
+PUT /projects/:id/issues/:issue_iid/metric_images/:image_id
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `image_id` | integer | yes | The ID of the image |
+| `url` | string | no | The URL to view more metric information |
+| `url_text` | string | no | A description of the image or URL |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" --request PUT --form 'url=http://example.com' --form 'url_text=Example website' "https://gitlab.example.com/api/v4/projects/5/issues/93/metric_images/1"
+```
+
+Example response:
+
+```json
+{
+ "id": 23,
+ "created_at": "2020-11-13T00:06:18.084Z",
+ "filename": "file.png",
+ "file_path": "/uploads/-/system/issuable_metric_image/file/23/file.png",
+ "url": "http://example.com",
+ "url_text": "Example website"
+}
+```
+
## Delete metric image
Available only for Incident issues.
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index a874379506f..d272f259ddf 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
---
@@ -293,7 +293,9 @@ FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to
[disable the `bulk_expire_project_artifacts` flag](../administration/feature_flags.md). On GitLab.com, this feature is available.
-[Expire artifacts of a project that can be deleted](https://gitlab.com/gitlab-org/gitlab/-/issues/223793) but that don't have an expiry time.
+Delete artifacts of a project that can be deleted.
+
+By default, [artifacts from the most recent successful pipeline of each ref are kept](../ci/pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
```plaintext
DELETE /projects/:id/artifacts
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 8dcd898b8c3..89018548f5f 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -10,14 +10,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Get a list of jobs in a project. Jobs are sorted in descending order of their IDs.
+By default, this request returns 20 results at a time because the API results [are paginated](index.md#pagination)
+
```plaintext
GET /projects/:id/jobs
```
-| Attribute | Type | Required | Description |
-|-----------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `scope` | string **or** array of strings | no | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| Attribute | Type | Required | Description |
+|-----------|--------------------------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --globoff --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running"
@@ -155,16 +157,18 @@ Example of response
Get a list of jobs for a pipeline.
+By default, this request returns 20 results at a time because the API results [are paginated](index.md#pagination)
+
```plaintext
GET /projects/:id/pipelines/:pipeline_id/jobs
```
-| Attribute | Type | Required | Description |
-|-------------------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `pipeline_id` | integer | yes | ID of a pipeline. Can also be obtained in CI jobs via the [predefined CI variable](../ci/variables/predefined_variables.md) `CI_PIPELINE_ID`. |
-| `scope` | string **or** array of strings | no | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
-| `include_retried` | boolean | no | Include retried jobs in the response. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/272627) in GitLab 13.9. |
+| Attribute | Type | Required | Description |
+|-------------------|--------------------------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. Can also be obtained in CI jobs via the [predefined CI variable](../ci/variables/predefined_variables.md) `CI_PIPELINE_ID`. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| `include_retried` | boolean | **{dotted-circle}** No | Include retried jobs in the response. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/272627) in GitLab 13.9. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running"
@@ -316,11 +320,11 @@ Get a list of bridge jobs for a pipeline.
GET /projects/:id/pipelines/:pipeline_id/bridges
```
-| Attribute | Type | Required | Description |
-|---------------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `pipeline_id` | integer | yes | ID of a pipeline. |
-| `scope` | string **or** array of strings | no | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| Attribute | Type | Required | Description |
+|---------------|--------------------------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/6/bridges?scope[]=pending&scope[]=running"
@@ -483,9 +487,9 @@ GET /job/allowed_agents
Supported attributes:
-| Attribute | Type | Required | Description |
-|:------------ |:---------|:---------|:----------------------|
-| `CI_JOB_TOKEN` | string | yes | Token value associated with the GitLab-provided `CI_JOB_TOKEN` variable. |
+| Attribute | Type | Required | Description |
+|----------------|----------|------------------------|-------------|
+| `CI_JOB_TOKEN` | string | **{check-circle}** Yes | Token value associated with the GitLab-provided `CI_JOB_TOKEN` variable. |
Example request:
@@ -558,10 +562,10 @@ Get a single job of a project
GET /projects/:id/jobs/:job_id
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8"
@@ -635,10 +639,10 @@ Get a log (trace) of a specific job of a project:
GET /projects/:id/jobs/:job_id/trace
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
```shell
curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
@@ -659,10 +663,10 @@ Cancel a single job of a project
POST /projects/:id/jobs/:job_id/cancel
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel"
@@ -709,10 +713,10 @@ Retry a single job of a project
POST /projects/:id/jobs/:job_id/retry
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry"
@@ -761,10 +765,10 @@ POST /projects/:id/jobs/:job_id/erase
Parameters
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
Example of request
@@ -818,10 +822,10 @@ Triggers a manual action to start a job.
POST /projects/:id/jobs/:job_id/play
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-----------|----------------|------------------------|-------------|
+| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | **{check-circle}** Yes | ID of a job. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play"
diff --git a/doc/api/lint.md b/doc/api/lint.md
index e5b5e0e2be8..a271b75c035 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -89,7 +89,7 @@ Example responses:
The CI lint returns an expanded version of the configuration. The expansion does not
work for CI configuration added with [`include: local`](../ci/yaml/index.md#includelocal),
-or with [`extends:`](../ci/yaml/index.md#extends).
+and the [`extends:`](../ci/yaml/index.md#extends) keyword is [not fully supported](https://gitlab.com/gitlab-org/gitlab/-/issues/258843).
Example contents of a `.gitlab-ci.yml` passed to the CI Lint API with
`include_merged_yaml` and `include_jobs` set as true:
@@ -169,8 +169,9 @@ POST /projects/:id/ci/lint
| Attribute | Type | Required | Description |
| ---------- | ------- | -------- | -------- |
| `content` | string | yes | The CI/CD configuration content. |
-| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. |
+| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#simulate-a-pipeline), or only do static check. This is false by default. |
| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
+| `ref` | string | no | When `dry_run` is `true`, sets the branch or tag to use. Defaults to the project's default branch when not set. |
Example request:
@@ -220,6 +221,7 @@ GET /projects/:id/ci/lint
| ---------- | ------- | -------- | -------- |
| `dry_run` | boolean | no | Run pipeline creation simulation, or only do static check. |
| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
+| `ref` | string | no | When `dry_run` is `true`, sets the branch or tag to use. Defaults to the project's default branch when not set. |
Example request:
diff --git a/doc/api/members.md b/doc/api/members.md
index 95565d40897..10072baf2ff 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index b6021d494fd..6a0b66ac5dc 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -278,6 +278,12 @@ GET /projects/:id/approval_rules/:approval_rule_id
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
+WARNING:
+The Vulnerability-Check feature, including the Vulnerability-Check attributes listed here, is in its
+end-of-life process. It is [deprecated](../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](../user/application_security/policies/#scan-result-policy-editor).
+
You can create project approval rules using the following endpoint:
```plaintext
@@ -295,11 +301,11 @@ POST /projects/:id/approval_rules
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
-| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `vulnerability`, `license_scanning`, `code_coverage`. |
-| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
-| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
-| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
-| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
+| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `vulnerability`, `license_scanning`, `code_coverage`. The `vulnerability` report type is part of the Vulnerability-Check feature, which deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `scanners` | Array | no | The security scanners the Vulnerability-Check approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `severity_levels` | Array | no | The severity levels the Vulnerability-Check approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the Vulnerability-Check approval rule. Defaults to `0`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerability_states` | Array | no | The vulnerability states the Vulnerability-Check approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
```json
{
@@ -404,6 +410,12 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
+WARNING:
+The Vulnerability-Check feature, including the Vulnerability-Check attributes listed here, is in its
+end-of-life process. It is [deprecated](../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](../user/application_security/policies/#scan-result-policy-editor).
+
You can update project approval rules using the following endpoint:
```plaintext
@@ -423,10 +435,10 @@ PUT /projects/:id/approval_rules/:approval_rule_id
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
-| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
-| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
-| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
-| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
+| `scanners` | Array | no | The security scanners the Vulnerability-Check approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `severity_levels` | Array | no | The severity levels the Vulnerability-Check approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the Vulnerability-Check approval rule. Defaults to `0`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerability_states` | Array | no | The vulnerability states the Vulnerability-Check approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
```json
{
@@ -527,9 +539,9 @@ DELETE /projects/:id/approval_rules/:approval_rule_id
| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
| `approval_rule_id` | integer | yes | The ID of a approval rule
-## Merge Request-level MR approvals
+## Merge request-level MR approvals
-Configuration for approvals on a specific Merge Request. Must be authenticated for all endpoints.
+Configuration for approvals on a specific merge request. Must be authenticated for all endpoints.
### Get Configuration
@@ -957,7 +969,7 @@ These are system generated rules.
| `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
+## Approve merge request
> Moved to GitLab Premium in 13.9.
@@ -978,7 +990,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/approve
| `approval_password` | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/approvals/settings.md#require-user-password-to-approve) is enabled in the project settings. |
The `sha` parameter works in the same way as
-when [accepting a merge request](merge_requests.md#accept-mr): if it is passed, then it must
+when [accepting a merge request](merge_requests.md#merge-a-merge-request): if it is passed, then it must
match the current HEAD of the merge request for the approval to be added. If it
does not match, the response code is `409`.
@@ -1020,7 +1032,7 @@ does not match, the response code is `409`.
}
```
-## Unapprove Merge Request
+## Unapprove merge request
> Moved to GitLab Premium in 13.9.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 905ecd05d52..a54ea33aca8 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -13,41 +13,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Every API call to merge requests must be authenticated.
-**Important notes:**
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29984) in GitLab 12.8, the mergeability (`merge_status`)
-of each merge request is checked asynchronously when a request is made to this endpoint. Poll this API endpoint
-to get updated status. This affects the `has_conflicts` property as it is dependent on the `merge_status`. It returns
-`false` unless `merge_status` is `cannot_be_merged`.
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0, listing merge requests may
-not proactively update `merge_status` (which also affects the `has_conflicts`), as this can be an expensive operation.
-If you need the value of these fields from this endpoint, set the `with_merge_status_recheck` parameter to
-`true` in the query.
-- `references.relative` is relative to the group or project that the merge request is being requested. When the merge request
-is fetched from its project, `relative` format would be the same as `short` format, and when requested across groups or projects, it is expected to be the same as `full` format.
-- If `approvals_before_merge` is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect:
-
- - The target project's `approvals_before_merge` must be greater than zero. A
- value of zero disables approvals for that project.
- - The provided value of `approvals_before_merge` must be greater than the
- target project's `approvals_before_merge`.
-
- This API returns `HTTP 201 Created` for a successful response.
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6,
-diffs associated with the set of changes have the same size limitations applied as other diffs
-returned by the API or viewed via the UI. When these limits impact the results, the `overflow`
-field contains a value of `true`. Diff data without these limits applied can be retrieved by
-adding the `access_raw_diffs` parameter, accessing diffs not from the database but from Gitaly directly.
-This approach is generally slower and more resource-intensive, but isn't subject to size limits
-placed on database-backed diffs. [Limits inherent to Gitaly](../development/diffs.md#diff-limits)
-still apply.
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/349031) in GitLab 14.7,
-field `merge_user` can be either user who merged this merge request,
-user who set it to merge when pipeline succeeds or `null`.
-Field `merged_by` (user who merged this merge request or `null`) has been deprecated.
-
## List merge requests
Get all merge requests the authenticated user has access to. By
@@ -78,7 +43,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
-| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `order_by` | string | no | Return requests ordered by `created_at`, `title`, or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8.|
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
@@ -241,6 +206,14 @@ the `approvals_before_merge` parameter:
]
```
+### Merge requests list response notes
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0, listing merge requests may
+ not proactively update `merge_status` (which also affects the `has_conflicts`), as this can be an expensive operation.
+ If you need the value of these fields from this endpoint, set the `with_merge_status_recheck` parameter to
+ `true` in the query.
+- For notes on merge request object fields, read [Single merge request response notes](#single-merge-request-response-notes).
+
## List project merge requests
Get all merge requests for this project.
@@ -273,7 +246,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `iids[]` | integer array | no | Return the request having the given `iid`. |
| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
-| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `order_by` | string | no | Return requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
@@ -421,16 +394,6 @@ 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](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
@@ -445,6 +408,8 @@ the `approvals_before_merge` parameter:
]
```
+For important notes on response data, read [Merge requests list response notes](#merge-requests-list-response-notes).
+
## List group merge requests
Get all merge requests for this group and its subgroups.
@@ -468,7 +433,7 @@ Parameters:
| ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
-| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `order_by` | string | no | Return merge requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. |
| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
@@ -627,6 +592,8 @@ the `approvals_before_merge` parameter:
]
```
+For important notes on response data, read [Merge requests list response notes](#merge-requests-list-response-notes).
+
## Get single MR
Shows information about a single merge request.
@@ -805,7 +772,26 @@ the `approvals_before_merge` parameter:
}
```
-The `diff_refs` in the response correspond to the latest diff version of the merge request.
+### Single merge request response notes
+
+- The `merge_status` field may hold one of the following values:
+ - `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.
+- The `diff_refs` in the response correspond to the latest diff version of the merge request.
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29984) in GitLab 12.8, the mergeability (`merge_status`)
+ of each merge request is checked asynchronously when a request is made to this endpoint. Poll this API endpoint
+ to get updated status. This affects the `has_conflicts` property as it is dependent on the `merge_status`. It returns
+ `false` unless `merge_status` is `cannot_be_merged`.
+- `references.relative` is relative to the group or project that the merge request is being requested. When the merge
+ request is fetched from its project, `relative` format would be the same as `short` format, and when requested across
+ groups or projects, it is expected to be the same as `full` format.
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/349031) in GitLab 14.7,
+ field `merge_user` can be either user who merged this merge request,
+ user who set it to merge when pipeline succeeds or `null`.
+ Field `merged_by` (user who merged this merge request or `null`) has been deprecated.
## Get single MR participants
@@ -885,6 +871,15 @@ Parameters:
Shows information about the merge request including its files and changes.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6,
+diffs associated with the set of changes have the same size limitations applied as other diffs
+returned by the API or viewed via the UI. When these limits impact the results, the `overflow`
+field contains a value of `true`. Diff data without these limits applied can be retrieved by
+adding the `access_raw_diffs` parameter, accessing diffs not from the database but from Gitaly directly.
+This approach is generally slower and more resource-intensive, but isn't subject to size limits
+placed on database-backed diffs. [Limits inherent to Gitaly](../development/diffs.md#diff-limits)
+still apply.
+
```plaintext
GET /projects/:id/merge_requests/:merge_request_iid/changes
```
@@ -1040,8 +1035,8 @@ It requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to c
The new pipeline can be:
- A detached merge request pipeline.
-- A [pipeline for merged results](../ci/pipelines/pipelines_for_merged_results.md)
- if the [project setting is enabled](../ci/pipelines/pipelines_for_merged_results.md#enable-pipelines-for-merged-results). **(PREMIUM)**
+- A [merged results pipeline](../ci/pipelines/merged_results_pipelines.md)
+ if the [project setting is enabled](../ci/pipelines/merged_results_pipelines.md#enable-merged-results-pipelines).
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/pipelines
@@ -1116,9 +1111,17 @@ POST /projects/:id/merge_requests
| `milestone_id` | integer | no | The global ID of a milestone. |
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging. |
| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. |
-| `allow_maintainer_to_push` | boolean | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/22665), see `allow_collaboration`. |
+| `allow_maintainer_to_push` | boolean | no | Alias of `allow_collaboration`. |
+| `approvals_before_merge` **(PREMIUM)** | integer | no | Number of approvals required before this can be merged (see below). |
| `squash` | boolean | no | Squash commits into a single commit when merging. |
+If `approvals_before_merge` is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect:
+
+- The target project's `approvals_before_merge` must be greater than zero. A
+ value of zero disables approvals for that project.
+- The provided value of `approvals_before_merge` must be greater than the
+ target project's `approvals_before_merge`.
+
```json
{
"id": 1,
@@ -1251,6 +1254,8 @@ the `approvals_before_merge` parameter:
}
```
+For important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Update MR
Updates an existing merge request. You can change the target branch, title, or even close the MR.
@@ -1278,7 +1283,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `squash` | boolean | no | Squash commits into a single commit when merging. |
| `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. |
| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. |
-| `allow_maintainer_to_push` | boolean | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/22665), see `allow_collaboration`. |
+| `allow_maintainer_to_push` | boolean | no | Alias of `allow_collaboration`. |
Must include at least one non-required attribute from above.
@@ -1430,6 +1435,8 @@ the `approvals_before_merge` parameter:
}
```
+For important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Delete a merge request
Only for administrators and project owners. Deletes the merge request in question.
@@ -1447,17 +1454,9 @@ DELETE /projects/:id/merge_requests/:merge_request_iid
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/merge_requests/85"
```
-## Accept MR
-
-Merge changes submitted with MR using this API.
-
-If a merge request is unable to be accepted (such as Draft, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you receive a `405` and the error message 'Method Not Allowed'
-
-If it has some conflicts and can not be merged - you receive a `406` and the error message 'Branch cannot be merged'
-
-If the `sha` parameter is passed and does not match the HEAD of the source - you receive a `409` and the error message 'SHA does not match HEAD of source branch'
+## Merge a merge request
-If you don't have permissions to accept this merge request - you receive a `401`
+Accept and merge changes submitted with MR using this API.
```plaintext
PUT /projects/:id/merge_requests/:merge_request_iid/merge
@@ -1624,6 +1623,17 @@ the `approvals_before_merge` parameter:
}
```
+This API returns specific HTTP status codes on failure:
+
+| HTTP Status | Message | Reason |
+| :---: | ------- | ------ |
+| `401` | `Unauthorized` | This user does not have permission to accept this merge request. |
+| `405` | `Method Not Allowed` | The merge request cannot be accepted because it is `Draft`, `Closed`, `Pipeline Pending Completion`, or `Failed`. `Success` is required. |
+| `406` | `Branch cannot be merged` | The branch has conflicts and cannot be merged. |
+| `409` | `SHA does not match HEAD of source branch` | The provided `sha` parameter does not match the HEAD of the source. |
+
+For additional important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Merge to default merge ref path
Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
@@ -1821,6 +1831,8 @@ the `approvals_before_merge` parameter:
}
```
+For important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Rebase a merge request
Automatically rebase the `source_branch` of the merge request against its
@@ -2130,6 +2142,8 @@ the `approvals_before_merge` parameter:
}
```
+For important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Unsubscribe from a merge request
Unsubscribes the authenticated user from a merge request to not receive
@@ -2298,6 +2312,8 @@ the `approvals_before_merge` parameter:
}
```
+For important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
+
## Create a to-do item
Manually creates a to-do item for the current user on a merge request.
@@ -2686,7 +2702,7 @@ Example response:
## Approvals
-For approvals, see [Merge Request Approvals](merge_request_approvals.md)
+For approvals, see [Merge request approvals](merge_request_approvals.md)
## List merge request state events
diff --git a/doc/api/metrics_dashboard_annotations.md b/doc/api/metrics_dashboard_annotations.md
index feba57a7ced..7732bf61d77 100644
--- a/doc/api/metrics_dashboard_annotations.md
+++ b/doc/api/metrics_dashboard_annotations.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
diff --git a/doc/api/metrics_user_starred_dashboards.md b/doc/api/metrics_user_starred_dashboards.md
index f615ddaaa71..3e54ec74b24 100644
--- a/doc/api/metrics_user_starred_dashboards.md
+++ b/doc/api/metrics_user_starred_dashboards.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index a02d44136d1..3972a46d7fc 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/notes.md b/doc/api/notes.md
index 879ffaca191..445940e02fc 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -320,7 +320,7 @@ Parameters:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659"
```
-## Merge Requests
+## Merge requests
### List all merge request notes
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index ef7d133e907..59a929e30f4 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -1,8 +1,8 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
-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
+group: Authentication and Authorization
+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
---
# OAuth 2.0 identity provider API **(FREE)**
@@ -32,7 +32,7 @@ GitLab supports the following authorization flows:
hosted, first-party services. GitLab recommends against use of this flow.
The draft specification for [OAuth 2.1](https://oauth.net/2.1/) specifically omits both the
-Implicit grant and Resource Owner Password Credentials flows. It will be deprecated in the next OAuth specification version.
+Implicit grant and Resource Owner Password Credentials flows.
Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out
how all those flows work and pick the right one for your use case.
@@ -41,7 +41,9 @@ Both **authorization code** (with or without PKCE) and **implicit grant** flows
registered first via the `/profile/applications` page in your user's account.
During registration, by enabling proper scopes, you can limit the range of
resources which the `application` can access. Upon creation, you obtain the
-`application` credentials: _Application ID_ and _Client Secret_ - **keep them secure**.
+`application` credentials: _Application ID_ and _Client Secret_. The _Client Secret_
+**must be kept secure**. It is also advantageous to keep the _Application ID_
+secret when your application architecture allows.
For a list of scopes in GitLab, see [the provider documentation](../integration/oauth_provider.md#authorized-applications).
@@ -74,7 +76,10 @@ detailed flow description, from authorization request through access token.
The following steps describe our implementation of the flow.
The Authorization code with PKCE flow, PKCE for short, makes it possible to securely perform
-the OAuth exchange of client credentials for access tokens on public clients.
+the OAuth exchange of client credentials for access tokens on public clients without
+requiring access to the _Client Secret_ at all. This makes the PKCE flow advantageous
+for single page JavaScript applications or other client side apps where keeping secrets
+from the user is a technical impossibility.
Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `CODE_CHALLENGE`.
@@ -113,7 +118,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
any HTTP client. The following example uses Ruby's `rest-client`:
```ruby
- parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
+ parameters = 'client_id=APP_ID&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
RestClient.post 'https://gitlab.example.com/oauth/token', parameters
```
@@ -135,7 +140,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
- Sends new tokens in the response.
```ruby
- parameters = 'client_id=APP_ID&client_secret=APP_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
+ parameters = 'client_id=APP_ID&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
RestClient.post 'https://gitlab.example.com/oauth/token', parameters
```
@@ -239,19 +244,13 @@ You can now make requests to the API with the access token returned.
### Implicit grant flow
-NOTE:
-For a detailed flow diagram, see the [RFC specification](https://tools.ietf.org/html/rfc6749#section-4.2).
-
WARNING:
Implicit grant flow is inherently insecure and the IETF has removed it in [OAuth 2.1](https://oauth.net/2.1/).
-For this reason, [support for it is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/288516).
-In GitLab 14.0, new applications can't be created using it. In GitLab 14.4, support for it is
-scheduled to be removed for existing applications.
+It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/288516) for use in GitLab 14.0, and is planned for
+[removal](https://gitlab.com/gitlab-org/gitlab/-/issues/344609) in GitLab 15.0.
-We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce) instead. If you choose to use Implicit flow, be sure to verify the
-`application id` (or `client_id`) associated with the access token before granting
-access to the data. To learn more, read
-[Retrieving the token information](#retrieve-the-token-information)).
+We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce)
+instead.
Unlike the authorization code flow, the client receives an `access token`
immediately as a result of the authorization request. The flow does not use the
@@ -415,7 +414,7 @@ The following is an example response:
The fields `scopes` and `expires_in_seconds` are included in the response.
-These are aliases for `scope` and `expires_in` respectively, and have been included to
+These fields are aliases for `scope` and `expires_in` respectively, and have been included to
prevent breaking changes introduced in [doorkeeper 5.0.2](https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-versions#from-4x-to-5x).
Don't rely on these fields as they are slated for removal in a later release.
diff --git a/doc/api/pages.md b/doc/api/pages.md
index a115f0b0a0f..7316d225dbc 100644
--- a/doc/api/pages.md
+++ b/doc/api/pages.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## Unpublish pages
-Remove pages. The user must have the Administrator role.
+Remove pages. The user must have administrator access.
```plaintext
DELETE /projects/:id/pages
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index 624bdf29e5d..c1f81ffa361 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## List all Pages domains
-Get a list of all Pages domains. The user must have the administrator role.
+Get a list of all Pages domains. The user must have administrator access.
```plaintext
GET /pages/domains
diff --git a/doc/api/plan_limits.md b/doc/api/plan_limits.md
index 8d37189ef2a..75c8d241513 100644
--- a/doc/api/plan_limits.md
+++ b/doc/api/plan_limits.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -13,8 +13,7 @@ The plan limits API allows you to maintain the application limits for the existi
The existing plans depend on the GitLab edition. In the Community Edition, only the plan `default`
is available. In the Enterprise Edition, additional plans are available as well.
-NOTE:
-The Administrator role is required to use this API.
+Administrator access is required to use this API.
## Get current plan limits
diff --git a/doc/api/project_access_tokens.md b/doc/api/project_access_tokens.md
index 125797a802f..f6eced4f08a 100644
--- a/doc/api/project_access_tokens.md
+++ b/doc/api/project_access_tokens.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/project_clusters.md b/doc/api/project_clusters.md
index 129b064c650..c1f59520bd7 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-Users need at least the [Maintainer](../user/permissions.md) role to use these endpoints.
+Users need at least the Maintainer role to use these endpoints.
## List project clusters
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index e7609d34998..218036b1ee0 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -188,9 +188,9 @@ As an administrator, you can modify the maximum import file size. To do so, use
## Import a file from a remote object storage
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/282503) in GitLab 13.12 in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/282503) in GitLab 13.12 in [Beta](../policy/alpha-beta-support.md#beta-features).
-This endpoint is behind a feature flag that is disabled by default.
+This endpoint is behind a feature flag that is enabled by default.
To enable this endpoint:
@@ -243,8 +243,8 @@ curl --request POST \
}
```
-The `ContentType` header must return a valid number. The maximum file size is 10 gigabytes.
-The `ContentLength` header must be `application/gzip`.
+The `Content-Length` header must return a valid number. The maximum file size is 10 gigabytes.
+The `Content-Type` header must be `application/gzip`.
## Import status
diff --git a/doc/api/project_relations_export.md b/doc/api/project_relations_export.md
index 2016dcbd141..74fdc91e420 100644
--- a/doc/api/project_relations_export.md
+++ b/doc/api/project_relations_export.md
@@ -18,7 +18,7 @@ With the Project Relations Export API, you can partially export project structur
similar to [project export](project_import_export.md),
but it exports each top-level relation (for example, milestones/boards/labels) as a separate file
instead of one archive. The project relations export API is primarily used in
-[group migration](../user/group/import/index.md#enable-or-disable-gitlab-group-migration)
+[group migration](../user/group/import/index.md)
to support group project import.
## Schedule new export
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index c5f317f7540..efbd8bf9431 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -246,7 +246,7 @@ curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/
## Get user agent details
-Available only for users with the Administrator [role](../user/permissions.md).
+Available only for users with administrator access.
```plaintext
GET /projects/:id/snippets/:snippet_id/user_agent_detail
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 791be613c71..db8d2361439 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -10,8 +10,8 @@ Interact with [projects](../user/project/index.md) using the REST API.
## Project visibility level
-Project in GitLab can be either private, internal or public.
-This is determined by the `visibility` field in the project.
+A project in GitLab can be private, internal, or public.
+The visibility level is determined by the `visibility` field in the project.
Values for the project visibility level are:
@@ -55,7 +55,7 @@ GET /projects
| `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`, `last_activity_at`, or `similarity` fields. `repository_size`, `storage_size`, `packages_size` or `wiki_size` fields are only allowed for administrators. `similarity` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332890) in GitLab 14.1) is only available when searching and is limited to projects that the current user is a member of. Default is `created_at`. |
| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
-| `repository_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in GitLab 11.2). |
+| `repository_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the repository checksum calculation has failed. |
| `repository_storage` | string | **{dotted-circle}** No | Limit results to projects stored on `repository_storage`. _(administrators only)_ |
| `search_namespaces` | boolean | **{dotted-circle}** No | Include ancestor namespaces when matching search criteria. Default is `false`. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
@@ -65,7 +65,7 @@ GET /projects
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. Only available to Reporter or higher level role members. |
| `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 11.2). |
+| `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed. |
| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(administrator only)_ |
| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
| `with_merge_requests_enabled` | boolean | **{dotted-circle}** No | Limit by enabled merge requests feature. |
@@ -383,6 +383,7 @@ GET /users/:user_id/projects
| Attribute | Type | Required | Description |
|-------------------------------|---------|------------------------|-------------|
+| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
| `id_after` | integer | **{dotted-circle}** No | Limit results to projects with IDs greater than the specified ID. |
| `id_before` | integer | **{dotted-circle}** No | Limit results to projects with IDs less than the specified ID. |
@@ -395,7 +396,6 @@ GET /users/:user_id/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. Only available to Reporter or higher level role members. |
-| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(administrator only)_ |
| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
@@ -628,17 +628,17 @@ GET /users/:user_id/starred_projects
| Attribute | Type | Required | Description |
|-------------------------------|---------|------------------------|-------------|
+| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
| `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`. |
| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
-| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned.. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
| `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. Only available to Reporter or higher level role members. |
-| `user_id` | string | **{check-circle}** Yes | The ID or username of the user. |
| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(administrator only)_ |
| `with_issues_enabled` | boolean | **{dotted-circle}** No | Limit by enabled issues feature. |
@@ -1045,10 +1045,6 @@ can also see the `approvals_before_merge` parameter:
}
```
-The `web_url` and `avatar_url` attributes on `namespace` were
-[introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27427)
-in GitLab 11.11.
-
If the project is a fork, the `forked_from_project` field appears in the response.
For this field, if the upstream project is private, a valid token for authentication must be provided.
The field `mr_default_target_self` appears as well. If this value is `false`, then all merge requests
@@ -1164,12 +1160,12 @@ GET /projects/:id/groups
| Attribute | Type | Required | Description |
|-----------------------------|-------------------|------------------------|-------------|
-| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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`. |
| `shared_min_access_level` | integer | **{dotted-circle}** No | Limit to shared groups with at least this [access level](members.md#valid-access-levels). |
| `shared_visible_only` | boolean | **{dotted-circle}** No | Limit to shared groups user has access to. |
+| `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`. |
```json
[
@@ -1226,8 +1222,8 @@ POST /projects
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `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 | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `container_registry_access_level` | string | **{dotted-circle}** No | Set visibility of container registry, for this project, to one of `disabled`, `private` or `enabled`. |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `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. |
@@ -1248,21 +1244,20 @@ POST /projects
| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
-| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful pipelines. This setting is named [**Pipelines must succeed**](../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) in the project settings. |
+| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
-| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrator only)_ |
| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
-| `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`. |
@@ -1304,10 +1299,10 @@ POST /projects/user/:user_id
| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
-| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `container_registry_access_level` | string | **{dotted-circle}** No | Set visibility of container registry, for this project, to one of `disabled`, `private` or `enabled`. |
-| `description` | string | **{dotted-circle}** No | Short project description. |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `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. |
| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
@@ -1319,19 +1314,17 @@ POST /projects/user/:user_id
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
-| `squash_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create squash commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) in GitLab 14.6.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
-| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
+| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
-| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
| `path` | string | **{dotted-circle}** No | Custom repository name for new project. By default generated based on name. |
| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project-members. |
@@ -1339,11 +1332,12 @@ POST /projects/user/:user_id
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrators only)_ |
| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
-| `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_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create squash commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) in GitLab 14.6.)_ |
| `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. |
@@ -1379,6 +1373,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|----------------|------------------------|-------------|
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `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. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
@@ -1395,38 +1390,39 @@ Supported attributes:
| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone). |
| `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
| `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). |
-| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `container_registry_access_level` | string | **{dotted-circle}** No | Set visibility of container registry, for this project, to one of `disabled`, `private` or `enabled`. |
+| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. |
| `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. |
| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
-| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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. |
+| `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). |
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
+| `keep_latest_artifact` | boolean | **{dotted-circle}** No | Disable or enable the ability to keep the latest artifact for this project. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
| `merge_pipelines_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge pipelines. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `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). |
| `merge_trains_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge trains. |
| `mirror_overwrites_diverged_branches` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirror overwrites diverged branches. |
| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
| `mirror_user_id` **(PREMIUM)** | integer | **{dotted-circle}** No | User responsible for all the activity surrounding a pull mirror event. _(administrators only)_ |
| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `mr_default_target_self` | boolean | **{dotted-circle}** No | For forked projects, target merge requests to this project. If `false`, the target will be the upstream project. |
| `name` | string | **{dotted-circle}** No | The name of the project. |
-| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
| `only_mirror_protected_branches` **(PREMIUM)** | boolean | **{dotted-circle}** No | Only mirror protected branches. |
+| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
-| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
-| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only users with the [Maintainer role](../user/permissions.md) to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. |
| `path` | string | **{dotted-circle}** No | Custom repository name for the project. By default generated based on name. |
| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
@@ -1434,10 +1430,11 @@ Supported attributes:
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrators only)_ |
| `request_access_enabled` | boolean | **{dotted-circle}** No | Allow users to request member access. |
+| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
| `resolve_outdated_diff_discussions` | boolean | **{dotted-circle}** No | Automatically resolve merge request diffs discussions on lines changed with a push. |
+| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only users with the Maintainer role to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. |
| `service_desk_enabled` | boolean | **{dotted-circle}** No | Enable or disable Service Desk feature. |
| `shared_runners_enabled` | boolean | **{dotted-circle}** No | Enable shared runners for this project. |
-| `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_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create squash commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) in GitLab 14.6.)_ |
@@ -1448,10 +1445,6 @@ Supported attributes:
| `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. |
-| `mr_default_target_self` | boolean | **{dotted-circle}** No | For forked projects, target merge requests to this project. If `false`, the target will be the upstream project. |
## Fork project
@@ -1468,18 +1461,16 @@ POST /projects/:id/fork
| Attribute | Type | Required | Description |
|------------------|----------------|------------------------|-------------|
| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `description` | string | **{dotted-circle}** No | The description assigned to the resultant project after forking. |
+| `mr_default_target_self` | boolean | **{dotted-circle}** No | For forked projects, target merge requests to this project. If `false`, the target will be the upstream project. |
| `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 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. |
-| `mr_default_target_self` | boolean | **{dotted-circle}** No | For forked projects, target merge requests to this project. If `false`, the target will be the upstream project. |
-
-## List Forks of a project
-> Introduced in GitLab 10.1.
+## List forks of a project
List the projects accessible to the calling user that have an established,
forked relationship with the specified project
@@ -1490,8 +1481,8 @@ GET /projects/:id/forks
| Attribute | Type | Required | Description |
|-------------------------------|----------------|------------------------|-------------|
-| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
| `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`. |
@@ -1789,7 +1780,7 @@ Example response:
}
```
-## List Starrers of a project
+## List starrers of a project
List the users who starred the specified project.
@@ -2267,10 +2258,10 @@ POST /projects/:id/share
| Attribute | Type | Required | Description |
|----------------|----------------|------------------------|-------------|
-| `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 or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `expires_at` | string | **{dotted-circle}** No | Share expiration date in ISO 8601 format: 2016-09-26 |
## Delete a shared project link within a group
@@ -2375,11 +2366,12 @@ POST /projects/:id/hooks
| Attribute | Type | Required | Description |
|------------------------------|----------------|------------------------|-------------|
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `url` | string | **{check-circle}** Yes | The hook URL. |
| `confidential_issues_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential issues events. |
| `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 or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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. |
@@ -2387,11 +2379,10 @@ POST /projects/:id/hooks
| `pipeline_events` | boolean | **{dotted-circle}** No | Trigger hook on pipeline events. |
| `push_events_branch_filter` | string | **{dotted-circle}** No | Trigger hook on push events for matching branches only. |
| `push_events` | boolean | **{dotted-circle}** No | Trigger hook on push events. |
+| `releases_events` | boolean | **{dotted-circle}** No | Trigger hook on release events. |
| `tag_push_events` | boolean | **{dotted-circle}** No | Trigger hook on tag push events. |
| `token` | string | **{dotted-circle}** No | Secret token to validate received payloads; this isn't returned in the response. |
-| `url` | string | **{check-circle}** Yes | The hook URL. |
| `wiki_page_events` | boolean | **{dotted-circle}** No | Trigger hook on wiki events. |
-| `releases_events` | boolean | **{dotted-circle}** No | Trigger hook on release events. |
### Edit project hook
@@ -2403,12 +2394,13 @@ PUT /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
|------------------------------|----------------|------------------------|-------------|
+| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `url` | string | **{check-circle}** Yes | The hook URL. |
| `confidential_issues_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential issues events. |
| `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. |
-| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
-| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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. |
@@ -2416,11 +2408,10 @@ PUT /projects/:id/hooks/:hook_id
| `pipeline_events` | boolean | **{dotted-circle}** No | Trigger hook on pipeline events. |
| `push_events_branch_filter` | string | **{dotted-circle}** No | Trigger hook on push events for matching branches only. |
| `push_events` | boolean | **{dotted-circle}** No | Trigger hook on push events. |
+| `releases_events` | boolean | **{dotted-circle}** No | Trigger hook on release events. |
| `tag_push_events` | boolean | **{dotted-circle}** No | Trigger hook on tag push events. |
| `token` | string | **{dotted-circle}** No | Secret token to validate received payloads; this isn't returned in the response. |
-| `url` | string | **{check-circle}** Yes | The hook URL. |
| `wiki_page_events` | boolean | **{dotted-circle}** No | Trigger hook on wiki page events. |
-| `releases_events` | boolean | **{dotted-circle}** No | Trigger hook on release events. |
### Delete project hook
@@ -2478,8 +2469,8 @@ GET /projects
| Attribute | Type | Required | Description |
|------------|--------|------------------------|-------------|
-| `order_by` | string | **{dotted-circle}** No | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields. |
| `search` | string | **{check-circle}** Yes | A string contained in the project name. |
+| `order_by` | string | **{dotted-circle}** No | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields. |
| `sort` | string | **{dotted-circle}** No | Return requests sorted in `asc` or `desc` order. |
```shell
@@ -2496,11 +2487,11 @@ POST /projects/:id/housekeeping
|-----------|----------------|------------------------|-------------|
| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
-## Push Rules **(PREMIUM)**
+## Push rules **(PREMIUM)**
### Get project push rules
-Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a
+Get the [push rules](../user/project/repository/push_rules.md#enabling-push-rules) of a
project.
```plaintext
@@ -2554,6 +2545,7 @@ POST /projects/:id/push_rule
| Attribute | Type | Required | Description |
|-----------------------------------------|----------------|------------------------|-------------|
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
| `commit_committer_check` | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
@@ -2561,7 +2553,6 @@ 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 or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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. |
@@ -2577,6 +2568,7 @@ PUT /projects/:id/push_rule
| Attribute | Type | Required | Description |
|-----------------------------------------|----------------|------------------------|-------------|
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
| `commit_committer_check` | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
@@ -2584,7 +2576,6 @@ 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 or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.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. |
@@ -2607,7 +2598,8 @@ DELETE /projects/:id/push_rule
## Transfer a project to a new namespace
-> Introduced in GitLab 11.1.
+See the [Project documentation](../user/project/settings/index.md#transferring-an-existing-project-into-another-namespace)
+for prerequisites to transfer a project.
```plaintext
PUT /projects/:id/transfer
@@ -2736,7 +2728,7 @@ Example response:
Read more in the [Branches](branches.md) documentation.
-## Project Import/Export
+## Project import/export
Read more in the [Project import/export](project_import_export.md) documentation.
@@ -2750,8 +2742,7 @@ Read more in the [Project vulnerabilities](project_vulnerabilities.md) documenta
## Configure pull mirroring for a project **(PREMIUM)**
-> - Introduced in GitLab 11.
-> - Moved to GitLab Premium in 13.9.
+> Moved to GitLab Premium in 13.9.
Configure pull mirroring while [creating a new project](#create-project)
or [updating an existing project](#edit-project) using the API
@@ -2791,8 +2782,6 @@ Read more in the [Project Badges](project_badges.md) documentation.
## Download snapshot of a Git repository
-> Introduced in GitLab 10.7
-
This endpoint may only be accessed by an administrative user.
Download a snapshot of the project (or wiki, if requested) Git repository. This
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index fd024240e90..23acebf5aab 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -185,17 +185,17 @@ This allows you to create a single file. For creating multiple files with a sing
POST /projects/:id/repository/files/:file_path
```
-| Attribute | Type | Required | Description |
-|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
-| `branch` | string | yes | Name of the branch |
-| `start_branch` | string | no | Name of the branch to start the new commit from |
-| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
-| `author_email` | string | no | Specify the commit author's email address |
-| `author_name` | string | no | Specify the commit author's name |
-| `content` | string | yes | File content |
-| `commit_message` | string | yes | Commit message |
+| Attribute | Type | Required | Description |
+| ---------------- | -------------- | -------- | ----------- |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
+| `start_branch` | string | no | Name of the base branch to create the new branch from. |
+| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
+| `author_email` | string | no | The commit author's email address. |
+| `author_name` | string | no | The commit author's name. |
+| `content` | string | yes | The file's content. |
+| `commit_message` | string | yes | The commit message. |
```shell
curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' \
@@ -222,18 +222,18 @@ This allows you to update a single file. For updating multiple files with a sing
PUT /projects/:id/repository/files/:file_path
```
-| Attribute | Type | Required | Description |
-|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| Attribute | Type | Required | Description |
+| ---------------- | -------------- | -------- | ----------- |
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
-| `branch` | string | yes | Name of the branch |
-| `start_branch` | string | no | Name of the branch to start the new commit from |
-| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
-| `author_email` | string | no | Specify the commit author's email address |
-| `author_name` | string | no | Specify the commit author's name |
-| `content` | string | yes | File content |
-| `commit_message` | string | yes | Commit message |
-| `last_commit_id` | string | no | Last known file commit ID |
+| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
+| `start_branch` | string | no | Name of the base branch to create the new branch from. |
+| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
+| `author_email` | string | no | The commit author's email address. |
+| `author_name` | string | no | The commit author's name. |
+| `content` | string | yes | The file's content. |
+| `commit_message` | string | yes | The commit message. |
+| `last_commit_id` | string | no | Last known file commit ID. |
```shell
curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' \
@@ -270,16 +270,16 @@ This allows you to delete a single file. For deleting multiple files with a sing
DELETE /projects/:id/repository/files/:file_path
```
-| Attribute | Type | Required | Description |
-|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
-| `branch` | string | yes | Name of the branch |
-| `start_branch` | string | no | Name of the branch to start the new commit from |
-| `author_email` | string | no | Specify the commit author's email address. |
-| `author_name` | string | no | Specify the commit author's name. |
-| `commit_message` | string | yes | Commit message. |
-| `last_commit_id` | string | no | Last known file commit ID. |
+| Attribute | Type | Required | Description |
+| ---------------- | -------------- | -------- | ----------- |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
+| `start_branch` | string | no | Name of the base branch to create the new branch from. |
+| `author_email` | string | no | The commit author's email address. |
+| `author_name` | string | no | The commit author's name. |
+| `commit_message` | string | yes | The commit message. |
+| `last_commit_id` | string | no | Last known file commit ID. |
```shell
curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \
diff --git a/doc/api/runners.md b/doc/api/runners.md
index e53062ce074..3423a02c078 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -39,27 +39,38 @@ Get a list of specific runners available to the user.
GET /runners
GET /runners?scope=active
GET /runners?type=project_type
-GET /runners?status=active
+GET /runners?status=online
+GET /runners?paused=true
GET /runners?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|-------------|----------------|----------|---------------------|
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `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 |
+| Attribute | Type | Required | Description |
+|------------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
+| `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: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 15.0 |
+| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
+| `tag_list` | string array | no | List of the runner's tags |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners"
```
+NOTE:
+The `active` and `paused` values in the `status` query parameter were deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). They are replaced by the `paused` query parameter.
+
+NOTE:
+The `active` attribute in the response was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
[
{
"active": true,
+ "paused": false,
"description": "test-1-20150125",
"id": 6,
"ip_address": "127.0.0.1",
@@ -71,6 +82,7 @@ Example response:
},
{
"active": true,
+ "paused": false,
"description": "test-2-20150125",
"id": 8,
"ip_address": "127.0.0.1",
@@ -86,33 +98,44 @@ Example response:
## List all runners **(FREE SELF)**
Get a list of all runners in the GitLab instance (specific and shared). Access
-is restricted to users with the administrator role.
+is restricted to users with administrator access.
```plaintext
GET /runners/all
GET /runners/all?scope=online
GET /runners/all?type=project_type
-GET /runners/all?status=active
+GET /runners/all?status=online
+GET /runners/all?paused=true
GET /runners/all?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|-------------|----------------|----------|---------------------|
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `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 |
+| Attribute | Type | Required | Description |
+|------------|--------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online` and `offline`; showing all runners if none provided |
+| `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: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 15.0 |
+| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
+| `tag_list` | string array | no | List of the runner's tags |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/all"
```
+NOTE:
+The `active` and `paused` values in the `status` query parameter were deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). They are replaced by the `paused` query parameter.
+
+NOTE:
+The `active` attribute in the response was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
[
{
"active": true,
+ "paused": false,
"description": "shared-runner-1",
"id": 1,
"ip_address": "127.0.0.1",
@@ -124,6 +147,7 @@ Example response:
},
{
"active": true,
+ "paused": false,
"description": "shared-runner-2",
"id": 3,
"ip_address": "127.0.0.1",
@@ -135,6 +159,7 @@ Example response:
},
{
"active": true,
+ "paused": false,
"description": "test-1-20150125",
"id": 6,
"ip_address": "127.0.0.1",
@@ -146,6 +171,7 @@ Example response:
},
{
"active": true,
+ "paused": false,
"description": "test-2-20150125",
"id": 8,
"ip_address": "127.0.0.1",
@@ -164,7 +190,7 @@ To view more than the first 20 runners, use [pagination](index.md#pagination).
Get details of a runner.
-At least the [Maintainer role](../user/permissions.md) is required to get runner details at the
+At least the Maintainer role 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.
@@ -185,11 +211,16 @@ NOTE:
The `token` attribute in the response was deprecated [in GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/214320).
and removed in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/214322).
+NOTE:
+The `active` attribute in the response was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
{
"active": true,
+ "paused": false,
"architecture": null,
"description": "test-1-20150125",
"id": 6,
@@ -229,16 +260,17 @@ Update details of a runner.
PUT /runners/:id
```
-| Attribute | Type | Required | Description |
-|---------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a runner |
-| `description` | string | no | The description of a runner |
-| `active` | boolean | no | The state of a runner; can be set to `true` or `false` |
-| `tag_list` | array | no | The list of tags for a runner; put array of tags, that should be finally assigned to a runner |
-| `run_untagged`| boolean | no | Flag indicating the runner can execute untagged jobs |
-| `locked` | boolean | no | Flag indicating the runner is locked |
-| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
-| `maximum_timeout` | integer | no | Maximum timeout set when this runner handles the job |
+| Attribute | Type | Required | Description |
+|-------------------|---------|----------|--------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | The ID of a runner |
+| `description` | string | no | The description of a runner |
+| `active` | boolean | no | Deprecated: Use `:paused` instead. Flag indicating whether the runner is allowed to receive jobs |
+| `paused` | boolean | no | Flag indicating whether the runner should ignore new jobs |
+| `tag_list` | array | no | The list of tags for a runner; put array of tags, that should be finally assigned to a runner |
+| `run_untagged` | boolean | no | Flag indicating the runner can execute untagged jobs |
+| `locked` | boolean | no | Flag indicating the runner is locked |
+| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
+| `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" \
@@ -249,6 +281,10 @@ NOTE:
The `token` attribute in the response was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/214320) in GitLab 12.10.
and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/214322) in GitLab 13.0.
+NOTE:
+The `active` query parameter was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
@@ -292,7 +328,12 @@ Example response:
Pause a specific runner.
```plaintext
-PUT --form "active=false" /runners/:runner_id
+PUT --form "paused=true" /runners/:runner_id
+
+# --or--
+
+# Deprecated: removal planned in 15.0
+PUT --form "active=false" /runners/:runner_id
```
| Attribute | Type | Required | Description |
@@ -301,9 +342,19 @@ PUT --form "active=false" /runners/:runner_id
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "paused=true" "https://gitlab.example.com/api/v4/runners/6"
+
+# --or--
+
+# Deprecated: removal planned in 15.0
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
--form "active=false" "https://gitlab.example.com/api/v4/runners/6"
```
+NOTE:
+The `active` form attribute was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
## List runner's jobs
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15432) in GitLab 10.3.
@@ -397,35 +448,45 @@ Example response:
## List project's runners
-List all runners (specific and shared) available in the project. Shared runners
-are listed if at least one shared runner is defined.
+List all runners available in the project, including from ancestor groups and [any allowed shared runners](../ci/runners/runners_scope.md#enable-shared-runners).
```plaintext
GET /projects/:id/runners
GET /projects/:id/runners?scope=active
GET /projects/:id/runners?type=project_type
-GET /projects/:id/runners?status=active
+GET /projects/:id/runners/all?status=online
+GET /projects/:id/runners/all?paused=true
GET /projects/:id/runners?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|------------|----------------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `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 |
+| Attribute | Type | Required | Description |
+|------------|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
+| `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: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 15.0 |
+| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
+| `tag_list` | string array | no | List of the runner's tags |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners"
```
+NOTE:
+The `active` and `paused` values in the `status` query parameter were deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). They are replaced by the `paused` query parameter.
+
+NOTE:
+The `active` attribute in the response was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
[
{
"active": true,
+ "paused": false,
"description": "test-2-20150125",
"id": 8,
"ip_address": "127.0.0.1",
@@ -437,6 +498,7 @@ Example response:
},
{
"active": true,
+ "paused": false,
"description": "development_runner",
"id": 5,
"ip_address": "127.0.0.1",
@@ -444,7 +506,7 @@ Example response:
"runner_type": "instance_type",
"name": null,
"online": true,
- "status": "paused"
+ "status": "online"
}
]
```
@@ -504,27 +566,36 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## List group's runners
-List all runners (specific and shared) available in the group as well it's ancestor groups.
-Shared runners are listed if at least one shared runner is defined.
+List all runners available in the group as well as its ancestor groups, including [any allowed shared runners](../ci/runners/runners_scope.md#enable-shared-runners).
```plaintext
GET /groups/:id/runners
GET /groups/:id/runners?type=group_type
-GET /groups/:id/runners?status=active
+GET /groups/:id/runners/all?status=online
+GET /groups/:id/runners/all?paused=true
GET /groups/:id/runners?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|------------|----------------|----------|---------------------|
-| `id` | integer | yes | The ID of the group owned by the authenticated user |
-| `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 |
+| Attribute | Type | Required | Description |
+|------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | The ID of the group owned by the authenticated user |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type`. The `project_type` value is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351466) and will be removed in GitLab 15.0 |
+| `status` | string | no | The status of runners to show, one of: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 15.0 |
+| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
+| `tag_list` | string array | no | List of the runner's tags |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/9/runners"
```
+NOTE:
+The `active` and `paused` values in the `status` query parameter were deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). They are replaced by the `paused` query parameter.
+
+NOTE:
+The `active` attribute in the response was deprecated [in GitLab 14.8](https://gitlab.com/gitlab-org/gitlab/-/issues/347211).
+and will be removed in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). It is replaced by the `paused` attribute.
+
Example response:
```json
@@ -534,6 +605,7 @@ Example response:
"description": "Shared",
"ip_address": "127.0.0.1",
"active": true,
+ "paused": false,
"is_shared": true,
"runner_type": "instance_type",
"name": "gitlab-runner",
@@ -545,6 +617,7 @@ Example response:
"description": "Test",
"ip_address": "127.0.0.1",
"active": true,
+ "paused": false,
"is_shared": true,
"runner_type": "instance_type",
"name": "gitlab-runner",
@@ -556,6 +629,7 @@ Example response:
"description": "Test 2",
"ip_address": "127.0.0.1",
"active": true,
+ "paused": false,
"is_shared": false,
"runner_type": "group_type",
"name": "gitlab-runner",
@@ -573,18 +647,20 @@ Register a new runner for the instance.
POST /runners
```
-| Attribute | Type | Required | Description |
-|-------------------|----------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `token` | string | yes | [Registration token](#registration-and-authentication-tokens). |
-| `description` | string | no | Runner's description |
-| `info` | hash | no | Runner's metadata. You can include `name`, `version`, `revision`, `platform`, and `architecture`, but only `version` is displayed in the Admin area of the UI. |
-| `active` | boolean | no | Whether the runner is active |
-| `locked` | boolean | no | Whether the runner should be locked for current project |
-| `run_untagged` | boolean | no | Whether the runner should handle untagged jobs |
-| `tag_list` | string array | no | List of runner's tags |
-| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
-| `maximum_timeout` | integer | no | Maximum timeout set when this runner handles the job |
-| `maintainer_note` | string | no | Free-form maintainer notes for the runner (255 characters) |
+| Attribute | Type | Required | Description |
+|--------------------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `token` | string | yes | [Registration token](#registration-and-authentication-tokens) |
+| `description` | string | no | Runner's description |
+| `info` | hash | no | Runner's metadata. You can include `name`, `version`, `revision`, `platform`, and `architecture`, but only `version` is displayed in the Admin area of the UI |
+| `active` | boolean | no | Deprecated: Use `:paused` instead. Whether the runner is allowed to receive jobs |
+| `paused` | boolean | no | Whether the runner should ignore new jobs |
+| `locked` | boolean | no | Whether the runner should be locked for current project |
+| `run_untagged` | boolean | no | Whether the runner should handle untagged jobs |
+| `tag_list` | string array | no | List of runner's tags |
+| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
+| `maximum_timeout` | integer | no | Maximum timeout set when this runner handles the job |
+| `maintainer_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350730), see `maintenance_note` |
+| `maintenance_note` | string | no | Free-form maintenance notes for the runner (255 characters) |
```shell
curl --request POST "https://gitlab.example.com/api/v4/runners" \
@@ -603,7 +679,8 @@ Example response:
```json
{
"id": 12345,
- "token": "6337ff461c94fd3fa32ba3b1ff4125"
+ "token": "6337ff461c94fd3fa32ba3b1ff4125",
+ "token_expires_at": "2021-09-27T21:05:03.203Z"
}
```
@@ -743,6 +820,7 @@ Example response:
```json
{
- "token": "6337ff461c94fd3fa32ba3b1ff4125"
+ "token": "6337ff461c94fd3fa32ba3b1ff4125",
+ "token_expires_at": "2021-09-27T21:05:03.203Z"
}
```
diff --git a/doc/api/scim.md b/doc/api/scim.md
index acc6a6ae686..ab3a181f5be 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/settings.md b/doc/api/settings.md
index 2ed841b885c..4246c7a46f1 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -65,6 +65,8 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "ecdsa_sk_key_restriction": 0,
+ "ed25519_sk_key_restriction": 0,
"first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
@@ -166,6 +168,8 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "ecdsa_sk_key_restriction": 0,
+ "ed25519_sk_key_restriction": 0,
"first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
@@ -268,7 +272,9 @@ listed in the descriptions of the relevant settings.
| `domain_allowlist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |
+| `ecdsa_sk_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA_SK key. Default is `0` (no restriction). `-1` disables ECDSA_SK keys. |
| `ed25519_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default is `0` (no restriction). `-1` disables ED25519 keys. |
+| `ed25519_sk_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519_SK key. Default is `0` (no restriction). `-1` disables ED25519_SK keys. |
| `eks_access_key_id` | string | no | AWS IAM access key ID. |
| `eks_account_id` | string | no | Amazon account ID. |
| `eks_integration_enabled` | boolean | no | Enable integration with Amazon EKS. |
@@ -370,6 +376,7 @@ listed in the descriptions of the relevant settings.
| `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services fire or not. Webhooks and services aren't submitted if it surpasses that value. |
| `rate_limiting_response_text` | string | no | When rate limiting is enabled via the `throttle_*` settings, send this plain text response when a rate limit is exceeded. 'Retry later' is sent if this is blank. |
| `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.|
+| `user_email_lookup_limit` | integer | no | Max number of requests per minute for email lookup. Default: 60. To disable throttling set to 0.|
| `recaptcha_enabled` | boolean | no | (**If enabled, requires:** `recaptcha_private_key` and `recaptcha_site_key`) Enable reCAPTCHA. |
| `recaptcha_private_key` | string | required by: `recaptcha_enabled` | Private key for reCAPTCHA. |
| `recaptcha_site_key` | string | required by: `recaptcha_enabled` | Site key for reCAPTCHA. |
diff --git a/doc/api/statistics.md b/doc/api/statistics.md
index 59197260988..17daf2fc71f 100644
--- a/doc/api/statistics.md
+++ b/doc/api/statistics.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/status_checks.md b/doc/api/status_checks.md
index 7de188ad185..a3a342854dd 100644
--- a/doc/api/status_checks.md
+++ b/doc/api/status_checks.md
@@ -31,7 +31,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/status_checks
"id": 2,
"name": "Rule 1",
"external_url": "https://gitlab.com/test-endpoint",
- "status": "approved"
+ "status": "pass"
},
{
"id": 1,
@@ -47,6 +47,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/status_checks
For a single merge request, use the API to inform GitLab that a merge request has passed a check by an external service.
To set the status of an external check, the personal access token used must belong to a user with at least the developer role on the target project of the merge request.
+Execute this API call as any user with rights to approve the merge request itself.
+
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/status_check_responses
```
@@ -59,6 +61,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/status_check_responses
| `merge_request_iid` | integer | yes | IID of a merge request |
| `sha` | string | yes | SHA at `HEAD` of the source branch |
| `external_status_check_id` | integer | yes | ID of an external status check |
+| `status` | string | no | Set to `pass` to pass the check |
NOTE:
`sha` must be the SHA at the `HEAD` of the merge request's source branch.
diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md
index ea9baa79b4a..0a3e7d54f88 100644
--- a/doc/api/suggestions.md
+++ b/doc/api/suggestions.md
@@ -13,8 +13,8 @@ Every API call to suggestions must be authenticated.
## Applying suggestions
-Applies a suggested patch in a merge request. Users must be
-at least [Developer](../user/permissions.md) to perform such action.
+Applies a suggested patch in a merge request. Users must have
+at least the Developer role to perform such action.
```plaintext
PUT /suggestions/:id/apply
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 6aa40cf476d..903cb361587 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -22,7 +22,7 @@ Parameters:
| `id` | integer/string| yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user|
| `order_by` | string | no | Return tags ordered by `name` or `updated` fields. Default is `updated` |
| `sort` | string | no | Return tags sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. |
+| `search` | string | no | Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. No other regular expressions are supported. |
```json
[
diff --git a/doc/api/usage_data.md b/doc/api/usage_data.md
index 4809166f357..c7064ebf65b 100644
--- a/doc/api/usage_data.md
+++ b/doc/api/usage_data.md
@@ -13,7 +13,7 @@ The Service Data API is associated with [Service Ping](../development/service_pi
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57270) in GitLab 13.11.
-Export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](https://metrics.gitlab.com/index.html), for easier importing.
+Export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](https://metrics.gitlab.com/), for easier importing.
```plaintext
GET /usage_data/metric_definitions
diff --git a/doc/api/users.md b/doc/api/users.md
index 9b79a249220..925563aeb1f 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -78,13 +78,14 @@ GET /users?external=true
GitLab supports bot users such as the [alert bot](../operations/incident_management/integrations.md)
or the [support bot](../user/project/service_desk.md#support-bot-user).
You can exclude the following types of [internal users](../development/internal_users.md#internal-users)
-from the users' list, with the `exclude_internal=true` parameter,
-([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241144) in GitLab 13.4).
+from the users' list with the `exclude_internal=true` parameter
+([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241144) in GitLab 13.4):
- Alert bot
- Support bot
-However, this action does not exclude [project bot users](../user/project/settings/project_access_tokens.md#project-bot-users).
+However, this action does not exclude [bot users for projects](../user/project/settings/project_access_tokens.md#bot-users-for-projects)
+or [bot users for groups](../user/group/settings/group_access_tokens.md#bot-users-for-groups).
```plaintext
GET /users?exclude_internal=true
@@ -108,7 +109,7 @@ GET /users
| `sort` | string | no | Return users sorted in `asc` or `desc` order. Default is `desc` |
| `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users |
| `without_projects` | boolean | no | Filter users without projects. Default is `false`, which means that all users are returned, with and without projects. |
-| `admins` | boolean | no | Return only admin users. Default is `false` |
+| `admins` | boolean | no | Return only administrators. Default is `false` |
| `saml_provider_id` **(PREMIUM)** | number | no | Return only users created by the specified SAML provider ID. If not included, it returns all users. |
```json
@@ -532,7 +533,7 @@ Parameters:
| Attribute | Type | Required | Description |
|---------------|---------|----------|----------------------------------------------|
| `id` | integer | yes | The ID of a user |
-| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to the ghost user](../user/profile/account/delete_account.md#associated-records) are deleted instead, as well as groups owned solely by this user. |
+| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to Ghost User](../user/profile/account/delete_account.md#associated-records) are deleted instead, as well as groups owned solely by this user. |
## List current user (for normal users)
@@ -696,6 +697,38 @@ Example response:
}
```
+## Set user status
+
+Set the status of the current user.
+
+```plaintext
+PUT /user/status
+```
+
+| Attribute | Type | Required | Description |
+| -------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `emoji` | string | no | The name of the emoji to use as status. If omitted `speech_balloon` is used. Emoji name can be one of the specified names in the [Gemojione index](https://github.com/bonusly/gemojione/blob/master/config/index.json). |
+| `message` | string | no | The message to set as a status. It can also contain emoji codes. |
+| `clear_status_after` | string | no | Automatically clean up the status after a given time interval, allowed values: `30_minutes`, `3_hours`, `8_hours`, `1_day`, `3_days`, `7_days`, `30_days`
+
+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"
+```
+
+Example responses
+
+```json
+{
+ "emoji":"coffee",
+ "message":"I crave coffee",
+ "message_html": "I crave coffee",
+ "clear_status_at":"2021-02-15T10:49:01.311Z"
+}
+```
+
## Get user preferences
Get a list of currently authenticated user's preferences.
@@ -743,38 +776,6 @@ Parameters:
| `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
-
-Set the status of the current user.
-
-```plaintext
-PUT /user/status
-```
-
-| Attribute | Type | Required | Description |
-| -------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `emoji` | string | no | The name of the emoji to use as status. If omitted `speech_balloon` is used. Emoji name can be one of the specified names in the [Gemojione index](https://github.com/bonusly/gemojione/blob/master/config/index.json). |
-| `message` | string | no | The message to set as a status. It can also contain emoji codes. |
-| `clear_status_after` | string | no | Automatically clean up the status after a given time interval, allowed values: `30_minutes`, `3_hours`, `8_hours`, `1_day`, `3_days`, `7_days`, `30_days`
-
-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"
-```
-
-Example responses
-
-```json
-{
- "emoji":"coffee",
- "message":"I crave coffee",
- "message_html": "I crave coffee",
- "clear_status_at":"2021-02-15T10:49:01.311Z"
-}
-```
-
## User Follow
### Follow and unfollow users
@@ -1545,7 +1546,7 @@ Please refer to the [Events API documentation](events.md#get-user-contribution-e
## Get all impersonation tokens of a user
-> Requires administrator permissions.
+Requires administrator access.
It retrieves every impersonation token of the user. Use the pagination
parameters `page` and `per_page` to restrict the list of impersonation tokens.
@@ -1719,8 +1720,8 @@ Example response:
## Create an impersonation token
-> Requires administrator permissions.
-> Token values are returned once. Make sure you save it - you can't access it again.
+Requires administrator access. Token values are returned once. Make sure you save it because you can't access
+it again.
It creates a new impersonation token. Only administrators can do this.
You are only able to create impersonation tokens to impersonate the user and perform
@@ -1764,7 +1765,7 @@ Example response:
## Revoke an impersonation token
-> Requires administrator permissions.
+Requires administrator access.
It revokes an impersonation token.
@@ -1837,7 +1838,7 @@ The activities that update the timestamp are:
- Git HTTP/SSH activities (such as clone, push)
- User logging in to GitLab
-- User visiting pages related to Dashboards, Projects, Issues, and Merge Requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8)
+- User visiting pages related to dashboards, projects, issues, and merge requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8)
- User using the API
- User using the GraphQL API
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index da269073905..9c2170e0709 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -1,18 +1,9 @@
---
-stage: Ecosystem
-group: Integrations
-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: 'https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md'
+remove_date: '2023-01-31'
---
-# API V3 to API V4
+This document was moved to [another location](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md).
-WARNING:
-The GitLab API v3 was [removed](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819) in GitLab 11.0.
-
-For information about the current version of the GitLab API, read the [API documentation](index.md).
-
-## Related topics
-
-- [GitLab v3 API documentation](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-16-stable/doc/api/index.md)
-- [Migration guide](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md) from
- v3 to v4
+<!-- This redirect file can be deleted after <2023-01-31>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/visual_review_discussions.md b/doc/api/visual_review_discussions.md
index 8457f63fd38..7f91b829061 100644
--- a/doc/api/visual_review_discussions.md
+++ b/doc/api/visual_review_discussions.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, api
---
# Visual Review discussions API **(PREMIUM)**
@@ -10,7 +9,7 @@ type: reference, api
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18710) in GitLab 12.5.
> - [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
-Visual Review discussions are notes on Merge Requests sent as
+Visual Review discussions are notes on merge requests sent as
feedback from [Visual Reviews](../ci/review_apps/index.md#visual-reviews).
## Create new merge request thread
diff --git a/doc/architecture/blueprints/ci_data_decay/index.md b/doc/architecture/blueprints/ci_data_decay/index.md
index 155c781b04a..cbd9f5dea7a 100644
--- a/doc/architecture/blueprints/ci_data_decay/index.md
+++ b/doc/architecture/blueprints/ci_data_decay/index.md
@@ -74,13 +74,13 @@ we might want to follow these three tracks described below.
<!-- markdownlint-disable MD029 -->
-1. Partition builds queuing tables
-2. Archive CI/CD data into partitioned database schema
-3. Migrate archived builds metadata out of primary database
+1. Partition CI/CD builds queuing database tables
+2. Partition CI/CD pipelines database tables
+3. Reduce the rate of builds metadata table growth
<!-- markdownlint-enable MD029 -->
-### Migrate archived builds metadata out of primary database
+### Reduce the rate of builds metadata table growth
Once a build (or a pipeline) gets archived, it is no longer possible to resume
pipeline processing in such pipeline. It means that all the metadata, we store
@@ -98,15 +98,16 @@ be able to use de-duplication of metadata entries and other normalization
strategies to consume less storage while retaining ability to query this
dataset. Technical evaluation will be required to find the best solution here.
-Epic: [Migrate archived builds metadata out of primary database](https://gitlab.com/groups/gitlab-org/-/epics/7216).
+Epic: [Reduce the rate of builds metadata table growth](https://gitlab.com/groups/gitlab-org/-/epics/7434).
-### Archive CI/CD data into partitioned database schema
+### Partition CI/CD pipelines database tables
-After we move CI/CD metadata to a different store, the problem of having
-billions of rows describing pipelines, builds and artifacts, remains. We still
-need to keep reference to the metadata we store in object storage and we still
-do need to be able to retrieve this information reliably in bulk (or search
-through it).
+After we move CI/CD metadata to a different store, or reduce the rate of
+metadata growth in a different way, the problem of having billions of rows
+describing pipelines, builds and artifacts, remains. We still need to keep
+reference to the metadata we might store in object storage and we still do need
+to be able to retrieve this information reliably in bulk (or search through
+it).
It means that by moving data to object storage we might not be able to reduce
the number of rows in CI/CD tables. Moving data to object storage should help
@@ -132,9 +133,9 @@ partitioning on the application level.
Partitioning rarely accessed data should also follow the policy defined for
builds archival, to make it consistent and reliable.
-Epic: [Archive CI/CD data into partitioned database schema](https://gitlab.com/groups/gitlab-org/-/epics/5417).
+Epic: [Partition CI/CD pipelines database tables](https://gitlab.com/groups/gitlab-org/-/epics/5417).
-### Partition builds queuing tables
+### Partition CI/CD builds queuing database tables
While working on the [CI/CD Scale](../ci_scale/index.md) blueprint, we have
introduced a [new architecture for queuing CI/CD builds](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908)
@@ -156,7 +157,7 @@ for builds archival. Instead we should leverage a long-standing policy saying
that builds created more 24 hours ago need to be removed from the queue. This
business rule is present in the product since the inception of GitLab CI.
-Epic: [Partition builds queuing tables](https://gitlab.com/gitlab-org/gitlab/-/issues/347027).
+Epic: [Partition CI/CD builds queuing database tables](https://gitlab.com/groups/gitlab-org/-/epics/7438).
## Principles
@@ -215,9 +216,9 @@ pipelines data, although a user provided partition identifier may be required.
All three tracks can be worked on in parallel:
-1. [Migrate archived build metadata to object storage](https://gitlab.com/groups/gitlab-org/-/epics/7216).
-1. [Partition CI/CD data that have been archived](https://gitlab.com/groups/gitlab-org/-/epics/5417).
-1. [Partition CI/CD queuing tables using list partitioning](https://gitlab.com/gitlab-org/gitlab/-/issues/347027)
+1. [Reduce the rate of builds metadata table growth](https://gitlab.com/groups/gitlab-org/-/epics/7434).
+1. [Partition CI/CD pipelines database tables](https://gitlab.com/groups/gitlab-org/-/epics/5417).
+1. [Partition CI/CD queuing tables using list partitioning](https://gitlab.com/groups/gitlab-org/-/epics/7438)
## Status
diff --git a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
index 345160dc77f..6040ac1e50f 100644
--- a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
+++ b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
@@ -131,7 +131,7 @@ epic.
The initial iteration will provide a framework to house features under `Namespaces`. Stage groups will eventually need to migrate their own features and functionality over to `Namespaces`. This may impact these features in unexpected ways. Therefore, to minimize UX debt and maintain product consistency, stage groups will have to consider a number of factors when migrating their features over to `Namespaces`:
-1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [Merge Requests](https://design.gitlab.com/objects/merge-request)).
+1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [merge requests](https://design.gitlab.com/objects/merge-request)).
1. **Merge conflicts**: What inconsistencies are there across project, group, and admin levels? How might these be addressed? For an example of how we rationalized this for labels, please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338820).
1. **Inheritance & information flow**: How is information inherited across our container hierarchy currently? How might this be impacted if complying with the new [inheritance behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/343316) framework?
1. **Settings**: Where can settings for this feature be found currently? How will these be impacted by `Namespaces`?
diff --git a/doc/architecture/blueprints/database_testing/index.md b/doc/architecture/blueprints/database_testing/index.md
index 4676caab85d..8c0cb550d61 100644
--- a/doc/architecture/blueprints/database_testing/index.md
+++ b/doc/architecture/blueprints/database_testing/index.md
@@ -100,7 +100,7 @@ The short-term goal is detailed in [this epic](https://gitlab.com/groups/gitlab-
### Mid-term - Improved feedback, query testing and background migration testing
-Mid-term, we plan to expand the level of detail the testing pipeline reports back to the Merge Request and expand its scope to cover query testing, too. By doing so, we use our experience from database code reviews and using thin-clone technology and bring this back closer to the GitLab workflow. Instead of reaching out to different tools (`postgres.ai`, `joe`, Slack, plan visualizations, and so on) we bring this back to GitLab and working directly on the Merge Request.
+Mid-term, we plan to expand the level of detail the testing pipeline reports back to the merge requet and expand its scope to cover query testing, too. By doing so, we use our experience from database code reviews and using thin-clone technology and bring this back closer to the GitLab workflow. Instead of reaching out to different tools (`postgres.ai`, `joe`, Slack, plan visualizations, and so on) we bring this back to GitLab and working directly on the merge request.
Secondly, we plan to cover background migrations testing, too. These are typically data migrations that are scheduled to run over a long period of time. The success of both the scheduling phase and the job execution phase typically depends a lot on data distribution - which only surfaces when running these migrations on actual production data. In order to become confident about a background migration, we plan to provide the following feedback:
@@ -109,7 +109,7 @@ Secondly, we plan to cover background migrations testing, too. These are typical
### Long-term - incorporate into GitLab product
-There are opportunities to discuss for extracting features from this into GitLab itself. For example, annotating the Merge Request with query examples and attaching feedback gathered from the testing run can become a first-class citizen instead of using Merge Request description and comments for it. We plan to evaluate those ideas as we see those being used in earlier phases and bring our experience back into the product.
+There are opportunities to discuss for extracting features from this into GitLab itself. For example, annotating the merge request with query examples and attaching feedback gathered from the testing run can become a first-class citizen instead of using merge request description and comments for it. We plan to evaluate those ideas as we see those being used in earlier phases and bring our experience back into the product.
## An alternative discussed: Anonymization
diff --git a/doc/architecture/blueprints/object_storage/index.md b/doc/architecture/blueprints/object_storage/index.md
index a79374d60bd..7864c951eca 100644
--- a/doc/architecture/blueprints/object_storage/index.md
+++ b/doc/architecture/blueprints/object_storage/index.md
@@ -89,20 +89,23 @@ replaced by a mock implementation. Furthermore, the presence of a
shared disk, both in CI and in local development, often hides broken
implementations until we deploy on an HA environment.
-Shipping MinIO as part of the product will reduce the differences
+One consideration we can take is to investigate shipping MinIO as part of the product. This could reduce the differences
between a cloud and a local installation, standardizing our file
storage on a single technology.
-The removal of local disk operations will reduce the complexity of
+The removal of local disk operations would reduce the complexity of
development as well as mitigate several security attack vectors as
we no longer write user-provided data on the local storage.
-It will also reduce human errors as we will always run a local object
+It would also reduce human errors as we will always run a local object
storage in development mode and any local file disk access should
raise a red flag during the merge request review.
This effort is described in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/6099).
+Before considering any specific third-party technology, the
+open source software licensing implications should be considered. As of 23 April 2021, [MinIO is subject to the AGPL v3 license](https://github.com/minio/minio/commit/069432566fcfac1f1053677cc925ddafd750730a). GitLab Legal must be consulted before any decision is taken to ship MinIO as proposed in this blueprint.
+
### Enable direct upload by default on every upload
Because every group of features requires its own bucket, we don't have
diff --git a/doc/architecture/blueprints/runner_scaling/index.md b/doc/architecture/blueprints/runner_scaling/index.md
index 8e47b5fda8c..174fe191cc7 100644
--- a/doc/architecture/blueprints/runner_scaling/index.md
+++ b/doc/architecture/blueprints/runner_scaling/index.md
@@ -44,7 +44,7 @@ and the documentation for it has been removed from the official page. This
means that the original reason to use Docker Machine is no longer valid too.
To keep supporting our customers and the wider community we need to design a
-new mechanism for GitLab Runner autoscaling. It not only needs to support
+new mechanism for GitLab Runner auto-scaling. It not only needs to support
auto-scaling, but it also needs to do that in the way to enable us to build on
top of it to improve efficiency, reliability and availability.
@@ -144,7 +144,7 @@ on a single machine bring. It is difficult to predict that, so ideally we
should build a PoC that will help us to better understand what we can expect
from this.
-To run this experiement we most likely we will need to build an experimental
+To run this experiment we most likely we will need to build an experimental
plugin, that not only allows us to schedule running multiple builds on a single
machine, but also has a set of comprehensive metrics built into it, to make it
easier to understand how it performs.
@@ -204,6 +204,44 @@ document, define requirements and score the solution accordingly. This will
allow us to choose a solution that will work best for us and the wider
community.
+### Design principles
+
+Our goal is to design a GitLab Runner plugin system interface that is flexible
+and simple for the wider community to consume. As we cannot build plugins for
+all cloud platforms, we want to ensure a low entry barrier for anyone who needs
+to develop a plugin. We want to allow everyone to contribute.
+
+To achieve this goal, we will follow a few critical design principles. These
+principles will guide our development process for the new plugin system
+abstraction.
+
+#### General high-level principles
+
+1. Design the new auto-scaling architecture aiming for having more choices and
+ flexibility in the future, instead of imposing new constraints.
+1. Design the new auto-scaling architecture to experiment with running multiple
+ jobs in parallel, on a single machine.
+1. Design the new provisioning architecture to replace Docker Machine in a way
+ that the wider community can easily build on top of the new abstractions.
+
+#### Principles for the new plugin system
+
+1. Make the entry barrier for writing a new plugin low.
+1. Developing a new plugin should be simple and require only basic knowledge of
+ a programming language and a cloud provider's API.
+1. Strive for a balance between the plugin system's simplicity and flexibility.
+ These are not mutually exclusive.
+1. Abstract away as many technical details as possible but do not hide them completely.
+1. Build an abstraction that serves our community well but allows us to ship it quickly.
+1. Invest in a flexible solution, avoid one-way-door decisions, foster iteration.
+1. When in doubts err on the side of making things more simple for the wider community.
+
+#### The most important technical details
+
+1. Favor gRPC communication between a plugin and GitLab Runner.
+1. Make it possible to version communication interface and support many versions.
+1. Make Go a primary language for writing plugins but accept other languages too.
+
## Status
Status: RFC.
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index 698b467a813..c785e2f29ea 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -43,7 +43,7 @@ job completes:
[Slack API](https://api.slack.com/) to send data to the channel.
To use the `run` command, you must have at least the
-[Developer role](../../user/permissions.md#project-members-permissions).
+Developer role.
If a job shouldn't be able to be triggered from chat, you can set the job to `except: [chat]`.
## Best practices for ChatOps CI jobs
@@ -55,7 +55,7 @@ functions available. Consider these best practices when creating ChatOps jobs:
of the standard CI pipeline.
- If the job is set to `when: manual`, ChatOps creates the pipeline, but the job waits to be started.
- ChatOps provides limited support for access control. If the user triggering the
- slash command has at least the [Developer role](../../user/permissions.md#project-members-permissions)
+ slash command has at least the Developer role
in the project, the job runs. The job itself can use existing
[CI/CD variables](../variables/index.md#predefined-cicd-variables) like
`GITLAB_USER_ID` to perform additional rights validation, but
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 4e4b7420697..a906f213626 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -16,7 +16,7 @@ Watch a video on [Using GitLab CI/CD pipelines with GitHub repositories](https:/
NOTE:
Because of [GitHub limitations](https://gitlab.com/gitlab-org/gitlab/-/issues/9147),
-[GitHub OAuth](../../integration/github.md#enabling-github-oauth)
+[GitHub OAuth](../../integration/github.md#enable-github-oauth-in-gitlab)
cannot be used to authenticate with GitHub as an external CI/CD repository.
## Connect with Personal Access Token
diff --git a/doc/ci/cloud_services/aws/index.md b/doc/ci/cloud_services/aws/index.md
index f09b23db2c5..aa38562c866 100644
--- a/doc/ci/cloud_services/aws/index.md
+++ b/doc/ci/cloud_services/aws/index.md
@@ -1,6 +1,6 @@
---
-stage: Configure
-group: Configure
+stage: Verify
+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
---
@@ -30,7 +30,7 @@ Include the following information:
After you create the identity provider, configure a [web identity role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html) with conditions for limiting access to GitLab resources. Temporary credentials are obtained using [AWS Security Token Service](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html), so set the `Action` to [sts:AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html).
-For the full list of supported filtering types, see [Connect to cloud services](../index.md).
+For the full list of supported filtering types, see [Connect to cloud services](../index.md#configure-a-conditional-role-with-oidc-claims).
```json
{
diff --git a/doc/ci/cloud_services/google_cloud/index.md b/doc/ci/cloud_services/google_cloud/index.md
new file mode 100644
index 00000000000..14928f91816
--- /dev/null
+++ b/doc/ci/cloud_services/google_cloud/index.md
@@ -0,0 +1,182 @@
+---
+stage: Verify
+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
+---
+
+# Configure OpenID Connect with GCP Workload Identity Federation
+
+WARNING:
+The `CI_JOB_JWT_V2` variable is under development [(alpha)](../../../policy/alpha-beta-support.md#alpha-features) and is not yet suitable for production use.
+
+This tutorial demonstrates authenticating to Google Cloud from a GitLab CI/CD job
+using a JSON Web Token (JWT) token and Workload Identity Federation. This configuration
+generates on-demand, short-lived credentials without needing to store any secrets.
+
+To get started, configure OpenID Connect (OIDC) for identity federation between GitLab
+and Google Cloud. For more information on using OIDC with GitLab, read
+[Connect to cloud services](../index.md).
+
+This tutorial assumes you have a Google Cloud account and a Google Cloud project.
+Your account must have at least the **Workload Identity Pool Admin** permission
+on the Google Cloud project.
+
+To complete this tutorial:
+
+1. [Create the Google Cloud Workload Identity Pool](#create-the-google-cloud-workload-identity-pool).
+1. [Create a Workload Identity Provider](#create-a-workload-identity-provider).
+1. [Grant permissions for service account impersonation](#grant-permissions-for-service-account-impersonation).
+1. [Retrieve a temporary credential](#retrieve-a-temporary-credential).
+
+## Create the Google Cloud Workload Identity Pool
+
+[Create a new Google Cloud Workload Identity Pool](https://cloud.google.com/iam/docs/configuring-workload-identity-federation#oidc) with the following options:
+
+- **Name**: Human-friendly name for the Workload Identity Pool, such as `GitLab`.
+- **Pool ID**: Unique ID in the Google Cloud project for the Workload Identity Pool,
+ such as `gitlab`. This value is used to refer to the pool. and appears in URLs.
+- **Description**: Optional. A description of the pool.
+- **Enabled Pool**: Ensure this option is `true`.
+
+We recommend creating a single _pool_ per GitLab installation per Google Cloud project. If you have multiple GitLab repositories and CI/CD jobs on the same GitLab instance, they can authenticate using different _providers_ against the same _pool_.
+
+## Create a Workload Identity Provider
+
+[Create a new Google Cloud Workload Identity Provider](https://cloud.google.com/iam/docs/configuring-workload-identity-federation#create_the_workload_identity_pool_and_provider)
+inside the Workload Identity Pool created in the previous step, using the following options:
+
+- **Provider type**: OpenID Connect (OIDC).
+- **Provider name**: Human-friendly name for the Workload Identity Provider,
+ such as `gitlab/gitlab`.
+- **Provider ID**: Unique ID in the pool for the Workload Identity Provider,
+ such as `gitlab-gitlab`. This value is used to refer to the provider, and appears in URLs.
+- **Issuer (URL)**: The address of your GitLab instance, such as `https://gitlab.com` or
+ `https://gitlab.example.com`.
+ - The address must use the `https://` protocol.
+ - The address must end in a trailing slash.
+- **Audiences**: Manually set the allowed audiences list to the address of your
+ GitLab instance, such as `https://gitlab.com` or `https://gitlab.example.com`.
+ - The address must use the `https://` protocol.
+ - The address must not end in a trailing slash.
+- **Provider attributes mapping**: Create the following mappings, where `attribute.X` is the
+ name of the attribute you would like to be present on Google's claims, and `assertion.X`
+ is the value to extract from the [GitLab claim](../index.md#how-it-works):
+
+ | Attribute (on Google) | Assertion (from GitLab) |
+ | --- | --- |
+ | `google.subject` | `assertion.sub` |
+ | `attribute.X` | `assertion.X` |
+
+ You can also [build complex attributes](https://cloud.google.com/iam/help/workload-identity/attribute-mapping)
+ using Common Expression Language (CEL).
+
+ You must map every attribute that you want to use for permission granting. For example, if you want to map permissions in the next step based on the user's email address, you must map `attribute.user_email` to `assertion.user_email`.
+
+## Grant permissions for Service Account impersonation
+
+Creating the Workload Identity Pool and Workload Identity Provider defines the _authentication_
+into Google Cloud. At this point, you can authenticate from GitLab CI/CD job into Google Cloud.
+However, you have no permissions on Google Cloud (_authorization_).
+
+To grant your GitLab CI/CD job permissions on Google Cloud, you must:
+
+1. [Create a Google Cloud Service Account](https://www.google.com/search?q=google+cloud+create+service+account).
+ You can use whatever name and ID you prefer.
+1. [Grant IAM permissions](https://cloud.google.com/iam/docs/granting-changing-revoking-access) to your
+ service account on Google Cloud resources. These permissions vary significantly based on
+ your use case. In general, grant this service account the permissions on your Google Cloud
+ project and resources you want your GitLab CI/CD job to be able to use. For example, if you needed to upload a file to a Google Cloud Storage bucket in your GitLab CI/CD job, you would grant this Service Account the `roles/storage.objectCreator` role on your Cloud Storage bucket.
+1. [Grant the external identity permissions](https://cloud.google.com/iam/docs/using-workload-identity-federation#impersonate)
+ to impersonate that Service Account. This step enables a GitLab CI/CD job to _authorize_
+ to Google Cloud, via Service Account impersonation. This step grants an IAM permission
+ _on the Service Account itself_, giving the external identity permissions to act as that
+ service account. External identities are expressed using the `principalSet://` protocol.
+
+Much like the previous step, this step depends heavily on your desired configuration.
+For example, to allow a GitLab CI/CD job to impersonate a Service Account named
+`my-service-account` if the GitLab CI/CD job was initiated by a GitLab user with the
+username `chris`, you would grant the `roles/iam.workloadIdentityUser` IAM role to the
+external identity on `my-service-account`. The external identity takes the format:
+
+```plaintext
+principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.user_login/chris
+```
+
+where `PROJECT_NUMBER` is your Google Cloud project number, and `POOL_ID` is the
+ID (not name) of the Workload Identity Pool created in the first section.
+
+This configuration also assumes you added `user_login` as an attribute mapped from
+the assertion in the previous section.
+
+## Retrieve a temporary credential
+
+After you configure the OIDC and role, the GitLab CI/CD job can retrieve a temporary credential from the
+[Google Cloud Security Token Service (STS)](https://cloud.google.com/iam/docs/reference/sts/rest).
+
+```shell
+PAYLOAD="$(cat <<EOF
+{
+ "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
+ "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
+ "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
+ "scope": "https://www.googleapis.com/auth/cloud-platform",
+ "subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
+ "subjectToken": "${CI_JOB_JWT_V2}"
+}
+EOF
+)"
+```
+
+```shell
+FEDERATED_TOKEN="$(curl --fail "https://sts.googleapis.com/v1/token" \
+ --header "Accept: application/json" \
+ --header "Content-Type: application/json" \
+ --data "${PAYLOAD}" \
+ | jq -r '.access_token'
+)"
+```
+
+Where:
+
+- `PROJECT_NUMBER` is your Google Cloud project number (not name).
+- `POOL_ID` is the ID of the Workload Identity Pool created in the first section.
+- `PROVIDER_ID` is the ID of the Workload Identity Provider created in the second section.
+- `CI_JOB_JWT_V2` is injected into the CI/CD job by GitLab. For more information about
+ this variable, read [Connect to cloud services](../index.md).
+
+You can then use the resulting federated token to impersonate the service account created
+in the previous section:
+
+```shell
+ACCESS_TOKEN="$(curl --fail "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken" \
+ --header "Accept: application/json" \
+ --header "Content-Type: application/json" \
+ --header "Authorization: Bearer FEDERATED_TOKEN" \
+ --data '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}' \
+ | jq -r '.accessToken'
+)"
+```
+
+Where:
+
+- `SERVICE_ACCOUNT_EMAIL` is the full email address of the service account to impersonate,
+ created in the previous section.
+- `FEDERATED_TOKEN` is the federated token retrieved from the previous step.
+
+The result is a Google Cloud OAuth 2.0 access token, which you can use to authenticate to
+most Google Cloud APIs and services when used as a bearer token. You can also pass this
+value to the `gcloud` CLI by setting the environment variable `CLOUDSDK_AUTH_ACCESS_TOKEN`.
+
+## Working example
+
+Review this
+[reference project](https://gitlab.com/guided-explorations/gcp/configure-openid-connect-in-gcp)
+for provisioning OIDC in GCP using Terraform and a sample script to retrieve temporary credentials.
+
+## Troubleshooting
+
+- When debugging `curl` responses, install the latest version of curl. Use `--fail-with-body`
+ instead of `-f`. This command prints the entire body, which can contain helpful error messages.
+
+- Review Google Cloud's documentation for
+ [Troubleshooting Workload Identity Federation](https://cloud.google.com/iam/docs/troubleshooting-workload-identity-federation).
diff --git a/doc/ci/cloud_services/index.md b/doc/ci/cloud_services/index.md
index 73e726ea8a9..a80231a04c2 100644
--- a/doc/ci/cloud_services/index.md
+++ b/doc/ci/cloud_services/index.md
@@ -1,6 +1,6 @@
---
-stage: Configure
-group: Configure
+stage: Verify
+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
---
@@ -19,7 +19,7 @@ GitLab CI/CD supports [OpenID Connect (OIDC)](https://openid.net/connect/faq/) t
The original implementation of `CI_JOB_JWT` supports [HashiCorp Vault integration](../examples/authenticating-with-hashicorp-vault/). The updated implementation of `CI_JOB_JWT_V2` supports additional cloud providers with OIDC including AWS, GCP, and Vault.
WARNING:
-The `CI_JOB_JWT_V2` variable is under development [(alpha)](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) and is not yet suitable for production use.
+The `CI_JOB_JWT_V2` variable is under development [(alpha)](../../policy/alpha-beta-support.md#alpha-features) and is not yet suitable for production use.
## Use cases
@@ -99,9 +99,9 @@ sequenceDiagram
Note right of Cloud: Decode & verify JWT with public key (https://gitlab/-/jwks)
Note right of Cloud: Validate audience defined in OIDC
Note right of Cloud: Validate conditional (sub, aud) role
- Note right of Cloud: Generate credential or fetch secret
+ Note right of Cloud: Generate credential or fetch secret
Cloud->>GitLab: Return temporary credential
- Note left of GitLab: Perform operation
+ Note left of GitLab: Perform operation
```
@@ -131,3 +131,4 @@ To configure the trust between GitLab and OIDC, you must create a conditional ro
To connect with your cloud provider, see the following tutorials:
- [Configure OpenID Connect in AWS](aws/index.md)
+- [Configure OpenID Connect in Google Cloud](google_cloud/index.md)
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 5bd9293924d..7edff334134 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -450,3 +450,26 @@ To configure access for `<aws_account_id>.dkr.ecr.<region>.amazonaws.com`, follo
You can add configuration for as many registries as you want, adding more
registries to the `"credHelpers"` hash.
+
+### Use checksum to keep your image secure
+
+We recommend using the image checksum in your job definition in your `.gitlab-ci.yml` file to verify the integrity of the image. A failed image integrity verification will prevent you from using a modified container.
+
+To use the image checksum you have to append the checksum at the end:
+
+```yaml
+image: ruby:2.6.8@sha256:d1dbaf9665fe8b2175198e49438092fdbcf4d8934200942b94425301b17853c7
+```
+
+To get the image checksum, on the image `TAG` tab, view the `DIGEST` column.
+For example, view the [Ruby image](https://hub.docker.com/_/ruby?tab=tags).
+The checksum is a random string, like `6155f0235e95`.
+
+You can also get the checksum of any image on your system with the command `docker images --digests`:
+
+```shell
+⯠docker images --digests
+REPOSITORY TAG DIGEST (...)
+gitlab/gitlab-ee latest sha256:723aa6edd8f122d50cae490b1743a616d54d4a910db892314d68470cc39dfb24 (...)
+gitlab/gitlab-runner latest sha256:4a18a80f5be5df44cb7575f6b89d1fdda343297c6fd666c015c0e778b276e726 (...)
+```
diff --git a/doc/ci/environments/deployment_approvals.md b/doc/ci/environments/deployment_approvals.md
index d60e5704877..e320118c191 100644
--- a/doc/ci/environments/deployment_approvals.md
+++ b/doc/ci/environments/deployment_approvals.md
@@ -7,7 +7,8 @@ description: Require approvals prior to deploying to a Protected Environment
# Deployment approvals **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 with a flag named `deployment_approvals`. Disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 with a flag named `deployment_approvals`. Disabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/347342) in GitLab 14.8.
WARNING:
This feature is in an alpha stage and subject to change without prior notice.
@@ -49,12 +50,19 @@ Example:
name: ${CI_JOB_NAME}
```
-### Require approvals for a protected environment
+### Require approvals for a protected environment
NOTE:
-At this time, only API-based configuration is available. UI-based configuration is planned for the near future. See [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/344675).
+At this time, it is not possible to require approvals for an existing protected environment. The workaround is to unprotect the environment and configure approvals when re-protecting the environment.
-Use the [Protected Environments API](../../api/protected_environments.md#protect-repository-environments) to create an environment with `required_approval_count` > 0. After this is set, all jobs deploying to this environment automatically go into a blocked state and wait for approvals before running.
+There are two ways to configure approvals for a protected environment:
+
+1. Using the [UI](protected_environments.md#protecting-environments)
+ 1. Set the **Required approvals** field to 1 or more.
+1. Using the [REST API](../../api/protected_environments.md#protect-repository-environments)
+ 2. Set the `required_approval_count` field to 1 or more.
+
+After this is configured, all jobs deploying to this environment automatically go into a blocked state and wait for approvals before running. Ensure that the number of required approvals is less than the number of users allowed to deploy.
Example:
@@ -65,8 +73,9 @@ curl --header 'Content-Type: application/json' --request POST \
"https://gitlab.example.com/api/v4/projects/22034114/protected_environments"
```
+NOTE:
To protect, update, or unprotect an environment, you must have at least the
-[Maintainer role](../../user/permissions.md).
+Maintainer role.
## Approve or reject a deployment
@@ -75,7 +84,7 @@ This functionality is currently only available through the API. UI is planned fo
A blocked deployment is enqueued as soon as it receives the required number of approvals. A single rejection causes the deployment to fail. The creator of a deployment cannot approve it, even if they have permission to deploy.
-Using the [Deployments API](../../api/deployments.md#approve-or-reject-a-blocked-deployment), users who are allowed to deploy to the protected environment can approve or reject a blocked deployment.
+Using the [Deployments API](../../api/deployments.md#approve-or-reject-a-blocked-deployment), users who are allowed to deploy to the protected environment can approve or reject a blocked deployment.
Example:
@@ -95,7 +104,11 @@ curl --data "status=approved" \
#### Using the API
-Use the [Deployments API](../../api/deployments.md) to see deployments. The `status` field indicates if a deployment is blocked.
+Use the [Deployments API](../../api/deployments.md) to see deployments.
+
+- The `status` field indicates if a deployment is blocked.
+- The `pending_approval_count` field indicates how many approvals are remaining to run a deployment.
+- The `approvals` field contains the deployment's approvals.
## Related features
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 55c3c83338d..0e73dc4f7cd 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -26,7 +26,7 @@ If you are using a continuous deployment workflow and want to ensure that concur
## Restrict write access to a critical environment
By default, environments can be modified by any team member that has at least the
-[Developer role](../../user/permissions.md#project-members-permissions).
+Developer role.
If you want to restrict write access to a critical environment (for example a `production` environment),
you can set up [protected environments](protected_environments.md).
@@ -93,7 +93,7 @@ If you want to prevent deployments for a particular period, for example during a
vacation period when most employees are out, you can set up a [Deploy Freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze).
During a deploy freeze period, no deployment can be executed. This is helpful to
ensure that deployments do not happen unexpectedly.
-
+
## Setting appropriate roles to your project
GitLab supports several different roles that can be assigned to your project members. See
@@ -119,7 +119,7 @@ The other pipelines don't get the protected variable. You can also
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/configure_runners.md#prevent-runners-from-revealing-sensitive-information).
-This prevents other users with the [Maintainer role](../../user/permissions.md) from reading the secrets and makes sure
+This prevents other users with the Maintainer role from reading the secrets and makes sure
that the runner only runs on protected branches.
For more information, see [pipeline security](../pipelines/index.md#pipeline-security-on-protected-branches).
diff --git a/doc/ci/environments/img/environments_open_live_environment_v14_8.png b/doc/ci/environments/img/environments_open_live_environment_v14_8.png
new file mode 100644
index 00000000000..daf531c83c4
--- /dev/null
+++ b/doc/ci/environments/img/environments_open_live_environment_v14_8.png
Binary files differ
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 794e4320fc6..63bdd279927 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -27,7 +27,7 @@ You can even access a [web terminal](#web-terminals-deprecated) for your environ
Prerequisites:
-- You must have at least the Reporter [role](../../user/permissions.md#project-members-permissions).
+- You must have at least the Reporter role.
To view a list of environments and deployments:
@@ -308,10 +308,18 @@ Note the following:
- If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update
the environment URL.
- If the script that runs in `stop_review` exists only in your repository and therefore can't use
- `GIT_STRATEGY: none`, configure [pipelines for merge requests](../../ci/pipelines/merge_request_pipelines.md)
+ `GIT_STRATEGY: none`, configure [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md)
for these jobs. This ensures that runners can fetch the repository even after a feature branch is
deleted. For more information, see [Ref Specs for Runners](../pipelines/index.md#ref-specs-for-runners).
+NOTE:
+For Windows runners, using `echo` to write to `.env` files may fail. Using the PowerShell `Add-Content`command
+will help in such cases. For example:
+
+```powershell
+Add-Content -Path deploy.env -Value "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL"
+```
+
## Track newly included merge requests per deployment
GitLab can track newly included merge requests per deployment.
@@ -372,7 +380,7 @@ places in GitLab:
- In a merge request as a link:
![Environment URL in merge request](../img/environments_mr_review_app.png)
- In the Environments view as a button:
- ![Environment URL in environments](../img/environments_available_13_10.png)
+ ![Open live environment from environments view](img/environments_open_live_environment_v14_8.png)
- In the Deployments view as a button:
![Environment URL in deployments](../img/deployments_view.png)
@@ -440,7 +448,7 @@ the `stop_review` job might not be included in all pipelines that include the
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](../pipelines/merge_request_pipelines.md),
+If you can't use [merge request pipelines](../pipelines/merge_request_pipelines.md),
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.
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 78db2345de4..c7d1653aace 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -20,7 +20,7 @@ NOTE:
GitLab administrators can use all environments, including protected environments.
To protect, update, or unprotect an environment, you need to have at least the
-[Maintainer role](../../user/permissions.md).
+Maintainer role.
## Protecting environments
@@ -38,6 +38,9 @@ To protect an environment:
- You can select groups that are already associated with the project only.
- Users must have at least the Developer role to appear in
the **Allowed to deploy** list.
+1. In the **Required approvals** list, select the number of approvals required to deploy to this environment.
+ - Ensure that this number is less than the number of users allowed to deploy.
+ - See [Deployment Approvals](deployment_approvals.md) for more information about this feature.
1. Select **Protect**.
The protected environment now appears in the list of protected environments.
@@ -94,7 +97,7 @@ 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}]}' \
+ curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}], "required_approval_count": 0}' \
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
```
@@ -103,12 +106,12 @@ The group now has access and can be seen in the UI.
## Environment access by group membership
A user may be granted access to protected environments as part of [group membership](../../user/group/index.md). Users
-with the Reporter [role](../../user/permissions.md) can only be granted access to protected environments with this
+with the Reporter role can only be granted access to protected environments with this
method.
## Deployment branch access
-Users with the [Developer role](../../user/permissions.md) can be granted
+Users with the Developer role can be granted
access to a protected environment through any of these methods:
- As an individual contributor, through a role.
@@ -125,7 +128,7 @@ they have the following privileges:
Users granted access to a protected environment, but not push or merge access
to the branch deployed to it, are only granted access to deploy the environment. An individual in a
-group with the Reporter [role](../../user/permissions.md), or in groups added to the project with the Reporter
+group with the Reporter role, or in groups added to the project with the Reporter
role, appears in the dropdown menu for deployment-only access.
To add deployment-only access:
@@ -136,7 +139,7 @@ To add deployment-only access:
1. Follow the steps in [Protecting Environments](#protecting-environments).
Note that deployment-only access is the only possible access level for groups with the Reporter
-[role](../../user/permissions.md).
+role.
## Modifying and unprotecting environments
@@ -194,14 +197,14 @@ and are protected at the same time.
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 given the [Maintainer role](../../user/permissions.md)
+might gain privileged access to a higher environment when they are given the Maintainer role
for 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 given at least the [Maintainer role](../../user/permissions.md)
+- Operators should be given at least the Maintainer role
for the top-level group. They can maintain CI/CD configurations for
the higher environments (such as production) in the group-level settings page,
which includes group-level protected environments,
@@ -210,8 +213,8 @@ configured:
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 given no more than the [Developer role](../../user/permissions.md)
- for the top-level group, or explicitly given the [Maintainer role](../../user/permissions.md) for a child project
+- Developers should be given no more than the Developer role
+ for the top-level group, or explicitly given the Maintainer role for a child project
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.
@@ -224,7 +227,7 @@ configured:
environment configurations exist, to run a deployment job, the user must be allowed in **both**
rulesets.
- In a project or a subgroup of the top-level group, developers can be
- safely assigned the [Maintainer role](../../user/permissions.md) to tune their lower environments (such
+ safely assigned the Maintainer role to tune their lower environments (such
as `testing`).
Having this configuration in place:
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index aed45951239..edc58684057 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -1,6 +1,6 @@
---
-stage: Release
-group: Release
+stage: Verify
+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: tutorial
---
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/index.md b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
index 9881c9657bc..4d247a4ff74 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
author: Vincent Tunru
author_gitlab: Vinnl
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 be33e62b75c..6dbec0dfc8b 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -378,7 +378,7 @@ Now, we would need to deploy our app by running `envoy run deploy`, but it won't
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:
+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
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index cdc75fd2bec..23055514839 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -60,6 +60,15 @@ To make submodules work correctly in CI/CD jobs:
GIT_SUBMODULE_STRATEGY: recursive
```
+1. You can provide additional flags to control advanced checkout behavior using
+ [`GIT_SUBMODULE_UPDATE_FLAGS`](runners/configure_runners.md#git-submodule-update-flags).
+
+ ```yaml
+ variables:
+ GIT_SUBMODULE_STRATEGY: recursive
+ GIT_SUBMODULE_UPDATE_FLAGS: --jobs 4
+ ```
+
If you use the [`CI_JOB_TOKEN`](jobs/ci_job_token.md) to clone a submodule in a
pipeline job, the user executing the job must be assigned to a role that has
[permission](../user/permissions.md#gitlab-cicd-permissions) to trigger a pipeline
diff --git a/doc/ci/img/ci_lint.png b/doc/ci/img/ci_lint.png
deleted file mode 100644
index fdc3868cdce..00000000000
--- a/doc/ci/img/ci_lint.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/img/ci_lint_dry_run.png b/doc/ci/img/ci_lint_dry_run.png
deleted file mode 100644
index 61d6379f70e..00000000000
--- a/doc/ci/img/ci_lint_dry_run.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/img/environments_available_13_10.png b/doc/ci/img/environments_available_13_10.png
deleted file mode 100644
index 94ffb0032fa..00000000000
--- a/doc/ci/img/environments_available_13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/index.md b/doc/ci/index.md
index c557e9e6f57..d0c2e1986b2 100644
--- a/doc/ci/index.md
+++ b/doc/ci/index.md
@@ -64,7 +64,7 @@ GitLab CI/CD supports numerous configuration options:
| [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/index.md) | Trigger pipelines through the API. |
-| [Pipelines for Merge Requests](pipelines/merge_request_pipelines.md) | Design a pipeline structure for running a pipeline in merge requests. |
+| [Merge request pipelines](pipelines/merge_request_pipelines.md) | Design a pipeline structure for running a pipeline in merge requests. |
| [Integrate with Kubernetes clusters](../user/infrastructure/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
| [Optimize GitLab and GitLab Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repositories. |
| [`.gitlab-ci.yml` full reference](yaml/index.md) | All the attributes you can use with GitLab CI/CD. |
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index 1906d9cdb6c..a62f670cb12 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -23,7 +23,6 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
- [Releases](../../api/releases/index.md).
- [Terraform plan](../../user/infrastructure/index.md).
-The token has the same permissions to access the API as the user that executes the
The token has the same permissions to access the API as the user that caused the
job to run. A user can cause a job to run by pushing a commit, triggering a manual job,
being the owner of a scheduled pipeline, and so on. Therefore, this user must be assigned to
@@ -95,7 +94,7 @@ The job token scope is only for controlling access to private projects.
1. Expand **Token Access**.
1. Toggle **Limit CI_JOB_TOKEN access** to enabled.
1. Optional. Add existing projects to the token's access scope. The user adding a
- project must have the [maintainer role](../../user/permissions.md) in both projects.
+ project must have the Maintainer role in both projects.
There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559) to improve
the feature with more strategic control of the access permissions.
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index 104badb782c..39e14d0d20a 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -95,6 +95,9 @@ You can't use these keywords as job names:
- `variables`
- `cache`
- `include`
+- `true`
+- `false`
+- `nil`
Job names must be 255 characters or less. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342800)
in GitLab 14.5, [with a feature flag](../../administration/feature_flags.md) named `ci_validate_job_length`.
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index a2406a68bb2..6523de0ed1e 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -220,7 +220,7 @@ check the value of the `$CI_PIPELINE_SOURCE` variable:
| `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](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/pipelines_for_merged_results.md), and [merge trains](../pipelines/merge_trains.md). |
+| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/merged_results_pipelines.md), and [merge trains](../pipelines/merge_trains.md). |
| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../pipelines/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](../pipelines/multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api), or the [`trigger`](../yaml/index.md#trigger) keyword. |
| `push` | For pipelines triggered by a `git push` event, including for branches and tags. |
@@ -263,6 +263,9 @@ Other commonly used variables for `if` clauses:
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: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/`:
+ If the commit branch is the default branch and the commit message title matches a regular expression.
+ For example, the default commit message for a merge commit starts with `Merge branch`.
- `if: '$CUSTOM_VARIABLE !~ /regex-expression/'`: If the [custom variable](../variables/index.md#custom-cicd-variables)
`CUSTOM_VARIABLE` does **not** match a regular expression.
- `if: '$CUSTOM_VARIABLE == "value1"'`: If the custom variable `CUSTOM_VARIABLE` is
@@ -406,9 +409,9 @@ the `build` job is still skipped. The job does not run for any of the files.
With some configurations that use `changes`, [jobs or pipelines might run unexpectedly](#jobs-or-pipelines-run-unexpectedly-when-using-changes)
-#### Use `only:changes` with pipelines for merge requests
+#### Use `only:changes` with merge request pipelines
-With [pipelines for merge requests](../pipelines/merge_request_pipelines.md),
+With [merge request pipelines](../pipelines/merge_request_pipelines.md),
it's possible to define a job to be created based on files modified
in a merge request.
@@ -704,9 +707,12 @@ deploystacks: [gcp, data]
deploystacks: [vultr, data]
```
-In [GitLab 14.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/239737), you can
-use the variables defined in `parallel: matrix` with the [`tags`](../yaml/index.md#tags) keyword for
-dynamic runner selection.
+### Select different runner tags for each parallel matrix job
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/239737) in GitLab 14.1.
+
+You can use variables defined in `parallel: matrix` with the [`tags`](../yaml/index.md#tags)
+keyword for dynamic runner selection:
```yaml
deploystacks:
@@ -931,7 +937,7 @@ For example:
You might have jobs or pipelines that run unexpectedly when using [`rules: changes`](../yaml/index.md#ruleschanges)
or [`only: changes`](../yaml/index.md#onlychanges--exceptchanges) without
-[pipelines for merge requests](../pipelines/merge_request_pipelines.md).
+[merge request pipelines](../pipelines/merge_request_pipelines.md).
Pipelines on branches or tags that don't have an explicit association with a merge request
use a previous SHA to calculate the diff. This calculation is equivalent to `git diff HEAD~`
@@ -944,3 +950,19 @@ and can cause unexpected behavior, including:
Additionally, rules with `changes` always evaluate as true in [scheduled pipelines](../pipelines/schedules.md).
All files are considered to have changed when a scheduled pipeline runs, so jobs
might always be added to scheduled pipelines that use `changes`.
+
+### `You are not allowed to download code from this project.` error message
+
+You might see pipelines fail when a GitLab administrator runs a protected manual job
+in a private project.
+
+CI/CD jobs usually clone the project when the job starts, and this uses [the permissions](../../user/permissions.md#job-permissions)
+of the user that runs the job. All users, including administrators, must be direct members
+of a private project to clone the source of that project. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/23130)
+to change this behavior.
+
+To run protected manual jobs:
+
+- Add the administrator as a direct member of the private project (any role)
+- [Impersonate a user](../../user/admin_area/index.md#user-impersonation) who is a
+ direct member of the project.
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index e58907ee0bd..c0df0b2a439 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -4,48 +4,54 @@ 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
---
-# Validate `.gitlab-ci.yml` syntax with the CI Lint tool **(FREE)**
+# Validate GitLab CI/CD configuration **(FREE)**
-If you want to test the validity of your GitLab CI/CD configuration before committing
-the changes, you can use the CI Lint tool. This tool checks for syntax and logical
-errors by default, and can simulate pipeline creation to try to find more complicated
-issues as well.
+Use the CI Lint tool to check the validity of GitLab CI/CD configuration.
+You can validate the syntax from a `.gitlab-ci.yml` file or any other sample CI/CD configuration.
+This tool checks for syntax and logic errors, and can simulate pipeline
+creation to try to find more complicated configuration problems.
-To access the CI Lint tool, navigate to **CI/CD > Pipelines** or **CI/CD > Jobs**
-in your project and click **CI lint**.
+If you use the [pipeline editor](pipeline_editor/index.md), it verifies configuration
+syntax automatically.
-If you use VS Code, you can also validate your CI/CD configuration with the
+If you use VS Code, you can validate your CI/CD configuration with the
[GitLab Workflow VS Code extension](../user/project/repository/vscode.md).
-## Validate basic logic and syntax
+## Check CI/CD syntax
-By default, the CI lint checks the syntax of your CI YAML configuration and also runs
-some basic logical validations. Configuration added with the [`includes` keyword](yaml/index.md#include),
-is also validated.
+The CI lint tool checks the syntax of GitLab CI/CD configuration, including
+configuration added with the [`includes` keyword](yaml/index.md#include).
-To use the CI lint, paste a complete CI configuration (`.gitlab-ci.yml` for example)
-into the text box and click **Validate**:
+To check CI/CD configuration with the CI lint tool:
-![CI Lint](img/ci_lint.png)
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select one of:
+ - **CI/CD > Pipelines**
+ - **CI/CD > Jobs**
+1. In the top right, select **CI lint**.
+1. Paste a copy of the CI/CD configuration you want to check into the text box.
+1. Select **Validate**.
-## Pipeline simulation
+## Simulate a pipeline
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229794) in GitLab 13.3.
-Not all pipeline configuration issues can be found by the [basic CI lint validation](#validate-basic-logic-and-syntax).
-You can simulate the creation of a pipeline for deeper validation that can discover
-more complicated issues.
-
-To validate the configuration by running a pipeline simulation:
+You can simulate the creation of a GitLab CI/CD pipeline to find more complicated issues,
+including problems with [`needs`](yaml/index.md#needs) and [`rules`](yaml/index.md#rules)
+configuration. A simulation runs as a Git `push` event on the default branch.
-1. Paste the GitLab CI configuration to verify into the text box.
-1. Select the **Simulate pipeline creation for the default branch** checkbox.
-1. Select **Validate**.
+Prerequisites:
-![Dry run](img/ci_lint_dry_run.png)
+- You must have [permissions](../user/permissions.md#project-members-permissions)
+ to create pipelines on this branch to validate with a simulation.
-### Pipeline simulation limitations
+To simulate a pipeline:
-Simulations run as `git push` events against the default branch. You must have
-[permissions](../user/permissions.md#project-members-permissions) to create pipelines
-on this branch to validate with a simulation.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select one of:
+ - **CI/CD > Pipelines**
+ - **CI/CD > Jobs**
+1. In the top right, select **CI lint**.
+1. Paste a copy of the CI/CD configuration you want to check into the text box.
+1. Select **Simulate pipeline creation for the default branch**.
+1. Select **Validate**.
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index eb302b9ed7f..5b472eec7b5 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference
---
# Metrics Reports **(PREMIUM)**
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index ef6f28e36e5..bfa2eb54806 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -196,7 +196,7 @@ can leverage. You can see the complete list of packaging features in the
Where you may have used plugins to get things like code quality, unit tests, security scanning, and so on working in Jenkins,
GitLab takes advantage of our connected ecosystem to automatically pull these kinds of results into
-your Merge Requests, pipeline details pages, and other locations. You may find that you actually don't
+your merge requests, pipeline details pages, and other locations. You may find that you actually don't
need to configure anything to have these appear.
If they aren't working as expected, or if you'd like to see what's available, our [CI feature index](../index.md#gitlab-cicd-features) has the full list
diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md
index e0fb5b45986..8b10a74bd78 100644
--- a/doc/ci/pipelines/cicd_minutes.md
+++ b/doc/ci/pipelines/cicd_minutes.md
@@ -149,7 +149,7 @@ namespace.
## How CI/CD minutes are calculated
-CI/CD minutes are calculated based on:
+CI/CD minutes for individual jobs are calculated based on:
- The duration the job runs.
- The visibility of the projects where the job runs.
@@ -174,6 +174,10 @@ For example:
- If a pipeline runs for one of the personal projects for `alice`, the CI/CD minutes
are added to the overall consumption for the `alice` namespace.
+The CI/CD minutes used by one pipeline is the total CI/CD minutes used by all the jobs
+that ran in the pipeline. The CI/CD minute usage for a pipeline can be higher than
+the duration of the pipeline if many jobs ran at the same time.
+
### Cost factor
The cost factor for a job running on a shared runner is:
diff --git a/doc/ci/pipelines/img/merged_result_pipeline.png b/doc/ci/pipelines/img/merged_result_pipeline.png
deleted file mode 100644
index 2584cd4d38d..00000000000
--- a/doc/ci/pipelines/img/merged_result_pipeline.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index b873b2ae30f..5a5fd2b5540 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -50,14 +50,14 @@ Pipelines can be configured in many different ways:
followed by the next stage.
- [Directed Acyclic Graph Pipeline (DAG) pipelines](../directed_acyclic_graph/index.md) are based on relationships
between jobs and can run more quickly than basic pipelines.
-- [Pipelines for Merge Requests](../pipelines/merge_request_pipelines.md) run for merge
+- [Merge request pipelines](../pipelines/merge_request_pipelines.md) run for merge
requests only (rather than for every commit).
-- [Pipelines for Merged Results](../pipelines/pipelines_for_merged_results.md)
+- [Merged results pipelines](../pipelines/merged_results_pipelines.md)
are merge request pipelines that act as though the changes from the source branch have
already been merged into the target branch.
-- [Merge Trains](../pipelines/merge_trains.md)
- use pipelines for merged results to queue merges one after the other.
-- [Parent-Child pipelines](parent_child_pipelines.md) break down complex pipelines
+- [Merge trains](../pipelines/merge_trains.md)
+ use merged results pipelines to queue merges one after the other.
+- [Parent-child pipelines](parent_child_pipelines.md) break down complex pipelines
into one parent pipeline that can trigger multiple child sub-pipelines, which all
run in the same project and with the same SHA. This pipeline architecture is commonly used for mono-repos.
- [Multi-project pipelines](multi_project_pipelines.md) combine pipelines for different projects together.
@@ -123,7 +123,7 @@ This table lists the refspecs injected for each pipeline type:
|--------------- |---------------------------------------- |
| pipeline for branches | `+<sha>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
| pipeline for tags | `+<sha>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
-| [pipeline for merge requests](../pipelines/merge_request_pipelines.md) | `+<sha>:refs/pipelines/<id>` |
+| [merge request pipeline](../pipelines/merge_request_pipelines.md) | `+<sha>:refs/pipelines/<id>` |
The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your
project repository. GitLab generates the special ref `refs/pipelines/<id>` during a
@@ -281,7 +281,7 @@ pipelines.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24851) in GitLab 12.7.
-Users with the [Owner role](../../user/permissions.md) in a project can delete a pipeline
+Users with the Owner role for 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 1710c57b36b..fa8041671dc 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -1,9 +1,8 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/job_artifacts.html'
-type: reference, howto
---
# Job artifacts **(FREE)**
@@ -194,7 +193,8 @@ artifacts:
### Add untracked files to artifacts
Use [`artifacts:untracked`](../yaml/index.md#artifactsuntracked) to add all Git untracked
-files as artifacts (along with the paths defined in [`artifacts:paths`](../yaml/index.md#artifactspaths)).
+files as artifacts (along with the paths defined in [`artifacts:paths`](../yaml/index.md#artifactspaths)). Untracked
+files are those that haven't been added to the repository but exist in the repository checkout.
Save all Git untracked files and files in `binaries`:
@@ -259,7 +259,7 @@ You can delete a single job, which also removes the job's
artifacts and log. You must be:
- The owner of the job.
-- A [maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project.
+- A user with at least the Maintainer role for the project.
To delete a job:
@@ -381,7 +381,7 @@ to the `expire_in` specification.
If a new pipeline for the same ref completes successfully, the previous pipeline's
artifacts are deleted according to the `expire_in` configuration. The artifacts
-of the new pipeline are kept automatically.
+of the new pipeline are kept automatically.
Keeping the latest artifacts can use a large amount of storage space in projects
with a lot of jobs or large artifacts. If the latest artifacts are not needed in
diff --git a/doc/ci/pipelines/merge_request_pipelines.md b/doc/ci/pipelines/merge_request_pipelines.md
index 4d7ebc09e6f..dcc3e7e6919 100644
--- a/doc/ci/pipelines/merge_request_pipelines.md
+++ b/doc/ci/pipelines/merge_request_pipelines.md
@@ -5,13 +5,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
---
-# Pipelines for merge requests **(FREE)**
+# Merge request pipelines **(FREE)**
+
+> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/351192) from `pipelines for merge requests` to `merge request pipelines` in GitLab 14.8.
You can configure your [pipeline](index.md) to run every time you commit changes to a branch.
This type of pipeline is called a *branch pipeline*.
Alternatively, you can configure your pipeline to run every time you make changes to the
-source branch for a merge request. This type of pipeline is called a *pipeline for merge requests*.
+source branch for a merge request. This type of pipeline is called a *merge request pipeline*.
Branch pipelines:
@@ -20,28 +22,28 @@ Branch pipelines:
- Have access to [some predefined variables](../variables/predefined_variables.md).
- Have access to [protected variables](../variables/index.md#protect-a-cicd-variable).
-Pipelines for merge requests:
+Merge request pipelines:
- Run when you:
- Create a new merge request.
- Push a new commit to the source branch for a merge request.
- Select **Run pipeline** from the **Pipelines** tab in a merge request. This option
- is only available when pipelines for merge requests are configured for the pipeline.
+ is only available when merge request pipelines are configured for the pipeline.
- Do not run by default. The jobs in the CI/CD configuration file [must be configured](#prerequisites)
- to run in pipelines for merge request.
+ to run in merge request pipelines.
- Have access to [more predefined variables](#available-predefined-variables).
- Do not have access to [protected variables](../variables/index.md#protect-a-cicd-variable).
Both of these types of pipelines can appear on the **Pipelines** tab of a merge request.
-## Types of pipelines for merge requests
+## Types of merge request pipelines
-The three types of pipelines for merge requests are:
+The three types of merge request pipelines are:
-- Pipelines for merge requests, which run on the changes in the merge request's
+- Merge request pipelines, which run on the changes in the merge request's
source branch. These pipelines display a `detached` label to indicate that the
pipeline ran only on the contents of the source branch, ignoring the target branch.
-- [Pipelines for merged results](pipelines_for_merged_results.md), which run on
+- [Merged results pipelines](merged_results_pipelines.md), which run on
the result of combining the source branch's changes with the target branch.
- [Merge trains](merge_trains.md), which run when merging multiple merge requests
at the same time. The changes from each merge request are combined into the
@@ -50,31 +52,31 @@ The three types of pipelines for merge requests are:
## Prerequisites
-To use pipelines for merge requests:
+To use merge request pipelines:
- Your project's [CI/CD configuration file](../yaml/index.md) must be configured with
- jobs that run in pipelines for merge requests. To do this, you can use:
+ jobs that run in merge request pipelines. To do this, you can use:
- [`rules`](#use-rules-to-add-jobs).
- [`only/except`](#use-only-to-add-jobs).
-- You must have at least the Developer [role](../../user/permissions.md) in the
- source project to run a pipeline for merge requests.
+- You must have at least the Developer role in the
+ source project to run a merge request pipeline.
- Your repository must be a GitLab repository, not an [external repository](../ci_cd_for_external_repos/index.md).
## Use `rules` to add jobs
You can use the [`rules`](../yaml/index.md#rules) keyword to configure jobs to run in
-pipelines for merge requests. For example:
+merge request pipelines. For example:
```yaml
job1:
script:
- - echo "This job runs in pipelines for merge requests"
+ - echo "This job runs in merge request pipelines"
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
```
You can also use the [`workflow: rules`](../yaml/index.md#workflowrules) keyword
-to configure the entire pipeline to run in pipelines for merge requests. For example:
+to configure the entire pipeline to run in merge request pipelines. For example:
```yaml
workflow:
@@ -83,22 +85,22 @@ workflow:
job1:
script:
- - echo "This job runs in pipelines for merge requests"
+ - echo "This job runs in merge request pipelines"
job2:
script:
- - echo "This job also runs in pipelines for merge requests"
+ - echo "This job also runs in merge request pipelines"
```
## Use `only` to add jobs
You can use the [`only`](../yaml/index.md#onlyrefs--exceptrefs) keyword with `merge_requests`
-to configure jobs to run in pipelines for merge requests.
+to configure jobs to run in merge request pipelines.
```yaml
job1:
script:
- - echo "This job runs in pipelines for merge requests"
+ - echo "This job runs in merge request pipelines"
only:
- merge_requests
```
@@ -122,7 +124,7 @@ Pipelines for forks display with the **fork** badge in the parent project:
### Run pipelines in the parent project **(PREMIUM)**
-Project members in the parent project can choose to run a pipeline for merge requests
+Project members in the parent project can choose to run a merge request pipeline
for a merge request submitted from a fork project. This pipeline:
- Is created and runs in the parent (target) project, not the fork (source) project.
@@ -140,20 +142,26 @@ parent project when the pipeline runs, even before merge. As a reviewer, careful
check the changes in the merge request before triggering the pipeline. GitLab shows
a warning that you must accept before you can trigger the pipeline.
-Parent project members with at least the [Developer role](../../user/permissions.md)
-can create pipelines in the parent project for merge requests from a forked project:
+Prerequisites:
+
+- You must be a member of the parent project and have at least the [Developer role](../../user/permissions.md).
+- The fork project must be [visible](../../public_access/public_access.md) to the
+ user running the pipeline. Otherwise, the **Pipelines** tab does not display
+ in the merge request.
+
+To run a pipeline in the parent project for a merge request from a fork project:
1. In the merge request, go to the **Pipelines** tab.
1. Select **Run pipeline**. You must accept the warning, or the pipeline does not run.
## Available predefined variables
-When you use pipelines for merge requests, you can use:
+When you use merge request pipelines, you can use:
- All the same [predefined variables](../variables/predefined_variables.md) that are
available in branch pipelines.
- [Additional predefined variables](../variables/predefined_variables.md#predefined-variables-for-merge-request-pipelines)
- available only to jobs in pipelines for merge requests. These variables contain
+ available only to jobs in merge request pipelines. These variables contain
information from the associated merge request, which can be when calling the
[GitLab Merge Request API endpoint](../../api/merge_requests.md) from a job.
@@ -166,14 +174,14 @@ to run for both branches and merge requests at the same time. Adjust your pipeli
configuration to [avoid duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines).
In [GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201845),
-you can add `workflow:rules` to [switch from branch pipelines to pipelines for merge requests](../yaml/workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines).
+you can add `workflow:rules` to [switch from branch pipelines to merge request pipelines](../yaml/workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines).
After a merge request is open on the branch, the pipeline switches to a merge request pipeline.
### Two pipelines when pushing an invalid CI/CD configuration file
If you push an invalid CI/CD configuration to a merge request's branch, two failed
pipelines appear in the pipelines tab. One pipeline is a failed branch pipeline,
-the other is a failed pipeline for merge requests.
+the other is a failed merge request pipeline.
When the configuration syntax is fixed, no further failed pipelines should appear.
To find and fix the configuration problem, you can use:
@@ -183,7 +191,7 @@ To find and fix the configuration problem, you can use:
### The merge request's pipeline is marked as failed but the latest pipeline succeeded
-It's possible to have both branch pipelines and pipelines for merge requests in the
+It's possible to have both branch pipelines and merge request pipelines in the
**Pipelines** tab of a single merge request. This might be [by configuration](../yaml/workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines),
or [by accident](#two-pipelines-when-pushing-to-a-branch).
@@ -191,8 +199,8 @@ If both types of pipelines are in one merge request, the merge request's pipelin
is not considered successful if:
- The branch pipeline succeeds.
-- The pipeline for merge request fails.
+- The merge request pipeline fails.
When using the [merge when pipeline succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.md)
-feature and both pipelines types are present, the pipelines for merge requests are checked,
+feature and both pipelines types are present, the merge request pipelines are checked,
not the branch pipelines.
diff --git a/doc/ci/pipelines/merge_trains.md b/doc/ci/pipelines/merge_trains.md
index d47cbf5f47c..ffcce06cfbd 100644
--- a/doc/ci/pipelines/merge_trains.md
+++ b/doc/ci/pipelines/merge_trains.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
For more information about why you might want to use merge trains, read [How merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
-When [pipelines for merged results](pipelines_for_merged_results.md) are
+When [merged results pipelines](merged_results_pipelines.md) are
enabled, the pipeline jobs run as if the changes from your source branch have already
been merged into the target branch.
@@ -67,7 +67,7 @@ branch](https://www.youtube.com/watch?v=D4qCqXgZkHQ).
To enable merge trains:
-- You must have the [Maintainer role](../../user/permissions.md).
+- You must have the Maintainer role.
- 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
@@ -93,7 +93,7 @@ In GitLab 13.5 and earlier, there is only one checkbox, named
WARNING:
If you select the check box but don't configure your CI/CD to use
-pipelines for merge requests, your merge requests may become stuck in an
+merge request pipelines, your merge requests may become stuck in an
unresolved state or your pipelines may be dropped.
## Start a merge train
@@ -145,8 +145,22 @@ This is the fastest option to get the change merged into the target branch.
![Merge Immediately](img/merge_train_immediate_merge_v12_6.png)
WARNING:
-Each time you merge a merge request immediately, the current merge train
-is recreated and all pipelines restart.
+Each time you merge a merge request immediately, the current merge train is recreated,
+all pipelines restart, and [redundant pipelines are cancelled](#automatic-pipeline-cancellation).
+
+### Automatic pipeline cancellation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12996) in GitLab 12.3.
+
+GitLab CI/CD can detect the presence of redundant pipelines, and cancels them
+to conserve CI resources.
+
+When a user merges a merge request immediately in an ongoing merge
+train, the train is reconstructed, because it recreates the expected
+post-merge commit and pipeline. In this case, the merge train may already
+have pipelines running against the previous expected post-merge commit.
+These pipelines are considered redundant and are automatically
+canceled.
## Troubleshooting
@@ -179,8 +193,8 @@ for more information.
### Merge train pipeline cannot be retried
-When a pipeline for merge trains fails the merge request is dropped from the train and the pipeline can't be retried.
-Pipelines for merge trains run on the merged result of the changes in the merge request and
+When a merge train pipeline fails, the merge request is dropped from the train and the pipeline can't be retried.
+Merge train pipelines run on the merged result of the changes in the merge request and
the changes from other merge requests already on the train. If the merge request is dropped from the train,
the merged result is out of date and the pipeline can't be retried.
@@ -197,11 +211,16 @@ is enabled in **Settings > General > Merge requests**. This option requires that
run a new successful pipeline before you can re-add a merge request to a merge train.
Merge trains ensure that each pipeline has succeeded before a merge happens, so
-you can clear the **Pipelines must succeed** checkbox and keep
-**Enable merge trains and pipelines for merged results** (merge trains) selected.
+you can:
+
+- Clear the **Pipelines must succeed** checkbox.
+- Select the **Enable merged results pipelines** and **Enable merge trains** checkboxes.
+
+ In GitLab 13.5 and earlier, there is only one checkbox, named
+ **Enable merge trains and pipelines for merged results**.
If you want to keep the **Pipelines must succeed** option selected along with merge
-trains, create a new pipeline for merged results when this error occurs:
+trains, create a new merged results pipeline when this error occurs:
1. On the **Pipelines** tab, select **Run pipeline**.
1. Select **Start/Add to merge train when pipeline succeeds**.
@@ -215,8 +234,8 @@ In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/244831)
you can [enable or disable merge trains in the project settings](#enable-merge-trains).
In GitLab 13.5 and earlier, merge trains are automatically enabled when
-[pipelines for merged results](pipelines_for_merged_results.md) are enabled.
-To use pipelines for merged results without using merge trains, you can enable a
+[merged results pipelines](merged_results_pipelines.md) are enabled.
+To use merged results pipelines without using merge trains, you can enable a
[feature flag](../../user/feature_flags.md) that blocks the merge trains feature.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
diff --git a/doc/ci/pipelines/merged_results_pipelines.md b/doc/ci/pipelines/merged_results_pipelines.md
new file mode 100644
index 00000000000..4794107cc87
--- /dev/null
+++ b/doc/ci/pipelines/merged_results_pipelines.md
@@ -0,0 +1,78 @@
+---
+stage: Verify
+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
+---
+
+# Merged results pipelines **(PREMIUM)**
+
+> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/351192) from `pipelines for merged results` to `merged results pipelines` in GitLab 14.8.
+
+A *merged results pipeline* is a type of [merge request pipeline](merge_request_pipelines.md). It is a pipeline that runs against the results of the source and target branches merged together.
+
+GitLab creates an internal commit with the merged results, so the pipeline can run
+against it. This commit does not exist in either branch,
+but you can view it in the pipeline details.
+
+The pipeline runs against the target branch as it exists at the moment you run the pipeline.
+Over time, while you're working in the source branch, the target branch might change.
+Any time you want to be sure the merged results are accurate, you should re-run the pipeline.
+
+Merged results pipelines can't run when:
+
+- The target branch has changes that conflict with the changes in the source branch.
+- The merge request is a [**Draft** merge request](../../user/project/merge_requests/drafts.md).
+
+In these cases, the pipeline runs as a [merge request pipeline](merge_request_pipelines.md)
+and is labeled as `detached`.
+
+## Prerequisites
+
+To use merged results pipelines:
+
+- Your project's [CI/CD configuration file](../yaml/index.md) must be configured to
+ [run jobs in merge request pipelines](merge_request_pipelines.md#prerequisites).
+- Your repository must be a GitLab repository, not an
+ [external repository](../ci_cd_for_external_repos/index.md).
+- You must not be using [fast forward merges](../../user/project/merge_requests/fast_forward_merge.md).
+ [An issue exits](https://gitlab.com/gitlab-org/gitlab/-/issues/26996) to change this behavior.
+
+## Enable merged results pipelines
+
+To enable merged results pipelines in a project, you must have at least the
+Maintainer role:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Merge requests**.
+1. Select **Enable merged results pipelines**.
+1. Select **Save changes**.
+
+WARNING:
+If you select the checkbox but don't configure your pipeline to use
+merge request pipelines, your merge requests may become stuck in an
+unresolved state or your pipelines may be dropped.
+
+## Troubleshooting
+
+### Merged results pipelines are not created
+
+In GitLab 13.7 and earlier, merged results pipelines might not be created due
+to a disabled [feature flag](../../user/feature_flags.md). This feature flag
+[was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299115) in GitLab 13.8.
+Upgrade to 13.8 or later, or make sure the `:merge_ref_auto_sync`
+[feature flag is enabled](../../administration/feature_flags.md#check-if-a-feature-flag-is-enabled)
+on your GitLab instance.
+
+### Pipelines fail intermittently with a `fatal: reference is not a tree:` error
+
+Merged results pipelines run on a merge ref for a merge request
+(`refs/merge-requests/<iid>/merge`), so the Git reference could be overwritten at an
+unexpected time.
+
+For example, when a source or target branch is advanced, the pipeline fails with
+the `fatal: reference is not a tree:` error, which indicates that the checkout-SHA
+is not found in the merge ref.
+
+This behavior was improved in GitLab 12.4 by introducing [persistent pipeline refs](../troubleshooting.md#fatal-reference-is-not-a-tree-error).
+Upgrade to GitLab 12.4 or later to resolve the problem.
diff --git a/doc/ci/pipelines/multi_project_pipelines.md b/doc/ci/pipelines/multi_project_pipelines.md
index 8a83e7e31f4..2163527e3ca 100644
--- a/doc/ci/pipelines/multi_project_pipelines.md
+++ b/doc/ci/pipelines/multi_project_pipelines.md
@@ -283,7 +283,7 @@ tag in a different project.
Prerequisites:
- The upstream project must be [public](../../public_access/public_access.md).
-- The user must have the [Developer role](../../user/permissions.md#project-members-permissions)
+- The user must have the Developer role
in the upstream project.
To trigger the pipeline when the upstream project is rebuilt:
diff --git a/doc/ci/pipelines/parent_child_pipelines.md b/doc/ci/pipelines/parent_child_pipelines.md
index 5e4b707a38c..a3ded24e8c9 100644
--- a/doc/ci/pipelines/parent_child_pipelines.md
+++ b/doc/ci/pipelines/parent_child_pipelines.md
@@ -100,7 +100,7 @@ microservice_a:
## Merge request child pipelines
-To trigger a child pipeline as a [Merge Request Pipeline](merge_request_pipelines.md) we need to:
+To trigger a child pipeline as a [merge request pipeline](merge_request_pipelines.md) we need to:
- Set the trigger job to run on merge requests:
diff --git a/doc/ci/pipelines/pipeline_artifacts.md b/doc/ci/pipelines/pipeline_artifacts.md
index b174b6af9f9..e9dd1b2a942 100644
--- a/doc/ci/pipelines/pipeline_artifacts.md
+++ b/doc/ci/pipelines/pipeline_artifacts.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Pipeline artifacts **(FREE)**
diff --git a/doc/ci/pipelines/pipelines_for_merged_results.md b/doc/ci/pipelines/pipelines_for_merged_results.md
index 91a49a48882..457f5ce9c30 100644
--- a/doc/ci/pipelines/pipelines_for_merged_results.md
+++ b/doc/ci/pipelines/pipelines_for_merged_results.md
@@ -1,133 +1,9 @@
---
-stage: Verify
-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
+redirect_to: 'merged_results_pipelines.md'
+remove_date: '2022-04-27'
---
-# Pipelines for merged results **(PREMIUM)**
+This document was moved to [another location](merged_results_pipelines.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7380) in GitLab 11.10.
-
-When you submit a merge request, you are requesting to merge changes from a
-source branch into a target branch. By default, the CI pipeline runs jobs
-against the source branch.
-
-With *pipelines for merged results*, the pipeline runs as if the changes from
-the source branch have already been merged into the target branch. The commit shown for the pipeline does not exist on the source or target branches but represents the combined target and source branches.
-
-![Merge request widget for merged results pipeline](img/merged_result_pipeline.png)
-
-If the pipeline fails due to a problem in the target branch, you can wait until the
-target is fixed and re-run the pipeline.
-This new pipeline runs as if the source is merged with the updated target, and you
-don't need to rebase.
-
-The pipeline does not automatically run when the target branch changes. Only changes
-to the source branch trigger a new pipeline. If a long time has passed since the last successful
-pipeline, you may want to re-run it before merge, to ensure that the source changes
-can still be successfully merged into the target.
-
-When the merge request can't be merged, the pipeline runs against the source branch only. For example, when:
-
-- The target branch has changes that conflict with the changes in the source branch.
-- The merge request is a [**Draft** merge request](../../user/project/merge_requests/drafts.md).
-
-In these cases, the pipeline runs as a [pipeline for merge requests](merge_request_pipelines.md)
-and is labeled as `detached`. If these cases no longer exist, new pipelines
-again run against the merged results.
-
-Any user who has developer [permissions](../../user/permissions.md) can run a
-pipeline for merged results.
-
-## Prerequisites
-
-To enable pipelines for merge results:
-
-- 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.
- To follow progress, see [#26996](https://gitlab.com/gitlab-org/gitlab/-/issues/26996).
-- Your repository must be a GitLab repository, not an
- [external repository](../ci_cd_for_external_repos/index.md).
-
-## Enable pipelines for merged results
-
-To enable pipelines for merged results for your project:
-
-1. [Configure your CI/CD configuration file](merge_request_pipelines.md#prerequisites)
- so that the pipeline or individual jobs run for merge requests.
-1. Visit your project's **Settings > General** and expand **Merge requests**.
-1. Check **Enable merged results pipelines**.
-1. Click **Save changes**.
-
-WARNING:
-If you select the checkbox but don't configure your CI/CD to use
-pipelines for merge requests, your merge requests may become stuck in an
-unresolved state or your pipelines may be dropped.
-
-## Using Merge Trains
-
-When you enable [Pipelines for merged results](#pipelines-for-merged-results),
-GitLab [automatically displays](merge_trains.md#add-a-merge-request-to-a-merge-train)
-a **Start/Add Merge Train button**.
-
-Generally, this is a safer option than merging merge requests immediately, because your
-merge request is evaluated with an expected post-merge result before the actual
-merge happens.
-
-For more information, read the [documentation on Merge Trains](merge_trains.md).
-
-## Automatic pipeline cancellation
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12996) in GitLab 12.3.
-
-GitLab CI/CD can detect the presence of redundant pipelines, and cancels them
-to conserve CI resources.
-
-When a user merges a merge request immediately in an ongoing merge
-train, the train is reconstructed, because it recreates the expected
-post-merge commit and pipeline. In this case, the merge train may already
-have pipelines running against the previous expected post-merge commit.
-These pipelines are considered redundant and are automatically
-canceled.
-
-## Troubleshooting
-
-### Pipelines for merged results not created even with new change pushed to merge request
-
-Can be caused by some disabled feature flags. Please make sure that
-the following feature flags are enabled on your GitLab instance:
-
-- `:merge_ref_auto_sync`
-
-To check and set these feature flag values, please ask an administrator to:
-
-1. Log into the Rails console of the GitLab instance:
-
- ```shell
- sudo gitlab-rails console
- ```
-
-1. Check if the flags are enabled or not:
-
- ```ruby
- Feature.enabled?(:merge_ref_auto_sync)
- ```
-
-1. If needed, enable the feature flags:
-
- ```ruby
- Feature.enable(:merge_ref_auto_sync)
- ```
-
-### Intermittently pipelines fail by `fatal: reference is not a tree:` error
-
-Since pipelines for merged results are a run on a merge ref of a merge request
-(`refs/merge-requests/<iid>/merge`), the Git reference could be overwritten at an
-unexpected timing. For example, when a source or target branch is advanced.
-In this case, the pipeline fails because of `fatal: reference is not a tree:` error,
-which indicates that the checkout-SHA is not found in the merge ref.
-
-This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../troubleshooting.md#fatal-reference-is-not-a-tree-error).
-You should be able to create pipelines at any timings without concerning the error.
+<!-- This redirect file can be deleted after 2022-04-27. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index 692460120fe..fe9db3306cd 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -17,7 +17,9 @@ Pipeline schedules can be used to also run [pipelines](index.md) at specific int
- Every other Sunday at 0900 hours (cron example: `0 9 * * sun%2`).
- Once every day (cron example: `0 0 * * *`).
-Schedule timing is configured with cron notation, parsed by [Fugit](https://github.com/floraison/fugit).
+Schedule timing is configured with [cron notation](../../topics/cron/index.md).
+You can use any cron value, but scheduled pipelines cannot run more frequently
+than the instance's [maximum frequency for scheduled pipelines](#advanced-configuration).
In addition to using the GitLab UI, pipeline schedules can be maintained using the
[Pipeline schedules API](../../api/pipeline_schedules.md).
@@ -82,20 +84,24 @@ job:
### Advanced configuration **(FREE SELF)**
-The pipelines are not executed exactly on schedule because schedules are handled by
-Sidekiq, which runs according to its interval.
+Scheduled pipelines can be configured with any [cron value](../../topics/cron/index.md),
+but they do not always run exactly when scheduled. An internal process, called the
+_pipeline schedule worker_, queues all the scheduled pipelines, but does not
+run continuously. The worker runs on its own schedule, and scheduled pipelines that
+are ready to start are only queued the next time the worker runs. Scheduled pipelines
+can't run more frequently than the worker.
-For example, only two pipelines are created per day if:
+The default frequency of the pipeline schedule worker is `3-59/10 * * * *` (every ten minutes,
+starting with `0:03`, `0:13`, `0:23`, and so on). The default frequency for GitLab.com
+is listed in the [GitLab.com settings](../../user/gitlab_com/index.md#gitlab-cicd).
-- You set a schedule to create a pipeline every minute (`* * * * *`).
-- The Sidekiq worker runs on 00:00 and 12:00 every day (`0 */12 * * *`).
-
-To change the Sidekiq worker's frequency:
+To change the frequency of the pipeline schedule worker:
1. Edit the `gitlab_rails['pipeline_schedule_worker_cron']` value in your instance's `gitlab.rb` file.
1. [Reconfigure GitLab](../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-For GitLab.com, refer to the [dedicated settings page](../../user/gitlab_com/index.md#gitlab-cicd).
+For example, to set the maximum frequency of pipelines to twice a day, set `pipeline_schedule_worker_cron`
+to a cron value of `0 */12 * * *` (`00:00` and `12:00` every day).
## Working with scheduled pipelines
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 85824dfb7c7..e22746dbfa0 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -108,6 +108,10 @@ To customize the path:
- Is on an external site, enter the full URL.
1. Select **Save changes**.
+NOTE:
+You cannot use your project's [pipeline editor](../pipeline_editor/index.md) to
+edit CI/CD configuration files in other projects or on an external site.
+
### Custom CI/CD configuration file examples
If the CI/CD configuration file is not in the root directory, the path must be relative to it.
@@ -191,21 +195,18 @@ Jobs that exceed the timeout are marked as failed.
You can override this value [for individual runners](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
-## Add test coverage results to a merge request
+## Add test coverage results to a merge request (DEPRECATED)
+
+> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 14.9. Replaced by [`coverage` keyword](../yaml/index.md#coverage).
+
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/17633)
+for use in GitLab 14.9, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 15.0.
If you use test coverage in your code, you can use a regular expression to
find coverage results in the job log. You can then include these results
in the merge request in GitLab.
-1. On the top bar, select **Menu > Projects** and find your project.
-1. On the left sidebar, select **Settings > CI/CD**.
-1. Expand **General pipelines**.
-1. In the **Test coverage parsing** field, enter a regular expression.
- Leave blank to disable this feature.
-
-You can use <https://rubular.com> to test your regex. The regex returns the **last**
-match found in the output.
-
If the pipeline succeeds, the coverage is shown in the merge request widget and
in the jobs table. If multiple jobs in the pipeline have coverage reports, they are
averaged.
@@ -214,6 +215,31 @@ averaged.
![Build status coverage](img/pipelines_test_coverage_build.png)
+To define a coverage-parsing regular expression:
+
+- Using the project's `.gitlab-ci.yml`, provide a regular expression using the [`coverage`](../yaml/index.md#coverage)
+ keyword. Setting the regular expression this way takes precedence over the project's CI/CD settings.
+
+- Using the Project's CI/CD settings:
+ - Set using the GitLab UI:
+
+ 1. On the top bar, select **Menu > Projects** and find your project.
+ 1. On the left sidebar, select **Settings > CI/CD**.
+ 1. Expand **General pipelines**.
+ 1. In the **Test coverage parsing** field, enter a regular expression. Leave blank to disable this feature.
+
+ - Set when [editing a project](../../api/projects.md#edit-project) or [creating a project](../../api/projects.md#create-project)
+ using the GitLab API with the `build_coverage_regex` attribute:
+
+ ```shell
+ curl --request PUT --header "PRIVATE-TOKEN: <your-token>" \
+ --url 'https://gitlab.com/api/v4/projects/<your-project-ID>' \
+ --data "build_coverage_regex=<your-regular-expression>"
+ ```
+
+You can use <https://rubular.com> to test your regular expression. The regular expression returns the **last**
+match found in the output.
+
### Test coverage examples
Use this regex for commonly used test tools.
@@ -338,7 +364,7 @@ https://gitlab.example.com/<namespace>/<project>/badges/<branch>/pipeline.svg?ig
### Test coverage report badge
-You can define the regular expression for the [coverage report](#add-test-coverage-results-to-a-merge-request)
+You can define the regular expression for the [coverage report](#add-test-coverage-results-to-a-merge-request-deprecated)
that each job log is matched against. This means that each job in the
pipeline can have the test coverage percentage value defined.
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
index 77a666c0cca..fbdf226181b 100644
--- a/doc/ci/quick_start/index.md
+++ b/doc/ci/quick_start/index.md
@@ -12,7 +12,7 @@ Use this document to get started with [GitLab CI/CD](../index.md).
Before you start, make sure you have:
- A project in GitLab that you would like to use CI/CD for.
-- The [Maintainer or Owner role](../../user/permissions.md) for the project.
+- The Maintainer or Owner role for the project.
If you are migrating from another CI/CD tool, view this documentation:
diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md
index d31fb5561e9..9312f4a8850 100644
--- a/doc/ci/resource_groups/index.md
+++ b/doc/ci/resource_groups/index.md
@@ -58,7 +58,7 @@ can still run `build` jobs concurrently for maximizing the pipeline efficiency.
- The basic knowledge of the [GitLab CI/CD pipelines](../pipelines/index.md)
- The basic knowledge of the [GitLab Environments and Deployments](../environments/index.md)
-- [Developer role](../../user/permissions.md) (or above) in the project to configure CI/CD pipelines.
+- At least the Developer role for the project to configure CI/CD pipelines.
### Limitations
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 37005939eb7..ed29b33bc3a 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference
---
# Review Apps **(FREE)**
@@ -73,7 +72,7 @@ you can copy and paste into `.gitlab-ci.yml` as a starting point.
Prerequisite:
-- You need at least the Developer [role](../../user/permissions.md) for the project.
+- You need at least the Developer role for the project.
To use the Review Apps template:
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index d826b28acce..60e21653a45 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -160,7 +160,7 @@ the GitLab instance. To determine this:
### 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
+you must have the Owner role for the
project.
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
@@ -187,7 +187,7 @@ 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/index.md#tags).
-To change this, you must have the [Owner role](../../user/permissions.md#project-members-permissions) for the project.
+To change this, you must have the Owner role for the project.
To make a runner pick untagged jobs:
@@ -291,6 +291,7 @@ globally or for individual jobs:
- [`GIT_CHECKOUT`](#git-checkout)
- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
+- [`GIT_SUBMODULE_UPDATE_FLAGS`](#git-submodule-update-flags)
- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
- [`TRANSFER_METER_FREQUENCY`](#artifact-and-cache-settings) (artifact/cache meter update frequency)
@@ -331,10 +332,6 @@ 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
@@ -382,6 +379,8 @@ For this feature to work correctly, the submodules must be configured
- a relative path to another repository on the same GitLab server. See the
[Git submodules](../git_submodules.md) documentation.
+You can provide additional flags to control advanced behavior using [`GIT_SUBMODULE_UPDATE_FLAGS`](#git-submodule-update-flags).
+
### Git checkout
> Introduced in GitLab Runner 9.3.
@@ -442,14 +441,14 @@ script:
> [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
+Use the `GIT_FETCH_EXTRA_FLAGS` variable to control the behavior of
`git fetch`. You can set it globally or per-job in the [`variables`](../yaml/index.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).
+- [`GIT_DEPTH`](#shallow-cloning).
- The list of [refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec).
- A remote called `origin`.
@@ -475,6 +474,47 @@ git fetch origin $REFSPECS --depth 50 --prune
Where `$REFSPECS` is a value provided to the runner internally by GitLab.
+### Git submodule update flags
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3192) in GitLab Runner 14.8.
+
+Use the `GIT_SUBMODULE_UPDATE_FLAGS` variable to control the behavior of `git submodule update`
+when [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy) is set to either `normal` or `recursive`.
+You can set it globally or per-job in the [`variables`](../yaml/index.md#variables) section.
+
+`GIT_SUBMODULE_UPDATE_FLAGS` accepts all options of the
+[`git submodule update`](https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-update--init--remote-N--no-fetch--no-recommend-shallow-f--force--checkout--rebase--merge--referenceltrepositorygt--depthltdepthgt--recursive--jobsltngt--no-single-branch--ltpathgt82308203)
+subcommand. However, note that `GIT_SUBMODULE_UPDATE_FLAGS` flags are appended after a few default flags:
+
+- `--init`, if [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy) was set to `normal` or `recursive`.
+- `--recursive`, if [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy) was set to `recursive`.
+- [`GIT_DEPTH`](#shallow-cloning). See the default value below.
+
+Git honors the last occurrence of a flag in the list of arguments, so manually
+providing them in `GIT_SUBMODULE_UPDATE_FLAGS` will also override these default flags.
+
+You can use this variable to fetch the latest remote `HEAD` instead of the commit tracked,
+in the repository, or to speed up the checkout by fetching submodules in multiple parallel jobs:
+
+```yaml
+variables:
+ GIT_SUBMODULE_STRATEGY: recursive
+ GIT_SUBMODULE_UPDATE_FLAGS: --remote --jobs 4
+script:
+ - ls -al .git/modules/
+```
+
+The configuration above results in `git submodule update` being called this way:
+
+```shell
+git submodule update --init --depth 50 --recursive --remote --jobs 4
+```
+
+WARNING:
+You should be aware of the implications for the security, stability, and reproducibility of
+your builds when using the `--remote` flag. In most cases, it is better to explicitly track
+submodule commits as designed, and update them using an auto-remediation/dependency bot.
+
### Shallow cloning
> Introduced in GitLab 8.9 as an experimental feature.
diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md
index f76a767abec..7cfd8e50f6c 100644
--- a/doc/ci/runners/runners_scope.md
+++ b/doc/ci/runners/runners_scope.md
@@ -55,7 +55,7 @@ To enable shared runners:
### 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
+You must have the Owner role for the project
or group.
To disable shared runners for a project:
@@ -144,7 +144,7 @@ Group runners process jobs by using a first in, first out ([FIFO](https://en.wik
### 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.
+You must have the Owner role for the group.
To create a group runner:
@@ -160,7 +160,7 @@ To create a group runner:
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.
+You must have the Owner role 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.
@@ -183,7 +183,7 @@ From this page, you can edit, pause, and remove runners from the group, its subg
### 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.
+You must have the Owner role 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.
@@ -213,7 +213,7 @@ 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.
+You must have the Owner role for the project.
To create a specific runner:
@@ -227,7 +227,7 @@ To create a specific runner:
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
+- You must have the Owner role for the
project.
- The specific runner must not be [locked](#prevent-a-specific-runner-from-being-enabled-for-other-projects).
diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md
index 40c4deb51aa..bfe408f4485 100644
--- a/doc/ci/runners/saas/macos_saas_runner.md
+++ b/doc/ci/runners/saas/macos_saas_runner.md
@@ -12,7 +12,7 @@ Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS
of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
build environment.
-SaaS runners on macOS are in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+SaaS runners on macOS are in [Beta](../../../policy/alpha-beta-support.md#beta-features)
and shouldn't be relied upon for mission-critical production jobs.
## Quickstart
diff --git a/doc/ci/runners/saas/windows_saas_runner.md b/doc/ci/runners/saas/windows_saas_runner.md
index b08be14dbc3..dddb3afee7c 100644
--- a/doc/ci/runners/saas/windows_saas_runner.md
+++ b/doc/ci/runners/saas/windows_saas_runner.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# SaaS runners on Windows (beta) **(FREE SAAS)**
-SaaS runners on Windows are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+SaaS runners on Windows are in [beta](../../../policy/alpha-beta-support.md#beta-features)
and shouldn't be used for production workloads.
During this beta period, the [shared runner quota for CI/CD minutes](../../pipelines/cicd_minutes.md)
@@ -15,14 +15,14 @@ change when the beta period ends, as discussed in this [related issue](https://g
Windows 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)
+[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/blob/main/docs/README.md)
developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
Windows 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/main/cookbooks/preinstalled-software/README.md).
We want to keep iterating to get Windows runners in a stable state and
-[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+[generally available](../../../policy/alpha-beta-support.md#generally-available-ga).
You can follow our work towards this goal in the
[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
@@ -127,7 +127,7 @@ test:
## Limitations and known issues
- All the limitations mentioned in our [beta
- definition](https://about.gitlab.com/handbook/product/#beta).
+ definition](../../../policy/alpha-beta-support.md#beta-features).
- 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 runner fleet during the beta. In a future
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index c0a763c80f0..ea0c0d9cc84 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -1,6 +1,6 @@
---
-stage: Configure
-group: Configure
+stage: Verify
+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: concepts, howto
---
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 51df8c102f7..d14027cb1ef 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -260,10 +260,12 @@ test:
| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
| `alias` (1) | no | 9.4 | Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
-| `variables` | no | 14.5 | Additional environment variables that are passed exclusively to the service. The syntax is the same as [Job Variables](../variables/index.md). |
+| `variables` (2) | no | 14.5 | Additional environment variables that are passed exclusively to the service. The syntax is the same as [Job Variables](../variables/index.md). |
(1) Alias support for the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229) in GitLab Runner 12.8, and is only available for Kubernetes version 1.7 or later.
+(2) Service variables support for the Docker and the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3158) in GitLab Runner 14.8.
+
## Starting multiple services from the same image
> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
@@ -387,7 +389,7 @@ time.
## Debug a job locally
The following commands are run without root privileges. You should be
-able to run Docker with your regular user account.
+able to run Docker with your user account.
First start with creating a file named `build_script`:
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 384bfc10779..3ef25a4924b 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -20,7 +20,7 @@ use external test planning tools, which require additional overhead, context swi
Prerequisite:
-- You must have at least the Reporter [role](../../user/permissions.md).
+- You must have at least the Reporter role.
To create a test case in a GitLab project:
@@ -36,7 +36,7 @@ issue list with a search query, including labels or the test case's title.
Prerequisite:
-- You must have at least the Guest [role](../../user/permissions.md).
+- You must have at least the Guest role.
To view a test case:
@@ -51,7 +51,7 @@ You can edit a test case's title and description.
Prerequisite:
-- You must have at least the Reporter [role](../../user/permissions.md).
+- You must have at least the Reporter role.
- Users demoted to the Guest role can continue to edit the test cases they created
when they were in the higher role.
@@ -68,7 +68,7 @@ When you want to stop using a test case, you can archive it. You can [reopen an
Prerequisite:
-- You must have at least the Reporter [role](../../user/permissions.md).
+- You must have at least the Reporter role.
To archive a test case, on the test case's page, select the **Archive test case** button.
@@ -81,6 +81,6 @@ To view archived test cases:
If you decide to start using an archived test case again, you can reopen it.
-You must have at least the Reporter [role](../../user/permissions.md).
+You must have at least the Reporter role.
To reopen an archived test case, on the test case's page, select **Reopen test case**.
diff --git a/doc/ci/triggers/index.md b/doc/ci/triggers/index.md
index 1b648a486ef..2c916ba092c 100644
--- a/doc/ci/triggers/index.md
+++ b/doc/ci/triggers/index.md
@@ -22,7 +22,7 @@ to authenticate an API call. The token impersonates a user's project access and
Prerequisite:
-- You must have at least the [Maintainer role](../../user/permissions.md) for the project.
+- You must have at least the Maintainer role for the project.
To create a trigger token:
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 4d550f6da13..81cb924532c 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -36,7 +36,7 @@ file is correct. Paste in full `.gitlab-ci.yml` files or individual jobs configu
to verify the basic syntax.
When a `.gitlab-ci.yml` file is present in a project, you can also use the CI Lint
-tool to [simulate the creation of a full pipeline](lint.md#pipeline-simulation).
+tool to [simulate the creation of a full pipeline](lint.md#simulate-a-pipeline).
It does deeper verification of the configuration syntax.
## Verify variables
@@ -69,12 +69,12 @@ if you are using that type:
and run separate pipelines in the same project. You can also
[dynamically generate the child pipeline's configuration](pipelines/parent_child_pipelines.md#dynamic-child-pipelines)
at runtime.
-- [Pipelines for Merge Requests](pipelines/merge_request_pipelines.md): Run a pipeline
+- [Merge request pipelines](pipelines/merge_request_pipelines.md): Run a pipeline
in the context of a merge request.
- - [Pipelines for Merge Results](pipelines/pipelines_for_merged_results.md):
- Pipelines for merge requests that run on the combined source and target branch
- - [Merge Trains](pipelines/merge_trains.md):
- Multiple pipelines for merged results that queue and run automatically before
+ - [Merged results pipelines](pipelines/merged_results_pipelines.md):
+ Merge request pipelines that run on the combined source and target branch
+ - [Merge trains](pipelines/merge_trains.md):
+ Multiple merged results pipelines that queue and run automatically before
changes are merged.
### Troubleshooting Guides for CI/CD features
@@ -173,8 +173,8 @@ a branch to its remote repository. To illustrate the problem, suppose you've had
This occurs because the previous pipeline cannot find a checkout-SHA (which is associated with the pipeline record)
from the `example` branch that the commit history has already been overwritten by the force-push.
-Similarly, [Pipelines for merged results](pipelines/pipelines_for_merged_results.md)
-might have failed intermittently due to [the same reason](pipelines/pipelines_for_merged_results.md#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error).
+Similarly, [Merged results pipelines](pipelines/merged_results_pipelines.md)
+might have failed intermittently due to [the same reason](pipelines/merged_results_pipelines.md#pipelines-fail-intermittently-with-a-fatal-reference-is-not-a-tree-error).
As of GitLab 12.4, we've improved this behavior by persisting pipeline refs exclusively.
To illustrate its life cycle:
@@ -192,6 +192,21 @@ To illustrate its life cycle:
The merge request pipeline widget shows information about the pipeline status in
a merge request. It's displayed above the [ability to merge status widget](#merge-request-status-messages).
+#### "Checking ability to merge automatically" message
+
+There is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/229352)
+where a merge request can be stuck with the `Checking ability to merge automatically`
+message.
+
+If your merge request has this message and it does not disappear after a few minutes,
+you can try one of these workarounds:
+
+- Refresh the merge request page.
+- Close & Re-open the merge request.
+- Rebase the merge request with the `/rebase` [quick action](../user/project/quick_actions.md).
+- If you have already confirmed the merge request is ready to be merged, you can merge
+ it with the `/merge` quick action.
+
#### "Checking pipeline status" message
This message is shown when the merge request has no pipeline associated with the
@@ -226,10 +241,10 @@ This also applies if the pipeline has not been created yet, or if you are waitin
for an external CI service. If you don't use pipelines for your project, then you
should disable **Pipelines must succeed** so you can accept merge requests.
-### "The pipeline for this merge request did not complete. Push a new commit to fix the failure or check the troubleshooting documentation to see other possible actions." message
+#### "Merge blocked: pipeline must succeed. Push a new commit that fixes the failure" message
This message is shown if the [merge request pipeline](pipelines/merge_request_pipelines.md),
-[merged results pipeline](pipelines/pipelines_for_merged_results.md),
+[merged results pipeline](pipelines/merged_results_pipelines.md),
or [merge train pipeline](pipelines/merge_trains.md)
has failed or been canceled.
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index 55fd8c1eb49..e2de47c6c62 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference
---
# Unit test reports **(FREE)**
@@ -21,7 +20,7 @@ report on the merge request so that it's easier and faster to identify the
failure without having to check the entire log. Unit test reports currently
only support test reports in the JUnit report format.
-If you don't use Merge Requests but still want to see the unit test report
+If you don't use merge requests but still want to see the unit test report
output without searching through job logs, the full
[Unit test reports](#viewing-unit-test-reports-on-gitlab) are available
in the pipeline detail view.
@@ -67,7 +66,7 @@ execution time and the error output.
### Number of recent failures
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in Merge Requests in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in merge requests in GitLab 13.7.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268249) in GitLab 13.8.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235525) in Test Reports in GitLab 13.9.
@@ -76,7 +75,7 @@ If a test failed in the project's default branch in the last 14 days, a message
## How to set it up
-To enable the Unit test reports in merge requests, you need to add
+To enable the Unit test reports in merge requests, you must add
[`artifacts:reports:junit`](yaml/artifacts_reports.md#artifactsreportsjunit)
in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
The reports must be `.xml` files, otherwise [GitLab returns an Error 500](https://gitlab.com/gitlab-org/gitlab/-/issues/216575).
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index 7ce58b015ca..ba8451110eb 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -154,7 +154,7 @@ job:
### Add a CI/CD variable to a project
You can add CI/CD variables to a project's settings. Only project members with the
-[Maintainer role](../../user/permissions.md#project-members-permissions)
+Maintainer role
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.
@@ -233,7 +233,7 @@ inherited.
> - [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,
-add an instance CI/CD variable. You must have the [Administrator role](../../user/permissions.md).
+add an instance CI/CD variable. You must have administrator access.
You can define instance variables via the UI or [API](../../api/instance_level_ci_variables.md).
@@ -372,7 +372,7 @@ You can protect a project, group or instance CI/CD variable so it is only passed
to pipelines running on [protected branches](../../user/project/protected_branches.md)
or [protected tags](../../user/project/protected_tags.md).
-[Pipelines for merge requests](../pipelines/merge_request_pipelines.md) do not have access to protected variables.
+[Merge request pipelines](../pipelines/merge_request_pipelines.md) do not have access to protected variables.
An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/28002) regarding this limitation.
To protect a variable:
@@ -651,9 +651,11 @@ which variables take precedence.
The order of precedence for variables is (from highest to lowest):
-1. [Trigger variables](../triggers/index.md#pass-cicd-variables-in-the-api-call),
- [scheduled pipeline variables](../pipelines/schedules.md#using-variables),
- and [manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
+1. These all have the same (highest) precedence:
+ - [Trigger variables](../triggers/index.md#pass-cicd-variables-in-the-api-call).
+ - [Scheduled pipeline variables](../pipelines/schedules.md#using-variables).
+ - [Manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
+ - Variables added when [creating a pipeline with the API](../../api/pipelines.md#create-a-new-pipeline).
1. Project [variables](#custom-cicd-variables).
1. Group [variables](#add-a-cicd-variable-to-a-group).
1. Instance [variables](#add-a-cicd-variable-to-an-instance).
@@ -900,7 +902,7 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8.
You can restrict access to debug logging. When restricted, only users with
-[developer or higher permissions](../../user/permissions.md#project-members-permissions)
+at least the Developer role
can view job logs when debug logging is enabled with a variable in:
- The [`.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 60888cd9b97..0f3461b3674 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -27,7 +27,7 @@ There are also a number of [variables you can use to configure runner behavior](
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | The top-level directory where builds are executed. |
| `CI_COMMIT_AUTHOR` | 13.11 | all | The author of the commit in `Name <email>` format. |
-| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. |
+| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in merge request pipelines. |
| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Available in branch pipelines, including pipelines for the default branch. Not available in merge request pipelines or tag pipelines. |
| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit. If the title is shorter than 100 characters, the message without the first line. |
| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. |
@@ -63,7 +63,7 @@ There are also a number of [variables you can use to configure runner behavior](
| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the Docker image running the job. |
| `CI_JOB_JWT` | 12.10 | all | A RS256 JSON web token to authenticate with third party systems that support JWT authentication, for example [HashiCorp's Vault](../secrets/index.md). |
| `CI_JOB_JWT_V1` | 14.6 | all | The same value as `CI_JOB_JWT`. |
-| `CI_JOB_JWT_V2` | 14.6 | all | [**alpha:**](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) A newly formatted RS256 JSON web token to increase compatibility. Similar to `CI_JOB_JWT`, except the issuer (`iss`) claim is changed from `gitlab.com` to `https://gitlab.com`, `sub` has changed from `job_id` to a string that contains the project path, and an `aud` claim is added. Format is subject to change. Be aware, the `aud` field is a constant value. Trusting JWTs in multiple relying parties can lead to [one RP sending a JWT to another one and acting maliciously as a job](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72555#note_769112331). |
+| `CI_JOB_JWT_V2` | 14.6 | all | [**alpha:**](../../policy/alpha-beta-support.md#alpha-features) A newly formatted RS256 JSON web token to increase compatibility. Similar to `CI_JOB_JWT`, except the issuer (`iss`) claim is changed from `gitlab.com` to `https://gitlab.com`, `sub` has changed from `job_id` to a string that contains the project path, and an `aud` claim is added. Format is subject to change. Be aware, the `aud` field is a constant value. Trusting JWTs in multiple relying parties can lead to [one RP sending a JWT to another one and acting maliciously as a job](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72555#note_769112331). |
| `CI_JOB_MANUAL` | 8.12 | all | `true` if a job was started manually. |
| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job. |
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the job's stage. |
@@ -148,12 +148,12 @@ These variables are available when:
| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request. For example, `http://192.168.10.15:3000/namespace/awesome-project`. |
| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request. For example, `refs/merge-requests/1/head`. |
| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request. |
-| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/pipelines_for_merged_results.md). **(PREMIUM)** |
+| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request. |
| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request. |
| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request. |
| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request. |
-| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/pipelines_for_merged_results.md). **(PREMIUM)** |
+| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request. |
| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | The event type of the merge request. Can be `detached`, `merged_result` or `merge_train`. |
| `CI_MERGE_REQUEST_DIFF_ID` | 13.7 | all | The version of the merge request diff. |
diff --git a/doc/ci/yaml/artifacts_reports.md b/doc/ci/yaml/artifacts_reports.md
index 25fb861cfb7..e010dd21b9e 100644
--- a/doc/ci/yaml/artifacts_reports.md
+++ b/doc/ci/yaml/artifacts_reports.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
---
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index 3c94ddb3c14..34db6c61d0b 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -217,6 +217,69 @@ default:
- echo "Job complete."
```
+### Use nested includes with duplicate `includes` entries
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28987) in GitLab 14.8
+
+Nested includes can include the same configuration file. The duplicate configuration
+file is included multiple times, but the effect is the same as if it was only
+included once.
+
+For example, with the following nested includes, where `defaults.gitlab-ci.yml`
+is included multiple times:
+
+- Contents of the `.gitlab-ci.yml` file:
+
+ ```yaml
+ include:
+ - template: defaults.gitlab-ci.yml
+ - local: unit-tests.gitlab-ci.yml
+ - local: smoke-tests.gitlab-ci.yml
+ ```
+
+- Contents of the `defaults.gitlab-ci.yml` file:
+
+ ```yaml
+ default:
+ before_script: default-before-script.sh
+ retry: 2
+ ```
+
+- Contents of the `unit-tests.gitlab-ci.yml` file:
+
+ ```yaml
+ include:
+ - template: defaults.gitlab-ci.yml
+
+ unit-test-job:
+ script: unit-test.sh
+ retry: 0
+ ```
+
+- Contents of the `smoke-tests.gitlab-ci.yml` file:
+
+ ```yaml
+ include:
+ - template: defaults.gitlab-ci.yml
+
+ smoke-test-job:
+ script: smoke-test.sh
+ ```
+
+The final configuration would be:
+
+```yaml
+unit-test-job:
+ before_script: default-before-script.sh
+ script: unit-test.sh
+ retry: 0
+
+smoke-test-job:
+ before_script: default-before-script.sh
+ script: smoke-test.sh
+ retry: 2
+```
+
## Use variables with `include`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/284883) in GitLab 13.8.
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 4530e2675c4..d9ea5498b63 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -415,7 +415,7 @@ and the pipeline is for either:
- You can use the [`workflow:rules` templates](workflow.md#workflowrules-templates) to import
a preconfigured `workflow: rules` entry.
- [Common `if` clauses for `workflow:rules`](workflow.md#common-if-clauses-for-workflowrules).
-- [Use `rules` to run pipelines for merge requests](../pipelines/merge_request_pipelines.md#use-rules-to-add-jobs).
+- [Use `rules` to run merge request pipelines](../pipelines/merge_request_pipelines.md#use-rules-to-add-jobs).
#### `workflow:rules:variables`
@@ -939,7 +939,7 @@ rspec:
Use `artifacts:untracked` to add all Git untracked files as artifacts (along
with the paths defined in `artifacts:paths`). `artifacts:untracked` ignores configuration
-in the repository's `.gitignore` file.
+in the repository's `.gitignore`, so matching artifacts in `.gitignore` are included.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
@@ -974,7 +974,7 @@ failure.
- `on_success` (default): Upload artifacts only when the job succeeds.
- `on_failure`: Upload artifacts only when the job fails.
-- `always`: Always upload artifacts. For example, when
+- `always`: Always upload artifacts (except when jobs time out). For example, when
[uploading artifacts](../unit_test_reports.md#viewing-junit-screenshots-on-gitlab)
required to troubleshoot failing tests.
@@ -1322,12 +1322,14 @@ Use `coverage` with a custom regular expression to configure how code coverage
is extracted from the job output. The coverage is shown in the UI if at least one
line in the job output matches the regular expression.
-To extract the code coverage value in the matching line, GitLab uses this
-regular expression: `\d+(\.\d+)?`.
+To extract the code coverage value from the match, GitLab uses
+this smaller regular expression: `\d+(\.\d+)?`.
**Possible inputs**:
-- A regular expression. Must start and end with `/`.
+- A regular expression. Must start and end with `/`. Must match the coverage number.
+ May match surrounding text as well, so you don't need to use a regular expression character group
+ to capture the exact number.
**Example of `coverage`**:
@@ -1339,14 +1341,20 @@ job1:
In this example:
-1. GitLab checks the job log for a line that matches the regular expression. A line
- like `Code coverage: 67.89` would match.
-1. GitLab then checks the line to find a match to `\d+(\.\d+)?`. The sample matching
- line above gives a code coverage of `67.89`.
+1. GitLab checks the job log for a match with the regular expression. A line
+ like `Code coverage: 67.89% of lines covered` would match.
+1. GitLab then checks the matched fragment to find a match to `\d+(\.\d+)?`.
+ The sample matching line above gives a code coverage of `67.89`.
**Additional details**:
-- If there is more than one matched line in the job output, the last line is used.
+- Coverage regular expressions set in `gitlab-ci.yml` take precedence over coverage regular expression set in the
+ [GitLab UI](../pipelines/settings.md#add-test-coverage-results-to-a-merge-request-deprecated).
+- If there is more than one matched line in the job output, the last line is used
+ (the first result of reverse search).
+- If there are multiple matches in a single line, the last match is searched
+ for the coverage number.
+- If there are multiple coverage numbers found in the matched fragment, the first number is used.
- Leading zeros are removed.
- Coverage output from [child pipelines](../pipelines/parent_child_pipelines.md)
is not recorded or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818)
@@ -1467,7 +1475,7 @@ Use `environment` to define the [environment](../environments/index.md) that a j
formats:
- Plain text, including letters, digits, spaces, and these characters: `-`, `_`, `/`, `$`, `{`, `}`.
-- CI/CD variables, including predefined, secure, or variables defined in the
+- CI/CD variables, including predefined, project, group, instance, or variables defined in the
`.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
**Example of `environment`**:
@@ -1496,7 +1504,7 @@ Common environment names are `qa`, `staging`, and `production`, but you can use
formats:
- Plain text, including letters, digits, spaces, and these characters: `-`, `_`, `/`, `$`, `{`, `}`.
-- CI/CD variables, including predefined, secure, or variables defined in the
+- CI/CD variables, including predefined, project, group, instance, or variables defined in the
`.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
**Example of `environment:name`**:
@@ -1518,7 +1526,7 @@ Set a URL for an [environment](../environments/index.md).
**Possible inputs**: A single URL, in one of these formats:
- Plain text, like `https://prod.example.com`.
-- CI/CD variables, including predefined, secure, or variables defined in the
+- CI/CD variables, including predefined, project, group, instance, or variables defined in the
`.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
**Example of `environment:url`**:
@@ -2366,7 +2374,7 @@ pipeline based on branch names or pipeline types.
| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
| `external` | When you use CI services other than GitLab. |
| `external_pull_requests` | 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_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/pipelines_for_merged_results.md), and [merge trains](../pipelines/merge_trains.md). |
+ | `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/merged_results_pipelines.md), and [merge trains](../pipelines/merge_trains.md). |
| `pipelines` | For [multi-project pipelines](../pipelines/multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api), or the [`trigger`](#trigger) keyword. |
| `pushes` | For pipelines triggered by a `git push` event, including for branches and tags. |
| `schedules` | For [scheduled pipelines](../pipelines/schedules.md). |
@@ -2465,7 +2473,7 @@ Use `changes` in pipelines with the following refs:
- `branches`
- `external_pull_requests`
-- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests))
+- `merge_requests` (see additional details about [using `only:changes` with merge request pipelines](../jobs/job_control.md#use-onlychanges-with-merge-request-pipelines))
**Keyword type**: Job keyword. You can use it only as part of a job.
@@ -2507,7 +2515,7 @@ docker build:
- [`only: changes` and `except: changes` examples](../jobs/job_control.md#onlychanges--exceptchanges-examples).
- If you use `changes` with [only allow merge requests to be merged if the pipeline succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds),
- you should [also use `only:merge_requests`](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests).
+ you should [also use `only:merge_requests`](../jobs/job_control.md#use-onlychanges-with-merge-request-pipelines).
- [Jobs or pipelines can run unexpectedly when using `only: changes`](../jobs/job_control.md#jobs-or-pipelines-run-unexpectedly-when-using-changes).
#### `only:kubernetes` / `except:kubernetes`
@@ -2654,6 +2662,7 @@ deploystacks: [vultr, processing]
- [Run a one-dimensional matrix of parallel jobs](../jobs/job_control.md#run-a-one-dimensional-matrix-of-parallel-jobs).
- [Run a matrix of triggered parallel jobs](../jobs/job_control.md#run-a-matrix-of-parallel-trigger-jobs).
+- [Select different runner tags for each parallel matrix job](../jobs/job_control.md#select-different-runner-tags-for-each-parallel-matrix-job).
### `release`
@@ -3079,7 +3088,7 @@ job:
- [Common `if` expressions for `rules`](../jobs/job_control.md#common-if-clauses-for-rules).
- [Avoid duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines).
-- [Use `rules` to run pipelines for merge requests](../pipelines/merge_request_pipelines.md#use-rules-to-add-jobs).
+- [Use `rules` to run merge request pipelines](../pipelines/merge_request_pipelines.md#use-rules-to-add-jobs).
#### `rules:changes`
@@ -3569,6 +3578,7 @@ In this example, only runners with *both* the `ruby` and `postgres` tags can run
**Related topics**:
- [Use tags to control which jobs a runner can run](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run).
+- [Select different runner tags for each parallel matrix job](../jobs/job_control.md#select-different-runner-tags-for-each-parallel-matrix-job).
### `timeout`
@@ -3642,7 +3652,7 @@ trigger_job:
- Jobs with `trigger` can only use a [limited set of keywords](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
- or [`after_script`](#after_script).
+ or [`after_script`](#after_script). Also, [`environment`](#environment) is not supported with `trigger`.
- You [cannot use the API to start `when:manual` trigger jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/284086).
- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index ca1e79c2395..4bffcbca1cc 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -4,7 +4,7 @@ group: Pipeline Authoring
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab CI/CD script syntax **(FREE)**
+# Format scripts and job logs **(FREE)**
You can use special syntax in [`script`](index.md#script) sections to:
diff --git a/doc/ci/yaml/workflow.md b/doc/ci/yaml/workflow.md
index 332214638d8..b46d504edfa 100644
--- a/doc/ci/yaml/workflow.md
+++ b/doc/ci/yaml/workflow.md
@@ -126,7 +126,7 @@ makes your pipelines run for branches and tags.
Branch pipeline status is displayed in merge requests that use the branch
as a source. However, this pipeline type does not support any features offered by
[merge request pipelines](../pipelines/merge_request_pipelines.md), like
-[pipelines for merged results](../pipelines/pipelines_for_merged_results.md)
+[merged results pipelines](../pipelines/merged_results_pipelines.md)
or [merge trains](../pipelines/merge_trains.md).
This template intentionally avoids those features.
@@ -140,7 +140,7 @@ include:
The [`MergeRequest-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml)
makes your pipelines run for the default branch, tags, and
all types of merge request pipelines. Use this template if you use any of the
-the [pipelines for merge requests features](../pipelines/merge_request_pipelines.md).
+the [merge request pipelines features](../pipelines/merge_request_pipelines.md).
To [include](index.md#include) it:
diff --git a/doc/development/agent/gitops.md b/doc/development/agent/gitops.md
index 3d59f5bd845..7c741408ae6 100644
--- a/doc/development/agent/gitops.md
+++ b/doc/development/agent/gitops.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/gitops.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/gitops.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/identity.md b/doc/development/agent/identity.md
index 67084a6d995..6caf108a32a 100644
--- a/doc/development/agent/identity.md
+++ b/doc/development/agent/identity.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/index.md b/doc/development/agent/index.md
index 2cb05e2dd8f..474f8a02933 100644
--- a/doc/development/agent/index.md
+++ b/doc/development/agent/index.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md
index 1fff5607de4..a4b29bea838 100644
--- a/doc/development/agent/local.md
+++ b/doc/development/agent/local.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/local.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/local.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/repository_overview.md b/doc/development/agent/repository_overview.md
index 43ea99889c5..8ea9dceb32a 100644
--- a/doc/development/agent/repository_overview.md
+++ b/doc/development/agent/repository_overview.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/repository_overview.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/repository_overview.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/routing.md b/doc/development/agent/routing.md
index 7792d6d56a4..364267a45fe 100644
--- a/doc/development/agent/routing.md
+++ b/doc/development/agent/routing.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/kas_request_routing.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/kas_request_routing.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/agent/user_stories.md b/doc/development/agent/user_stories.md
index ce38064b31b..2ed4bbdc9f6 100644
--- a/doc/development/agent/user_stories.md
+++ b/doc/development/agent/user_stories.md
@@ -1,9 +1,9 @@
---
redirect_to: 'https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/user_stories.md'
-remove_date: '2022-06-24'
+remove_date: '2022-02-01'
---
This file was moved to [another location](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/user_stories.md).
-<!-- This redirect file can be deleted after <2022-06-24>. -->
+<!-- This redirect file can be deleted after <2022-02-01>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/application_slis/index.md b/doc/development/application_slis/index.md
index 87c0bcfede5..adb656761c5 100644
--- a/doc/development/application_slis/index.md
+++ b/doc/development/application_slis/index.md
@@ -57,31 +57,10 @@ Gitlab::Metrics::Sli.initialize_sli(:received_email, [
])
```
-Metrics must be initialized before they get
-scraped for the first time. This could be done at the start time of the
-process that will emit them, in which case we need to pay attention
-not to increase application's boot time too much. This is preferable
-if possible.
-
-Alternatively, if initializing would take too long, this can be done
-during the first scrape. We need to make sure we don't do it for every
-scrape. This can be done as follows:
-
-```ruby
-def initialize_request_slis_if_needed!
- return if Gitlab::Metrics::Sli.initialized?(:rails_request_apdex)
- Gitlab::Metrics::Sli.initialize_sli(:rails_request_apdex, possible_request_labels)
-end
-```
-
-Also pay attention to do it for the different metrics
-endpoints we have. Currently the
-[`WebExporter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/metrics/exporter/web_exporter.rb)
-and the
-[`HealthController`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/health_controller.rb)
-for Rails and
-[`SidekiqExporter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/metrics/exporter/sidekiq_exporter.rb)
-for Sidekiq.
+Metrics must be initialized before they get scraped for the first time.
+This currently happens during the `on_master_start` [life-cycle event](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/cluster/lifecycle_events.rb).
+Since this delays application readiness until metrics initialization returns, make sure the overhead
+this adds is understood and acceptable.
## Tracking operations for an SLI
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 36d3655ba93..e8d04d68565 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -339,7 +339,7 @@ Component statuses are linked to configuration documentation for each component.
### Component list
-| Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) | [GitLab chart](https://docs.gitlab.com/charts/) | [minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | [Source](../install/installation.md) | [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) | [CE/EE](https://about.gitlab.com/install/ce-or-ee/) |
+| Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) | [GitLab chart](https://docs.gitlab.com/charts/) | [minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | [Source](../install/installation.md) | [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) | [CE/EE](https://about.gitlab.com/install/ce-or-ee/) |
|-------------------------------------------------------|----------------------------------------------------------------------|:--------------:|:--------------:|:------------:|:----------------:|:----------:|:------:|:---:|:-------:|
| [Certificate Management](#certificate-management) | TLS Settings, Let's Encrypt | ✅ | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE |
| [Consul](#consul) | Database node discovery, failover | ⚙ | ✅ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
@@ -528,7 +528,7 @@ You can use it either for personal or business websites, such as portfolios, doc
#### GitLab Runner
-- [Project page](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/README.md)
+- [Project page](https://gitlab.com/gitlab-org/gitlab-runner/blob/main/README.md)
- Configuration:
- [Omnibus](https://docs.gitlab.com/runner/)
- [Charts](https://docs.gitlab.com/runner/install/kubernetes.html)
diff --git a/doc/development/avoiding_downtime_in_migrations.md b/doc/development/avoiding_downtime_in_migrations.md
index 1d36bbf1212..1de96df327c 100644
--- a/doc/development/avoiding_downtime_in_migrations.md
+++ b/doc/development/avoiding_downtime_in_migrations.md
@@ -399,7 +399,7 @@ migrations:
1. Change the index pattern to `pubsub-sidekiq-inf-gprd*`.
1. Add filter for `json.queue: cronjob:database_batched_background_migration`.
-#### PostgerSQL slow queries log
+#### PostgreSQL slow queries log
Slow queries log keeps track of low queries that took above 1 second to execute. To see them
for batched background migration:
@@ -408,7 +408,7 @@ for batched background migration:
1. Change the index pattern to `pubsub-postgres-inf-gprd*`.
1. Add filter for `json.endpoint_id.keyword: Database::BatchedBackgroundMigrationWorker`.
1. Optional. To see only updates, add a filter for `json.command_tag.keyword: UPDATE`.
-1. Optional. To see only failed statements, add a filter for `json.error_severiry.keyword: ERROR`.
+1. Optional. To see only failed statements, add a filter for `json.error_severity.keyword: ERROR`.
1. Optional. Add a filter by table name.
#### Grafana dashboards
diff --git a/doc/development/cached_queries.md b/doc/development/cached_queries.md
index 4f82d721164..492c8d13600 100644
--- a/doc/development/cached_queries.md
+++ b/doc/development/cached_queries.md
@@ -163,5 +163,5 @@ factors help improve the overall execution time:
## For more information
- [Metrics that would help us detect the potential N+1 Cached SQL calls](https://gitlab.com/gitlab-org/gitlab/-/issues/259007)
-- [Merge Request performance guidelines for cached queries](merge_request_performance_guidelines.md#cached-queries)
+- [Merge request performance guidelines for cached queries](merge_request_performance_guidelines.md#cached-queries)
- [Improvements for biggest offenders](https://gitlab.com/groups/gitlab-org/-/epics/4508)
diff --git a/doc/development/cascading_settings.md b/doc/development/cascading_settings.md
index f9c96e414d0..76ab2c6e693 100644
--- a/doc/development/cascading_settings.md
+++ b/doc/development/cascading_settings.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/changelog.md b/doc/development/changelog.md
index 7c4a600e1fa..b51db69c2f7 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -101,7 +101,9 @@ EE: true
- _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one.
- Any [GLEX experiment](experiment_guide/gitlab_experiment.md) changes **should not** have a changelog entry.
-- [Modifying](feature_flags/#changelog) a feature flag (flag removal, default-on setting).
+
+For more information, see
+[how to handle changelog entries with feature flags](feature_flags/index.md#changelog).
## Writing good changelog entries
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index 17a70393c96..2779b457fb9 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -27,7 +27,7 @@ On the left side we have the events that can trigger a pipeline based on various
- A `git push` is the most common event that triggers a pipeline.
- The [Web API](../../api/pipelines.md#create-a-new-pipeline).
- A user clicking the "Run pipeline" button in the UI.
-- When a [merge request is created or updated](../../ci/pipelines/merge_request_pipelines.md#pipelines-for-merge-requests).
+- When a [merge request is created or updated](../../ci/pipelines/merge_request_pipelines.md).
- When an MR is added to a [Merge Train](../../ci/pipelines/merge_trains.md#merge-trains).
- A [scheduled pipeline](../../ci/pipelines/schedules.md#pipeline-schedules).
- When project is [subscribed to an upstream project](../../ci/pipelines/multi_project_pipelines.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt).
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index b1252b86cc0..d7edad842b8 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
-# Development guide for GitLab CI/CD templates
+# Development guide for GitLab CI/CD templates **(FREE)**
This document explains how to develop [GitLab CI/CD templates](../../ci/examples/index.md).
@@ -18,6 +18,7 @@ Before submitting a merge request with a new or updated CI/CD template, you must
- Name the template following the `*.gitlab-ci.yml` format.
- Use valid [`.gitlab-ci.yml` syntax](../../ci/yaml/index.md). Verify it's valid
with the [CI/CD lint tool](../../ci/lint.md).
+- [Add template metrics](#add-metrics).
- Include [a changelog](../changelog.md) if the merge request introduces a user-facing change.
- Follow the [template review process](#contribute-cicd-template-merge-requests).
- (Optional but highly recommended) Test the template in an example GitLab project
@@ -382,6 +383,77 @@ you must:
This information is important for users when [a stable template](#stable-version)
is updated in a major version GitLab release.
+### Add metrics
+
+Every CI/CD template must also have metrics defined to track their use.
+
+To add a metric definition for a new template:
+
+1. Install and start the [GitLab GDK](https://gitlab.com/gitlab-org/gitlab-development-kit#installation).
+1. In the `gitlab` directory in your GDK, check out the branch that contains the new template.
+1. [Add the template inclusion event](../service_ping/implement.md#add-new-events)
+ with this Rake task:
+
+ ```shell
+ bin/rake gitlab:usage_data:generate_ci_template_events
+ ```
+
+ The task adds a section like the following to [`lib/gitlab/usage_data_counters/known_events/ci_templates.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/ci_templates.yml):
+
+ ```yaml
+ - name: p_ci_templates_my_template_name
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ ```
+
+1. Copy the value of `name` from the new YAML section, and add it to the weekly
+ and monthly CI/CD template total count metrics:
+ - [`config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml)
+ - [`config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml)
+
+1. Use the same `name` as above as the last argument in the following command to
+ [add new metric definitions](../service_ping/metrics_dictionary.md#metrics-added-dynamic-to-service-ping-payload):
+
+ ```shell
+ bundle exec rails generate gitlab:usage_metric_definition:redis_hll ci_templates <template_metric_event_name>
+ ```
+
+ The output should look like:
+
+ ```shell
+ $ bundle exec rails generate gitlab:usage_metric_definition:redis_hll ci_templates p_ci_templates_my_template_name
+ create config/metrics/counts_7d/20220120073740_p_ci_templates_my_template_name_weekly.yml
+ create config/metrics/counts_28d/20220120073746_p_ci_templates_my_template_name_monthly.yml
+ ```
+
+1. Edit both newly generated files as follows:
+
+ - `name:` and `performance_indicator_type:`: Delete (not needed).
+ - `introduced_by_url:`: The URL of the MR adding the template.
+ - `data_source:`: Set to `redis_hll`.
+ - All other fields that have no values: Set to empty strings (`''`).
+ - Add the following to the end of each file:
+
+ ```yaml
+ options:
+ events:
+ - p_ci_templates_my_template_name
+ ```
+
+1. Commit and push the changes.
+
+For example, these are the metrics configuration files for the
+[5 Minute Production App template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml):
+
+- The template inclusion event: [`lib/gitlab/usage_data_counters/known_events/ci_templates.yml#L438-L441`](https://gitlab.com/gitlab-org/gitlab/-/blob/dcddbf83c29d1ad0839d55362c1b43888304f453/lib/gitlab/usage_data_counters/known_events/ci_templates.yml#L438-L441)
+- The weekly and monthly metrics definitions:
+ - [`config/metrics/counts_7d/20210901223501_p_ci_templates_5_minute_production_app_weekly.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/1a6eceff3914f240864b2ca15ae2dc076ea67bf6/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml)
+ - [`config/metrics/counts_28d/20210901223505_p_ci_templates_5_minute_production_app_monthly.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml)
+- The metrics count totals:
+ - [`config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml#L19`](https://gitlab.com/gitlab-org/gitlab/-/blob/4e01ef2b094763943348655ef77008aba7a052ae/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml#L19)
+ - [`config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml#L19`](https://gitlab.com/gitlab-org/gitlab/-/blob/4e01ef2b094763943348655ef77008aba7a052ae/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml#L19)
+
## Security
A template could contain malicious code. For example, a template that contains the `export` shell command in a job
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 1ed510c6ad7..3664ca7642a 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -285,7 +285,7 @@ Maintainers should check before merging if the merge request is approved by the
required approvers. If still awaiting further approvals from others, remove yourself as a reviewer then `@` mention the author and explain why in a comment. Stay as reviewer if you're merging the code.
Maintainers must check before merging if the merge request is introducing new
-vulnerabilities, by inspecting the list in the Merge Request
+vulnerabilities, by inspecting the list in the merge request
[Security Widget](../user/application_security/index.md).
When in doubt, a [Security Engineer](https://about.gitlab.com/company/team/) can be involved. The list of detected
vulnerabilities must be either empty or containing:
@@ -296,8 +296,8 @@ vulnerabilities must be either empty or containing:
Maintainers should **never** dismiss vulnerabilities to "empty" the list,
without duly verifying them.
-Note that certain Merge Requests may target a stable branch. These are rare
-events. These types of Merge Requests cannot be merged by the Maintainer.
+Note that certain merge requests may target a stable branch. These are rare
+events. These types of merge requests cannot be merged by the Maintainer.
Instead, these should be sent to the [Release Manager](https://about.gitlab.com/community/release-managers/).
After merging, a maintainer should stay as the reviewer listed on the merge request.
@@ -479,7 +479,7 @@ WARNING:
[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 was created before the merge request was approved, start a new pipeline to ensure that full RSpec suite has been run. You may skip this step only if the merge request does not contain any backend change.
- - If the **latest [Pipeline for Merged Results](../ci/pipelines/pipelines_for_merged_results.md)** finished less than 2 hours ago, you
+ - If the **latest [merged results pipeline](../ci/pipelines/merged_results_pipelines.md)** finished less than 2 hours ago, you
may merge without starting a new pipeline as the merge request is close
enough to `main`.
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
@@ -489,7 +489,7 @@ WARNING:
the squashed commit's default commit message is taken from the merge request title.
You're encouraged to [select a commit with a more informative commit message](../user/project/merge_requests/squash_and_merge.md) before merging.
-Thanks to **Pipeline for Merged Results**, authors no longer have to rebase their
+Thanks to **merged results pipelines**, 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 `main`.
This results in faster review/merge cycles because maintainers don't have to ask
@@ -501,7 +501,7 @@ Merge Results against the latest `main` at the time of the pipeline creation.
WARNING:
**Review all changes thoroughly for malicious code before starting a
-[Pipeline for Merged Results](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project).**
+[merged results pipeline](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project).**
When reviewing merge requests added by wider community contributors:
@@ -510,6 +510,9 @@ When reviewing merge requests added by wider community contributors:
fetching of malicious packages.
- Review links and images, especially in documentation MRs.
- When in doubt, ask someone from `@gitlab-com/gl-security/appsec` to review the merge request **before manually starting any merge request pipeline**.
+- Only set the milestone when the merge request is likely to be included in
+ the current milestone. This is to avoid confusion around when it'll be
+ merged and avoid moving milestone too often when it's not yet ready.
If the MR source branch is more than 1,000 commits behind the target branch:
@@ -599,7 +602,7 @@ Enterprise Edition instance. This has some implications:
- [Background migrations](background_migrations.md) run in Sidekiq, and
should only be done for migrations that would take an extreme amount of
time at GitLab.com scale.
-1. **Sidekiq workers** [cannot change in a backwards-incompatible way](sidekiq_style_guide.md#sidekiq-compatibility-across-updates):
+1. **Sidekiq workers** [cannot change in a backwards-incompatible way](sidekiq/compatibility_across_updates.md):
1. Sidekiq queues are not drained before a deploy happens, so there are
workers in the queue from the previous version of GitLab.
1. If you need to change a method signature, try to do so across two releases,
@@ -670,7 +673,7 @@ Properties of customer critical merge requests:
- It is required that the reviewer(s) and maintainer(s) involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required to prioritize work for those involved on a customer critical merge request so that they have the time available necessary to focus on it.
- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values/) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
-- Customer critical merge requests are required to not reduce security, introduce data-loss risk, reduce availability, nor break existing functionality per the process for [prioritizing technical decisions](https://about.gitlab.com/handbook/engineering/#prioritizing-technical-decisions.md).
+- Customer critical merge requests are required to not reduce security, introduce data-loss risk, reduce availability, nor break existing functionality per the process for [prioritizing technical decisions](https://about.gitlab.com/handbook/engineering/principles/#prioritizing-technical-decisions).
- On customer critical requests, it is _recommended_ that those involved _consider_ coordinating synchronously (Zoom, Slack) in addition to asynchronously (merge requests comments) if they believe this may reduce the elapsed time to merge even though this _may_ sacrifice [efficiency](https://about.gitlab.com/company/culture/all-remote/asynchronous/#evaluating-efficiency.md).
- After a customer critical merge request is merged, a retrospective must be completed with the intention of reducing the frequency of future customer critical merge requests.
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index e85f5dd8349..efa8d4b0c41 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -60,7 +60,7 @@ Check visual design properties using your browser's _elements inspector_ ([Chrom
guidelines.
- _Optionally_ consider [dark mode](../../user/profile/preferences.md#dark-mode). [^1]
- [^1]: You're not required to design for [dark mode](../../user/profile/preferences.md#dark-mode) while the feature is in [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha). The [UX Foundations team](https://about.gitlab.com/direction/ecosystem/foundations/) plans to improve the dark mode in the future. Until we integrate [Pajamas](https://design.gitlab.com/) components into the product and the underlying design strategy is in place to support dark mode, we cannot guarantee that we won't introduce bugs and debt to this mode. At your discretion, evaluate the need to create dark mode patches.
+ [^1]: You're not required to design for [dark mode](../../user/profile/preferences.md#dark-mode) while the feature is in [alpha](../../policy/alpha-beta-support.md#alpha-features). The [UX Foundations team](https://about.gitlab.com/direction/ecosystem/foundations/) plans to improve the dark mode in the future. Until we integrate [Pajamas](https://design.gitlab.com/) components into the product and the underlying design strategy is in place to support dark mode, we cannot guarantee that we won't introduce bugs and debt to this mode. At your discretion, evaluate the need to create dark mode patches.
### States
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index ec05f75c709..ea54f36a7e5 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -91,7 +91,7 @@ Sign up for the mailing list, answer GitLab questions on StackOverflow or respon
If you would like to contribute to GitLab:
- Issues with the
- [`~Accepting merge requests` label](issue_workflow.md#label-for-community-contributors)
+ [`~Seeking community contributions` label](issue_workflow.md#label-for-community-contributors)
are a great place to start.
- Optimizing our tests is another great opportunity to contribute. You can use
[RSpec profiling statistics](https://gitlab-org.gitlab.io/rspec_profiling_stats/) to identify
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 6a7bbb2e302..ad8403d242c 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -57,6 +57,10 @@ Most issues will have labels for at least one of the following:
- Priority: `~"priority::1"`, `~"priority::2"`, `~"priority::3"`, `~"priority::4"`
- Severity: ~`"severity::1"`, `~"severity::2"`, `~"severity::3"`, `~"severity::4"`
+Please add `~"breaking change"` label if the issue can be considered as a [breaking change](index.md#breaking-changes).
+
+Please add `~security` label if the issue is related to application security.
+
All labels, their meaning and priority are defined on the
[labels page](https://gitlab.com/gitlab-org/gitlab/-/labels).
@@ -282,12 +286,12 @@ Please refer to the issue triage [severity label](https://about.gitlab.com/handb
### Label for community contributors
-Issues that are beneficial to our users, 'nice to haves', that we currently do
-not have the capacity for or want to give the priority to, are labeled as
-~"Accepting merge requests", so the community can make a contribution.
+There are many issues that have a clear solution with uncontroversial benefit to GitLab users.
+However, GitLab might not have the capacity for all these proposals in the current roadmap.
+These issues are labeled ~"Seeking community contributions" because we welcome merge requests to resolve them.
Community contributors can submit merge requests for any issue they want, but
-the ~"Accepting merge requests" label has a special meaning. It points to
+the ~"Seeking community contributions" label has a special meaning. It points to
changes that:
1. We already agreed on,
@@ -295,20 +299,24 @@ changes that:
1. Are likely to get accepted by a maintainer.
We want to avoid a situation when a contributor picks an
-~"Accepting merge requests" issue and then their merge request gets closed,
+~"Seeking community contributions" issue and then their merge request gets closed,
because we realize that it does not fit our vision, or we want to solve it in a
different way.
-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 manually add the ~"Seeking community contributions" label to issues
+that fit the criteria described above.
+We do not automatically add this label, because it requires human evaluation.
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&state=opened&label_name[]=good%20for%20new%20contributors&assignee_id=None) attached to it.
+look for issues labeled `~"Seeking community contributions"` with a
+[weight of 1](https://gitlab.com/groups/gitlab-org/-/issues?sort=created_date&state=opened&label_name[]=Seeking+community+contributions&assignee_id=None&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).
+[any of them](https://gitlab.com/groups/gitlab-org/-/issues?sort=created_date&state=opened&label_name[]=Seeking+community+contributions&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&state=opened&label_name[]=Accepting%20merge%20requests&label_name[]=Community%20challenge).
+with the [label `~"Community Challenge"`](https://gitlab.com/gitlab-org/gitlab/-/issues?sort=created_date&state=opened&label_name[]=Seeking+community+contributions&label_name[]=Community+challenge).
If your MR for the `~"Community Challenge"` issue gets merged, you will also have a chance to win a custom
GitLab merchandise.
@@ -319,7 +327,7 @@ members to further discuss scope, design, and technical considerations. This wil
ensure that your contribution is aligned with the GitLab product and minimize
any rework and delay in getting it merged into main.
-GitLab team members who apply the ~"Accepting merge requests" label to an issue
+GitLab team members who apply the ~"Seeking community contributions" label to an issue
should update the issue description with a responsible product manager, inviting
any potential community contributor to @-mention per above.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index cc6997e1a20..02148f2a717 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
We welcome merge requests from everyone, with fixes and improvements
to GitLab code, tests, and documentation. The issues that are specifically suitable
-for community contributions are listed with the [`Accepting merge requests`](issue_workflow.md#label-for-community-contributors)
+for community contributions have the [`Seeking community contributions`](issue_workflow.md#label-for-community-contributors)
label, but you are free to contribute to any issue you want.
If an issue is marked for the current milestone at any time, even
@@ -18,7 +18,7 @@ in order to ensure the work is finished before the release date.
If you want to add a new feature that is not labeled, it is best to first create
an issue (if there isn't one already) and leave a comment asking for it
-to be marked as `Accepting merge requests`. See the [feature proposals](issue_workflow.md#feature-proposals)
+to be labeled as `Seeking community contributions`. See the [feature proposals](issue_workflow.md#feature-proposals)
section.
Merge requests should be submitted to the appropriate project at GitLab.com, for example
@@ -71,6 +71,9 @@ request is as follows:
1. The MR must include *Before* and *After* screenshots if UI changes are made.
1. Include any steps or setup required to ensure reviewers can view the changes you've made (for example, include any information about feature flags).
1. If you're allowed to, set a relevant milestone and [labels](issue_workflow.md).
+ MR labels should generally match the corresponding issue (if there is one).
+ The group label should reflect the group that executed or coached the work,
+ not necessarily the group that owns the feature.
1. UI changes should use available components from the GitLab Design System,
[Pajamas](https://design.gitlab.com/).
1. If the MR changes CSS classes, please include the list of affected pages, which
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index fdb6e99fdcd..da926005466 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -51,20 +51,10 @@ This should return a fully qualified path command with no other output.
### Lefthook configuration
-The current Lefthook configuration can be found in [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml).
+Lefthook is configured with a combination of:
-Before you push your changes, Lefthook automatically runs the following checks:
-
-- Danger: Runs a subset of checks that `danger-review` runs on your merge requests.
-- ES lint: Run `yarn run lint:eslint` checks (with the [`.eslintrc.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.eslintrc.yml) configuration) on the modified `*.{js,vue}` files. Tags: `frontend`, `style`.
-- HAML lint: Run `bundle exec haml-lint` checks (with the [`.haml-lint.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.haml-lint.yml) configuration) on the modified `*.html.haml` files. Tags: `view`, `haml`, `style`.
-- Markdown lint: Run `yarn markdownlint` checks on the modified `*.md` files. Tags: `documentation`, `style`.
-- SCSS lint: Run `yarn lint:stylelint` checks (with the [`.stylelintrc`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.stylelintrc) configuration) on the modified `*.scss{,.css}` files. Tags: `stylesheet`, `css`, `style`.
-- RuboCop: Run `bundle exec rubocop` checks (with the [`.rubocop.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.rubocop.yml) configuration) on the modified `*.rb` files. Tags: `backend`, `style`.
-- Vale: Run `vale` checks (with the [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) configuration) on the modified `*.md` files. Tags: `documentation`, `style`.
-- Documentation metadata: Run checks for the absence of [documentation metadata](../documentation/index.md#metadata).
-
-In addition to the default configuration, you can define a [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
+- Project configuration in [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml).
+- Any [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
### Disable Lefthook temporarily
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 374e4e5de68..8da1f5700e5 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -66,7 +66,7 @@ continue to apply. However, there are a few things that deserve special emphasis
Danger is a powerful tool and flexible tool, but not always the most appropriate
way to solve a given problem or workflow.
-First, be aware of the GitLab [commitment to dogfooding](https://about.gitlab.com/handbook/engineering/#dogfooding).
+First, be aware of the GitLab [commitment to dogfooding](https://about.gitlab.com/handbook/engineering/principles/#dogfooding).
The code we write for Danger is GitLab-specific, and it **may not** be most
appropriate place to implement functionality that addresses a need we encounter.
Our users, customers, and even our own satellite projects, such as [Gitaly](https://gitlab.com/gitlab-org/gitaly),
diff --git a/doc/development/database/dbcheck-migrations-job.md b/doc/development/database/dbcheck-migrations-job.md
new file mode 100644
index 00000000000..af72e28a875
--- /dev/null
+++ b/doc/development/database/dbcheck-migrations-job.md
@@ -0,0 +1,67 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# db:check-migrations job
+
+This job runs on the test stage of a merge request pipeline. It checks:
+
+1. A schema dump comparison between the author's working branch and the target branch,
+ after executing a rollback of your new migrations. This check validates that the
+ schema properly resets to what it was before executing this new migration.
+1. A schema dump comparison between the author's working branch and the `db/structure.sql`
+ file that the author committed. This check validates that it contains all the expected changes
+ in the migration.
+1. A Git diff between the `db/schema_migrations` that the author committed and the
+ one that the script generated after running migrations. This check validates that everything
+ was properly committed.
+
+## Troubleshooting
+
+### False positives
+
+This job is allowed to fail, because it can throw some false positives.
+
+For example, when we drop a column and then roll back, this column is always
+re-added at the end of the list of columns. If the column was previously in
+the middle of the list, the rollback can't return the schema back exactly to
+its previous state. The job fails, but it's an acceptable situation.
+
+For a real-life example, refer to
+[this failed job](https://gitlab.com/gitlab-org/gitlab/-/jobs/2006544972#L138).
+Here, the author dropped the `position` column.
+
+### Schema dump comparison fails after rollback
+
+This failure often happens if your working branch is behind the target branch.
+A real scenario:
+
+```mermaid
+graph LR
+ Main((main<br>commit A)) ===> |remove constraint<br>fk_rails_dbebdaa8fe| MainB((main<br>commit B))
+ Main((main<br>commit A)) --> |checkout<br>dev| DevA((dev<br>commit A)):::dev
+ DevA((dev<br>commit A)) --> |add column<br>dependency_proxy_size| DevC((dev<br>commit C)):::dev
+ DevC -.-> |CI pipeline<br>executes| JOB-FAILED((JOB FAILED!)):::error
+
+ classDef main fill:#f4f0ff,stroke:#7b58cf
+ classDef dev fill:#e9f3fc,stroke:#1f75cb
+ classDef error fill:#f15146,stroke:#d4121a
+```
+
+1. You check out the `dev` working branch from the `main` target branch. At this point,
+ each branch has their `HEAD` at commit A.
+1. Someone works on the `main` branch and drops the `fk_rails_dbebdaa8fe` constraint,
+ thus creating commit B on `main`.
+1. You add column `dependency_proxy_size` to your `dev` branch.
+1. The `db:check-migrations` job fails for your `dev` branch's CI/CD pipeline, because
+ the `structure.sql` file did not rollback to its expected state.
+
+This happened because branch `dev` contained commits A and C, not B. Its database schema
+did not know about the removal of the `fk_rails_dbebdaa8fe` constraint. When comparing the two
+schemas, the `dev` branch contained this constraint while the `main` branch didn't.
+
+This example really happened. Read the [job failure logs](https://gitlab.com/gitlab-org/gitlab/-/jobs/1992050890).
+
+To fix these kind of issues, rebase the working branch onto the target branch to get the latest changes.
diff --git a/doc/development/database/efficient_in_operator_queries.md b/doc/development/database/efficient_in_operator_queries.md
index 76518a6f5e2..2503be826ea 100644
--- a/doc/development/database/efficient_in_operator_queries.md
+++ b/doc/development/database/efficient_in_operator_queries.md
@@ -368,7 +368,7 @@ then the query might perform worse than the non-optimized query. The `milestone_
"index_issues_on_milestone_id" btree (milestone_id)
```
-Adding the `miletone_id = X` filter to the `scope` argument or to the optimized scope causes bad performance.
+Adding the `milestone_id = X` filter to the `scope` argument or to the optimized scope causes bad performance.
Example (bad):
@@ -618,7 +618,7 @@ The following example shows the final `ORDER BY` clause:
ORDER BY extract('epoch' FROM epics.closed_at - epics.created_at) DESC, epics.id DESC
```
-Snippet for loading records ordered by the calcualted duration:
+Snippet for loading records ordered by the calculated duration:
```ruby
arel_table = Epic.arel_table
@@ -641,7 +641,7 @@ records = Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
array_mapping_scope: -> (id_expression) { Epic.where(Epic.arel_table[:group_id].eq(id_expression)) }
).execute.limit(20)
-puts records.pluck(:duration_in_seconds, :id) # other columnns are not available
+puts records.pluck(:duration_in_seconds, :id) # other columns are not available
```
Building the query requires quite a bit of configuration. For the order configuration you
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index a7b752e14ef..efc48f72d00 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -19,6 +19,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Understanding EXPLAIN plans](../understanding_explain_plans.md)
- [explain.depesz.com](https://explain.depesz.com/) or [explain.dalibo.com](https://explain.dalibo.com/) for visualizing the output of `EXPLAIN`
- [pgFormatter](https://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier
+- [db:check-migrations job](dbcheck-migrations-job.md)
## Migrations
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
index 97d150b1a18..d08e90683fe 100644
--- a/doc/development/database/loose_foreign_keys.md
+++ b/doc/development/database/loose_foreign_keys.md
@@ -61,7 +61,7 @@ following information:
- Child table name (`ci_pipelines`)
- The data cleanup method (`async_delete` or `async_nullify`)
-The YAML file is located at `lib/gitlab/database/gitlab_loose_foreign_keys.yml`. The file groups
+The YAML file is located at `config/gitlab_loose_foreign_keys.yml`. The file groups
foreign key definitions by the name of the child table. The child table can have multiple loose
foreign key definitions, therefore we store them as an array.
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 082c843a12c..8e217725a17 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -49,7 +49,7 @@ If new migrations are introduced, in the MR **you are required to provide**:
Note that we have automated tooling for
[GitLab](https://gitlab.com/gitlab-org/gitlab) (provided by the
-`db:check-migrations` pipeline job) that provides this output for migrations on
+[`db:check-migrations`](database/dbcheck-migrations-job.md) pipeline job) that provides this output for migrations on
~database merge requests. You do not need to provide this information manually
if the bot can do it for you. The bot also checks that migrations are correctly
reversible.
@@ -66,7 +66,7 @@ Refer to [Preparation when adding or modifying queries](#preparation-when-adding
### Roles and process
-A Merge Request **author**'s role is to:
+A merge request **author**'s role is to:
- Decide whether a database review is needed.
- If database review is needed, add the ~database label.
diff --git a/doc/development/dependencies.md b/doc/development/dependencies.md
index c81c6408211..329539f0cc2 100644
--- a/doc/development/dependencies.md
+++ b/doc/development/dependencies.md
@@ -51,6 +51,6 @@ This has certain benefits as outlined in our <a href="https://docs.gitlab.com/ee
You might find that we do not currently update DEPENDENCY automatically, but we are planning to do so in [the near future](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/21).
-Thank you for understanding, I will close this Merge Request.
+Thank you for understanding, I will close this merge request.
/close
```
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index 27c29a1ed7c..08e29e373f6 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Deprecation guidelines
-This page includes information about how and when to remove or make breaking
-changes to GitLab features.
+This page includes information about how and when to remove or make [breaking
+changes](../contributing/index.md#breaking-changes) to GitLab features.
## Terminology
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index aaa3340af33..d61de740f15 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -35,7 +35,7 @@ have changed since then, it should still serve as a good introduction.
### Merge request diffs
-When refreshing a Merge Request (pushing to a source branch, force-pushing to target branch, or if the target branch now contains any commits from the MR)
+When refreshing a merge request (pushing to a source branch, force-pushing to target branch, or if the target branch now contains any commits from the MR)
we fetch the comparison information using `Gitlab::Git::Compare`, which fetches `base` and `head` data using Gitaly and diff between them through
`Gitlab::Git::Diff.between`.
The diffs fetching process _limits_ single file diff sizes and the overall size of the whole diff through a series of constant values. Raw diff files are
@@ -45,7 +45,7 @@ Even though diffs larger than 10% of the value of `ApplicationSettings#diff_max_
we still keep them on PostgreSQL. However, diff files larger than defined _safety limits_
(see the [Diff limits section](#diff-limits)) are _not_ persisted in the database.
-In order to present diffs information on the Merge Request diffs page, we:
+In order to present diffs information on the merge request diffs page, we:
1. Fetch all diff files from database `merge_request_diff_files`
1. Fetch the _old_ and _new_ file blobs in batch to:
diff --git a/doc/development/directory_structure.md b/doc/development/directory_structure.md
index 8ba77bade2c..f909fda897f 100644
--- a/doc/development/directory_structure.md
+++ b/doc/development/directory_structure.md
@@ -38,7 +38,7 @@ end
### About namespace naming
A good guideline for naming a top-level namespace (bounded context) is to use the related
-feature category. For example, `Continuous Integration` feature category maps to `Ci::` namespace.
+[feature category](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/categories.yml). For example, `Continuous Integration` feature category maps to `Ci::` namespace.
Alternatively a new class could be added to `Projects::` or `Groups::` if it's either:
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 1e85abf585c..680ac71f857 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/documentation/index.md b/doc/development/documentation/index.md
index 776e5aefd00..5cf7bb74549 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -68,7 +68,7 @@ Adhere to the [Documentation Style Guide](styleguide/index.md). If a style stand
## Folder structure and files
-See the [Structure](styleguide/index.md#structure) section of the [Documentation Style Guide](styleguide/index.md).
+See the [Folder structure](site_architecture/folder_structure.md) page.
## Metadata
@@ -290,9 +290,7 @@ For example, [GitLab.com's `/help`](https://gitlab.com/help).
## Docs site architecture
-See the [Docs site architecture](site_architecture/index.md) page to learn
-how we build and deploy the site at <https://docs.gitlab.com> and
-to review all the assets and libraries in use.
+For information on how we build and deploy <https://docs.gitlab.com>, see [Docs site architecture](site_architecture/index.md).
### Global navigation
diff --git a/doc/development/documentation/review_apps.md b/doc/development/documentation/review_apps.md
index 4b58778a20c..8cb9e6437b8 100644
--- a/doc/development/documentation/review_apps.md
+++ b/doc/development/documentation/review_apps.md
@@ -41,7 +41,7 @@ the GitLab team to run the job.
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.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/trigger-build.rb)
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 `main`).
1. The preview URL is shown both at the job output and in the merge request
@@ -61,7 +61,7 @@ The following GitLab features are used among others:
- [Review Apps](../../ci/review_apps/index.md)
- [Artifacts](../../ci/yaml/index.md#artifacts)
- [Specific runner](../../ci/runners/runners_scope.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
-- [Pipelines for merge requests](../../ci/pipelines/merge_request_pipelines.md)
+- [Merge request pipelines](../../ci/pipelines/merge_request_pipelines.md)
## Troubleshooting review apps
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index 25bc699c9d4..5203ca52922 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -82,7 +82,7 @@ for the stable branch of the image to rebuild. You might do this:
## Latest documentation
-A Docker image (tagged `latest`) is built that contains:
+We build a Docker image (tagged `latest`) that contains:
- The latest online version of the documentation.
- The documentation from the stable branches of upstream projects.
diff --git a/doc/development/documentation/site_architecture/folder_structure.md b/doc/development/documentation/site_architecture/folder_structure.md
new file mode 100644
index 00000000000..e960a6491c7
--- /dev/null
+++ b/doc/development/documentation/site_architecture/folder_structure.md
@@ -0,0 +1,98 @@
+---
+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
+---
+
+# Folder structure for documentation
+
+The documentation is separated by top-level audience folders [`user`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/user),
+[`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration),
+and [`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development)
+(contributing) folders.
+
+Beyond that, we primarily follow the structure of the GitLab user interface or
+API.
+
+Our goal is to have a clear hierarchical structure with meaningful URLs like
+`docs.gitlab.com/user/project/merge_requests/`. With this pattern, you can
+immediately tell that you are navigating to user-related documentation about
+Project features; specifically about Merge Requests. Our site's paths match
+those of our repository, so the clear structure also makes documentation easier
+to update.
+
+Put files for a specific product area into the related folder:
+
+| Directory | Contents |
+|:----------------------|:------------------|
+| `doc/user/` | Documentation for users. Anything that can be done in the GitLab user interface goes here, including usage of the `/admin` interface. |
+| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. Administrator settings in the GitLab user interface are under `doc/user/admin_area/`. |
+| `doc/api/` | Documentation for the API. |
+| `doc/development/` | Documentation related to the development of GitLab, whether contributing code or documentation. Related process and style guides should go here. |
+| `doc/legal/` | Legal documents about contributing to GitLab. |
+| `doc/install/` | Instructions for installing GitLab. |
+| `doc/update/` | Instructions for updating GitLab. |
+| `doc/topics/` | Indexes per topic (`doc/topics/topic_name/index.md`): all resources for that topic. |
+
+## Work with directories and files
+
+When working with directories and files:
+
+1. When you create a new directory, always start with an `index.md` file.
+ Don't use another filename and do not create `README.md` files.
+1. Do not use special characters and spaces, or capital letters in file
+ names, directory names, branch names, and anything that generates a path.
+1. When creating or renaming a file or directory and it has more than one word
+ in its name, use underscores (`_`) instead of spaces or dashes. For example,
+ proper naming would be `import_project/import_from_github.md`. This applies
+ to both image files and Markdown files.
+1. For image files, do not exceed 100KB.
+1. Do not upload video files to the product repositories.
+ [Link or embed videos](../styleguide/index.md#videos) instead.
+1. There are four main directories: `user`, `administration`, `api`, and
+ `development`.
+1. The `doc/user/` directory has five main subdirectories: `project/`, `group/`,
+ `profile/`, `dashboard/` and `admin_area/`.
+ - `doc/user/project/` should contain all project related documentation.
+ - `doc/user/group/` should contain all group related documentation.
+ - `doc/user/profile/` should contain all profile related documentation.
+ Every page you would navigate under `/profile` should have its own document,
+ for example, `account.md`, `applications.md`, or `emails.md`.
+ - `doc/user/dashboard/` should contain all dashboard related documentation.
+ - `doc/user/admin_area/` should contain all administrator-related
+ documentation describing what can be achieved by accessing the GitLab
+ administrator interface (not to be confused with `doc/administration` where
+ server access is required).
+ - Every category under `/admin/application_settings/` should have its
+ own document located at `doc/user/admin_area/settings/`. For example,
+ the **Visibility and Access Controls** category should have a document
+ located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
+1. The `doc/topics/` directory holds topic-related technical content. Create
+ `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
+ General user and administrator documentation should be placed accordingly.
+1. The `/university/` directory is *deprecated* and the majority of its documentation
+ has been moved.
+
+If you're unsure where to place a document or a content addition, this shouldn't
+stop you from authoring and contributing. Use your best judgment, and then ask
+the reviewer of your MR to confirm your decision. You can also ask a technical writer at
+any stage in the process. The technical writing team reviews all
+documentation changes, regardless, and can move content if there is a better
+place for it.
+
+## Avoid duplication
+
+Do not include the same information in multiple places.
+[Link to a single source of truth instead.](../styleguide/index.md#link-instead-of-repeating-text)
+
+## References across documents
+
+- Give each folder an `index.md` page that introduces the topic, and both introduces
+ and links to the child pages, including to the index pages of
+ any next-level sub-paths.
+- To ensure discoverability, ensure each new or renamed doc is linked from its
+ higher-level index page and other related pages.
+- When making reference to other GitLab products and features, link to their
+ respective documentation, at least on first mention.
+- When making reference to third-party products or technologies, link out to
+ their external sites, documentation, and resources.
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 60894430d15..e7a915eab09 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -52,19 +52,20 @@ product, and all together are pulled to generate the docs website:
- [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs)
- [GitLab Chart](https://gitlab.com/charts/gitlab/tree/master/doc)
+Learn more about [the docs folder structure](folder_structure.md).
+
## Assets
To provide an optimized site structure, design, and a search-engine friendly
website, along with a discoverable documentation, we use a few assets for
the GitLab Documentation website.
-### Libraries
+### External libraries
+
+GitLab Docs is built with a combination of external:
-- [Bootstrap 4.3.1 components](https://getbootstrap.com/docs/4.3/components/)
-- [Bootstrap 4.3.1 JS](https://getbootstrap.com/docs/4.3/getting-started/javascript/)
-- [jQuery](https://jquery.com/) 3.3.1
-- [Clipboard JS](https://clipboardjs.com/)
-- [Font Awesome 4.7.0](https://fontawesome.com/v4.7.0/icons/)
+- [JavaScript libraries](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/package.json).
+- [Ruby libraries](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/Gemfile).
### SEO
@@ -98,7 +99,7 @@ The pipeline in the `gitlab-docs` project:
Once a week on Mondays, a scheduled pipeline runs and rebuilds the Docker images
used in various pipeline jobs, like `docs-lint`. The Docker image configuration files are
-located in the [Dockerfiles directory](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/master/dockerfiles).
+located in the [Dockerfiles directory](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/main/dockerfiles).
If you need to rebuild the Docker images immediately (must have maintainer level permissions):
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 6ecffce01b4..21368098f39 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -5,10 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: What to include in GitLab documentation pages.
---
-# Documentation topic types
+# Documentation topic types (CTRT)
At GitLab, we have not traditionally used types for our content. However, we are starting to
-move in this direction, and we now use four primary topic types:
+move in this direction, and we now use four primary topic types (CTRT):
- [Concept](#concept)
- [Task](#task)
@@ -154,7 +154,7 @@ If multiple causes or workarounds exist, consider putting them into a table form
## Other types of content
There are other types of content in the GitLab documentation that don't
-classify as one of the four primary [topic types](#documentation-topic-types).
+classify as one of the four primary [topic types](#documentation-topic-types-ctrt).
These include:
- [Tutorials](#tutorials)
@@ -174,7 +174,7 @@ In general, you might consider using a tutorial when:
Tutorials are learning aids that complement our core documentation.
They do not introduce new features.
-Always use the primary [topic types](#documentation-topic-types) to document new features.
+Always use the primary [topic types](#documentation-topic-types-ctrt) to document new features.
Tutorials should be in this format:
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index e57ffb90028..3e9c0177d48 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -181,115 +181,6 @@ included in backticks. For example:
- `git clone` is a command, so it must be lowercase, while Git is the product,
so it must have a capital G.
-## Structure
-
-We include concept and task topic types in the same larger topic.
-
-In general, we have one topic that's a landing page.
-Below that topic in the left nav are individual topics. Each of these include a concept
-and multiple related tasks, reference, and troubleshooting topics.
-
-### Folder structure overview
-
-The documentation is separated by top-level audience folders [`user`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/user),
-[`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration),
-and [`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development)
-(contributing) folders.
-
-Beyond that, we primarily follow the structure of the GitLab user interface or
-API.
-
-Our goal is to have a clear hierarchical structure with meaningful URLs like
-`docs.gitlab.com/user/project/merge_requests/`. With this pattern, you can
-immediately tell that you are navigating to user-related documentation about
-Project features; specifically about Merge Requests. Our site's paths match
-those of our repository, so the clear structure also makes documentation easier
-to update.
-
-Put files for a specific product area into the related folder:
-
-| Directory | Contents |
-|:----------------------|:------------------|
-| `doc/user/` | Documentation for users. Anything that can be done in the GitLab user interface goes here, including usage of the `/admin` interface. |
-| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. Administrator settings in the GitLab user interface are under `doc/user/admin_area/`. |
-| `doc/api/` | Documentation for the API. |
-| `doc/development/` | Documentation related to the development of GitLab, whether contributing code or documentation. Related process and style guides should go here. |
-| `doc/legal/` | Legal documents about contributing to GitLab. |
-| `doc/install/` | Instructions for installing GitLab. |
-| `doc/update/` | Instructions for updating GitLab. |
-| `doc/topics/` | Indexes per topic (`doc/topics/topic_name/index.md`): all resources for that topic. |
-
-### Work with directories and files
-
-When working with directories and files:
-
-1. When you create a new directory, always start with an `index.md` file.
- Don't use another filename and do not create `README.md` files.
-1. Do not use special characters and spaces, or capital letters in file
- names, directory names, branch names, and anything that generates a path.
-1. When creating or renaming a file or directory and it has more than one word
- in its name, use underscores (`_`) instead of spaces or dashes. For example,
- proper naming would be `import_project/import_from_github.md`. This applies
- to both image files and Markdown files.
-1. For image files, do not exceed 100KB.
-1. Do not upload video files to the product repositories.
- [Link or embed videos](#videos) instead.
-1. There are four main directories: `user`, `administration`, `api`, and
- `development`.
-1. The `doc/user/` directory has five main subdirectories: `project/`, `group/`,
- `profile/`, `dashboard/` and `admin_area/`.
- - `doc/user/project/` should contain all project related documentation.
- - `doc/user/group/` should contain all group related documentation.
- - `doc/user/profile/` should contain all profile related documentation.
- Every page you would navigate under `/profile` should have its own document,
- for example, `account.md`, `applications.md`, or `emails.md`.
- - `doc/user/dashboard/` should contain all dashboard related documentation.
- - `doc/user/admin_area/` should contain all administrator-related
- documentation describing what can be achieved by accessing the GitLab
- administrator interface (not to be confused with `doc/administration` where
- server access is required).
- - Every category under `/admin/application_settings/` should have its
- own document located at `doc/user/admin_area/settings/`. For example,
- the **Visibility and Access Controls** category should have a document
- located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
-1. The `doc/topics/` directory holds topic-related technical content. Create
- `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
- General user and administrator documentation should be placed accordingly.
-1. The `/university/` directory is *deprecated* and the majority of its documentation
- has been moved.
-
-If you're unsure where to place a document or a content addition, this shouldn't
-stop you from authoring and contributing. Use your best judgment, and then ask
-the reviewer of your MR to confirm your decision. You can also ask a technical writer at
-any stage in the process. The technical writing team reviews all
-documentation changes, regardless, and can move content if there is a better
-place for it.
-
-### Avoid duplication
-
-Do not include the same information in multiple places.
-[Link to a single source of truth instead.](#link-instead-of-repeating-text)
-
-### References across documents
-
-- Give each folder an `index.md` page that introduces the topic, and both introduces
- and links to the child pages, including to the index pages of
- any next-level sub-paths.
-- To ensure discoverability, ensure each new or renamed doc is linked from its
- higher-level index page and other related pages.
-- When making reference to other GitLab products and features, link to their
- respective documentation, at least on first mention.
-- When making reference to third-party products or technologies, link out to
- their external sites, documentation, and resources.
-
-### Structure in documents
-
-- Include any and all applicable subsections as described on the
- [structure and template](../structure.md) page.
-- Structure content in alphabetical order in tables, lists, and so on, unless
- there's a logical reason not to (for example, when mirroring the user
- interface or an otherwise ordered sequence).
-
## Language
GitLab documentation should be clear and easy to understand.
@@ -320,10 +211,11 @@ create an issue or an MR to propose a change to the user interface text.
#### Feature names
- Feature names are typically lowercase.
-- Some features are capitalized, typically nouns that name GitLab-specific
- capabilities or tools.
-
-See the [word list](word_list.md) for details.
+- Some features require title case, typically nouns that name GitLab-specific capabilities or tools. Features requiring
+ title case should be:
+ - Added as a proper name to markdownlint [configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.yml),
+ so that it can be consistently applied across all documentation.
+ - Added to the [word list](word_list.md).
If the term is not in the word list, ask a GitLab Technical Writer for advice.
@@ -1151,7 +1043,8 @@ When you take screenshots:
- **Review how the image renders on the page.** Preview the image locally or use the
review app in the merge request. Make sure the image isn't blurry or overwhelming.
- **Be consistent.** Coordinate screenshots with the other screenshots already on
- a documentation page for a consistent reading experience.
+ a documentation page for a consistent reading experience. Ensure your navigation theme
+ is **Indigo** and the syntax highlighting theme is **Light**. These are the default preferences.
### Add callouts
@@ -1745,11 +1638,12 @@ If the content in a topic is not ready, use the disclaimer in the topic.
### Removing versions after each major release
-Whenever a major GitLab release occurs, we remove all version references
-to now-unsupported versions of GitLab. Note that this includes the removal of
-specific instructions for users of non-supported GitLab versions. For example,
-if GitLab versions 11.x and later are supported, special
-instructions for users of GitLab 10 should be removed.
+When a major GitLab release occurs, we remove all references
+to now-unsupported versions. This removal includes version-specific instructions. For example,
+if GitLab version 12.1 and later are supported,
+instructions for users of GitLab 11 should be removed.
+
+[View the list of supported versions](https://about.gitlab.com/support/statement-of-support.html#version-support).
To view historical information about a feature, review GitLab
[release posts](https://about.gitlab.com/releases/), or search for the issue or
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index dc3dcba0c95..2c435cdc69d 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -58,11 +58,7 @@ Capitalize these words when you refer to the UI. Otherwise use lowercase.
## administrator
-Use **administrator** instead of **admin** when talking about a user's access level.
-Use lowercase unless you are referring to the **Admin** access level you select in the UI.
-
-To view the administrator access level, in the GitLab UI, go to the Admin Area and select
-**Users**. Then select **New user**.
+Use **administrator access** instead of **admin** when talking about a user's access level.
![admin access level](img/admin_access_level.png)
@@ -71,7 +67,7 @@ An **administrator** is not a [role](#roles) or [permission](#permissions).
Use:
- To do this thing, you must be an administrator.
-- To do this thing, you must have the administrator access level.
+- To do this thing, you must have administrator access.
Instead of:
@@ -82,6 +78,17 @@ Instead of:
Use title case **Admin Area** to refer to the area of the UI that you access when you select **Menu > Admin**.
This area of the UI says **Admin Area** at the top of the page and on the menu.
+## agent
+
+Use lowercase to refer to the [GitLab agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent).
+For example:
+
+- To connect your cluster to GitLab, use the GitLab agent for Kubernetes.
+- Install the agent in your cluster.
+- Select an agent from the list.
+
+Do not use title case **GitLab Agent** or **GitLab Agent for Kubernetes**.
+
## allow, enable
Try to avoid **allow** and **enable**, unless you are talking about security-related features.
@@ -102,7 +109,7 @@ This phrasing is more active and is from the user perspective, rather than the p
Use uppercase for **Alpha**. For example: **The XYZ feature is in Alpha.** or **This Alpha release is ready to test.**
-You might also want to link to [this section](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga)
+You might also want to link to [this section](../../../policy/alpha-beta-support.md#alpha-features)
in the handbook when writing about Alpha features.
## and/or
@@ -128,7 +135,7 @@ Try to avoid **below** when referring to an example or table in a documentation
Use uppercase for **Beta**. For example: **The XYZ feature is in Beta.** or **This Beta release is ready to test.**
-You might also want to link to [this section](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga)
+You might also want to link to [this section](../../../policy/alpha-beta-support.md#beta-features)
in the handbook when writing about Beta features.
## blacklist
@@ -194,6 +201,10 @@ CI/CD is always uppercase. No need to spell it out on first use.
Use **CI/CD minutes** instead of **CI minutes**, **pipeline minutes**, **pipeline minutes quota**, or
**CI pipeline minutes**. This decision was made in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342813).
+## CI/CD tunnel
+
+Use lowercase for **tunnel** in **CI/CD tunnel**.
+
## click
Do not use **click**. Instead, use **select** with buttons, links, menu items, and lists.
@@ -312,6 +323,11 @@ Instead of:
Use **expand** instead of **open** when you are talking about expanding or collapsing a section in the UI.
+## FAQ
+
+We want users to find information quickly, and they rarely search for the term **FAQ**.
+Information in FAQs belongs with other similar information, under an easily searchable topic title.
+
## field
Use **box** instead of **field** or **text box**.
@@ -367,6 +383,11 @@ Use title case for **GitLab Runner**. This is the product you install. See also
Use **GitLab self-managed** to refer to the product license for GitLab instances managed by customers themselves.
+## guide
+
+We want to speak directly to users. On `docs.gitlab.com`, do not use **guide** as part of a page title.
+For example, **Snowplow Guide**. Instead, speak about the feature itself, and how to use it. For example, **Use Snowplow to do xyz**.
+
## Guest
When writing about the Guest role:
@@ -540,6 +561,8 @@ Do not use **navigate**. Use **go** instead. For example:
- Go to this webpage.
- Open a terminal and go to the `runner` directory.
+([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+
## need to, should
Try to avoid **needs to**, because it's wordy. Avoid **should** when you can be more specific. If something is required, use **must**.
@@ -658,10 +681,22 @@ Use **press** when talking about keyboard keys. For example:
Do not use profanity. 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).
+## provision
+
+Use the term **provision** when referring to provisioning cloud infrastructure. You provision the infrastructure, and then deploy applications to it.
+
+For example, you might write something like:
+
+- Provision an AWS EKS cluster and deploy your application to it.
+
## push rules
Use lowercase for **push rules**.
+## register
+
+Use **register** instead of **sign up** when talking about creating an account.
+
## Reporter
When writing about the Reporter role:
@@ -690,6 +725,9 @@ Roles are not the same as [**access levels**](#access-level).
Use lowercase for **runners**. These are the agents that run CI/CD jobs. See also [GitLab Runner](#gitlab-runner) and [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/233529).
+When referring to runners, if you have to specify that the runners are installed on a customer's GitLab instance,
+use **self-managed** rather than **self-hosted**.
+
## (s)
Do not use **(s)** to make a word optionally plural. It can slow down comprehension. For example:
@@ -735,6 +773,10 @@ Instead of:
Use **select** with buttons, links, menu items, and lists. **Select** applies to more devices,
while **click** is more specific to a mouse.
+## self-managed
+
+Use **self-managed** to refer to a customer's installation of GitLab. Do not use **self-hosted**.
+
## Service Desk
Use title case for **Service Desk**.
@@ -752,6 +794,10 @@ Use **sign in** instead of **sign on** or **log on** or **log in**. If the user
You can use **single sign-on**.
+## sign up
+
+Use **register** instead of **sign up** when talking about creating an account.
+
## simply, simple
Do not use **simply** or **simple**. If the user doesn't find the process to be simple, we lose their trust. ([Vale](../testing.md#vale) rule: [`Simplicity.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Simplicity.yml))
@@ -883,10 +929,6 @@ Instead of:
Do not use **utilize**. Use **use** instead. It's more succinct and easier for non-native English speakers to understand.
([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
-## Value Stream Analytics
-
-Use title case for **Value Stream Analytics**.
-
## 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))
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 134183a0e75..905b44823c3 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -126,6 +126,24 @@ If you don't want to install all of the dependencies to test the links, you can:
If you manually install `haml-lint` with this process, it does not update automatically
and you should make sure your version matches the version used by GitLab.
+## Update linter configuration
+
+[Vale configuration](#vale) and [markdownlint configuration](#markdownlint) is under source control in each
+project, so updates must be committed to each project individually.
+
+We consider the configuration in the `gitlab` project as the source of truth and that's where all updates should
+first be made.
+
+On a regular basis, the changes made in `gitlab` project to the Vale and markdownlint configuration should be
+synchronized to the other projects. In `omnibus-gitlab`, `gitlab-runner`, and `charts/gitlab`:
+
+1. Create a new branch.
+1. Copy the configuration files from the `gitlab` project into this branch, overwriting
+ the project's old configuration. Make sure no project-specific changes from the `gitlab`
+ project are included. For example, [`RelativeLinks.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/RelativeLinks.yml)
+ is hard coded for specific projects.
+1. Create a merge request and submit it to a technical writer for review and merge.
+
## Local linters
To help adhere to the [documentation style guidelines](styleguide/index.md), and improve the content
@@ -181,7 +199,7 @@ You can find Vale configuration in the following projects:
- [`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)
+- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main/doc/.vale/gitlab)
This configuration is also used in build pipelines, where
[error-level rules](#vale-result-types) are enforced.
@@ -293,23 +311,7 @@ To configure Vale in your editor, install one of the following as appropriate:
- Sublime Text [`SublimeLinter-contrib-vale` package](https://packagecontrol.io/packages/SublimeLinter-contrib-vale).
- Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server).
- You can configure the plugin to
- [display only a subset of alerts](#show-subset-of-vale-alerts).
-
- In the extension's settings:
-
- <!-- vale gitlab.Spelling = NO -->
-
- - Select the **Use CLI** checkbox.
- - In the **Config** setting, enter an absolute
- 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 -->
-
- - In the **Path** setting, enter the absolute path to the Vale binary. In most
- cases, `vale` should work. To find the location, run `which vale` in a terminal.
-
+ You can configure the plugin to [display only a subset of alerts](#show-subset-of-vale-alerts).
- Vim [ALE plugin](https://github.com/dense-analysis/ale).
- Emacs [Flycheck extension](https://github.com/flycheck/flycheck).
This requires some configuration:
@@ -344,7 +346,7 @@ To configure Vale in your editor, install one of the following as appropriate:
In this setup the `markdownlint` checker is set as a "next" checker from the defined `vale` checker.
Enabling this custom Vale checker provides error linting from both Vale and markdownlint.
-We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application).
+We don't use [Vale Server](https://docs.errata.ai/vale-server/install).
### Configure pre-push hooks
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 49ad51874e3..a12af51e436 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -79,7 +79,7 @@ A member of the Technical Writing team adds these labels:
### Reviewing and merging
-Anyone with the [Maintainer role](../../user/permissions.md) to the relevant GitLab project can
+Anyone with the Maintainer role 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.
@@ -157,7 +157,7 @@ Ensure the following if skipping an initial Technical Writer review:
- Specific [user permissions](../../user/permissions.md) are documented.
- New documents are linked from higher-level indexes, for discoverability.
- The style guide is followed:
- - For [directories and files](styleguide/index.md#work-with-directories-and-files).
+ - For [directories and files](site_architecture/folder_structure.md).
- For [images](styleguide/index.md#images).
Merge requests that change the location of documentation must always be reviewed by a Technical
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 9f705f2c6f1..17e35d34ec7 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -11,8 +11,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- **Write documentation.**: Add documentation to the `doc/` directory. Describe
the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide/index.md#product-tier-badges)
the feature applies to.
-- **Submit a MR to the `www-gitlab-com` project.**: Add the new feature to the
+<!-- markdownlint-disable MD044 -->
+- **Submit a MR to the [`www-gitlab-com`](https://gitlab.com/gitlab-com/www-gitlab-com) project.**: Add the new feature to the
[EE features list](https://about.gitlab.com/features/).
+<!-- markdownlint-enable MD044 -->
## Act as CE when unlicensed
diff --git a/doc/development/emails.md b/doc/development/emails.md
index 811619bb0ff..5361282334f 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -10,8 +10,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
A Sidekiq job is enqueued whenever `deliver_later` is called on an `ActionMailer`.
If a mailer argument needs to be added or removed, it is important to ensure
-both backward and forward compatibility. Adhere to the Sidekiq Style Guide steps for
-[changing the arguments for a worker](sidekiq_style_guide.md#changing-the-arguments-for-a-worker).
+both backward and forward compatibility. Adhere to the Sidekiq steps for
+[changing the arguments for a worker](sidekiq/compatibility_across_updates.md#changing-the-arguments-for-a-worker).
In the following example from [`NotificationService`](https://gitlab.com/gitlab-org/gitlab/-/blob/33ccb22e4fc271dbaac94b003a7a1a2915a13441/app/services/notification_service.rb#L74)
adding or removing an argument in this mailer's definition may cause problems
@@ -89,6 +89,8 @@ See the [Rails guides](https://guides.rubyonrails.org/action_mailer_basics.html#
As mentioned, the part after `+` is ignored, and this message is sent to the mailbox for `gitlab-incoming@gmail.com`.
+1. Read the [MailRoom Gem updates](#mailroom-gem-updates) section for more details before you proceed to make sure you have the right version of MailRoom installed. In summary, you need to update the `gitlab-mail_room` version in the `Gemfile` to the latest `gitlab-mail_room` temporarily and run `bundle install`. **Do not commit** this change as it's a temporary workaround.
+
1. Run this command in the GitLab root directory to launch `mail_room`:
```shell
diff --git a/doc/development/event_store.md b/doc/development/event_store.md
index 7f2b9c86d27..c6d553f41cd 100644
--- a/doc/development/event_store.md
+++ b/doc/development/event_store.md
@@ -185,7 +185,7 @@ Changes to the schema require multiple rollouts. While the new version is being
- Events get persisted in the Sidekiq queue as job arguments, so we could have 2 versions of the schema during deployments.
As changing the schema ultimately impacts the Sidekiq arguments, please refer to our
-[Sidekiq style guide](sidekiq_style_guide.md#changing-the-arguments-for-a-worker) with regards to multiple rollouts.
+[Sidekiq style guide](sidekiq/compatibility_across_updates.md#changing-the-arguments-for-a-worker) with regards to multiple rollouts.
#### Add properties
@@ -232,7 +232,6 @@ the event safely via the `handle_event` method. For example:
```ruby
module MergeRequests
class UpdateHeadPipelineWorker
- include ApplicationWorker
include Gitlab::EventStore::Subscriber
def handle_event(event)
@@ -252,19 +251,20 @@ add a line like this to the `Gitlab::EventStore.configure!` method:
```ruby
module Gitlab
module EventStore
- def self.configure!
- Store.new.tap do |store|
- # ...
+ def self.configure!(store)
+ # ...
- store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, to: ::Ci::PipelineCreatedEvent
+ store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, to: ::Ci::PipelineCreatedEvent
- # ...
- end
+ # ...
end
end
end
```
+A worker that is only defined in the EE codebase can subscribe to an event in the same way by
+declaring the subscription in `ee/lib/ee/gitlab/event_store.rb`.
+
Subscriptions are stored in memory when the Rails app is loaded and they are immediately frozen.
It's not possible to modify subscriptions at runtime.
@@ -274,7 +274,7 @@ A subscription can specify a condition when to accept an event:
```ruby
store.subscribe ::MergeRequests::UpdateHeadPipelineWorker,
- to: ::Ci::PipelineCreatedEvent,
+ to: ::Ci::PipelineCreatedEvent,
if: -> (event) { event.data[:merge_request_id].present? }
```
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index 36d2a4f6fbf..369690ba86c 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -4,26 +4,24 @@ group: Adoption
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
---
-# Implementing an A/B/n experiment using GLEX
+# Implementing an A/B/n experiment
## Introduction
-`Gitlab::Experiment` (GLEX) is tightly coupled with the concepts provided by
-[Feature flags in development of GitLab](../feature_flags/index.md). Here, we refer
-to this layer as feature flags, and may also use the term Flipper, because we
-built our development and experiment feature flags atop it.
-
-You're strongly encouraged to read and understand the
-[Feature flags in development of GitLab](../feature_flags/index.md) portion of the
-documentation before considering running experiments. Experiments add additional
-concepts which may seem confusing or advanced without understanding the underpinnings
-of how GitLab uses feature flags in development. One concept: GLEX supports
-experiments with multiple variants, which are sometimes referred to as A/B/n tests.
-
-The [`gitlab-experiment` project](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment)
-exists in a separate repository, so it can be shared across any GitLab property that uses
-Ruby. You should feel comfortable reading the documentation on that project as well
-if you want to dig into more advanced topics.
+Experiments in GitLab are tightly coupled with the concepts provided by
+[Feature flags in development of GitLab](../feature_flags/index.md). You're strongly encouraged
+to read and understand the [Feature flags in development of GitLab](../feature_flags/index.md)
+portion of the documentation before considering running experiments. Experiments add additional
+concepts which may seem confusing or advanced without understanding the underpinnings of how GitLab
+uses feature flags in development. One concept: experiments can be run with multiple variants,
+which are sometimes referred to as A/B/n tests.
+
+We use the [`gitlab-experiment` gem](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment),
+sometimes referred to as GLEX, to run our experiments. The gem exists in a separate repository
+so it can be shared across any GitLab property that uses Ruby. You should feel comfortable reading
+the documentation on that project if you want to dig into more advanced topics or open issues. Be
+aware that the documentation there reflects what's in the main branch and may not be the same as
+the version being used within GitLab.
## Glossary of terms
@@ -35,41 +33,9 @@ when communicating about experiments:
- `control`: The default, or "original" code path.
- `candidate`: Defines an experiment with only one code path.
- `variant(s)`: Defines an experiment with multiple code paths.
+- `behaviors`: Used to reference all possible code paths of an experiment, including the control.
-### How it works
-
-Use this decision tree diagram to understand how GLEX works. When an experiment runs,
-the following logic is executed to determine what variant should be provided,
-given how the experiment has been defined and using the provided context:
-
-```mermaid
-graph TD
- GP[General Pool/Population] --> Running?
- Running? -->|Yes| Cached?[Cached? / Pre-segmented?]
- Running? -->|No| Excluded[Control / No Tracking]
- Cached? -->|No| Excluded?
- Cached? -->|Yes| Cached[Cached Value]
- Excluded? -->|Yes| Excluded
- Excluded? -->|No| Segmented?
- Segmented? -->|Yes / Cached| VariantA
- Segmented? -->|No| Included?[Experiment Group?]
- Included? -->|Yes| Rollout
- Included? -->|No| Control
- Rollout -->|Cached| VariantA
- Rollout -->|Cached| VariantB
- Rollout -->|Cached| VariantC
-
-classDef included fill:#380d75,color:#ffffff,stroke:none
-classDef excluded fill:#fca121,stroke:none
-classDef cached fill:#2e2e2e,color:#ffffff,stroke:none
-classDef default fill:#fff,stroke:#6e49cb
-
-class VariantA,VariantB,VariantC included
-class Control,Excluded excluded
-class Cached cached
-```
-
-## Implement an experiment
+## Implementing an experiment
[Examples](https://gitlab.com/gitlab-org/growth/growth/-/wikis/GLEX-Framework-code-examples)
@@ -87,9 +53,9 @@ experiment in code. An experiment implementation can be as simple as:
```ruby
experiment(:pill_color, actor: current_user) do |e|
- e.use { 'control' }
- e.try(:red) { 'red' }
- e.try(:blue) { 'blue' }
+ e.control { 'control' }
+ e.variant(:red) { 'red' }
+ e.variant(:blue) { 'blue' }
end
```
@@ -146,11 +112,11 @@ We can also implement this experiment in a HAML file with HTML wrappings:
```haml
#cta-interface
- experiment(:pill_color, actor: current_user) do |e|
- - e.use do
+ - e.control do
.pill-button control
- - e.try(:red) do
+ - e.variant(:red) do
.pill-button.red red
- - e.try(:blue) do
+ - e.variant(:blue) do
.pill-button.blue blue
```
@@ -212,38 +178,30 @@ wouldn't be resolvable.
### Advanced experimentation
-GLEX allows for two general implementation styles:
+There are two ways to implement an experiment:
1. The simple experiment style described previously.
-1. A more advanced style where an experiment class can be provided.
+1. A more advanced style where an experiment class is provided.
The advanced style is handled by naming convention, and works similar to what you
would expect in Rails.
To generate a custom experiment class that can override the defaults in
-`ApplicationExperiment` (our base GLEX implementation), use the rails generator:
+`ApplicationExperiment` use the Rails generator:
```shell
rails generate gitlab:experiment pill_color control red blue
```
This generates an experiment class in `app/experiments/pill_color_experiment.rb`
-with the variants (or _behaviors_) we've provided to the generator. Here's an example
-of how that class would look after migrating the previous example into it:
+with the _behaviors_ we've provided to the generator. Here's an example
+of how that class would look after migrating our previous example into it:
```ruby
class PillColorExperiment < ApplicationExperiment
- def control_behavior
- 'control'
- end
-
- def red_behavior
- 'red'
- end
-
- def blue_behavior
- 'blue'
- end
+ control { 'control' }
+ variant(:red) { 'red' }
+ variant(:blue) { 'blue' }
end
```
@@ -254,13 +212,13 @@ providing the block we were initially providing, by explicitly calling `run`:
experiment(:pill_color, actor: current_user).run
```
-The _behavior_ methods we defined in our experiment class represent the default
-implementation. You can still use the block syntax to override these _behavior_
-methods however, so the following would also be valid:
+The _behaviors_ we defined in our experiment class represent the default
+implementation. You can still use the block syntax to override these _behaviors_
+however, so the following would also be valid:
```ruby
experiment(:pill_color, actor: current_user) do |e|
- e.use { '<strong>control</strong>' }
+ e.control { '<strong>control</strong>' }
end
```
@@ -279,11 +237,11 @@ variant, and any account older than 2 weeks old would be assigned the _blue_ var
```ruby
class PillColorExperiment < ApplicationExperiment
+ # ...registered behaviors
+
segment(variant: :red) { context.actor.first_name == 'Richard' }
segment :old_account?, variant: :blue
- # ...behaviors
-
private
def old_account?
@@ -315,9 +273,9 @@ be nothing - but no events are tracked in these cases as well.
```ruby
class PillColorExperiment < ApplicationExperiment
- exclude :old_account?, ->{ context.actor.first_name == 'Richard' }
+ # ...registered behaviors
- # ...behaviors
+ exclude :old_account?, ->{ context.actor.first_name == 'Richard' }
private
@@ -327,23 +285,11 @@ class PillColorExperiment < ApplicationExperiment
end
```
-We can also do exclusion when we run the experiment. For instance,
-if we wanted to prevent the inclusion of non-administrators in an experiment, consider
-the following experiment. This type of logic enables us to do complex experiments
-while preventing us from passing things into our experiments, because
-we want to minimize passing things into our experiments:
-
-```ruby
-experiment(:pill_color, actor: current_user) do |e|
- e.exclude! unless can?(current_user, :admin_project, project)
-end
-```
-
You may also need to check exclusion in custom tracking logic by calling `should_track?`:
```ruby
class PillColorExperiment < ApplicationExperiment
- # ...behaviors
+ # ...registered behaviors
def expensive_tracking_logic
return unless should_track?
@@ -353,16 +299,11 @@ class PillColorExperiment < ApplicationExperiment
end
```
-Exclusion rules aren't the best way to determine if an experiment is active. Override
-the `enabled?` method for a high-level way of determining if an experiment should
-run and track. Make the `enabled?` check as efficient as possible because it's the
-first early opt-out path an experiment can implement.
-
### Tracking events
One of the most important aspects of experiments is gathering data and reporting on
-it. GLEX provides an interface that allows tracking events across an experiment.
-You can implement it consistently if you provide the same context between
+it. You can use the `track` method to track events across an experimental implementation.
+You can track events consistently to an experiment if you provide the same context between
calls to your experiment. If you do not yet understand context, you should read
about contexts now.
@@ -373,13 +314,13 @@ the arguments you would normally use when
of tracking an event in Ruby would be:
```ruby
-experiment(:pill_color, actor: current_user).track(:created)
+experiment(:pill_color, actor: current_user).track(:clicked)
```
-When you run an experiment with any of these examples, an `:assigned` event
+When you run an experiment with any of the examples so far, an `:assigned` event
is tracked automatically by default. All events that are tracked from an
experiment have a special
-[experiment context](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0)
+[experiment context](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-3)
added to the event. This can be used - typically by the data team - to create a connection
between the events on a given experiment.
@@ -390,28 +331,20 @@ event would be tracked at that time for them.
NOTE:
GitLab tries to be sensitive and respectful of our customers regarding tracking,
-so GLEX allows us to implement an experiment without ever tracking identifying
+so our experimentation library allows us to implement an experiment without ever tracking identifying
IDs. It's not always possible, though, based on experiment reporting requirements.
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.
-## Test with RSpec
+## Testing with RSpec
-This gem provides some RSpec helpers and custom matchers. These are in flux as of GitLab 13.10.
-
-First, require the RSpec support file to mix in some of the basics:
-
-```ruby
-require 'gitlab/experiment/rspec'
-```
-
-You still need to include matchers and other aspects, which happens
-automatically for files in `spec/experiments`, but for other files and specs
-you want to include it in, you can specify the `:experiment` type:
+In the course of working with experiments, you'll probably want to utilize the RSpec
+tooling that's built in. This happens automatically for files in `spec/experiments`, but
+for other files and specs you want to include it in, you can specify the `:experiment` type:
```ruby
-it "tests", :experiment do
+it "tests experiments nicely", :experiment do
end
```
@@ -421,28 +354,32 @@ You can stub experiments using `stub_experiments`. Pass it a hash using experime
names as the keys, and the variants you want each to resolve to, as the values:
```ruby
-# Ensures the experiments named `:example` & `:example2` are both
-# "enabled" and that each will resolve to the given variant
-# (`:my_variant` & `:control` respectively).
+# Ensures the experiments named `:example` & `:example2` are both "enabled" and
+# that each will resolve to the given variant (`:my_variant` and `:control`
+# respectively).
stub_experiments(example: :my_variant, example2: :control)
experiment(:example) do |e|
e.enabled? # => true
- e.variant.name # => 'my_variant'
+ e.assigned.name # => 'my_variant'
end
experiment(:example2) do |e|
e.enabled? # => true
- e.variant.name # => 'control'
+ e.assigned.name # => 'control'
end
```
-### Exclusion and segmentation matchers
+### Exclusion, segmentation, and behavior matchers
-You can also test the exclusion and segmentation matchers.
+You can also test things like the registered behaviors, the exclusions, and
+segmentations using the matchers.
```ruby
class ExampleExperiment < ApplicationExperiment
+ control { }
+ candidate { '_candidate_' }
+
exclude { context.actor.first_name == 'Richard' }
segment(variant: :candidate) { context.actor.username == 'jejacks0n' }
end
@@ -450,6 +387,10 @@ end
excluded = double(username: 'rdiggitty', first_name: 'Richard')
segmented = double(username: 'jejacks0n', first_name: 'Jeremy')
+# register_behavior matcher
+expect(experiment(:example)).to register_behavior(:control)
+expect(experiment(:example)).to register_behavior(:candidate).with('_candidate_')
+
# exclude matcher
expect(experiment(:example)).to exclude(actor: excluded)
expect(experiment(:example)).not_to exclude(actor: segmented)
@@ -495,35 +436,36 @@ expect(experiment(:example)).to track(:my_event, value: 1, property: '_property_
experiment(:example, :variant_name, foo: :bar).track(:my_event, value: 1, property: '_property_')
```
-### Recording and assignment tracking
-
-To test assignment tracking and the `record!` method, you can use or adopt the following
-shared example: [tracks assignment and records the subject](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb).
-
## Experiments in the client layer
-This is in flux as of GitLab 13.10, and can't be documented just yet.
+Any experiment that's been run in the request lifecycle surfaces in `window.gl.experiments`,
+and matches [this schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-3)
+so it can be used when resolving experimentation in the client layer.
-Any experiment that's been run in the request lifecycle surfaces in and `window.gl.experiments`,
-and matches [this schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0)
-so you can use it when resolving some concepts around experimentation in the client layer.
+Given that we've defined a class for our experiment, and have defined the variants for it, we can publish that experiment in a couple ways.
-### Use experiments in Vue
+The first way is simply by running the experiment. Assuming the experiment has been run, it will surface in the client layer without having to do anything special.
-With the `gitlab-experiment` component, you can define slots that match the name of the
-variants pushed to `window.gl.experiments`. For example, if we alter the `pill_color`
-experiment to just use the default variants of `control` and `candidate` like so:
+The second way doesn't run the experiment and is intended to be used if the experiment only needs to surface in the client layer. To accomplish this we can simply `.publish` the experiment. This won't run any logic, but does surface the experiment details in the client layer so they can be utilized there.
+
+An example might be to publish an experiment in a `before_action` in a controller. Assuming we've defined the `PillColorExperiment` class, like we have above, we can surface it to the client by publishing it instead of running it:
```ruby
-def show
- experiment(:pill_color) do |e|
- e.use { } # control
- e.try { } # candidate
- end.run
-end
+before_action -> { experiment(:pill_color).publish }, only: [:show]
```
-We can make use of the named slots `control` and `candidate` in the Vue component:
+You can then see this surface in the JavaScript console:
+
+```javascript
+window.gl.experiments // => { pill_color: { excluded: false, experiment: "pill_color", key: "ca63ac02", variant: "candidate" } }
+```
+
+### Using experiments in Vue
+
+With the `gitlab-experiment` component, you can define slots that match the name of the
+variants pushed to `window.gl.experiments`.
+
+We can make use of the named slots in the Vue component, that match the behaviors defined in :
```vue
<script>
@@ -540,23 +482,6 @@ export default {
<button class="bg-default">Click default button</button>
</template>
- <template #candidate>
- <button class="bg-red">Click red button</button>
- </template>
- </gitlab-experiment>
-</template>
-```
-
-When you're coding for an experiment with multiple variants, you can use the variant names.
-For example, the Vue component for the previously-defined `pill_color` experiment with `red` and `blue` variants would look like this:
-
-```vue
-<template>
- <gitlab-experiment name="pill_color">
- <template #control>
- <button class="bg-default">Click default button</button>
- </template>
-
<template #red>
<button class="bg-red">Click red button</button>
</template>
@@ -596,7 +521,7 @@ NOTE:
This method of stubbing in Jest specs will not automatically un-stub itself at the end of the test. We merge our stubbed experiment in with all the other global data in `window.gl`. If you need to remove the stubbed experiment(s) after your test or ensure a clean global object before your test, you'll need to manage the global object directly yourself:
```javascript
-desribe('tests that care about global state', () => {
+describe('tests that care about global state', () => {
const originalObjects = [];
beforeEach(() => {
@@ -628,7 +553,7 @@ is viewed as being either `on` or `off`, this isn't accurate for experiments.
Generally, `off` means that when we ask if a feature flag is enabled, it will always
return `false`, and `on` means that it will always return `true`. An interim state,
-considered `conditional`, also exists. GLEX takes advantage of this trinary state of
+considered `conditional`, also exists. We take advantage of this trinary state of
feature flags. To understand this `conditional` aspect: consider that either of these
settings puts a feature flag into this state:
@@ -638,7 +563,7 @@ settings puts a feature flag into this state:
Conditional means that it returns `true` in some situations, but not all situations.
When a feature flag is disabled (meaning the state is `off`), the experiment is
-considered _inactive_. You can visualize this in the [decision tree diagram](#how-it-works)
+considered _inactive_. You can visualize this in the [decision tree diagram](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment#how-it-works)
as reaching the first `Running?` node, and traversing the negative path.
When a feature flag is rolled out to a `percentage_of_actors` or similar (meaning the
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 8d62f92e0b9..254c136ef79 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -54,7 +54,7 @@ This uses [experiment](../feature_flags/index.md#experiment-type) feature flags.
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).
+Therefore, you should postpone this effort until the [experiment cleanup process](https://about.gitlab.com/handbook/engineering/development/growth/experimentation/#experiment-cleanup-issue).
We recommend the following workflow:
diff --git a/doc/development/export_csv.md b/doc/development/export_csv.md
index e2bbd0491d6..ff827023a50 100644
--- a/doc/development/export_csv.md
+++ b/doc/development/export_csv.md
@@ -11,8 +11,8 @@ This document lists the different implementations of CSV export in GitLab codeba
| Export type | How it works | Advantages | Disadvantages | Existing examples |
|---|---|---|---|---|
| Streaming | - Query and yield data in batches to a response stream.<br>- Download starts immediately. | - Report available immediately. | - No progress indicator.<br>- Requires a reliable connection. | [Export Audit Event Log](../administration/audit_events.md#export-to-csv) |
-| Downloading | - Query and write data in batches to a temporary file.<br>- Loads the file into memory.<br>- Sends the file to the client. | - Report available immediately. | - Large amount of data might cause request timeout.<br>- Memory intensive.<br>- Request expires when user navigates to a different page. | [Export Chain of Custody Report](../user/compliance/compliance_report/#chain-of-custody-report) |
-| As email attachment | - Asynchronously process the query with background job.<br>- Email uses the export as an attachment. | - Asynchronous processing. | - Requires users use a different app (email) to download the CSV.<br>- Email providers may limit attachment size. | - [Export Issues](../user/project/issues/csv_export.md)<br>- [Export Merge Requests](../user/project/merge_requests/csv_export.md) |
+| Downloading | - Query and write data in batches to a temporary file.<br>- Loads the file into memory.<br>- Sends the file to the client. | - Report available immediately. | - Large amount of data might cause request timeout.<br>- Memory intensive.<br>- Request expires when user navigates to a different page. | - [Export Chain of Custody Report](../user/compliance/compliance_report/#chain-of-custody-report)<br>- [Export License Usage File](../subscriptions/self_managed/index.md#export-your-license-usage) |
+| As email attachment | - Asynchronously process the query with background job.<br>- Email uses the export as an attachment. | - Asynchronous processing. | - Requires users use a different app (email) to download the CSV.<br>- Email providers may limit attachment size. | - [Export issues](../user/project/issues/csv_export.md)<br>- [Export merge requests](../user/project/merge_requests/csv_export.md) |
| As downloadable link in email (*) | - Asynchronously process the query with background job.<br>- Email uses an export link. | - Asynchronous processing.<br>- Bypasses email provider attachment size limit. | - Requires users use a different app (email).<br>- Requires additional storage and cleanup. | [Export User Permissions](https://gitlab.com/gitlab-org/gitlab/-/issues/1772) |
| Polling (non-persistent state) | - Asynchronously processes the query with the background job.<br>- Frontend(FE) polls every few seconds to check if CSV file is ready. | - Asynchronous processing.<br>- Automatically downloads to local machine on completion.<br>- In-app solution. | - Non-persistable request - request expires when user navigates to a different page.<br>- API is processed for each polling request. | [Export Vulnerabilities](../user/application_security/vulnerability_report/#export-vulnerability-details) |
| Polling (persistent state) (*) | - Asynchronously processes the query with background job.<br>- Backend (BE) maintains the export state<br>- FE polls every few seconds to check status.<br>- FE shows 'Download link' when export is ready.<br>- User can download or regenerate a new report. | - Asynchronous processing.<br>- No database calls made during the polling requests (HTTP 304 status is returned until export status changes).<br>- Does not require user to stay on page until export is complete.<br>- In-app solution.<br>- Can be expanded into a generic CSV feature (such as dashboard / CSV API). | - Requires to maintain export states in DB.<br>- Does not automatically download the CSV export to local machine, requires users to click 'Download' button. | [Export Merge Commits Report](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43055) |
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index 9e602b1ea04..76825d6ff18 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Anti-patterns may seem like good approaches at first, but it has been shown that they bring more ills than benefits. These should
generally be avoided.
-Throughout the GitLab codebase, there may be historic uses of these anti-patterns. Please [use discretion](https://about.gitlab.com/handbook/engineering/#balance-refactoring-and-velocity)
+Throughout the GitLab codebase, there may be historic uses of these anti-patterns. Please [use discretion](https://about.gitlab.com/handbook/engineering/principles/#balance-refactoring-and-velocity)
when figuring out whether or not to refactor, when touching code that uses one of these legacy patterns.
NOTE:
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index cd82a7dadc3..9921b851344 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -64,6 +64,30 @@ Please use your best judgment when to use it and please contribute new points th
- [ ] Follow up on issues that came out of the review. Create issues for discovered edge cases that should be covered in future iterations.
```
+### Code deletion checklist
+
+When your merge request deletes code, it's important to also delete all
+related code that is no longer used.
+When deleting Haml and Vue code, check whether it contains the following types of
+code that is unused:
+
+- CSS.
+
+ For example, we've deleted a Vue component that contained the `.mr-card` class, which is now unused.
+ The `.mr-card` CSS rule set should then be deleted from `merge_requests.scss`.
+
+- Ruby variables.
+
+ Deleting unused Ruby variables is important so we don't continue instantiating them with
+ potentially expensive code.
+
+ For example, we've deleted a Haml template that used the `@total_count` Ruby variable.
+ The `@total_count` variable was no longer used in the remaining templates for the page.
+ The instantiation of `@total_count` in `issues_controller.rb` should then be deleted so that we
+ don't make unnecessary database calls to calculate the count of issues.
+
+- Ruby methods.
+
### Merge Request Review
With the purpose of being [respectful of others' time](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time) please follow these guidelines when asking for a review:
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index ed71f612061..e79a473df9e 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -107,9 +107,9 @@ Default client accepts two parameters: `resolvers` and `config`.
### 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)
+If you are making multiple queries to the same Apollo client object you might encounter the following error: `Cache data may be lost when replacing the someProperty field of a Query object. To address this problem, either ensure all objects of SomeEntityhave an id or a custom merge function`. We are already checking `ID` presence for every GraphQL type that has an `ID`, so this shouldn't be the case. Most likely, the `SomeEntity` type doesn't have an `ID` property, and to fix this warning we need to define a custom merge function.
-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.
+We have some client-wide types with `merge: true` defined in the default client as [typePolicies](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/graphql.js) (this means that Apollo will merge existing and incoming responses in the case of subsequent queries). Please consider adding `SomeEntity` there or defining a custom merge function for it.
## GraphQL Queries
@@ -667,9 +667,7 @@ apollo: {
```
When we want to move to the next page, we use an Apollo `fetchMore` method, passing a
-new cursor (and, optionally, new variables) there. In the `updateQuery` hook, we have
-to return a result we want to see in the Apollo cache after fetching the next page.
-[`Immer`s `produce`](#immutability-and-cache-updates)-function can help us with the immutability here:
+new cursor (and, optionally, new variables) there.
```javascript
fetchNextPage(endCursor) {
@@ -679,24 +677,114 @@ fetchNextPage(endCursor) {
first: 10,
after: endCursor,
},
- updateQuery(previousResult, { fetchMoreResult }) {
- // Here we can implement the logic of adding new designs to existing ones
- // (for example, if we use infinite scroll) or replacing old result
- // with the new one if we use numbered pages
-
- const { designs: previousDesigns } = previousResult.project.issue.designCollection;
- const { designs: newDesigns } = fetchMoreResult.project.issue.designCollection
-
- return produce(previousResult, draftData => {
- // `produce` gives us a working copy, `draftData`, that we can modify
- // as we please and from it will produce the next immutable result for us
- draftData.project.issue.designCollection.designs = [...previousDesigns, ...newDesigns];
- });
- },
});
}
```
+##### Defining field merge policy
+
+We would also need to define a field policy to specify how do we want to merge the existing results with the incoming results. For example, if we have `Previous/Next` buttons, it makes sense to replace the existing result with the incoming one:
+
+```javascript
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ typePolicies: {
+ DesignCollection: {
+ fields: {
+ designs: {
+ merge(existing, incoming) {
+ if (!incoming) return existing;
+ if (!existing) return incoming;
+
+ // We want to save only incoming nodes and replace existing ones
+ return incoming
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ),
+});
+```
+
+When we have an infinite scroll, it would make sense to add the incoming `designs` nodes to existing ones instead of replacing. In this case, merge function would be slightly different:
+
+```javascript
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ typePolicies: {
+ DesignCollection: {
+ fields: {
+ designs: {
+ merge(existing, incoming) {
+ if (!incoming) return existing;
+ if (!existing) return incoming;
+
+ const { nodes, ...rest } = incoming;
+ // We only need to merge the nodes array.
+ // The rest of the fields (pagination) should always be overwritten by incoming
+ let result = rest;
+ result.nodes = [...existing.nodes, ...nodes];
+ return result;
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ),
+});
+```
+
+`apollo-client` [provides](https://github.com/apollographql/apollo-client/blob/212b1e686359a3489b48d7e5d38a256312f81fde/src/utilities/policies/pagination.ts)
+a few field policies to be used with paginated queries. Here's another way to achieve infinite
+scroll pagination with the `concatPagination` policy:
+
+```javascript
+import { concatPagination } from '@apollo/client/utilities';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+
+Vue.use(VueApollo);
+
+export default new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ typePolicies: {
+ Project: {
+ fields: {
+ dastSiteProfiles: {
+ keyArgs: ['fullPath'], // You might need to set the keyArgs option to enforce the cache's integrity
+ },
+ },
+ },
+ DastSiteProfileConnection: {
+ fields: {
+ nodes: concatPagination(),
+ },
+ },
+ },
+ },
+ },
+ ),
+});
+```
+
+This is similar to the `DesignCollection` example above as new page results are appended to the
+previous ones.
+
#### Using a recursive query in components
When it is necessary to fetch all paginated data initially an Apollo query can do the trick for us.
@@ -816,7 +904,7 @@ const data = store.readQuery({
});
```
-Read more about the `@connection` directive in [Apollo's documentation](https://www.apollographql.com/docs/react/v2/caching/cache-interaction/#the-connection-directive).
+Read more about the `@connection` directive in [Apollo's documentation](https://www.apollographql.com/docs/react/caching/advanced-topics/#the-connection-directive).
### Managing performance
@@ -1017,22 +1105,13 @@ apollo: {
issuableId: convertToGraphQLId(this.issuableClass, this.issuableId),
};
},
- // Describe how subscription should update the query
- updateQuery(prev, { subscriptionData }) {
- if (prev && subscriptionData?.data?.issuableAssigneesUpdated) {
- const data = produce(prev, (draftData) => {
- draftData.workspace.issuable.assignees.nodes =
- subscriptionData.data.issuableAssigneesUpdated.assignees.nodes;
- });
- return data;
- }
- return prev;
- },
},
},
},
```
+We would need also to define a field policy similarly like we do it for the [paginated queries](#defining-field-merge-policy)
+
### Best Practices
#### When to use (and not use) `update` hook in mutations
@@ -1081,55 +1160,6 @@ If you use the RubyMine IDE, and have marked the `tmp` directory as
`gitlab/tmp/tests/graphql`. This will allow the **JS GraphQL** plugin to
automatically find and index the schema.
-#### Mocking response as component data
-
-<!-- vale gitlab.Spelling = NO -->
-
-With [Vue Test Utils](https://vue-test-utils.vuejs.org/) one can quickly test components that
-fetch GraphQL queries. The simplest way is to use `shallowMount` and then set
-the data on the component:
-
-<!-- vale gitlab.Spelling = YES -->
-
-```javascript
-it('tests apollo component', () => {
- const vm = shallowMount(App);
-
- vm.setData({
- ...mockData
- });
-});
-```
-
-#### Testing loading state
-
-To test how a component renders when results from the GraphQL API are still loading, mock a loading state into respective Apollo queries/mutations:
-
-```javascript
- function createComponent({
- loading = false,
- } = {}) {
- const $apollo = {
- queries: {
- designs: {
- loading,
- },
- },
- };
-
- wrapper = shallowMount(Index, {
- sync: false,
- mocks: { $apollo }
- });
- }
-
- it('renders loading icon', () => {
- createComponent({ loading: true });
-
- expect(wrapper.element).toMatchSnapshot();
-})
-```
-
#### Testing Apollo components
If we use `ApolloQuery` or `ApolloMutation` in our components, in order to test their functionality we need to add a stub first:
@@ -1197,11 +1227,9 @@ it('calls mutation on submitting form ', () => {
});
```
-### Testing with mocked Apollo Client
-
-To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__/mock_apollo_helper.js) we created on top of it.
+#### Mocking Apollo Client
-To separate tests with mocked client from 'usual' unit tests, create an additional factory and pass the created `mockApollo` as an option to the `createComponent`-factory. This way we only create Apollo Client instance when it's necessary.
+To test the components with Apollo operations, we need to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__/mock_apollo_helper.js) we created on top of it.
We need to inject `VueApollo` into the Vue instance by calling `Vue.use(VueApollo)`. This will install `VueApollo` globally for all the tests in the file. It is recommended to call `Vue.use(VueApollo)` just after the imports.
@@ -1320,8 +1348,7 @@ it('renders designs list', async () => {
const mockApollo = createMockApolloProvider();
const wrapper = createComponent({ mockApollo });
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await waitForPromises()
expect(findDesigns()).toHaveLength(3);
});
@@ -1342,8 +1369,7 @@ function createMockApolloProvider() {
it('renders error if query fails', async () => {
const wrapper = createComponent();
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await waitForPromises()
expect(wrapper.find('.test-error').exists()).toBe(true)
})
@@ -1351,7 +1377,7 @@ it('renders error if query fails', async () => {
Request handlers can also be passed to component factory as a parameter.
-Mutations could be tested the same way with a few additional `nextTick`s to get the updated result:
+Mutations could be tested the same way:
```javascript
function createMockApolloProvider({
@@ -1391,7 +1417,7 @@ it('calls a mutation with correct parameters and reorders designs', async () =>
expect(moveDesignHandler).toHaveBeenCalled();
- await wrapper.vm.$nextTick();
+ await waitForPromises();
expect(
findDesigns()
@@ -1407,8 +1433,7 @@ To mock multiple query response states, success and failure, Apollo Client's nat
describe('when query times out', () => {
const advanceApolloTimers = async () => {
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
- await wrapper.vm.$nextTick();
+ await waitForPromises()
};
beforeEach(async () => {
@@ -1419,7 +1444,7 @@ describe('when query times out', () => {
.mockResolvedValueOnce({ errors: [{ message: 'timeout' }] });
createComponentWithApollo(failSucceedFail);
- await wrapper.vm.$nextTick();
+ await waitForPromises();
});
it('shows correct errors and does not overwrite populated data when data is empty', async () => {
@@ -1862,6 +1887,16 @@ relative to `app/graphql/queries` folder: for example, if we need a
`app/graphql/queries/repository/files.query.graphql` query, the path is
`repository/files`.
+## Troubleshooting
+
+### Mocked client returns empty objects instead of mock response
+
+If your unit test is failing because response contains empty objects instead of mock data, you would need to add `__typename` field to the mocked response. This happens because mocked client (unlike the real one) does not populate the response with typenames and in some cases we need to do it manually so the client is able to recognize a GraphQL type.
+
+### Warning about losing cache data
+
+Sometimes you can see a warning in the console: `Cache data may be lost when replacing the someProperty field of a Query object. To address this problem, either ensure all objects of SomeEntityhave an id or a custom merge function`. Please check section about [multiple queries](#multiple-client-queries-for-the-same-object) to resolve an issue.
+
```yaml
- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index f22e3ea6395..4a0923ebe19 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -136,24 +136,40 @@ the class name with `js-`.
## ES Module Syntax
-Use ES module syntax to import modules:
+For most JavaScript files, use ES module syntax to import or export from modules.
+Prefer named exports, as they improve name consistency.
```javascript
-// bad
-const SomeClass = require('some_class');
+// bad (with exceptions, see below)
+export default SomeClass;
+import SomeClass from 'file';
// good
-import SomeClass from 'some_class';
+export { SomeClass };
+import { SomeClass } from 'file';
+```
+
+Using default exports is acceptable in a few particular circumstances:
+
+- Vue Single File Components (SFCs)
+- Vuex mutation files
+
+For more information, see [RFC 20](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20).
+## CommonJS Module Syntax
+
+Our Node configuration requires CommonJS module syntax. Prefer named exports.
+
+```javascript
// bad
module.exports = SomeClass;
+const SomeClass = require('./some_class');
// good
-export default SomeClass;
+module.exports = { SomeClass };
+const { SomeClass } = require('./some_class');
```
-We still use `require` in `scripts/` and `config/` files.
-
## Absolute vs relative paths for modules
Use relative paths if the module you are importing is less than two levels up.
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 820b4bab802..af402713f6e 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -169,7 +169,7 @@ Each feature flag is defined in a separate YAML file consisting of a number of f
| `name` | yes | Name of the feature flag. |
| `type` | yes | Type of feature flag. |
| `default_enabled` | yes | The default state of the feature flag that is strictly validated, with `default_enabled:` passed as an argument. |
-| `introduced_by_url` | no | The URL to the Merge Request that introduced the feature flag. |
+| `introduced_by_url` | no | The URL to the merge request that introduced the feature flag. |
| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. |
| `milestone` | no | Milestone in which the feature was added. |
| `group` | no | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the feature flag. |
@@ -513,7 +513,7 @@ Feature.remove(:feature_flag_name)
- Any change behind a feature flag **disabled** by default **should not** have a changelog entry.
- **Exception:** database migrations **should** have a changelog entry.
-- Any change related to a feature flag itself (flag removal, default-on setting) **should** have a changelog entry.
+- Any change related to a feature flag itself (flag removal, default-on setting) **should** have [a changelog entry](../changelog.md).
Use the flowchart to determine the changelog entry type.
```mermaid
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index 73ba9cbd674..283a0d5d5fb 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -11,7 +11,7 @@ When implementing new features, please refer to these existing features to avoid
- [Custom Dashboards](../operations/metrics/dashboards/index.md#add-a-new-dashboard-to-your-project): `.gitlab/dashboards/`.
- [Issue Templates](../user/project/description_templates.md#create-an-issue-template): `.gitlab/issue_templates/`.
-- [Merge Request Templates](../user/project/description_templates.md#create-a-merge-request-template): `.gitlab/merge_request_templates/`.
+- [Merge request Templates](../user/project/description_templates.md#create-a-merge-request-template): `.gitlab/merge_request_templates/`.
- [GitLab Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
- [CODEOWNERS](../user/project/code_owners.md#set-up-code-owners): `.gitlab/CODEOWNERS`.
- [Route Maps](../ci/review_apps/#route-maps): `.gitlab/route-map.yml`.
diff --git a/doc/development/img/architecture_simplified.png b/doc/development/img/architecture_simplified.png
index bd731758ddd..bab673feb4a 100644
--- a/doc/development/img/architecture_simplified.png
+++ b/doc/development/img/architecture_simplified.png
Binary files differ
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index 9e236b4cfce..86e6e04347c 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -125,6 +125,14 @@ it fails with this error as `/` is not a valid character in a project name.
A project with that name already exists.
+##### `Exception: Error importing repository into (namespace) - No space left on device`
+
+The disk has insufficient space to complete the import.
+
+During import, the tarball is cached in your configured `shared_path` directory. Verify the
+disk has enough free space to accommodate both the cached tarball and the unpacked
+project files on disk.
+
### Importing via the Rails console
The last option is to import a project using a Rails console:
diff --git a/doc/development/index.md b/doc/development/index.md
index 197c7f48398..0501f70b818 100644
--- a/doc/development/index.md
+++ b/doc/development/index.md
@@ -221,10 +221,10 @@ the [reviewer values](https://about.gitlab.com/handbook/engineering/workflow/rev
- [Geo development](geo.md)
- [Redis guidelines](redis.md)
- [Adding a new Redis instance](redis/new_redis_instance.md)
-- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
+- [Sidekiq guidelines](sidekiq/index.md) for working with Sidekiq workers
- [Working with Gitaly](gitaly.md)
- [Elasticsearch integration docs](elasticsearch.md)
-- [Working with Merge Request diffs](diffs.md)
+- [Working with merge request diffs](diffs.md)
- [Approval Rules](approval_rules.md)
- [Repository mirroring](repository_mirroring.md)
- [File uploads](uploads.md)
diff --git a/doc/development/integrations/img/copy_cookies.png b/doc/development/integrations/img/copy_cookies.png
deleted file mode 100644
index 21575987173..00000000000
--- a/doc/development/integrations/img/copy_cookies.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/integrations/img/copy_curl.png b/doc/development/integrations/img/copy_curl.png
deleted file mode 100644
index 9fa871efbd5..00000000000
--- a/doc/development/integrations/img/copy_curl.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
index fc7204fdd5a..cfa1fdba699 100644
--- a/doc/development/integrations/jira_connect.md
+++ b/doc/development/integrations/jira_connect.md
@@ -65,27 +65,3 @@ If the app install failed, you might need to delete `jira_connect_installations`
1. Open the [database console](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#access-postgresql).
1. Run `TRUNCATE TABLE jira_connect_installations CASCADE;`.
-
-## Add a namespace
-
-To add a [namespace](../../user/group/index.md#namespaces) to Jira:
-
-1. Make sure you are logged in on your GitLab development instance.
-1. On the GitLab app page in Jira, click **Get started**.
-1. Open your browser's developer tools and navigate to the **Network** tab.
-1. Try to add the namespace in Jira.
-1. If the request fails with 401 "not authorized", copy the request as a cURL command
- and paste it in your terminal.
-
- ![Example Vulnerability](img/copy_curl.png)
-
-1. Go to your development instance (usually at: <http://localhost:3000>), open developer
- tools, navigate to the Network tab and reload the page.
-1. Copy all cookies from the first request.
-
- ![Example Vulnerability](img/copy_cookies.png)
-
-1. Append the cookies to the cURL command in your terminal:
- `--cookies "<cookies from the request>"`.
-1. Submit the cURL request.
-1. If the response is `{"success":true}`, the namespace was added.
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 147d379cec7..27a166aebf9 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -10,7 +10,7 @@ Integrating a security scanner into GitLab consists of providing end users
with a [CI job definition](../../ci/yaml/index.md)
they can add to their CI configuration files to scan their GitLab projects.
This CI job should then output its results in a GitLab-specified format. These results are then
-automatically presented in various places in GitLab, such as the Pipeline view, Merge Request
+automatically presented in various places in GitLab, such as the Pipeline view, merge request
widget, and Security Dashboard.
The scanning job is usually based on a [Docker image](https://docs.docker.com/)
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index 96910892022..db978253747 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -507,7 +507,7 @@ curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
Called from the GitLab Agent Server (`kas`) to create a security vulnerability
from a Starboard vulnerability report. This request is idempotent. Multiple requests with the same data
-create a single vulnerability.
+create a single vulnerability. The response contains the UUID of the created vulnerability finding.
| Attribute | Type | Required | Description |
|:----------------|:-------|:---------|:------------|
@@ -553,6 +553,37 @@ curl --request PUT --header "Gitlab-Kas-Api-Request: <JWT token>" \
}'
```
+Example response:
+
+```json
+{
+ "uuid": "4773b2ee-5ba5-5e9f-b48c-5f7a17f0faac"
+}
+```
+
+### Resolve Starboard vulnerabilities
+
+Called from the GitLab Agent Server (`kas`) to resolve Starboard security vulnerabilities.
+Accepts a list of finding UUIDs and marks all Starboard vulnerabilities not identified by
+the list as resolved.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------|
+| `uuids` | string array | yes | UUIDs of detected vulnerabilities, as collected from [Create Starboard vulnerability](#create-starboard-vulnerability) responses. |
+
+```plaintext
+POST internal/kubernetes/modules/starboard_vulnerability/scan_result
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
+ --url "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability/scan_result" \
+ --data '{ "uuids": ["102e8a0a-fe29-59bd-b46c-57c3e9bc6411", "5eb12985-0ed5-51f4-b545-fd8871dc2870"] }'
+```
+
## Subscriptions
The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
diff --git a/doc/development/issuable-like-models.md b/doc/development/issuable-like-models.md
index b3be2b1b2e6..42dfe2e0f2f 100644
--- a/doc/development/issuable-like-models.md
+++ b/doc/development/issuable-like-models.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab Rails codebase contains several models that hold common functionality and behave similarly to
[Issues](../user/project/issues/index.md). Other examples of "issuables"
-are [Merge Requests](../user/project/merge_requests/index.md) and
+are [merge requests](../user/project/merge_requests/index.md) and
[Epics](../user/group/epics/index.md).
This guide accumulates guidelines on working with such Rails models.
diff --git a/doc/development/issue_types.md b/doc/development/issue_types.md
index 31fa50e1d97..e6047c62827 100644
--- a/doc/development/issue_types.md
+++ b/doc/development/issue_types.md
@@ -11,7 +11,7 @@ We are deprecating Issue Types as of GitLab 14.2 in favor of [Work Items and Wor
Sometimes when a new resource type is added it's not clear if it should be only an
"extension" of Issue (Issue Type) or if it should be a new first-class resource type
-(similar to Issue, Epic, Merge Request, Snippet).
+(similar to issue, epic, merge request, snippet).
The idea of Issue Types was first proposed in [this
issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8767) and its usage was
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 9ea7fd3dc29..38cdbdf5b79 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -142,7 +142,7 @@ database query:
SELECT "users"."id" FROM "users" ORDER BY "users"."id" ASC LIMIT 1
```
-![Reading the start `id` value](img/each_batch_users_table_iteration_1_v13_7.png)
+![Reading the start ID value](img/each_batch_users_table_iteration_1_v13_7.png)
Notice that the query only reads data from the index (`INDEX ONLY SCAN`), the table is not
accessed. Database indexes are sorted so taking out the first item is a very cheap operation.
@@ -155,7 +155,7 @@ to get a "shifted" `id` value.
SELECT "users"."id" FROM "users" WHERE "users"."id" >= 1 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
```
-![Reading the end `id` value](img/each_batch_users_table_iteration_2_v13_7.png)
+![Reading the end ID value](img/each_batch_users_table_iteration_2_v13_7.png)
Again, the query only looks into the index. The `OFFSET 5` takes out the sixth `id` value: this
query reads a maximum of six items from the index regardless of the table size or the iteration
@@ -181,7 +181,7 @@ previous iteration in order to find out the next end `id` value.
SELECT "users"."id" FROM "users" WHERE "users"."id" >= 302 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
```
-![Reading the second end `id` value](img/each_batch_users_table_iteration_4_v13_7.png)
+![Reading the second end ID value](img/each_batch_users_table_iteration_4_v13_7.png)
Now we can easily construct the `users` query for the second iteration.
diff --git a/doc/development/jh_features_review.md b/doc/development/jh_features_review.md
index 858048c1e7c..88830a80bf1 100644
--- a/doc/development/jh_features_review.md
+++ b/doc/development/jh_features_review.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: https://gitlab.com/gitlab-jh/gitlab
+info: https://jihulab.com/gitlab-cn/gitlab
---
# Guidelines for reviewing JiHu (JH) Edition related merge requests
@@ -21,13 +21,13 @@ We have two kinds of changes related to JH:
- We will generalize this so both EE and JH can share the same mechanism,
then we wouldn't have to treat them differently.
-If needed, review the corresponding JH merge request located at [JH repository](https://gitlab.com/gitlab-jh/gitlab)
+If needed, review the corresponding JH merge request located at [JH repository](https://jihulab.com/gitlab-cn/gitlab).
## When to merge files to the GitLab Inc. repository
-Files that are added to the `gitlab-jh` repository outside of `jh/` must be mirrored in the GitLab Inc. repository.
+Files that are added to the GitLab JH repository outside of `jh/` must be mirrored in the GitLab Inc. repository.
-If code that is added to the GitLab Inc. repository references (for example, `render_if_exists`) any `gitlab-jh` file that does not
+If code that is added to the GitLab Inc. repository references (for example, `render_if_exists`) any GitLab JH file that does not
exist in the GitLab Inc. codebase, add a comment with a link to the JiHu merge request or file. This is to prevent
the reference from being misidentified as a missing partial and subsequently deleted in the `gitlab` codebase.
@@ -49,7 +49,7 @@ This page is the single source of truth for JiHu-related processes.
## CI pipelines in a JH context
EE repository does not have `jh/` directory therefore there is no way to run
-JH pipelines in the EE repository. All JH tests should go to [JH repository](https://gitlab.com/gitlab-jh/gitlab).
+JH pipelines in the EE repository. All JH tests should go to [JH repository](https://jihulab.com/gitlab-cn/gitlab).
The top-level JH CI configuration is located at `jh/.gitlab-ci.yml` (which
does not exist in EE repository) and it'll include EE CI configurations
@@ -89,7 +89,7 @@ Do not use methods such as `prepend`, `extend`, and `include`. Instead, use
the relevant EE and JH modules by the name of the receiver module.
If reviewing the corresponding JH file is needed, it should be found at
-[JH repository](https://gitlab.com/gitlab-jh/gitlab).
+[JH repository](https://jihulab.com/gitlab-cn/gitlab).
### General guidance for writing JH extensions
diff --git a/doc/development/logging.md b/doc/development/logging.md
index a4eda6ad02e..6a0b50d6970 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -398,3 +398,14 @@ end
1. Be sure to update the [GitLab CE/EE documentation](../administration/logs.md) and the [GitLab.com
runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/docs/logging/README.md).
+
+## Control logging visibility
+
+An increase in the logs can cause a growing backlog of unacknowledged messages. When adding new log messages, make sure they don't increase the overall volume of logging by more than 10%.
+
+### Deprecation notices
+
+If the expected volume of deprecation notices is large:
+
+- Only log them in the development environment.
+- If needed, log them in the testing environment.
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 106db862122..c8e99e8547f 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -255,15 +255,15 @@ It re-instantiates project object for each build, instead of using the same in-m
In this particular case the workaround is fairly easy:
```ruby
+ActiveRecord::Associations::Preloader.new.preload(pipeline, [builds: :project])
+
pipeline.builds.each do |build|
- build.project = pipeline.project
build.to_json(only: [:name], include: [project: { only: [:name]}])
end
```
-We can assign `pipeline.project` to each `build.project`, since we know it should point to the same project.
-This allows us that each build point to the same in-memory project,
-avoiding the cached SQL query and re-instantiation of the project object for each build.
+`ActiveRecord::Associations::Preloader` uses the same in-memory object for the same project.
+This avoids the cached SQL query and also avoids re-instantiation of the project object for each build.
## Executing Queries in Loops
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index 27c4edf15f4..bdab92f5185 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -14,14 +14,14 @@ In a sense, these scenarios are all transient states. But they can often persist
### When modifying a Sidekiq worker
-For example when [changing arguments](sidekiq_style_guide.md#changing-the-arguments-for-a-worker):
+For example when [changing arguments](sidekiq/compatibility_across_updates.md#changing-the-arguments-for-a-worker):
- 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?
### 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)?
+Is it ok if these jobs don't get executed for several hours because [Sidekiq nodes are not yet updated](sidekiq/compatibility_across_updates.md#adding-new-workers)?
### When modifying JavaScript
@@ -89,7 +89,7 @@ Many users [skip some monthly releases](../update/index.md#upgrading-to-a-new-ma
- 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?
+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/compatibility_across_updates.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?
@@ -180,7 +180,7 @@ coexists in production.
### Changing Sidekiq worker's parameters
-This topic is explained in detail in [Sidekiq Compatibility across Updates](sidekiq_style_guide.md#sidekiq-compatibility-across-updates).
+This topic is explained in detail in [Sidekiq Compatibility across Updates](sidekiq/compatibility_across_updates.md).
When we need to add a new parameter to a Sidekiq worker class, we can split this into the following steps:
diff --git a/doc/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md
index b833ba7c630..37712cb2cec 100644
--- a/doc/development/new_fe_guide/modules/widget_extensions.md
+++ b/doc/development/new_fe_guide/modules/widget_extensions.md
@@ -1,6 +1,6 @@
---
stage: Create
-group: Source Code
+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
---
@@ -11,27 +11,39 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Summary
Extensions in the merge request widget enable you to add new features
-into the widget that match the existing design and interaction as other extensions.
+into the merge request widget that match the design framework.
+With extensions we get a lot of benefits out of the box without much effort required, like:
+
+- A consistent look and feel.
+- Tracking when the extension is opened.
+- Virtual scrolling for performance.
## Usage
-To use extensions you need to first create a new extension object to fetch the
-data to render in the extension. See the example file in
-`app/assets/javascripts/vue_merge_request_widget/extensions/issues.js` for a working example.
+To use extensions you must first create a new extension object to fetch the
+data to render in the extension. For a working example, refer to the example file in
+`app/assets/javascripts/vue_merge_request_widget/extensions/issues.js`.
-The basic object structure is as below:
+The basic object structure:
```javascript
export default {
- name: '',
- props: [],
+ name: '', // Required: This helps identify the widget
+ props: [], // Required: Props passed from the widget state
+ i18n: { // Required: Object to hold i18n text
+ label: '', // Required: Used for tooltips and aria-labels
+ loading: '', // Required: Loading text for when data is loading
+ },
+ expandEvent: '', // Optional: RedisHLL event name to track expanding content
+ enablePolling: false, // Optional: Tells extension to poll for data
computed: {
- summary() {},
- statusIcon() {},
+ summary(data) {}, // Required: Level 1 summary text
+ statusIcon(data) {}, // Required: Level 1 status icon
+ tertiaryButtons() {}, // Optional: Level 1 action buttons
},
methods: {
- fetchCollapsedData() {},
- fetchFullData() {},
+ fetchCollapsedData(props) {}, // Required: Fetches data required for collapsed state
+ fetchFullData(props) {}, // Required: Fetches data for the full expanded content
},
};
```
@@ -39,10 +51,8 @@ export default {
By following the same data structure, each extension can follow the same registering structure,
but each extension can manage its data sources.
-After creating this structure you need to register it. Registering the extension can happen at any
-point _after_ the widget has been created.
-
-To register a extension the following can be done:
+After creating this structure, you must register it. You can register the extension at any
+point _after_ the widget has been created. To register a extension:
```javascript
// Import the register method
@@ -55,18 +65,174 @@ import issueExtension from '~/vue_merge_request_widget/extensions/issues';
registerExtension(issueExtension);
```
-## Fetching errors
+## Data fetching
+
+Each extension must fetch data. Fetching is handled when registering the extension,
+not by the core component itself. This approach allows for various different
+data fetching methods to be used, such as GraphQL or REST API calls.
+
+### API calls
+
+For performance reasons, it is best if the collapsed state fetches only the data required to
+render the collapsed state. This fetching happens within the `fetchCollapsedData` method.
+This method is called with the props as an argument, so you can easily access
+any paths set in the state.
+
+To allow the extension to set the data, this method **must** return the data. No
+special formatting is required. When the extension receives this data,
+it is set to `collapsedData`. You can access `collapsedData` in any computed property or
+method.
+
+When the user clicks **Expand**, the `fetchFullData` method is called. This method
+also gets called with the props as an argument. This method **must** also return
+the full data. However, this data needs to be correctly formatted to match the format
+mentioned in the data structure section.
+
+#### Technical debt
+
+For some of the current extensions, there is no split in data fetching. All the data
+is fetched through the `fetchCollapsedData` method. While less performant,
+it allows for faster iteration.
+
+To handle this the `fetchFullData` returns the data set through
+the `fetchCollapsedData` method call. In these cases, the `fetchFullData` must
+return a promise:
+
+```javascript
+fetchCollapsedData() {
+ return ['Some data'];
+},
+fetchFullData() {
+ return Promise.resolve(this.collapsedData)
+},
+```
+
+### Data structure
+
+The data returned from `fetchFullData` must match the format below. This format
+allows the core component to render the data in a way that matches
+the design framework. Any text properties can use the styling placeholders
+mentioned below:
+
+```javascript
+{
+ id: data.id, // Required: ID used as a key for each row
+ header: 'Header' || ['Header', 'sub-header'], // Required: String or array can be used for the header text
+ text: '', // Required: Main text for the row
+ subtext: '', // Optional: Smaller sub-text to be displayed below the main text
+ icon: { // Optional: Icon object
+ name: EXTENSION_ICONS.success, // Required: The icon name for the row
+ },
+ badge: { // Optional: Badge displayed after text
+ text: '', // Required: Text to be displayed inside badge
+ variant: '', // Optional: GitLab UI badge variant, defaults to info
+ },
+ actions: [], // Optional: Action button for row
+}
+```
+
+### Polling
+
+To enable polling for an extension, an options flag must be present in the extension:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+};
+```
+
+This flag tells the base component we should poll the `fetchCollapsedData()`
+defined in the extension. Polling stops if the response has data, or if an error is present.
+
+When writing the logic for `fetchCollapsedData()`, a complete Axios response must be returned
+from the method. The polling utility needs data like polling headers to work correctly:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath)
+ },
+ },
+};
+```
+
+Most of the time the data returned from the extension's endpoint is not in the format
+the UI needs. We must format the data before setting the collapsed data in the base component.
+
+If the computed property `summary` can rely on `collapsedData`, you can format the data
+when `fetchFullData` is invoked:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath)
+ },
+ fetchFullData() {
+ return Promise.resolve(this.prepareReports());
+ },
+ // custom method
+ prepareReports() {
+ // unpack values from collapsedData
+ const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+
+ // perform data formatting
+
+ return [...newErrors, ...existingErrors, ...resolvedErrors]
+ }
+ },
+};
+```
+
+If the extension relies on `collapsedData` being formatted before invoking `fetchFullData()`,
+then `fetchCollapsedData()` must return the Axios response as well as the formatted data:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath).then(res => {
+ const formattedData = this.prepareReports(res.data)
+
+ return {
+ ...res,
+ data: formattedData,
+ }
+ })
+ },
+ // Custom method
+ prepareReports() {
+ // Unpack values from collapsedData
+ const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+
+ // Perform data formatting
+
+ return [...newErrors, ...existingErrors, ...resolvedErrors]
+ }
+ },
+};
+```
+
+### Errors
If `fetchCollapsedData()` or `fetchFullData()` methods throw an error:
-- The loading state of the extension is updated to `LOADING_STATES.collapsedError` and `LOADING_STATES.expandedError`
- respectively.
+- The loading state of the extension is updated to `LOADING_STATES.collapsedError`
+ and `LOADING_STATES.expandedError` respectively.
- The extensions header displays an error icon and updates the text to be either:
- The text defined in `$options.i18n.error`.
- "Failed to load" if `$options.i18n.error` is not defined.
- The error is sent to Sentry to log that it occurred.
-To customise the error text, you need to add it to the `i18n` object in your extension:
+To customise the error text, add it to the `i18n` object in your extension:
```javascript
export default {
@@ -77,3 +243,77 @@ export default {
},
};
```
+
+## Icons
+
+Level 1 and all subsequent levels can have their own status icons. To keep with
+the design framework, import the `EXTENSION_ICONS` constant
+from the `constants.js` file:
+
+```javascript
+import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants.js';
+```
+
+This constant has the below icons available for use. Per the design framework,
+only some of these icons should be used on level 1:
+
+- `failed`
+- `warning`
+- `success`
+- `neutral`
+- `error`
+- `notice`
+- `severityCritical`
+- `severityHigh`
+- `severityMedium`
+- `severityLow`
+- `severityInfo`
+- `severityUnknown`
+
+## Text styling
+
+Any area that has text can be styled with the placeholders below. This
+technique follows the same technique as `sprintf`. However, instead of specifying
+these through `sprintf`, the extension does this automatically.
+
+Every placeholder contains starting and ending tags. For example, `success` uses
+`Hello %{success_start}world%{success_end}`. The extension then
+adds the start and end tags with the correct styling classes.
+
+| Placeholder | Style |
+|---|---|
+| success | `gl-font-weight-bold gl-text-green-500` |
+| danger | `gl-font-weight-bold gl-text-red-500` |
+| critical | `gl-font-weight-bold gl-text-red-800` |
+| same | `gl-font-weight-bold gl-text-gray-700` |
+| strong | `gl-font-weight-bold` |
+| small | `gl-font-sm` |
+
+## Action buttons
+
+You can add action buttons to all level 1 and 2 in each extension. These buttons
+are meant as a way to provide links or actions for each row:
+
+- Action buttons for level 1 can be set through the `tertiaryButtons` computed property.
+ This property should return an array of objects for each action button.
+- Action buttons for level 2 can be set by adding the `actions` key to the level 2 rows object.
+ The value for this key must also be an array of objects for each action button.
+
+Links must follow this structure:
+
+```javascript
+{
+ text: 'Click me',
+ href: this.someLinkHref,
+ target: '_blank', // Optional
+}
+```
+
+For internal action buttons, follow this structure:
+
+```javascript
+{
+ text: 'Click me',
+ onClick() {}
+}
+```
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index 72e20d31cf8..a5d211a5d2e 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/pipelines.md b/doc/development/pipelines.md
index a9c68905095..f3a4f47eb22 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -12,7 +12,7 @@ which itself includes files under
[`.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)
+We're striving to [dogfood](https://about.gitlab.com/handbook/engineering/principles/#dogfooding)
GitLab [CI/CD features and best-practices](../ci/yaml/index.md)
as much as possible.
@@ -90,6 +90,13 @@ In addition, there are a few circumstances where we would always run the full Je
- when any vendored JavaScript file is changed (i.e. `vendor/assets/javascripts/**/*`)
- when any backend file is changed ([see the patterns list for details](https://gitlab.com/gitlab-org/gitlab/-/blob/3616946936c1adbd9e754c1bd06f86ba670796d8/.gitlab/ci/rules.gitlab-ci.yml#L205-216))
+### Fork pipelines
+
+We only run the minimal RSpec & Jest jobs for fork pipelines unless the `pipeline:run-all-rspec`
+label is set on the MR. The goal is to reduce the CI minutes consumed by fork pipelines.
+
+See the [experiment issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1170).
+
## Fail-fast job in merge request pipelines
To provide faster feedback when a merge request breaks existing tests, we are experimenting with a
@@ -170,10 +177,23 @@ After that, the next pipeline uses the up-to-date `knapsack/report-master.json`
### Flaky tests
+#### Automatic skipping of flaky tests
+
Tests that are [known to be flaky](testing_guide/flaky_tests.md#automatic-retries-and-flaky-tests-detection) are
skipped unless the `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is set to `false` or if the `~"pipeline:run-flaky-tests"`
label is set on the MR.
+See the [experiment issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1069).
+
+#### Automatic retry of failing tests in a separate process
+
+When the `$RETRY_FAILED_TESTS_IN_NEW_PROCESS` variable is set to `true`, RSpec tests that failed are automatically retried once in a separate
+RSpec process. The goal is to get rid of most side-effects from previous tests that may lead to a subsequent test failure.
+
+We keep track of retried tests in the `$RETRIED_TESTS_REPORT_FILE` file saved as artifact by the `rspec:flaky-tests-report` job.
+
+See the [experiment issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1148).
+
### Monitoring
The GitLab test suite is [monitored](performance.md#rspec-profiling) for the `main` branch, and any branch
@@ -194,7 +214,7 @@ If you want to force a Review App to be deployed regardless of your changes, you
## As-if-FOSS jobs
The `* as-if-foss` jobs run the GitLab test suite "as if FOSS", meaning as if the jobs would run in the context
-of the `gitlab-org/gitlab-foss` project. These jobs are only created in the following cases:
+of `gitlab-org/gitlab-foss`. These jobs are only created in the following cases:
- when the `pipeline:run-as-if-foss` label is set on the merge request
- when the merge request is created in the `gitlab-org/security/gitlab` project
@@ -203,13 +223,12 @@ of the `gitlab-org/gitlab-foss` project. These jobs are only created in the foll
The `* as-if-foss` jobs are run in addition to the regular EE-context jobs. They have the `FOSS_ONLY='1'` variable
set and get the `ee/` folder removed before the tests start running.
-The intent is to ensure that a change doesn't introduce a failure after the `gitlab-org/gitlab` project is synced to
-the `gitlab-org/gitlab-foss` project.
+The intent is to ensure that a change doesn't introduce a failure after `gitlab-org/gitlab` is synced to `gitlab-org/gitlab-foss`.
## As-if-JH jobs
The `* as-if-jh` jobs run the GitLab test suite "as if JiHu", meaning as if the jobs would run in the context
-of [the `gitlab-jh/gitlab` project](jh_features_review.md). These jobs are only created in the following cases:
+of [GitLab JH](jh_features_review.md). These jobs are only created in the following cases:
- when the `pipeline:run-as-if-jh` label is set on the merge request
- when the `pipeline:run-all-rspec` label is set on the merge request
@@ -218,16 +237,18 @@ of [the `gitlab-jh/gitlab` project](jh_features_review.md). These jobs are only
The `* as-if-jh` jobs are run in addition to the regular EE-context jobs. The `jh/` folder is added before the tests start running.
-The intent is to ensure that a change doesn't introduce a failure after the `gitlab-org/gitlab` project is synced to
-the `gitlab-jh/gitlab` project.
+The intent is to ensure that a change doesn't introduce a failure after `gitlab-org/gitlab` is synced to [GitLab JH](https://jihulab.com/gitlab-cn/gitlab).
### Corresponding JH branch
-You can create a corresponding JH branch on the `gitlab-jh/gitlab` project by
+You can create a corresponding JH branch on [GitLab JH](https://jihulab.com/gitlab-cn/gitlab) by
appending `-jh` to the branch name. If a corresponding JH branch is found,
`* as-if-jh` jobs grab the `jh` folder from the respective branch,
rather than from the default branch.
+NOTE:
+For now, CI will try to fetch the branch on the [GitLab JH mirror](https://gitlab.com/gitlab-org/gitlab-jh/gitlab), so it might take some time for the new JH branch to propagate to the mirror.
+
## `undercover` RSpec test
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74859) in GitLab 14.6.
@@ -235,7 +256,7 @@ rather than from the default branch.
The `rspec:undercoverage` job runs [`undercover`](https://rubygems.org/gems/undercover)
to detect, and fail if any changes introduced in the merge request has zero coverage.
-The `rsepc:undercoverage` job obtains coverage data from the `rspec:coverage`
+The `rspec:undercoverage` job obtains coverage data from the `rspec:coverage`
job.
In the event of an emergency, or false positive from this job, add the
diff --git a/doc/development/policies.md b/doc/development/policies.md
index 61cc6e0edf5..c9e4fdb4350 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -111,7 +111,7 @@ Each line represents a rule that was evaluated. There are a few things to note:
Here you can see that the first four rules were evaluated `false` for
which user and subject. For example, you can see in the last line that
-the rule was activated because the user `john` had the Reporter [role](../user/permissions.md) on
+the rule was activated because the user `john` had the Reporter role on
`Project/4`.
When a policy is asked whether a particular ability is allowed
diff --git a/doc/development/product_qualified_lead_guide/index.md b/doc/development/product_qualified_lead_guide/index.md
new file mode 100644
index 00000000000..f9d18bacecd
--- /dev/null
+++ b/doc/development/product_qualified_lead_guide/index.md
@@ -0,0 +1,94 @@
+---
+stage: Growth
+group: Conversion
+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
+---
+
+# Product Qualified Lead (PQL) development guide
+
+The Product Qualified Lead (PQL) funnel connects our users with our team members. Read more about [PQL product principles](https://about.gitlab.com/handbook/product/product-principles/#product-qualified-leads-pqls).
+
+A hand-raise PQL is a user who requests to speak to sales from within the product.
+
+## Embed a hand-raise lead form
+
+[HandRaiseLeadButton](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue) is a reusable component that adds a button and a hand-raise modal to any screen.
+
+You can import a hand-raise lead button the following way.
+
+```javascript
+import HandRaiseLeadButton from 'ee/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue';
+
+export default {
+ components: {
+ HandRaiseLeadButton,
+...
+</script>
+
+<template>
+
+<hand-raise-lead-button />
+
+```
+
+The hand-raise lead form accepts the following parameters via provide or inject.
+
+```javascript
+ provide: {
+ user: {
+ namespaceId,
+ userName,
+ firstName,
+ lastName,
+ companyName,
+ glmContent,
+ },
+ },
+```
+
+### Monitor the lead location
+
+When embedding a new hand raise form, use a unique `glmContent` or `glm_content` field that is different to any existing values.
+
+We currently use the following `glm content` values:
+
+| glm_content value | Notes |
+| ------ | ------ |
+| discover-group-security | This value is used in the group security feature discovery page. |
+| discover-group-security-pqltest | This value is used in the group security feature discovery page [experiment with 3 CTAs](https://gitlab.com/gitlab-org/gitlab/-/issues/349799). |
+| discover-project-security | This value is used in the project security feature discovery page. |
+| discover-project-security-pqltest | This value is used in the project security feature discovery page [experiment with 3 CTAs](https://gitlab.com/gitlab-org/gitlab/-/issues/349799). |
+| group-billing | This value is used in the group billing page. |
+| trial-status-show-group | This value is used in the top left nav when a namespace has an active trial. |
+
+### Test the component
+
+In a jest test, you may test the presence of the component.
+
+```javascript
+expect(wrapper.findComponent(HandRaiseLeadButton).exists()).toBe(true);
+```
+
+## PQL lead flow
+
+The flow of a PQL lead is as follows:
+
+1. A user triggers a [`HandRaiseLeadButton` component](#embed-a-hand-raise-lead-form) on `gitlab.com`.
+1. The `HandRaiseLeadButton` submits any information to the following API endpoint: `/-/trials/create_hand_raise_lead`.
+1. That endpoint reposts the form to the CustomersDot `trials/create_hand_raise_lead` endpoint.
+1. CustomersDot records the form data to the `leads` table and posts the form to [Platypus](https://gitlab.com/gitlab-com/business-technology/enterprise-apps/integrations/platypus).
+1. Platypus posts the form to Workato (which is under the responsibility of the Business Operations team).
+1. Workato sends the form to Marketo.
+1. Marketo does scoring and sends the form to Salesforce.
+1. Our Sales team uses Salesforce to connect to the leads.
+
+## Monitor and manually test leads
+
+- Check the application and Sidekiq logs on `gitlab.com` and CustomersDot to monitor leads.
+- Check the `leads` table in CustomersDot.
+- Set up staging credentials for Platypus, and track the leads on the [Platypus Dashboard](https://staging.ci.nexus.gitlabenvironment.cloud/admin/queues/queue/new-lead-queue).
+- Ask for access to the Marketo Sandbox and validate the leads there.
+
+## Trials
+
+Trials follow the same flow as the PQL leads.
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index 789e0640933..deb743569c5 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -91,11 +91,6 @@ printer = RubyProf::CallStackPrinter.new(result)
printer.print(File.open('/tmp/profile.html', 'w'))
```
-[GitLab-Profiler](https://gitlab.com/gitlab-com/gitlab-profiler) is a project
-that builds on this to add some additional niceties, such as allowing
-configuration with a single YAML file for multiple URLs, and uploading of the
-profile and log output to S3.
-
## Speedscope flamegraphs
You can generate a flamegraph for a particular URL by selecting a flamegraph sampling mode button in the performance bar or by adding the `performance_bar=flamegraph` parameter to the request.
diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md
index da6ba14cdd8..b3f259efc3d 100644
--- a/doc/development/prometheus_metrics.md
+++ b/doc/development/prometheus_metrics.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/ruby_upgrade.md b/doc/development/ruby_upgrade.md
index 2102a256645..a208a93e300 100644
--- a/doc/development/ruby_upgrade.md
+++ b/doc/development/ruby_upgrade.md
@@ -272,4 +272,4 @@ and merged back independently.
- **Give yourself enough time to fix problems ahead of a milestone release.** GitLab moves fast.
As a Ruby upgrade requires many MRs to be sent and reviewed, make sure all changes are merged at least a week
before the 22nd. This gives us extra time to act if something breaks. If in doubt, it is better to
-postpone the upgrade to the following month, as we [prioritize availability over velocity](https://about.gitlab.com/handbook/engineering/#prioritizing-technical-decisions).
+postpone the upgrade to the following month, as we [prioritize availability over velocity](https://about.gitlab.com/handbook/engineering/principles/#prioritizing-technical-decisions).
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 7a3f3c7097d..fe7063be0e8 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -45,7 +45,7 @@ many groups or projects, and the access level (including guest, developer, or
maintainer) to groups and projects determines what users can see and
what they can access.
-Users with the administrator role can access all projects and even impersonate
+Users with administrator access can access all projects and even impersonate
users.
#### Sharding and partitioning
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 51d3338e5ed..d34b12c6361 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -184,13 +184,15 @@ and [possessive quantifiers](https://www.regular-expressions.info/possessive.htm
- Avoid nested quantifiers if possible (for example `(a+)+`)
- Try to be as precise as possible in your regex and avoid the `.` if there's an alternative
- For example, Use `_[^_]+_` instead of `_.*_` to match `_text here_`
+- Use reasonable ranges (for example, `{1,10}`) for repeating patterns instead of unbounded `*` and `+` matchers
+- When possible, perform simple input validation such as maximum string length checks before using regular expressions
- If in doubt, don't hesitate to ping `@gitlab-com/gl-security/appsec`
#### Go
Go's [`regexp`](https://pkg.go.dev/regexp) package uses `re2` and isn't vulnerable to backtracking issues.
-## Further Links
+### Further Links
- [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps.
- [Runaway Regular Expressions](https://www.regular-expressions.info/catastrophic.html)
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index c32789740c3..3a1e4c6d87b 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -793,6 +793,8 @@ The Service Ping JSON payload for GitLab.com is shared in the
You may also use the [Service Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs.
The dashboard allows filtering by GitLab version, by "Self-managed" and "SaaS", and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you can re-optimize your metric.
+Use [Metrics Dictionary](https://metrics.gitlab.com/) [copy query to clipboard feature](https://www.youtube.com/watch?v=n4o65ivta48&list=PL05JrBw4t0Krg3mbR6chU7pXtMt_es6Pb) to get a query ready to run in Sisense for a specific metric.
+
## Set up and test Service Ping locally
To set up Service Ping locally, you must:
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index 315ff2b090c..86e70cc8bbc 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -84,7 +84,7 @@ Registration is not yet required for participation, but will be added in a futur
#### Enable Registration Features
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
@@ -96,7 +96,7 @@ Registration is not yet required for participation, but will be added in a futur
You can view the exact JSON payload sent to GitLab Inc. in the Admin Area. To view the payload:
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
@@ -118,7 +118,7 @@ configuration file.
To disable Service Ping in the GitLab UI:
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
@@ -198,13 +198,32 @@ sequenceDiagram
## How Service Ping works
1. The Service Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_service_ping_worker.rb#L24) is set in Sidekiq to run weekly.
-1. When the cron job runs, it calls [`Gitlab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/service_ping/submit_service.rb#L49).
-1. `Gitlab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb) to ~400+ other counter method calls.
-1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L68) into a single JSON payload in `Gitlab::UsageData.to_json`.
+1. When the cron job runs, it calls [`Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/service_ping/submit_service.rb).
+1. `Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb) to ~400+ other counter method calls.
+1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L68) into a single JSON payload.
1. The JSON payload is then [posted to the Versions application](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/service_ping/submit_service.rb#L20)
If a firewall exception is needed, the required URL depends on several things. If
the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
the required URL is <https://version.gitlab.com/>.
+1. In case of an error, it will be reported to the Version application along with following pieces of information:
+
+- `uuid` - GitLab instance unique identifier
+- `hostname` - GitLab instance hostname
+- `version` - GitLab instance current versions
+- `elapsed` - Amount of time which passed since Service Ping report process started and moment of error occurrence
+- `message` - Error message
+
+<pre>
+<code>
+{
+ "uuid"=>"02333324-1cd7-4c3b-a45b-a4993f05fb1d",
+ "hostname"=>"127.0.0.1",
+ "version"=>"14.7.0-pre",
+ "elapsed"=>0.006946,
+ "message"=>'PG::UndefinedColumn: ERROR: column \"non_existent_attribute\" does not exist\nLINE 1: SELECT COUNT(non_existent_attribute) FROM \"issues\" /*applica...'
+}
+</code>
+</pre>
### On a Geo secondary site
@@ -510,7 +529,7 @@ To generate Service Ping, use [Teleport](https://goteleport.com/docs/) or a deta
### Verification (After approx 30 hours)
-#### Verify with a detached screen session
+#### Verify with Teleport
1. Follow [the steps](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/Teleport/Connect_to_Rails_Console_via_Teleport.md#how-to-use-teleport-to-connect-to-rails-console) to request a new access to the required environment and connect to the Rails console
1. Check the last payload in `raw_usage_data` table: `RawUsageData.last.payload`
@@ -557,6 +576,28 @@ skip_db_write:
ServicePing::SubmitService.new(skip_db_write: true).execute
```
+## Manually upload Service Ping payload
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7388) in GitLab 14.8 with a flag named `admin_application_settings_service_usage_data_center`. Disabled by default.
+
+Service Ping payload can be uploaded to GitLab even if your application instance doesn't have access to the internet,
+or you don't have Service Ping [cron job](#how-service-ping-works) enabled.
+
+To upload payload manually:
+
+1. Sign in as a user with administrator access.
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Service** usage data.
+1. Select **Download payload**.
+1. Save the JSON file.
+1. Visit [Service usage data center](https://version.gitlab.com/usage_data/new).
+1. Select **Choose file** and choose the file from p5.
+1. Select **Upload**.
+
+## Monitoring
+
+Service Ping reporting process state is monitored with [internal SiSense dashboard](https://app.periscopedata.com/app/gitlab/968489/Product-Intelligence---Service-Ping-Health).
+
## Troubleshooting
### Cannot disable Service Ping using the configuration file
diff --git a/doc/development/service_ping/metrics_dictionary.md b/doc/development/service_ping/metrics_dictionary.md
index 808c5064cf3..93eec4efabd 100644
--- a/doc/development/service_ping/metrics_dictionary.md
+++ b/doc/development/service_ping/metrics_dictionary.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Metrics Dictionary Guide
-[Service Ping](index.md) metrics are defined in the
-[Metrics Dictionary](https://metrics.gitlab.com/index.html).
+[Service Ping](index.md) metrics are defined in individual YAML files definitions from which the
+[Metrics Dictionary](https://metrics.gitlab.com/) is built.
This guide describes the dictionary and how it's implemented.
## Metrics Definition and validation
@@ -39,7 +39,7 @@ 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 `active`, `deprecated`, `removed`, `broken`. |
+| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `active`, `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`. The default value is `optional`.|
@@ -49,7 +49,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| `tier` | yes | `array`; may contain one or a combination of `free`, `premium` or `ultimate`. The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the tracked feature is available. This should be verbose and contain all tiers where a metric 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. |
+| `introduced_by_url` | no | The URL to the merge request that introduced the metric. |
| `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). |
@@ -60,7 +60,6 @@ Metric definitions can have one of the following statuses:
- `active`: Metric is used and reports data.
- `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.
-- `deprecated`: Metric is deprecated and possibly planned to be removed.
- `removed`: Metric was removed, but it may appear in Service Ping payloads sent from instances running on older versions of GitLab.
### Metric value_type
@@ -194,7 +193,7 @@ tier:
- ultimate
```
-## Create a new metric definition
+### Create a new metric definition
The GitLab codebase provides a dedicated [generator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/generators/gitlab/usage_metric_definition_generator.rb) to create new metric definitions.
@@ -229,7 +228,7 @@ bundle exec rails generate gitlab:usage_metric_definition counts.issues --ee --d
create ee/config/metrics/counts_7d/issues.yml
```
-## Metrics added dynamic to Service Ping payload
+### Metrics added dynamic to Service Ping payload
The [Redis HLL metrics](implement.md#known-events-are-added-automatically-in-service-data-payload) are added automatically to Service Ping payload.
@@ -250,3 +249,13 @@ bundle exec rails generate gitlab:usage_metric_definition:redis_hll issues users
create config/metrics/counts_7d/i_closed_weekly.yml
create config/metrics/counts_28d/i_closed_monthly.yml
```
+
+## Metrics Dictionary
+
+[Metrics Dictionary is a separate application](https://gitlab.com/gitlab-org/growth/product-intelligence/metric-dictionary).
+
+All metrics available in Service Ping are in the [Metrics Dictionary](https://metrics.gitlab.com/).
+
+### Copy query to clipboard
+
+To check if a metric has data in Sisense, use the copy query to clipboard feature. This copies a query that's ready to use in Sisense. The query gets the last five service ping data for GitLab.com for a given metric. For information about how to check if a Service Ping metric has data in Sisense, see this [demo](https://www.youtube.com/watch?v=n4o65ivta48).
diff --git a/doc/development/service_ping/metrics_lifecycle.md b/doc/development/service_ping/metrics_lifecycle.md
index ebfab6341e9..a7ecf15a493 100644
--- a/doc/development/service_ping/metrics_lifecycle.md
+++ b/doc/development/service_ping/metrics_lifecycle.md
@@ -14,6 +14,11 @@ Follow the [Implement Service Ping](implement.md) guide.
## Change an existing metric
+See [this video tutorial](https://youtu.be/bYf3c01KCls) for help with the update of metric attributes.
+
+NOTE:
+The `key_path` attribute represents the location of the metric in Service Ping payload and must not be changed.
+
Because we do not control when customers update their self-managed instances of GitLab,
we **STRONGLY DISCOURAGE** changes to the logic used to calculate any metric.
Any such changes lead to inconsistent reports from multiple GitLab instances.
@@ -85,10 +90,9 @@ To remove a metric:
1. Verify that removing the metric from the Service Ping payload does not cause
errors in [Version App](https://gitlab.com/gitlab-services/version-gitlab-com)
when the updated payload is collected and processed. Version App collects
- and persists all Service Ping reports. To do that you can modify
- [fixtures](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/spec/support/usage_data_helpers.rb#L540)
- used to test
- [`UsageDataController#create`](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/3760ef28/spec/controllers/usage_data_controller_spec.rb#L75)
+ and persists all Service Ping reports. To verify Service Ping processing in your local development environment, follow this [guide](https://www.youtube.com/watch?v=FS5emplabRU).
+ Alternatively, you can modify [fixtures](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/spec/support/usage_data_helpers.rb#L540)
+ used to test the [`UsageDataController#create`](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/3760ef28/spec/controllers/usage_data_controller_spec.rb#L75)
endpoint, and assure that test suite does not fail when metric that you wish to remove is not included into test payload.
1. Create an issue in the
diff --git a/doc/development/service_ping/review_guidelines.md b/doc/development/service_ping/review_guidelines.md
index eb64d460b5a..137e11608cf 100644
--- a/doc/development/service_ping/review_guidelines.md
+++ b/doc/development/service_ping/review_guidelines.md
@@ -14,7 +14,7 @@ general best practices for code reviews, refer to our [code review guide](../cod
## Resources for reviewers
- [Service Ping Guide](index.md)
-- [Metrics Dictionary](https://metrics.gitlab.com/index.html)
+- [Metrics Dictionary](https://metrics.gitlab.com/)
## Review process
diff --git a/doc/development/service_ping/troubleshooting.md b/doc/development/service_ping/troubleshooting.md
new file mode 100644
index 00000000000..770b6650764
--- /dev/null
+++ b/doc/development/service_ping/troubleshooting.md
@@ -0,0 +1,31 @@
+---
+stage: Growth
+group: Product Intelligence
+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
+
+## Service Ping Payload drop
+
+### Symptoms
+
+You will be alerted by a [Sisense alert](https://app.periscopedata.com/app/gitlab/alert/Service-ping-payload-drop-Alert/5a5b8766b8af43b4a75d6e9c684a365f/edit) that is sent to `#g_product_intelligence` Slack channel
+
+### Locating the problem
+
+First you need to identify at which stage in Service Ping data pipeline the drop is occurring.
+
+Start at [Service Ping Health Dashboard](https://app.periscopedata.com/app/gitlab/968489/Product-Intelligence---Service-Ping-Health) on Sisense.
+
+The alert compares the current daily value with the daily value from previous week, excluding the last 48 hours as this is the interval where we export the data in GCP and get it into DWH.
+
+You can use [this query](https://gitlab.com/gitlab-org/gitlab/-/issues/347298#note_836685350) as an example, to start detecting when the drop started.
+
+### Troubleshooting GitLab application layer
+
+For results about an investigation conducted into an unexpected drop in Service ping Payload events volume, see [this issue](https://gitlab.com/gitlab-data/analytics/-/issues/11071).
+
+### Troubleshooting data warehouse layer
+
+Reach out to the [Data team](https://about.gitlab.com/handbook/business-technology/data-team) to ask about current state of data warehouse. On their handbook page there is a [section with contact details](https://about.gitlab.com/handbook/business-technology/data-team/#how-to-connect-with-us).
diff --git a/doc/development/sidekiq/compatibility_across_updates.md b/doc/development/sidekiq/compatibility_across_updates.md
new file mode 100644
index 00000000000..919f6935139
--- /dev/null
+++ b/doc/development/sidekiq/compatibility_across_updates.md
@@ -0,0 +1,159 @@
+---
+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
+---
+
+# Sidekiq Compatibility across Updates
+
+The arguments for a Sidekiq job are stored in a queue while it is
+scheduled for execution. During a online update, this could lead to
+several possible situations:
+
+1. An older version of the application publishes a job, which is executed by an
+ upgraded Sidekiq node.
+1. A job is queued before an upgrade, but executed after an upgrade.
+1. A job is queued by a node running the newer version of the application, but
+ executed on a node running an older version of the application.
+
+## Adding new workers
+
+On GitLab.com, we [do not currently have a Sidekiq deployment in the
+canary stage](https://gitlab.com/gitlab-org/gitlab/-/issues/19239). This
+means that a new worker than can be scheduled from an HTTP endpoint may
+be scheduled from canary but not run on Sidekiq until the full
+production deployment is complete. This can be several hours later than
+scheduling the job. For some workers, this will not be a problem. For
+others - particularly [latency-sensitive
+jobs](worker_attributes.md#latency-sensitive-jobs) - this will result in a poor user
+experience.
+
+This only applies to new worker classes when they are first introduced.
+As we recommend [using feature flags](../feature_flags/) as a general
+development process, it's best to control the entire change (including
+scheduling of the new Sidekiq worker) with a feature flag.
+
+## Changing the arguments for a worker
+
+Jobs need to be backward and forward compatible between consecutive versions
+of the application. Adding or removing an argument may cause problems
+during deployment before all Rails and Sidekiq nodes have the updated code.
+
+### Deprecate and remove an argument
+
+**Before you remove arguments from the `perform_async` and `perform` methods.**, deprecate them. The
+following example deprecates and then removes `arg2` from the `perform_async` method:
+
+1. Provide a default value (usually `nil`) and use a comment to mark the
+ argument as deprecated in the coming minor release. (Release M)
+
+ ```ruby
+ class ExampleWorker
+ # Keep arg2 parameter for backwards compatibility.
+ def perform(object_id, arg1, arg2 = nil)
+ # ...
+ end
+ end
+ ```
+
+1. One minor release later, stop using the argument in `perform_async`. (Release M+1)
+
+ ```ruby
+ ExampleWorker.perform_async(object_id, arg1)
+ ```
+
+1. At the next major release, remove the value from the worker class. (Next major release)
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, arg1)
+ # ...
+ end
+ end
+ ```
+
+### Add an argument
+
+There are two options for safely adding new arguments to Sidekiq workers:
+
+1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker.
+1. Use a [parameter hash](#parameter-hash) for additional arguments. This is perhaps the most flexible option.
+
+#### Multi-step deployment
+
+This approach requires multiple releases.
+
+1. Add the argument to the worker with a default value (Release M).
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, new_arg = nil)
+ # ...
+ end
+ end
+ ```
+
+1. Add the new argument to all the invocations of the worker (Release M+1).
+
+ ```ruby
+ ExampleWorker.perform_async(object_id, new_arg)
+ ```
+
+1. Remove the default value (Release M+2).
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, new_arg)
+ # ...
+ end
+ end
+ ```
+
+#### Parameter hash
+
+This approach doesn't require multiple releases if an existing worker already
+uses a parameter hash.
+
+1. Use a parameter hash in the worker to allow future flexibility.
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, params = {})
+ # ...
+ end
+ end
+ ```
+
+## Removing workers
+
+Try to avoid removing workers and their queues in minor and patch
+releases.
+
+During online update instance can have pending jobs and removing the queue can
+lead to those jobs being stuck forever. If you can't write migration for those
+Sidekiq jobs, please consider removing the worker in a major release only.
+
+## Renaming queues
+
+For the same reasons that removing workers is dangerous, care should be taken
+when renaming queues.
+
+When renaming queues, use the `sidekiq_queue_migrate` helper migration method
+in a **post-deployment migration**:
+
+```ruby
+class MigrateTheRenamedSidekiqQueue < Gitlab::Database::Migration[1.0]
+ def up
+ sidekiq_queue_migrate 'old_queue_name', to: 'new_queue_name'
+ end
+
+ def down
+ sidekiq_queue_migrate 'new_queue_name', to: 'old_queue_name'
+ end
+end
+
+```
+
+You must rename the queue in a post-deployment migration not in a normal
+migration. Otherwise, it runs too early, before all the workers that
+schedule these jobs have stopped running. See also [other examples](../post_deployment_migrations.md#use-cases).
diff --git a/doc/development/sidekiq/idempotent_jobs.md b/doc/development/sidekiq/idempotent_jobs.md
new file mode 100644
index 00000000000..4b201e22ca9
--- /dev/null
+++ b/doc/development/sidekiq/idempotent_jobs.md
@@ -0,0 +1,208 @@
+---
+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
+---
+
+# Sidekiq idempotent jobs
+
+It's known that a job can fail for multiple reasons. For example, network outages or bugs.
+In order to address this, Sidekiq has a built-in retry mechanism that is
+used by default by most workers within GitLab.
+
+It's expected that a job can run again after a failure without major side-effects for the
+application or users, which is why Sidekiq encourages
+jobs to be [idempotent and transactional](https://github.com/mperham/sidekiq/wiki/Best-Practices#2-make-your-job-idempotent-and-transactional).
+
+As a general rule, a worker can be considered idempotent if:
+
+- It can safely run multiple times with the same arguments.
+- Application side-effects are expected to happen only once
+ (or side-effects of a second run do not have an effect).
+
+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.
+
+## Ensuring a worker is idempotent
+
+Make sure the worker tests pass using the following shared example:
+
+```ruby
+include_examples 'an idempotent worker' do
+ it 'marks the MR as merged' do
+ # Using subject inside this block will process the job multiple times
+ subject
+
+ expect(merge_request.state).to eq('merged')
+ end
+end
+```
+
+Use the `perform_multiple` method directly instead of `job.perform` (this
+helper method is automatically included for workers).
+
+## Declaring a worker as idempotent
+
+```ruby
+class IdempotentWorker
+ include ApplicationWorker
+
+ # Declares a worker is idempotent and can
+ # safely run multiple times.
+ idempotent!
+
+ # ...
+end
+```
+
+It's encouraged to only have the `idempotent!` call in the top-most worker class, even if
+the `perform` method is defined in another class or module.
+
+If the worker class isn't marked as idempotent, a cop fails. Consider skipping
+the cop if you're not confident your job can safely run multiple times.
+
+## Deduplication
+
+When a job for an idempotent worker is enqueued while another
+unstarted job is already in the queue, GitLab drops the second
+job. The work is skipped because the same work would be
+done by the job that was scheduled first; by the time the second
+job executed, the first job would do nothing.
+
+### Strategies
+
+GitLab supports two deduplication strategies:
+
+- `until_executing`
+- `until_executed`
+
+More [deduplication strategies have been
+suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195). If
+you are implementing a worker that could benefit from a different
+strategy, please comment in the issue.
+
+#### Until Executing
+
+This strategy takes a lock when a job is added to the queue, and removes that lock before the job starts.
+
+For example, `AuthorizedProjectsWorker` takes a user ID. When the
+worker runs, it recalculates a user's authorizations. GitLab schedules
+this job each time an action potentially changes a user's
+authorizations. If the same user is added to two projects at the
+same time, the second job can be skipped if the first job hasn't
+begun, because when the first job runs, it creates the
+authorizations for both projects.
+
+```ruby
+module AuthorizedProjectUpdate
+ class UserRefreshOverUserRangeWorker
+ include ApplicationWorker
+
+ deduplicate :until_executing
+ idempotent!
+
+ # ...
+ end
+end
+```
+
+#### Until Executed
+
+This strategy takes a lock when a job is added to the queue, and removes that lock after the job finishes.
+It can be used to prevent jobs from running simultaneously multiple times.
+
+```ruby
+module Ci
+ class BuildTraceChunkFlushWorker
+ include ApplicationWorker
+
+ deduplicate :until_executed
+ idempotent!
+
+ # ...
+ end
+end
+```
+
+Also, you can pass `if_deduplicated: :reschedule_once` option to re-run a job once after
+the currently running job finished and deduplication happened at least once.
+This ensures that the latest result is always produced even if a race condition
+happened. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342123) for more information.
+
+### Scheduling jobs in the future
+
+GitLab doesn't skip jobs scheduled in the future, as we assume that
+the state has changed by the time the job is scheduled to
+execute. Deduplication of jobs scheduled in the feature is possible
+for both `until_executed` and `until_executing` strategies.
+
+If you do want to deduplicate jobs scheduled in the future,
+this can be specified on the worker by passing `including_scheduled: true` argument
+when defining deduplication strategy:
+
+```ruby
+module AuthorizedProjectUpdate
+ class UserRefreshOverUserRangeWorker
+ include ApplicationWorker
+
+ deduplicate :until_executing, including_scheduled: true
+ idempotent!
+
+ # ...
+ end
+end
+```
+
+## Setting the deduplication time-to-live (TTL)
+
+Deduplication depends on an idempotency key that is stored in Redis. This is normally
+cleared by the configured deduplication strategy.
+
+However, the key can remain until its TTL in certain cases like:
+
+1. `until_executing` is used but the job was never enqueued or executed after the Sidekiq
+ client middleware was run.
+
+1. `until_executed` is used but the job fails to finish due to retry exhaustion, gets
+ interrupted the maximum number of times, or gets lost.
+
+The default value is 6 hours. During this time, jobs won't be enqueued even if the first
+job never executed or finished.
+
+The TTL can be configured with:
+
+```ruby
+class ProjectImportScheduleWorker
+ include ApplicationWorker
+
+ idempotent!
+ deduplicate :until_executing, ttl: 5.minutes
+end
+```
+
+Duplicate jobs can happen when the TTL is reached, so make sure you lower this only for jobs
+that can tolerate some duplication.
+
+### Preserve the latest WAL location for idempotent jobs
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69372) in GitLab 14.3.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.4.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.6.
+
+The deduplication always take into account the latest binary replication pointer, not the first one.
+This happens because we drop the same job scheduled for the second time and the Write-Ahead Log (WAL) is lost.
+This could lead to comparing the old WAL location and reading from a stale replica.
+
+To support both deduplication and maintaining data consistency with load balancing,
+we are preserving the latest WAL location for idempotent jobs in Redis.
+This way we are always comparing the latest binary replication pointer,
+making sure that we read from the replica that is fully caught up.
+
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to
+[disable the feature flag](../../administration/feature_flags.md) named `preserve_latest_wal_locations_for_idempotent_jobs`.
+
+This feature flag is related to GitLab development and is not intended to be used by GitLab administrators, though.
+On GitLab.com, this feature is available.
diff --git a/doc/development/sidekiq/index.md b/doc/development/sidekiq/index.md
new file mode 100644
index 00000000000..c9906c4c768
--- /dev/null
+++ b/doc/development/sidekiq/index.md
@@ -0,0 +1,190 @@
+---
+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
+---
+
+# Sidekiq guides
+
+We use [Sidekiq](https://github.com/mperham/sidekiq) as our background
+job processor. These guides are for writing jobs that will work well on
+GitLab.com and be consistent with our existing worker classes. For
+information on administering GitLab, see [configuring Sidekiq](../../administration/sidekiq.md).
+
+There are pages with additional detail on the following topics:
+
+1. [Compatibility across updates](compatibility_across_updates.md)
+1. [Job idempotency and job deduplication](idempotent_jobs.md)
+1. [Limited capacity worker: continuously performing work with a specified concurrency](limited_capacity_worker.md)
+1. [Logging](logging.md)
+1. [Worker attributes](worker_attributes.md)
+ 1. **Job urgency** specifies queuing and execution SLOs
+ 1. **Resource boundaries** and **external dependencies** for describing the workload
+ 1. **Feature categorization**
+ 1. **Database load balancing**
+
+## ApplicationWorker
+
+All workers should include `ApplicationWorker` instead of `Sidekiq::Worker`,
+which adds some convenience methods and automatically sets the queue based on
+the [routing rules](../../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
+
+## Retries
+
+Sidekiq defaults to using [25
+retries](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry),
+with back-off between each retry. 25 retries means that the last retry
+would happen around three weeks after the first attempt (assuming all 24
+prior retries failed).
+
+For most workers - especially [idempotent workers](idempotent_jobs.md) -
+the default of 25 retries is more than sufficient. Many of our older
+workers declare 3 retries, which used to be the default within the
+GitLab application. 3 retries happen over the course of a couple of
+minutes, so the jobs are prone to failing completely.
+
+A lower retry count may be applicable if any of the below apply:
+
+1. The worker contacts an external service and we do not provide
+ guarantees on delivery. For example, webhooks.
+1. The worker is not idempotent and running it multiple times could
+ leave the system in an inconsistent state. For example, a worker that
+ posts a system note and then performs an action: if the second step
+ fails and the worker retries, the system note will be posted again.
+1. The worker is a cronjob that runs frequently. For example, if a cron
+ job runs every hour, then we don't need to retry beyond an hour
+ because we don't need two of the same job running at once.
+
+Each retry for a worker is counted as a failure in our metrics. A worker
+which always fails 9 times and succeeds on the 10th would have a 90%
+error rate.
+
+## Sidekiq Queues
+
+Previously, each worker had its own queue, which was automatically set based on the
+worker class name. For a worker named `ProcessSomethingWorker`, the queue name
+would be `process_something`. You can now route workers to a specific queue using
+[queue routing rules](../../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
+In GDK, new workers are routed to a queue named `default`.
+
+If you're not sure what queue a worker uses,
+you can find it using `SomeWorker.queue`. There is almost never a reason to
+manually override the queue name using `sidekiq_options queue: :some_queue`.
+
+After adding a new worker, run `bin/rake
+gitlab:sidekiq:all_queues_yml:generate` to regenerate
+`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
+it can be picked up by
+[`sidekiq-cluster`](../../administration/operations/extra_sidekiq_processes.md)
+in installations that don't use routing rules. To learn more about potential changes,
+read [Use routing rules by default and deprecate queue selectors for self-managed](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/596).
+
+Additionally, run
+`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
+`config/sidekiq_queues.yml`.
+
+## Queue Namespaces
+
+While different workers cannot share a queue, they can share a queue namespace.
+
+Defining a queue namespace for a worker makes it possible to start a Sidekiq
+process that automatically handles jobs for all workers in that namespace,
+without needing to explicitly list all their queue names. If, for example, all
+workers that are managed by `sidekiq-cron` use the `cronjob` queue namespace, we
+can spin up a Sidekiq process specifically for these kinds of scheduled jobs.
+If a new worker using the `cronjob` namespace is added later on, the Sidekiq
+process also picks up jobs for that worker (after having been restarted),
+without the need to change any configuration.
+
+A queue namespace can be set using the `queue_namespace` DSL class method:
+
+```ruby
+class SomeScheduledTaskWorker
+ include ApplicationWorker
+
+ queue_namespace :cronjob
+
+ # ...
+end
+```
+
+Behind the scenes, this sets `SomeScheduledTaskWorker.queue` to
+`cronjob:some_scheduled_task`. Commonly used namespaces have their own
+concern module that can easily be included into the worker class, and that may
+set other Sidekiq options besides the queue namespace. `CronjobQueue`, for
+example, sets the namespace, but also disables retries.
+
+`bundle exec sidekiq` is namespace-aware, and listens on all
+queues in a namespace (technically: all queues prefixed with the namespace name)
+when a namespace is provided instead of a simple queue name in the `--queue`
+(`-q`) option, or in the `:queues:` section in `config/sidekiq_queues.yml`.
+
+Note that adding a worker to an existing namespace should be done with care, as
+the extra jobs take resources away from jobs from workers that were already
+there, if the resources available to the Sidekiq process handling the namespace
+are not adjusted appropriately.
+
+## Versioning
+
+Version can be specified on each Sidekiq worker class.
+This is then sent along when the job is created.
+
+```ruby
+class FooWorker
+ include ApplicationWorker
+
+ version 2
+
+ def perform(*args)
+ if job_version == 2
+ foo = args.first['foo']
+ else
+ foo = args.first
+ end
+ end
+end
+```
+
+Under this schema, any worker is expected to be able to handle any job that was
+enqueued by an older version of that worker. This means that when changing the
+arguments a worker takes, you must increment the `version` (or set `version 1`
+if this is the first time a worker's arguments are changing), but also make sure
+that the worker is still able to handle jobs that were queued with any earlier
+version of the arguments. From the worker's `perform` method, you can read
+`self.job_version` if you want to specifically branch on job version, or you
+can read the number or type of provided arguments.
+
+## Job size
+
+GitLab stores Sidekiq jobs and their arguments in Redis. To avoid
+excessive memory usage, we compress the arguments of Sidekiq jobs
+if their original size is bigger than 100KB.
+
+After compression, if their size still exceeds 5MB, it raises an
+[`ExceedLimitError`](https://gitlab.com/gitlab-org/gitlab/-/blob/f3dd89e5e510ea04b43ffdcb58587d8f78a8d77c/lib/gitlab/sidekiq_middleware/size_limiter/exceed_limit_error.rb#L8)
+error when scheduling the job.
+
+If this happens, rely on other means of making the data
+available in Sidekiq. There are possible workarounds such as:
+
+- Rebuild the data in Sidekiq with data loaded from the database or
+ elsewhere.
+- Store the data in [object storage](../file_storage.md#object-storage)
+ before scheduling the job, and retrieve it inside the job.
+
+## Job weights
+
+Some jobs have a weight declared. This is only used when running Sidekiq
+in the default execution mode - using
+[`sidekiq-cluster`](../../administration/operations/extra_sidekiq_processes.md)
+does not account for weights.
+
+As we are [moving towards using `sidekiq-cluster` in
+Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
+workers do not need to have weights specified. They can use the
+default weight, which is 1.
+
+## Tests
+
+Each Sidekiq worker must be tested using RSpec, just like any other class. These
+tests should be placed in `spec/workers`.
diff --git a/doc/development/sidekiq/limited_capacity_worker.md b/doc/development/sidekiq/limited_capacity_worker.md
new file mode 100644
index 00000000000..5b86e01781c
--- /dev/null
+++ b/doc/development/sidekiq/limited_capacity_worker.md
@@ -0,0 +1,84 @@
+---
+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
+---
+
+# Sidekiq limited capacity worker
+
+It is possible to limit the number of concurrent running jobs for a worker class
+by using the `LimitedCapacity::Worker` concern.
+
+The worker must implement three methods:
+
+- `perform_work`: The concern implements the usual `perform` method and calls
+ `perform_work` if there's any available capacity.
+- `remaining_work_count`: Number of jobs that have work to perform.
+- `max_running_jobs`: Maximum number of jobs allowed to run concurrently.
+
+```ruby
+class MyDummyWorker
+ include ApplicationWorker
+ include LimitedCapacity::Worker
+
+ def perform_work(*args)
+ end
+
+ def remaining_work_count(*args)
+ 5
+ end
+
+ def max_running_jobs
+ 25
+ end
+end
+```
+
+Additional to the regular worker, a cron worker must be defined as well to
+backfill the queue with jobs. the arguments passed to `perform_with_capacity`
+are passed to the `perform_work` method.
+
+```ruby
+class ScheduleMyDummyCronWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ def perform(*args)
+ MyDummyWorker.perform_with_capacity(*args)
+ end
+end
+```
+
+## How many jobs are running?
+
+It runs `max_running_jobs` at almost all times.
+
+The cron worker checks the remaining capacity on each execution and it
+schedules at most `max_running_jobs` jobs. Those jobs on completion
+re-enqueue themselves immediately, but not on failure. The cron worker is in
+charge of replacing those failed jobs.
+
+## Handling errors and idempotence
+
+This concern disables Sidekiq retries, logs the errors, and sends the job to the
+dead queue. This is done to have only one source that produces jobs and because
+the retry would occupy a slot with a job to perform in the distant future.
+
+We let the cron worker enqueue new jobs, this could be seen as our retry and
+back off mechanism because the job might fail again if executed immediately.
+This means that for every failed job, we run at a lower capacity
+until the cron worker fills the capacity again. If it is important for the
+worker not to get a backlog, exceptions must be handled in `#perform_work` and
+the job should not raise.
+
+The jobs are deduplicated using the `:none` strategy, but the worker is not
+marked as `idempotent!`.
+
+## Metrics
+
+This concern exposes three Prometheus metrics of gauge type with the worker class
+name as label:
+
+- `limited_capacity_worker_running_jobs`
+- `limited_capacity_worker_max_running_jobs`
+- `limited_capacity_worker_remaining_work_count`
diff --git a/doc/development/sidekiq/logging.md b/doc/development/sidekiq/logging.md
new file mode 100644
index 00000000000..015376b0fc6
--- /dev/null
+++ b/doc/development/sidekiq/logging.md
@@ -0,0 +1,155 @@
+---
+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
+---
+
+# Sidekiq logging
+
+## Worker context
+
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/9) in GitLab 12.8.
+
+To have some more information about workers in the logs, we add
+[metadata to the jobs in the form of an
+`ApplicationContext`](../logging.md#logging-context-metadata-through-rails-or-grape-requests).
+In most cases, when scheduling a job from a request, this context is already
+deducted from the request and added to the scheduled job.
+
+When a job runs, the context that was active when it was scheduled
+is restored. This causes the context to be propagated to any job
+scheduled from within the running job.
+
+All this means that in most cases, to add context to jobs, we don't
+need to do anything.
+
+There are however some instances when there would be no context
+present when the job is scheduled, or the context that is present is
+likely to be incorrect. For these instances, we've added Rubocop rules
+to draw attention and avoid incorrect metadata in our logs.
+
+As with most our cops, there are perfectly valid reasons for disabling
+them. In this case it could be that the context from the request is
+correct. Or maybe you've specified a context already in a way that
+isn't picked up by the cops. In any case, leave a code comment
+pointing to which context to use when disabling the cops.
+
+When you do provide objects to the context, make sure that the
+route for namespaces and projects is pre-loaded. This can be done by using
+the `.with_route` scope defined on all `Routable`s.
+
+### Cron workers
+
+The context is automatically cleared for workers in the cronjob queue
+(`include CronjobQueue`), even when scheduling them from
+requests. We do this to avoid incorrect metadata when other jobs are
+scheduled from the cron worker.
+
+Cron workers themselves run instance wide, so they aren't scoped to
+users, namespaces, projects, or other resources that should be added to
+the context.
+
+However, they often schedule other jobs that _do_ require context.
+
+That is why there needs to be an indication of context somewhere in
+the worker. This can be done by using one of the following methods
+somewhere within the worker:
+
+1. Wrap the code that schedules jobs in the `with_context` helper:
+
+ ```ruby
+ def perform
+ deletion_cutoff = Gitlab::CurrentSettings
+ .deletion_adjourned_period.days.ago.to_date
+ projects = Project.with_route.with_namespace
+ .aimed_for_deletion(deletion_cutoff)
+
+ projects.find_each(batch_size: 100).with_index do |project, index|
+ delay = index * INTERVAL
+
+ with_context(project: project) do
+ AdjournedProjectDeletionWorker.perform_in(delay, project.id)
+ end
+ end
+ end
+ ```
+
+1. Use the a batch scheduling method that provides context:
+
+ ```ruby
+ def schedule_projects_in_batch(projects)
+ ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
+ projects,
+ arguments_proc: -> (project) { project.id },
+ context_proc: -> (project) { { project: project } }
+ )
+ end
+ ```
+
+ Or, when scheduling with delays:
+
+ ```ruby
+ diffs.each_batch(of: BATCH_SIZE) do |diffs, index|
+ DeleteDiffFilesWorker
+ .bulk_perform_in_with_contexts(index * 5.minutes,
+ diffs,
+ arguments_proc: -> (diff) { diff.id },
+ context_proc: -> (diff) { { project: diff.merge_request.target_project } })
+ end
+ ```
+
+### Jobs scheduled in bulk
+
+Often, when scheduling jobs in bulk, these jobs should have a separate
+context rather than the overarching context.
+
+If that is the case, `bulk_perform_async` can be replaced by the
+`bulk_perform_async_with_context` helper, and instead of
+`bulk_perform_in` use `bulk_perform_in_with_context`.
+
+For example:
+
+```ruby
+ ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
+ projects,
+ arguments_proc: -> (project) { project.id },
+ context_proc: -> (project) { { project: project } }
+ )
+```
+
+Each object from the enumerable in the first argument is yielded into 2
+blocks:
+
+- The `arguments_proc` which needs to return the list of arguments the
+ job needs to be scheduled with.
+
+- The `context_proc` which needs to return a hash with the context
+ information for the job.
+
+## Arguments logging
+
+As of GitLab 13.6, Sidekiq job arguments are logged by default, unless [`SIDEKIQ_LOG_ARGUMENTS`](../../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
+is disabled.
+
+By default, the only arguments logged are numeric arguments, because
+arguments of other types could contain sensitive information. To
+override this, use `loggable_arguments` inside a worker with the indexes
+of the arguments to be logged. (Numeric arguments do not need to be
+specified here.)
+
+For example:
+
+```ruby
+class MyWorker
+ include ApplicationWorker
+
+ loggable_arguments 1, 3
+
+ # object_id will be logged as it's numeric
+ # string_a will be logged due to the loggable_arguments call
+ # string_b will be filtered from logs
+ # string_c will be logged due to the loggable_arguments call
+ def perform(object_id, string_a, string_b, string_c)
+ end
+end
+```
diff --git a/doc/development/sidekiq/worker_attributes.md b/doc/development/sidekiq/worker_attributes.md
new file mode 100644
index 00000000000..d681e17a053
--- /dev/null
+++ b/doc/development/sidekiq/worker_attributes.md
@@ -0,0 +1,325 @@
+---
+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
+---
+
+# Sidekiq worker attributes
+
+## Job urgency
+
+Jobs can have an `urgency` attribute set, which can be `:high`,
+`:low`, or `:throttled`. These have the below targets:
+
+| **Urgency** | **Queue Scheduling Target** | **Execution Latency Requirement** |
+|--------------|-----------------------------|------------------------------------|
+| `:high` | 10 seconds | p50 of 1 second, p99 of 10 seconds |
+| `:low` | 1 minute | Maximum run time of 5 minutes |
+| `:throttled` | None | Maximum run time of 5 minutes |
+
+To set a job's urgency, use the `urgency` class method:
+
+```ruby
+class HighUrgencyWorker
+ include ApplicationWorker
+
+ urgency :high
+
+ # ...
+end
+```
+
+### Latency sensitive jobs
+
+If a large number of background jobs get scheduled at once, queueing of jobs may
+occur while jobs wait for a worker node to be become available. This is normal
+and gives the system resilience by allowing it to gracefully handle spikes in
+traffic. Some jobs, however, are more sensitive to latency than others.
+
+In general, latency-sensitive jobs perform operations that a user could
+reasonably expect to happen synchronously, rather than asynchronously in a
+background worker. A common example is a write following an action. Examples of
+these jobs include:
+
+1. A job which updates a merge request following a push to a branch.
+1. A job which invalidates a cache of known branches for a project after a push
+ to the branch.
+1. A job which recalculates the groups and projects a user can see after a
+ change in permissions.
+1. A job which updates the status of a CI pipeline after a state change to a job
+ in the pipeline.
+
+When these jobs are delayed, the user may perceive the delay as a bug: for
+example, they may push a branch and then attempt to create a merge request for
+that branch, but be told in the UI that the branch does not exist. We deem these
+jobs to be `urgency :high`.
+
+Extra effort is made to ensure that these jobs are started within a very short
+period of time after being scheduled. However, in order to ensure throughput,
+these jobs also have very strict execution duration requirements:
+
+1. The median job execution time should be less than 1 second.
+1. 99% of jobs should complete within 10 seconds.
+
+If a worker cannot meet these expectations, then it cannot be treated as a
+`urgency :high` worker: consider redesigning the worker, or splitting the
+work between two different workers, one with `urgency :high` code that
+executes quickly, and the other with `urgency :low`, which has no
+execution latency requirements (but also has lower scheduling targets).
+
+### Changing a queue's urgency
+
+On GitLab.com, we run Sidekiq in several
+[shards](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail),
+each of which represents a particular type of workload.
+
+When changing a queue's urgency, or adding a new queue, we need to take
+into account the expected workload on the new shard. Note that, if we're
+changing an existing queue, there is also an effect on the old shard,
+but that always reduces work.
+
+To do this, we want to calculate the expected increase in total execution time
+and RPS (throughput) for the new shard. We can get these values from:
+
+- The [Queue Detail
+ dashboard](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)
+ has values for the queue itself. For a new queue, we can look for
+ queues that have similar patterns or are scheduled in similar
+ circumstances.
+- The [Shard Detail
+ dashboard](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)
+ has Total Execution Time and Throughput (RPS). The Shard Utilization
+ panel displays if there is currently any excess capacity for this
+ shard.
+
+We can then calculate the RPS * average runtime (estimated for new jobs)
+for the queue we're changing to see what the relative increase in RPS and
+execution time we expect for the new shard:
+
+```ruby
+new_queue_consumption = queue_rps * queue_duration_avg
+shard_consumption = shard_rps * shard_duration_avg
+
+(new_queue_consumption / shard_consumption) * 100
+```
+
+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.
+
+## Jobs with External Dependencies
+
+Most background jobs in the GitLab application communicate with other GitLab
+services. For example, PostgreSQL, Redis, Gitaly, and Object Storage. These are considered
+to be "internal" dependencies for a job.
+
+However, some jobs are dependent on external services in order to complete
+successfully. Some examples include:
+
+1. Jobs which call web-hooks configured by a user.
+1. Jobs which deploy an application to a k8s cluster configured by a user.
+
+These jobs have "external dependencies". This is important for the operation of
+the background processing cluster in several ways:
+
+1. Most external dependencies (such as web-hooks) do not provide SLOs, and
+ therefore we cannot guarantee the execution latencies on these jobs. Since we
+ cannot guarantee execution latency, we cannot ensure throughput and
+ therefore, in high-traffic environments, we need to ensure that jobs with
+ external dependencies are separated from high urgency jobs, to ensure
+ throughput on those queues.
+1. Errors in jobs with external dependencies have higher alerting thresholds as
+ there is a likelihood that the cause of the error is external.
+
+```ruby
+class ExternalDependencyWorker
+ include ApplicationWorker
+
+ # Declares that this worker depends on
+ # third-party, external services in order
+ # to complete successfully
+ worker_has_external_dependencies!
+
+ # ...
+end
+```
+
+A job cannot be both high urgency and have external dependencies.
+
+## CPU-bound and Memory-bound Workers
+
+Workers that are constrained by CPU or memory resource limitations should be
+annotated with the `worker_resource_boundary` method.
+
+Most workers tend to spend most of their time blocked, waiting on network responses
+from other services such as Redis, PostgreSQL, and Gitaly. Since Sidekiq is a
+multi-threaded environment, these jobs can be scheduled with high concurrency.
+
+Some workers, however, spend large amounts of time _on-CPU_ running logic in
+Ruby. Ruby MRI does not support true multi-threading - it relies on the
+[GIL](https://thoughtbot.com/blog/untangling-ruby-threads#the-global-interpreter-lock)
+to greatly simplify application development by only allowing one section of Ruby
+code in a process to run at a time, no matter how many cores the machine
+hosting the process has. For IO bound workers, this is not a problem, since most
+of the threads are blocked in underlying libraries (which are outside of the
+GIL).
+
+If many threads are attempting to run Ruby code simultaneously, this leads
+to contention on the GIL which has the effect of slowing down all
+processes.
+
+In high-traffic environments, knowing that a worker is CPU-bound allows us to
+run it on a different fleet with lower concurrency. This ensures optimal
+performance.
+
+Likewise, if a worker uses large amounts of memory, we can run these on a
+bespoke low concurrency, high memory fleet.
+
+Note that memory-bound workers create heavy GC workloads, with pauses of
+10-50ms. This has an impact on the latency requirements for the
+worker. For this reason, `memory` bound, `urgency :high` jobs are not
+permitted and fail CI. In general, `memory` bound workers are
+discouraged, and alternative approaches to processing the work should be
+considered.
+
+If a worker needs large amounts of both memory and CPU time, it should
+be marked as memory-bound, due to the above restriction on high urgency
+memory-bound workers.
+
+## Declaring a Job as CPU-bound
+
+This example shows how to declare a job as being CPU-bound.
+
+```ruby
+class CPUIntensiveWorker
+ include ApplicationWorker
+
+ # Declares that this worker will perform a lot of
+ # calculations on-CPU.
+ worker_resource_boundary :cpu
+
+ # ...
+end
+```
+
+## Determining whether a worker is CPU-bound
+
+We use the following approach to determine whether a worker is CPU-bound:
+
+- In the Sidekiq structured JSON logs, aggregate the worker `duration` and
+ `cpu_s` fields.
+- `duration` refers to the total job execution duration, in seconds
+- `cpu_s` is derived from the
+ [`Process::CLOCK_THREAD_CPUTIME_ID`](https://www.rubydoc.info/stdlib/core/Process:clock_gettime)
+ counter, and is a measure of time spent by the job on-CPU.
+- Divide `cpu_s` by `duration` to get the percentage time spend on-CPU.
+- If this ratio exceeds 33%, the worker is considered CPU-bound and should be
+ annotated as such.
+- Note that these values should not be used over small sample sizes, but
+ rather over fairly large aggregates.
+
+## Feature category
+
+All Sidekiq workers must define a known [feature category](../feature_categorization/index.md#sidekiq-workers).
+
+## Job data consistency strategies
+
+In GitLab 13.11 and earlier, Sidekiq workers would always send database queries to the primary
+database node,
+both for reads and writes. This ensured that data integrity
+is both guaranteed and immediate, since in a single-node scenario it is impossible to encounter
+stale reads even for workers that read their own writes.
+If a worker writes to the primary, but reads from a replica, however, the possibility
+of reading a stale record is non-zero due to replicas potentially lagging behind the primary.
+
+When the number of jobs that rely on the database increases, ensuring immediate data consistency
+can put unsustainable load on the primary database server. We therefore added the ability to use
+[Database Load Balancing for Sidekiq workers](../../administration/postgresql/database_load_balancing.md).
+By configuring a worker's `data_consistency` field, we can then allow the scheduler to target read replicas
+under several strategies outlined below.
+
+## Trading immediacy for reduced primary load
+
+We require Sidekiq workers to make an explicit decision around whether they need to use the
+primary database node for all reads and writes, or whether reads can be served from replicas. This is
+enforced by a RuboCop rule, which ensures that the `data_consistency` field is set.
+
+When setting this field, consider the following trade-off:
+
+- Ensure immediately consistent reads, but increase load on the primary database.
+- Prefer read replicas to add relief to the primary, but increase the likelihood of stale reads that have to be retried.
+
+To maintain the same behavior compared to before this field was introduced, set it to `:always`, so
+database operations will only target the primary. Reasons for having to do so include workers
+that mostly or exclusively perform writes, or workers that read their own writes and who might run
+into data consistency issues should a stale record be read back from a replica. **Try to avoid
+these scenarios, since `:always` should be considered the exception, not the rule.**
+
+To allow for reads to be served from replicas, we added two additional consistency modes: `:sticky` and `:delayed`.
+
+When you declare either `:sticky` or `:delayed` consistency, workers become eligible for database
+load-balancing.
+
+In both cases, if the replica is not up-to-date and the time from scheduling the job was less than the minimum delay interval,
+ the jobs sleep up to the minimum delay interval (0.8 seconds). This gives the replication process time to finish.
+The difference is in what happens when there is still replication lag after the delay: `sticky` workers
+switch over to the primary right away, whereas `delayed` workers fail fast and are retried once.
+If they still encounter replication lag, they also switch to the primary instead.
+**If your worker never performs any writes, it is strongly advised to apply one of these consistency settings,
+since it will never need to rely on the primary database node.**
+
+The table below shows the `data_consistency` attribute and its values, ordered by the degree to which
+they prefer read replicas and will wait for replicas to catch up:
+
+| **Data Consistency** | **Description** |
+|--------------|-----------------------------|
+| `:always` | The job is required to use the primary database (default). It should be used for workers that primarily perform writes or that have strict requirements around data consistency when reading their own writes. |
+| `:sticky` | The job prefers replicas, but switches to the primary for writes or when encountering replication lag. It should be used for jobs that require to be executed as fast as possible but can sustain a small initial queuing delay. |
+| `:delayed` | The job prefers replicas, but switches to the primary for writes. When encountering replication lag before the job starts, the job is retried once. If the replica is still not up to date on the next retry, it switches to the primary. It should be used for jobs where delaying execution further typically does not matter, such as cache expiration or web hooks execution. |
+
+In all cases workers read either from a replica that is fully caught up,
+or from the primary node, so data consistency is always ensured.
+
+To set a data consistency for a worker, use the `data_consistency` class method:
+
+```ruby
+class DelayedWorker
+ include ApplicationWorker
+
+ data_consistency :delayed
+
+ # ...
+end
+```
+
+### `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](../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](../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
+```
+
+### Data consistency with idempotent jobs
+
+For [idempotent jobs](idempotent_jobs.md) that declare either `:sticky` or `:delayed` data consistency, we are
+[preserving the latest WAL location](idempotent_jobs.md#preserve-the-latest-wal-location-for-idempotent-jobs) while deduplicating,
+ensuring that we read from the replica that is fully caught up.
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index af994e7138d..3756dd6b598 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -1,1101 +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
+redirect_to: 'sidekiq/index.md'
+remove_date: '2022-04-13'
---
-# Sidekiq Style Guide
+This document was moved to [another location](sidekiq/index.md).
-This document outlines various guidelines that should be followed when adding or
-modifying Sidekiq workers.
-
-## ApplicationWorker
-
-All workers should include `ApplicationWorker` instead of `Sidekiq::Worker`,
-which adds some convenience methods and automatically sets the queue based on
-the [routing rules](../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
-
-## Retries
-
-Sidekiq defaults to using [25
-retries](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry),
-with back-off between each retry. 25 retries means that the last retry
-would happen around three weeks after the first attempt (assuming all 24
-prior retries failed).
-
-For most workers - especially [idempotent workers](#idempotent-jobs) -
-the default of 25 retries is more than sufficient. Many of our older
-workers declare 3 retries, which used to be the default within the
-GitLab application. 3 retries happen over the course of a couple of
-minutes, so the jobs are prone to failing completely.
-
-A lower retry count may be applicable if any of the below apply:
-
-1. The worker contacts an external service and we do not provide
- guarantees on delivery. For example, webhooks.
-1. The worker is not idempotent and running it multiple times could
- leave the system in an inconsistent state. For example, a worker that
- posts a system note and then performs an action: if the second step
- fails and the worker retries, the system note will be posted again.
-1. The worker is a cronjob that runs frequently. For example, if a cron
- job runs every hour, then we don't need to retry beyond an hour
- because we don't need two of the same job running at once.
-
-Each retry for a worker is counted as a failure in our metrics. A worker
-which always fails 9 times and succeeds on the 10th would have a 90%
-error rate.
-
-## Sidekiq Queues
-
-Previously, each worker had its own queue, which was automatically set based on the
-worker class name. For a worker named `ProcessSomethingWorker`, the queue name
-would be `process_something`. You can now route workers to a specific queue using
-[queue routing rules](../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
-In GDK, new workers are routed to a queue named `default`.
-
-If you're not sure what queue a worker uses,
-you can find it using `SomeWorker.queue`. There is almost never a reason to
-manually override the queue name using `sidekiq_options queue: :some_queue`.
-
-After adding a new worker, run `bin/rake
-gitlab:sidekiq:all_queues_yml:generate` to regenerate
-`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
-it can be picked up by
-[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md)
-in installations that don't use routing rules. To learn more about potential changes,
-read [Use routing rules by default and deprecate queue selectors for self-managed](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/596).
-
-Additionally, run
-`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
-`config/sidekiq_queues.yml`.
-
-## Queue Namespaces
-
-While different workers cannot share a queue, they can share a queue namespace.
-
-Defining a queue namespace for a worker makes it possible to start a Sidekiq
-process that automatically handles jobs for all workers in that namespace,
-without needing to explicitly list all their queue names. If, for example, all
-workers that are managed by `sidekiq-cron` use the `cronjob` queue namespace, we
-can spin up a Sidekiq process specifically for these kinds of scheduled jobs.
-If a new worker using the `cronjob` namespace is added later on, the Sidekiq
-process also picks up jobs for that worker (after having been restarted),
-without the need to change any configuration.
-
-A queue namespace can be set using the `queue_namespace` DSL class method:
-
-```ruby
-class SomeScheduledTaskWorker
- include ApplicationWorker
-
- queue_namespace :cronjob
-
- # ...
-end
-```
-
-Behind the scenes, this sets `SomeScheduledTaskWorker.queue` to
-`cronjob:some_scheduled_task`. Commonly used namespaces have their own
-concern module that can easily be included into the worker class, and that may
-set other Sidekiq options besides the queue namespace. `CronjobQueue`, for
-example, sets the namespace, but also disables retries.
-
-`bundle exec sidekiq` is namespace-aware, and listens on all
-queues in a namespace (technically: all queues prefixed with the namespace name)
-when a namespace is provided instead of a simple queue name in the `--queue`
-(`-q`) option, or in the `:queues:` section in `config/sidekiq_queues.yml`.
-
-Note that adding a worker to an existing namespace should be done with care, as
-the extra jobs take resources away from jobs from workers that were already
-there, if the resources available to the Sidekiq process handling the namespace
-are not adjusted appropriately.
-
-## Versioning
-
-Version can be specified on each Sidekiq worker class.
-This is then sent along when the job is created.
-
-```ruby
-class FooWorker
- include ApplicationWorker
-
- version 2
-
- def perform(*args)
- if job_version == 2
- foo = args.first['foo']
- else
- foo = args.first
- end
- end
-end
-```
-
-Under this schema, any worker is expected to be able to handle any job that was
-enqueued by an older version of that worker. This means that when changing the
-arguments a worker takes, you must increment the `version` (or set `version 1`
-if this is the first time a worker's arguments are changing), but also make sure
-that the worker is still able to handle jobs that were queued with any earlier
-version of the arguments. From the worker's `perform` method, you can read
-`self.job_version` if you want to specifically branch on job version, or you
-can read the number or type of provided arguments.
-
-## Idempotent Jobs
-
-It's known that a job can fail for multiple reasons. For example, network outages or bugs.
-In order to address this, Sidekiq has a built-in retry mechanism that is
-used by default by most workers within GitLab.
-
-It's expected that a job can run again after a failure without major side-effects for the
-application or users, which is why Sidekiq encourages
-jobs to be [idempotent and transactional](https://github.com/mperham/sidekiq/wiki/Best-Practices#2-make-your-job-idempotent-and-transactional).
-
-As a general rule, a worker can be considered idempotent if:
-
-- It can safely run multiple times with the same arguments.
-- Application side-effects are expected to happen only once
- (or side-effects of a second run do not have an effect).
-
-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.
-
-### Ensuring a worker is idempotent
-
-Make sure the worker tests pass using the following shared example:
-
-```ruby
-include_examples 'an idempotent worker' do
- it 'marks the MR as merged' do
- # Using subject inside this block will process the job multiple times
- subject
-
- expect(merge_request.state).to eq('merged')
- end
-end
-```
-
-Use the `perform_multiple` method directly instead of `job.perform` (this
-helper method is automatically included for workers).
-
-### Declaring a worker as idempotent
-
-```ruby
-class IdempotentWorker
- include ApplicationWorker
-
- # Declares a worker is idempotent and can
- # safely run multiple times.
- idempotent!
-
- # ...
-end
-```
-
-It's encouraged to only have the `idempotent!` call in the top-most worker class, even if
-the `perform` method is defined in another class or module.
-
-If the worker class isn't marked as idempotent, a cop fails. Consider skipping
-the cop if you're not confident your job can safely run multiple times.
-
-### Deduplication
-
-When a job for an idempotent worker is enqueued while another
-unstarted job is already in the queue, GitLab drops the second
-job. The work is skipped because the same work would be
-done by the job that was scheduled first; by the time the second
-job executed, the first job would do nothing.
-
-#### Strategies
-
-GitLab supports two deduplication strategies:
-
-- `until_executing`
-- `until_executed`
-
-More [deduplication strategies have been
-suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195). If
-you are implementing a worker that could benefit from a different
-strategy, please comment in the issue.
-
-##### Until Executing
-
-This strategy takes a lock when a job is added to the queue, and removes that lock before the job starts.
-
-For example, `AuthorizedProjectsWorker` takes a user ID. When the
-worker runs, it recalculates a user's authorizations. GitLab schedules
-this job each time an action potentially changes a user's
-authorizations. If the same user is added to two projects at the
-same time, the second job can be skipped if the first job hasn't
-begun, because when the first job runs, it creates the
-authorizations for both projects.
-
-```ruby
-module AuthorizedProjectUpdate
- class UserRefreshOverUserRangeWorker
- include ApplicationWorker
-
- deduplicate :until_executing
- idempotent!
-
- # ...
- end
-end
-```
-
-##### Until Executed
-
-This strategy takes a lock when a job is added to the queue, and removes that lock after the job finishes.
-It can be used to prevent jobs from running simultaneously multiple times.
-
-```ruby
-module Ci
- class BuildTraceChunkFlushWorker
- include ApplicationWorker
-
- deduplicate :until_executed
- idempotent!
-
- # ...
- end
-end
-```
-
-Also, you can pass `if_deduplicated: :reschedule_once` option to re-run a job once after
-the currently running job finished and deduplication happened at least once.
-This ensures that the latest result is always produced even if a race condition
-happened. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342123) for more information.
-
-#### Scheduling jobs in the future
-
-GitLab doesn't skip jobs scheduled in the future, as we assume that
-the state has changed by the time the job is scheduled to
-execute. Deduplication of jobs scheduled in the feature is possible
-for both `until_executed` and `until_executing` strategies.
-
-If you do want to deduplicate jobs scheduled in the future,
-this can be specified on the worker by passing `including_scheduled: true` argument
-when defining deduplication strategy:
-
-```ruby
-module AuthorizedProjectUpdate
- class UserRefreshOverUserRangeWorker
- include ApplicationWorker
-
- deduplicate :until_executing, including_scheduled: true
- idempotent!
-
- # ...
- end
-end
-```
-
-### Setting the deduplication time-to-live (TTL)
-
-Deduplication depends on an idempotency key that is stored in Redis. This is normally
-cleared by the configured deduplication strategy.
-
-However, the key can remain until its TTL in certain cases like:
-
-1. `until_executing` is used but the job was never enqueued or executed after the Sidekiq
- client middleware was run.
-
-1. `until_executed` is used but the job fails to finish due to retry exhaustion, gets
- interrupted the maximum number of times, or gets lost.
-
-The default value is 6 hours. During this time, jobs won't be enqueued even if the first
-job never executed or finished.
-
-The TTL can be configured with:
-
-```ruby
-class ProjectImportScheduleWorker
- include ApplicationWorker
-
- idempotent!
- deduplicate :until_executing, ttl: 5.minutes
-end
-```
-
-Duplicate jobs can happen when the TTL is reached, so make sure you lower this only for jobs
-that can tolerate some duplication.
-
-### Deduplication with load balancing
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6763) in GitLab 14.4.
-
-Jobs that declare either `:sticky` or `:delayed` data consistency
-are eligible for database load-balancing.
-In both cases, jobs are [scheduled in the future](#scheduling-jobs-in-the-future) with a short delay (1 second).
-This minimizes the chance of replication lag after a write.
-
-If you really want to deduplicate jobs eligible for load balancing,
-specify `including_scheduled: true` argument when defining deduplication strategy:
-
-```ruby
-class DelayedIdempotentWorker
- include ApplicationWorker
- data_consistency :delayed
-
- deduplicate :until_executing, including_scheduled: true
- idempotent!
-
- # ...
-end
-```
-
-#### Preserve the latest WAL location for idempotent jobs
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69372) in GitLab 14.3.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.4.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.6.
-
-The deduplication always take into account the latest binary replication pointer, not the first one.
-This happens because we drop the same job scheduled for the second time and the Write-Ahead Log (WAL) is lost.
-This could lead to comparing the old WAL location and reading from a stale replica.
-
-To support both deduplication and maintaining data consistency with load balancing,
-we are preserving the latest WAL location for idempotent jobs in Redis.
-This way we are always comparing the latest binary replication pointer,
-making sure that we read from the replica that is fully caught up.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to
-[disable the feature flag](../administration/feature_flags.md) named `preserve_latest_wal_locations_for_idempotent_jobs`.
-
-This feature flag is related to GitLab development and is not intended to be used by GitLab administrators, though.
-On GitLab.com, this feature is available.
-
-## Limited capacity worker
-
-It is possible to limit the number of concurrent running jobs for a worker class
-by using the `LimitedCapacity::Worker` concern.
-
-The worker must implement three methods:
-
-- `perform_work`: The concern implements the usual `perform` method and calls
- `perform_work` if there's any available capacity.
-- `remaining_work_count`: Number of jobs that have work to perform.
-- `max_running_jobs`: Maximum number of jobs allowed to run concurrently.
-
-```ruby
-class MyDummyWorker
- include ApplicationWorker
- include LimitedCapacity::Worker
-
- def perform_work(*args)
- end
-
- def remaining_work_count(*args)
- 5
- end
-
- def max_running_jobs
- 25
- end
-end
-```
-
-Additional to the regular worker, a cron worker must be defined as well to
-backfill the queue with jobs. the arguments passed to `perform_with_capacity`
-are passed to the `perform_work` method.
-
-```ruby
-class ScheduleMyDummyCronWorker
- include ApplicationWorker
- include CronjobQueue
-
- def perform(*args)
- MyDummyWorker.perform_with_capacity(*args)
- end
-end
-```
-
-### How many jobs are running?
-
-It runs `max_running_jobs` at almost all times.
-
-The cron worker checks the remaining capacity on each execution and it
-schedules at most `max_running_jobs` jobs. Those jobs on completion
-re-enqueue themselves immediately, but not on failure. The cron worker is in
-charge of replacing those failed jobs.
-
-### Handling errors and idempotence
-
-This concern disables Sidekiq retries, logs the errors, and sends the job to the
-dead queue. This is done to have only one source that produces jobs and because
-the retry would occupy a slot with a job to perform in the distant future.
-
-We let the cron worker enqueue new jobs, this could be seen as our retry and
-back off mechanism because the job might fail again if executed immediately.
-This means that for every failed job, we run at a lower capacity
-until the cron worker fills the capacity again. If it is important for the
-worker not to get a backlog, exceptions must be handled in `#perform_work` and
-the job should not raise.
-
-The jobs are deduplicated using the `:none` strategy, but the worker is not
-marked as `idempotent!`.
-
-### Metrics
-
-This concern exposes three Prometheus metrics of gauge type with the worker class
-name as label:
-
-- `limited_capacity_worker_running_jobs`
-- `limited_capacity_worker_max_running_jobs`
-- `limited_capacity_worker_remaining_work_count`
-
-## Job urgency
-
-Jobs can have an `urgency` attribute set, which can be `:high`,
-`:low`, or `:throttled`. These have the below targets:
-
-| **Urgency** | **Queue Scheduling Target** | **Execution Latency Requirement** |
-|--------------|-----------------------------|------------------------------------|
-| `:high` | 10 seconds | p50 of 1 second, p99 of 10 seconds |
-| `:low` | 1 minute | Maximum run time of 5 minutes |
-| `:throttled` | None | Maximum run time of 5 minutes |
-
-To set a job's urgency, use the `urgency` class method:
-
-```ruby
-class HighUrgencyWorker
- include ApplicationWorker
-
- urgency :high
-
- # ...
-end
-```
-
-### Latency sensitive jobs
-
-If a large number of background jobs get scheduled at once, queueing of jobs may
-occur while jobs wait for a worker node to be become available. This is normal
-and gives the system resilience by allowing it to gracefully handle spikes in
-traffic. Some jobs, however, are more sensitive to latency than others.
-
-In general, latency-sensitive jobs perform operations that a user could
-reasonably expect to happen synchronously, rather than asynchronously in a
-background worker. A common example is a write following an action. Examples of
-these jobs include:
-
-1. A job which updates a merge request following a push to a branch.
-1. A job which invalidates a cache of known branches for a project after a push
- to the branch.
-1. A job which recalculates the groups and projects a user can see after a
- change in permissions.
-1. A job which updates the status of a CI pipeline after a state change to a job
- in the pipeline.
-
-When these jobs are delayed, the user may perceive the delay as a bug: for
-example, they may push a branch and then attempt to create a merge request for
-that branch, but be told in the UI that the branch does not exist. We deem these
-jobs to be `urgency :high`.
-
-Extra effort is made to ensure that these jobs are started within a very short
-period of time after being scheduled. However, in order to ensure throughput,
-these jobs also have very strict execution duration requirements:
-
-1. The median job execution time should be less than 1 second.
-1. 99% of jobs should complete within 10 seconds.
-
-If a worker cannot meet these expectations, then it cannot be treated as a
-`urgency :high` worker: consider redesigning the worker, or splitting the
-work between two different workers, one with `urgency :high` code that
-executes quickly, and the other with `urgency :low`, which has no
-execution latency requirements (but also has lower scheduling targets).
-
-### Changing a queue's urgency
-
-On GitLab.com, we run Sidekiq in several
-[shards](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail),
-each of which represents a particular type of workload.
-
-When changing a queue's urgency, or adding a new queue, we need to take
-into account the expected workload on the new shard. Note that, if we're
-changing an existing queue, there is also an effect on the old shard,
-but that always reduces work.
-
-To do this, we want to calculate the expected increase in total execution time
-and RPS (throughput) for the new shard. We can get these values from:
-
-- The [Queue Detail
- dashboard](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)
- has values for the queue itself. For a new queue, we can look for
- queues that have similar patterns or are scheduled in similar
- circumstances.
-- The [Shard Detail
- dashboard](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)
- has Total Execution Time and Throughput (RPS). The Shard Utilization
- panel displays if there is currently any excess capacity for this
- shard.
-
-We can then calculate the RPS * average runtime (estimated for new jobs)
-for the queue we're changing to see what the relative increase in RPS and
-execution time we expect for the new shard:
-
-```ruby
-new_queue_consumption = queue_rps * queue_duration_avg
-shard_consumption = shard_rps * shard_duration_avg
-
-(new_queue_consumption / shard_consumption) * 100
-```
-
-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 size
-
-GitLab stores Sidekiq jobs and their arguments in Redis. To avoid
-excessive memory usage, we compress the arguments of Sidekiq jobs
-if their original size is bigger than 100KB.
-
-After compression, if their size still exceeds 5MB, it raises an
-[`ExceedLimitError`](https://gitlab.com/gitlab-org/gitlab/-/blob/f3dd89e5e510ea04b43ffdcb58587d8f78a8d77c/lib/gitlab/sidekiq_middleware/size_limiter/exceed_limit_error.rb#L8)
-error when scheduling the job.
-
-If this happens, rely on other means of making the data
-available in Sidekiq. There are possible workarounds such as:
-
-- Rebuild the data in Sidekiq with data loaded from the database or
- elsewhere.
-- Store the data in [object storage](file_storage.md#object-storage)
- before scheduling the job, and retrieve it inside the job.
-
-## Job data consistency strategies
-
-In GitLab 13.11 and earlier, Sidekiq workers would always send database queries to the primary
-database node,
-both for reads and writes. This ensured that data integrity
-is both guaranteed and immediate, since in a single-node scenario it is impossible to encounter
-stale reads even for workers that read their own writes.
-If a worker writes to the primary, but reads from a replica, however, the possibility
-of reading a stale record is non-zero due to replicas potentially lagging behind the primary.
-
-When the number of jobs that rely on the database increases, ensuring immediate data consistency
-can put unsustainable load on the primary database server. We therefore added the ability to use
-[Database Load Balancing for Sidekiq workers](../administration/postgresql/database_load_balancing.md).
-By configuring a worker's `data_consistency` field, we can then allow the scheduler to target read replicas
-under several strategies outlined below.
-
-## Trading immediacy for reduced primary load
-
-We require Sidekiq workers to make an explicit decision around whether they need to use the
-primary database node for all reads and writes, or whether reads can be served from replicas. This is
-enforced by a RuboCop rule, which ensures that the `data_consistency` field is set.
-
-When setting this field, consider the following trade-off:
-
-- Ensure immediately consistent reads, but increase load on the primary database.
-- Prefer read replicas to add relief to the primary, but increase the likelihood of stale reads that have to be retried.
-
-To maintain the same behavior compared to before this field was introduced, set it to `:always`, so
-database operations will only target the primary. Reasons for having to do so include workers
-that mostly or exclusively perform writes, or workers that read their own writes and who might run
-into data consistency issues should a stale record be read back from a replica. **Try to avoid
-these scenarios, since `:always` should be considered the exception, not the rule.**
-
-To allow for reads to be served from replicas, we added two additional consistency modes: `:sticky` and `:delayed`.
-
-When you declare either `:sticky` or `:delayed` consistency, workers become eligible for database
-load-balancing. In both cases, jobs are enqueued with a short delay.
-This minimizes the likelihood of replication lag after a write.
-
-The difference is in what happens when there is replication lag after the delay: `sticky` workers
-switch over to the primary right away, whereas `delayed` workers fail fast and are retried once.
-If they still encounter replication lag, they also switch to the primary instead.
-**If your worker never performs any writes, it is strongly advised to apply one of these consistency settings,
-since it will never need to rely on the primary database node.**
-
-The table below shows the `data_consistency` attribute and its values, ordered by the degree to which
-they prefer read replicas and will wait for replicas to catch up:
-
-| **Data Consistency** | **Description** |
-|--------------|-----------------------------|
-| `:always` | The job is required to use the primary database (default). It should be used for workers that primarily perform writes or that have strict requirements around data consistency when reading their own writes. |
-| `:sticky` | The job prefers replicas, but switches to the primary for writes or when encountering replication lag. It should be used for jobs that require to be executed as fast as possible but can sustain a small initial queuing delay. |
-| `:delayed` | The job prefers replicas, but switches to the primary for writes. When encountering replication lag before the job starts, the job is retried once. If the replica is still not up to date on the next retry, it switches to the primary. It should be used for jobs where delaying execution further typically does not matter, such as cache expiration or web hooks execution. |
-
-In all cases workers read either from a replica that is fully caught up,
-or from the primary node, so data consistency is always ensured.
-
-To set a data consistency for a worker, use the `data_consistency` class method:
-
-```ruby
-class DelayedWorker
- include ApplicationWorker
-
- data_consistency :delayed
-
- # ...
-end
-```
-
-### `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
-```
-
-### Data consistency with idempotent jobs
-
-For [idempotent jobs](#idempotent-jobs) that declare either `:sticky` or `:delayed` data consistency, we are
-[preserving the latest WAL location](#preserve-the-latest-wal-location-for-idempotent-jobs) while deduplicating,
-ensuring that we read from the replica that is fully caught up.
-
-## Jobs with External Dependencies
-
-Most background jobs in the GitLab application communicate with other GitLab
-services. For example, PostgreSQL, Redis, Gitaly, and Object Storage. These are considered
-to be "internal" dependencies for a job.
-
-However, some jobs are dependent on external services in order to complete
-successfully. Some examples include:
-
-1. Jobs which call web-hooks configured by a user.
-1. Jobs which deploy an application to a k8s cluster configured by a user.
-
-These jobs have "external dependencies". This is important for the operation of
-the background processing cluster in several ways:
-
-1. Most external dependencies (such as web-hooks) do not provide SLOs, and
- therefore we cannot guarantee the execution latencies on these jobs. Since we
- cannot guarantee execution latency, we cannot ensure throughput and
- therefore, in high-traffic environments, we need to ensure that jobs with
- external dependencies are separated from high urgency jobs, to ensure
- throughput on those queues.
-1. Errors in jobs with external dependencies have higher alerting thresholds as
- there is a likelihood that the cause of the error is external.
-
-```ruby
-class ExternalDependencyWorker
- include ApplicationWorker
-
- # Declares that this worker depends on
- # third-party, external services in order
- # to complete successfully
- worker_has_external_dependencies!
-
- # ...
-end
-```
-
-A job cannot be both high urgency and have external dependencies.
-
-## CPU-bound and Memory-bound Workers
-
-Workers that are constrained by CPU or memory resource limitations should be
-annotated with the `worker_resource_boundary` method.
-
-Most workers tend to spend most of their time blocked, waiting on network responses
-from other services such as Redis, PostgreSQL, and Gitaly. Since Sidekiq is a
-multi-threaded environment, these jobs can be scheduled with high concurrency.
-
-Some workers, however, spend large amounts of time _on-CPU_ running logic in
-Ruby. Ruby MRI does not support true multi-threading - it relies on the
-[GIL](https://thoughtbot.com/blog/untangling-ruby-threads#the-global-interpreter-lock)
-to greatly simplify application development by only allowing one section of Ruby
-code in a process to run at a time, no matter how many cores the machine
-hosting the process has. For IO bound workers, this is not a problem, since most
-of the threads are blocked in underlying libraries (which are outside of the
-GIL).
-
-If many threads are attempting to run Ruby code simultaneously, this leads
-to contention on the GIL which has the effect of slowing down all
-processes.
-
-In high-traffic environments, knowing that a worker is CPU-bound allows us to
-run it on a different fleet with lower concurrency. This ensures optimal
-performance.
-
-Likewise, if a worker uses large amounts of memory, we can run these on a
-bespoke low concurrency, high memory fleet.
-
-Note that memory-bound workers create heavy GC workloads, with pauses of
-10-50ms. This has an impact on the latency requirements for the
-worker. For this reason, `memory` bound, `urgency :high` jobs are not
-permitted and fail CI. In general, `memory` bound workers are
-discouraged, and alternative approaches to processing the work should be
-considered.
-
-If a worker needs large amounts of both memory and CPU time, it should
-be marked as memory-bound, due to the above restriction on high urgency
-memory-bound workers.
-
-## Declaring a Job as CPU-bound
-
-This example shows how to declare a job as being CPU-bound.
-
-```ruby
-class CPUIntensiveWorker
- include ApplicationWorker
-
- # Declares that this worker will perform a lot of
- # calculations on-CPU.
- worker_resource_boundary :cpu
-
- # ...
-end
-```
-
-## Determining whether a worker is CPU-bound
-
-We use the following approach to determine whether a worker is CPU-bound:
-
-- In the Sidekiq structured JSON logs, aggregate the worker `duration` and
- `cpu_s` fields.
-- `duration` refers to the total job execution duration, in seconds
-- `cpu_s` is derived from the
- [`Process::CLOCK_THREAD_CPUTIME_ID`](https://www.rubydoc.info/stdlib/core/Process:clock_gettime)
- counter, and is a measure of time spent by the job on-CPU.
-- Divide `cpu_s` by `duration` to get the percentage time spend on-CPU.
-- If this ratio exceeds 33%, the worker is considered CPU-bound and should be
- annotated as such.
-- Note that these values should not be used over small sample sizes, but
- rather over fairly large aggregates.
-
-## Feature category
-
-All Sidekiq workers must define a known [feature category](feature_categorization/index.md#sidekiq-workers).
-
-## Job weights
-
-Some jobs have a weight declared. This is only used when running Sidekiq
-in the default execution mode - using
-[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md)
-does not account for weights.
-
-As we are [moving towards using `sidekiq-cluster` in
-Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
-workers do not need to have weights specified. They can use the
-default weight, which is 1.
-
-## Worker context
-
-> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/9) in GitLab 12.8.
-
-To have some more information about workers in the logs, we add
-[metadata to the jobs in the form of an
-`ApplicationContext`](logging.md#logging-context-metadata-through-rails-or-grape-requests).
-In most cases, when scheduling a job from a request, this context is already
-deducted from the request and added to the scheduled job.
-
-When a job runs, the context that was active when it was scheduled
-is restored. This causes the context to be propagated to any job
-scheduled from within the running job.
-
-All this means that in most cases, to add context to jobs, we don't
-need to do anything.
-
-There are however some instances when there would be no context
-present when the job is scheduled, or the context that is present is
-likely to be incorrect. For these instances, we've added Rubocop rules
-to draw attention and avoid incorrect metadata in our logs.
-
-As with most our cops, there are perfectly valid reasons for disabling
-them. In this case it could be that the context from the request is
-correct. Or maybe you've specified a context already in a way that
-isn't picked up by the cops. In any case, leave a code comment
-pointing to which context to use when disabling the cops.
-
-When you do provide objects to the context, make sure that the
-route for namespaces and projects is pre-loaded. This can be done by using
-the `.with_route` scope defined on all `Routable`s.
-
-### Cron workers
-
-The context is automatically cleared for workers in the cronjob queue
-(`include CronjobQueue`), even when scheduling them from
-requests. We do this to avoid incorrect metadata when other jobs are
-scheduled from the cron worker.
-
-Cron workers themselves run instance wide, so they aren't scoped to
-users, namespaces, projects, or other resources that should be added to
-the context.
-
-However, they often schedule other jobs that _do_ require context.
-
-That is why there needs to be an indication of context somewhere in
-the worker. This can be done by using one of the following methods
-somewhere within the worker:
-
-1. Wrap the code that schedules jobs in the `with_context` helper:
-
- ```ruby
- def perform
- deletion_cutoff = Gitlab::CurrentSettings
- .deletion_adjourned_period.days.ago.to_date
- projects = Project.with_route.with_namespace
- .aimed_for_deletion(deletion_cutoff)
-
- projects.find_each(batch_size: 100).with_index do |project, index|
- delay = index * INTERVAL
-
- with_context(project: project) do
- AdjournedProjectDeletionWorker.perform_in(delay, project.id)
- end
- end
- end
- ```
-
-1. Use the a batch scheduling method that provides context:
-
- ```ruby
- def schedule_projects_in_batch(projects)
- ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
- projects,
- arguments_proc: -> (project) { project.id },
- context_proc: -> (project) { { project: project } }
- )
- end
- ```
-
- Or, when scheduling with delays:
-
- ```ruby
- diffs.each_batch(of: BATCH_SIZE) do |diffs, index|
- DeleteDiffFilesWorker
- .bulk_perform_in_with_contexts(index * 5.minutes,
- diffs,
- arguments_proc: -> (diff) { diff.id },
- context_proc: -> (diff) { { project: diff.merge_request.target_project } })
- end
- ```
-
-### Jobs scheduled in bulk
-
-Often, when scheduling jobs in bulk, these jobs should have a separate
-context rather than the overarching context.
-
-If that is the case, `bulk_perform_async` can be replaced by the
-`bulk_perform_async_with_context` helper, and instead of
-`bulk_perform_in` use `bulk_perform_in_with_context`.
-
-For example:
-
-```ruby
- ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
- projects,
- arguments_proc: -> (project) { project.id },
- context_proc: -> (project) { { project: project } }
- )
-```
-
-Each object from the enumerable in the first argument is yielded into 2
-blocks:
-
-- The `arguments_proc` which needs to return the list of arguments the
- job needs to be scheduled with.
-
-- The `context_proc` which needs to return a hash with the context
- information for the job.
-
-## Arguments logging
-
-As of GitLab 13.6, Sidekiq job arguments are logged by default, unless [`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
-is disabled.
-
-By default, the only arguments logged are numeric arguments, because
-arguments of other types could contain sensitive information. To
-override this, use `loggable_arguments` inside a worker with the indexes
-of the arguments to be logged. (Numeric arguments do not need to be
-specified here.)
-
-For example:
-
-```ruby
-class MyWorker
- include ApplicationWorker
-
- loggable_arguments 1, 3
-
- # object_id will be logged as it's numeric
- # string_a will be logged due to the loggable_arguments call
- # string_b will be filtered from logs
- # string_c will be logged due to the loggable_arguments call
- def perform(object_id, string_a, string_b, string_c)
- end
-end
-```
-
-## Tests
-
-Each Sidekiq worker must be tested using RSpec, just like any other class. These
-tests should be placed in `spec/workers`.
-
-## Sidekiq Compatibility across Updates
-
-Keep in mind that the arguments for a Sidekiq job are stored in a queue while it
-is scheduled for execution. During a online update, this could lead to several
-possible situations:
-
-1. An older version of the application publishes a job, which is executed by an
- upgraded Sidekiq node.
-1. A job is queued before an upgrade, but executed after an upgrade.
-1. A job is queued by a node running the newer version of the application, but
- executed on a node running an older version of the application.
-
-### Adding new workers
-
-On GitLab.com, we [do not currently have a Sidekiq deployment in the
-canary stage](https://gitlab.com/gitlab-org/gitlab/-/issues/19239). This
-means that a new worker than can be scheduled from an HTTP endpoint may
-be scheduled from canary but not run on Sidekiq until the full
-production deployment is complete. This can be several hours later than
-scheduling the job. For some workers, this will not be a problem. For
-others - particularly [latency-sensitive
-jobs](#latency-sensitive-jobs) - this will result in a poor user
-experience.
-
-This only applies to new worker classes when they are first introduced.
-As we recommend [using feature flags](feature_flags/) as a general
-development process, it's best to control the entire change (including
-scheduling of the new Sidekiq worker) with a feature flag.
-
-### Changing the arguments for a worker
-
-Jobs need to be backward and forward compatible between consecutive versions
-of the application. Adding or removing an argument may cause problems
-during deployment before all Rails and Sidekiq nodes have the updated code.
-
-#### Deprecate and remove an argument
-
-**Before you remove arguments from the `perform_async` and `perform` methods.**, deprecate them. The
-following example deprecates and then removes `arg2` from the `perform_async` method:
-
-1. Provide a default value (usually `nil`) and use a comment to mark the
- argument as deprecated in the coming minor release. (Release M)
-
- ```ruby
- class ExampleWorker
- # Keep arg2 parameter for backwards compatibility.
- def perform(object_id, arg1, arg2 = nil)
- # ...
- end
- end
- ```
-
-1. One minor release later, stop using the argument in `perform_async`. (Release M+1)
-
- ```ruby
- ExampleWorker.perform_async(object_id, arg1)
- ```
-
-1. At the next major release, remove the value from the worker class. (Next major release)
-
- ```ruby
- class ExampleWorker
- def perform(object_id, arg1)
- # ...
- end
- end
- ```
-
-#### Add an argument
-
-There are two options for safely adding new arguments to Sidekiq workers:
-
-1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker.
-1. Use a [parameter hash](#parameter-hash) for additional arguments. This is perhaps the most flexible option.
-
-##### Multi-step deployment
-
-This approach requires multiple releases.
-
-1. Add the argument to the worker with a default value (Release M).
-
- ```ruby
- class ExampleWorker
- def perform(object_id, new_arg = nil)
- # ...
- end
- end
- ```
-
-1. Add the new argument to all the invocations of the worker (Release M+1).
-
- ```ruby
- ExampleWorker.perform_async(object_id, new_arg)
- ```
-
-1. Remove the default value (Release M+2).
-
- ```ruby
- class ExampleWorker
- def perform(object_id, new_arg)
- # ...
- end
- end
- ```
-
-##### Parameter hash
-
-This approach doesn't require multiple releases if an existing worker already
-uses a parameter hash.
-
-1. Use a parameter hash in the worker to allow future flexibility.
-
- ```ruby
- class ExampleWorker
- def perform(object_id, params = {})
- # ...
- end
- end
- ```
-
-### Removing workers
-
-Try to avoid removing workers and their queues in minor and patch
-releases.
-
-During online update instance can have pending jobs and removing the queue can
-lead to those jobs being stuck forever. If you can't write migration for those
-Sidekiq jobs, please consider removing the worker in a major release only.
-
-### Renaming queues
-
-For the same reasons that removing workers is dangerous, care should be taken
-when renaming queues.
-
-When renaming queues, use the `sidekiq_queue_migrate` helper migration method
-in a **post-deployment migration**:
-
-```ruby
-class MigrateTheRenamedSidekiqQueue < Gitlab::Database::Migration[1.0]
- def up
- sidekiq_queue_migrate 'old_queue_name', to: 'new_queue_name'
- end
-
- def down
- sidekiq_queue_migrate 'new_queue_name', to: 'old_queue_name'
- end
-end
-
-```
-
-You must rename the queue in a post-deployment migration not in a normal
-migration. Otherwise, it runs too early, before all the workers that
-schedule these jobs have stopped running. See also [other examples](post_deployment_migrations.md#use-cases).
+<!-- This redirect file can be deleted after <2022-04-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/snowplow/implementation.md b/doc/development/snowplow/implementation.md
index 439485c9e73..d35413cfd5f 100644
--- a/doc/development/snowplow/implementation.md
+++ b/doc/development/snowplow/implementation.md
@@ -18,21 +18,27 @@ to track custom events.
For the recommended frontend tracking implementation, see [Usage recommendations](#usage-recommendations).
+Structured events and page views include the [`gitlab_standard`](schemas.md#gitlab_standard)
+context, using the `window.gl.snowplowStandardContext` object which includes
+[default data](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/views/layouts/_snowplow.html.haml)
+as base. This object can be modified for any subsequent structured event fired,
+although it's not recommended.
+
Tracking implementations must have an `action` and a `category`. You can provide additional
-categories from the [structured event taxonomy](index.md#structured-event-taxonomy) with an `extra` object
-that accepts key-value pairs.
+properties from the [structured event taxonomy](index.md#structured-event-taxonomy), in
+addition to an `extra` object that accepts key-value pairs.
-| Field | Type | Default value | Description |
+| Property | Type | Default value | Description |
|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `category` | string | `document.body.dataset.page` | Page or subsection of a page in which events are captured. |
-| `action` | string | generic | Action the user is taking. Clicks must be `click` and activations must be `activate`. For example, focusing a form field is `activate_form_input`, and clicking a button is `click_button`. |
-| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, `context` as described in [Structured event taxonomy](index.md#structured-event-taxonomy), and `extra` (key-value pairs object). |
+| `action` | string | `'generic'` | Action the user is taking. Clicks must be `click` and activations must be `activate`. For example, focusing a form field is `activate_form_input`, and clicking a button is `click_button`. |
+| `data` | object | `{}` | Additional data such as `label`, `property`, `value` as described in [Structured event taxonomy](index.md#structured-event-taxonomy), `context` for custom contexts, and `extra` (key-value pairs object). |
### Usage recommendations
- Use [data attributes](#implement-data-attribute-tracking) on HTML elements that emit `click`, `show.bs.dropdown`, or `hide.bs.dropdown` events.
-- Use the [Vue mixin](#implement-vue-component-tracking) for tracking custom events, or if the supported events for data attributes are not propagating.
-- Use the [tracking class](#implement-raw-javascript-tracking) when tracking raw JavaScript files.
+- Use the [Vue mixin](#implement-vue-component-tracking) for tracking custom events, or if the supported events for data attributes are not propagating. For example, clickable components that don't emit `click`.
+- Use the [tracking class](#implement-raw-javascript-tracking) when tracking in vanilla JavaScript files.
### Implement data attribute tracking
@@ -42,6 +48,9 @@ The following example shows `data-track-*` attributes assigned to a button:
```haml
%button.btn{ data: { track: { action: "click_button", label: "template_preview", property: "my-template" } } }
+
+// or
+// %button.btn{ data: { track_action: "click_button", track_label: "template_preview", track_property: "my-template" } }
```
```html
@@ -62,7 +71,7 @@ The following example shows `data-track-*` attributes assigned to a button:
| `data-track-property` | false | Any additional property of the element, or object being acted on. |
| `data-track-value` | false | Describes a numeric value (decimal) directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. 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 pair object passed as a valid JSON string. This attribute is added to the `extra` property in our [`gitlab_standard`](schemas.md#gitlab_standard) schema. |
-| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](index.md#structured-event-taxonomy). |
+| `data-track-context` | false | To append a custom context object, passed as a valid JSON string. |
#### Event listeners
@@ -74,12 +83,19 @@ If click events stop propagating, you must implement listeners and [Vue componen
#### Helper methods
-Use the following Ruby helper:
+You can use the following Ruby helper:
```ruby
tracking_attrs(label, action, property) # { data: { track_label... } }
+```
+You can also use it on HAML templates:
+
+```haml
%button{ **tracking_attrs('main_navigation', 'click_button', 'navigation') }
+
+// When adding additional data
+// %button{ data: { platform: "...", **tracking_attrs('main_navigation', 'click_button', 'navigation') } }
```
If you use the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/tab_helper.rb#L76), you must wrap `html_options` under the `html_options` keyword argument. If you
@@ -91,7 +107,7 @@ use the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.
track_action: "click_button" })
# Good
-= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label:
+= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label:
"explore_groups", track_action: "click_button" } })
# Good (other helpers)
@@ -101,63 +117,64 @@ track_action: "click_button" })
### Implement Vue component tracking
-For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event`
-static method and the `track` method. You can specify tracking options in `data` or `computed`.
-These options override any defaults and allow the values to be dynamic from props or based on state.
-
-Several default options are passed when an event is tracked from the component:
+For custom event tracking, use the [Vue mixin](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/tracking.js#L207). It exposes `Tracking.event` as the `track` method.
+You can specify tracking options by creating a `tracking` data object or
+computed property, and as a second parameter: `this.track('click_button', opts)`.
+These options override any defaults and allow the values to be dynamic from props or based on state:
-- `category`: If you don't specify, by default `document.body.dataset.page` is used.
-- `label`
-- `property`
-- `value`
+| Property | Type | Default | Example |
+| -- | -- | -- | -- |
+| `category` | string | `document.body.dataset.page` | `'code_quality_walkthrough'` |
+| `label` | string | `''` | `'process_start_button'` |
+| `property` | string | `''` | `'asc'` or `'desc'` |
+| `value` | integer | `undefined` | `0`, `1`, `500` |
+| `extra` | object | `{}` | `{ selectedVariant: this.variant }` |
To implement Vue component tracking:
-1. Import the `Tracking` library and request a `mixin`:
+1. Import the `Tracking` library and call the `mixin` method:
```javascript
import Tracking from '~/tracking';
- const trackingMixin = Tracking.mixin;
- ```
-1. Provide categories to track the event from the component. For example, to track all events in a
-component with a label, use the `label` category:
+ const trackingMixin = Tracking.mixin();
- ```javascript
- import Tracking from '~/tracking';
- const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
+ // Optionally provide default properties
+ // const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
```
-1. In the component, declare the Vue `mixin`:
+1. Use the mixin in the component:
```javascript
export default {
mixins: [trackingMixin],
- // ...[component implementation]...
+ // Or
+ // mixins: [Tracking.mixin()],
+ // mixins: [Tracking.mixin({ label: 'right_sidebar' })],
+
data() {
return {
expanded: false,
- tracking: {
- label: 'left_sidebar',
- },
};
},
};
```
-1. To receive event data as a tracking object or computed property:
- - Declare it in the `data` function. Use a `tracking` object when default event properties are dynamic or provided at runtime:
+1. You can specify tracking options in by creating a `tracking` data object
+or computed property:
```javascript
export default {
name: 'RightSidebar',
+
mixins: [Tracking.mixin()],
+
data() {
return {
+ expanded: false,
+ variant: '',
tracking: {
label: 'right_sidebar',
- // category: '',
// property: '',
// value: '',
// experiment: '',
@@ -165,18 +182,28 @@ component with a label, use the `label` category:
},
};
},
+
+ // Or
+ // computed: {
+ // tracking() {
+ // return {
+ // property: this.variant,
+ // extra: { expanded: this.expanded },
+ // };
+ // },
+ // },
};
```
- - Declare it in the event data in the `track` function. This object merges with any previously provided options:
+1. Call the `track` method. Tracking options can be passed as the second parameter:
- ```javascript
- this.track('click_button', {
- label: 'right_sidebar',
- });
- ```
+ ```javascript
+ this.track('click_button', {
+ label: 'right_sidebar',
+ });
+ ```
-1. Optional. Use the `track` method in a template:
+ Or use the `track` method in the template:
```html
<template>
@@ -185,55 +212,67 @@ component with a label, use the `label` category:
<div v-if="expanded">
<p>Hello world!</p>
- <button @click="track('click_action')">Track another event</button>
+ <button @click="track('click_button')">Track another event</button>
</div>
</div>
</template>
```
-The following example shows an implementation of Vue component tracking:
+#### Testing example
```javascript
export default {
- name: 'RightSidebar',
- mixins: [Tracking.mixin({ label: 'right_sidebar' })],
+ name: 'CountDropdown',
+
+ mixins: [Tracking.mixin({ label: 'count_dropdown' })],
+
data() {
return {
- expanded: false,
+ variant: 'counter',
+ count: 0,
};
},
+
methods: {
- toggle() {
- this.expanded = !this.expanded;
- // Additional data will be merged, like `value` below
- this.track('click_toggle', { value: Number(this.expanded) });
- }
- }
+ handleChange({ target }) {
+ const { variant } = this;
+
+ this.count = Number(target.value);
+
+ this.track('change_value', {
+ value: this.count,
+ extra: { variant }
+ });
+ },
+ },
};
```
-#### Testing example
-
```javascript
import { mockTracking } from 'helpers/tracking_helper';
// mockTracking(category, documentOverride, spyMethod)
-describe('RightSidebar.vue', () => {
+describe('CountDropdown.vue', () => {
let trackingSpy;
let wrapper;
+ ...
+
beforeEach(() => {
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
- const findToggle = () => wrapper.find('[data-testid="toggle"]');
+ const findDropdown = () => wrapper.find('[data-testid="dropdown"]');
- it('tracks turning off toggle', () => {
- findToggle().trigger('click');
+ it('tracks change event', () => {
+ const dropdown = findDropdown();
+ dropdown.element.value = 30;
+ dropdown.trigger('change');
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_toggle', {
- label: 'right_sidebar',
- value: 0,
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'change_value', {
+ value: 30,
+ label: 'count_dropdown',
+ extra: { variant: 'counter' },
});
});
});
@@ -241,7 +280,8 @@ describe('RightSidebar.vue', () => {
### Implement raw JavaScript tracking
-To call custom event tracking and instrumentation directly from the JavaScript file, call the `Tracking.event` static function.
+To track from a vanilla JavaScript file, use the `Tracking.event` static function
+(calls [`dispatchSnowplowEvent`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/dispatch_snowplow_event.js)).
The following example demonstrates tracking a click on a button by manually calling `Tracking.event`.
@@ -251,7 +291,7 @@ import Tracking from '~/tracking';
const button = document.getElementById('create_from_template_button');
button.addEventListener('click', () => {
- Tracking.event('dashboard:projects:index', 'click_button', {
+ Tracking.event(undefined, 'click_button', {
label: 'create_from_template',
property: 'template_preview',
extra: {
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index dbc7a25075f..29f4514a21e 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -72,6 +72,7 @@ sequenceDiagram
GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk
end
GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose
+ Note over GitLab.com Snowplow Collector, S3 Bucket: Pseudonymization
S3 Bucket->>Snowflake DW: Import data
Snowflake DW->>Snowflake DW: Transform data using dbt
Snowflake DW->>Sisense Dashboards: Data available for querying
@@ -166,11 +167,24 @@ LIMIT 100
Snowplow JavaScript adds [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
+## Snowplow monitoring
+
+For different stages in the processing pipeline, there are several tools that monitor Snowplow events tracking:
+
+- [Product Intelligence Grafana dashboard](https://dashboards.gitlab.net/d/product-intelligence-main/product-intelligence-product-intelligence?orgId=1) monitors backend events sent from GitLab.com instance to collectors fleet. This dashboard provides information about:
+ - The number of events that successfully reach Snowplow collectors.
+ - The number of events that failed to reach Snowplow collectors.
+ - The number of backend events that were sent.
+- [AWS CloudWatch dashboard](https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#dashboards:name=SnowPlow;start=P3D) monitors the state of the events processing pipeline. The pipeline starts from Snowplow collectors, through to enrichers and pseudonymization, and up to persistence on S3 bucket from which events are imported to Snowflake Data Warehouse. To view this dashboard AWS access is required, follow this [instruction](https://gitlab.com/gitlab-org/growth/product-intelligence/snowplow-pseudonymization#monitoring) if you are interested in getting one.
+- [SiSense dashboard](https://app.periscopedata.com/app/gitlab/417669/Snowplow-Summary-Dashboard) provides information about the number of good and bad events imported into the Data Warehouse, in addition to the total number of imported Snowplow events.
+
+For more information, see this [video walk-through](https://www.youtube.com/watch?v=NxPS0aKa_oU).
+
## Related topics
- [Snowplow data structure](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)](https://metrics.gitlab.com/snowplow.html)
+- [List of events used in our codebase (Event Dictionary)](https://metrics.gitlab.com/snowplow/)
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Service Ping Guide](../service_ping/index.md)
- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
diff --git a/doc/development/snowplow/review_guidelines.md b/doc/development/snowplow/review_guidelines.md
index 69fad1794e2..0359636380b 100644
--- a/doc/development/snowplow/review_guidelines.md
+++ b/doc/development/snowplow/review_guidelines.md
@@ -14,7 +14,7 @@ general best practices for code reviews, refer to our [code review guide](../cod
## Resources for reviewers
- [Snowplow Guide](index.md)
-- [Event Dictionary](https://metrics.gitlab.com/snowplow.html)
+- [Event Dictionary](https://metrics.gitlab.com/snowplow/)
## Review process
diff --git a/doc/development/snowplow/schemas.md b/doc/development/snowplow/schemas.md
index eb57e7d98a5..63864c9329b 100644
--- a/doc/development/snowplow/schemas.md
+++ b/doc/development/snowplow/schemas.md
@@ -12,19 +12,23 @@ This page provides Snowplow schema reference for GitLab events.
We are including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details.
-The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application.
+The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb)
+class represents this schema in the application. Some properties are automatically populated for [frontend](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/views/layouts/_snowplow.html.haml)
+events.
-| Field Name | Required | Type | Description |
-|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------|
-| `project_id` | **{dotted-circle}** | integer | |
-| `namespace_id` | **{dotted-circle}** | integer | |
-| `user_id` | **{dotted-circle}** | integer | User database record ID attribute. This file undergoes a pseudonymization process at the collector level. |
-| `context_generated_at` | **{dotted-circle}** | string (date time format) | Timestamp indicating when context was generated. |
-| `environment` | **{check-circle}** | string (max 32 chars) | Name of the source environment, such as `production` or `staging` |
-| `source` | **{check-circle}** | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` |
-| `plan` | **{dotted-circle}** | string (max 32 chars) | Name of the plan for the namespace, such as `free`, `premium`, or `ultimate`. Automatically picked from the `namespace`. |
-| `google_analytics_id` | **{dotted-circle}** | string (max 32 chars) | Google Analytics ID, present when set from our marketing sites. |
-| `extra` | **{dotted-circle}** | JSON | Any additional data associated with the event, in the form of key-value pairs |
+| Field Name | Required | Default value | Type | Description |
+|----------------|:-------------------:|-----------------------|--|---------------------------------------------------------------------------------------------|
+| `project_id` | **{dotted-circle}** | Current project ID * | integer | |
+| `namespace_id` | **{dotted-circle}** | Current group/namespace ID * | integer | |
+| `user_id` | **{dotted-circle}** | Current user ID * | integer | User database record ID attribute. This file undergoes a pseudonymization process at the collector level. |
+| `context_generated_at` | **{dotted-circle}** | Current timestamp | string (date time format) | Timestamp indicating when context was generated. |
+| `environment` | **{check-circle}** | Current environment | string (max 32 chars) | Name of the source environment, such as `production` or `staging` |
+| `source` | **{check-circle}** | Event source | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` |
+| `plan` | **{dotted-circle}** | Current namespace plan * | string (max 32 chars) | Name of the plan for the namespace, such as `free`, `premium`, or `ultimate`. Automatically picked from the `namespace`. |
+| `google_analytics_id` | **{dotted-circle}** | GA ID value * | string (max 32 chars) | Google Analytics ID, present when set from our marketing sites. |
+| `extra` | **{dotted-circle}** | | JSON | Any additional data associated with the event, in the form of key-value pairs |
+
+_\* Default value present for frontend events only_
## Default Schema
diff --git a/doc/development/snowplow/troubleshooting.md b/doc/development/snowplow/troubleshooting.md
new file mode 100644
index 00000000000..75c8b306a67
--- /dev/null
+++ b/doc/development/snowplow/troubleshooting.md
@@ -0,0 +1,50 @@
+---
+stage: Growth
+group: Product Intelligence
+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
+
+## Good events drop
+
+### Symptoms
+
+You will be alarmed via a [Sisense alert](https://app.periscopedata.com/app/gitlab/alert/Volume-of-Snowplow-Good-events/5a5f80ef34fe450da5ebb84eaa84067f/edit) that is sent to `#g_product_intelligence` Slack channel
+
+### Locating the problem
+
+First you need to identify at which stage in Snowplow the data pipeline the drop is occurring.
+Start at [Snowplow dashboard](https://console.aws.amazon.com/systems-manager/resource-groups/cloudwatch?dashboard=SnowPlow&region=us-east-1#) on CloudWatch,
+if you do not have access to CloudWatch you need to create an [access request issue](https://gitlab.com/gitlab-com/team-member-epics/access-requests/-/issues/9730) first.
+While on CloudWatch dashboard set time range to last 4 weeks, to get better picture of system characteristics over time. Than visit following charts:
+
+1. `ELB New Flow Count` and `Collector Auto Scaling Group Network In/Out` - they show in order: number of connections to collectors via load balancers and data volume (in bytes) processed by collectors. If there is drop visible there, it means less events were fired from the GitLab application. Proceed to [application layer guide](#troubleshooting-gitlab-application-layer) for more details
+1. `Firehose Records to S3` - it shows how many event records were saved to S3 bucket, if there was drop on this chart but not on the charts from 1. it means that problem is located at AWS infrastructure layer, please refer to [AWS layer guide](#troubleshooting-aws-layer)
+1. If drop wasn't visible on any of previous charts it means that probelm is at data warehouse layer, please refer to [data warehouse layer guide](#troubleshooting-data-warehouse-layer)
+
+### Troubleshooting GitLab application layer
+
+Drop occurring at application layer can be symptom of some issue, but it might be also a result of normal application lifecycle, intended changes done to product intelligence or experiments tracking
+or even a result of a public holiday in some regions of the world with a larger user-base. To verify if there is an underlying problem to solve, you can check following things:
+
+1. Check `about.gitlab.com` website traffic on [Google Analytics](https://analytics.google.com/) to verify if some public holiday might impact overall use of GitLab system
+ 1. You may require to open an access request for Google Analytics access first eg: [access request internal issue](https://gitlab.com/gitlab-com/team-member-epics/access-requests/-/issues/1772)
+1. Plot `select date(dvce_created_tstamp) , event , count(*) from legacy.snowplow_unnested_events_90 where dvce_created_tstamp > '2021-06-15' and dvce_created_tstamp < '2021-07-10' group by 1 , 2 order by 1 , 2` in SiSense to see what type of events was responsible for drop
+1. Plot `select date(dvce_created_tstamp) ,se_category , count(*) from legacy.snowplow_unnested_events_90 where dvce_created_tstamp > '2021-06-15' and dvce_created_tstamp < '2021-07-31' and event = 'struct' group by 1 , 2 order by 1, 2` what events recorded the biggest drops in suspected category
+1. Check if there was any MR merged that might cause reduction in reported events, pay an attention to ~"product intelligence" and ~"growth experiment" labeled MRs
+1. Check (via [Grafana explore tab](https://dashboards.gitlab.net/explore) ) following Prometheus counters `gitlab_snowplow_events_total`, `gitlab_snowplow_failed_events_total` and `gitlab_snowplow_successful_events_total` to see how many events were fired correctly from GitLab.com. Example query to use `sum(rate(gitlab_snowplow_successful_events_total{env="gprd"}[5m])) / sum(rate(gitlab_snowplow_events_total{env="gprd"}[5m]))` would chart rate at which number of good events rose in comparison to events sent in total. If number drops from 1 it means that problem might be in communication between GitLab and AWS collectors fleet.
+1. Check [logs in Kibana](https://log.gprd.gitlab.net/app/discover#) and filter with `{ "query": { "match_phrase": { "json.message": "failed to be reported to collector at" } } }` if there are some failed events logged
+
+For results about an investigation conducted into an unexpected drop in snowplow events volume, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/335206).
+
+### Troubleshooting AWS layer
+
+Already conducted investigations:
+
+- [Steep decrease of Snowplow page views](https://gitlab.com/gitlab-org/gitlab/-/issues/268009)
+- [`snowplow.trx.gitlab.net` unreachable](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5073)
+
+### Troubleshooting data warehouse layer
+
+Reach out to [Data team](https://about.gitlab.com/handbook/business-technology/data-team) to ask about current state of data warehouse. On their handbook page there is a [section with contact details](https://about.gitlab.com/handbook/business-technology/data-team/#how-to-connect-with-us)
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index 88e9141574e..744d049f72d 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -64,8 +64,8 @@ component can have 2 indicators:
[customize the request Apdex](application_slis/rails_request_apdex.md), this new Apdex
measurement is not yet part of the error budget.
- For Sidekiq job execution, the threshold depends on the [job
- urgency](sidekiq_style_guide.md#job-urgency). It is
+ For Sidekiq job execution, the threshold depends on the
+ [job urgency](sidekiq/worker_attributes.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.
diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md
index 543feaa967c..405ff40ef6a 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -363,11 +363,11 @@ after(:all) do
end
```
-## Tag tests that require the Administrator role
+## Tag tests that require administrator access
-We don't run tests that require the Administrator role against our Production environments.
+We don't run tests that require administrator access against our Production environments.
-When you add a new test that requires the Administrator role, apply the RSpec metadata `:requires_admin` so that the test will not be included in the test suites executed against Production and other environments on which we don't want to run those tests.
+When you add a new test that requires administrator access, apply the RSpec metadata `:requires_admin` so that the test will not be included in the test suites executed against Production and other environments on which we don't want to run those tests.
When running tests locally or configuring a pipeline, the environment variable `QA_CAN_TEST_ADMIN_FEATURES` can be set to `false` to skip tests that have the `:requires_admin` tag.
diff --git a/doc/development/testing_guide/end_to_end/execution_context_selection.md b/doc/development/testing_guide/end_to_end/execution_context_selection.md
index 8456cfa8314..0fdcf0c8c3b 100644
--- a/doc/development/testing_guide/end_to_end/execution_context_selection.md
+++ b/doc/development/testing_guide/end_to_end/execution_context_selection.md
@@ -120,3 +120,5 @@ Similarly to specifying that a test should only run against a specific environme
test only when it runs against a specific environment. The syntax is exactly the same, except that the `only: { ... }`
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests) hash.
For example, `quarantine: { only: { subdomain: :staging } }` only quarantines the test when run against `staging`.
+
+The quarantine feature can be explicitly disabled with the `DISABLE_QUARANTINE` environment variable. This can be useful when running tests locally.
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 48157a961e1..238b1ccd8f9 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -144,6 +144,14 @@ end
After the feature flag is removed, clean up the resource class and delete the variable.
All methods should use the condition procedures of the now-default state.
+## Managing flakiness due to caching
+
+All application settings, and all feature flags, are cached inside GitLab for one minute.
+All caching is disabled during testing, except on static environments.
+
+When a test changes a feature flag, it can cause flaky behavior if elements are visible only with an
+active feature flag. To circumvent this behavior, add a wait for elements behind a feature flag.
+
## Running a scenario with a feature flag enabled
It's also possible to run an entire scenario with a feature flag enabled, without having to edit
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index 1fc9bc8258a..dc989acbdcc 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -101,19 +101,19 @@ This is due to technical limitations in the GitLab permission model: the ability
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 the
-[Maintainer role](../../../user/permissions.md) for those projects.
+Maintainer role 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"
work-around was suggested in <https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4717>.
A feature proposal to segregate access control regarding running pipelines from ability to push/merge was also created at <https://gitlab.com/gitlab-org/gitlab/-/issues/24585>.
-#### With Pipeline for Merged Results
+#### With merged results pipelines
-In a Pipeline for Merged Results, the pipeline runs on a new ref that contains the merge result of the source and target branch.
+In a merged results pipeline, the pipeline runs on a new ref that contains the merge result of the source and target branch.
However, this ref is not available to the `gitlab-qa-mirror` pipeline.
-For this reason, the end-to-end tests on a Pipeline for Merged Results would use the head of the merge request source branch.
+For this reason, the end-to-end tests on a merged results pipeline would use the head of the merge request source branch.
```mermaid
graph LR
@@ -126,7 +126,7 @@ A --> C
B --> C
A --> E["E2E tests"]
-C --> D["Pipeline for merged results"]
+C --> D["Merged results pipeline"]
```
##### Running custom tests
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
index abba1d51f07..e2b005d8a1b 100644
--- a/doc/development/testing_guide/end_to_end/resources.md
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -431,11 +431,32 @@ module QA
def validate_reuse_preconditions
raise ResourceReuseError unless reused_name_valid?
end
+
+ # Internally we identify an instance of a reusable resource by a unique value of `@reuse_as`, but in GitLab the
+ # resource has one or more attributes that must also be unique. This method lists those attributes and allows the
+ # test framework to check that each instance of a reusable resource has values that match the associated values
+ # in Gitlab.
+ def unique_identifiers
+ [:name, :path]
+ end
end
end
end
```
+Reusable resources aren't removed immediately when `remove_via_api!` is called. Instead, they're removed after the test
+suite completes. To do so each class must be registered with `QA::Resource::ReusableCollection` in `qa/spec/spec_helper.rb`
+as in the example below. Registration allows `QA::Resource::ReusableCollection` to keep track of each instance of each
+registered class, and to delete them all in the `config.after(:suite)` hook.
+
+```ruby
+config.before(:suite) do |suite|
+ QA::Resource::ReusableCollection.register_resource_classes do |collection|
+ QA::Resource::ReusableProject.register(collection)
+ end
+end
+```
+
Consider some examples of how a reusable resource is used:
```ruby
@@ -488,6 +509,65 @@ end
# match the name specified when the project was first fabricated.
```
+### Validating reusable resources
+
+Reusable resources can speed up test suites by avoiding the cost of creating the same resource again and again. However,
+that can cause problems if a test makes changes to a resource that prevent it from being reused as expected by later
+tests. That can lead to order-dependent test failures that can be difficult to troubleshoot.
+
+For example, the default project created by `QA::Resource::ReusableProject` has `auto_devops_enabled` set to `false`
+(inherited from `QA::Resource::Project`). If a test reuses that project and enables Auto DevOps, subsequent tests that reuse
+the project will fail if they expect Auto DevOps to be disabled.
+
+We try to avoid that kind of trouble by validating reusable resources after a test suite. If the environment variable
+`QA_VALIDATE_RESOURCE_REUSE` is set to `true` the test framework will check each reusable resource to verify that none
+of the attributes they were created with have been changed. It does that by creating a new resource using the same
+attributes that were used to create the original resource. It then compares the new resource to the original and raises
+an error if any attributes don't match.
+
+#### Implementation
+
+When you implement a new type of reusable resource there are two `private` methods you must implement so the resource
+can be validated. They are:
+
+- `reference_resource`: creates a new instance of the resource that can be compared with the one that was used during the tests.
+- `unique_identifiers`: returns an array of attributes that allow the resource to be identified (e.g., name) and that are therefore
+expected to differ when comparing the reference resource with the resource reused in the tests.
+
+The following example shows the implementation of those two methods in `QA::Resource::ReusableProject`.
+
+```ruby
+# Creates a new project that can be compared to a reused project, using the attributes of the original.
+#
+# @return [QA::Resource] a new instance of Resource::ReusableProject that should be a copy of the original resource
+def reference_resource
+ # These are the attributes that the reused resource was created with
+ attributes = self.class.resources[reuse_as][:attributes]
+
+ # Two projects can't have the same path, and since we typically use the same value for the name and path, we assign
+ # a unique name and path to the reference resource.
+ name = "reference_resource_#{SecureRandom.hex(8)}_for_#{attributes.delete(:name)}"
+
+ Project.fabricate_via_api! do |project|
+ self.class.resources[reuse_as][:attributes].each do |attribute_name, attribute_value|
+ project.instance_variable_set("@#{attribute_name}", attribute_value) if attribute_value
+ end
+ project.name = name
+ project.path = name
+ project.path_with_namespace = "#{project.group.full_path}/#{project.name}"
+ end
+end
+
+# The attributes of the resource that should be the same whenever a test wants to reuse a project.
+#
+# @return [Array<Symbol>] the attribute names.
+def unique_identifiers
+ # As noted above, path must be unique, and since we typically use the same value for both, we treat name and path
+ # as unique. These attributes are ignored when we compare the reference and reused resources.
+ [:name, :path]
+end
+```
+
## Where to ask for help?
If you need more information, ask for help on `#quality` channel on Slack
diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
index bb214976926..07f7e9582ee 100644
--- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
+++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
@@ -20,6 +20,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:github` | The test requires a GitHub personal access token. |
| `:group_saml` | The test requires a GitLab instance that has SAML SSO enabled at the group level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
| `:instance_saml` | The test requires a GitLab instance that has SAML SSO enabled at the instance level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
+| `:integrations` | This aims to test the available [integrations](../../../user/project/integrations/overview.md#integrations-listing). The test requires Docker to be installed in the run context. It will provision the containers and can be run against a local instance or using the `gitlab-qa` scenario `Test::Integration::Integrations` |
| `:service_ping_disabled` | The test interacts with the GitLab configuration service ping at the instance level to turn admin setting service ping checkbox on or off. This tag will have the test run only in the `service_ping_disabled` job and must be paired with the `:orchestrated` and `:requires_admin` tags. |
| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) provisions the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run.
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test also includes provisioning of at least one Kubernetes cluster to test against. _This tag is often be paired with `:orchestrated`._ |
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 ef3e0624395..7fb95769fc2 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
@@ -141,6 +141,34 @@ docker stop gitlab-gitaly-cluster praefect postgres gitaly3 gitaly2 gitaly1
docker rm gitlab-gitaly-cluster praefect postgres gitaly3 gitaly2 gitaly1
```
+## Tests that require a runner
+
+To execute tests that use a runner without errors, while creating the GitLab Docker instance the `--hostname` parameter in the Docker `run` command should be given a specific interface IP address or a non-loopback hostname accessible from the runner container. Having `localhost` (or `127.0.0.1`) as the GitLab hostname won't work (unless the GitLab Runner is created with the Docker network as `host`)
+
+Examples of tests which require a runner:
+
+- `qa/qa/specs/features/ee/browser_ui/13_secure/create_merge_request_with_secure_spec.rb`
+- `qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb`
+
+Example:
+
+```shell
+docker run \
+ --detach \
+ --hostname interface_ip_address \
+ --publish 80:80 \
+ --name gitlab \
+ --restart always \
+ --volume ~/ee_volume/config:/etc/gitlab \
+ --volume ~/ee_volume/logs:/var/log/gitlab \
+ --volume ~/ee_volume/data:/var/opt/gitlab \
+ --shm-size 256m \
+ gitlab/gitlab-ee:latest
+```
+
+Where `interface_ip_address` is your local network's interface IP, which you can find with the `ifconfig` command.
+The same would apply to GDK running with the instance address as `localhost` too.
+
## Guide to run and debug Monitor tests
### How to set up
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index d2e68ea7715..09fc8f4d33e 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -14,14 +14,14 @@ eventually.
## Quarantined tests
When a test frequently fails in `main`,
-[a ~"master:broken" issue](https://about.gitlab.com/handbook/engineering/workflow/#broken-master)
-should be created.
+create [a ~"failure::flaky-test" issue](https://about.gitlab.com/handbook/engineering/workflow/#broken-master).
+
If the test cannot be fixed in a timely fashion, there is an impact on the
-productivity of all the developers, so it should be placed in quarantine by
-assigning the `:quarantine` metadata with the issue URL.
+productivity of all the developers, so it should be quarantined by
+assigning the `:quarantine` metadata with the issue URL, and add the `~"quarantined test"` label to the issue.
```ruby
-it 'should succeed', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/12345' do
+it 'succeeds', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/12345' do
expect(response).to have_gitlab_http_status(:ok)
end
```
@@ -32,23 +32,13 @@ This means it is skipped unless run with `--tag quarantine`:
bin/rspec --tag quarantine
```
-**Before putting a test in quarantine, you should make sure that a
-~"master:broken" issue exists for it so it doesn't stay in quarantine forever.**
-
Once a test is in quarantine, there are 3 choices:
-- Should the test be fixed (that is, get rid of its flakiness)?
-- Should the test be moved to a lower level of testing?
-- Should the test be removed entirely (for example, because there's already a
+- Fix the test (that is, get rid of its flakiness).
+- Move the test to a lower level of testing.
+- Remove the test entirely (for example, because there's already a
lower-level test, or it's duplicating another same-level test, or it's testing
- too much etc.)?
-
-### Quarantine tests on the CI
-
-Quarantined tests are run on the CI in dedicated jobs that are allowed to fail:
-
-- `rspec-pg-quarantine` (CE & EE)
-- `rspec-pg-quarantine-ee` (EE only)
+ too much etc.).
## Automatic retries and flaky tests detection
@@ -116,6 +106,7 @@ reproduction.
- [Lazy loaded images can cause Capybara to mis-click](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18713)
- [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18742)
- [Wait for the image to be lazy-loaded when asserting on a Markdown image's `src` attribute](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25408)
+- [Avoid asserting against flash notice banners](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79432)
#### Capybara viewport size related issues
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index eb35227a50c..d03a4976a8c 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -748,6 +748,8 @@ Consult the [official Jest docs](https://jestjs.io/docs/jest-object#mock-modules
## Running Frontend Tests
+Before generating fixtures, make sure you have a running GDK instance.
+
For running the frontend tests, you need the following commands:
- `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). Make sure that
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index aef83109b9b..27d5ae70ed7 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -15,6 +15,7 @@ For any of the following scenarios, the `start-review-app-pipeline` job would be
- for merge requests with CI config changes
- for merge requests with frontend changes
- for merge requests with changes to `{,ee/,jh/}{app/controllers}/**/*`
+- for merge requests with changes to `{,ee/,jh/}{app/models}/**/*`
- for merge requests with QA changes
- for scheduled pipelines
- the MR has the `pipeline:run-review-app` label set
@@ -30,6 +31,8 @@ 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`, `allure-report-qa-reliable`, and `allure-report-qa-all` jobs. A comment with links to the reports are added to the merge request.
+Errors can be found in the `gitlab-review-apps` Sentry project and [filterable by Review App URL](https://sentry.gitlab.net/gitlab/gitlab-review-apps/?query=url%3A%22https%3A%2F%2Fgitlab-review-require-ve-u92nn2.gitlab-review.app%2F%22) or [commit SHA](https://sentry.gitlab.net/gitlab/gitlab-review-apps/releases/6095b501da7/all-events/).
+
## Performance Metrics
On every [pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730) in the `qa` stage, the
diff --git a/doc/development/transient/prevention-patterns.md b/doc/development/transient/prevention-patterns.md
index c517a6bcd54..93712b104e6 100644
--- a/doc/development/transient/prevention-patterns.md
+++ b/doc/development/transient/prevention-patterns.md
@@ -120,7 +120,7 @@ When there are 2 jobs being worked on at the same time, it is possible that the
In this example, `Worker B` is meant to set the updated status. But `Worker A` calls `#update_state` a little too late.
This can be avoided by utilizing either database locks or `Gitlab::ExclusiveLease`. This way, jobs will be
-worked on one at a time. This also allows them to be marked as [idempotent](../sidekiq_style_guide.md#idempotent-jobs).
+worked on one at a time. This also allows them to be marked as [idempotent](../sidekiq/idempotent_jobs.md).
### Retry mechanism handling
diff --git a/doc/development/uploads.md b/doc/development/uploads.md
index 6d8b951be83..14ecf38e21c 100644
--- a/doc/development/uploads.md
+++ b/doc/development/uploads.md
@@ -346,3 +346,85 @@ object using `UploadedFile#from_params`! This method can be unsafe to use depend
passed. Instead, use the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
object that [`multipart.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/middleware/multipart.rb)
builds automatically for you.
+
+### Document Object Storage buckets and CarrierWave integration
+
+When using Object Storage, GitLab expects each kind of upload to maintain its own bucket in the respective
+Object Storage destination. Moreover, the integration with CarrierWave is not used all the time.
+The [Object Storage Working Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/)
+is investigating an approach that unifies Object Storage buckets into a single one and removes CarrierWave
+so as to simplify implementation and administration of uploads.
+
+Therefore, document new uploads here by slotting them into the following tables:
+
+- [Feature bucket details](#feature-bucket-details)
+- [CarrierWave integration](#carrierwave-integration)
+
+#### Feature bucket details
+
+| Feature | Upload technology | Uploader | Bucket structure |
+|------------------------------------------|-------------------|-----------------------|-----------------------------------------------------------------------------------------------------------|
+| Job artifacts | `direct upload` | `workhorse` | `/artifacts/<proj_id_hash>/<date>/<job_id>/<artifact_id>` |
+| Pipeline artifacts | `carrierwave` | `sidekiq` | `/artifacts/<proj_id_hash>/pipelines/<pipeline_id>/artifacts/<artifact_id>` |
+| Live job traces | `fog` | `sidekiq` | `/artifacts/tmp/builds/<job_id>/chunks/<chunk_index>.log` |
+| Job traces archive | `carrierwave` | `sidekiq` | `/artifacts/<proj_id_hash>/<date>/<job_id>/<artifact_id>/job.log` |
+| Autoscale runner caching | N/A | `gitlab-runner` | `/gitlab-com-[platform-]runners-cache/???` |
+| Backups | N/A | `s3cmd`, `awscli`, or `gcs` | `/gitlab-backups/???` |
+| Git LFS | `direct upload` | `workhorse` | `/lsf-objects/<lfs_obj_oid[0:2]>/<lfs_obj_oid[2:2]>` |
+| Design management files | `disk buffering` | `rails controller` | `/lsf-objects/<lfs_obj_oid[0:2]>/<lfs_obj_oid[2:2]>` |
+| Design management thumbnails | `carrierwave` | `sidekiq` | `/uploads/design_management/action/image_v432x230/<model_id>` |
+| Generic file uploads | `direct upload` | `workhorse` | `/uploads/@hashed/[0:2]/[2:4]/<hash1>/<hash2>/file` |
+| Generic file uploads - personal snippets | `direct upload` | `workhorse` | `/uploads/personal_snippet/<snippet_id>/<filename>` |
+| Global appearance settings | `disk buffering` | `rails controller` | `/uploads/appearance/...` |
+| Topics | `disk buffering` | `rails controller` | `/uploads/projects/topic/...` |
+| Avatar images | `direct upload` | `workhorse` | `/uploads/[user,group,project]/avatar/<model_id>` |
+| Import/export | `direct upload` | `workhorse` | `/uploads/import_export_upload/???` |
+| GitLab Migration | `carrierwave` | `sidekiq` | `/uploads/bulk_imports/???` |
+| MR diffs | `carrierwave` | `sidekiq` | `/external-diffs/merge_request_diffs/mr-<mr_id>/diff-<diff_id>` |
+| Package manager archives | `direct upload` | `sidekiq` | `/packages/<proj_id_hash>/packages/<pkg_segment>/files/<pkg_file_id>` |
+| Package manager archives | `direct upload` | `sidekiq` | `/packages/<container_id_hash>/debian_*_component_file/<component_file_id>` |
+| Package manager archives | `direct upload` | `sidekiq` | `/packages/<container_id_hash>/debian_*_distribution/<distribution_file_id>` |
+| Container image cache (?) | `direct upload` | `workhorse` | `/dependency-proxy/<group_id_hash>/dependency_proxy/<group_id>/files/<proxy_id>/<blob_id or manifest_id>` |
+| Terraform state files | `carrierwave` | `rails controller` | `/terraform/<proj_id_hash>/<terraform_state_id>` |
+| Pages content archives | `carrierwave` | `sidekiq` | `/gitlab-gprd-pages/<proj_id_hash>/pages_deployments/<deployment_id>/` |
+| Secure Files | `carrierwave` | `sidekiq` | `/ci-secure-files/<proj_id_hash>/secure_files/<secure_file_id>/` |
+
+#### CarrierWave integration
+
+| File | Carrierwave usage | Categorized |
+|---------------------------------------------------------|----------------------------------------------------------------------------------|---------------------|
+| `app/models/project.rb` | `include Avatarable` | :white_check_mark: |
+| `app/models/projects/topic.rb` | `include Avatarable` | :white_check_mark: |
+| `app/models/group.rb` | `include Avatarable` | :white_check_mark: |
+| `app/models/user.rb` | `include Avatarable` | :white_check_mark: |
+| `app/models/terraform/state_version.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/ci/job_artifact.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/ci/pipeline_artifact.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/pages_deployment.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/lfs_object.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/dependency_proxy/blob.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/dependency_proxy/manifest.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/packages/composer/cache_file.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/packages/package_file.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `app/models/concerns/packages/debian/component_file.rb` | `include FileStoreMounter` | :white_check_mark: |
+| `ee/app/models/issuable_metric_image.rb` | `include FileStoreMounter` | |
+| `ee/app/models/vulnerabilities/remediation.rb` | `include FileStoreMounter` | |
+| `ee/app/models/vulnerabilities/export.rb` | `include FileStoreMounter` | |
+| `app/models/packages/debian/project_distribution.rb` | `include Packages::Debian::Distribution` | :white_check_mark: |
+| `app/models/packages/debian/group_distribution.rb` | `include Packages::Debian::Distribution` | :white_check_mark: |
+| `app/models/packages/debian/project_component_file.rb` | `include Packages::Debian::ComponentFile` | :white_check_mark: |
+| `app/models/packages/debian/group_component_file.rb` | `include Packages::Debian::ComponentFile` | :white_check_mark: |
+| `app/models/merge_request_diff.rb` | `mount_uploader :external_diff, ExternalDiffUploader` | :white_check_mark: |
+| `app/models/note.rb` | `mount_uploader :attachment, AttachmentUploader` | :white_check_mark: |
+| `app/models/appearance.rb` | `mount_uploader :logo, AttachmentUploader` | :white_check_mark: |
+| `app/models/appearance.rb` | `mount_uploader :header_logo, AttachmentUploader` | :white_check_mark: |
+| `app/models/appearance.rb` | `mount_uploader :favicon, FaviconUploader` | :white_check_mark: |
+| `app/models/project.rb` | `mount_uploader :bfg_object_map, AttachmentUploader` | |
+| `app/models/import_export_upload.rb` | `mount_uploader :import_file, ImportExportUploader` | :white_check_mark: |
+| `app/models/import_export_upload.rb` | `mount_uploader :export_file, ImportExportUploader` | :white_check_mark: |
+| `app/models/ci/deleted_object.rb` | `mount_uploader :file, DeletedObjectUploader` | |
+| `app/models/design_management/action.rb` | `mount_uploader :image_v432x230, DesignManagement::DesignV432x230Uploader` | :white_check_mark: |
+| `app/models/concerns/packages/debian/distribution.rb` | `mount_uploader :signed_file, Packages::Debian::DistributionReleaseFileUploader` | :white_check_mark: |
+| `app/models/bulk_imports/export_upload.rb` | `mount_uploader :export_file, ExportUploader` | :white_check_mark: |
+| `ee/app/models/user_permission_export_upload.rb` | `mount_uploader :file, AttachmentUploader` | |
+| `app/models/ci/secure_file.rb` | `include FileStoreMounter` | |
diff --git a/doc/development/value_stream_analytics.md b/doc/development/value_stream_analytics.md
index 6b2442f1c32..0d545fa8e3f 100644
--- a/doc/development/value_stream_analytics.md
+++ b/doc/development/value_stream_analytics.md
@@ -4,11 +4,11 @@ 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
---
-# Value Stream Analytics development guide
+# Value stream analytics development guide
Value stream analytics calculates the time between two arbitrary events recorded on domain objects and provides aggregated statistics about the duration.
-For information on how to configure Value Stream Analytics in GitLab, see our [analytics documentation](../user/analytics/value_stream_analytics.md).
+For information on how to configure value stream analytics in GitLab, see our [analytics documentation](../user/analytics/value_stream_analytics.md).
## Stage
diff --git a/doc/development/value_stream_analytics/img/object_hierarchy_example_V14_10.png b/doc/development/value_stream_analytics/img/object_hierarchy_example_V14_10.png
new file mode 100644
index 00000000000..0e3c760fa3c
--- /dev/null
+++ b/doc/development/value_stream_analytics/img/object_hierarchy_example_V14_10.png
Binary files differ
diff --git a/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md b/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md
new file mode 100644
index 00000000000..aef85107cd9
--- /dev/null
+++ b/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md
@@ -0,0 +1,330 @@
+---
+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
+---
+
+# Aggregated Value Stream Analytics
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335391) in GitLab 14.7.
+
+DISCLAIMER:
+This page contains information related to upcoming products, features, and functionality.
+It is important to note that the information presented is for informational purposes only.
+Please do not rely on this information for purchasing or planning purposes.
+As with all projects, the items mentioned on this page are subject to change or delay.
+The development, release, and timing of any products, features, or functionality remain at the
+sole discretion of GitLab Inc.
+
+This page provides a high-level overview of the aggregated backend for
+Value Stream Analytics (VSA).
+
+## Current Status
+
+As of 14.8 the aggregated VSA backend is used only in the `gitlab-org` group, for testing purposes
+. We plan to gradually roll it out in the next major release (15.0) for the rest of the groups.
+
+## Motivation
+
+The aggregated backend aims to solve the performance limitations of the VSA feature and set it up
+for long-term growth.
+
+Our main database is not prepared for analytical workloads. Executing long-running queries can
+affect the reliability of the application. For large groups, the current
+implementation (old backend) is slow and, in some cases, doesn't even load due to the configured
+statement timeout (15s).
+
+The database queries in the old backend use the core domain models directly through
+`IssuableFinders` classes: ([MergeRequestsFinder](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/finders/merge_requests_finder.rb) and [IssuesFinder](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/finders/issues_finder.rb)).
+With the requested change of the [date range filters](https://gitlab.com/groups/gitlab-org/-/epics/6046),
+this approach was no longer viable from the performance point of view.
+
+Benefits of the aggregated VSA backend:
+
+- Simpler database queries (fewer JOINs).
+- Faster aggregations, only a single table is accessed.
+- Possibility to introduce further aggregations for improving the first page load time.
+- Better performance for large groups (with many sub-groups, projects, issues and, merge requests).
+- Ready for database decomposition. The VSA related database tables could live in a separate
+database with a minimal development effort.
+- Ready for keyset pagination which can be useful for exporting the data.
+- Possibility to implement more complex event definitions.
+ - For example, the start event can be two timestamp columns where the earliest value would be
+ used by the system.
+ - Example: `MIN(issues.created_at, issues.updated_at)`
+
+## How does Value Stream Analytics work?
+
+Value Stream Analytics calculates the duration between two timestamp columns or timestamp
+expressions and runs various aggregations on the data.
+
+Examples:
+
+- Duration between the Merge Request creation time and Merge Request merge time.
+- Duration between the Issue creation time and Issue close time.
+
+This duration is exposed in various ways:
+
+- Aggregation: median, average
+- Listing: list the duration for individual Merge Request and Issue records
+
+Apart from the durations, we expose the record count within a stage.
+
+### Stages
+
+A stage represents an event pair (start and end events) with additional metadata, such as the name
+of the stage. Stages are configurable by the user within the pairing rules defined in the backend.
+
+**Example stage: Code Review**
+
+- Start event identifier: Merge Request creation time
+- Start event column: uses the `merge_requests.created_at` timestamp column.
+- End event identifier: Merge Request merge time
+- End event column: uses the `merge_request_metrics.merged_at` timestamp column.
+- Stage event hash ID: a calculated hash for the pair of start and end event identifiers.
+ - If two stages have the same configuration of start and end events, then their stage event hash
+ IDs are identical.
+ - The stage event hash ID is later used to store the aggregated data in partitioned database tables.
+
+### Value streams
+
+Value streams are container objects for the stages. There can be multiple value streams per group
+or project focusing on different aspects of the Dev Ops lifecycle.
+
+### Example configuration
+
+![vsa object hierarchy example](img/object_hierarchy_example_V14_10.png)
+
+In this example, there are two independent value streams set up for two teams that are using
+different development workflows within the `Test Group` (top-level namespace).
+
+The first value stream uses standard timestamp-based events for defining the stages. The second
+value stream uses label events.
+
+Each value stream and stage item from the example will be persisted in the database. Notice that
+the `Deployment` stage is identical for both value streams; that means that the underlying
+`stage_event_hash_id` is the same for both stages. The `stage_event_hash_id` reduces
+the amount of data the backend collects and plays a vital role in database partitioning.
+
+We expect value streams and stages to be rarely changed. When stages (start and end events) are
+changed, the aggregated data gets stale. This is fixed by the periodical aggregation occurring
+every day.
+
+### Feature availability
+
+The aggregated VSA feature is available on the group and project level however, the aggregated
+backend is only available for Premium and Ultimate customers due to data storage and data
+computation costs. Storing de-normalized, aggregated data requires significant disk space.
+
+## Aggregated value stream analytics architecture
+
+The main idea behind the aggregated VSA backend is separation: VSA database tables and queries do
+not use the core domain models directly (Issue, MergeRequest). This allows us to scale and
+optimize VSA independently from the other parts of the application.
+
+The architecture consists of two main mechanisms:
+
+- Periodical data collection and loading (happens in the background).
+- Querying the collected data (invoked by the user).
+
+### Data loading
+
+The aggregated nature of VSA comes from the periodical data loading. The system queries the core
+domain models to collect the stage and timestamp data. This data is periodically inserted into the
+VSA database tables.
+
+High-level overview for each top-level namespace with Premium or Ultimate license:
+
+1. Load all stages in the group.
+1. Iterate over the issues and merge requests records.
+1. Based on the stage configurations (start and end event identifiers) collect the timestamp data.
+1. `INSERT` or `UPDATE` the data into the VSA database tables.
+
+The data loading is implemented within the [`Analytics::CycleAnalytics::DataLoaderService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/services/analytics/cycle_analytics/data_loader_service.rb)
+class. There are groups containing a lot of data, so to avoid overloading the primary database,
+the service performs operations in batches and enforces strict application limits:
+
+- Load records in batches.
+- Insert records in batches.
+- Stop processing when a limit is reached, schedule a background job to continue the processing
+later.
+- Continue processing data from a specific point.
+
+As of GitLab 14.7, the data loading is done manually. Once the feature is ready, the service will
+be invoked periodically by the system via a cron job (this part is not implemented yet).
+
+#### Record iteration
+
+The batched iteration is implemented with the
+[efficient IN operator](../database/efficient_in_operator_queries.md). The background job scans
+all issues and merge request records in the group hierarchy ordered by the `updated_at` and the
+`id` columns. For already aggregated groups, the `DataLoaderService` continues the aggregation
+from a specific point which saves time.
+
+Collecting the timestamp data happens on every iteration. The `DataLoaderService` determines which
+stage events are configured within the group hierarchy and builds a query that selects the
+required timestamps. The stage record knows which events are configured and the events know how to
+select the timestamp columns.
+
+Example for collected stage events: merge request merged, merge request created, merge request
+closed
+
+Generated SQL query for loading the timestamps:
+
+```sql
+SELECT
+ -- the list of columns depends on the configured stages
+ "merge_request_metrics"."merged_at",
+ "merge_requests"."created_at",
+ "merge_request_metrics"."latest_closed_at"
+ FROM "merge_requests"
+ LEFT OUTER JOIN "merge_request_metrics" ON "merge_request_metrics"."merge_request_id" = "merge_requests"."id"
+ WHERE "merge_requests"."id" IN (1, 2, 3, 4) -- ids are coming from the batching query
+```
+
+The `merged_at` column is located in a separate table (`merge_request_metrics`). The
+`Gitlab::Analytics::CycleAnalytics::StagEvents::MergeRequestMerged` class adds itself to a scope
+for loading the timestamp data without affecting the number of rows (uses `LEFT JOIN`). This
+behavior is implemented for each `StageEvent` class with the `include_in` method.
+
+The data collection query works on the event level. It extracts the event timestamps from the
+stages and ensures that we don't collect the same data multiple times. The events mentioned above
+could come from the following stage configuration:
+
+- merge request created - merge request merged
+- merge request created - merge request closed
+
+Other combinations might be also possible, but we prevent the ones that make no sense, for example:
+
+- merge request merged - merge request created
+
+Creation time always happens first, so this stage always reports negative duration.
+
+#### Data scope
+
+The data collection scans and processes all issues and merge requests records in the group
+hierarchy, starting from the top-level group. This means that if a group only has one value stream
+in a sub-group, we nevertheless collect data of all issues and merge requests in the hierarchy of
+this group. This aims to simplify the data collection mechanism. Moreover, data research shows
+that most group hierarchies have their stages configured on the top level.
+
+During the data collection process, the collected timestamp data is transformed into rows. For
+each configured stage, if the start event timestamp is present, the system inserts or updates one
+event record. This allows us to determine the upper limit of the inserted rows per group by
+counting all issues and merge requests and multiplying the sum by the stage count.
+
+#### Data consistency concerns
+
+Due to the async nature of the data collection, data consistency issues are bound to happen. This
+is a trade-off that makes the query performance significantly faster. We think that for analytical
+workload a slight lag in the data is acceptable.
+
+Before the rollout we plan to implement some indicators on the VSA page that shows the most
+recent backend activities. For example, indicators that show the last data collection timestamp
+and the last consistency check timestamp.
+
+#### Database structure
+
+VSA collects data for the following domain models: `Issue` and `MergeRequest`. To keep the
+aggregated data separated, we use two additional database tables:
+
+- `analytics_cycle_analytics_issue_stage_events`
+- `analytics_cycle_analytics_merge_request_stage_events`
+
+Both tables are hash partitioned by the `stage_event_hash_id`. Each table uses 32 partitions. It's
+an arbitrary number and it could be changed. Important is to keep the partitions under 100GB in
+size (which gives the feature a lot of headroom).
+
+|Column|Description|
+|-|-|
+|`stage_event_hash_id`|partitioning key|
+|`merge_request_id` or `issue_id`|reference to the domain record (Issuable)|
+|`group_id`|reference to the group (de-normalization)|
+|`project_id`|reference to the project|
+|`milestone_id`|duplicated data from the domain record table|
+|`author_id`|duplicated data from the domain record table|
+|`state_id`|duplicated data from the domain record table|
+|`start_event_timestamp`|timestamp derived from the stage configuration|
+|`end_event_timestamp`|timestamp derived from the stage configuration|
+
+With accordance to the data separation requirements, the table doesn't have any foreign keys. The
+consistency is ensured by a background job (eventually consistent).
+
+### Data querying
+
+The base query always includes the following filters:
+
+- `stage_event_hash_id` - partition key
+- `project_id` or `group_id` - depending if it's a project or group level query
+- `end_event_timestamp` - date range filter (last 30 days)
+
+Example: Selecting review stage duration for the GitLab project
+
+```sql
+SELECT end_event_timestamp - start_event_timestamp
+FROM analytics_cycle_analytics_merge_request_stage_events
+WHERE
+stage_event_hash_id = 16 AND -- hits a specific partition
+project_id = 278964 AND
+end_event_timestamp > '2022-01-01' AND end_event_timestamp < '2022-01-30'
+```
+
+#### Query generation
+
+The query backend is hidden behind the same interface that the old backend implementation uses.
+Thanks to this, we can easily switch between the old and new query backends.
+
+- `DataCollector`: entrypoint for querying VSA data
+ - `BaseQueryBuilder`: provides the base `ActiveRecord` scope (filters are applied here).
+ - `average`: average aggregation.
+ - `median`: median aggregation.
+ - `count`: row counting.
+ - `records`: list of issue or merge request records.
+
+#### Filters
+
+VSA supports various filters on the base query. Most of the filters require no additional JOINs:
+
+|Filter name|Description|
+|-|-|
+|`milestone_title`|The backend translates it to `milestone_id` filter|
+|`author_username`|The backend translates it to `author_id` filter|
+|`project_ids`|Only used on the group-level|
+
+Exceptions: these filters are applied on other tables which means we `JOIN` them.
+
+|Filter name|Description|
+|-|-|
+|`label_name`|Array filter, using the `label_links` table|
+|`assignee_username`|Array filter, using the `*_assignees` table|
+
+To fully decompose the database, the required ID values would need to be replicated in the VSA
+database tables. This change could be implemented using array columns.
+
+### Endpoints
+
+The feature uses private JSON APIs for delivering the data to the frontend. On the first page load
+, the following requests are invoked:
+
+- Initial HTML page load which is mostly empty. Some configuration data is exposed via `data`
+attributes.
+- `value_streams` - Load the available value streams for the given group.
+- `stages` - Load the stages for the currently selected value stream.
+- `median` - For each stage, request the median duration.
+- `count` - For each stage, request the number of items in the stage (this is a
+[limit count](../merge_request_performance_guidelines.md#badge-counters), maximum 1000 rows).
+- `average_duration_chart` - Data for the duration chart.
+- `summary`, `time_summary` - Top-level aggregations, most of the metrics are using different APIs/
+finders and not invoking the aggregated backend.
+
+When clicking on a specific stage, the `records` endpoint is invoked, which returns the related
+records (paginated) for the chosen stage in a specific order.
+
+### Database decomposition
+
+By separating the query logic from the main application code, the feature is ready for database
+decomposition. If we decide that VSA requires a separate database instance, then moving the
+aggregated tables can be accomplished with little effort.
+
+A different database technology could also be used to further improve the performance of the
+feature, for example [Timescale DB](https://www.timescale.com).
diff --git a/doc/install/aws/eks_clusters_aws.md b/doc/install/aws/eks_clusters_aws.md
index 86318467a91..fe436a03cb5 100644
--- a/doc/install/aws/eks_clusters_aws.md
+++ b/doc/install/aws/eks_clusters_aws.md
@@ -23,7 +23,7 @@ Using `eksctl` enables the following when building an EKS Cluster:
- You have various cluster configuration options:
- Selection of operating system: Amazon Linux 2, Windows, Bottlerocket
- Selection of Hardware Architecture: x86, ARM, GPU
- - Selection of Kubernetes version (the GitLab-managed clusters for your project's applications have [specific Kubernetes version requirements](../../user/infrastructure/clusters/connect/index.md#supported-cluster-versions))
+ - Selection of Kubernetes version (the GitLab-managed clusters for your project's applications have [specific Kubernetes version requirements](../../user/clusters/agent/index.md#supported-cluster-versions))
- It can deploy high value-add items to the cluster, including:
- A bastion host to keep the cluster endpoint private and possible perform performance testing.
- Prometheus and Grafana for monitoring.
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index 2183f351efd..2c40efd5909 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Provision GitLab Cloud Native Hybrid on AWS EKS **(FREE SELF)**
-GitLab "Cloud Native Hybrid" is a hybrid of the cloud native technology Kubernetes (EKS) and EC2. While as much of the GitLab application as possible runs in Kubernetes or on AWS services (PaaS), the GitLab service Gitaly must still be run on Ec2. Gitaly is a layer designed to overcome limitations of the Git binaries in a horizontally scaled architecture. You can read more here about why Gitaly was built and why the limitations of Git mean that it must currently run on instance compute in [Git Characteristics That Make Horizontal Scaling Difficult](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/DESIGN.md#git-characteristics-that-make-horizontal-scaling-difficult).
+GitLab "Cloud Native Hybrid" is a hybrid of the cloud native technology Kubernetes (EKS) and EC2. While as much of the GitLab application as possible runs in Kubernetes or on AWS services (PaaS), the GitLab service Gitaly must still be run on EC2. Gitaly is a layer designed to overcome limitations of the Git binaries in a horizontally scaled architecture. You can read more here about why Gitaly was built and why the limitations of Git mean that it must currently run on instance compute in [Git Characteristics That Make Horizontal Scaling Difficult](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/DESIGN.md#git-characteristics-that-make-horizontal-scaling-difficult).
Amazon provides a managed Kubernetes service offering known as [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/).
@@ -38,13 +38,13 @@ NOTE:
This automation is in **Developer Preview**. GitLab is working with AWS on resolving [the outstanding issues](https://github.com/aws-quickstart/quickstart-eks-gitlab/issues?q=is%3Aissue+is%3Aopen+%5BHL%5D) before it is fully released. You can subscribe to this issue to be notified of progress and release announcements: [AWS Quick Start for GitLab Cloud Native Hybrid on EKS Status: DEVELOPER PREVIEW](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues/11).<br><br>
The developer preview deploys Aurora PostgreSQL, but the release version will deploy Amazon RDS PostgreSQL due to [known issues](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) with Aurora. All performance testing results will also be redone after this change has been made.
-The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions.
-It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/issues) to understand if any of them may affect your provisioning plans.
+The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/tree/main) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions.
+It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/issues) to understand if any of them may affect your provisioning plans.
-| | [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) |
+| | [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
-| Licensing | [Open Source (Apache 2.0)](https://github.com/aws-quickstart/quickstart-eks-gitlab/blob/main/LICENSE.txt) | [GitLab Enterprise Edition license](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/LICENSE) ([GitLab Premium tier](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/README.md)) |
-| Overview and Vision | [AWS Quick Start](https://aws.amazon.com/quickstart/) | [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/README.md) |
+| Licensing | [Open Source (Apache 2.0)](https://github.com/aws-quickstart/quickstart-eks-gitlab/blob/main/LICENSE.txt) | [GitLab Enterprise Edition license](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/LICENSE) ([GitLab Premium tier](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md)) |
+| Overview and Vision | [AWS Quick Start](https://aws.amazon.com/quickstart/) | [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md) |
| GitLab Reference Architecture Compliant | Yes | Yes |
| GitLab Performance Tool (GPT) Tested | Yes | Yes |
| Amazon Well Architected Compliant | Yes<br />(via Quick Start program) | Critical portions <br />reviewed by AWS |
diff --git a/doc/install/aws/manual_install_aws.md b/doc/install/aws/manual_install_aws.md
index 531a006dbf3..26d93ea06b7 100644
--- a/doc/install/aws/manual_install_aws.md
+++ b/doc/install/aws/manual_install_aws.md
@@ -24,11 +24,11 @@ GitLab maintains and tests two main types of Reference Architectures. The **Omni
### Getting started for production-grade Omnibus GitLab
-The Infrastructure as Code tooling [GitLab Environment Tool (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) is the best place to start for building Omnibus GitLab on AWS and most especially if you are targeting an HA setup. While it does not automate everything, it does complete complex setups like Gitaly Cluster for you. GET is open source so anyone can build on top of it and contribute improvements to it.
+The Infrastructure as Code tooling [GitLab Environment Tool (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/tree/main) is the best place to start for building Omnibus GitLab on AWS and most especially if you are targeting an HA setup. While it does not automate everything, it does complete complex setups like Gitaly Cluster for you. GET is open source so anyone can build on top of it and contribute improvements to it.
### Getting started for production-grade Cloud Native Hybrid GitLab
-For the Cloud Native Hybrid architectures there are two Infrastructure as Code options which are compared in GitLab Cloud Native Hybrid on AWS EKS implementation pattern in the section [Available Infrastructure as Code for GitLab Cloud Native Hybrid](gitlab_hybrid_on_aws.md#available-infrastructure-as-code-for-gitlab-cloud-native-hybrid). It compares the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) to the AWS Quick Start for GitLab Cloud Native Hybrid on EKS which was co-developed by GitLab and AWS. GET and the AWS Quick Start are both open source so anyone can build on top of them and contribute improvements to them.
+For the Cloud Native Hybrid architectures there are two Infrastructure as Code options which are compared in GitLab Cloud Native Hybrid on AWS EKS implementation pattern in the section [Available Infrastructure as Code for GitLab Cloud Native Hybrid](gitlab_hybrid_on_aws.md#available-infrastructure-as-code-for-gitlab-cloud-native-hybrid). It compares the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/tree/main) to the AWS Quick Start for GitLab Cloud Native Hybrid on EKS which was co-developed by GitLab and AWS. GET and the AWS Quick Start are both open source so anyone can build on top of them and contribute improvements to them.
## Introduction
@@ -268,7 +268,7 @@ On the EC2 dashboard, look for Load Balancer in the left navigation bar:
1. Click **Configure Health Check** and set up a health check for your EC2 instances.
1. For **Ping Protocol**, select HTTP.
1. For **Ping Port**, enter 80.
- 1. For **Ping Path** - we recommend that you [use the Readiness check endpoint](../../administration/load_balancer.md#readiness-check). You'll need to add [the VPC IP Adddress Range (CIDR)](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl) to the [IP Allowlist](../../administration/monitoring/ip_whitelist.md) for the [Health Check endpoints](../../user/admin_area/monitoring/health_check.md)
+ 1. For **Ping Path** - we recommend that you [use the Readiness check endpoint](../../administration/load_balancer.md#readiness-check). You'll need to add [the VPC IP Address Range (CIDR)](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl) to the [IP Allowlist](../../administration/monitoring/ip_whitelist.md) for the [Health Check endpoints](../../user/admin_area/monitoring/health_check.md)
1. Keep the default **Advanced Details** or adjust them according to your needs.
1. Click **Add EC2 Instances** - don't add anything as we will create an Auto Scaling Group later to manage instances for us.
1. Click **Add Tags** and add any tags you need.
@@ -588,8 +588,8 @@ Let's create an EC2 instance where we'll install Gitaly:
1. In the **Subnet** dropdown, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
1. Double check that **Auto-assign Public IP** is set to `Use subnet setting (Disable)`.
1. Click **Add Storage**.
-1. Increase the Root volume size to `20 GiB` and change the **Volume Type** to `Provisoned IOPS SSD (io1)`. (This is an arbitrary size. Create a volume big enough for your repository storage requirements.)
- 1. For **IOPS** set `1000` (20 GiB x 50 IOPS). You can provision up to 50 IOPS per GiB. If you select a larger volume, increase the IOPS accordingly. Workloads where many small files are written in a serialized manner, like `git`, requires performant storage, hence the choice of `Provisoned IOPS SSD (io1)`.
+1. Increase the Root volume size to `20 GiB` and change the **Volume Type** to `Provisioned IOPS SSD (io1)`. (This is an arbitrary size. Create a volume big enough for your repository storage requirements.)
+ 1. For **IOPS** set `1000` (20 GiB x 50 IOPS). You can provision up to 50 IOPS per GiB. If you select a larger volume, increase the IOPS accordingly. Workloads where many small files are written in a serialized manner, like `git`, requires performant storage, hence the choice of `Provisioned IOPS SSD (io1)`.
1. Click on **Add Tags** and add your tags. In our case, we'll only set `Key: Name` and `Value: Gitaly`.
1. Click on **Configure Security Group** and let's **Create a new security group**.
1. Give your security group a name and description. We'll use `gitlab-gitaly-sec-group` for both.
diff --git a/doc/install/index.md b/doc/install/index.md
index 44b234747dc..9ffed87fd61 100644
--- a/doc/install/index.md
+++ b/doc/install/index.md
@@ -31,7 +31,7 @@ install GitLab:
| [Helm charts](https://docs.gitlab.com/charts/) | The cloud native Helm chart for installing GitLab and all of its components on Kubernetes. | When installing GitLab on Kubernetes, there are some trade-offs that you need to be aware of: <br/>- Administration and troubleshooting requires Kubernetes knowledge.<br/>- It can be more expensive for smaller installations. The default installation requires more resources than a single node Linux package deployment, as most services are deployed in a redundant fashion.<br/>- There are some feature [limitations to be aware of](https://docs.gitlab.com/charts/#limitations).<br/><br/> Use this method if your infrastructure is built on Kubernetes and you're familiar with how it works. The methods for management, observability, and some concepts are different than traditional deployments. |
| [Docker](https://docs.gitlab.com/omnibus/docker/) | The GitLab packages, Dockerized. | Use this method if you're familiar with Docker. |
| [Source](installation.md) | Install GitLab and all of its components from scratch. | Use this method if none of the previous methods are available for your platform. Useful for unsupported systems like \*BSD.|
-| [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#documentation) | The GitLab Environment toolkit provides a set of automation tools to deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers. | Customers are very welcome to trial and evaluate GET today, however be aware of [key limitations](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#missing-features-to-be-aware-of) of the current iteration. For production environments further manual setup will be required based on your specific requirements. |
+| [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit#documentation) | The GitLab Environment toolkit provides a set of automation tools to deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers. | Customers are very welcome to trial and evaluate GET today, however be aware of [key limitations](https://gitlab.com/gitlab-org/gitlab-environment-toolkit#missing-features-to-be-aware-of) of the current iteration. For production environments further manual setup will be required based on your specific requirements. |
| [GitLab Operator](https://docs.gitlab.com/charts/installation/operator.html) | The GitLab Operator provides an installation and management method for GitLab following the [Kubernetes Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/). | Use the GitLab Operator to run GitLab in an [OpenShift](openshift_and_gitlab/index.md) environment. |
## Install GitLab on cloud providers
diff --git a/doc/install/installation.md b/doc/install/installation.md
index f405bc40f43..21d1ee84722 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -230,7 +230,7 @@ Download Ruby and compile it:
```shell
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.gz"
+curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.gz"
echo '3043099089608859fc8cce7f9fdccaa1f53a462457e3838ec3b25a7d609fbc5b ruby-2.7.4.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.4.tar.gz
cd ruby-2.7.4
@@ -250,7 +250,7 @@ page](https://go.dev/dl).
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
+curl --remote-name --location --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
echo '414cd18ce1d193769b9e97d2401ad718755ab47816e13b2a1cde203d263b55cf go1.16.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.16.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,gofmt} /usr/local/bin/
@@ -560,10 +560,6 @@ sudo -u git -H cp config/puma.rb.example config/puma.rb
# cores you have available. You can get that number via the `nproc` command.
sudo -u git -H editor config/puma.rb
-# Configure Git global settings for git user
-# 'autocrlf' is needed for the web editor
-sudo -u git -H git config --global core.autocrlf input
-
# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed
sudo -u git -H git config --global gc.auto 0
@@ -571,6 +567,7 @@ sudo -u git -H git config --global gc.auto 0
sudo -u git -H git config --global repack.writeBitmaps true
# Enable push options
+# Refer to https://docs.gitlab.com/ee/user/project/push_options.html for more information.
sudo -u git -H git config --global receive.advertisePushOptions true
# Enable fsyncObjectFiles to reduce risk of repository corruption if the server crashes
@@ -578,9 +575,10 @@ sudo -u git -H git config --global core.fsyncObjectFiles true
# Configure Redis connection settings
sudo -u git -H cp config/resque.yml.example config/resque.yml
+sudo -u git -H cp config/cable.yml.example config/cable.yml
# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
-sudo -u git -H editor config/resque.yml
+sudo -u git -H editor config/resque.yml config/cable.yml
```
Make sure to edit both `gitlab.yml` and `puma.rb` to match your setup.
@@ -1041,9 +1039,8 @@ To use GitLab with HTTPS:
1. Update `ssl_certificate` and `ssl_certificate_key`.
1. Review the configuration file and consider applying other security and performance enhancing features.
-Using a self-signed certificate is discouraged but if you must use it, follow the normal directions. Then:
-
-1. Generate a self-signed SSL certificate:
+Using a self-signed certificate is discouraged. If you must use one,
+follow the normal directions and generate a self-signed SSL certificate:
```shell
mkdir -p /etc/nginx/ssl/
@@ -1052,7 +1049,12 @@ Using a self-signed certificate is discouraged but if you must use it, follow th
sudo chmod o-r gitlab.key
```
-1. In the `config.yml` of GitLab Shell set `self_signed_cert` to `true`.
+WARNING:
+The `self_signed_cert` variable is
+[deprecated and redundant](https://gitlab.com/gitlab-org/gitlab-shell/-/issues/120).
+It is set to `false` by default, but still accepts self-signed certificates. Setting
+this value to `true` allows any certificate to be accepted, and can make
+machine-in-the-middle attacks possible.
### Enable Reply by email
@@ -1142,7 +1144,7 @@ You can configure the Prometheus server in `config/gitlab.yml`:
# example
prometheus:
enabled: true
- server_address: '10.1.2.3:9090'
+ server_address: '10.1.2.3:9090'
```
## Troubleshooting
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 665e80e6e00..bce9702b032 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -331,6 +331,10 @@ NOTE:
We don't support running GitLab with JavaScript disabled in the browser and have no plans of supporting that
in the future because we have features such as issue boards which require JavaScript extensively.
+## Security
+
+After installation, be sure to read and follow guidance on [maintaining a secure GitLab installation](../security/index.md).
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md
index 4be0089703a..a9be7754cb9 100644
--- a/doc/integration/datadog.md
+++ b/doc/integration/datadog.md
@@ -26,7 +26,7 @@ project, group, or instance level:
Copy this value, as you need it in a later step.
1. *For project-level or group-level integrations:* In GitLab, go to your project or group.
1. *For instance-level integrations:*
- 1. Sign in to GitLab as a user with the [Administrator role](../user/permissions.md).
+ 1. Sign in to GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Integrations**.
1. Scroll to **Add an integration**, and select **Datadog**.
@@ -42,6 +42,8 @@ project, group, or instance level:
1. Optional. If you use groups of GitLab instances (such as staging and production
environments), provide an **Env** name. This value is attached to each span
the integration generates.
+1. Optional. To define any custom tags for all spans at which the integration is being configured,
+ enter one tag per line in **Tags**. Each line must be in the format `key:value`. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.)
1. Optional. Select **Test settings** to test your integration.
1. Select **Save changes**.
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 7356574a33e..4976f7c2664 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -14,22 +14,30 @@ Advanced Search provides faster search response times and [improved search featu
## Version requirements
-<!-- Remember to update ee/lib/system_check/app/elasticsearch_check.rb if this changes -->
+> Support for Elasticsearch 6.8 was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350275) in GitLab 14.8 and is scheduled for removal in GitLab 15.0.
-| GitLab version | Elasticsearch version |
-|---------------------------------------------|-------------------------------|
-| GitLab Enterprise Edition 13.9 or greater | Elasticsearch 6.8 through 7.x |
-| GitLab Enterprise Edition 13.3 through 13.8 | Elasticsearch 6.4 through 7.x |
-| GitLab Enterprise Edition 12.7 through 13.2 | Elasticsearch 6.x through 7.x |
-| GitLab Enterprise Edition 11.5 through 12.6 | Elasticsearch 5.6 through 6.x |
-| GitLab Enterprise Edition 9.0 through 11.4 | Elasticsearch 5.1 through 5.5 |
-| GitLab Enterprise Edition 8.4 through 8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed |
+| GitLab version | Elasticsearch version |
+|----------------------|--------------------------|
+| GitLab 14.8 or later | Elasticsearch 7.x - 7.17 |
+| GitLab 13.9 - 14.7 | Elasticsearch 6.8 - 7.x |
+| GitLab 13.3 - 13.8 | Elasticsearch 6.4 - 7.x |
+| GitLab 12.7 - 13.2 | Elasticsearch 6.x - 7.x |
+| GitLab 11.5 - 12.6 | Elasticsearch 5.6 - 6.x |
The Elasticsearch Integration works with supported versions of
Elasticsearch and follows Elasticsearch's [End of Life Policy](https://www.elastic.co/support/eol).
When we change Elasticsearch supported versions in GitLab, we announce them in [deprecation notes](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations) in monthly release posts
before we remove them.
+### Versions not supported
+
+GitLab does not support:
+
+- [Amazon's OpenSearch](https://aws.amazon.com/blogs/opensource/opensearch-1-0-launches/)
+(a [fork of Elasticsearch](https://www.elastic.co/what-is/opensearch)). Use AWS Elasticsearch Service 7.10 instead.
+For updates, see [issue #327560](https://gitlab.com/gitlab-org/gitlab/-/issues/327560).
+- Elasticsearch 8.0. For updates, see [issue #350600](https://gitlab.com/gitlab-org/gitlab/-/issues/350600). Use Elasticsearch 7.17 instead.
+
## System requirements
Elasticsearch requires additional resources to those documented in the
@@ -155,8 +163,7 @@ may need to set the `production -> elasticsearch -> indexer_path` setting in you
## Enable Advanced Search
-For GitLab instances with more than 50GB repository data you can follow the instructions for [Indexing large
-instances](#indexing-large-instances) below.
+For GitLab instances with more than 50GB repository data you can follow the instructions for [how to index large instances efficiently](#how-to-index-large-instances-efficiently) below.
To enable Advanced Search, you must have administrator access to GitLab:
@@ -466,7 +473,7 @@ The following are some available Rake tasks:
| [`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:pause_indexing`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Pauses Elasticsearch indexing. Changes are still tracked. Useful for cluster/index migrations. |
| [`sudo gitlab-rake gitlab:elastic:resume_indexing`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Resumes Elasticsearch indexing. |
-| [`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`](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. It can only be used after the index is created. |
| [`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 results 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. |
@@ -511,7 +518,7 @@ When performing a search, the GitLab index uses the following scopes:
| `projects` | Project data (default) |
| `blobs` | Code |
| `issues` | Issue data |
-| `merge_requests` | Merge Request data |
+| `merge_requests` | Merge request data |
| `milestones` | Milestone data |
| `notes` | Note data |
| `snippets` | Snippet data |
@@ -543,7 +550,7 @@ For basic guidance on choosing a cluster configuration you may refer to [Elastic
- The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you benefit from having at least 3*4=12 shards in the cluster. It's only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards.
- The `Number of Elasticsearch replicas` setting should most of the time be equal to `1` (each shard has 1 replica). Using `0` is not recommended, because losing one node corrupts the index.
-### Indexing large instances
+### How to index large instances efficiently
This section may be helpful in the event that the other
[basic instructions](#enable-advanced-search) cause problems
@@ -741,6 +748,86 @@ However, some larger installations may wish to tune the merge policy settings:
- 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.
+## Index large instances with dedicated Sidekiq nodes or processes
+
+Indexing a large instance can be a lengthy and resource-intensive process that has the potential
+of overwhelming Sidekiq nodes and processes. This negatively affects the GitLab performance and
+availability.
+
+As GitLab allows you to start multiple Sidekiq processes, you can create an
+additional process dedicated to indexing a set of queues (or queue group). This way, you can
+ensure that indexing queues always have a dedicated worker, while the rest of the queues have
+another dedicated worker to avoid contention.
+
+For this purpose, use the [queue selector](../administration/operations/extra_sidekiq_processes.md#queue-selector)
+option that allows a more general selection of queue groups using a [worker matching query](../administration/operations/extra_sidekiq_routing.md#worker-matching-query).
+
+To handle these two queue groups, we generally recommend one of the following two options. You can either:
+
+- [Use two queue groups on one single node](#single-node-two-processes).
+- [Use two queue groups, one on each node](#two-nodes-one-process-for-each).
+
+For the steps below, consider:
+
+- `feature_category=global_search` as an indexing queue group with its own Sidekiq process.
+- `feature_category!=global_search` as a non-indexing queue group that has its own Sidekiq process.
+
+### Single node, two processes
+
+To create both an indexing and a non-indexing Sidekiq process in one node:
+
+1. On your Sidekiq node, change the `/etc/gitlab/gitlab.rb` file to:
+
+ ```ruby
+ sidekiq['enable'] = true
+ sidekiq['queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category=global_search",
+ "feature_category!=global_search"
+ ]
+ ```
+
+1. Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
+for the changes to take effect.
+
+WARNING:
+When starting multiple processes, the number of processes cannot exceed the number of CPU
+cores you want to dedicate to Sidekiq. Each Sidekiq process can use only one CPU core, subject
+to the available workload and concurrency settings. For more details, see how to
+[run multiple Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
+
+### Two nodes, one process for each
+
+To handle these queue groups on two nodes:
+
+1. To set up the indexing Sidekiq process, on your indexing Sidekiq node, change the `/etc/gitlab/gitlab.rb` file to:
+
+ ```ruby
+ sidekiq['enable'] = true
+ sidekiq['queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category=global_search"
+ ]
+ ```
+
+1. Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
+for the changes to take effect.
+
+1. To set up the non-indexing Sidekiq process, on your non-indexing Sidekiq node, change the `/etc/gitlab/gitlab.rb` file to:
+
+ ```ruby
+ sidekiq['enable'] = true
+ sidekiq['queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category!=global_search"
+ ]
+ ```
+
+ to set up a non-indexing Sidekiq process.
+
+1. Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
+for the changes to take effect.
+
## Reverting to Basic Search
Sometimes there may be issues with your Elasticsearch index data and as such
@@ -983,6 +1070,13 @@ however searches will only surface results that can be viewed by the user.
Advanced Search will honor all permission checks in the application by
filtering out projects that a user does not have access to at search time.
+### Indexing fails with `error: elastic: Error 429 (Too Many Requests)`
+
+If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error during indexing, it usually means that Elasticsearch is unable to keep up with the concurrency of indexing request. To address change the following settings:
+
+- To decrease the indexing throughput you can decrease `Bulk request concurrency` (see [Advanced Search settings](#advanced-search-configuration)). This is set to `10` by default, but you change it to as low as 1 to reduce the number of concurrent indexing operations.
+- If changing `Bulk request concurrency` didn't help, you can use the [queue selector](../administration/operations/extra_sidekiq_processes.md#queue-selector) option to [limit indexing jobs only to specific Sidekiq nodes](#index-large-instances-with-dedicated-sidekiq-nodes-or-processes), which should reduce the number of indexing requests.
+
### Access requirements for the self-managed AWS OpenSearch Service
To use the self-managed AWS OpenSearch Service with GitLab, configure your instance's domain access policies
diff --git a/doc/integration/github.md b/doc/integration/github.md
index d8877e069b8..a265d5c67ed 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -4,198 +4,218 @@ group: Integrations
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
---
-# Integrate your GitLab instance with GitHub **(FREE SELF)**
+# Use GitHub as an authentication provider **(FREE SELF)**
-You can integrate your GitLab instance with GitHub.com and GitHub Enterprise. This integration
-enables users to import projects from GitHub, or sign in to your GitLab instance
-with their GitHub account.
+You can integrate your GitLab instance with GitHub.com and GitHub Enterprise.
+You can import projects from GitHub, or sign in to GitLab
+with your GitHub credentials.
-## Security check
+## Create an OAuth app in GitHub
-Some integrations risk compromising GitLab accounts. To help mitigate this
-[OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/)
-vulnerability, append `/users/auth` to the end of the authorization callback URL.
+To enable the GitHub OmniAuth provider, you need an OAuth 2.0 client ID and client
+secret from GitHub:
+
+1. Sign in to GitHub.
+1. [Create an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)
+ and provide the following information:
+ - The URL of your GitLab instance, such as `https://gitlab.example.com`.
+ - The authorization callback URL, such as, `https://gitlab.example.com/users/auth`.
+ Include the port number if your GitLab instance uses a non-default port.
+
+### Check for security vulnerabilities
+
+For some integrations, the [OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/)
+vulnerability can compromise GitLab accounts.
+To mitigate this vulnerability, append `/users/auth` to the authorization
+callback URL.
However, as far as we know, GitHub does not validate the subdomain part of the `redirect_uri`.
-This means that a subdomain takeover, an XSS, or an open redirect on any subdomain of
+Therefore, a subdomain takeover, an XSS, or an open redirect on any subdomain of
your website could enable the covert redirect attack.
-## Enabling GitHub OAuth
+## Enable GitHub OAuth in GitLab
-To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app).
+1. [Configure the initial settings](omniauth.md#configure-initial-settings) in GitLab.
-When you create an OAuth 2 app in GitHub, you need the following information:
+1. Edit the GitLab configuration file using the following information:
-- The URL of your GitLab instance, such as `https://gitlab.example.com`.
-- The authorization callback URL; in this case, `https://gitlab.example.com/users/auth`. Include the port number if your GitLab instance uses a non-default port.
+ | GitHub setting | Value in the GitLab configuration file | Description |
+ |----------------|----------------------------------------|-------------------------|
+ | Client ID | `YOUR_APP_ID` | OAuth 2.0 client ID |
+ | Client secret | `YOUR_APP_SECRET` | OAuth 2.0 client secret |
+ | URL | `https://github.example.com/` | GitHub deployment URL |
-See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
+ - **For Omnibus installations**
-After you have configured the GitHub provider, you need the following information. You must substitute that information in the GitLab configuration file in these next steps.
+ 1. Open the `/etc/gitlab/gitlab.rb` file.
-| Setting from GitHub | Substitute in the GitLab configuration file | Description |
-|:---------------------|:---------------------------------------------|:------------|
-| Client ID | `YOUR_APP_ID` | OAuth 2 Client ID |
-| Client Secret | `YOUR_APP_SECRET` | OAuth 2 Client Secret |
-| URL | `https://github.example.com/` | GitHub Deployment URL |
+ For GitHub.com, update the following section:
-Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ args: { scope: "user:email" }
+ }
+ ]
+ ```
-**For Omnibus installations**
+ For GitHub Enterprise, update the following section and replace
+ `https://github.example.com/` with your GitHub URL:
-1. Edit `/etc/gitlab/gitlab.rb`:
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ url: "https://github.example.com/",
+ args: { scope: "user:email" }
+ }
+ ]
+ ```
- For GitHub.com:
+ 1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ GitLab.
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: "github",
- # label: "Provider name", # optional label for login button, defaults to "GitHub"
- app_id: "YOUR_APP_ID",
- app_secret: "YOUR_APP_SECRET",
- args: { scope: "user:email" }
- }
- ]
- ```
+ - **For installations from source**
- For GitHub Enterprise:
+ 1. Open the `config/gitlab.yml` file.
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: "github",
- # label: "Provider name", # optional label for login button, defaults to "GitHub"
- app_id: "YOUR_APP_ID",
- app_secret: "YOUR_APP_SECRET",
- url: "https://github.example.com/",
- args: { scope: "user:email" }
- }
- ]
- ```
+ For GitHub.com, update the following section:
- **Replace `https://github.example.com/` with your GitHub URL.**
+ ```yaml
+ - { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
+ app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
+ args: { scope: 'user:email' } }
+ ```
-1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
+ For GitHub Enterprise, update the following section and replace
+ `https://github.example.com/` with your GitHub URL:
----
-
-**For installations from source**
+ ```yaml
+ - { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
+ app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
+ url: "https://github.example.com/",
+ args: { scope: 'user:email' } }
+ ```
-1. Navigate to your repository and edit `config/gitlab.yml`:
+ 1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source)
+ GitLab.
- For GitHub.com:
+1. Refresh the GitLab sign-in page. A GitHub icon should display below the
+ sign-in form.
- ```yaml
- - { name: 'github',
- # label: 'Provider name', # optional label for login button, defaults to "GitHub"
- app_id: 'YOUR_APP_ID',
- app_secret: 'YOUR_APP_SECRET',
- args: { scope: 'user:email' } }
- ```
+1. Select the icon. Sign in to GitHub and authorize the GitLab application.
- For GitHub Enterprise:
+## Troubleshooting
- ```yaml
- - { name: 'github',
- # label: 'Provider name', # optional label for login button, defaults to "GitHub"
- app_id: 'YOUR_APP_ID',
- app_secret: 'YOUR_APP_SECRET',
- url: "https://github.example.com/",
- args: { scope: 'user:email' } }
- ```
+### Imports from GitHub Enterprise with a self-signed certificate fail
- **Replace `https://github.example.com/` with your GitHub URL.**
+When you import projects from GitHub Enterprise using a self-signed
+certificate, the imports fail.
-1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect.
+To fix this issue, you must disable SSL verification:
----
+1. Set `verify_ssl` to `false` in the configuration file.
-1. Refresh the GitLab sign in page. You should now see a GitHub icon below the regular sign in form.
+ - **For Omnibus installations**
-1. Click the icon to begin the authentication process. GitHub asks the user to sign in and authorize the GitLab application.
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ url: "https://github.example.com/",
+ verify_ssl: false,
+ args: { scope: "user:email" }
+ }
+ ]
+ ```
-## GitHub Enterprise with self-signed Certificate
+ - **For installations from source**
-If you are attempting to import projects from GitHub Enterprise with a self-signed
-certificate and the imports are failing, you must disable SSL verification.
-It should be disabled by adding `verify_ssl` to `false` in the provider configuration
-and changing the global Git `sslVerify` option to `false` in the GitLab server.
+ ```yaml
+ - { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
+ app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
+ url: "https://github.example.com/",
+ verify_ssl: false,
+ args: { scope: 'user:email' } }
+ ```
-For Omnibus package:
+1. Change the global Git `sslVerify` option to `false` on the GitLab server.
-```ruby
-gitlab_rails['omniauth_providers'] = [
- {
- name: "github",
- # label: "Provider name", # optional label for login button, defaults to "GitHub"
- app_id: "YOUR_APP_ID",
- app_secret: "YOUR_APP_SECRET",
- url: "https://github.example.com/",
- verify_ssl: false,
- args: { scope: "user:email" }
- }
-]
-```
+ - **For Omnibus installations**
-You must also disable Git SSL verification on the server hosting GitLab.
+ ```ruby
+ omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
+ ```
-```ruby
-omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
-```
+ - **For installations from source**
-For installation from source:
+ ```shell
+ git config --global http.sslVerify false
+ ```
-```yaml
-- { name: 'github',
- # label: 'Provider name', # optional label for login button, defaults to "GitHub"
- app_id: 'YOUR_APP_ID',
- app_secret: 'YOUR_APP_SECRET',
- url: "https://github.example.com/",
- verify_ssl: false,
- args: { scope: 'user:email' } }
-```
+1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ if you installed using Omnibus, or [restart GitLab](../administration/restart_gitlab.md#installations-from-source)
+ if you installed from source.
-You must also disable Git SSL verification on the server hosting GitLab.
+### Signing in using GitHub Enterprise returns a 500 error
-```shell
-git config --global http.sslVerify false
-```
+This error can occur because of a network connectivity issue between your
+GitLab instance and GitHub Enterprise.
-For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) if you installed
-via Omnibus, or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) if you installed from source.
+To check for a connectivity issue:
-## Troubleshooting
+1. Go to the [`production.log`](../administration/logs.md#productionlog)
+ on your GitLab server and look for the following error:
-### Error 500 when trying to sign in to GitLab via GitHub Enterprise
+ ``` plaintext
+ Faraday::ConnectionFailed (execution expired)
+ ```
-Check the [`production.log`](../administration/logs.md#productionlog)
-on your GitLab server to obtain further details. If you are getting the error like
-`Faraday::ConnectionFailed (execution expired)` in the log, there may be a connectivity issue
-between your GitLab instance and GitHub Enterprise. To verify it, [start the rails console](../administration/operations/rails_console.md#starting-a-rails-console-session)
-and run the commands below replacing `<github_url>` with the URL of your GitHub Enterprise instance:
+1. [Start the rails console](../administration/operations/rails_console.md#starting-a-rails-console-session)
+ and run the following commands. Replace `<github_url>` with the URL of your
+ GitHub Enterprise instance:
-```ruby
-uri = URI.parse("https://<github_url>") # replace `GitHub-URL` with the real one here
-http = Net::HTTP.new(uri.host, uri.port)
-http.use_ssl = true
-http.verify_mode = 1
-response = http.request(Net::HTTP::Get.new(uri.request_uri))
-```
+ ```ruby
+ uri = URI.parse("https://<github_url>") # replace `GitHub-URL` with the real one here
+ http = Net::HTTP.new(uri.host, uri.port)
+ http.use_ssl = true
+ http.verify_mode = 1
+ response = http.request(Net::HTTP::Get.new(uri.request_uri))
+ ```
-If you are getting a similar `execution expired` error, it confirms the theory about the
-network connectivity. In that case, make sure that the GitLab server is able to reach your
-GitHub enterprise instance.
+1. If a similar `execution expired` error is returned, this confirms the error is
+ caused by a connectivity issue. Make sure the GitLab server can reach
+ your GitHub Enterprise instance.
### Signing in using your GitHub account without a pre-existing GitLab account is not allowed
-If you're getting the message `Signing in using your GitHub account without a pre-existing
-GitLab account is not allowed. Create a GitLab account first, and then connect it to your
-GitHub account` when signing in, in GitLab:
+When you sign in to GitLab, you get the following error:
+
+```plaintext
+Signing in using your GitHub account without a pre-existing
+GitLab account is not allowed. Create a GitLab account first,
+and then connect it to your GitHub account
+```
+
+To fix this issue, you must activate GitHub sign-in in GitLab:
-1. In the top-right corner, select your avatar.
+1. On the top bar, in the top right corner, select your avatar.
1. Select **Edit profile**.
1. On the left sidebar, select **Account**.
1. In the **Social sign-in** section, select **Connect to GitHub**.
-
-After that, you should be able to sign in via GitHub successfully.
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 2dd357e50a6..74ae9bb1998 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -24,7 +24,12 @@ GitLab.com generates an application ID and secret key for you to use.
http://your-gitlab.example.com/users/auth/gitlab/callback
```
- The first link is required for the importer and second for the authorization.
+ The first link is required for the importer and second for authentication.
+
+ If you:
+
+ - Plan to use the importer, you can leave scopes as they are.
+ - Only want to use this application for authentication, we recommend using a more minimal set of scopes. `read_user` is sufficient.
1. Select **Save application**.
1. You should now see an **Application ID** and **Secret**. Keep this page open as you continue
@@ -57,7 +62,9 @@ GitLab.com generates an application ID and secret key for you to use.
# label: "Provider name", # optional label for login button, defaults to "GitLab.com"
app_id: "YOUR_APP_ID",
app_secret: "YOUR_APP_SECRET",
- args: { scope: "api" }
+ args: { scope: "read_user" # optional: defaults to the scopes of the application
+ , client_options: { site: "https://gitlab.example.com/api/v4" }
+ }
}
]
```
@@ -71,7 +78,8 @@ GitLab.com generates an application ID and secret key for you to use.
label: "Provider name", # optional label for login button, defaults to "GitLab.com"
app_id: "YOUR_APP_ID",
app_secret: "YOUR_APP_SECRET",
- args: { scope: "api", client_options: { site: "https://gitlab.example.com/api/v4" } }
+ args: { scope: "read_user" # optional: defaults to the scopes of the application
+ , client_options: { site: "https://gitlab.example.com/api/v4" } }
}
]
```
@@ -83,7 +91,7 @@ GitLab.com generates an application ID and secret key for you to use.
# label: 'Provider name', # optional label for login button, defaults to "GitLab.com"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
- args: { scope: 'api' } }
+ args: { "client_options": { "site": 'https://gitlab.example.com/api/v4' } }
```
Or, for installations from source to authenticate against a different GitLab instance:
@@ -93,7 +101,7 @@ GitLab.com generates an application ID and secret key for you to use.
label: 'Provider name', # optional label for login button, defaults to "GitLab.com"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
- args: { scope: 'api', "client_options": { "site": 'https://gitlab.example.com/api/v4' } }
+ args: { "client_options": { "site": 'https://gitlab.example.com/api/v4' } }
```
1. Change `'YOUR_APP_ID'` to the Application ID from the GitLab.com application page.
@@ -101,7 +109,6 @@ GitLab.com generates an application ID and secret key for you to use.
1. Save the configuration file.
1. Based on how GitLab was installed, implement these changes by using
the appropriate method:
-
- Omnibus GitLab: [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
- Source: [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
@@ -110,3 +117,20 @@ regular sign-in form. Select the icon to begin the authentication process.
GitLab.com asks the user to sign in and authorize the GitLab application. If
everything goes well, the user is returned to your GitLab instance and is
signed in.
+
+## Reduce access privileges on sign in
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/337663) in GitLab 14.8 [with a flag](../administration/feature_flags.md) named `omniauth_login_minimal_scopes`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `omniauth_login_minimal_scopes`. On GitLab.com, this feature is not available.
+
+If you use a GitLab instance for authentication, you can reduce access rights when an OAuth application is used for sign in.
+
+Any OAuth application can advertise the purpose of the application with the
+authorization parameter: `gl_auth_type=login`. If the application is
+configured with `api` or `read_api`, the access token is issued with
+`read_user` for login, because no higher permissions are needed.
+
+The GitLab OAuth client is configured to pass this parameter, but other
+applications can also pass it.
diff --git a/doc/integration/img/enable_trello_powerup.png b/doc/integration/img/enable_trello_powerup.png
deleted file mode 100644
index f80d0eadc0b..00000000000
--- a/doc/integration/img/enable_trello_powerup.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index bae52622966..b86643c7279 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -44,7 +44,7 @@ Grant a GitLab user access to the relevant GitLab projects.
1. Grant the user permission to the GitLab projects.
If you're integrating Jenkins with many GitLab projects, consider granting the
- user the administrator access level. Otherwise, add the user to each project
+ user administrator access. Otherwise, add the user to each project
and grant the Developer role.
## Grant Jenkins access to the GitLab API
@@ -137,6 +137,7 @@ than the [webhook integration](#configure-a-webhook).
- Merge request
- Tag push
1. Enter the **Jenkins server URL**.
+1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](../user/project/integrations/overview.md#ssl-verification).
1. Enter the **Project name**.
The project name should be URL-friendly, where spaces are replaced with underscores. To ensure
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index 8da3118cf2c..57219b18047 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -19,7 +19,7 @@ This service was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/1600) i
Integration includes:
- Trigger Jenkins build after push to repository
-- Show build status on Merge Request page
+- Show build status on Merge request page
Requirements:
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index 597293ae5ca..ebe8a0f1af4 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -10,8 +10,7 @@ You can integrate GitLab and Jira Cloud using the
[GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
app in the Atlassian Marketplace.
-NOTE:
-Only Jira users with the administrator role can install or configure
+Only Jira users with administrator access can install or configure
the GitLab.com for Jira Cloud app.
## Install the GitLab.com for Jira Cloud app **(FREE SAAS)**
@@ -23,7 +22,7 @@ We recommend the GitLab.com for Jira Cloud app, because data is
synchronized in real time. The DVCS connector updates data only once per hour.
The user configuring the GitLab.com for Jira Cloud app must have
-at least the [Maintainer](../../user/permissions.md) role in the GitLab.com namespace.
+at least the Maintainer role in the GitLab.com namespace.
This integration method supports [Smart Commits](dvcs.md#smart-commits).
@@ -43,7 +42,7 @@ To install the GitLab.com for Jira Cloud app:
![Start GitLab.com app configuration on Jira Cloud](img/jira_dev_panel_setup_com_2.png)
1. If not already signed in to GitLab.com, you must sign in as a user with
- [Maintainer](../../user/permissions.md) permissions to add namespaces.
+ the Maintainer role to add namespaces.
![Sign in to GitLab.com in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_3_v13_9.png)
1. To open the list of available namespaces, select **Add namespace**.
@@ -91,10 +90,10 @@ self-managed GitLab instances with Jira Cloud, you can either:
You can configure your Atlassian Cloud instance to allow you to install applications
from outside the Marketplace, which allows you to install the application:
-1. Sign in to your Jira instance as a user with an Administrator role.
+1. Sign in to your Jira instance as an administrator.
1. Place your Jira instance into
[development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode).
-1. Sign in to your GitLab application as an [administrator](../../user/permissions.md).
+1. Sign in to your GitLab application as a user with administrator access.
1. Install the GitLab application from your self-managed GitLab instance, as
described in the [Atlassian developer guides](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-3--install-and-test-your-app):
1. In your Jira instance, go to **Apps > Manage Apps** and select **Upload app**:
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 04a02b8fa68..17a81419ad0 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 02fe0f4ea71..6ac4faa5a35 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -372,19 +372,11 @@ For a complete list of upgrade notices and special considerations for older vers
## Upgrading GitLab Mattermost to 14.6
-GitLab 14.6 includes Mattermost 6.1, and also includes the migrations for Mattermost 6.0. For information about upgrading and for ways to reduce the downtime of those migrations, read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for both versions.
+GitLab 14.6 ships with Mattermost 6.1 including potentially long running database migrations for Mattermost 6.0. For information about upgrading and for ways to reduce the downtime caused by those migrations, read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for both versions. If you need to perform any manual migrations, [connect to the bundled PostgreSQL database](#connecting-to-the-bundled-postgresql-database).
NOTE:
The Mattermost upgrade notes refer to different impacts when used with a PostgreSQL versus a MySQL database. The GitLab Mattermost included with the GitLab Linux packages uses a PostgreSQL database.
-If you need to connect in the database to perform any manual migrations, run the following:
-
-```console
-sudo gitlab-psql -d mattermost_production
-```
-
-You can then run the necessary queries that are described in the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html).
-
## Upgrading GitLab Mattermost from versions prior to 11.0
With version 11.0, GitLab introduced breaking changes which affected Mattermost configuration.
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index ff144d9985b..adfb2fad941 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -86,25 +86,24 @@ To create an application for your GitLab instance:
When creating application in the **Admin Area** , you can mark it as _trusted_.
The user authorization step is automatically skipped for this application.
-## Expiring Access Tokens
+## Expiring access tokens
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21745) in GitLab 14.3.
-By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and
-earlier, OAuth access tokens had no expiration.
+WARNING:
+The ability to opt-out of expiring access tokens [is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/340848).
+All existing integrations should be updated to support access token refresh.
-All integrations should update to support access token refresh.
+Access tokens expire in two hours which means that integrations that use them must support generating new access
+tokens at least every two hours. Existing:
-When creating new applications, you can opt-out of expiry for backward compatibility by clearing
-**Expire access tokens** when creating them. The ability to opt-out
-[is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/340848).
-
-Existing:
-
-- Applications can have expiring access tokens. Edit the application and select
- **Expire access tokens** to enable them.
+- Applications can have expiring access tokens:
+ 1. Edit the application.
+ 1. Select **Expire access tokens**.
- Tokens must be [revoked](../api/oauth2.md#revoke-a-token) or they don't expire.
+When applications are deleted, all grants and tokens associated with the application are also deleted.
+
## Authorized applications
Every application you authorize with your GitLab credentials is shown
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index e85231d1c25..1254b29bfb9 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -35,12 +35,15 @@ is select the `openid` scope in the application settings.
## Settings discovery
-If your client allows importing OIDC settings from a discovery URL, you can use the following URL to automatically find the correct settings:
+If your client allows importing OIDC settings from a discovery URL, you can use
+the following URL to automatically find the correct settings for GitLab.com:
```plaintext
-https://gitlab.example.com/.well-known/openid-configuration
+https://gitlab.com/.well-known/openid-configuration
```
+Similar URLs can be used for other GitLab instances.
+
## Shared information
The following user information is shared with clients:
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 61d09b4e173..95bf835147d 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -367,7 +367,7 @@ The requirements are the same as the previous settings:
- The IdP must pass Group information to GitLab.
- GitLab must know where to look for the groups in the SAML response, as well as
- which group(s) grant the user an administrator role.
+ which groups grant the user administrator access.
```yaml
{ name: 'saml',
@@ -504,7 +504,7 @@ omniauth:
Keep in mind that every sign in attempt redirects to the SAML server;
you cannot sign in using local credentials. Ensure at least one of the
-SAML users has an administrator role.
+SAML users has administrator access.
You may also bypass the auto sign-in feature by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
diff --git a/doc/integration/trello_power_up.md b/doc/integration/trello_power_up.md
index 96150440e53..8a8952cb594 100644
--- a/doc/integration/trello_power_up.md
+++ b/doc/integration/trello_power_up.md
@@ -6,44 +6,25 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Trello Power-Up **(FREE)**
-The GitLab Trello Power-Up enables you to seamlessly attach
-GitLab **merge requests** to Trello cards.
+You can use the Trello Power-Up for GitLab to attach
+GitLab merge requests to Trello cards.
![GitLab Trello PowerUp - Trello card](img/trello_card_with_gitlab_powerup.png)
-## Configuring the Power-Up
+## Configure the Power-Up
-In order to get started, you must configure your Power-Up.
+To configure a Power-Up for a Trello board:
-In Trello:
+1. Go to your Trello board.
+1. Select **Power-Ups** and find the **GitLab** row.
+1. Select **Enable**.
+1. Select **Settings** (the gear icon).
+1. Select **Authorize Account**.
+1. Enter the [GitLab API URL](#get-the-api-url) and [personal access token](../user/profile/personal_access_tokens.md#create-a-personal-access-token) with the **API** scope.
+1. Select **Save**.
-1. Go to your Trello board
-1. Select `Power-Ups` to see a listing of all the available Power-Ups
-1. Look for a row that says `GitLab` and select the `Enable` button
-1. Select the `Settings` (gear) icon
-1. In the popup menu, select `Authorize Account`
+## Get the API URL
-In this popup, fill in your `API URL` and `Personal Access Token`. After that, you can attach any merge request to any Trello card on your selected Trello board.
-
-## What is my API URL?
-
-Your API URL should be your GitLab instance URL with `/api/v4` appended in the end of the URL.
-For example, if your GitLab instance URL is `https://gitlab.com`, your API URL would be `https://gitlab.com/api/v4`.
-If your instance's URL is `https://example.com`, your API URL is `https://example.com/api/v4`.
-
-![configure GitLab Trello PowerUp in Trello](img/enable_trello_powerup.png)
-
-## What is my Personal Access Token?
-
-Your GitLab personal access token enables your GitLab account to be accessed
-from Trello.
-
-To find it in GitLab:
-
-1. In the top-right corner, select your avatar.
-1. Select **Edit profile**.
-1. On the left sidebar, select **Access Tokens**.
-
-Learn more about generating a personal access token in the
-[Personal Access Token Documentation](../user/profile/personal_access_tokens.md).
-Don't forget to check the API scope checkbox!
+Your API URL is your GitLab instance URL with `/api/v4` appended at the end of the URL.
+For example, if your GitLab instance URL is `https://gitlab.com`, your API URL is `https://gitlab.com/api/v4`.
+If your instance URL is `https://example.com`, your API URL is `https://example.com/api/v4`.
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 7533646aa34..6f97f002a32 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/feature_flags.md b/doc/operations/feature_flags.md
index b0a180b5635..8903e99ab3b 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -168,7 +168,7 @@ target users. See the [Ruby example](#ruby-application-example) below.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300299) in GitLab 14.4.
Search your project and find any references of a feature flag in your
-code so that you and clean it up when it's time to remove the feature flag.
+code so that you can clean it up when it's time to remove the feature flag.
To search for code references of a feature flag:
@@ -345,7 +345,7 @@ import (
"log"
"net/http"
- "github.com/Unleash/unleash-client-go"
+ "github.com/Unleash/unleash-client-go/v3"
)
type metricsInterface struct {
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index cdf7ca5c8bc..b03955edf87 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -10,7 +10,7 @@ Alerts are a critical entity in your incident management workflow. They represen
## Alert List
-Users with at least the Developer [role](../../user/permissions.md) can
+Users with at least the Developer role can
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.
@@ -68,7 +68,7 @@ Alerts contain one of the following icons:
## Alert details page
Navigate to the Alert details view by visiting the [Alert list](alerts.md)
-and selecting an alert from the list. You need at least the Developer [role](../../user/permissions.md)
+and selecting an alert from the list. You need at least the Developer role
to access alerts.
NOTE:
@@ -96,7 +96,7 @@ instance.
Prerequisite:
-- You must have at least the Developer [role](../../user/permissions.md).
+- You must have at least the Developer role.
To view the metrics for an alert:
@@ -120,7 +120,7 @@ your application's performance and how to resolve any problems.
Prerequisite:
-- You must have at least the Developer [role](../../user/permissions.md).
+- You must have at least the Developer role.
To view the logs for an alert:
diff --git a/doc/operations/incident_management/escalation_policies.md b/doc/operations/incident_management/escalation_policies.md
index 5f132720000..c24824e55f8 100644
--- a/doc/operations/incident_management/escalation_policies.md
+++ b/doc/operations/incident_management/escalation_policies.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -17,7 +17,7 @@ where you manage [On-call schedules](oncall_schedules.md).
Prerequisite:
-- You must have at least the Maintainer [role](../../user/permissions.md).
+- You must have at least the Maintainer role.
- You must have an [on-call schedule](oncall_schedules.md).
To create an escalation policy:
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index ada1f426dd8..e142d060d87 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -21,15 +21,15 @@ You can create an incident manually or automatically.
> - [Moved](https://gitlab.com/gitlab-org/monitor/monitor/-/issues/24) to GitLab Free in 13.3.
> - [Permission changed](https://gitlab.com/gitlab-org/gitlab/-/issues/336624) from Guest to Reporter in GitLab 14.5.
+> - Automatic application of the `incident` label [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/290964) in GitLab 14.8.
If you have at least Reporter [permissions](../../user/permissions.md),
you can create an incident manually from the Incidents List or the Issues List.
To create an incident from the Incidents List:
-1. Navigate to **Monitor > Incidents** and click **Create Incident**.
-1. Create a new issue using the `incident` template available when creating it.
-1. Create a new issue and assign the `incident` label to it.
+1. Navigate to **Monitor > Incidents** and select **Create Incident**.
+1. Create a new issue using the `incident` template.
![Incident List Create](img/incident_list_create_v13_3.png)
@@ -47,15 +47,15 @@ To create an incident from the Issues List:
### Create incidents automatically **(ULTIMATE)**
-With at least the Maintainer [role](../../user/permissions.md), you can enable
- GitLab to create incident automatically whenever an alert is triggered:
+With at least the Maintainer role, you can enable
+GitLab to create incident automatically whenever an alert is triggered:
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).
1. To send [an email notification](paging.md#email-notifications) to users
- with the Developer [role](../../user/permissions.md), select
+ with the Developer role, select
**Send a separate email notification to Developers**. Email notifications are
also sent to users with the **Maintainer** and **Owner** roles.
1. Click **Save changes**.
@@ -68,7 +68,7 @@ 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 the Maintainer [role](../../user/permissions.md).
+1. Sign in as a user with the Maintainer role.
1. Navigate to **Settings > Monitor > Incidents** and expand **Incidents**.
1. Select the **PagerDuty integration** tab:
@@ -276,7 +276,7 @@ templates.
> - [Introduced for Prometheus Integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/13401) in GitLab 12.5.
> - [Introduced for HTTP Integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/13402) in GitLab 13.4.
-With at least the Maintainer [role](../../user/permissions.md), you can enable
+With at least the Maintainer role, you can enable
GitLab to close an incident automatically when a **Recovery Alert** is received:
1. Navigate to **Settings > Monitor > Incidents** and expand **Incidents**.
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index ff5f41e59e9..3b38d4ab427 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index a8b455e05a0..fe05cb9fda0 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -18,7 +18,7 @@ to use this endpoint.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in GitLab 13.5.
-With at least the Maintainer [role](../../user/permissions.md), you can view the list of configured
+With at least the Maintainer role, 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):
@@ -36,7 +36,7 @@ Enabling the HTTP Endpoint in a GitLab projects activates it to
receive alert payloads in JSON format. You can always
[customize the payload](#customize-the-alert-payload-outside-of-gitlab) to your liking.
-1. Sign in to GitLab as a user with the Maintainer [role](../../user/permissions.md)
+1. Sign in to GitLab as a user with the Maintainer role
for a project.
1. Navigate to **Settings > Monitor** in your project.
1. Expand the **Alerts** section, and in the **Select integration type** dropdown menu,
@@ -53,7 +53,7 @@ In [GitLab Premium](https://about.gitlab.com/pricing/), you can create multiple
unique HTTP endpoints to receive alerts from any external source in JSON format,
and you can [customize the payload](#customize-the-alert-payload-outside-of-gitlab).
-1. Sign in to GitLab as a user with the Maintainer [role](../../user/permissions.md)
+1. Sign in to GitLab as a user with the Maintainer role
for a project.
1. Navigate to **Settings > Monitor** in your project.
1. Expand the **Alerts** section.
@@ -225,7 +225,7 @@ After a [project maintainer or owner](../../user/permissions.md)
configures an integration, you can trigger a test
alert to confirm your integration works properly.
-1. Sign in as a user with at least the Developer [role](../../user/permissions.md).
+1. Sign in as a user with at least the Developer role.
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).
@@ -279,7 +279,7 @@ active at the same time.
To enable Opsgenie integration:
-1. Sign in as a user with the Maintainer or Owner [role](../../user/permissions.md).
+1. Sign in as a user with the Maintainer or Owner role.
1. Navigate to **Monitor > Alerts**.
1. In the **Integrations** select box, select **Opsgenie**.
1. Select the **Active** toggle.
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
index 2a8f0eac59c..84ab5da77df 100644
--- a/doc/operations/incident_management/oncall_schedules.md
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -24,7 +24,7 @@ Set up an on-call schedule for your team to add rotations to.
Prerequisite:
-- You must have at least the Maintainer [role](../../user/permissions.md).
+- You must have at least the Maintainer role.
To create an on-call schedule:
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
index 6fdf880783a..b6f77de3b4f 100644
--- a/doc/operations/incident_management/paging.md
+++ b/doc/operations/incident_management/paging.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index 241112df521..fe75c1812c8 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -41,7 +41,7 @@ Only AWS S3 is supported as a deploy target.
Prerequisite:
-- You must have at least the Maintainer [role](../../user/permissions.md).
+- You must have at least the Maintainer role.
To provide GitLab with the AWS account information needed to push content to your Status Page:
@@ -175,5 +175,5 @@ within GitLab. Closing the issue triggers a background worker to update the
GitLab Status Page website.
If you
-[make a published issue confidential](../../user/project/issues/confidential_issues.md#making-an-issue-confidential),
+[make a published issue confidential](../../user/project/issues/confidential_issues.md#make-an-issue-confidential),
GitLab unpublishes it from your GitLab Status Page website.
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 5a83e47b556..9b988ff561d 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 712ee04e916..702ff944fc5 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -99,8 +99,7 @@ GitLab tags each incident issue with the `incident` label automatically. If the
does not yet exist, it is also created automatically.
If the metric exceeds the threshold of the alert for over 5 minutes, GitLab sends
-an email to all [Maintainers and Owners](../../user/permissions.md#project-members-permissions)
-of the project.
+an email to all Maintainers and Owners of the project.
### Recovery alerts
diff --git a/doc/operations/metrics/dashboards/default.md b/doc/operations/metrics/dashboards/default.md
index 295c146f0d5..3e14917209a 100644
--- a/doc/operations/metrics/dashboards/default.md
+++ b/doc/operations/metrics/dashboards/default.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/develop.md b/doc/operations/metrics/dashboards/develop.md
index 38f375c40a6..fc7686c8f86 100644
--- a/doc/operations/metrics/dashboards/develop.md
+++ b/doc/operations/metrics/dashboards/develop.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index 9a75703a2f1..a8ca23b7002 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/panel_types.md b/doc/operations/metrics/dashboards/panel_types.md
index 9b015760fe9..09e969e8af6 100644
--- a/doc/operations/metrics/dashboards/panel_types.md
+++ b/doc/operations/metrics/dashboards/panel_types.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index f4c37718c52..14da5cf4a04 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/templating_variables.md b/doc/operations/metrics/dashboards/templating_variables.md
index 8ccd334dac3..531693d032f 100644
--- a/doc/operations/metrics/dashboards/templating_variables.md
+++ b/doc/operations/metrics/dashboards/templating_variables.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index 0008706df40..369bcd1ddeb 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/yaml.md b/doc/operations/metrics/dashboards/yaml.md
index 9d1c270388e..81f1354d3c0 100644
--- a/doc/operations/metrics/dashboards/yaml.md
+++ b/doc/operations/metrics/dashboards/yaml.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/dashboards/yaml_number_format.md b/doc/operations/metrics/dashboards/yaml_number_format.md
index ce9e359a587..fd83bff3c08 100644
--- a/doc/operations/metrics/dashboards/yaml_number_format.md
+++ b/doc/operations/metrics/dashboards/yaml_number_format.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/embed.md b/doc/operations/metrics/embed.md
index e84c190e08d..6a3712d8377 100644
--- a/doc/operations/metrics/embed.md
+++ b/doc/operations/metrics/embed.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
@@ -53,7 +53,7 @@ The following requirements must be met for the metric to unfurl:
- The `<environment_id>` must correspond to a real environment.
- Prometheus must be monitoring the environment.
- The GitLab instance must be configured to receive data from the environment.
-- The user must be allowed access to the monitoring dashboard for the environment ([Reporter or higher](../../user/permissions.md)).
+- The user must have at least the Reporter role for the monitoring dashboard for the environment.
- The dashboard must have data within the last 8 hours.
If all of the above are true, then the metric unfurls as seen below:
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 81b1f8a3bc6..5bfb097619d 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/metrics/index.md b/doc/operations/metrics/index.md
index f09b9f35d88..b04e19807f8 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/operations/product_analytics.md b/doc/operations/product_analytics.md
index 3ff33027042..a55cbe906a0 100644
--- a/doc/operations/product_analytics.md
+++ b/doc/operations/product_analytics.md
@@ -50,7 +50,7 @@ Feature.disable(:product_analytics, Project.find(<project ID>))
After enabling the feature flag for Product Analytics, you can access the
user interface:
-1. Sign in to GitLab as a user with at least the Reporter [role](../user/permissions.md).
+1. Sign in to GitLab as a user with at least the Reporter role.
1. Navigate to **Monitor > Product Analytics**.
The user interface contains:
diff --git a/doc/operations/tracing.md b/doc/operations/tracing.md
index 09a31c12bf4..044f6800e73 100644
--- a/doc/operations/tracing.md
+++ b/doc/operations/tracing.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/public_access/public_access.md b/doc/public_access/public_access.md
index e0b07abd4e9..8eee8fc9a6b 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -7,7 +7,7 @@ type: reference
# Project and group visibility **(FREE)**
-GitLab allows users with the Owner [role](../user/permissions.md) to set a project's or group's visibility as:
+GitLab allows users with the Owner role to set a project's or group's visibility as:
- **Public**
- **Internal**
@@ -24,7 +24,7 @@ Public projects can be cloned **without any** authentication over HTTPS.
They are listed in the public access directory (`/public`) for all users.
-**Any signed-in user** has the Guest [role](../user/permissions.md) on the repository.
+**Any signed-in user** has the Guest role on the repository.
NOTE:
By default, `/public` is visible to unauthenticated users. However, if the
@@ -39,7 +39,7 @@ Internal projects can be cloned by any signed-in user except
They are also listed in the public access directory (`/public`), but only for signed-in users.
Any signed-in users except [external users](../user/permissions.md#external-users) have the
-Guest [role](../user/permissions.md) on the repository.
+Guest role on the repository.
NOTE:
From July 2019, the `Internal` visibility setting is disabled for new projects, groups,
@@ -57,7 +57,7 @@ They appear in the public access directory (`/public`) for project members only.
Prerequisite:
-- You must have the Owner [role](../user/permissions.md) for a project.
+- You must have the Owner role for a project.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > General**.
@@ -69,7 +69,7 @@ Prerequisite:
Prerequisite:
-- You must have the Owner [role](../user/permissions.md) for a group.
+- You must have the Owner role for a group.
1. On the top bar, select **Menu > Groups** and find your project.
1. On the left sidebar, select **Settings > General**.
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index c37853ffe81..3c4b0e10bf9 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -1,273 +1,9 @@
---
-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"
-type: reference, howto
+redirect_to: '../user/project/repository/push_rules.md'
+remove_date: '2022-05-10'
---
-# Push rules **(PREMIUM)**
+This document was moved to [another location](../user/project/repository/push_rules.md).
-Gain additional control over what can and can't be pushed to your repository by using
-regular expressions to reject pushes based on commit contents, branch names or file details.
-
-GitLab already offers [protected branches](../user/project/protected_branches.md), but there are
-cases when you need some specific rules. Some common scenarios: preventing Git tag removal, or
-enforcing a special format for commit messages.
-
-Push rules are [pre-receive Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you
-can enable in a user-friendly interface. They are defined either:
-
-- Globally if you are an administrator.
-- Per project, so you can have different rules applied to different
- projects depending on your needs.
-
-## Use cases
-
-Every push rule could have its own use case, but let's consider some examples.
-
-### Commit messages with a specific reference
-
-Let's assume you have the following requirements for your workflow:
-
-- every commit should reference a Jira issue, for example: `Refactored css. Fixes JIRA-123.`
-- users should not be able to remove Git tags with `git push`
-
-Write a regular expression that requires the mention
-of a Jira issue in the commit message, like `JIRA\-\d+`.
-
-Now when a user tries to push a commit with a message `Bugfix`, their push is
-declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
-is accepted.
-
-### Restrict branch names
-
-If your company has a strict policy for branch names, you may want the branches to start
-with a certain name. This approach enables different
-GitLab CI/CD jobs (such as `feature`, `hotfix`, `docker`, `android`) that rely on the
-branch name.
-
-Your developers may not remember that policy, so they might push to
-various branches, and CI pipelines might not work as expected. By restricting the
-branch names globally in Push Rules, such mistakes are prevented.
-All branch names that don't match your push rule are rejected.
-
-Note that the name of your default branch is always allowed, regardless of the branch naming
-regular expression (regex) specified. GitLab is configured this way
-because merges typically have the default branch as their target.
-If you have other target branches, include them in your regex. (See [Enabling push rules](#enabling-push-rules)).
-
-The default branch also defaults to being a [protected branch](../user/project/protected_branches.md),
-which already limits users from pushing directly.
-
-Some example regular expressions you can use in push rules:
-
-- `^JIRA-` Branches must start with `JIRA-`.
-- `-JIRA$` Branches must end with `-JIRA`.
-- `^[a-z0-9\\-]{4,15}$` Branches must be between `4` and `15` characters long,
- accepting only lowercase letters, numbers and dashes.
-
-#### Default restricted branch names
-
-> Introduced in GitLab 12.10.
-
-By default, GitLab restricts certain formats of branch names for security purposes.
-40-character hexadecimal names, similar to Git commit hashes, are prohibited.
-
-### Custom Push Rules **(PREMIUM SELF)**
-
-It's possible to create custom push rules rather than the push rules available in
-**Admin Area > Push Rules** by using more advanced server hooks.
-
-See [server hooks](../administration/server_hooks.md) for more information.
-
-## Enabling 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**.
-1. On the left sidebar, select **Push Rules**.
-
-To override global push rules in a project's settings:
-
-1. On the top bar, select **Menu > Projects** and find your project.
-1. On the left sidebar, select **Settings > Repository**.
-1. Expand **Push rules**.
-1. Set the rule you want.
-1. Select **Save push rules**.
-
-The following options are available:
-
-| Push rule | Description |
-|---------------------------------|-------------|
-| Removal of tags with `git push` | Forbid users to remove Git tags with `git push`. Tags can be deleted through the web UI. |
-| Check whether the commit author is a GitLab user | Restrict commits to existing GitLab users (checked against their emails). <sup>1</sup> |
-| Reject unverified users | GitLab rejects any commit that was not committed by the same user as the user who pushed it, or where the committer's email address is not [confirmed](../security/user_email_confirmation.md). |
-| Check whether commit is signed through GPG | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). |
-| Prevent pushing secret files | GitLab rejects any files that are likely to contain secrets. See the [forbidden file names](#prevent-pushing-secrets-to-the-repository). |
-| Require expression in commit messages | Only commit messages that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
-| Reject expression in commit messages | Only commit messages that do not match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
-| Restrict by branch name | Only branch names that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow all branch names. |
-| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. <sup>1</sup> <sup>2</sup> Leave empty to allow any email. |
-| Prohibited file names | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. <sup>2</sup> Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
-| Maximum file size | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
-
-1. Checks both the commit author and committer.
-1. GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
-
-### Caveat to "Reject unsigned commits" push rule
-
-This push rule ignores commits that are authenticated and created by GitLab
-(either through the UI or API). When the **Reject unsigned commits** push rule is
-enabled, unsigned commits may still show up in the commit history if a commit was
-created **within** GitLab itself. As expected, commits created outside GitLab and
-pushed to the repository are rejected. For more information about how GitLab
-plans to fix this issue, read [issue #19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
-
-#### "Reject unsigned commits" push rule disables Web IDE
-
-In 13.10, if a project has the "Reject unsigned commits" push rule, the user will not be allowed to
-commit through GitLab Web IDE.
-
-To allow committing through the Web IDE on a project with this push rule, a GitLab administrator will
-need to disable the feature flag `reject_unsigned_commits_by_gitlab`. This can be done through a
-[rails console](../administration/operations/rails_console.md) and running:
-
-```ruby
-Feature.disable(:reject_unsigned_commits_by_gitlab)
-```
-
-## Prevent pushing secrets to the repository
-
-> Moved to GitLab Premium in 13.9.
-
-Secrets, such as credential files and SSH private keys, should never be committed to a version control
-system. In GitLab, you can use a predefined list of files to block those files from a
-repository. Any merge request containing a file matching the list is blocked from being merged.
-Files already committed to the repository are not restricted by this push rule.
-
-Files blocked by this rule are listed below. For a complete list of criteria, see
-[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml).
-
-- AWS CLI credential blobs:
-
- - `.aws/credentials`
- - `aws/credentials`
- - `homefolder/aws/credentials`
-
-- Private RSA SSH keys:
-
- - `/ssh/id_rsa`
- - `/.ssh/personal_rsa`
- - `/config/server_rsa`
- - `id_rsa`
- - `.id_rsa`
-
-- Private DSA SSH keys:
-
- - `/ssh/id_dsa`
- - `/.ssh/personal_dsa`
- - `/config/server_dsa`
- - `id_dsa`
- - `.id_dsa`
-
-- Private ed25519 SSH keys:
-
- - `/ssh/id_ed25519`
- - `/.ssh/personal_ed25519`
- - `/config/server_ed25519`
- - `id_ed25519`
- - `.id_ed25519`
-
-- Private ECDSA SSH keys:
-
- - `/ssh/id_ecdsa`
- - `/.ssh/personal_ecdsa`
- - `/config/server_ecdsa`
- - `id_ecdsa`
- - `.id_ecdsa`
-
-- Any files ending with these suffixes:
-
- - `*.pem`
- - `*.key`
- - `*.history`
- - `*_history`
-
-### Prevent pushing secrets to all projects
-
-To set a global push rule to prevent pushing secrets to all projects:
-
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Push Rules**.
-1. Expand **Push rules**.
-1. Select **Prevent pushing secret files**.
-1. Select **Save push rules**.
-
-### Prevent pushing secrets to a project
-
-The push rule of a project overrides the global push rule.
-
-To prevent pushing secrets to a project:
-
-1. On the top bar, select **Menu > Projects** and find your project.
-1. On the left sidebar, select **Settings > Repository**.
-1. Expand **Push rules**.
-1. Select **Prevent pushing secret files**.
-1. Select **Save push rules**.
-
-## Prohibited file names
-
-> Moved to GitLab Premium in 13.9.
-
-Each filename contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension.
-
-The following examples make use of regex string boundary characters which match the beginning of a string (`^`), and the end (`$`). They also include instances where either the directory path or the filename can include `.` or `/`. Both of these special regex characters have to be escaped with a backslash `\\` to be used as normal characters in a match condition.
-
-Example: prevent pushing any `.exe` files to any location in the repository. This is an example of a partial match, which can match any filename that contains `.exe` at the end:
-
-```plaintext
-\.exe$
-```
-
-Example: prevent a specific configuration file in the repository root from being pushed:
-
-```plaintext
-^config\.yml$
-```
-
-Example: prevent a specific configuration file in a known directory from being pushed:
-
-```plaintext
-^directory-name\/config\.yml$
-```
-
-Example: prevent the specific file named `install.exe` from being pushed to any
-location in the repository. The parenthesized expression `(^|\/)` matches either
-a file following a directory separator or a file in the root directory of the repository:
-
-```plaintext
-(^|\/)install\.exe$
-```
-
-Example: combining all of the above in a single expression. The preceding expressions rely
-on the end-of-string character `$`. We can move that part of each expression to the
-end of the grouped collection of match conditions where it is appended to all matches:
-
-```plaintext
-(\.exe|^config\.yml|^directory-name\/config\.yml|(^|\/)install\.exe)$
-```
-
-<!-- ## 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. -->
+<!-- This redirect file can be deleted after <2022-05-10>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 539908cd7bc..30cd0f8f511 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -828,6 +828,7 @@ For installations from source:
The `CRON=1` environment setting directs the backup script to hide all progress
output if there aren't any errors. This is recommended to reduce cron spam.
+When troubleshooting backup problems, however, replace `CRON=1` with `--trace` to log verbosely.
### Limit backup lifetime for local files (prune old backups)
@@ -943,7 +944,7 @@ First ensure your backup tar file is in the backup directory described in the
```shell
sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
-sudo chown git.git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar
+sudo chown git:git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar
```
Stop the processes that are connected to the database. Leave the rest of GitLab
@@ -965,6 +966,7 @@ sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce
```
Users of GitLab 12.1 and earlier should use the command `gitlab-rake gitlab:backup:restore` instead.
+Some [known non-blocking error messages may appear](#restoring-database-backup-using-omnibus-packages-outputs-warnings).
WARNING:
`gitlab-rake gitlab:backup:restore` doesn't set the correct file system
diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md
index f014b82cca1..cdc95c1f3cc 100644
--- a/doc/raketasks/generate_sample_prometheus_data.md
+++ b/doc/raketasks/generate_sample_prometheus_data.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/security/asset_proxy.md b/doc/security/asset_proxy.md
index 45c1c71158a..e4849b1b658 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 1abb0c9e918..8288f7f6a74 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/index.md b/doc/security/index.md
index ab554e9135f..da3fa761f3f 100644
--- a/doc/security/index.md
+++ b/doc/security/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
@@ -30,3 +30,5 @@ type: index
## Securing your GitLab installation
Consider access control features like [Sign up restrictions](../user/admin_area/settings/sign_up_restrictions.md) and [Authentication options](../topics/authentication/) to harden your GitLab instance and minimize the risk of unwanted user account creation.
+
+Self-hosting GitLab customers and administrators are responsible for the security of their underlying hosts, and for keeping GitLab itself up to date. It is important to [regularly patch GitLab](../policy/maintenance.md), patch your operating system and its software, and harden your hosts in accordance with vendor guidance.
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 07b5a688671..0d55881c147 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md
index 1cfff358c9d..04c3a5c99e1 100644
--- a/doc/security/password_length_limits.md
+++ b/doc/security/password_length_limits.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
diff --git a/doc/security/password_storage.md b/doc/security/password_storage.md
index 6b71933b1ae..b4c2e27c952 100644
--- a/doc/security/password_storage.md
+++ b/doc/security/password_storage.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/passwords_for_integrated_authentication_methods.md b/doc/security/passwords_for_integrated_authentication_methods.md
index 7281b310a30..d4eb16c07e7 100644
--- a/doc/security/passwords_for_integrated_authentication_methods.md
+++ b/doc/security/passwords_for_integrated_authentication_methods.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/project_import_decompressed_archive_size_limits.md b/doc/security/project_import_decompressed_archive_size_limits.md
index 9727ba1c5f0..5082d917748 100644
--- a/doc/security/project_import_decompressed_archive_size_limits.md
+++ b/doc/security/project_import_decompressed_archive_size_limits.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index 14fc526ca7e..a9b066631e7 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -41,6 +41,7 @@ You can set these rate limits in the Admin Area of your instance:
- [Git LFS rate limits](../user/admin_area/settings/git_lfs_rate_limits.md)
- [Files API rate limits](../user/admin_area/settings/files_api_rate_limits.md)
- [Deprecated API rate limits](../user/admin_area/settings/deprecated_api_rate_limits.md)
+- [GitLab Pages rate limits](../administration/pages/index.md#rate-limits)
You can set these rate limits using the Rails console:
@@ -89,7 +90,7 @@ The **rate limit** is 5 requests per minute per user.
### Users sign up
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77835) in GitLab 14.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339151) in GitLab 14.7.
There is a rate limit per IP address on the `/users/sign_up` endpoint. This is to mitigate attempts to misuse the endpoint. For example, to mass
discover usernames or email addresses in use.
@@ -98,19 +99,19 @@ The **rate limit** is 20 calls per minute per IP address.
### Update username
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77221) in GitLab 14.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339152) in GitLab 14.7.
-There is a rate limit on the update username action. This is enforced to mitigate misuse of the feature. For example, to mass discover
+There is a rate limit on how frequently a username can be changed. This is enforced to mitigate misuse of the feature. For example, to mass discover
which usernames are in use.
The **rate limit** is 10 calls per minute per signed-in user.
### Username exists
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77119) in GitLab 14.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29040) in GitLab 14.7.
-There is a rate limit for the internal endpoint `/users/:username/exists`, used by registration to perform a client-side validation for
-uniqueness of the chosen username. This is to mitigate the risk of misuses, such as mass discovery of usernames in use.
+There is a rate limit for the internal endpoint `/users/:username/exists`, used upon sign up to check if a chosen username has already been taken.
+This is to mitigate the risk of misuses, such as mass discovery of usernames in use.
The **rate limit** is 20 calls per minute per IP address.
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index f67b1934dc5..1940c5be73a 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index a7d852e2754..2e4a737f9aa 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -13,9 +13,9 @@ NIST). Some organizations deploying GitLab need to enforce minimum key
strength, either to satisfy internal security policy or for regulatory
compliance.
-Similarly, certain standards groups recommend using RSA, ECDSA, or ED25519 over
-the older DSA, and administrators may need to limit the allowed SSH key
-algorithms.
+Similarly, certain standards groups recommend using RSA, ECDSA, ED25519,
+ECDSA_SK, or ED25519_SK over 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:
@@ -45,6 +45,8 @@ By default, the GitLab.com and self-managed settings for the
- DSA SSH keys are forbidden ([since GitLab 11.0](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys)).
- ECDSA SSH keys are allowed.
- ED25519 SSH keys are allowed.
+- ECDSA_SK SSH keys are allowed (GitLab 14.8 and later).
+- ED25519_SK SSH keys are allowed (GitLab 14.8 and later).
<!-- ## Troubleshooting
diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md
index 578bb03563f..a2119c86268 100644
--- a/doc/security/token_overview.md
+++ b/doc/security/token_overview.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -44,8 +44,21 @@ are scoped to a project. As with [Personal access tokens](#personal-access-token
- The GitLab registry.
You can limit the scope and expiration date of project access tokens. When you
-create a project access token, GitLab creates a [project bot user](../user/project/settings/project_access_tokens.md#project-bot-users). Project
-bot users are service accounts and do not count as licensed seats.
+create a project access token, GitLab creates a [bot user for projects](../user/project/settings/project_access_tokens.md#bot-users-for-projects).
+Bot users for projects are service accounts and do not count as licensed seats.
+
+## Group access tokens
+
+[Group access tokens](../user/group/settings/group_access_tokens.md#group-access-tokens)
+are scoped to a group. As with [Personal access tokens](#personal-access-tokens), you can use them to authenticate with:
+
+- The GitLab API.
+- GitLab repositories.
+- The GitLab registry.
+
+You can limit the scope and expiration date of group access tokens. When you
+create a group access token, GitLab creates a [bot user for groups](../user/group/settings/group_access_tokens.md#bot-users-for-groups).
+Bot users for groups are service accounts and do not count as licensed seats.
## Deploy tokens
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index b83d81722fa..e8bb627ccbd 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -1,7 +1,7 @@
---
type: howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -116,8 +116,10 @@ reactivate 2FA from scratch if they want to use it again.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-Two-factor authentication can be enforced for Git over SSH operations. The one-time password (OTP)
-verification can be done via a GitLab Shell command:
+Two-factor authentication can be enforced for Git over SSH operations. However, we recommend using
+[ED25519_SK](../ssh/index.md#ed25519_sk-ssh-keys) or [ECDSA_SK](../ssh/index.md#ecdsa_sk-ssh-keys) SSH keys instead.
+
+The one-time password (OTP) verification can be done using a command:
```shell
ssh git@<hostname> 2fa_verify
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index 057d4e87efa..f2ad6696b9a 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index 8baddaf1383..54920b15362 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -1,7 +1,7 @@
---
type: howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/security/user_file_uploads.md b/doc/security/user_file_uploads.md
index 734a4cde7e8..e8b0c08e240 100644
--- a/doc/security/user_file_uploads.md
+++ b/doc/security/user_file_uploads.md
@@ -1,12 +1,14 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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 File Uploads **(FREE)**
+> - In GitLab 14.8 and later, [authorization checks are enforced](https://gitlab.com/gitlab-org/gitlab/-/issues/26781) on media uploads. This change is being [rolled out incrementally](https://gitlab.com/gitlab-org/gitlab/-/issues/352291) on GitLab.com in 14.9.
+
Images that are attached to issues, merge requests, or comments
do not require authentication to be viewed if they are accessed directly by URL.
This direct URL contains a random 32-character ID that prevents unauthorized
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index 621e6d595bf..07b35ccebe8 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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, reference, howto
---
diff --git a/doc/ssh/index.md b/doc/ssh/index.md
index 6196ee5465b..35ca9a23179 100644
--- a/doc/ssh/index.md
+++ b/doc/ssh/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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, reference
---
@@ -28,6 +28,8 @@ To view the version of SSH installed on your system, run `ssh -V`.
To communicate with GitLab, you can use the following SSH key types:
- [ED25519](#ed25519-ssh-keys)
+- [ED25519_SK](#ed25519_sk-ssh-keys) (Available in GitLab 14.8 and later.)
+- [ECDSA_SK](#ecdsa_sk-ssh-keys) (Available in GitLab 14.8 and later.)
- [RSA](#rsa-ssh-keys)
- DSA ([Deprecated](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) in GitLab 11.0.)
- ECDSA (As noted in [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa), the security issues related to DSA also apply to ECDSA.)
@@ -42,6 +44,20 @@ suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and perf
OpenSSH 6.5 introduced ED25519 SSH keys in 2014 and they should be available on most
operating systems.
+### ED25519_SK SSH keys
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78934) in GitLab 14.8.
+
+To use ED25519_SK SSH keys on GitLab, your local client and GitLab server
+must have [OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) or later installed.
+
+### ECDSA_SK SSH keys
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78934) in GitLab 14.8.
+
+To use ECDSA_SK SSH keys on GitLab, your local client and GitLab server
+must have [OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) or later installed.
+
### RSA SSH keys
Available documentation suggests that ED25519 is more secure than RSA.
@@ -64,6 +80,8 @@ Before you create a key pair, see if a key pair already exists.
| Algorithm | Public key | Private key |
| --------- | ---------- | ----------- |
| ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
+ | ED25519_SK | `id_ed25519_sk.pub` | `id_ed25519_sk` |
+ | ECDSA_SK | `id_ecdsa_sk.pub` | `id_ecdsa_sk` |
| RSA (at least 2048-bit key size) | `id_rsa.pub` | `id_rsa` |
| DSA (deprecated) | `id_dsa.pub` | `id_dsa` |
| ECDSA | `id_ecdsa.pub` | `id_ecdsa` |
@@ -177,6 +195,67 @@ OpenSSH format.
ssh-keygen -o -t rsa -b 4096 -C "<comment>"
```
+## Generate an SSH key pair for a FIDO/U2F hardware security key
+
+To generate ED25519_SK or ECDSA_SK SSH keys, you must use OpenSSH 8.2 or later.
+
+1. Insert a hardware security key into your computer.
+1. Open a terminal.
+1. Type `ssh-keygen -t` followed by the key type and an optional comment.
+ This comment is included in the `.pub` file that's created.
+ You may want to use an email address for the comment.
+
+ For example, for ED25519_SK:
+
+ ```shell
+ ssh-keygen -t ed25519-sk -C "<comment>"
+ ```
+
+ For ECDSA_SK:
+
+ ```shell
+ ssh-keygen -t ecdsa-sk -C "<comment>"
+ ```
+
+ If your security key supports FIDO2 resident keys, you can enable this when
+ creating your SSH key:
+
+ ```shell
+ ssh-keygen -t ed25519-sk -O resident -C "<comment>"
+ ```
+
+ `-O resident` indicates that the key should be stored on the FIDO authenticator itself.
+ Resident key is easier to import to a new computer because it can be loaded directly
+ from the security key by [`ssh-add -K`](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/ssh-add.1#K)
+ or [`ssh-keygen -K`](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/ssh-keygen#K).
+
+1. Select Enter. Output similar to the following is displayed:
+
+ ```plaintext
+ Generating public/private ed25519-sk key pair.
+ You may need to touch your authenticator to authorize key generation.
+ ```
+
+1. Touch the button on the hardware security key.
+
+1. Accept the suggested filename and directory:
+
+ ```plaintext
+ Enter file in which to save the key (/home/user/.ssh/id_ed25519_sk):
+ ```
+
+1. Specify a [passphrase](https://www.ssh.com/academy/ssh/passphrase):
+
+ ```plaintext
+ Enter passphrase (empty for no passphrase):
+ Enter same passphrase again:
+ ```
+
+1. A confirmation is displayed, including information about where your files are stored.
+
+A public and private key are generated.
+[Add the public SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account).
+
## Add an SSH key to your GitLab account
To use SSH with GitLab, copy your public key to your GitLab account.
@@ -210,7 +289,8 @@ To use SSH with GitLab, copy your public key to your GitLab account.
1. On the left sidebar, select **SSH Keys**.
1. In the **Key** box, paste the contents of your public key.
If you manually copied the key, make sure you copy the entire key,
- which starts with `ssh-ed25519` or `ssh-rsa`, and may end with a comment.
+ which starts with `ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`,
+ `ssh-ed25519`, `sk-ecdsa-sha2-nistp256@openssh.com`, or `sk-ssh-ed25519@openssh.com`, and may end with a comment.
1. In the **Title** box, type a description, like `Work Laptop` or
`Home Workstation`.
1. Optional. In the **Expires at** box, select an expiration date. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36243) in GitLab 12.9.)
@@ -219,7 +299,7 @@ To use SSH with GitLab, copy your public key to your GitLab account.
you from using the key. Administrators can view expiration dates and use them for
guidance when [deleting keys](../user/admin_area/credentials_inventory.md#delete-a-users-ssh-key).
- GitLab 14.0 and later, the expiration date is enforced. Administrators can
- [allow expired keys to be used](../user/admin_area/settings/account_and_limit_settings.md#allow-expired-ssh-keys-to-be-used).
+ [allow expired keys to be used](../user/admin_area/settings/account_and_limit_settings.md#allow-expired-ssh-keys-to-be-used-deprecated).
- GitLab checks all SSH keys at 02:00 AM UTC every day. It emails an expiration notice for all SSH keys that expire on the current date. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.11.)
- GitLab checks all SSH keys at 01:00 AM UTC every day. It emails an expiration notice for all SSH keys that are scheduled to expire seven days from now. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.11.)
1. Select **Add key**.
@@ -318,7 +398,8 @@ on the files make them readable to you but not accessible to others.
## Configure two-factor authentication (2FA)
You can set up two-factor authentication (2FA) for
-[Git over SSH](../security/two_factor_authentication.md#2fa-for-git-over-ssh-operations).
+[Git over SSH](../security/two_factor_authentication.md#2fa-for-git-over-ssh-operations). We recommend using
+[ED25519_SK](#ed25519_sk-ssh-keys) or [ECDSA_SK](#ecdsa_sk-ssh-keys) SSH keys.
## Use EGit on Eclipse
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index 2c66d32f669..7ca3a3ffade 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -17,9 +17,7 @@ the tiers are no longer mentioned in GitLab documentation:
- [Activate GitLab EE with a license](../user/admin_area/license.md)
- [Add a help message to the sign-in page](../user/admin_area/settings/help_page.md#add-a-help-message-to-the-sign-in-page)
-- [Burndown and burnup charts](../user/project/milestones/burndown_and_burnup_charts.md),
- including [per-project charts](../user/project/milestones/index.md#project-burndown-charts) and
- [per-group charts](../user/project/milestones/index.md#group-burndown-charts)
+- [Burndown and burnup charts](../user/project/milestones/burndown_and_burnup_charts.md) in the [Milestone View](../user/project/milestones/index.md#burndown-charts),
- [Code owners](../user/project/code_owners.md)
- Description templates:
- [Setting a default template for merge requests and issues](../user/project/description_templates.md#set-a-default-template-for-merge-requests-and-issues)
@@ -100,7 +98,7 @@ the tiers are no longer mentioned in GitLab documentation:
- Runners:
- Run pipelines in the parent project [for merge requests from a forked project](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project)
- [Shared runners CI/CD minutes](../ci/pipelines/cicd_minutes.md)
-- [Push rules](../push_rules/push_rules.md)
+- [Push rules](../user/project/repository/push_rules.md)
- SAML for self-managed GitLab instance:
- [Administrator groups](../integration/saml.md#administrator-groups)
- [Auditor groups](../integration/saml.md#auditor-groups)
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index b72fad02b3d..c94d90f61b8 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -14,7 +14,7 @@ You don't need to install anything to use GitLab SaaS, you only need to
- [A subscription](https://about.gitlab.com/pricing/).
- [The number of seats you want](#how-seat-usage-is-determined).
-The subscription determines which features are available for your private projects. Public projects automatically get **Ultimate** tier features.
+The subscription determines which features are available for your private projects. Organizations with public open source projects can actively apply to our [GitLab for Open Source Program](https://about.gitlab.com/solutions/open-source/join/).
Qualifying open source projects also get 50,000 CI/CD minutes and free access to the **Ultimate** tier
through the [GitLab for Open Source program](https://about.gitlab.com/solutions/open-source/).
@@ -44,7 +44,7 @@ To subscribe to GitLab SaaS:
Prerequisite:
-- You must have the Owner [role](../../user/permissions.md) for the group.
+- You must have the Owner role for the group.
To see the status of your GitLab SaaS subscription:
@@ -79,10 +79,12 @@ Every user is included in seat usage, with the following exceptions:
- Users who are pending approval.
- Members with the Guest role on an Ultimate subscription.
-- GitLab-created service accounts: `Ghost User` and bots
- ([`Support Bot`](../../user/project/service_desk.md#support-bot-user),
- [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and
- so on.)
+- GitLab-created service accounts:
+ - [Ghost User](../../user/profile/account/delete_account.md#associated-records).
+ - Bots such as:
+ - [Support Bot](../../user/project/service_desk.md#support-bot-user).
+ - [Bot users for projects](../../user/project/settings/project_access_tokens.md#bot-users-for-projects).
+ - [Bot users for groups](../../user/group/settings/group_access_tokens.md#bot-users-for-groups).
Seat usage is reviewed [quarterly or annually](../quarterly_reconciliation.md).
@@ -254,7 +256,7 @@ expiration date without a gap in available service. An invoice is
generated for the renewal and available for viewing or download on the
[View invoices](https://customers.gitlab.com/receipts) page.
-#### Enable automatic renewal
+#### Enable or disable automatic renewal
To view or change automatic subscription renewal (at the same tier as the
previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
@@ -290,21 +292,28 @@ for more information.
### Purchase additional CI/CD minutes
You can [purchase additional minutes](../../ci/pipelines/cicd_minutes.md#purchase-additional-cicd-minutes)
-for your personal or group namespace.
+for your personal or group namespace. CI/CD minutes are a **one-time purchase**, so they do not renew.
-## Storage subscription
+## Add-on subscription for additional Storage and Transfer
+
+NOTE:
+Free namespaces are subject to a 5GB storage and 10GB transfer [soft limit](https://about.gitlab.com/pricing). Once all storage is available to view in the usage quota workflow, GitLab will automatically enforce the namespace storage limit and the project limit will be removed. This change will be announced separately. The storage and transfer add-on can be purchased to increase the limits.
Projects have a free storage quota of 10 GB. To exceed this quota you must first [purchase one or
-more storage subscription units](#purchase-more-storage). Each unit provides 10 GB of additional
+more storage subscription units](#purchase-more-storage-and-transfer). Each unit provides 10 GB of additional
storage per namespace. A storage subscription is renewed annually. For more details, see
[Usage Quotas](../../user/usage_quotas.md).
When the amount of purchased storage reaches zero, all projects over the free storage quota are
locked. Projects can only be unlocked by purchasing more storage subscription units.
-### Purchase more storage
+### Purchase more storage and transfer
+
+You can purchase a storage subscription for your personal or group namespace.
-You can purchase storage for your personal or group namespace.
+NOTE:
+Storage subscriptions **[renew automatically](#automatic-renewal) each year**.
+You can [cancel the subscription](#enable-or-disable-automatic-renewal) to disable the automatic renewal.
#### For your personal namespace
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 4e4c0309c3d..3f9a1898505 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -150,11 +150,11 @@ To change the namespace linked to a subscription:
1. Navigate to the **Manage Purchases** page.
1. Select **Change linked namespace**.
1. Select the desired group from the **This subscription is for** dropdown. For a group to appear
- here, you must have the Owner [role](../user/permissions.md)
+ here, you must have the Owner role
for that group.
1. Select **Proceed to checkout**.
-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.
+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](gitlab_com/index.md#view-seat-usage) exceeds the number of seats in your subscription, your account is charged for the additional users and you need to pay for the overage before you can change the linked namespace.
Only one namespace can be linked to a subscription.
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 5ac2c5a5037..cb9db3673ac 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -65,10 +65,12 @@ billable user, with the following exceptions:
- Users who are [pending approval](../../user/admin_area/moderate_users.md#users-pending-approval).
- Members with the Guest role on an Ultimate subscription.
- Users without project or group memberships on an Ultimate subscription.
-- GitLab-created service accounts: `Ghost User` and bots
- ([`Support Bot`](../../user/project/service_desk.md#support-bot-user),
- [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and
- so on.)
+- GitLab-created service accounts:
+ - [Ghost User](../../user/profile/account/delete_account.md#associated-records).
+ - Bots such as:
+ - [Support Bot](../../user/project/service_desk.md#support-bot-user).
+ - [Bot users for projects](../../user/project/settings/project_access_tokens.md#bot-users-for-projects).
+ - [Bot users for groups](../../user/group/settings/group_access_tokens.md#bot-users-for-groups).
**Billable users** as reported in the `/admin` section is updated once per day.
@@ -307,6 +309,11 @@ The **License Usage** CSV includes the following details:
- Date the count was recorded
- Active user count
+NOTES:
+
+- All timestamps are displayed in UTC.
+- A custom format is used for [dates](https://gitlab.com/gitlab-org/gitlab/blob/3be39f19ac3412c089be28553e6f91b681e5d739/config/initializers/date_time_formats.rb#L7) and [times](https://gitlab.com/gitlab-org/gitlab/blob/3be39f19ac3412c089be28553e6f91b681e5d739/config/initializers/date_time_formats.rb#L13) in CSV files.
+
## Renew your subscription
To renew your subscription,
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index 44429754747..71d7e7f1426 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -79,8 +79,12 @@ X-Gitlab-Event: System Hook
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "project_create",
"name": "StoreCloud",
- "owner_email": "johnsmith@gmail.com",
+ "owner_email": "johnsmith@example.com",
"owner_name": "John Smith",
+ "owners": [{
+ "name": "John",
+ "email": "user1@example.com"
+ }],
"path": "storecloud",
"path_with_namespace": "jsmith/storecloud",
"project_id": 74,
@@ -96,8 +100,12 @@ X-Gitlab-Event: System Hook
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "project_destroy",
"name": "Underscore",
- "owner_email": "johnsmith@gmail.com",
+ "owner_email": "johnsmith@example.com",
"owner_name": "John Smith",
+ "owners": [{
+ "name": "John",
+ "email": "user1@example.com"
+ }],
"path": "underscore",
"path_with_namespace": "jsmith/underscore",
"project_id": 73,
@@ -117,7 +125,11 @@ X-Gitlab-Event: System Hook
"path_with_namespace": "jsmith/underscore",
"project_id": 73,
"owner_name": "John Smith",
- "owner_email": "johnsmith@gmail.com",
+ "owner_email": "johnsmith@example.com",
+ "owners": [{
+ "name": "John",
+ "email": "user1@example.com"
+ }],
"project_visibility": "internal",
"old_path_with_namespace": "jsmith/overscore"
}
@@ -138,7 +150,11 @@ Please refer to `group_rename` and `user_rename` for that case.
"path_with_namespace": "scores/underscore",
"project_id": 73,
"owner_name": "John Smith",
- "owner_email": "johnsmith@gmail.com",
+ "owner_email": "johnsmith@example.com",
+ "owners": [{
+ "name": "John",
+ "email": "user1@example.com"
+ }],
"project_visibility": "internal",
"old_path_with_namespace": "jsmith/overscore"
}
@@ -152,8 +168,12 @@ Please refer to `group_rename` and `user_rename` for that case.
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "project_update",
"name": "StoreCloud",
- "owner_email": "johnsmith@gmail.com",
+ "owner_email": "johnsmith@example.com",
"owner_name": "John Smith",
+ "owners": [{
+ "name": "John",
+ "email": "user1@example.com"
+ }],
"path": "storecloud",
"path_with_namespace": "jsmith/storecloud",
"project_id": 74,
@@ -173,7 +193,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"project_name": "StoreCloud",
"project_path": "storecloud",
"project_path_with_namespace": "jsmith/storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41,
@@ -193,7 +213,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"project_name": "StoreCloud",
"project_path": "storecloud",
"project_path_with_namespace": "jsmith/storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41,
@@ -213,7 +233,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"project_name": "StoreCloud",
"project_path": "storecloud",
"project_path_with_namespace": "jsmith/storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41,
@@ -360,7 +380,7 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"group_id": 78,
"group_name": "StoreCloud",
"group_path": "storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41
@@ -378,7 +398,7 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"group_id": 78,
"group_name": "StoreCloud",
"group_path": "storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41
@@ -396,7 +416,7 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"group_id": 78,
"group_name": "StoreCloud",
"group_path": "storecloud",
- "user_email": "johnsmith@gmail.com",
+ "user_email": "johnsmith@example.com",
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41
diff --git a/doc/tools/email.md b/doc/tools/email.md
index 0429b9b952e..0a3e37719a4 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -26,7 +26,7 @@ For information about email notifications originating from GitLab, read
1. On the left sidebar, select **Overview > Users**.
1. Select **Send email to users**.
- ![admin users](email1.png)
+ ![administrators](email1.png)
1. Compose an email and choose where to send it (all users or users of a
chosen group or project). The email body only supports plain text messages.
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 2a301e6ff5b..9ab6235164a 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 177e10b99b9..089f9f8e7cc 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -190,6 +190,9 @@ You can override the default values in the `values.yaml` file in the
`HELM_UPGRADE_VALUES_FILE` [CI/CD variable](#cicd-variables) with
the path and name.
+Some values can not be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
+[build and deployment](#build-and-deployment) CI/CD variable. Follow [this issue](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/31) for more information.
+
NOTE:
For GitLab 12.5 and earlier, use the `HELM_UPGRADE_EXTRA_ARGS` variable
to override the default chart values by setting `HELM_UPGRADE_EXTRA_ARGS` to `--values <my-values.yaml>`.
@@ -433,7 +436,7 @@ applications.
| `KUBE_NAMESPACE` | The namespace used for deployments. When using certificate-based clusters, [this value should not be overwritten directly](../../user/project/clusters/deploy_to_cluster.md#custom-namespace). |
| `KUBECONFIG` | The kubeconfig to use for deployments. User-provided values take priority over GitLab-provided values. |
| `PRODUCTION_REPLICAS` | Number of replicas to deploy in the production environment. Takes precedence over `REPLICAS` and defaults to 1. For zero downtime upgrades, set to 2 or greater. |
-| `REPLICAS` | Number of replicas to deploy. Defaults to 1. |
+| `REPLICAS` | Number of replicas to deploy. Defaults to 1. Change this variable instead of [modifying](#customize-values-for-helm-chart) `replicaCount`. |
| `ROLLOUT_RESOURCE_TYPE` | Allows specification of the resource type being deployed when using a custom Helm chart. Default value is `deployment`. |
| `ROLLOUT_STATUS_DISABLED` | From GitLab 12.0, used to disable rollout status check because it does not support all resource types, for example, `cronjob`. |
| `STAGING_ENABLED` | Used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
@@ -478,6 +481,7 @@ The following table lists variables used to disable jobs.
| `brakeman-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `bundler-audit-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `canary` | `CANARY_ENABLED` | | This manual job is created if the variable is present. |
+| `cluster_image_scanning` | `CLUSTER_IMAGE_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `code_intelligence` | `CODE_INTELLIGENCE_DISABLED` | From GitLab 13.6 | If the variable is present, the job isn't created. |
| `code_quality` | `CODE_QUALITY_DISABLED` | | If the variable is present, the job isn't created. |
| `container_scanning` | `CONTAINER_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md
index de83ec8b51b..affd746f66f 100644
--- a/doc/topics/cron/index.md
+++ b/doc/topics/cron/index.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Cron syntax is used to schedule when jobs should run.
You may need to use a cron syntax string to
-create a [pipeline schedule](../../api/pipeline_schedules.md#create-a-new-pipeline-schedule),
+create a [pipeline schedule](../../ci/pipelines/schedules.md),
or to prevent unintentional releases by setting a
[deploy freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze).
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index a94caf2bf33..977f51a7211 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -31,7 +31,7 @@ Documentation for GitLab instance administrators is under [LFS administration do
- Git LFS is supported in GitLab starting with version 8.2
- Git LFS must be enabled under project settings
-- [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up
+- [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up must be installed
## Known limitations
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index 2786368a9d7..32e3b6e2f72 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -46,7 +46,7 @@ Before beginning, make sure:
To follow this tutorial, you need:
-- The [Maintainer role](../../../user/permissions.md) for the existing Git repository
+- The Maintainer role 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)
diff --git a/doc/topics/git/merge_conflicts.md b/doc/topics/git/merge_conflicts.md
index bf69190030c..47276ccb0b2 100644
--- a/doc/topics/git/merge_conflicts.md
+++ b/doc/topics/git/merge_conflicts.md
@@ -23,7 +23,7 @@ comments: false
1. Fix conflicts on the `conflicts.rb` file.
1. Stage the file and continue rebasing.
1. Force push the changes.
-1. Finally continue with the Merge Request.
+1. Finally continue with the merge request.
```shell
git checkout -b conflicts_branch
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 7675bba8d83..3bca33b32b7 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -71,7 +71,7 @@ For example, many projects do releases but don't need to do hotfixes.
## GitHub flow as a simpler alternative
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 `main` branch:
+[GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow) has only feature branches and a `main` branch:
```mermaid
graph TD
@@ -221,7 +221,7 @@ If the assigned person does not feel comfortable, they can request more changes
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).
+Maintainer role.
After you merge a feature branch, you should remove it from the source control software.
In GitLab, you can do this when merging.
@@ -341,7 +341,7 @@ However, as discussed in [the section about rebasing](#squashing-commits-with-re
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).
+Atlassian has [a more thorough explanation of the tradeoffs between merging and rebasing](https://www.atlassian.com/blog/git/git-team-workflows-merge-or-rebase) on their blog.
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.
@@ -403,7 +403,7 @@ git commit -m 'Properly escape special characters in XML generation'
An example of a good commit message is: "Combine templates to reduce duplicate code in the user views."
The words "change," "improve," "fix," and "refactor" don't add much information to a commit message.
-For more information about formatting commit messages, please see this excellent [blog post by Tim Pope](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
+For more information, please see Tim Pope's excellent [note about formatting commit messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
To add more context to a commit message, consider adding information regarding the
origin of the change. For example, the URL of a GitLab issue, or a Jira issue number,
diff --git a/doc/topics/release_your_application.md b/doc/topics/release_your_application.md
index 3a0080fe21c..64decba33ad 100644
--- a/doc/topics/release_your_application.md
+++ b/doc/topics/release_your_application.md
@@ -30,8 +30,8 @@ to Kubernetes clusters using the [GitLab Agent](../user/clusters/agent/install/i
#### GitOps deployments **(PREMIUM)**
-With the [GitLab Agent](../user/clusters/agent/install/index.md), you can perform pull-based
-deployments using Kubernetes manifests. This provides a scalable, secure, and cloud-native
+With the [GitLab Agent](../user/clusters/agent/install/index.md), you can perform [pull-based
+deployments of Kubernetes manifests](../user/clusters/agent/repository.md#synchronize-manifest-projects). This provides a scalable, secure, and cloud-native
approach to manage Kubernetes deployments.
#### Deploy to Kubernetes with the CI/CD Tunnel
@@ -63,4 +63,4 @@ Use GitLab [Releases](../user/project/releases/index.md) to plan, build, and del
### Feature flags
-Use [feature flags](../operations/feature_flags.md) to control and strategically roullout application deployments.
+Use [feature flags](../operations/feature_flags.md) to control and strategically rollout application deployments.
diff --git a/doc/tutorials/index.md b/doc/tutorials/index.md
index 1f866aeb889..ac05b9945db 100644
--- a/doc/tutorials/index.md
+++ b/doc/tutorials/index.md
@@ -4,7 +4,7 @@ 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
---
-# Get started with GitLab tutorials
+# Learn GitLab with tutorials
These tutorials can help you learn how to use GitLab.
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 7388f4baf83..2f5146b8161 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -38,7 +38,7 @@ For deprecation reviewers (Technical Writers only):
## 14.0
-### NFS for Git repository storage deprecated
+### NFS for Git repository storage
WARNING:
This feature will be changed or removed in 15.0
@@ -58,6 +58,18 @@ We encourage customers currently using NFS for Git repositories to plan their mi
**Planned removal milestone: 15.0 (2022-05-22)**
+### OAuth implicit grant
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The OAuth implicit grant authorization flow will be removed in our next major release, GitLab 15.0. Any applications that use OAuth implicit grant should switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
## 14.2
### Release CLI distributed as a generic package
@@ -84,7 +96,7 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push) are now deprecated and will be removed in GitLab 15.0.
+Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push-deprecated) are now deprecated and will be removed in GitLab 15.0.
These events have always been disabled by default and had to be manually enabled with a
feature flag. Enabling them can cause too many events to be generated which can
@@ -143,24 +155,28 @@ Note that we are not deprecating the Kerberos SPNEGO integration, only the old p
### Certificate-based integration with Kubernetes
WARNING:
-This feature will be changed or removed in 15.0
+This feature will be changed or removed in 15.6
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
[We are deprecating the certificate-based integration with Kubernetes](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
-The timeline of removal of the integration from the product is not yet planned and we will communicate
-more details as they emerge. The certificate-based integration will continue to receive security and
+The timeline of removal of the integration from the product is planned to happen in two steps, starting with milestone 15.0 and finishing in GitLab version 15.6.
+
+In 15.0, we plan to introduce a feature flag that will allow GitLab Self-Managed customers to keep the certificate-based integration enabled, it will be disabled by default. We plan to remove this feature flag together with the underlying code in GitLab version 15.6.
+The certificate-based integration will continue to receive security and
critical fixes, and features built on the integration will continue to work with supported Kubernetes
-versions. We will provide migration plans in a future iteration. See [the list of features affected by this deprecation](https://docs.gitlab.com/ee/user/infrastructure/clusters/#deprecated-features).
-For updates and details, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+versions until the final removal in 15.6.
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend the use of the
-[Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
+[Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
+We provide [migration plans](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) in the documentation.
-**Planned removal milestone: 15.0 (2022-05-22)**
+For updates and details around this deprecation, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+
+**Planned removal milestone: 15.6 (2022-11-22)**
-### Converting an instance (shared) runner to a project (specific) runner is deprecated
+### Converting an instance (shared) runner to a project (specific) runner
WARNING:
This feature will be changed or removed in 15.0
@@ -172,7 +188,7 @@ In GitLab 15.0, we will remove the feature that enables you to convert an instan
**Planned removal milestone: 15.0 (2022-05-22)**
-### Deprecate `Versions` on base `PackageType`
+### Known host required for GitLab Runner SSH executor
WARNING:
This feature will be changed or removed in 15.0
@@ -180,13 +196,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
+In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml` file. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.
-In milestone 15.0, we will completely remove `Version` from `PackageType`.
+In GitLab 15.0 and later, the default value for this configuration option will change from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Deprecate support for SLES 12 SP2
+### Must explicitly assign `AuthenticationType` for `[runners.cache.s3]`
WARNING:
This feature will be changed or removed in 15.0
@@ -194,11 +210,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
+In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
+
+Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Known host required for GitLab Runner SSH executor
+### Package pipelines in API payload is paginated
WARNING:
This feature will be changed or removed in 15.0
@@ -206,13 +224,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml` file. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.
+A request to the API for `/api/v4/projects/:id/packages` returns a paginated result of packages. Each package lists all of its pipelines in this response. This is a performance concern, as it's possible for a package to have hundreds or thousands of associated pipelines.
-In GitLab 15.0 and later, the default value for this configuration option will change from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.
+In milestone 15.0, we will remove the `pipelines` attribute from the API response.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Must explicitly assign `AuthenticationType` for `[runners.cache.s3]`
+### REST and GraphQL API Runner status will not return `paused`
WARNING:
This feature will be changed or removed in 15.0
@@ -220,13 +238,17 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
+The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 15.0.
-Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+A runner's status will only relate to runner contact status, such as:
+`online`, `offline`, or `not_connected`. Status `paused` or `active` will no longer appear.
+
+When checking if a runner is `paused`, API users are advised to check the boolean attribute
+`paused` to be `true` instead. When checking if a runner is `active`, check if `paused` is `false`.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Package pipelines in API payload is paginated
+### Support for SLES 12 SP2
WARNING:
This feature will be changed or removed in 15.0
@@ -234,13 +256,11 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-A request to the API for `/api/v4/projects/:id/packages` returns a paginated result of packages. Each package lists all of its pipelines in this response. This is a performance concern, as it's possible for a package to have hundreds or thousands of associated pipelines.
-
-In milestone 15.0, we will remove the `pipelines` attribute from the API response.
+Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
**Planned removal milestone: 15.0 (2022-05-22)**
-### REST API Runner will not contain `paused`
+### Update to the Container Registry group-level API
WARNING:
This feature will be changed or removed in 15.0
@@ -248,17 +268,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 15.0.
-
-A runner's status will only relate to runner contact status, such as:
-`online`, `offline`, or `not_connected`. Status `paused` or `active` will no longer appear.
+In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
-When checking if a runner is `paused`, API users are advised to check the boolean attribute
-`active` to be `false` instead. When checking if a runner is `active`, check if `active` is `true`.
+The `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Removal of `defaultMergeCommitMessageWithDescription` GraphQL API field
+### Value Stream Analytics filtering calculation change
WARNING:
This feature will be changed or removed in 15.0
@@ -266,11 +282,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
+We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
+
+If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Removal of `promote-db` command from `gitlab-ctl`
+### `Versions` on base `PackageType`
WARNING:
This feature will be changed or removed in 15.0
@@ -278,11 +296,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
+
+In milestone 15.0, we will completely remove `Version` from `PackageType`.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Removal of `promote-to-primary-node` command from `gitlab-ctl`
+### `defaultMergeCommitMessageWithDescription` GraphQL API field
WARNING:
This feature will be changed or removed in 15.0
@@ -290,11 +310,11 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Remove the `:dependency_proxy_for_private_groups` feature flag
+### `dependency_proxy_for_private_groups` feature flag
WARNING:
This feature will be changed or removed in 15.0
@@ -308,7 +328,7 @@ In milestone 15.0, we will remove the feature flag entirely. Moving forward, you
**Planned removal milestone: 15.0 (2022-05-22)**
-### Remove the `pipelines` field from the `version` field
+### `pipelines` field from the `version` field
WARNING:
This feature will be changed or removed in 15.0
@@ -325,7 +345,7 @@ To mitigate possible performance problems, we will remove the `versions` field's
**Planned removal milestone: 15.0 (2022-05-22)**
-### Update to the Container Registry group-level API
+### `promote-db` command from `gitlab-ctl`
WARNING:
This feature will be changed or removed in 15.0
@@ -333,13 +353,11 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
-
-The `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.
+In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Value Stream Analytics filtering calculation change
+### `promote-to-primary-node` command from `gitlab-ctl`
WARNING:
This feature will be changed or removed in 15.0
@@ -347,9 +365,7 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
-
-If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
+In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
**Planned removal milestone: 15.0 (2022-05-22)**
@@ -389,21 +405,7 @@ In GitLab 15.0 we are going to limit the number of characters in CI/CD job names
**Planned removal milestone: 15.0 (2022-05-22)**
-### Deprecate `pipelines` fields in the Package GraphQL types
-
-WARNING:
-This feature will be changed or removed in 15.0
-as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
-Before updating GitLab, review the details carefully to determine if you need to make any
-changes to your code, settings, or workflow.
-
-As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `pipelines` fields in all Package-related GraphQL types. As of GitLab 14.6, the `pipelines` field is deprecated in [`Package`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#package) and [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype) due to scalability and performance concerns.
-
-In milestone 15.0, we will completely remove `pipelines` from `Package` and `PackageDetailsType`. You can follow and contribute to work on a replacement in the epic [GitLab-#7214](https://gitlab.com/groups/gitlab-org/-/epics/7214).
-
-**Planned removal milestone: 15.0 (2022-05-22)**
-
-### Deprecate legacy approval status names from License Compliance API
+### Legacy approval status names from License Compliance API
WARNING:
This feature will be changed or removed in 15.0
@@ -417,7 +419,7 @@ If you are using our License Compliance API you should stop using the `approved`
**Planned removal milestone: 15.0 (2022-05-22)**
-### Deprecation of Runner status `not_connected` API value
+### Runner status `not_connected` API value
WARNING:
This feature will be changed or removed in 15.0
@@ -432,7 +434,7 @@ Runners that have never contacted the GitLab instance will also return `stale` i
**Planned removal milestone: 15.0 (2022-05-22)**
-### Deprecation of bundler-audit Dependency Scanning tool
+### `pipelines` fields in the Package GraphQL types
WARNING:
This feature will be changed or removed in 15.0
@@ -440,13 +442,13 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
-As of 14.6 bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
+As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `pipelines` fields in all Package-related GraphQL types. As of GitLab 14.6, the `pipelines` field is deprecated in [`Package`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#package) and [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype) due to scalability and performance concerns.
-If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.
+In milestone 15.0, we will completely remove `pipelines` from `Package` and `PackageDetailsType`. You can follow and contribute to work on a replacement in the epic [GitLab-#7214](https://gitlab.com/groups/gitlab-org/-/epics/7214).
**Planned removal milestone: 15.0 (2022-05-22)**
-### Remove `type` and `types` keyword in CI/CD configuration
+### `type` and `types` keyword in CI/CD configuration
WARNING:
This feature will be changed or removed in 15.0
@@ -472,6 +474,20 @@ which isn't being used in GitLab anymore.
**Planned removal milestone: 15.0 (2022-05-22)**
+### bundler-audit Dependency Scanning tool
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+As of 14.6 bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
+
+If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
## 14.7
### Container scanning schemas below 14.0.0
@@ -604,21 +620,6 @@ It is now considered deprecated, and will be removed in GitLab 15.0.
**Planned removal milestone: 15.0 (2022-05-22)**
-### Removal of Static Site Editor
-
-The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects.
-
-**Planned removal milestone: 15.0 (2022-05-22)**
-
-### Removal of `artifacts:report:cobertura` keyword
-
-Currently, test coverage visualizations in GitLab only support Cobertura reports. Starting 15.0, the
-`artifacts:report:cobertura` keyword will be replaced by
-[`artifacts:reports:coverage_report`](https://gitlab.com/gitlab-org/gitlab/-/issues/344533). Cobertura will be the
-only supported report file in 15.0, but this is the first step towards GitLab supporting other report types.
-
-**Planned removal milestone: 15.0 (2022-05-22)**
-
### SAST schemas below 14.0.0
[SAST report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/releases)
@@ -685,6 +686,12 @@ to serve the Sidekiq metrics, similar to the way Sidekiq will behave in 15.0.
**Planned removal milestone: 15.0 (2022-05-22)**
+### Static Site Editor
+
+The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
### Tracing in GitLab
WARNING:
@@ -697,14 +704,699 @@ Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distr
**Planned removal milestone: 15.0 (2022-05-22)**
+### `artifacts:report:cobertura` keyword
+
+Currently, test coverage visualizations in GitLab only support Cobertura reports. Starting 15.0, the
+`artifacts:report:cobertura` keyword will be replaced by
+[`artifacts:reports:coverage_report`](https://gitlab.com/gitlab-org/gitlab/-/issues/344533). Cobertura will be the
+only supported report file in 15.0, but this is the first step towards GitLab supporting other report types.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
### merged_by API field
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `merge_user` field (already present in GraphQL) which more correctly identifies who merged a merge request when performing actions (merge when pipeline succeeds, add to merge train) other than a simple merge.
**Planned removal milestone: 15.0 (2022-05-22)**
## 14.8
+### Changes to the `CI_JOB_JWT`
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The `CI_JOB_JWT` will be updated to support a wider variety of cloud providers. It will be changed to match [`CI_JOB_JWT_V2`](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html), but this change may not be backwards compatible for all users, including Hashicorp Vault users. To maintain the current behavior, users can switch to using `CI_JOB_JWT_V1`, or update their configuration in GitLab 15.0 to use the improved `CI_JOB_JWT`.
+
+**Planned removal milestone: 15.0 ()**
+
+### Configurable Gitaly `per_repository` election strategy
+
+Configuring the `per_repository` Gitaly election strategy is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352612).
+`per_repository` has been the only option since GitLab 14.0.
+
+This change is part of regular maintenance to keep our codebase clean.
+
+**Planned removal milestone: 14.9 (2022-03-22)**
+
+### Container Network and Host Security
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+All functionality related to GitLab's Container Network Security and Container Host Security categories is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to evaluate the following open source projects as potential solutions that can be installed and managed outside of GitLab: [AppArmor](https://gitlab.com/apparmor/apparmor), [Cilium](https://github.com/cilium/cilium), [Falco](https://github.com/falcosecurity/falco), [FluentD](https://github.com/fluent/fluentd), [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/). To integrate these technologies into GitLab, add the desired Helm charts into your copy of the [Cluster Management Project Template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Deploy these Helm charts in production by calling commands through the GitLab [Secure CI/CD Tunnel](https://docs.gitlab.com/ee/user/clusters/agent/repository.html#run-kubectl-commands-using-the-cicd-tunnel).
+
+As part of this change, the following specific capabilities within GitLab are now deprecated, and are scheduled for removal in GitLab 15.0:
+
+- The **Security & Compliance > Threat Monitoring** page.
+- The `Network Policy` security policy type, as found on the **Security & Compliance > Policies** page.
+- The ability to manage integrations with the following technologies through GitLab: AppArmor, Cilium, Falco, FluentD, and Pod Security Policies.
+- All APIs related to the above functionality.
+
+For additional context, or to provide feedback regarding this change, please reference our open [deprecation issue](https://gitlab.com/groups/gitlab-org/-/epics/7476).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Dependency Scanning Python 3.9 and 3.6 image deprecation
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+For those using Dependency Scanning for Python projects, we are deprecating the default `gemnasium-python:2` image which uses Python 3.6 as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).
+
+For users using Python 3.9 or 3.9-compatible projects, you should not need to take action and dependency scanning should begin to work in GitLab 15.0. If you wish to test the new container now please run a test pipeline in your project with this container (which will be removed in 15.0). Use the Python 3.9 image:
+
+```yaml
+gemnasium-python-dependency_scanning:
+ image:
+ name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
+```
+
+For users using Python 3.6, as of GitLab 15.0 you will no longer be able to use the default template for dependency scanning. You will need to switch to use the deprecated `gemnasium-python:2` analyzer image. If you are impacted by this please comment in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351503) so we can extend the removal if needed.
+
+For users using the 3.9 special exception image, you must instead use the default value and no longer override your container. To verify if you are using the 3.9 special exception image, check your `.gitlab-ci.yml` file for the following reference:
+
+```yaml
+gemnasium-python-dependency_scanning:
+ image:
+ name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
+```
+
+**Planned removal milestone: 15.0 (2021-05-22)**
+
+### Deprecate Geo Admin UI Routes
+
+In GitLab 13.0, we introduced new project and design replication details routes in the Geo Admin UI. These routes are `/admin/geo/replication/projects` and `/admin/geo/replication/designs`. We kept the legacy routes and redirected them to the new routes. In GitLab 15.0, we will remove support for the legacy routes `/admin/geo/projects` and `/admin/geo/designs`. Please update any bookmarks or scripts that may use the legacy routes.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Deprecate custom Geo:db:* Rake tasks
+
+In GitLab 14.8, we are [replacing the `geo:db:*` Rake tasks with built-in tasks](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77269/diffs) that are now possible after [switching the Geo tracking database to use Rails' 6 support of multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6458).
+The following `geo:db:*` tasks will be replaced with their corresponding `db:*:geo` tasks:
+
+- `geo:db:drop` -> `db:drop:geo`
+- `geo:db:create` -> `db:create:geo`
+- `geo:db:setup` -> `db:setup:geo`
+- `geo:db:migrate` -> `db:migrate:geo`
+- `geo:db:rollback` -> `db:rollback:geo`
+- `geo:db:version` -> `db:version:geo`
+- `geo:db:reset` -> `db:reset:geo`
+- `geo:db:seed` -> `db:seed:geo`
+- `geo:schema:load:geo` -> `db:schema:load:geo`
+- `geo:db:schema:dump` -> `db:schema:dump:geo`
+- `geo:db:migrate:up` -> `db:migrate:up:geo`
+- `geo:db:migrate:down` -> `db:migrate:down:geo`
+- `geo:db:migrate:redo` -> `db:migrate:redo:geo`
+- `geo:db:migrate:status` -> `db:migrate:status:geo`
+- `geo:db:test:prepare` -> `db:test:prepare:geo`
+- `geo:db:test:load` -> `db:test:load:geo`
+- `geo:db:test:purge` -> `db:test:purge:geo`
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Deprecate feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Deprecate legacy Gitaly configuration methods
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+Using environment variables `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configure Gitaly is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352609).
+These variables are being replaced with standard [`config.toml` Gitaly configuration](https://docs.gitlab.com/ee/administration/gitaly/reference.html).
+
+GitLab instances that use `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configure Gitaly should switch to configuring using
+`config.toml`.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Elasticsearch 6.8
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+Elasticsearch 6.8 is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
+Customers using Elasticsearch 6.8 need to upgrade their Elasticsearch version to 7.x prior to upgrading to GitLab 15.0.
+We recommend using the latest version of Elasticsearch 7 to benefit from all Elasticsearch improvements.
+
+Elasticsearch 6.8 is also incompatible with Amazon OpenSearch, which we [plan to support in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/327560).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### External status check API breaking changes
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The [external status check API](https://docs.gitlab.com/ee/api/status_checks.html) was originally implemented to
+support pass-by-default requests to mark a status check as passing. Pass-by-default requests are now deprecated.
+Specifically, the following are deprecated:
+
+- Requests that do not contain the `status` field.
+- Requests that have the `status` field set to `approved`.
+
+Beginning in GitLab 15.0, status checks will only be updated to a passing state if the `status` field is both present
+and set to `pass`. Requests that:
+
+- Do not contain the `status` field will be rejected with a `422` error. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338827).
+- Contain any value other than `pass` will cause the status check to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/339039).
+
+To align with this change, API calls to list external status checks will also return the value of `pass` rather than
+`approved` for status checks that have passed.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### GraphQL ID and GlobalID compatibility
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+We are removing a non-standard extension to our GraphQL processor, which we added for backwards compatibility. This extension modifies the validation of GraphQL queries, allowing the use of the `ID` type for arguments where it would normally be rejected.
+Some arguments originally had the type `ID`. These were changed to specific
+kinds of `ID`. This change may be a breaking change if you:
+
+- Use GraphQL.
+- Use the `ID` type for any argument in your query signatures.
+
+Some field arguments still have the `ID` type. These are typically for
+IID values, or namespace paths. An example is `Query.project(fullPath: ID!)`.
+
+For a list of affected and unaffected field arguments,
+see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352832).
+
+You can test if this change affects you by validating
+your queries locally, using schema data fetched from a GitLab server.
+You can do this by using the GraphQL explorer tool for the relevant GitLab
+instance. For example: `https://gitlab.com/-/graphql-explorer`.
+
+For example, the following query illustrates the breaking change:
+
+```graphql
+# a query using the deprecated type of Query.issue(id:)
+# WARNING: This will not work after GitLab 15.0
+query($id: ID!) {
+ deprecated: issue(id: $id) {
+ title, description
+ }
+}
+```
+
+The query above will not work after GitLab 15.0 is released, because the type
+of `Query.issue(id:)` is actually `IssueID!`.
+
+Instead, you should use one of the following two forms:
+
+```graphql
+# This will continue to work
+query($id: IssueID!) {
+ a: issue(id: $id) {
+ title, description
+ }
+ b: issue(id: "gid://gitlab/Issue/12345") {
+ title, description
+ }
+}
+```
+
+This query works now, and will continue to work after GitLab 15.0.
+You should convert any queries in the first form (using `ID` as a named type in the signature)
+to one of the other two forms (using the correct appropriate type in the signature, or using
+an inline argument expression).
+
+**Planned removal milestone: 15.0 (2022-04-22)**
+
+### OAuth tokens without expiration
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and earlier, OAuth access tokens
+had no expiration. In GitLab 15.0, an expiry will be automatically generated for any existing token that does not
+already have one.
+
+You should [opt in](https://docs.gitlab.com/ee/integration/oauth_provider.html#expiring-access-tokens) to expiring
+tokens before GitLab 15.0 is released:
+
+1. Edit the application.
+1. Select **Expire access tokens** to enable them. Tokens must be revoked or they don’t expire.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Optional enforcement of PAT expiration
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The feature to disable enforcement of PAT expiration is unusual from a security perspective.
+We have become concerned that this unusual feature could create unexpected behavior for users.
+Unexpected behavior in a security feature is inherently dangerous, so we have decided to remove this feature.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Optional enforcement of SSH expiration
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The feature to disable enforcement of SSH expiration is unusual from a security perspective.
+We have become concerned that this unusual feature could create unexpected behavior for users.
+Unexpected behavior in a security feature is inherently dangerous, so we have decided to remove this feature.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Out-of-the-box SAST support for Java 8
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The [GitLab SAST SpotBugs analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) scans [Java, Scala, Groovy, and Kotlin code](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) for security vulnerabilities.
+For technical reasons, the analyzer must first compile the code before scanning.
+Unless you use the [pre-compilation strategy](https://docs.gitlab.com/ee/user/application_security/sast/#pre-compilation), the analyzer attempts to automatically compile your project's code.
+
+In GitLab versions prior to 15.0, the analyzer image includes Java 8 and Java 11 runtimes to facilitate compilation.
+
+In GitLab 15.0, we will:
+
+- Remove Java 8 from the analyzer image to reduce the size of the image.
+- Add Java 17 to the analyzer image to make it easier to compile with Java 17.
+
+If you rely on Java 8 being present in the analyzer environment, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352549#breaking-change).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Querying Usage Trends via the `instanceStatisticsMeasurements` GraphQL node
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The `instanceStatisticsMeasurements` GraphQL node has been renamed to `usageTrendsMeasurements` in 13.10 and the old field name has been marked as deprecated. To fix the existing GraphQL queries, replace `instanceStatisticsMeasurements` with `usageTrendsMeasurements`.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### REST API Runner will not accept `status` filter values of `active` or `paused`
+
+WARNING:
+This feature will be changed or removed in 16.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The GitLab Runner REST endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
+
+A runner's status will only relate to runner contact status, such as: `online`, `offline`.
+Status values `paused` or `active` will no longer be accepted and will be replaced by the `paused` query parameter.
+
+When checking for paused runners, API users are advised to specify `paused=true` as the query parameter.
+When checking for active runners, specify `paused=false`.
+
+**Planned removal milestone: 16.0 (2023-04-22)**
+
+### REST API endpoint to list group runners no longer accepts `project_type` value for `type` argument
+
+WARNING:
+This feature will be changed or removed in 16.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The `GET /groups/:id/runners?type=project_type` endpoint will be removed in GitLab 16.0. The endpoint always returned an empty collection.
+
+**Planned removal milestone: 16.0 (2023-04-22)**
+
+### REST and GraphQL API Runner usage of `active` replaced by `paused`
+
+WARNING:
+This feature will be changed or removed in 16.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+Occurrences of the `active` identifier in the GitLab Runner REST and GraphQL API endpoints will be
+renamed to `paused` in GitLab 16.0, namely:
+
+- GraphQL API:
+ - the `CiRunner` property;
+ - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation;
+ - the `runners` and `Group.runners` queries.
+- REST API:
+ - endpoints taking or returning `active` properties, such as:
+ - `GET /runners`
+ - `GET /runners/all`
+ - `GET /runners/:id` / `PUT /runners/:id`
+ - `PUT --form "active=false" /runners/:runner_id`
+ - `GET /projects/:id/runners` / `POST /projects/:id/runners`
+ - `GET /groups/:id/runners`
+
+The 16.0 release of the GitLab Runner will start using the `paused` property when registering runners, and therefore
+will only be compatible with GitLab 16.0 and later. Until 16.0, GitLab will accept the deprecated `active` flag from
+existing runners.
+
+**Planned removal milestone: 16.0 (2023-04-22)**
+
+### Reminder: support for NFS repository storage
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+As [announced](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#nfs-for-git-repository-storage-deprecated) at the
+release of GitLab 14.0, technical support for NFS storage for Git repositories is being removed. Please see our official
+[Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for additional information.
+
+We encourage customers currently using NFS for Git repositories to plan their migration by reviewing our documentation on
+[migrating to Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/#migrating-to-gitaly-cluster).
+
+Gitaly Cluster offers tremendous benefits for our customers such as:
+
+- [Variable replication factors](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#configure-replication-factor)
+- [Strong consistency](https://docs.gitlab.com/ee/administration/gitaly/#strong-consistency)
+- [Distributed read capabilities](https://docs.gitlab.com/ee/administration/gitaly/#distributed-reads)
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Request profiling
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
+
+We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
+We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.
+It also depends on a few third-party gems that are not actively maintained anymore, have not been updated for the latest version of Ruby, or crash frequently when profiling heavy page loads.
+
+For more information, check the [summary section of the deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352488#deprecation-summary).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Required pipeline configurations in Premium tier
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The [required pipeline configuration](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#required-pipeline-configuration) feature is deprecated in GitLab 14.8 for Premium customers and is scheduled for removal in GitLab 15.0. This feature is not deprecated for GitLab Ultimate customers.
+
+This change to move the feature to GitLab's Ultimate tier is intended to help our features better align with our [pricing philosophy](https://about.gitlab.com/company/pricing/#three-tiers) as we see demand for this feature originating primarily from executives.
+
+This change will also help GitLab remain consistent in its tiering strategy with the other related Ultimate-tier features of:
+[Security policies](https://docs.gitlab.com/ee/user/application_security/policies/) and [compliance framework pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Retire-JS Dependency Scanning tool
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+As of 14.8 the retire.js job is being deprecated from Dependency Scanning. It will continue to be included in our CI/CD template while deprecated. We are removing retire.js from Dependency Scanning on May 22, 2022 in GitLab 15.0. JavaScript scanning functionality will not be affected as it is still being covered by Gemnasium.
+
+If you have explicitly excluded retire.js using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration related to the `retire-js-dependency_scanning` job you will want to switch to gemnasium-dependency_scanning before the removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference retire.js, or customized your template specifically for retire.js, you will not need to take action.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### SAST analyzer consolidation and CI/CD template changes
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+GitLab SAST uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/sast/analyzers/) to scan code for vulnerabilities.
+
+We are reducing the number of analyzers used in GitLab SAST as part of our long-term strategy to deliver a better and more consistent user experience.
+Streamlining the set of analyzers will also enable faster [iteration](https://about.gitlab.com/handbook/values/#iteration), better [results](https://about.gitlab.com/handbook/values/#results), and greater [efficiency](https://about.gitlab.com/handbook/values/#results) (including a reduction in CI runner usage in most cases).
+
+In GitLab 15.0, GitLab SAST will no longer use the following analyzers:
+
+- [ESLint](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) (JavaScript, TypeScript, React)
+- [Gosec](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) (Go)
+- [Bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Python)
+
+These analyzers will be removed from the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) and replaced with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
+They will no longer receive routine updates, except for security issues.
+We will not delete container images previously published for these analyzers; any such change would be announced as a [deprecation, removal, or breaking change announcement](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes).
+
+We will also remove Java from the scope of the [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) analyzer and replace it with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
+This change will make it simpler to scan Java code; compilation will no longer be required.
+This change will be reflected in the automatic language detection portion of the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml).
+
+If you applied customizations to any of the affected analyzers, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352554#breaking-change).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### SAST support for .NET 2.1
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The GitLab SAST Security Code Scan analyzer scans .NET code for security vulnerabilities.
+For technical reasons, the analyzer must first build the code to scan it.
+
+In GitLab versions prior to 15.0, the default analyzer image (version 2) includes support for:
+
+- .NET 2.1
+- .NET 3.0 and .NET Core 3.0
+- .NET Core 3.1
+- .NET 5.0
+
+In GitLab 15.0, we will change the default major version for this analyzer from version 2 to version 3. This change:
+
+- Adds [severity values for vulnerabilities](https://gitlab.com/gitlab-org/gitlab/-/issues/350408) along with [other new features and improvements](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/blob/master/CHANGELOG.md).
+- Removes .NET 2.1 support.
+- Adds support for .NET 6.0, Visual Studio 2019, and Visual Studio 2022.
+
+Version 3 was [announced in GitLab 14.6](https://about.gitlab.com/releases/2021/12/22/gitlab-14-6-released/#sast-support-for-net-6) and made available as an optional upgrade.
+
+If you rely on .NET 2.1 support being present in the analyzer image by default, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352553#breaking-change).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Secret Detection configuration variables deprecated
+
+To make it simpler and more reliable to [customize GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings), we're deprecating some of the variables that you could previously set in your CI/CD configuration.
+
+The following variables currently allow you to customize the options for historical scanning, but interact poorly with the [GitLab-managed CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) and are now deprecated:
+
+- `SECRET_DETECTION_COMMIT_FROM`
+- `SECRET_DETECTION_COMMIT_TO`
+- `SECRET_DETECTION_COMMITS`
+- `SECRET_DETECTION_COMMITS_FILE`
+
+The `SECRET_DETECTION_ENTROPY_LEVEL` previously allowed you to configure rules that only considered the entropy level of strings in your codebase, and is now deprecated.
+This type of entropy-only rule created an unacceptable number of incorrect results (false positives) and is no longer supported.
+
+In GitLab 15.0, we'll update the Secret Detection [analyzer](https://docs.gitlab.com/ee/user/application_security/terminology/#analyzer) to ignore these deprecated options.
+You'll still be able to configure historical scanning of your commit history by setting the [`SECRET_DETECTION_HISTORIC_SCAN` CI/CD variable](https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-cicd-variables).
+
+For further details, see [the deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352565).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Secure and Protect analyzer images published in new location
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+GitLab uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/terminology/#analyzer) to [scan for security vulnerabilities](https://docs.gitlab.com/ee/user/application_security/).
+Each analyzer is distributed as a container image.
+
+Starting in GitLab 14.8, new versions of GitLab Secure and Protect analyzers are published to a new registry location under `registry.gitlab.com/security-products`.
+
+We will update the default value of [GitLab-managed CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security) to reflect this change:
+
+- For all analyzers except Container Scanning, we will update the variable `SECURE_ANALYZERS_PREFIX` to the new image registry location.
+- For Container Scanning, the default image address is already updated. There is no `SECURE_ANALYZERS_PREFIX` variable for Container Scanning.
+
+In a future release, we will stop publishing images to `registry.gitlab.com/gitlab-org/security-products/analyzers`.
+Once this happens, you must take action if you manually pull images and push them into a separate registry. This is commonly the case for [offline deployments](https://docs.gitlab.com/ee/user/application_security/offline_deployments/index.html).
+Otherwise, you won't receive further updates.
+
+See the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352564) for more details.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Secure and Protect analyzer major version update
+
+WARNING:
+This feature will be changed or removed in 15.00
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The Secure and Protect stages will be bumping the major versions of their analyzers in tandem with the GitLab 15.0 release. This major bump will enable a clear delineation for analyzers, between:
+
+- Those released prior to May 22, 2022, which generate reports that _are not_ subject to stringent schema validation.
+- Those released after May 22, 2022, which generate reports that _are_ subject to stringent schema validation.
+
+If you are not using the default inclusion templates, or have pinned your analyzer version(s) you will need to update your CI/CD job definition to either remove the pinned version or to update the latest major version.
+Users of GitLab 12.0-14.10 will continue to experience analyzer updates as normal until the release of GitLab 15.0, following which all newly fixed bugs and newly released features in the new major versions of the analyzers will not be available in the deprecated versions because we do not backport bugs and new features as per our [maintenance policy](https://docs.gitlab.com/ee/policy/maintenance.html). As required security patches will be backported within the latest 3 minor releases.
+Specifically, the following are being deprecated and will no longer be updated after 15.0 GitLab release:
+
+- API Security: version 1
+- Container Scanning: version 4
+- Coverage-guided fuzz testing: version 2
+- Dependency Scanning: version 2
+- Dynamic Application Security Testing (DAST): version 2
+- License Scanning: version 3
+- Secret Detection: version 3
+- Static Application Security Testing (SAST): version 2, except security-code-scan which is version 3
+ - `bandit`: version 2
+ - `brakeman`: version 2
+ - `eslint`: version 2
+ - `flawfinder`: version 2
+ - `gosec`: version 3
+ - `kubesec`: version 2
+ - `mobsf`: version 2
+ - `nodejs-scan`: version 2
+ - `phpcs-security-audit`: version 2
+ - `pmd-apex`: version 2
+ - `security-code-scan`: version 3
+ - `semgrep`: version 2
+ - `sobelow`: version 2
+ - `spotbugs`: version 2
+
+**Planned removal milestone: 15.00 ()**
+
+### Support for gRPC-aware proxy deployed between Gitaly and rest of GitLab
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+Although not recommended or documented, it was possible to deploy a gRPC-aware proxy between Gitaly and
+the rest of GitLab. For example, NGINX and Envoy. The ability to deploy a gRPC-aware proxy is
+[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352517). If you currently use a gRPC-aware proxy for
+Gitaly connections, you should change your proxy configuration to use TCP or TLS proxying (OSI layer 4) instead.
+
+Gitaly Cluster became incompatible with gRPC-aware proxies in GitLab 13.12. Now all GitLab installations will be incompatible with
+gRPC-aware proxies, even without Gitaly Cluster.
+
+By sending some of our internal RPC traffic through a custom protocol (instead of gRPC) we
+increase throughput and reduce Go garbage collection latency. For more information, see
+the [relevant epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/463).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Test coverage project CI/CD setting
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+To simplify setting a test coverage pattern, in GitLab 15.0 the
+[project setting for test coverage parsing](https://docs.gitlab.com/ee/ci/pipelines/settings.html#add-test-coverage-results-to-a-merge-request-deprecated)
+is being removed.
+
+Instead, using the project’s `.gitlab-ci.yml`, provide a regular expression with the `coverage` keyword to set
+testing coverage results in merge requests.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Vulnerability Check
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The vulnerability check feature is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. We encourage you to migrate to the new security approvals feature instead. You can do so by navigating to **Security & Compliance > Policies** and creating a new Scan Result Policy.
+
+The new security approvals feature is similar to vulnerability check. For example, both can require approvals for MRs that contain security vulnerabilities. However, security approvals improve the previous experience in several ways:
+
+- Users can choose who is allowed to edit security approval rules. An independent security or compliance team can therefore manage rules in a way that prevents development project maintainers from modifying the rules.
+- Multiple rules can be created and chained together to allow for filtering on different severity thresholds for each scanner type.
+- A two-step approval process can be enforced for any desired changes to security approval rules.
+- A single set of security policies can be applied to multiple development projects to allow for ease in maintaining a single, centralized ruleset.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### `CI_BUILD_*` predefined variables
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The predefined CI/CD variables that start with `CI_BUILD_*` were deprecated in GitLab 9.0, and will be removed in GitLab 15.0. If you still use these variables, be sure to change to the current [`CI_JOB_*` predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) which are identical (except for the updated name).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
### `fixup!` commit messages setting draft status of associated Merge Request
The use of `fixup!` as a commit message to trigger draft status
@@ -716,3 +1408,30 @@ Support for `fixup!` is now considered deprecated, and will be
removed in GitLab 15.0.
**Planned removal milestone: 15.0 (2022-06-22)**
+
+### `projectFingerprint` in `PipelineSecurityReportFinding` GraphQL
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The `projectFingerprint` field in the [PipelineSecurityReportFinding](https://docs.gitlab.com/ee/api/graphql/reference/index.html#pipelinesecurityreportfinding)
+GraphQL object is being deprecated. This field contains a "fingerprint" of security findings used to determine uniqueness.
+The method for calculating fingerprints has changed, resulting in different values. Going forward, the new values will be
+exposed in the UUID field. Data previously available in the projectFingerprint field will eventually be removed entirely.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### `started` iterations API field
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
+
+**Planned removal milestone: 15.0 (2022-05-22)**
diff --git a/doc/update/index.md b/doc/update/index.md
index 3a17d3c01d7..45b5f36bc5a 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -98,7 +98,7 @@ that can process jobs in the `background_migration` queue.
```shell
sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
-sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigrationJob.pending'
+sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigrationJob.pending.count'
```
**For installations from source:**
@@ -106,7 +106,7 @@ sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigrati
```shell
cd /home/git/gitlab
sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
-sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::BackgroundMigrationJob.pending'
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::BackgroundMigrationJob.pending.count'
```
### Batched background migrations
@@ -269,9 +269,9 @@ Additional steps between the mentioned versions are possible. We list the minima
| Target version | Your version | Supported upgrade path | Note |
| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| `14.2.6` | `13.10.2` | `13.10.2` -> `13.12.12` -> `14.0.11` -> `14.1.8` -> `14.2.6` | Three intermediate versions are required: `13.12`, `14.0`, and `14.1`, then `14.2.6`. |
-| `14.1.8` | `13.9.2` | `13.9.2` -> `13.12.12` -> `14.0.11` -> `14.1.8` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1.8`. |
-| `13.12.10` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.8.8` -> `13.12.10` | Four intermediate versions are required: `12.10`, `13.0`, `13.1` and `13.8.8`, then `13.12.10`. |
+| `14.2.6` | `13.10.2` | `13.10.2` -> `13.12.15` -> `14.0.11` -> `14.1.8` -> `14.2.6` | Three intermediate versions are required: `13.12`, `14.0`, and `14.1`, then `14.2.6`. |
+| `14.1.8` | `13.9.2` | `13.9.2` -> `13.12.15` -> `14.0.11` -> `14.1.8` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1.8`. |
+| `13.12.15` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.8.8` -> `13.12.15` | Four intermediate versions are required: `12.10`, `13.0`, `13.1` and `13.8.8`, then `13.12.15`. |
| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. |
| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: `11.11`, `12.0` and `12.1`, then `12.10.14`. |
| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5`. |
@@ -351,7 +351,8 @@ or [init scripts](upgrading_from_source.md#configure-sysv-init-script) by [follo
In 14.5 we introduce a set of migrations that wrap up this process by making sure
that all remaining jobs over the `merge_request_diff_commits` table are completed.
These jobs will have already been processed in most cases so that no extra time is necessary during an upgrade to 14.5.
- But if there are remaining jobs, the deployment may take a few extra minutes to complete.
+ However, if there are remaining jobs or you haven't already upgraded to 14.1,
+ the deployment may take multiple hours to complete.
All merge request diff commits will automatically incorporate these changes, and there are no
additional requirements to perform the upgrade.
@@ -439,6 +440,11 @@ for how to proceed.
with self-managed installations, and ensure 14.0.0-14.0.4 installations do not
encounter issues with [batched background migrations](#batched-background-migrations).
+- Upgrading to GitLab [14.5](#1450) (or later) may take a lot longer if you do not upgrade to at least 14.1
+ first. The 14.1 merge request diff commits database migration can take hours to run, but runs in the
+ background while GitLab is in use. GitLab instances upgraded directly from 14.0 to 14.5 or later must
+ run the migration in the foreground and therefore take a lot longer to complete.
+
- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
### 14.0.0
@@ -676,7 +682,7 @@ When [Maintenance mode](../administration/maintenance_mode/index.md) is enabled,
Users who were signed in before Maintenance mode was enabled will continue to be signed in. If the admin who enabled Maintenance mode loses their session, then they will not be able to disable Maintenance mode via the UI. In that case, you can [disable Maintenance mode via the API or Rails console](../administration/maintenance_mode/#disable-maintenance-mode).
-[This bug](https://gitlab.com/gitlab-org/gitlab/-/issues/329261) was fixed in GitLab 14.5.0, and is expected to be backported to GitLab 14.3 and 14.4.
+[This bug](https://gitlab.com/gitlab-org/gitlab/-/issues/329261) was fixed in GitLab 14.5.0 and backported into 14.4.3 and 14.3.5.
## Miscellaneous
diff --git a/doc/update/removals.md b/doc/update/removals.md
index 94ce815a110..9a28adf1f96 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -30,24 +30,70 @@ For removal reviewers (Technical Writers only):
## 14.0
+### Auto Deploy CI template v1
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+In GitLab 14.0, we will update the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the v2 [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). Auto Deploy CI template v1 is deprecated going forward.
+
+Since the v1 and v2 versions are not backward-compatible, your project might encounter an unexpected failure if you already have a deployed application. Follow the [upgrade guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#upgrade-guide) to upgrade your environments. You can also start using the latest template today by following the [early adoption guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#early-adopters).
+
### Breaking changes to Terraform CI template
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
GitLab 14.0 renews the Terraform CI template to the latest version. The new template is set up for the GitLab Managed Terraform state, with a dependency on the GitLab `terraform-images` image, to provide a good user experience around GitLab's Infrastructure-as-Code features.
The current stable and latest templates are not compatible, and the current latest template becomes the stable template beginning with GitLab 14.0, your Terraform pipeline might encounter an unexpected failure if you run a custom `init` job.
### Code Quality RuboCop support changed
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#rubocop-errors).
Relevant Issue: [Default `codeclimate-rubocop` engine does not support Ruby 2.6+](https://gitlab.com/gitlab-org/ci-cd/codequality/-/issues/28)
### Container Scanning Engine Clair
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Clair, the default container scanning engine, was deprecated in GitLab 13.9 and is removed from GitLab 14.0 and replaced by Trivy. We advise customers who are customizing variables for their container scanning job to [follow these instructions](https://docs.gitlab.com/ee/user/application_security/container_scanning/#change-scanners) to ensure that their container scanning jobs continue to work.
+### DAST default template stages
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+In GitLab 14.0, we've removed the stages defined in the current `DAST.gitlab-ci.yml` template to avoid the situation where the template overrides manual changes made by DAST users. We're making this change in response to customer issues where the stages in the template cause problems when used with customized DAST configurations. Because of this removal, `gitlab-ci.yml` configurations that do not specify a `dast` stage must be updated to include this stage.
+
### DAST environment variable renaming and removal
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
GitLab 13.8 renamed multiple environment variables to support their broader usage in different workflows. In GitLab 14.0, the old variables have been permanently removed and will no longer work. Any configurations using these variables must be updated to the new variable names. Any scans using these variables in GitLab 14.0 and later will fail to be configured correctly. These variables are:
- `DAST_AUTH_EXCLUDE_URLS` becomes `DAST_EXCLUDE_URLS`.
@@ -61,23 +107,61 @@ GitLab 13.8 renamed multiple environment variables to support their broader usag
### Default Browser Performance testing job renamed in GitLab 14.0
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
Relevant Issue: [Rename default Browser Performance Testing job](https://gitlab.com/gitlab-org/gitlab/-/issues/225914)
### Default DAST spider begins crawling at target URL
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
In GitLab 14.0, DAST has removed the current method of resetting the scan to the hostname when starting to spider. Prior to GitLab 14.0, the spider would not begin at the specified target path for the URL but would instead reset the URL to begin crawling at the host root. GitLab 14.0 changes the default for the new variable `DAST_SPIDER_START_AT_HOST` to `false` to better support users' intention of beginning spidering and scanning at the specified target URL, rather than the host root URL. This change has an added benefit: scans can take less time, if the specified path does not contain links to the entire site. This enables easier scanning of smaller sections of an application, rather than crawling the entire app during every scan.
### Default branch name for new repositories now `main`
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Every Git repository has an initial branch, which is named `master` by default. It's the first branch to be created automatically when you create a new repository. Future [Git versions](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/) will change the default branch name in Git from `master` to `main`. In coordination with the Git project and the broader community, [GitLab has changed the default branch name](https://gitlab.com/gitlab-org/gitlab/-/issues/223789) for new projects on both our SaaS (GitLab.com) and self-managed offerings starting with GitLab 14.0. This will not affect existing projects.
GitLab has already introduced changes that allow you to change the default branch name both at the [instance level](https://docs.gitlab.com/ee/user/project/repository/branches/default.html#instance-level-custom-initial-branch-name) (for self-managed users) and at the [group level](https://docs.gitlab.com/ee/user/group/#use-a-custom-name-for-the-initial-branch) (for both SaaS and self-managed users). We encourage you to make use of these features to set default branch names on new projects.
For more information, check out our [blog post](https://about.gitlab.com/blog/2021/03/10/new-git-default-branch-name/).
-### Deprecated GraphQL fields have been removed
+### Dependency Scanning
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+As mentioned in [13.9](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#deprecations-for-dependency-scanning) and [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/) several removals for Dependency Scanning take effect.
+
+Previously, to exclude a DS analyzer, you needed to remove it from the default list of analyzers, and use that to set the `DS_DEFAULT_ANALYZERS` variable in your project’s CI template. We determined it should be easier to avoid running a particular analyzer without losing the benefit of newly added analyzers. As a result, we ask you to migrate from `DS_DEFAULT_ANALYZERS` to `DS_EXCLUDED_ANALYZERS` when it is available. Read about it in [issue #287691](https://gitlab.com/gitlab-org/gitlab/-/issues/287691).
+
+Previously, to prevent the Gemnasium analyzers to fetch the advisory database at runtime, you needed to set the `GEMNASIUM_DB_UPDATE` variable. However, this is not documented properly, and its naming is inconsistent with the equivalent `BUNDLER_AUDIT_UPDATE_DISABLED` variable. As a result, we ask you to migrate from `GEMNASIUM_DB_UPDATE` to `GEMNASIUM_UPDATE_DISABLED` when it is available. Read about it in [issue #215483](https://gitlab.com/gitlab-org/gitlab/-/issues/215483).
+
+### Deprecated GraphQL fields
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
In accordance with our [GraphQL deprecation and removal process](https://docs.gitlab.com/ee/api/graphql/#deprecation-process), the following fields that were deprecated prior to 13.7 are [fully removed in 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/267966):
@@ -88,19 +172,55 @@ In accordance with our [GraphQL deprecation and removal process](https://docs.gi
- `DeprecatedMutations (concern**)` - `AddAwardEmoji`, `RemoveAwardEmoji`, `ToggleAwardEmoji`
- `EE::Types::DeprecatedMutations (concern***)` - `Mutations::Pipelines::RunDastScan`, `Mutations::Vulnerabilities::Dismiss`, `Mutations::Vulnerabilities::RevertToDetected`
-### Deprecations for Dependency Scanning
+### DevOps Adoption API Segments
-As mentioned in [13.9](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#deprecations-for-dependency-scanning) and [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/) several removals for Dependency Scanning take effect.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-Previously, to exclude a DS analyzer, you needed to remove it from the default list of analyzers, and use that to set the `DS_DEFAULT_ANALYZERS` variable in your project’s CI template. We determined it should be easier to avoid running a particular analyzer without losing the benefit of newly added analyzers. As a result, we ask you to migrate from `DS_DEFAULT_ANALYZERS` to `DS_EXCLUDED_ANALYZERS` when it is available. Read about it in [issue #287691](https://gitlab.com/gitlab-org/gitlab/-/issues/287691).
+The first release of the DevOps Adoption report had a concept of **Segments**. Segments were [quickly removed from the report](https://gitlab.com/groups/gitlab-org/-/epics/5251) because they introduced an additional layer of complexity on top of **Groups** and **Projects**. Subsequent iterations of the DevOps Adoption report focus on comparing adoption across groups rather than segments. GitLab 14.0 removes all references to **Segments** [from the GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/324414) and replaces them with **Enabled groups**.
-Previously, to prevent the Gemnasium analyzers to fetch the advisory database at runtime, you needed to set the `GEMNASIUM_DB_UPDATE` variable. However, this is not documented properly, and its naming is inconsistent with the equivalent `BUNDLER_AUDIT_UPDATE_DISABLED` variable. As a result, we ask you to migrate from `GEMNASIUM_DB_UPDATE` to `GEMNASIUM_UPDATE_DISABLED` when it is available. Read about it in [issue #215483](https://gitlab.com/gitlab-org/gitlab/-/issues/215483).
+### Disk source configuration for GitLab Pages
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+GitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration) has been available since GitLab 13.0. It replaces the unsupported `disk` source configuration removed in GitLab 14.0, which can no longer be chosen. You should stop using `disk` source configuration, and move to `gitlab` for an API-based configuration. To migrate away from the 'disk' source configuration, set `gitlab_pages['domain_config_source'] = "gitlab"` in your `/etc/gitlab/gitlab.rb` file. We recommend you migrate before updating to GitLab 14.0, to identify and troubleshoot any potential problems before upgrading.
+
+### Experimental prefix in Sidekiq queue selector options
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+GitLab supports a [queue selector](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html#queue-selector) to run only a subset of background jobs for a given process. When it was introduced, this option had an 'experimental' prefix (`experimental_queue_selector` in Omnibus, `experimentalQueueSelector` in Helm charts).
+
+As announced in the [13.6 release post](https://about.gitlab.com/releases/2020/11/22/gitlab-13-6-released/#sidekiq-cluster-queue-selector-configuration-option-has-been-renamed), the 'experimental' prefix is no longer supported. Instead, `queue_selector` for Omnibus and `queueSelector` in Helm charts should be used.
### External Pipeline Validation Service Code Changes
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
For self-managed instances using the experimental [external pipeline validation service](https://docs.gitlab.com/ee/administration/external_pipeline_validation.html), the range of error codes GitLab accepts will be reduced. Currently, pipelines are invalidated when the validation service returns a response code from `400` to `499`. In GitLab 14.0 and later, pipelines will be invalidated for the `406: Not Accepted` response code only.
-### Geo Foreign Data Wrapper settings removed
+### Geo Foreign Data Wrapper settings
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
As [announced in GitLab 13.3](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#geo-foreign-data-wrapper-settings-deprecated), the following configuration settings in `/etc/gitlab/gitlab.rb` have been removed in 14.0:
@@ -109,236 +229,448 @@ As [announced in GitLab 13.3](https://about.gitlab.com/releases/2020/08/22/gitla
- `geo_postgresql['fdw_external_password']`
- `gitlab-_rails['geo_migrated_local_files_clean_up_worker_cron']`
-### GitLab OAuth implicit grant deprecation
+### GitLab OAuth implicit grant
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
GitLab is deprecating the [OAuth 2 implicit grant flow](https://docs.gitlab.com/ee/api/oauth2.html#implicit-grant-flow) as it has been removed for [OAuth 2.1](https://oauth.net/2.1/).
-Beginning in 14.0, new applications can't be created with the OAuth 2 implicit grant flow. Existing OAuth implicit grant flows are no longer supported in 14.4. Migrate your existing applications to other supported [OAuth2 flows](https://docs.gitlab.com/ee/api/oauth2.html#supported-oauth2-flows) before release 14.4.
+Migrate your existing applications to other supported [OAuth2 flows](https://docs.gitlab.com/ee/api/oauth2.html#supported-oauth2-flows).
### GitLab Runner helper image in GitLab.com Container Registry
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
In 14.0, we are now pulling the GitLab Runner [helper image](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#helper-image) from the GitLab Container Registry instead of Docker Hub. Refer to [issue #27218](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27218) for details.
### GitLab Runner installation to ignore the `skel` directory
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
In GitLab Runner 14.0, the installation process will ignore the `skel` directory by default when creating the user home directory. Refer to [issue #4845](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4845) for details.
-### Gitaly Cluster SQL primary elector has been removed
+### Gitaly Cluster SQL primary elector
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
Now that Praefect supports a [primary election strategy](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#repository-specific-primary-nodes) for each repository, we have removed the `sql` election strategy.
The `per_repository` election strategy is the new default, which is automatically used if no election strategy was specified.
If you had configured the `sql` election strategy, you must follow the [migration instructions](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#migrate-to-repository-specific-primary-gitaly-nodes) before upgrading to 14.0.
+### Global `SAST_ANALYZER_IMAGE_TAG` in SAST CI template
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+With the maturity of GitLab Secure scanning tools, we've needed to add more granularity to our release process. Previously, GitLab shared a major version number for [all analyzers and tools](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). This requires all tools to share a major version, and prevents the use of [semantic version numbering](https://semver.org/). In GitLab 14.0, SAST removes the `SAST_ANALYZER_IMAGE_TAG` global variable in our [managed `SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml) CI template, in favor of the analyzer job variable setting the `major.minor` tag in the SAST vendored template.
+
+Each analyzer job now has a scoped `SAST_ANALYZER_IMAGE_TAG` variable, which will be actively managed by GitLab and set to the `major` tag for the respective analyzer. To pin to a specific version, [change the variable value to the specific version tag](https://docs.gitlab.com/ee/user/application_security/sast/#pinning-to-minor-image-version).
+If you override or maintain custom versions of `SAST.gitlab-ci.yml`, update your CI templates to stop referencing the global `SAST_ANALYZER_IMAGE_TAG`, and move it to a scoped analyzer job tag. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs) to future-proof your CI templates. This change allows you to more granularly control future analyzer updates with a pinned `major.minor` version.
+This deprecation and removal changes our [previously announced plan](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#pin-static-analysis-analyzers-and-tools-to-minor-versions) to pin the Static Analysis tools.
+
+### Hardcoded `master` in CI/CD templates
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+Our CI/CD templates have been updated to no longer use hard-coded references to a `master` branch. In 14.0, they all use a variable that points to your project's configured default branch instead. If your CI/CD pipeline relies on our built-in templates, verify that this change works with your current configuration. For example, if you have a `master` branch and a different default branch, the updates to the templates may cause changes to your pipeline behavior. For more information, [read the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324131).
+
### Helm v2 support
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Helm v2 was [officially deprecated](https://helm.sh/blog/helm-v2-deprecation-timeline/) in November of 2020, with the `stable` repository being [de-listed from the Helm Hub](https://about.gitlab.com/blog/2020/11/09/ensure-auto-devops-work-after-helm-stable-repo/) shortly thereafter. With the release of GitLab 14.0, which will include the 5.0 release of the [GitLab Helm chart](https://docs.gitlab.com/charts/), Helm v2 will no longer be supported.
Users of the chart should [upgrade to Helm v3](https://helm.sh/docs/topics/v2_v3_migration/) to deploy GitLab 14.0 and later.
-### Legacy feature flags removed
+### Legacy DAST domain validation
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The legacy method of DAST Domain Validation for CI/CD scans was deprecated in GitLab 13.8, and is removed in GitLab 14.0. This method of domain validation only disallows scans if the `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` environment variable is set to `true` in the `gitlab-ci.yml` file, and a `Gitlab-DAST-Permission` header on the site is not set to `allow`. This two-step method required users to opt in to using the variable before they could opt out from using the header.
+
+For more information, see the [removal issue](https://gitlab.com/gitlab-org/gitlab/-/issues/293595).
+
+### Legacy feature flags
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
Legacy feature flags became read-only in GitLab 13.4. GitLab 14.0 removes support for legacy feature flags, so you must migrate them to the [new version](https://docs.gitlab.com/ee/operations/feature_flags.html). You can do this by first taking a note (screenshot) of the legacy flag, then deleting the flag through the API or UI (you don't need to alter the code), and finally create a new Feature Flag with the same name as the legacy flag you deleted. Also, make sure the strategies and environments match the deleted flag. We created a [video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) to help with this migration.
-### Legacy storage removed
+### Legacy fields from DAST report
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+As a part of the migration to a common report format for all of the Secure scanners in GitLab, DAST is making changes to the DAST JSON report. Certain legacy fields were deprecated in 13.8 and have been completely removed in 14.0. These fields are `@generated`, `@version`, `site`, and `spider`. This should not affect any normal DAST operation, but does affect users who consume the JSON report in an automated way and use these fields. Anyone affected by these changes, and needs these fields for business reasons, is encouraged to open a new GitLab issue and explain the need.
+
+For more information, see [the removal issue](https://gitlab.com/gitlab-org/gitlab/-/issues/33915).
+
+### Legacy storage
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
As [announced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#planned-removal-of-legacy-storage-in-14.0), [legacy storage](https://docs.gitlab.com/ee/administration/repository_storage_types.html#legacy-storage) has been removed in GitLab 14.0.
+### License Compliance
+
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+In 13.0, we deprecated the License-Management CI template and renamed it License-Scanning. We have been providing backward compatibility by warning users of the old template to switch. Now in 14.0, we are completely removing the License-Management CI template. Read about it in [issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261) or [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/).
+
### Limit projects returned in `GET /groups/:id/`
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
To improve performance, we are limiting the number of projects returned from the `GET /groups/:id/` API call to 100. A complete list of projects can still be retrieved with the `GET /groups/:id/projects` API call.
### Make `pwsh` the default shell for newly-registered Windows Runners
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
In GitLab Runner 13.2, PowerShell Core support was added to the Shell executor. In 14.0, PowerShell Core, `pwsh` is now the default shell for newly-registered Windows runners. Windows `CMD` will still be available as a shell option for Windows runners. Refer to [issue #26419](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26419) for details.
### Migrate from `SAST_DEFAULT_ANALYZERS` to `SAST_EXCLUDED_ANALYZERS`
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Until GitLab 13.9, if you wanted to avoid running one particular GitLab SAST analyzer, you needed to remove it from the [long string of analyzers in the `SAST.gitlab-ci.yml` file](https://gitlab.com/gitlab-org/gitlab/-/blob/390afc431e7ce1ac253b35beb39f19e49c746bff/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L12) and use that to set the [`SAST_DEFAULT_ANALYZERS`](https://docs.gitlab.com/ee/user/application_security/sast/#docker-images) variable in your project's CI file. If you did this, it would exclude you from future new analyzers because this string hard codes the list of analyzers to execute. We avoid this problem by inverting this variable's logic to exclude, rather than choose default analyzers.
Beginning with 13.9, [we migrated](https://gitlab.com/gitlab-org/gitlab/-/blob/14fed7a33bfdbd4663d8928e46002a5ef3e3282c/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L13) to `SAST_EXCLUDED_ANALYZERS` in our `SAST.gitlab-ci.yml` file. We encourage anyone who uses a [customized SAST configuration](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) in their project CI file to migrate to this new variable. If you have not overridden `SAST_DEFAULT_ANALYZERS`, no action is needed. The CI/CD variable `SAST_DEFAULT_ANALYZERS` has been removed in GitLab 14.0, which released on June 22, 2021.
-### New Terraform template version
+### Off peak time mode configuration for Docker Machine autoscaling
-As we continuously [develop GitLab's Terraform integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/325312), to minimize customer disruption, we maintain two GitLab CI/CD templates for Terraform:
-
-- The ["latest version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml), which is updated frequently between minor releases of GitLab (such as 13.10, 13.11, etc).
-- The ["major version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml), which is updated only at major releases (such as 13.0, 14.0, etc).
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-At every major release of GitLab, the "latest version" template becomes the "major version" template, inheriting the "latest template" setup.
-As we have added many new features to the Terraform integration, the new setup for the "major version" template can be considered a breaking change.
-
-The latest template supports the [Terraform Merge Request widget](https://docs.gitlab.com/ee/user/infrastructure/mr_integration.html) and
-doesn't need additional setup to work with the [GitLab managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/terraform_state.html).
-
-To check the new changes, see the [new "major version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml).
+In GitLab Runner 13.0, [issue #5069](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/5069), we introduced new timing options for the GitLab Docker Machine executor. In GitLab Runner 14.0, we have removed the old configuration option, [off peak time mode](https://docs.gitlab.com/runner/configuration/autoscale.html#off-peak-time-mode-configuration-deprecated).
### OpenSUSE Leap 15.1
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
Support for [OpenSUSE Leap 15.1 is being deprecated](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5135). Support for 15.1 will be dropped in 14.0. We are now providing support for openSUSE Leap 15.2 packages.
### PostgreSQL 11 support
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
PostgreSQL 12 will be the minimum required version in GitLab 14.0. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits.
Starting in GitLab 13.7, all new installations default to version 12. From GitLab 13.8, single-node instances are automatically upgraded as well. If you aren't ready to upgrade, you can [opt out of automatic upgrades](https://docs.gitlab.com/omnibus/settings/database.html#opt-out-of-automatic-postgresql-upgrades).
-### Removal of deprecated `trace` parameter from `jobs` API endpoint
+### Redundant timestamp field from DORA metrics API payload
-GitLab Runner was updated in GitLab 13.4 to internally stop passing the `trace` parameter to the `/api/jobs/:id` endpoint. GitLab 14.0 deprecates the `trace` parameter entirely for all other requests of this endpoint. Make sure your [GitLab Runner version matches your GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions) to ensure consistent behavior.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Removal of legacy fields from DAST report
-
-As a part of the migration to a common report format for all of the Secure scanners in GitLab, DAST is making changes to the DAST JSON report. Certain legacy fields were deprecated in 13.8 and have been completely removed in 14.0. These fields are `@generated`, `@version`, `site`, and `spider`. This should not affect any normal DAST operation, but does affect users who consume the JSON report in an automated way and use these fields. Anyone affected by these changes, and needs these fields for business reasons, is encouraged to open a new GitLab issue and explain the need.
+The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
-For more information, see [the removal issue](https://gitlab.com/gitlab-org/gitlab/-/issues/33915).
+### Release description in the Tags API
-### Removal of release description in the Tags API
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
GitLab 14.0 removes support for the release description in the Tags API. You can no longer add a release description when [creating a new tag](https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag). You also can no longer [create](https://docs.gitlab.com/ee/api/tags.html#create-a-new-release) or [update](https://docs.gitlab.com/ee/api/tags.html#update-a-release) a release through the Tags API. Please migrate to use the [Releases API](https://docs.gitlab.com/ee/api/releases/#create-a-release) instead.
-### Removals for License Compliance
+### Ruby version changed in `Ruby.gitlab-ci.yml`
-In 13.0, we deprecated the License-Management CI template and renamed it License-Scanning. We have been providing backward compatibility by warning users of the old template to switch. Now in 14.0, we are completely removing the License-Management CI template. Read about it in [issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261) or [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/).
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Remove DAST default template stages
+By default, the `Ruby.gitlab-ci.yml` file has included Ruby 2.5.
-In GitLab 14.0, we've removed the stages defined in the current `DAST.gitlab-ci.yml` template to avoid the situation where the template overrides manual changes made by DAST users. We're making this change in response to customer issues where the stages in the template cause problems when used with customized DAST configurations. Because of this removal, `gitlab-ci.yml` configurations that do not specify a `dast` stage must be updated to include this stage.
+To better support the latest versions of Ruby, the template is changed to use `ruby:latest`, which is currently 3.0. To better understand the changes in Ruby 3.0, please reference the [Ruby-lang.org release announcement](https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/).
-### Remove SAST analyzer `SAST_GOSEC_CONFIG` variable in favor of custom rulesets
+Relevant Issue: [Updates Ruby version 2.5 to 3.0](https://gitlab.com/gitlab-org/gitlab/-/issues/329160)
-With the release of [SAST Custom Rulesets](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) in GitLab 13.5 we allow greater flexibility in configuration options for our Go analyzer (GoSec). As a result we no longer plan to support our less flexible [`SAST_GOSEC_CONFIG`](https://docs.gitlab.com/ee/user/application_security/sast/#analyzer-settings) analyzer setting. This variable was deprecated in GitLab 13.10.
-GitLab 14.0 removes the old `SAST_GOSEC_CONFIG variable`. If you use or override `SAST_GOSEC_CONFIG` in your CI file, update your SAST CI configuration or pin to an older version of the GoSec analyzer. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs) to future-proof your CI templates.
+### SAST analyzer `SAST_GOSEC_CONFIG` variable
-### Remove Ubuntu 19.10 (Eoan Ermine) package
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-Ubuntu 19.10 (Eoan Ermine) reached end of life on Friday, July 17, 2020. In GitLab Runner 14.0, Ubuntu 19.10 (Eoan Ermine) is no longer available from our package distribution. Refer to [issue #26036](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26036) for details.
+With the release of [SAST Custom Rulesets](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) in GitLab 13.5 we allow greater flexibility in configuration options for our Go analyzer (GoSec). As a result we no longer plan to support our less flexible [`SAST_GOSEC_CONFIG`](https://docs.gitlab.com/ee/user/application_security/sast/#analyzer-settings) analyzer setting. This variable was deprecated in GitLab 13.10.
+GitLab 14.0 removes the old `SAST_GOSEC_CONFIG variable`. If you use or override `SAST_GOSEC_CONFIG` in your CI file, update your SAST CI configuration or pin to an older version of the GoSec analyzer. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs) to future-proof your CI templates.
-### Remove `/usr/lib/gitlab-runner` symlink from package
+### Service Templates
-In GitLab Runner 13.3, a symlink was added from `/user/lib/gitlab-runner/gitlab-runner` to `/usr/bin/gitlab-runner`. In 14.0, the symlink has been removed and the runner is now installed in `/usr/bin/gitlab-runner`. Refer to [issue #26651](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26651) for details.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Remove `?w=1` URL parameter to ignore whitespace changes
+Service Templates are [removed in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/5672). They were used to apply identical settings to a large number of projects, but they only did so at the time of project creation.
-To create a consistent experience for users based on their preferences, support for toggling whitespace changes via URL parameter has been removed in GitLab 14.0.
+While they solved part of the problem, _updating_ those values later proved to be a major pain point. [Project Integration Management](https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html) solves this problem by enabling you to create settings at the Group or Instance level, and projects within that namespace inheriting those settings.
-### Remove `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag
+### Success and failure for finished build metric conversion
-In 14.0, we have deactivated the `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag. Refer to issue [#26679](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26679) for details.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Remove `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL` feature flag
+In GitLab Runner 13.5, we introduced `failed` and `success` states for a job. To support Prometheus rules, we chose to convert `success/failure` to `finished` for the metric. In 14.0, the conversion has now been removed. Refer to [issue #26900](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26900) for details.
-In [GitLab Runner 13.1](https://docs.gitlab.com/runner/executors/shell.html#gitlab-131-and-later), [issue #3376](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3376), we introduced `sigterm` and then `sigkill` to a process in the Shell executor. We also introduced a new feature flag, `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL`, so you can use the previous process termination sequence. In GitLab Runner 14.0, [issue #6413](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6413), the feature flag has been removed.
+### Terraform template version
-### Remove `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-GitLab Runner 14.0 removes the `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag. Refer to [issue #27175](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27175) for details.
+As we continuously [develop GitLab's Terraform integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/325312), to minimize customer disruption, we maintain two GitLab CI/CD templates for Terraform:
-### Remove `secret_detection_default_branch` job
+- The ["latest version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml), which is updated frequently between minor releases of GitLab (such as 13.10, 13.11, etc).
+- The ["major version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml), which is updated only at major releases (such as 13.0, 14.0, etc).
-To ensure Secret Detection was scanning both default branches and feature branches, we introduced two separate secret detection CI jobs (`secret_detection_default_branch` and `secret_detection`) in our managed [`Secret-Detection.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) template. These two CI jobs created confusion and complexity in the CI rules logic. This deprecation moves the `rule` logic into the `script` section, which then determines how the `secret_detection` job is run (historic, on a branch, commits, etc).
-If you override or maintain custom versions of `SAST.gitlab-ci.yml` or `Secret-Detection.gitlab-ci.yml`, you must update your CI templates. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/secret_detection/#custom-settings-example) to future-proof your CI templates. GitLab 14.0 no longer supports the old `secret_detection_default_branch` job.
+At every major release of GitLab, the "latest version" template becomes the "major version" template, inheriting the "latest template" setup.
+As we have added many new features to the Terraform integration, the new setup for the "major version" template can be considered a breaking change.
-### Remove disk source configuration for GitLab Pages
+The latest template supports the [Terraform Merge Request widget](https://docs.gitlab.com/ee/user/infrastructure/mr_integration.html) and
+doesn't need additional setup to work with the [GitLab managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/terraform_state.html).
-GitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration) has been available since GitLab 13.0. It replaces the unsupported `disk` source configuration removed in GitLab 14.0, which can no longer be chosen. You should stop using `disk` source configuration, and move to `gitlab` for an API-based configuration. To migrate away from the 'disk' source configuration, set `gitlab_pages['domain_config_source'] = "gitlab"` in your `/etc/gitlab/gitlab.rb` file. We recommend you migrate before updating to GitLab 14.0, to identify and troubleshoot any potential problems before upgrading.
+To check the new changes, see the [new "major version" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml).
-### Remove legacy DAST domain validation
+### Ubuntu 16.04 support
-The legacy method of DAST Domain Validation for CI/CD scans was deprecated in GitLab 13.8, and is removed in GitLab 14.0. This method of domain validation only disallows scans if the `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` environment variable is set to `true` in the `gitlab-ci.yml` file, and a `Gitlab-DAST-Permission` header on the site is not set to `allow`. This two-step method required users to opt in to using the variable before they could opt out from using the header.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-For more information, see the [removal issue](https://gitlab.com/gitlab-org/gitlab/-/issues/293595).
+Ubuntu 16.04 [reached end-of-life in April 2021](https://ubuntu.com/about/release-cycle), and no longer receives maintenance updates. We strongly recommend users to upgrade to a newer release, such as 20.04.
-### Remove off peak time mode configuration for Docker Machine autoscaling
+GitLab 13.12 will be the last release with Ubuntu 16.04 support.
-In GitLab Runner 13.0, [issue #5069](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/5069), we introduced new timing options for the GitLab Docker Machine executor. In GitLab Runner 14.0, we have removed the old configuration option, [off peak time mode](https://docs.gitlab.com/runner/configuration/autoscale.html#off-peak-time-mode-configuration-deprecated).
+### Ubuntu 19.10 (Eoan Ermine) package
-### Remove redundant timestamp field from DORA metrics API payload
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
+Ubuntu 19.10 (Eoan Ermine) reached end of life on Friday, July 17, 2020. In GitLab Runner 14.0, Ubuntu 19.10 (Eoan Ermine) is no longer available from our package distribution. Refer to [issue #26036](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26036) for details.
-### Remove success and failure for finished build metric conversion
+### Unicorn in GitLab self-managed
-In GitLab Runner 13.5, we introduced `failed` and `success` states for a job. To support Prometheus rules, we chose to convert `success/failure` to `finished` for the metric. In 14.0, the conversion has now been removed. Refer to [issue #26900](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26900) for details.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Remove support for Windows Server 1903 image
+[Support for Unicorn](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6078) has been removed in GitLab 14.0 in favor of Puma. [Puma has a multi-threaded architecture](https://docs.gitlab.com/ee/administration/operations/puma.html) which uses less memory than a multi-process application server like Unicorn. On GitLab.com, we saw a 40% reduction in memory consumption by using Puma.
-In 14.0, we have removed Windows Server 1903. Microsoft ended support for this version on 2020-08-12. Refer to [issue #27551](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27551) for details.
+### WIP merge requests renamed 'draft merge requests'
-### Remove support for Windows Server 1909 image
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-In 14.0, we have removed Windows Server 1909. Microsoft ended support for this version on 2021-05-11. Refer to [issue #27899](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27899) for details.
+The WIP (work in progress) status for merge requests signaled to reviewers that the merge request in question wasn't ready to merge. We've renamed the WIP feature to **Draft**, a more inclusive and self-explanatory term. **Draft** clearly communicates the merge request in question isn't ready for review, and makes no assumptions about the progress being made toward it. **Draft** also reduces the cognitive load for new users, non-English speakers, and anyone unfamiliar with the WIP acronym.
-### Removed Global `SAST_ANALYZER_IMAGE_TAG` in SAST CI template
+### Web Application Firewall (WAF)
-With the maturity of GitLab Secure scanning tools, we've needed to add more granularity to our release process. Previously, GitLab shared a major version number for [all analyzers and tools](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). This requires all tools to share a major version, and prevents the use of [semantic version numbering](https://semver.org/). In GitLab 14.0, SAST removes the `SAST_ANALYZER_IMAGE_TAG` global variable in our [managed `SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml) CI template, in favor of the analyzer job variable setting the `major.minor` tag in the SAST vendored template.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-Each analyzer job now has a scoped `SAST_ANALYZER_IMAGE_TAG` variable, which will be actively managed by GitLab and set to the `major` tag for the respective analyzer. To pin to a specific version, [change the variable value to the specific version tag](https://docs.gitlab.com/ee/user/application_security/sast/#pinning-to-minor-image-version).
-If you override or maintain custom versions of `SAST.gitlab-ci.yml`, update your CI templates to stop referencing the global `SAST_ANALYZER_IMAGE_TAG`, and move it to a scoped analyzer job tag. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs) to future-proof your CI templates. This change allows you to more granularly control future analyzer updates with a pinned `major.minor` version.
-This deprecation and removal changes our [previously announced plan](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#pin-static-analysis-analyzers-and-tools-to-minor-versions) to pin the Static Analysis tools.
+The Web Application Firewall (WAF) was deprecated in GitLab 13.6 and is removed from GitLab 14.0. The WAF had limitations inherent in the architectural design that made it difficult to meet the requirements traditionally expected of a WAF. By removing the WAF, GitLab is able to focus on improving other areas in the product where more value can be provided to users. Users who currently rely on the WAF can continue to use the free and open source [ModSecurity](https://github.com/SpiderLabs/ModSecurity) project, which is independent from GitLab. Additional details are available in the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271276).
-### Ruby version changed in `Ruby.gitlab-ci.yml`
+### Windows Server 1903 image support
-By default, the `Ruby.gitlab-ci.yml` file has included Ruby 2.5.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-To better support the latest versions of Ruby, the template is changed to use `ruby:latest`, which is currently 3.0. To better understand the changes in Ruby 3.0, please reference the [Ruby-lang.org release announcement](https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/).
+In 14.0, we have removed Windows Server 1903. Microsoft ended support for this version on 2020-08-12. Refer to [issue #27551](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27551) for details.
-Relevant Issue: [Updates Ruby version 2.5 to 3.0](https://gitlab.com/gitlab-org/gitlab/-/issues/329160)
+### Windows Server 1909 image support
-### Segments removed from DevOps Adoption API
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-The first release of the DevOps Adoption report had a concept of **Segments**. Segments were [quickly removed from the report](https://gitlab.com/groups/gitlab-org/-/epics/5251) because they introduced an additional layer of complexity on top of **Groups** and **Projects**. Subsequent iterations of the DevOps Adoption report focus on comparing adoption across groups rather than segments. GitLab 14.0 removes all references to **Segments** [from the GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/324414) and replaces them with **Enabled groups**.
+In 14.0, we have removed Windows Server 1909. Microsoft ended support for this version on 2021-05-11. Refer to [issue #27899](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27899) for details.
-### Service Templates removed
+### `/usr/lib/gitlab-runner` symlink from package
-Service Templates are [removed in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/5672). They were used to apply identical settings to a large number of projects, but they only did so at the time of project creation.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-While they solved part of the problem, _updating_ those values later proved to be a major pain point. [Project Integration Management](https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html) solves this problem by enabling you to create settings at the Group or Instance level, and projects within that namespace inheriting those settings.
+In GitLab Runner 13.3, a symlink was added from `/user/lib/gitlab-runner/gitlab-runner` to `/usr/bin/gitlab-runner`. In 14.0, the symlink has been removed and the runner is now installed in `/usr/bin/gitlab-runner`. Refer to [issue #26651](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26651) for details.
-### Sidekiq queue selector options no longer accept the 'experimental' prefix
+### `?w=1` URL parameter to ignore whitespace changes
-GitLab supports a [queue selector](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html#queue-selector) to run only a subset of background jobs for a given process. When it was introduced, this option had an 'experimental' prefix (`experimental_queue_selector` in Omnibus, `experimentalQueueSelector` in Helm charts).
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-As announced in the [13.6 release post](https://about.gitlab.com/releases/2020/11/22/gitlab-13-6-released/#sidekiq-cluster-queue-selector-configuration-option-has-been-renamed), the 'experimental' prefix is no longer supported. Instead, `queue_selector` for Omnibus and `queueSelector` in Helm charts should be used.
+To create a consistent experience for users based on their preferences, support for toggling whitespace changes via URL parameter has been removed in GitLab 14.0.
-### Ubuntu 16.04 support
+### `CI_PROJECT_CONFIG_PATH` variable
-Ubuntu 16.04 [reached end-of-life in April 2021](https://ubuntu.com/about/release-cycle), and no longer receives maintenance updates. We strongly recommend users to upgrade to a newer release, such as 20.04.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-GitLab 13.12 will be the last release with Ubuntu 16.04 support.
+The `CI_PROJECT_CONFIG_PATH` [predefined project variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
+has been removed in favor of `CI_CONFIG_PATH`, which is functionally the same.
-### Unicorn removed in favor of Puma for GitLab self-managed
+If you are using `CI_PROJECT_CONFIG_PATH` in your pipeline configurations,
+please update them to use `CI_CONFIG_PATH` instead.
-[Support for Unicorn](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6078) has been removed in GitLab 14.0 in favor of Puma. [Puma has a multi-threaded architecture](https://docs.gitlab.com/ee/administration/operations/puma.html) which uses less memory than a multi-process application server like Unicorn. On GitLab.com, we saw a 40% reduction in memory consumption by using Puma.
+### `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag
-### Update Auto Deploy template version
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-In GitLab 14.0, we will update the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the v2 [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). Auto Deploy CI tempalte v1 will is deprecated going forward.
+In 14.0, we have deactivated the `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag. Refer to issue [#26679](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26679) for details.
-Since the v1 and v2 versions are not backward-compatible, your project might encounter an unexpected failure if you already have a deployed application. Follow the [upgrade guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#upgrade-guide) to upgrade your environments. You can also start using the latest template today by following the [early adoption guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#early-adopters).
+### `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL` feature flag
-### Update CI/CD templates to stop using hardcoded `master`
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-Our CI/CD templates have been updated to no longer use hard-coded references to a `master` branch. In 14.0, they all use a variable that points to your project's configured default branch instead. If your CI/CD pipeline relies on our built-in templates, verify that this change works with your current configuration. For example, if you have a `master` branch and a different default branch, the updates to the templates may cause changes to your pipeline behavior. For more information, [read the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324131).
+In [GitLab Runner 13.1](https://docs.gitlab.com/runner/executors/shell.html#gitlab-131-and-later), [issue #3376](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3376), we introduced `sigterm` and then `sigkill` to a process in the Shell executor. We also introduced a new feature flag, `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL`, so you can use the previous process termination sequence. In GitLab Runner 14.0, [issue #6413](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6413), the feature flag has been removed.
-### WIP merge requests renamed 'draft merge requests'
+### `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag
-The WIP (work in progress) status for merge requests signaled to reviewers that the merge request in question wasn't ready to merge. We've renamed the WIP feature to **Draft**, a more inclusive and self-explanatory term. **Draft** clearly communicates the merge request in question isn't ready for review, and makes no assumptions about the progress being made toward it. **Draft** also reduces the cognitive load for new users, non-English speakers, and anyone unfamiliar with the WIP acronym.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-### Web Application Firewall (WAF)
+GitLab Runner 14.0 removes the `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag. Refer to [issue #27175](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27175) for details.
-The Web Application Firewall (WAF) was deprecated in GitLab 13.6 and is removed from GitLab 14.0. The WAF had limitations inherent in the architectural design that made it difficult to meet the requirements traditionally expected of a WAF. By removing the WAF, GitLab is able to focus on improving other areas in the product where more value can be provided to users. Users who currently rely on the WAF can continue to use the free and open source [ModSecurity](https://github.com/SpiderLabs/ModSecurity) project, which is independent from GitLab. Additional details are available in the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271276).
+### `secret_detection_default_branch` job
-### `CI_PROJECT_CONFIG_PATH` removed in GitLab 14.0
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-GitLab 14.0 removes the `CI_PROJECT_CONFIG_PATH` pre-defined project variable in favor of `CI_CONFIG_PATH`, which is functionally the same. If you are using `CI_PROJECT_CONFIG_PATH` in your pipeline configurations, update them to use `CI_CONFIG_PATH` instead.
+To ensure Secret Detection was scanning both default branches and feature branches, we introduced two separate secret detection CI jobs (`secret_detection_default_branch` and `secret_detection`) in our managed [`Secret-Detection.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) template. These two CI jobs created confusion and complexity in the CI rules logic. This deprecation moves the `rule` logic into the `script` section, which then determines how the `secret_detection` job is run (historic, on a branch, commits, etc).
+If you override or maintain custom versions of `SAST.gitlab-ci.yml` or `Secret-Detection.gitlab-ci.yml`, you must update your CI templates. We strongly encourage [inheriting and overriding our managed CI templates](https://docs.gitlab.com/ee/user/application_security/secret_detection/#custom-settings-example) to future-proof your CI templates. GitLab 14.0 no longer supports the old `secret_detection_default_branch` job.
-### `CI_PROJECT_CONFIG_PATH` variable has been removed
+### `trace` parameter in `jobs` API
-The `CI_PROJECT_CONFIG_PATH` [predefined project variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
-has been removed in favor of `CI_CONFIG_PATH`, which is functionally the same.
+WARNING:
+This feature was changed or removed in 14.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
-If you are using `CI_PROJECT_CONFIG_PATH` in your pipeline configurations,
-please update them to use `CI_CONFIG_PATH` instead.
+GitLab Runner was updated in GitLab 13.4 to internally stop passing the `trace` parameter to the `/api/jobs/:id` endpoint. GitLab 14.0 deprecates the `trace` parameter entirely for all other requests of this endpoint. Make sure your [GitLab Runner version matches your GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions) to ensure consistent behavior.
## 14.1
@@ -388,3 +720,13 @@ In GitLab 14.3, we will remove the ability to filter by `name` in the [list proj
The support for [`gitlab_pages['use_legacy_storage']` setting](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) in Omnibus installations has been removed.
In 14.0 we removed [`domain_config_source`](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) which had been previously deprecated, and allowed users to specify disk storage. In 14.0 we added `use_legacy_storage` as a **temporary** flag to unblock upgrades, and allow us to debug issues with our users and it was deprecated and communicated for removal in 14.3.
+
+## 14.6
+
+### Limit the number of triggered pipeline to 25K in free tier
+
+A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change.
+
+### Release CLI distributed as a generic package
+
+The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 22ffcda9138..22367435ae4 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -73,7 +73,7 @@ Download Ruby and compile it:
```shell
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.gz"
+curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.gz"
echo '3043099089608859fc8cce7f9fdccaa1f53a462457e3838ec3b25a7d609fbc5b ruby-2.7.4.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.4.tar.gz
cd ruby-2.7.4
@@ -111,7 +111,7 @@ Download and install Go (for Linux, 64-bit):
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
+curl --remote-name --location --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
echo '414cd18ce1d193769b9e97d2401ad718755ab47816e13b2a1cde203d263b55cf go1.16.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.16.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,gofmt} /usr/local/bin/
@@ -410,6 +410,20 @@ Example:
Additional instructions here.
-->
+### 14.5.0
+
+As part of [enabling real-time issue assignees](https://gitlab.com/gitlab-org/gitlab/-/issues/330117), Action Cable is now enabled by default, and requires `config/cable.yml` to be present.
+You can configure this by running:
+
+```shell
+cd /home/git/gitlab
+
+sudo -u git -H cp config/cable.yml.example config/cable.yml
+
+# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
+sudo -u git -H editor config/cable.yml
+```
+
### 13.0.1
As part of [deprecating Rack Attack throttles on Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4750), the Rack Attack initializer on GitLab
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index 13658e6071b..050c5909934 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -87,6 +87,9 @@ meet the other online upgrade requirements mentioned above.
## Single-node deployment
+WARNING:
+You can only upgrade one minor release at a time.
+
Before following these instructions, note the following **important** information:
- You can only upgrade one minor release at a time. So from 13.6 to 13.7, not to 13.8.
@@ -158,6 +161,7 @@ you've completed these steps.
## Multi-node / HA deployment
+WARNING:
You can only upgrade one minor release at a time. So from 13.6 to 13.7, not to 13.8.
If you attempt more than one minor release, the upgrade may fail.
@@ -531,6 +535,9 @@ procedure.
## Geo deployment **(PREMIUM SELF)**
+WARNING:
+You can only upgrade one minor release at a time.
+
The order of steps is important. While following these steps, make
sure you follow them in the right order, on the correct node.
@@ -651,6 +658,9 @@ setting `gitlab_rails['auto_migrate'] = false` in
## Multi-node / HA deployment with Geo **(PREMIUM SELF)**
+WARNING:
+You can only upgrade one minor release at a time.
+
This section describes the steps required to upgrade a multi-node / HA
deployment with Geo. Some steps must be performed on a particular node. This
node is known as the “deploy node†and is noted through the following
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index df34cd03d71..2ad18d5f70e 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -39,7 +39,7 @@ feature is available.
## 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](../../../policy/alpha-beta-support.md#beta-features).
> - The Overview tab [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330401) in GitLab 14.1.
> - DAST and SAST metrics [added](https://gitlab.com/gitlab-org/gitlab/-/issues/328033) in GitLab 14.1.
> - Fuzz Testing metrics [added](https://gitlab.com/gitlab-org/gitlab/-/issues/330398) in GitLab 14.2.
diff --git a/doc/user/admin_area/analytics/usage_trends.md b/doc/user/admin_area/analytics/usage_trends.md
index 7901d30c3ea..a9c5adcf838 100644
--- a/doc/user/admin_area/analytics/usage_trends.md
+++ b/doc/user/admin_area/analytics/usage_trends.md
@@ -33,7 +33,7 @@ At the top of the page, Usage Trends shows total counts for:
- Projects
- Groups
- Issues
-- Merge Requests
+- Merge requests
- Pipelines
These figures can be useful for understanding how much data your instance contains in total.
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index f9b5168fb08..437a72da767 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -13,9 +13,14 @@ GitLab administrators are responsible for the overall security of their instance
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)
-and [delete](#delete-a-users-ssh-key) and see:
+Use Credentials inventory to see for your GitLab instance all:
+
+- Personal access tokens (PAT).
+- Project access tokens (GitLab 14.8 and later).
+- SSH keys.
+- GPG keys.
+
+You can also [revoke](#revoke-a-users-personal-access-token) and [delete](#delete-a-users-ssh-key) and see:
- Who they belong to.
- Their access scope.
@@ -28,17 +33,13 @@ To access the Credentials inventory:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Credentials**.
-The following is an example of the Credentials inventory page:
-
-![Credentials inventory page](img/credentials_inventory_v13_10.png)
-
## Revoke a user's personal access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214811) in GitLab 13.4.
If you see a **Revoke** button, you can revoke that user's PAT. Whether you see a **Revoke** button depends on the token state, and if an expiration date has been set. For more information, see the following table:
-| Token state | [Token expiration enforced?](settings/account_and_limit_settings.md#allow-expired-personal-access-tokens-to-be-used) | Show Revoke button? | Comments |
+| Token state | [Token expiration enforced?](settings/account_and_limit_settings.md#allow-expired-personal-access-tokens-to-be-used-deprecated) | Show Revoke button? | Comments |
|-------------|------------------------|--------------------|----------------------------------------------------------------------------|
| Active | Yes | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
| Active | No | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
@@ -49,6 +50,15 @@ If you see a **Revoke** button, you can revoke that user's PAT. Whether you see
When a PAT is revoked from the credentials inventory, the instance notifies the user by email.
+## Revoke a user's project access token
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/243833) in GitLab 14.8.
+
+The **Revoke** button next to a project access token can be selected to revoke that particular project access token. This will both:
+
+- Revoke the token project access token.
+- Enqueue a background worker to delete the project bot user.
+
## Delete a user's SSH key
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225248) in GitLab 13.5.
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_10.png b/doc/user/admin_area/img/credentials_inventory_v13_10.png
deleted file mode 100644
index 2790ca70fba..00000000000
--- a/doc/user/admin_area/img/credentials_inventory_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index ba0802b3b7a..57a4a746ff0 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -32,7 +32,7 @@ The Admin Area is made up of the following sections:
| **{slight-frown}** Abuse Reports | Manage [abuse reports](review_abuse_reports.md) submitted by your users. |
| **{license}** License | Upload, display, and remove [licenses](license.md). |
| **{cloud-gear}** Kubernetes | Create and manage instance-level [Kubernetes clusters](../instance/clusters/index.md). |
-| **{push-rules}** Push rules | Configure pre-defined Git [push rules](../../push_rules/push_rules.md) for projects. Also, configure [merge requests approvers rules](merge_requests_approvals.md). |
+| **{push-rules}** Push rules | Configure pre-defined Git [push rules](../project/repository/push_rules.md) for projects. Also, configure [merge requests approvers rules](merge_requests_approvals.md). |
| **{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. |
@@ -107,23 +107,6 @@ You can combine the filter options. For example, to list only public projects wi
1. Click the **Public** tab.
1. Enter `score` in the **Filter by name...** input box.
-#### Projects pending deletion **(PREMIUM SELF)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37014) in GitLab 13.3.
-> - [Tab renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/347468) from **Deleted projects** in GitLab 14.6.
-
-When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-deletion),
-projects within that group are not deleted immediately, but only after a delay. To access a list of all projects that are pending deletion:
-
-1. On the top bar, select **Menu > Projects > Explore projects**.
-1. Select the **Pending deletion** tab (in GitLab 14.6 and later) or the **Deleted projects** tab (GitLab 14.5 and earlier).
-
-Listed for each project is:
-
-- The time the project was marked for deletion.
-- The time the project is scheduled for final deletion.
-- A **Restore** link to stop the project being eventually deleted.
-
### Administering Users
You can administer all users in the GitLab instance from the Admin Area's Users page:
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index c3f0c94db21..22133e30aa0 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -27,9 +27,8 @@ If you have questions or need assistance upgrading from GitLab CE to EE,
## Activate GitLab EE with an activation code
In GitLab Enterprise Edition 14.1 and later, you need an activation code to activate
-your instance. To get an activation code, [purchase a license](https://about.gitlab.com/pricing/)
-or sign up for a [free trial](https://about.gitlab.com/free-trial/). The activation
-code is a 24-character alphanumeric string you receive in a confirmation email.
+your instance. To get an activation code you have to [purchase a license](https://about.gitlab.com/pricing/).
+The activation code is a 24-character alphanumeric string you receive in a confirmation email.
You can also sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in)
to copy the activation code to your clipboard.
@@ -60,8 +59,10 @@ Otherwise, to upload your license:
1. On the left sidebar, select **Settings**.
1. In the **License file** area, select **Upload a license**.
1. Upload a license:
- - For a file, select **Upload `.gitlab-license` file**, **Choose file**, and
- select the license file from your local machine.
+ - For a file, either:
+ - Select **Upload `.gitlab-license` file**, then **Choose File** and
+ select the license file from your local machine.
+ - Drag and drop the license file to the **Drag your license file here** area.
- For plain text, select **Enter license key** and paste the contents in
**License key**.
1. Select the **Terms of Service** checkbox.
@@ -129,6 +130,8 @@ the current date range is the active license.
When you upload a future-dated license, it doesn't take effect until its applicable date.
You can view all active subscriptions in the **Subscription history** table.
+You can also [export](../../subscriptions/self_managed/index.md) your license usage information to a CSV file.
+
NOTE:
In GitLab 13.6 and earlier, a banner about an expiring license may continue to display
when you upload a new license. This happens when the start date of the new license
diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md
index ee38664fa66..e8db319df77 100644
--- a/doc/user/admin_area/moderate_users.md
+++ b/doc/user/admin_area/moderate_users.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -208,7 +208,13 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
## Ban and unban users
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.2 [with a flag](../../administration/feature_flags.md) named `ban_user_feature_flag`. Disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/330667) in GitLab 14.8.
+
+FLAG:
+On self-managed GitLab, by default this feature is available.
+To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `ban_user_feature_flag`.
+On GitLab.com, this feature is available to GitLab.com administrators only.
GitLab administrators can ban and unban users. Banned users are blocked, and their issues are hidden.
The banned user's comments are still displayed. Hiding a banned user's comments is [tracked in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327356).
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 75905d60c4e..213bddec325 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/admin_area/reporting/spamcheck.md b/doc/user/admin_area/reporting/spamcheck.md
new file mode 100644
index 00000000000..02d7cd01139
--- /dev/null
+++ b/doc/user/admin_area/reporting/spamcheck.md
@@ -0,0 +1,65 @@
+---
+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/#designated-technical-writers
+---
+
+# Spamcheck anti-spam service **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6259) in GitLab 14.8.
+
+[Spamcheck](https://gitlab.com/gitlab-org/spamcheck) is an anti-spam engine
+developed by GitLab originally to combat rising amount of spam in GitLab.com,
+and later made public to be used in self-managed GitLab instances.
+
+## Enable Spamcheck
+
+Spamcheck is only available for package-based installations:
+
+1. Edit `/etc/gitlab/gitlab.rb` and enable Spamcheck:
+
+ ```ruby
+ spamcheck['enable'] = true
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. Verify that the new services `spamcheck` and `spam-classifier` are
+ up and running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+## Configure GitLab to use Spamcheck
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Reporting**.
+1. Expand **Spam and Anti-bot Protection**.
+1. Update the Spam Check settings:
+ 1. Check the "Enable Spam Check via external API endpoint" checkbox.
+ 1. For **URL of the external Spam Check endpoint** use `grpc://localhost:8001`.
+ 1. Leave **Spam Check API key** blank.
+1. Select **Save changes**.
+
+NOTE:
+In single-node instances, Spamcehck runs over `localhost`, and hence is running
+in an unauthenticated mode. If on multi-node instances where GitLab runs on one
+server and Spamcheck runs on another server listening over a public endpoint, it
+is recommended to enforce some sort of authentication using a reverse proxy in
+front of the Spamcheck service that can be used along with an API key. One
+example would be to use `JWT` authentication for this and specifying a bearer
+token as the API key.
+[Native authentication for Spamcheck is in the works](https://gitlab.com/gitlab-com/gl-security/engineering-and-research/automation-team/spam/spamcheck/-/issues/171).
+
+## Running Spamcheck over TLS
+
+Spamcheck service on its own can not communicate directly over TLS with GitLab.
+However, Spamcheck can be deployed behind a reverse proxy which performs TLS
+termination. In such a scenario, GitLab can be made to communicate with
+Spamcheck over TLS by specifying `tls://` scheme for the external Spamcheck URL
+instead of `grpc://` in the Admin settings.
diff --git a/doc/user/admin_area/review_abuse_reports.md b/doc/user/admin_area/review_abuse_reports.md
index 4c5a241ab18..ec8e6f2dda4 100644
--- a/doc/user/admin_area/review_abuse_reports.md
+++ b/doc/user/admin_area/review_abuse_reports.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
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 f748f575419..1d982196228 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -234,10 +234,14 @@ Once a lifetime for SSH keys is set, GitLab:
NOTE:
When a user's SSH key becomes invalid they can delete and re-add the same key again.
-## Allow expired SSH keys to be used **(ULTIMATE SELF)**
+## Allow expired SSH keys to be used (DEPRECATED) **(ULTIMATE SELF)**
> - [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.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351963) in GitLab 14.8.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351963) in GitLab 14.8.
By default, expired SSH keys **are not usable**.
@@ -283,10 +287,14 @@ Once a lifetime for personal access tokens is set, GitLab:
allowed lifetime. Three hours is given to allow administrators to change the allowed lifetime,
or remove it, before revocation takes place.
-## Allow expired Personal Access Tokens to be used **(ULTIMATE SELF)**
+## Allow expired Personal Access Tokens to be used (DEPRECATED) **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in GitLab 13.1.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/296881) in GitLab 13.9.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351962) in GitLab 14.8.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351962) in GitLab 14.8.
By default, expired personal access tokens (PATs) **are not usable**.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index e18808ffb41..18379471bcf 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -197,6 +197,12 @@ To enable or disable the banner:
## Required pipeline configuration **(PREMIUM SELF)**
+WARNING:
+Required pipeline configurations is in its end-of-life process for Premium users. It's
+[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352316) for use in GitLab 14.8,
+and planned to be unavailable for Premium users in GitLab 15.0. This feature is planned to continue
+to be available for Ultimate users. Ultimate users are not impacted by this deprecation and removal.
+
NOTE:
An alternative [compliance solution](../../project/settings/index.md#compliance-pipeline-configuration)
is available. We recommend this alternative solution because it provides greater flexibility,
diff --git a/doc/user/admin_area/settings/deprecated_api_rate_limits.md b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
index 9be703f3b82..d651e445a95 100644
--- a/doc/user/admin_area/settings/deprecated_api_rate_limits.md
+++ b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
@@ -30,7 +30,7 @@ for deprecated API endpoints. No other new features are provided by this overrid
Prerequisites:
-- You must have the Administrator role for your instance.
+- You must have administrator access for your instance.
To override the general user and IP rate limits for requests to deprecated API endpoints:
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 6bc9e97629c..e4fc3b6e6d4 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -56,7 +56,7 @@ To change the hostname used in private commit emails:
NOTE:
After the hostname is configured, every private commit email using the previous hostname is not
-recognized by GitLab. This can directly conflict with certain [Push rules](../../../push_rules/push_rules.md) such as
+recognized by GitLab. This can directly conflict with certain [Push rules](../../project/repository/push_rules.md) such as
`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`.
## Custom additional text **(PREMIUM SELF)**
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index 4fd7c59ef24..ef980981fec 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -105,7 +105,7 @@ label defined in the [global settings](#configuration) is used.
The label is shown on all project pages in the upper right corner.
-![classification label on project page](img/classification_label_on_project_page.png)
+![classification label on project page](img/classification_label_on_project_page_v14_8.png)
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/files_api_rate_limits.md b/doc/user/admin_area/settings/files_api_rate_limits.md
index 675561ce9cf..7305e49b0d2 100644
--- a/doc/user/admin_area/settings/files_api_rate_limits.md
+++ b/doc/user/admin_area/settings/files_api_rate_limits.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Files API rate limits **(FREE SELF)**
+# Rate limits on Repository files API **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68561) in GitLab 14.3.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75918) in GitLab 14.6. [Feature flag files_api_throttling](https://gitlab.com/gitlab-org/gitlab/-/issues/338903) removed.
@@ -26,7 +26,7 @@ for the Files API. No other new features are provided by this override.
Prerequisite:
-- You must have the Administrator role for your instance.
+- You must have administrator access for your instance.
To override the general user and IP rate limits for requests to the Repository files API:
diff --git a/doc/user/admin_area/settings/git_lfs_rate_limits.md b/doc/user/admin_area/settings/git_lfs_rate_limits.md
index adc6cc2b11b..c10300baeef 100644
--- a/doc/user/admin_area/settings/git_lfs_rate_limits.md
+++ b/doc/user/admin_area/settings/git_lfs_rate_limits.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Git LFS Rate Limits **(FREE SELF)**
+# Rate limits on Git LFS **(FREE SELF)**
[Git LFS (Large File Storage)](../../../topics/git/lfs/index.md) is a Git extension
for handling large files. If you use Git LFS in your repository, common Git operations
diff --git a/doc/user/admin_area/settings/img/classification_label_on_project_page.png b/doc/user/admin_area/settings/img/classification_label_on_project_page.png
deleted file mode 100644
index 4aedb332cec..00000000000
--- a/doc/user/admin_area/settings/img/classification_label_on_project_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/classification_label_on_project_page_v14_8.png b/doc/user/admin_area/settings/img/classification_label_on_project_page_v14_8.png
new file mode 100644
index 00000000000..4bd2e7d389b
--- /dev/null
+++ b/doc/user/admin_area/settings/img/classification_label_on_project_page_v14_8.png
Binary files differ
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 2820f3ae9df..a581fd4aebc 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -137,6 +137,7 @@ The **Network** settings contain:
- [Incident Management Limits](../../../operations/incident_management/index.md) - Limit the
number of inbound alerts that can be sent to a project.
- [Notes creation limit](rate_limit_on_notes_creation.md) - Set a rate limit on the note creation requests.
+- [Get single user limit](rate_limit_on_users_api.md) - Set a rate limit on users API endpoint to get a user by ID.
### Preferences
@@ -160,7 +161,7 @@ The **Preferences** settings contain:
The **Reporting** settings contain:
- [Spam and Anti-bot Protection](../../../integration/recaptcha.md) -
- Enable anti-spam services, like reCAPTCHA or Akismet, and set IP limits.
+ Enable anti-spam services, like reCAPTCHA, Akismet or [Spamcheck](../reporting/spamcheck.md), and set IP limits.
- [Abuse reports](../review_abuse_reports.md) - Set notification email for abuse reports.
### Repository
diff --git a/doc/user/admin_area/settings/rate_limit_on_users_api.md b/doc/user/admin_area/settings/rate_limit_on_users_api.md
new file mode 100644
index 00000000000..7954055f38b
--- /dev/null
+++ b/doc/user/admin_area/settings/rate_limit_on_users_api.md
@@ -0,0 +1,33 @@
+---
+type: reference
+stage: Manage
+group: Authentication & Authorization
+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
+---
+
+# Rate limits on Users API **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78364) in GitLab 14.8.
+
+You can configure the per user rate limit for requests to [Users API](../../../api/users.md).
+
+To change the rate limit:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Network**.
+1. Expand **Users API rate limit**.
+1. In the **Maximum requests per 10 minutes** text box, enter the new value.
+1. Optional. In the **Users to exclude from the rate limit** box, list users allowed to exceed the limit.
+1. Select **Save changes**.
+
+This limit is:
+
+- Applied independently per user.
+- Not applied per IP address.
+
+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 to the `GET /users/:id` API endpoint
+exceeding a rate of 300 per 10 minutes are blocked. Access to the endpoint is allowed after ten minutes have elapsed.
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index 52b20d5b437..c63cd88eeb4 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -38,7 +38,7 @@ they do not have access to all projects, groups, or the **Admin Area** menu.
To access potentially dangerous resources, an administrator can activate Admin Mode by:
- Selecting the *Enable Admin Mode* button
-- Trying to access any part of the UI that requires an administrator role, specifically those which call `/admin` endpoints.
+- Trying to access any part of the UI that requires administrator access, specifically those which call `/admin` endpoints.
The main use case allows administrators to perform their regular tasks as a regular
user, based on their memberships, without having to set up a second account for
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 d713ef4b4e0..88be73c3215 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
@@ -22,6 +22,11 @@ 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.
+NOTE:
+[In GitLab 14.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/344807),
+the rate limits for API requests don't affect requests made by the frontend, as these are always
+counted as web traffic.
+
## Enable unauthenticated API request rate limit
To enable the unauthenticated request rate limit:
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 82e0d3d27d4..c38b2455a8d 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -7,12 +7,12 @@ type: reference
# Control access and visibility **(FREE SELF)**
-GitLab enables users with the [Administrator role](../../permissions.md) to enforce
+GitLab enables users with administrator access to enforce
specific controls on branches, projects, snippets, groups, and more.
To access the visibility and access control options:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -29,7 +29,7 @@ or configure [branch protection for groups](../../group/index.md#change-the-defa
To change the default branch protection for the entire instance:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -55,7 +55,7 @@ can be overridden on a per-group basis by the group's owner. In
[GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab administrators can
disable this privilege for group owners, enforcing the instance-level protection rule:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -71,7 +71,7 @@ Instance-level protections for project creation define which roles can
[add projects to a group](../../group/index.md#specify-who-can-add-projects-to-a-group)
on the instance. To alter which roles have permission to create projects:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -84,9 +84,9 @@ on the instance. To alter which roles have permission to create projects:
## Restrict project deletion to Administrators **(PREMIUM SELF)**
Anyone with the **Owner** role, either at the project or group level, can
-delete a project. To allow only users with the Administrator role to delete projects:
+delete a project. To allow only users with administrator access to delete projects:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -137,7 +137,7 @@ Alternatively, projects that are marked for removal can be deleted immediately.
To set the default [visibility levels for new projects](../../../public_access/public_access.md):
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -152,7 +152,7 @@ To set the default [visibility levels for new projects](../../../public_access/p
To set the default visibility levels for new [snippets](../../snippets.md):
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -166,7 +166,7 @@ For more details on snippet visibility, read
To set the default visibility levels for new groups:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -183,7 +183,7 @@ For more details on group visibility, see
To restrict visibility levels for projects, snippets, and selected pages:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -200,7 +200,7 @@ For more details on project visibility, see
You can specify from which hosting sites users can [import their projects](../../project/import/index.md):
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -212,7 +212,7 @@ You can specify from which hosting sites users can [import their projects](../..
To enable the export of
[projects and their data](../../../user/project/settings/import_export.md#export-a-project-and-its-data):
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -228,7 +228,7 @@ The GitLab restrictions apply at the application level.
To specify the enabled Git access protocols:
-1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
@@ -280,7 +280,7 @@ NOTE:
SSH clone URLs can be customized in `gitlab.rb` by setting `gitlab_rails['gitlab_ssh_host']` and
other related settings.
-## Configure defaults for RSA, DSA, ECDSA, ED25519 SSH keys
+## Configure defaults for RSA, DSA, ECDSA, ED25519, ECDSA_SK, ED25519_SK SSH keys
These options specify the permitted types and lengths for SSH keys.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 066b45aeb39..18a6ca20bc7 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -17,7 +17,7 @@ requests, and:
- Take action on individual merge requests.
- Reduce overall cycle time.
-Code Review Analytics is available to users with at least the Reporter [role](../permissions.md), and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
+Code Review Analytics is available to users with at least the Reporter role, and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
NOTE:
Initially, no data appears. Data is populated as users comment on open merge requests.
diff --git a/doc/user/analytics/img/issues_created_per_month_v13_11.png b/doc/user/analytics/img/issues_created_per_month_v13_11.png
deleted file mode 100644
index da3340bfdc2..00000000000
--- a/doc/user/analytics/img/issues_created_per_month_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/issues_created_per_month_v14_8.png b/doc/user/analytics/img/issues_created_per_month_v14_8.png
new file mode 100644
index 00000000000..7dcfa73ea19
--- /dev/null
+++ b/doc/user/analytics/img/issues_created_per_month_v14_8.png
Binary files differ
diff --git a/doc/user/analytics/img/mr_mean_time_to_merge_metric_v13_9.png b/doc/user/analytics/img/mr_mean_time_to_merge_metric_v13_9.png
deleted file mode 100644
index ad108dabf73..00000000000
--- a/doc/user/analytics/img/mr_mean_time_to_merge_metric_v13_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/mr_throughput_table_v13_3.png b/doc/user/analytics/img/mr_throughput_table_v13_3.png
deleted file mode 100644
index bb63770dc3f..00000000000
--- a/doc/user/analytics/img/mr_throughput_table_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/issue_analytics.md b/doc/user/analytics/issue_analytics.md
index 6aa2f594532..62fff443073 100644
--- a/doc/user/analytics/issue_analytics.md
+++ b/doc/user/analytics/issue_analytics.md
@@ -34,7 +34,7 @@ You can change the total number of months displayed by setting a URL parameter.
For example, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15`
shows a total of 15 months for the chart in the GitLab.org group.
-![Issues created per month](img/issues_created_per_month_v13_11.png)
+![Issues created per month](img/issues_created_per_month_v14_8.png)
## Drill into the information
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index bb110ab495f..f9ca06c0ef9 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -1,119 +1,66 @@
---
-description: "Merge Request Analytics help you understand the efficiency of your code review process, and the productivity of your team." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
+description: "Merge request analytics help you understand the efficiency of your code review process, and the productivity of your team." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
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
---
-# Merge Request Analytics **(PREMIUM)**
+# Merge request analytics **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229045) in GitLab 13.3.
> - Moved to GitLab Premium in 13.9.
-Merge Request Analytics helps you understand the efficiency of your code review process, and the productivity of your team.
+Use merge request analytics to view:
-## Overview
+- The number of merge requests your organization merged per month.
+- The average time between merge request creation and merge.
+- Information about each merged merge request.
-Merge Request Analytics displays information that will help you evaluate the efficiency and productivity of your merge request process.
+You can use merge request analytics to identify:
-The Throughput chart shows the number of merge requests merged, by month. Merge request throughput is
-a common measure of productivity in software engineering. Although imperfect, the average throughput can
-be a meaningful benchmark of your team's overall productivity.
+- Low or high productivity months.
+- Efficiency and productivity of your merge request process.
+- Efficiency of your code review process.
-To access Merge Request Analytics:
+## View merge request analytics
+
+You must have at least the Reporter role to view merge request analytics.
+
+To view merge request analytics:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Merge request**.
-## Use cases
+## View merge requests merged per month
-This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#delaney-development-team-lead)
-and others who want to understand broad patterns in code review and productivity.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232651) in GitLab 13.3.
+> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229266) in GitLab 13.4
-You can use Merge Request Analytics to expose when your team is most and least productive, and
-identify improvements that might substantially accelerate your development cycle.
+To view the number of merge requests merged per month:
-Merge Request Analytics could be used when:
-
-- You want to know if you were more productive this month than last month, or 12 months ago.
-- You want to drill into low- or high-productivity months to understand the work that took place.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Analytics > Merge request**.
+1. Optional. Filter results:
+ 1. Select the filter bar.
+ 1. Select a parameter.
+ 1. Select a value or enter text to refine the results.
+ 1. To adjust the date range:
+ - In the **From** field, select a start date.
+ - In the **To** field, select an end date.
-## Visualizations and data
+The **Throughput** chart shows the number of merge requests merged per month.
-The following visualizations and data are available, representing all merge requests that were merged in the given date range.
+The table shows up to 20 merge requests per page, and includes
+information about each merge request.
-### Mean time to merge
+## View average time between merge request creation and merge
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229389) in GitLab 13.9.
-The mean time to merge (MTTM) metric shows the average time between when a merge request is created,
-and when it is merged. To view how the MTTM changes over time, compare MTTM across different date ranges.
-
-![Mean time to merge](img/mr_mean_time_to_merge_metric_v13_9.png "Merge Request Analytics - MTTM metric showing the average time it takes from initiating a MR to being merged")
-
-### Throughput chart
-
-The throughput chart shows the number of merge requests merged per month.
-
-![Throughput chart](img/mr_throughput_chart_v13_3.png "Merge Request Analytics - Throughput chart showing merge requests merged in the past 12 months")
-
-### Throughput table
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232651) in GitLab 13.3.
-
-The Throughput table displays the most recent merge requests merged in the date range. The
-table displays up to 20 merge requests at a time. If there are more than 20 merge requests,
-you can paginate to them. For each merge request, you can review the following data:
-
-- Title (as a link to the merge request itself)
-- ID
-- Pipeline status
-- Label count
-- Comment count
-- Approval count (if approved)
-- Date merged
-- Time to merge
-- Milestone
-- Commit count
-- Pipeline count
-- Line change counts
-- Assignees
-
-![Throughput table](img/mr_throughput_table_v13_3.png "Merge Request Analytics - Throughput table listing the 100 merge requests most recently merged")
+Use the number in **Mean time to merge** to view the average time between when a merge request is
+created and when it's merged.
-## Filter the data
+To view **Mean time to merge**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229266) in GitLab 13.4
-
-You can filter the data that is presented on the page based on the following parameters:
-
-- Author
-- Assignee
-- Label
-- Milestone
-- Source branch
-- Target branch
-
-To filter results:
-
-1. Select the filter bar.
-1. Select a parameter to filter by.
-1. Select a value from the autocompleted results, or enter search text to refine the results.
-1. Press Enter.
-
-## Date range
-
-The date range is set to the past 12 months by default. You can modify the date range by changing the "From" and/or "To" values that appear alongside the filter bar. After changing either value, the data displayed on the page will update automatically.
-
-## Tip: Bookmark preferred settings
-
-You can bookmark preferred filters and date ranges. After you have applied a change to the
-filter bar or the date range, you'll see that information in the URL. You can create a
-bookmark for those preferred settings in your browser.
-
-## Permissions
-
-The **Merge Request Analytics** feature can be accessed only:
-
-- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
-- By users with at least the Reporter [role](../permissions.md).
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Analytics > Merge request**.
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index e1ba2f5565e..be710f8cbd7 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -65,7 +65,7 @@ request is merged. Select the dropdown to view:
The right-side histogram shows the size or complexity of a merge request.
Select the dropdown to view:
-
+
- Number of commits per merge request.
- Number of lines of code (LOC) per commit.
- Number of files touched.
@@ -103,4 +103,4 @@ You can filter analytics based on a date range. To filter results:
The **Productivity Analytics** dashboard can be accessed only:
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
-- By users with at least the Reporter [role](../permissions.md).
+- By users with at least the Reporter role.
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index be6b06a0797..4eb721f8832 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -114,6 +114,7 @@ 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.
> - Support for OpenAPI Specification using YAML format was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
> - Support for OpenAPI Specification v3.1 was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327268) in GitLab 14.2.
+> - Support to generate media type `application/xml` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327268) in GitLab 14.8.
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.
@@ -125,6 +126,7 @@ the body generation is limited to these body types:
- `application/x-www-form-urlencoded`
- `multipart/form-data`
- `application/json`
+- `application/xml`
#### Configure Web API fuzzing with an OpenAPI Specification
@@ -459,7 +461,7 @@ Follow these steps to provide the bearer token with `FUZZAPI_OVERRIDES_ENV`:
```
1. To validate that authentication is working, run an API fuzzing test and review the fuzzing logs
- and the test API's application logs.
+ and the test API's application logs. See the [overrides section](#overrides) for more information about override commands.
##### Token generated at test runtime
@@ -493,7 +495,7 @@ variables:
FUZZAPI_PROFILE: Quick
FUZZAPI_OPENAPI: test-api-specification.json
FUZZAPI_TARGET_URL: http://test-deployment/
- FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
```
To validate that authentication is working, run an API fuzzing test and review the fuzzing logs and
@@ -535,7 +537,7 @@ variables:
FUZZAPI_PROFILE: Quick-10
FUZZAPI_OPENAPI: test-api-specification.json
FUZZAPI_TARGET_URL: http://test-deployment/
- FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
FUZZAPI_OVERRIDES_CMD: renew_token.py
FUZZAPI_OVERRIDES_INTERVAL: 300
```
@@ -575,6 +577,9 @@ profile increases as the number of tests increases.
|[`FUZZAPI_OVERRIDES_FILE`](#overrides) | Path to a JSON file containing overrides. |
|[`FUZZAPI_OVERRIDES_ENV`](#overrides) | JSON string containing headers to override. |
|[`FUZZAPI_OVERRIDES_CMD`](#overrides) | Overrides command. |
+|[`FUZZAPI_OVERRIDES_CMD_VERBOSE`](#overrides) | When set to any value. It shows overrides command output as part of the job output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.8. |
+|`FUZZAPI_PRE_SCRIPT` | Run user command or script before scan session starts. |
+|`FUZZAPI_POST_SCRIPT` | Run user command or script after scan session has finished. |
|[`FUZZAPI_OVERRIDES_INTERVAL`](#overrides) | How often to run overrides command in seconds. Defaults to `0` (once). |
|[`FUZZAPI_HTTP_USERNAME`](#http-basic-authentication) | Username for HTTP authentication. |
|[`FUZZAPI_HTTP_PASSWORD`](#http-basic-authentication) | Password for HTTP authentication. |
@@ -754,7 +759,7 @@ variables:
FUZZAPI_PROFILE: Quick
FUZZAPI_OPENAPI: test-api-specification.json
FUZZAPI_TARGET_URL: http://test-deployment/
- FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
```
#### Using a CI/CD variable
@@ -799,16 +804,181 @@ variables:
If the value must be generated or regenerated on expiration, you can provide a program or script for
the API fuzzer to execute on a specified interval. The provided script runs in an Alpine Linux
-container that has Python 3 and Bash installed. If the Python script requires additional packages,
-it must detect this and install the packages at runtime. The script creates the overrides JSON file
-as defined above.
+container that has Python 3 and Bash installed.
+
+You have to set the environment variable `FUZZAPI_OVERRIDES_CMD` to the program or script you would like
+to execute. The provided command creates the overrides JSON file as defined previously.
+
+You might want to install other scripting runtimes like NodeJS or Ruby, or maybe you need to install a dependency for
+your overrides command. In this case, we recommend setting the `FUZZAPI_PRE_SCRIPT` to the file path of a script which
+provides those prerequisites. The script provided by `FUZZAPI_PRE_SCRIPT` is executed once, before the analyzer starts.
+
+See the [Alpine Linux package management](https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management)
+page for information about installing Alpine Linux packages.
You must provide three CI/CD variables, each set for correct operation:
- `FUZZAPI_OVERRIDES_FILE`: File generated by the provided command.
-- `FUZZAPI_OVERRIDES_CMD`: Command to generate JSON file.
+- `FUZZAPI_OVERRIDES_CMD`: Overrides command in charge of generating the overrides JSON file periodically.
- `FUZZAPI_OVERRIDES_INTERVAL`: Interval in seconds to run command.
+Optionally:
+
+- `FUZZAPI_PRE_SCRIPT`: Script to install runtimes or dependencies before the analyzer starts.
+
+```yaml
+stages:
+ - fuzz
+
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_CMD: renew_token.py
+ FUZZAPI_OVERRIDES_INTERVAL: 300
+```
+
+#### Debugging overrides
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.8.
+
+By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `FUZZAPI_OVERRIDES_CMD_VERBOSE` to any value in order to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
+
+It is also possible to write messages from your script to a log file that is collected when the job completes or fails. The log file must be created in a specific location and follow a naming convention.
+
+Adding some basic logging to your overrides script is useful in case the script fails unexpectedly during normal running of the job. The log file is automatically included as an artifact of the job, allowing you to download it after the job has finished.
+
+Following our example, we provided `renew_token.py` in the environmental variable `FUZZAPI_OVERRIDES_CMD`. Please notice two things in the script:
+
+- Log file is saved in the location indicated by the environment variable `CI_PROJECT_DIR`.
+- Log file name should match `gl-*.log`.
+
+```python
+#!/usr/bin/env python
+
+# Example of an overrides command
+
+# Override commands can update the overrides json file
+# with new values to be used. This is a great way to
+# update an authentication token that will expire
+# during testing.
+
+import logging
+import json
+import os
+import requests
+import backoff
+
+# [1] Store log file in directory indicated by env var CI_PROJECT_DIR
+working_directory = os.environ['CI_PROJECT_DIR']
+
+# [2] File name should match the pattern: gl-*.log
+log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')
+
+# Set up logger
+logging.basicConfig(filename=log_file_path, level=logging.DEBUG)
+
+# Use `backoff` decorator to retry in case of transient errors.
+@backoff.on_exception(backoff.expo,
+ (requests.exceptions.Timeout,
+ requests.exceptions.ConnectionError),
+ max_time=30)
+def get_auth_response():
+ return requests.get('https://authorization.service/api/get_api_token', auth=(os.environ['AUTH_USER'], os.environ['AUTH_PWD']))
+
+
+# In our example, access token is retrieved from a given endpoint
+try:
+
+ # Performs a http request, response sample:
+ # { "Token" : "b5638ae7-6e77-4585-b035-7d9de2e3f6b3" }
+ response = get_auth_response()
+
+ # Check that the request is successful. may raise `requests.exceptions.HTTPError`
+ response.raise_for_status()
+
+ # Gets JSON data
+ response_body = response.json()
+
+# If needed specific exceptions can be caught
+# requests.ConnectionError : A network connection error problem occurred
+# requests.HTTPError : HTTP request returned an unsuccessful status code. [Response.raise_for_status()]
+# requests.ConnectTimeout : The request timed out while trying to connect to the remote server
+# requests.ReadTimeout : The server did not send any data in the allotted amount of time.
+# requests.TooManyRedirects : The request exceeds the configured number of maximum redirections
+# requests.exceptions.RequestException : All exceptions that related to Requests
+except requests.exceptions.RequestException as requests_error:
+ # logs exceptions related to `Requests`
+ logging.error(f'Error, failed while performing HTTP request. Error message: {requests_error}')
+ raise
+except requests.exceptions.JSONDecodeError as json_decode_error:
+ # logs errors related decoding JSON response
+ logging.error(f'Error, failed while decoding JSON response. Error message: {json_decode_error}')
+ raise
+except Exception as e:
+ # logs any other error
+ logging.error(f'Error, unknown error while retrieving access token. Error message: {e}')
+ raise
+
+# computes object that holds overrides file content.
+# It uses data fetched from request
+overrides_data = {
+ "headers": {
+ "Authorization": f"Token {response_body['Token']}"
+ }
+}
+
+# log entry informing about the file override computation
+overrides_file_path = os.path.join(
+ working_directory, "api-fuzzing-overrides.json")
+logging.info("Creating overrides file: %s" % overrides_file_path)
+
+# attempts to overwrite the file
+try:
+ if os.path.exists(overrides_file_path):
+ os.unlink(overrides_file_path)
+
+ # overwrites the file with our updated dictionary
+ with open(overrides_file_path, "wb+") as fd:
+ fd.write(json.dumps(overrides_data).encode('utf-8'))
+except Exception as e:
+ # logs any other error
+ logging.error(f'Error, unkown error when overwritng file {overrides_file_path}. Error message: {e}')
+ raise
+
+# logs informing override has finished successfully
+logging.info("Override file has been updated")
+
+# end
+```
+
+In the overrides command example, the Python script depends on the `backoff` library. To make sure the library is installed before executing the Python script, the `FUZZAPI_PRE_SCRIPT` is set to a script that will install the dependencies of your overrides command.
+As for example, the following script `user-pre-scan-set-up.sh`:
+
+```shell
+#!/bin/bash
+
+# user-pre-scan-set-up.sh
+# Ensures python dependencies are installed
+
+echo "**** install python dependencies ****"
+
+python3 -m ensurepip
+pip3 install --no-cache --upgrade \
+ pip \
+ backoff
+
+echo "**** python dependencies installed ****"
+
+# end
+```
+
+You have to update your configuration to set the `FUZZAPI_PRE_SCRIPT` to our new `user-pre-scan-set-up.sh` script. For example:
+
```yaml
stages:
- fuzz
@@ -820,11 +990,14 @@ variables:
FUZZAPI_PROFILE: Quick
FUZZAPI_OPENAPI: test-api-specification.json
FUZZAPI_TARGET_URL: http://test-deployment/
- FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_PRE_SCRIPT: user-pre-scan-set-up.sh
+ FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
FUZZAPI_OVERRIDES_CMD: renew_token.py
FUZZAPI_OVERRIDES_INTERVAL: 300
```
+In the previous sample, you could use the script `user-pre-scan-set-up.sh` to also install new runtimes or applications that later on you could use in your overrides command.
+
### Exclude Paths
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211892) in GitLab 14.0.
diff --git a/doc/user/application_security/cluster_image_scanning/index.md b/doc/user/application_security/cluster_image_scanning/index.md
index 5f2dd626526..0db9af7a0d3 100644
--- a/doc/user/application_security/cluster_image_scanning/index.md
+++ b/doc/user/application_security/cluster_image_scanning/index.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in GitLab 14.1.
WARNING:
-This analyzer is in [Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha)
+This analyzer is in [Alpha](../../../policy/alpha-beta-support.md#alpha-features)
and is unstable. The JSON report and CI/CD configuration may be subject to change or breakage
across GitLab releases.
@@ -301,7 +301,9 @@ the security vulnerabilities in your groups, projects, and pipelines.
## Interacting with the vulnerabilities
-After a vulnerability is found, you can [address it](../vulnerabilities/index.md).
+After you find a vulnerability, you can address it in the [vulnerability report](../vulnerabilities/index.md)
+or the [GitLab Agent's](../../clusters/agent/install/index.md#view-vulnerabilities-in-cluster-images)
+details section.
## Troubleshooting
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index cdcd334dba6..430f8e1a2a2 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -58,11 +58,11 @@ You can configure the following security controls:
- [API Fuzzing](../api_fuzzing/index.md)
- Select **Enable API Fuzzing** to use API Fuzzing for the current project. For more details, read [API Fuzzing](../../../user/application_security/api_fuzzing/index.md#enable-web-api-fuzzing).
- [Coverage Fuzzing](../coverage_fuzzing/index.md)
- - Can be configured with `.gitlab-ci.yml`. For more details, read [Coverage Fuzzing](../../../user/application_security/coverage_fuzzing/index.md#configuration).
+ - Can be configured with `.gitlab-ci.yml`. For more details, read [Coverage Fuzzing](../../../user/application_security/coverage_fuzzing/index.md#enable-coverage-guided-fuzz-testing).
## Compliance **(ULTIMATE)**
You can configure the following security controls:
- [License Compliance](../../../user/compliance/license_compliance/index.md)
- - Can be configured with `.gitlab-ci.yml`. For more details, read [License Compliance](../../../user/compliance/license_compliance/index.md#configuration).
+ - Can be configured with `.gitlab-ci.yml`. For more details, read [License Compliance](../../../user/compliance/license_compliance/index.md#enable-license-compliance).
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 5a2dd5eb54f..08a8c46cc72 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -222,6 +222,7 @@ You can [configure](#customizing-the-container-scanning-settings) analyzers by u
| `CS_DISABLE_DEPENDENCY_LIST` | `"false"` | Disable Dependency Scanning for packages installed in the scanned image. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6. | All |
| `CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` | `"true"` | Disable scanning for language-specific packages installed in the scanned image. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6. | All |
| `CS_DOCKER_INSECURE` | `"false"` | Allow access to secure Docker registries using HTTPS without validating the certificates. | All |
+| `CS_IGNORE_UNFIXED` | `"false"` | Ignore vulnerabilities that are not fixed. | All |
| `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. Works with all scanners, but the registry must listen on port `80/tcp` for Trivy to work. | All |
| `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 |
@@ -513,7 +514,7 @@ registry.gitlab.com/security-products/container-scanning/trivy:4
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
process by which you can import or temporarily access external resources. These scanners
-are [periodically updated](../vulnerabilities/index.md#vulnerability-scanner-maintenance),
+are [periodically updated](../index.md#vulnerability-scanner-maintenance),
and you may be able to make occasional updates on your own.
For more information, see [the specific steps on how to update an image with a pipeline](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline).
@@ -728,8 +729,16 @@ the security vulnerabilities in your groups, projects and pipelines.
## Vulnerabilities database update
-If you use container scanning and want more information about the vulnerabilities database update,
-see the [maintenance table](../vulnerabilities/index.md#vulnerability-scanner-maintenance).
+All analyzer images are [updated daily](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning/-/blob/master/README.md#image-updates).
+
+The images include the latest advisory database available for their respective scanner. Each
+scanner includes data from multiple sources:
+
+- [Grype](https://github.com/anchore/grype#grypes-database).
+- [Trivy](https://aquasecurity.github.io/trivy/latest/vulnerability/detection/data-source/).
+
+Database update information for other analyzers is available in the
+[maintenance table](../index.md#vulnerability-scanner-maintenance).
## Interacting with the vulnerabilities
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 89b4cdcc34d..290d4a06dcc 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -2,7 +2,6 @@
stage: Secure
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
---
# Coverage-guided fuzz testing **(ULTIMATE)**
@@ -23,8 +22,14 @@ The fuzz testing process:
1. Compiles the target application.
1. Runs the instrumented application, using the `gitlab-cov-fuzz` tool.
1. Parses and analyzes the exception information output by the fuzzer.
-1. Downloads the [corpus](../terminology/index.md#corpus) and crash events from previous pipelines.
+1. Downloads the [corpus](../terminology/index.md#corpus) from either:
+ - The previous pipelines.
+ - If `COVFUZZ_USE_REGISTRY` is set to `true`, the [corpus registry](#corpus-registry).
+1. Downloads crash events from previous pipeline.
1. Outputs the parsed crash events and data to the `gl-coverage-fuzzing-report.json` file.
+1. Updates the corpus, either:
+ - In the job's pipeline.
+ - If `COVFUZZ_USE_REGISTRY` is set to `true`, in the corpus registry.
The results of the coverage-guided fuzz testing are available in the CI/CD pipeline.
@@ -44,9 +49,20 @@ You can use the following fuzzing engines to test the specified languages.
| Python | [`pythonfuzz`](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/pythonfuzz) | [pythonfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/pythonfuzz-fuzzing-example) |
| AFL (any language that works on top of AFL) | [AFL](https://lcamtuf.coredump.cx/afl/) | [afl-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/afl-fuzzing-example) |
-## Configuration
+## Confirm status of coverage-guided fuzz testing
-To enable coverage-guided fuzz testing, edit the `.gitlab-ci.yml` file:
+To confirm the status of coverage-guided fuzz testing:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Security & Compliance > Configuration**.
+1. In the **Coverage Fuzzing** section the status is:
+ - **Not configured**
+ - **Enabled**
+ - A prompt to upgrade to GitLab Ultimate.
+
+## Enable coverage-guided fuzz testing
+
+To enable coverage-guided fuzz testing, edit `.gitlab-ci.yml`:
1. Add the `fuzz` stage to the list of stages.
@@ -99,10 +115,13 @@ Use the following variables to configure coverage-guided fuzz testing in your CI
| CI/CD variable | Description |
|---------------------------|---------------------------------------------------------------------------------|
-| `COVFUZZ_ADDITIONAL_ARGS` | Arguments passed to `gitlab-cov-fuzz`. Used to customize the behavior of the underlying fuzzing engine. Read the fuzzing engine's documentation for a complete list of arguments. |
+| `COVFUZZ_ADDITIONAL_ARGS` | Arguments passed to `gitlab-cov-fuzz`. Used to customize the behavior of the underlying fuzzing engine. Read the fuzzing engine's documentation for a complete list of arguments. |
| `COVFUZZ_BRANCH` | The branch on which long-running fuzzing jobs are to be run. On all other branches, only fuzzing regression tests are run. Default: Repository's default branch. |
| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. Default: empty. |
| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this value when using an offline environment. Default: `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
+| `COVFUZZ_USE_REGISTRY` | Set to `true` to have the corpus stored in the GitLab corpus registry. The variables `COVFUZZ_CORPUS_NAME` and `COVFUZZ_GITLAB_TOKEN` are required if this variable is set to `true`. Default: `false`. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
+| `COVFUZZ_CORPUS_NAME` | Name of the corpus to be used in the job. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
+| `COVFUZZ_GITLAB_TOKEN` | Environment variable configured with [Personal Access Token](../../../user/profile/personal_access_tokens.md#create-a-personal-access-token) with API read/write access. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
#### Seed corpus
@@ -123,9 +142,93 @@ Each fuzzing step outputs these artifacts:
You can download the JSON report file from the CI/CD pipelines page. For more information, see
[Downloading artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
-### Coverage-guided fuzz testing report
+## Corpus registry
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8.
+
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an
+administrator to [disable the feature flags](../../../administration/feature_flags.md) named
+`corpus_management` and `corpus_management_ui`. On GitLab.com, this feature is available.
+
+The corpus registry is a library of corpuses. Corpuses in a project's registry are available to
+all jobs in that project. A project-wide registry is a more efficient way to manage corpuses than
+the default option of one corpus per job.
+
+The corpus registry uses the package registry to store the project's corpuses. Corpuses stored in
+the registry are hidden to ensure data integrity.
+
+In the GitLab UI, with corpus management you can:
+
+- View details of the corpus registry.
+- Download a corpus.
+- Delete a corpus.
+- Create a new corpus.
+
+When you download a corpus, the file is named `artifacts.zip`, regardless of the filename used when
+the corpus was initially uploaded. This file contains only the corpus, which is different to the
+artifacts files you can download from the CI/CD pipeline.
+
+### View details of the corpus registry
+
+To view details of the corpus registry:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Security & Compliance > Configuration**.
+1. In the **Coverage Fuzzing** section, select **Manage corpus**.
+
+### Create a corpus in the corpus registry
+
+To create a corpus in the corpus registry, either:
+
+- Create a corpus in a pipeline
+- Upload an existing corpus file
+
+#### Create a corpus in a pipeline
+
+To create a corpus in a pipeline:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220062) in GitLab 13.3 as an [Alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
+1. In the `.gitlab-ci.yml` file, edit the `my_fuzz_target` job.
+1. Set the following variables:
+ - Set `COVFUZZ_USE_REGISTRY` to `true`.
+ - Set `COVFUZZ_CORPUS_NAME` to name the corpus.
+ - Set `COVFUZZ_GITLAB_TOKEN` to the value of the personal access token.
+
+After the `my_fuzz_target` job runs, the corpus is stored in the corpus registry, with the name
+provided by the `COVFUZZ_CORPUS_NAME` variable. The corpus is updated on every pipeline run.
+
+#### Upload a corpus file
+
+To upload an existing corpus file:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Security & Compliance > Configuration**.
+1. In the **Coverage Fuzzing** section, select **Manage corpus**.
+1. Select **New corpus**.
+1. Complete the fields.
+1. Select **Upload file**.
+1. Select **Add**.
+
+You can now reference the corpus in the `.gitlab-ci.yml` file. Ensure the value used in the
+`COVFUZZ_CORPUS_NAME` variable matches exactly the name given to the uploaded corpus file.
+
+### Use a corpus stored in the corpus registry
+
+To use a corpus stored in the corpus registry, you must reference it by its name. To confirm the
+name of the relevant corpus, view details of the corpus registry.
+
+Prerequisites:
+
+- [Enable coverage-guide fuzz testing](#enable-coverage-guided-fuzz-testing) in the project.
+
+1. Set the following variables in the `.gitlab-ci.yml` file:
+ - Set `COVFUZZ_USE_REGISTRY` to `true`.
+ - Set `COVFUZZ_CORPUS_NAME` to the name of the corpus.
+ - Set `COVFUZZ_GITLAB_TOKEN` to the value of the personal access token.
+
+## Coverage-guided fuzz testing report
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220062) in GitLab 13.3 as an [Alpha feature](../../../policy/alpha-beta-support.md#alpha-features).
For detailed information about the `gl-coverage-fuzzing-report.json` file's format, read the
[schema](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/coverage-fuzzing-report-format.json).
@@ -161,9 +264,9 @@ Example coverage-guided fuzzing report:
## Duration of coverage-guided fuzz testing
-The available durations for coverage-guided fuzz testing are: 10 minutes (default) and 60 minutes.
+The available durations for coverage-guided fuzz testing are:
-- 10-minute duration: Recommended for the default branch.
+- 10-minute duration (default): Recommended for the default branch.
- 60-minute duration: Recommended for the development branch and merge requests. The longer duration provides greater coverage.
In the `COVFUZZ_ADDITIONAL_ARGS` variable set the value `--regression=true`.
@@ -256,3 +359,16 @@ vulnerability:
engines listed in [Supported fuzzing engines and languages](#supported-fuzzing-engines-and-languages).
<!-- vale gitlab.Acronyms = YES -->
+
+## Troubleshooting
+
+### Error "Unable to extract corpus folder from artifacts zip file"
+
+If you see this error message, and `COVFUZZ_USE_REGISTRY` is set to `true`, ensure that the uploaded
+corpus file extracts into a folder named `corpus`.
+
+### Error "400 Bad request - Duplicate package is not allowed"
+
+If you see this error message when running the fuzzing job with `COVFUZZ_USE_REGISTRY` set to `true`,
+ensure that duplicates are allowed. For more details, see
+[duplicate Generic packages](../../packages/generic_packages/#do-not-allow-duplicate-generic-packages).
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index 5d1e57553f4..4cde1847419 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -10,7 +10,7 @@ type: reference, howto
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/323423) in GitLab 13.12.
WARNING:
-This product is in an early-access stage and is considered a [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta) feature.
+This product is in an early-access stage and is considered a [beta](../../../policy/alpha-beta-support.md#beta-features) feature.
GitLab DAST's new browser-based crawler is a crawl engine built by GitLab to test Single Page Applications (SPAs) and traditional web applications.
Due to the reliance of modern web applications on JavaScript, handling SPAs or applications that are dependent on JavaScript is paramount to ensuring proper coverage of an application for Dynamic Application Security Testing (DAST).
diff --git a/doc/user/application_security/dast/checks/1004.1.md b/doc/user/application_security/dast/checks/1004.1.md
index dfbc600b05b..9626973eb36 100644
--- a/doc/user/application_security/dast/checks/1004.1.md
+++ b/doc/user/application_security/dast/checks/1004.1.md
@@ -4,7 +4,7 @@ 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
---
-# Sensitive cookie without `HttpOnly` attribute
+# Sensitive cookie without HttpOnly attribute
## Description
diff --git a/doc/user/application_security/dast/checks/16.2.md b/doc/user/application_security/dast/checks/16.2.md
index 95461e8677d..484460b6642 100644
--- a/doc/user/application_security/dast/checks/16.2.md
+++ b/doc/user/application_security/dast/checks/16.2.md
@@ -38,7 +38,7 @@ the `Server` header.
## Links
-- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
- [Apache ServerTokens](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
- [NGINX server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens)
- [IIS 10 Remove Server Header](https://docs.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/#attributes)
diff --git a/doc/user/application_security/dast/checks/16.3.md b/doc/user/application_security/dast/checks/16.3.md
index 6f80a2a32c6..e4fc2468dae 100644
--- a/doc/user/application_security/dast/checks/16.3.md
+++ b/doc/user/application_security/dast/checks/16.3.md
@@ -32,4 +32,4 @@ information from the `X-Powered-By` header.
## Links
- [CWE](https://cwe.mitre.org/data/definitions/16.html)
-- [PHP `expose_php`](https://www.php.net/manual/en/ini.core.php#ini.expose-php)
+- [PHP expose_php](https://www.php.net/manual/en/ini.core.php#ini.expose-php)
diff --git a/doc/user/application_security/dast/checks/200.1.md b/doc/user/application_security/dast/checks/200.1.md
new file mode 100644
index 00000000000..98a482b4a0f
--- /dev/null
+++ b/doc/user/application_security/dast/checks/200.1.md
@@ -0,0 +1,29 @@
+---
+stage: Secure
+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
+---
+
+# Exposure of sensitive information to an unauthorized actor (private IP address)
+
+## Description
+
+A private RFC 1918 was identified in the target application. Public facing websites should not be issuing
+requests to private IP Addresses. Attackers attempting to execute subsequent attacks, such as Server-Side
+Request Forgery (SSRF), may be able to use this information to identify additional internal targets.
+
+## Remediation
+
+Identify the resource that is incorrectly specifying an internal IP address and replace it with it's public
+facing version, or remove the reference from the target application.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 200.1 | true | 200 | Passive | Low |
+
+## Links
+
+- [CWE](https://cwe.mitre.org/data/definitions/200.html)
+- [RFC](https://datatracker.ietf.org/doc/html/rfc1918)
diff --git a/doc/user/application_security/dast/checks/548.1.md b/doc/user/application_security/dast/checks/548.1.md
new file mode 100644
index 00000000000..94f747739c5
--- /dev/null
+++ b/doc/user/application_security/dast/checks/548.1.md
@@ -0,0 +1,45 @@
+---
+stage: Secure
+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
+---
+
+# Exposure of information through directory listing
+
+## Description
+
+The target web server is configured to list the contents of directories that do not contain an index file
+such as `index.html`. This could lead to accidental exposure of sensitive information, or give an attacker
+details on how filenames and directories are structured and stored.
+
+## Remediation
+
+Directory indexing should be disabled.
+
+Apache:
+For Apache based web sites, ensure all `<Directory>` definitions have `Options -Indexes` configured in the
+`apache2.conf` or `httpd.conf` configuration file.
+
+NGINX:
+For NGINX based websites, ensure all `location` definitions have the `autoindex off` directive set in the
+`nginx.conf` file.
+
+IIS:
+For IIS based websites version 7.0 and above you can use the `<directoryBrowse enabled="false" />` element
+in the `applicationHost.config` or `Web.config` files.
+
+For all other server types, please consult your product's documentation on how to disable directory
+indexing.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 548.1 | false | 548 | Passive | Low |
+
+## Links
+
+- [CWE](https://cwe.mitre.org/data/definitions/598.html)
+- [Apache Options](https://httpd.apache.org/docs/2.4/mod/core.html#options)
+- [NGINX autoindex](https://nginx.org/en/docs/http/ngx_http_autoindex_module.html)
+- [IIS directoryBrowse element](https://docs.microsoft.com/en-us/iis/configuration/system.webserver/directorybrowse)
diff --git a/doc/user/application_security/dast/checks/614.1.md b/doc/user/application_security/dast/checks/614.1.md
index 46f7f61b0c7..ec68ce33529 100644
--- a/doc/user/application_security/dast/checks/614.1.md
+++ b/doc/user/application_security/dast/checks/614.1.md
@@ -4,7 +4,7 @@ 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
---
-# Sensitive cookie without `Secure` attribute
+# Sensitive cookie without Secure attribute
## Description
@@ -35,6 +35,6 @@ Set-Cookie: {cookie_name}=<random secure value>; Secure
## Links
-- [owasp](https://owasp.org/www-community/controls/SecureCookieAttribute)
+- [OWASP](https://owasp.org/www-community/controls/SecureCookieAttribute)
- [CWE](https://cwe.mitre.org/data/definitions/614.html)
- [Mozilla MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
diff --git a/doc/user/application_security/dast/checks/index.md b/doc/user/application_security/dast/checks/index.md
index a3b89e09751..97224554723 100644
--- a/doc/user/application_security/dast/checks/index.md
+++ b/doc/user/application_security/dast/checks/index.md
@@ -10,12 +10,14 @@ The [DAST browser-based crawler](../browser_based.md) provides a number of vulne
| ID | Check | Severity | Type |
|:---|:------|:---------|:-----|
-| [1004.1](1004.1.md) | Sensitive cookie without `HttpOnly` attribute | Low | Passive |
+| [1004.1](1004.1.md) | Sensitive cookie without HttpOnly attribute | Low | Passive |
| [16.1](16.1.md) | Missing Content-Type header | Low | Passive |
| [16.2](16.2.md) | Server header exposes version information | Low | Passive |
| [16.3](16.3.md) | X-Powered-By header exposes version information | Low | Passive |
| [16.4](16.4.md) | X-Backend-Server header exposes server information | Info | Passive |
| [16.5](16.5.md) | AspNet header exposes version information | Low | Passive |
| [16.6](16.6.md) | AspNetMvc header exposes version information | Low | Passive |
-| [614.1](614.1.md) | Sensitive cookie without `Secure` attribute | Low | Passive |
+| [200.1](200.1.md) | Exposure of sensitive information to an unauthorized actor (private IP address) | Low | Passive |
+| [548.1](548.1.md) | Exposure of information through directory listing | Low | Passive |
+| [614.1](614.1.md) | Sensitive cookie without Secure attribute | Low | Passive |
| [693.1](693.1.md) | Missing X-Content-Type-Options: nosniff | Low | Passive |
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index aeaa93f4a85..0865cc10691 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -53,7 +53,7 @@ results. On failure, the analyzer outputs an
- [GitLab Runner](../../../ci/runners/index.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).
-- DAST runs in the `test` stage, which is available by default. If you redefine the stages in the `.gitlab-ci.yml` file, the `test` stage is required.
+- DAST runs in the `dast` stage, which must be added manually to your `.gitlab-ci.yml`.
### Deployment options
@@ -588,6 +588,28 @@ Using the [`DAST_MASK_HTTP_HEADERS` CI/CD variable](#available-cicd-variables),
headers whose values you want masked. For details on how to mask headers, see
[Customizing the DAST settings](#customize-dast-settings).
+#### Use Mutual TLS
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299596) in GitLab 14.8.
+
+Mutual TLS allows a target application server to verify that requests are from a known source. Browser-based scans do not support Mutual TLS.
+
+**Requirements**
+
+- Base64-encoded PKCS12 certificate
+- Password of the base64-encoded PKCS12 certificate
+
+To enable Mutual TLS:
+
+1. If the PKCS12 certificate is not already base64-encoded, convert it to base64 encoding. For security reasons, we recommend encoding the certificate locally, **not** using a web-hosted conversion service. For example, to encode the certificate on either macOS or Linux:
+
+ ```shell
+ base64 <path-to-pkcs12-certificate-file>
+ ```
+
+1. Create a [masked variable](../../../ci/variables/index.md) named `DAST_PKCS12_CERTIFICATE_BASE64` and store the base64-encoded PKCS12 certificate's value in that variable.
+1. Create a masked variable `DAST_PKCS12_PASSWORD` and store the PKCS12 certificate's password in that variable.
+
#### Available CI/CD variables
These CI/CD variables are specific to DAST. They can be used to customize the behavior of DAST to your requirements.
@@ -623,6 +645,8 @@ These CI/CD variables are specific to DAST. They can be used to customize the be
| `DAST_PASSWORD_FIELD` <sup>1,2</sup> | string | The selector of password field at the sign-in HTML form. Example: `id:password` |
| `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_PKCS12_CERTIFICATE_BASE64` | string | The PKCS12 certificate used for sites that require Mutual TLS. Must be encoded as base64 text. |
+| `DAST_PKCS12_PASSWORD` | string | The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. |
| `DAST_REQUEST_HEADERS` <sup>1</sup> | 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_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_SPIDER_MINS` <sup>1</sup> | 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. |
@@ -1172,7 +1196,7 @@ To edit an existing site profile:
1. Edit the fields then select **Save profile**.
If a site profile is linked to a security policy, a user cannot edit the profile from this page. See
-[Scan Execution Policies](../policies/index.md#scan-execution-policy-editor)
+[Scan execution policies](../policies/scan-execution-policies.md)
for more information.
#### Delete a site profile
@@ -1186,7 +1210,7 @@ To delete an existing site profile:
1. Select **Delete** to confirm the deletion.
If a site profile is linked to a security policy, a user cannot delete the profile from this page.
-See [Scan Execution Policies](../policies/index.md#scan-execution-policy-editor)
+See [Scan execution policies](../policies/scan-execution-policies.md)
for more information.
#### Validate a site profile
@@ -1329,7 +1353,7 @@ To edit a scanner profile:
1. Select **Save profile**.
If a scanner profile is linked to a security policy, a user cannot edit the profile from this page.
-See [Scan Execution Policies](../policies/index.md#scan-execution-policy-editor)
+See [Scan execution policies](../policies/scan-execution-policies.md)
for more information.
#### Delete a scanner profile
@@ -1343,7 +1367,7 @@ To delete a scanner profile:
1. Select **Delete**.
If a scanner profile is linked to a security policy, a user cannot delete the profile from this
-page. See [Scan Execution Policies](../policies/index.md#scan-execution-policy-editor)
+page. See [Scan execution policies](../policies/scan-execution-policies.md)
for more information.
## Auditing
@@ -1365,7 +1389,7 @@ The JSON report artifacts are not a public API of DAST and their format is expec
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).
+[DAST repository](https://gitlab.com/gitlab-org/security-products/dast/-/tree/main/test/end-to-end/expect).
## Optimizing DAST
diff --git a/doc/user/application_security/dast/run_dast_offline.md b/doc/user/application_security/dast/run_dast_offline.md
index 86621d73524..63163167a6c 100644
--- a/doc/user/application_security/dast/run_dast_offline.md
+++ b/doc/user/application_security/dast/run_dast_offline.md
@@ -36,7 +36,7 @@ For DAST, import the following default DAST analyzer image from `registry.gitlab
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
process by which external resources can be imported or temporarily accessed.
-These scanners are [periodically updated](../vulnerabilities/index.md#vulnerability-scanner-maintenance)
+These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
For details on saving and transporting Docker images as a file, see Docker's documentation on
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index f1eba505589..cc20b49764f 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -69,8 +69,8 @@ starting in GitLab 14.0, GitLab will not check your repository's root for config
### OpenAPI Specification
-> Support for OpenAPI Specification using YAML format was
-> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
+> - Support for OpenAPI Specification using YAML format was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
+> - Support to generate media type `application/xml` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327268) in GitLab 14.8.
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.
@@ -82,6 +82,7 @@ the body generation is limited to these body types:
- `application/x-www-form-urlencoded`
- `multipart/form-data`
- `application/json`
+- `application/xml`
Follow these steps to configure DAST API in GitLab with an OpenAPI specification:
@@ -478,6 +479,9 @@ Follow these steps to provide the bearer token with `DAST_API_OVERRIDES_ENV`:
`{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}}` (substitute your token). You
can create CI/CD variables from the GitLab projects page at **Settings > CI/CD**, in the
**Variables** section.
+ Due to the format of `TEST_API_BEARERAUTH` it's not possible to mask the variable.
+ To mask the token's value, you can create a second variable with the token value's, and define
+ `TEST_API_BEARERAUTH` with the value `{"headers":{"Authorization":"Bearer $MASKED_VARIABLE"}}`.
1. In your `.gitlab-ci.yml` file, set `DAST_API_OVERRIDES_ENV` to the variable you just created:
@@ -529,7 +533,7 @@ variables:
DAST_API_PROFILE: Quick
DAST_API_OPENAPI: test-api-specification.json
DAST_API_TARGET_URL: http://test-deployment/
- DAST_API_OVERRIDES_FILE: output/dast-api-overrides.json
+ DAST_API_OVERRIDES_FILE: dast-api-overrides.json
```
To validate that authentication is working, run an DAST API test and review the job logs and
@@ -571,13 +575,12 @@ variables:
DAST_API_PROFILE: Quick
DAST_API_OPENAPI: test-api-specification.json
DAST_API_TARGET_URL: http://test-deployment/
- DAST_API_OVERRIDES_FILE: output/dast-api-overrides.json
+ DAST_API_OVERRIDES_FILE: dast-api-overrides.json
DAST_API_OVERRIDES_CMD: renew_token.py
DAST_API_OVERRIDES_INTERVAL: 300
```
-To validate that authentication is working, run an DAST API test and review the job logs and
-the test API's application logs.
+To validate that authentication is working, run an DAST API test and review the job logs and the test API's application logs. See the [overrides section](#overrides) for more information about override commands.
### Configuration files
@@ -644,6 +647,9 @@ can be added, removed, and modified by creating a custom configuration.
|[`DAST_API_OVERRIDES_FILE`](#overrides) | Path to a JSON file containing overrides. |
|[`DAST_API_OVERRIDES_ENV`](#overrides) | JSON string containing headers to override. |
|[`DAST_API_OVERRIDES_CMD`](#overrides) | Overrides command. |
+|[`DAST_API_OVERRIDES_CMD_VERBOSE`](#overrides) | When set to any value. It shows overrides command output as part of the job output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.6. |
+|`DAST_API_PRE_SCRIPT` | Run user command or script before scan session starts. |
+|`DAST_API_POST_SCRIPT` | Run user command or script after scan session has finished. |
|[`DAST_API_OVERRIDES_INTERVAL`](#overrides) | How often to run overrides command in seconds. Defaults to `0` (once). |
|[`DAST_API_HTTP_USERNAME`](#http-basic-authentication) | Username for HTTP authentication. |
|[`DAST_API_HTTP_PASSWORD`](#http-basic-authentication) | Password for HTTP authentication. |
@@ -825,7 +831,7 @@ variables:
DAST_API_PROFILE: Quick
DAST_API_OPENAPI: test-api-specification.json
DAST_API_TARGET_URL: http://test-deployment/
- DAST_API_OVERRIDES_FILE: output/dast-api-overrides.json
+ DAST_API_OVERRIDES_FILE: dast-api-overrides.json
```
#### Using a CI/CD variable
@@ -869,17 +875,29 @@ variables:
#### Using a command
If the value must be generated or regenerated on expiration, you can provide a program or script for
-the DAST API scanner to execute on a specified interval. The provided script runs in an Alpine Linux
-container that has Python 3 and Bash installed. If the Python script requires additional packages,
-it must detect this and install the packages at runtime. The script creates the overrides JSON file
-as defined above.
+the DAST API scanner to execute on a specified interval. The provided command runs in an Alpine Linux
+container that has Python 3 and Bash installed.
+
+You have to set the environment variable `DAST_API_OVERRIDES_CMD` to the program or script you would like
+to execute. The provided command creates the overrides JSON file as defined previously.
+
+You might want to install other scripting runtimes like NodeJS or Ruby, or maybe you need to install a dependency for
+your overrides command. In this case, we recommend setting the `DAST_API_PRE_SCRIPT` to the file path of a script which
+provides those prerequisites. The script provided by `DAST_API_PRE_SCRIPT` is executed once, before the analyzer starts.
+
+See the [Alpine Linux package management](https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management)
+page for information about installing Alpine Linux packages.
You must provide three CI/CD variables, each set for correct operation:
- `DAST_API_OVERRIDES_FILE`: File generated by the provided command.
-- `DAST_API_OVERRIDES_CMD`: Command to generate JSON file.
+- `DAST_API_OVERRIDES_CMD`: Overrides command in charge of generating the overrides JSON file periodically.
- `DAST_API_OVERRIDES_INTERVAL`: Interval in seconds to run command.
+Optionally:
+
+- `DAST_API_PRE_SCRIPT`: Script to install runtimes or dependencies before the scan starts.
+
```yaml
stages:
- dast
@@ -891,11 +909,167 @@ variables:
DAST_API_PROFILE: Quick
DAST_API_OPENAPI: test-api-specification.json
DAST_API_TARGET_URL: http://test-deployment/
- DAST_API_OVERRIDES_FILE: output/dast-api-overrides.json
+ DAST_API_OVERRIDES_FILE: dast-api-overrides.json
DAST_API_OVERRIDES_CMD: renew_token.py
DAST_API_OVERRIDES_INTERVAL: 300
```
+#### Debugging overrides
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.8.
+
+By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `DAST_API_OVERRIDES_CMD_VERBOSE` to any value in order to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
+
+It is also possible to write messages from your script to a log file that is collected when the job completes or fails. The log file must be created in a specific location and following a naming convention.
+
+Adding some basic logging to your overrides script is useful in case the script fails unexpectedly during normal running of the job. The log file is automatically included as an artifact of the job, allowing you to download it after the job has finished.
+
+Following our example, we provided `renew_token.py` in the environment variable `DAST_API_OVERRIDES_CMD`. Please notice two things in the script:
+
+- Log file is saved in the location indicated by the environmental variable `CI_PROJECT_DIR`.
+- Log file name should match `gl-*.log`.
+
+```python
+#!/usr/bin/env python
+
+# Example of an overrides command
+
+# Override commands can update the overrides json file
+# with new values to be used. This is a great way to
+# update an authentication token that will expire
+# during testing.
+
+import logging
+import json
+import os
+import requests
+import backoff
+
+# [1] Store log file in directory indicated by env var CI_PROJECT_DIR
+working_directory = os.environ['CI_PROJECT_DIR']
+
+# [2] File name should match the pattern: gl-*.log
+log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')
+
+# Set up logger
+logging.basicConfig(filename=log_file_path, level=logging.DEBUG)
+
+# Use `backoff` decorator to retry in case of transient errors.
+@backoff.on_exception(backoff.expo,
+ (requests.exceptions.Timeout,
+ requests.exceptions.ConnectionError),
+ max_time=30)
+def get_auth_response():
+ return requests.get('https://authorization.service/api/get_api_token', auth=(os.environ['AUTH_USER'], os.environ['AUTH_PWD']))
+
+# In our example, access token is retrieved from a given endpoint
+try:
+
+ # Performs a http request, response sample:
+ # { "Token" : "b5638ae7-6e77-4585-b035-7d9de2e3f6b3" }
+ response = get_auth_response()
+
+ # Check that the request is successful. may raise `requests.exceptions.HTTPError`
+ response.raise_for_status()
+
+ # Gets JSON data
+ response_body = response.json()
+
+# If needed specific exceptions can be caught
+# requests.ConnectionError : A network connection error problem occurred
+# requests.HTTPError : HTTP request returned an unsuccessful status code. [Response.raise_for_status()]
+# requests.ConnectTimeout : The request timed out while trying to connect to the remote server
+# requests.ReadTimeout : The server did not send any data in the allotted amount of time.
+# requests.TooManyRedirects : The request exceeds the configured number of maximum redirections
+# requests.exceptions.RequestException : All exceptions that related to Requests
+except requests.exceptions.RequestException as requests_error:
+ # logs exceptions related to `Requests`
+ logging.error(f'Error, failed while performing HTTP request. Error message: {requests_error}')
+ raise
+except requests.exceptions.JSONDecodeError as json_decode_error:
+ # logs errors related decoding JSON response
+ logging.error(f'Error, failed while decoding JSON response. Error message: {json_decode_error}')
+ raise
+except Exception as e:
+ # logs any other error
+ logging.error(f'Error, unknown error while retrieving access token. Error message: {e}')
+ raise
+
+# computes object that holds overrides file content.
+# It uses data fetched from request
+overrides_data = {
+ "headers": {
+ "Authorization": f"Token {response_body['Token']}"
+ }
+}
+
+# log entry informing about the file override computation
+# the location of the overrides json file is also CI_PROJECT_DIR
+overrides_file_path = os.path.join(
+ working_directory, "dast-api-overrides.json")
+logging.info("Creating overrides file: %s" % overrides_file_path)
+
+# attempts to overwrite the file
+try:
+ if os.path.exists(overrides_file_path):
+ os.unlink(overrides_file_path)
+
+ # overwrites the file with our updated dictionary
+ with open(overrides_file_path, "wb+") as fd:
+ fd.write(json.dumps(overrides_data).encode('utf-8'))
+except Exception as e:
+ # logs any other error
+ logging.error(f'Error, unkown error when overwritng file {overrides_file_path}. Error message: {e}')
+ raise
+
+# logs informing override has finished successfully
+logging.info("Override file has been updated")
+
+# end
+```
+
+In the overrides command example, the Python script depends on the `backoff` library. To make sure the library is installed before executing the Python script, the `DAST_API_PRE_SCRIPT` is set to a script that will install the dependencies of your overrides command.
+As for example, the following script `user-pre-scan-set-up.sh`
+
+```shell
+#!/bin/bash
+
+# user-pre-scan-set-up.sh
+# Ensures python dependencies are installed
+
+echo "**** install python dependencies ****"
+
+python3 -m ensurepip
+pip3 install --no-cache --upgrade \
+ pip \
+ backoff
+
+echo "**** python dependencies installed ****"
+
+# end
+```
+
+You have to update your configuration to set the `DAST_API_PRE_SCRIPT` to our new `user-pre-scan-set-up.sh` script. For example:
+
+```yaml
+stages:
+ - dast
+
+include:
+ - template: DAST-API.gitlab-ci.yml
+
+variables:
+ DAST_API_PROFILE: Quick
+ DAST_API_OPENAPI: test-api-specification.json
+ DAST_API_TARGET_URL: http://test-deployment/
+ DAST_API_PRE_SCRIPT: user-pre-scan-set-up.sh
+ DAST_API_OVERRIDES_FILE: dast-api-overrides.json
+ DAST_API_OVERRIDES_CMD: renew_token.py
+ DAST_API_OVERRIDES_INTERVAL: 300
+```
+
+In the previous sample, you could use the script `user-pre-scan-set-up.sh` to also install new runtimes or applications that later on you could use in our overrides command.
+
### Exclude Paths
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211892) in GitLab 14.0.
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index 1b502b306bb..551488c0dc0 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -29,11 +29,16 @@ Dependency Scanning supports the following official analyzers:
The analyzers are published as Docker images, which Dependency Scanning uses
to launch dedicated containers for each analysis.
+The Dependency Scanning analyzers' current major version number is 2.
+
Dependency Scanning is pre-configured with a set of **default images** that are
maintained by GitLab, but users can also integrate their own **custom images**.
WARNING:
-The `bundler-audit` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#deprecation-of-bundler-audit-dependency-scanning-tool).
+The `bundler-audit` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#bundler-audit-dependency-scanning-tool).
+
+WARNING:
+The `retire.js` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#retire-js-dependency-scanning-tool).
## Official default analyzers
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index a8cc33d5545..a169b78a193 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -338,12 +338,12 @@ To support the following package managers, the GitLab analyzers proceed in two s
| Package Manager | Preinstalled Versions | Tested Versions |
| ------ | ------ | ------ |
| Bundler | [2.1.4](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit/-/blob/v2.11.3/Dockerfile#L15)<sup><b><a href="#exported-dependency-information-notes-1">1</a></b></sup> | [1.17.3](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/master/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
-| sbt | [1.3.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L4) | [1.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L263), [1.1.4](https://gitlab.com/gitlab-org/security-products/tests/scala-sbt-multiproject/-/blob/main/project/build.properties#L1), [1.1.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L272), [1.2.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L281), [1.3.12](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L290), [1.4.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L299) |
+| sbt | [1.6.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/config/.tool-versions#L4) | [1.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L330), [1.1.4](https://gitlab.com/gitlab-org/security-products/tests/scala-sbt-multiproject/-/blob/main/project/build.properties#L1), [1.1.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L339), [1.2.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L348), [1.3.12](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L357), [1.4.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L366), [1.6.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.24.6/.gitlab-ci.yml#L384) |
| Maven | [3.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L3) | [3.6.3](https://gitlab.com/gitlab-org/security-products/tests/java-maven/-/blob/master/pom.xml#L3) |
-| Gradle | [6.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L5) | [5.6.4](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/master/gradle/wrapper/gradle-wrapper.properties#L3), [6.5](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14/gradle/wrapper/gradle-wrapper.properties#L3), [6.7-rc-1](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-15/gradle/wrapper/gradle-wrapper.properties#L3), [6.9](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14-gradle-6-9/gradle/wrapper/gradle-wrapper.properties#L3), [7.0-rc-2](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-16/gradle/wrapper/gradle-wrapper.properties#L3) |
-| setuptools | [50.3.2](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L27) | [57.5.0](https://gitlab.com/gitlab-org/security-products/tests/python-setuptools/-/blob/main/setup.py) |
+| Gradle | [6.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L5) | [5.6.4](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/master/gradle/wrapper/gradle-wrapper.properties#L3), [6.5](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14/gradle/wrapper/gradle-wrapper.properties#L3), [6.7-rc-1](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-15/gradle/wrapper/gradle-wrapper.properties#L3), [6.9](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14-gradle-6-9/gradle/wrapper/gradle-wrapper.properties#L3), [7.0-rc-2](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-16/gradle/wrapper/gradle-wrapper.properties#L3) |
+| setuptools | [50.3.2](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L27) | [57.5.0](https://gitlab.com/gitlab-org/security-products/tests/python-setuptools/-/blob/main/setup.py) |
| pip | [20.2.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L26) | [20.x](https://gitlab.com/gitlab-org/security-products/tests/python-pip/-/blob/master/requirements.txt) |
-| Pipenv | [2018.11.26](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v2.18.4/requirements.txt#L13) | [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/pipfile-lock-FREEZE/Pipfile.lock#L6)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>, [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/master/Pipfile) |
+| Pipenv | [2018.11.26](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v2.18.4/requirements.txt#L13) | [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/pipfile-lock-FREEZE/Pipfile.lock#L6)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>, [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/master/Pipfile) |
<!-- markdownlint-disable MD044 -->
<ol>
@@ -389,7 +389,8 @@ The following analyzers are executed, each of which have different behavior when
Does not support multiple lockfiles. When multiple lockfiles exist, `bundler-audit`
analyzes the first lockfile discovered while traversing the directory tree in alphabetical order.
-We execute both analyzers because they use different sources of vulnerability data. The result is more comprehensive analysis than if only one was executed.
+WARNING:
+The `bundler-audit` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#bundler-audit-dependency-scanning-tool).
#### Python
@@ -418,6 +419,11 @@ The following analyzers are executed, each of which have different behavior when
Does not support multiple lockfiles. When multiple lockfiles exist, `Retire.js`
analyzes the first lockfile discovered while traversing the directory tree in alphabetical order.
+From GitLab 14.8 the `Gemnasium` analyzer scans supported JavaScript projects for vendored libraries
+(that is, those checked into the project but not managed by the package manager).
+
+WARNING:
+The `retire.js` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#retire-js-dependency-scanning-tool).
We execute both analyzers because they use different sources of vulnerability data. The result is more comprehensive analysis than if only one was executed.
#### PHP, Go, C, C++, .NET, C&#35;
@@ -547,7 +553,7 @@ The following variables allow configuration of global dependency scanning settin
The following variables are used for configuring specific analyzers (used for a specific language/framework).
| CI/CD variable | Analyzer | Default | Description |
-| ------------------------------------ | ------------------ | ---------------------------- |------------ |
+|--------------------------------------| ------------------ | ---------------------------- |------------ |
| `BUNDLER_AUDIT_UPDATE_DISABLED` | `bundler-audit` | `"false"` | Disable automatic updates for the `bundler-audit` analyzer. Use if you're running dependency scanning in an offline, air-gapped environment.|
| `BUNDLER_AUDIT_ADVISORY_DB_URL` | `bundler-audit` | `https://github.com/rubysec/ruby-advisory-db` | URL of the advisory database used by bundler-audit. |
| `BUNDLER_AUDIT_ADVISORY_DB_REF_NAME` | `bundler-audit` | `master` | Git ref for the advisory database specified by `BUNDLER_AUDIT_ADVISORY_DB_URL`. |
@@ -556,6 +562,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. |
+| `GEMNASIUM_LIBRARY_SCAN_ENABLED` | `gemnasium` | `"true"` | Enable detecting vulnerabilities in vendored JavaScript libraries. For now, `gemnasium` leverages [`Retire.js`](https://github.com/RetireJS/retire.js) to do this job. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350512) in GitLab 14.8. |
| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`, `15`, `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. |
@@ -565,11 +572,36 @@ The following variables are used for configuring specific analyzers (used for a
| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` | | Pip requirements file to be scanned. |
| `DS_PIP_VERSION` | `gemnasium-python` | | Force the install of a specific pip version (example: `"19.3"`), otherwise the pip installed in the Docker image is used. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) in GitLab 12.7) |
| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` | | Path to load Python pip dependencies from. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) in GitLab 12.2) |
-| `DS_PYTHON_VERSION` | `retire.js` | | Version of Python. If set to 2, dependencies are installed using Python 2.7 instead of Python 3.6. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12296) in GitLab 12.1, [removed](https://www.python.org/doc/sunset-python-2/) in GitLab 13.7). |
| `RETIREJS_JS_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json` | Path or URL to `retire.js` JS vulnerability data file. Note that if the URL hosting the data file uses a custom SSL certificate, for example in an offline installation, you can pass the certificate in the `ADDITIONAL_CA_CERT_BUNDLE` variable. |
| `RETIREJS_NODE_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/npmrepository.json` | Path or URL to `retire.js` node vulnerability data file. Note that if the URL hosting the data file uses a custom SSL certificate, for example in an offline installation, you can pass the certificate in the `ADDITIONAL_CA_CERT_BUNDLE` variable. |
| `RETIREJS_ADVISORY_DB_INSECURE` | `retire.js` | `false` | Enable fetching remote JS and Node vulnerability data files (defined by the `RETIREJS_JS_ADVISORY_DB` and `RETIREJS_NODE_ADVISORY_DB` variables) from hosts using an insecure or self-signed SSL (TLS) certificate. |
+#### Other variables
+
+The previous tables are not an exhaustive list of all variables that can be used. They contain all specific GitLab and analyzer variables we support and test. There are many variables, such as environment variables, that you can pass in and they will work. This is a large list, many of which we may be unaware of, and as such is not documented.
+
+For example, to pass the non-GitLab environment variable `HTTPS_PROXY` to all Dependency Scanning jobs,
+set it as a [custom CI/CD variable in your `.gitlab-ci.yml`](../../../ci/variables/#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file)
+file like this:
+
+```yaml
+variables:
+ HTTPS_PROXY: "https://squid-proxy:3128"
+```
+
+Alternatively we may use it in specific jobs, like Dependency Scanning:
+
+```yaml
+dependency_scanning:
+ variables:
+ HTTPS_PROXY: $HTTPS_PROXY
+```
+
+As we have not tested all variables you may find some will work and others will not.
+If one does not work and you need it we suggest
+[submitting a feature request](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal%20-%20detailed&issue[title]=Docs%20feedback%20-%20feature%20proposal:%20Write%20your%20title)
+or [contributing to the code](../../../development/index.md) to enable it to be used.
+
### 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. 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:
@@ -613,7 +645,7 @@ vulnerabilities in your groups, projects and pipelines. Read more about the
## Vulnerabilities database update
For more information about the vulnerabilities database update, see the
-[maintenance table](../vulnerabilities/index.md#vulnerability-scanner-maintenance).
+[maintenance table](../index.md#vulnerability-scanner-maintenance).
## Dependency List
@@ -735,6 +767,87 @@ Here's an example dependency scanning report:
}
```
+### CycloneDX reports
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350509) in GitLab 14.8 in [Beta](../../../policy/alpha-beta-support.md#beta-features).
+
+In addition to the [JSON report file](#reports-json-format), the [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium)
+Dependency Scanning tool outputs a [CycloneDX](https://cyclonedx.org/) report for
+each supported lock or build file it detects. These CycloneDX reports are named
+`cyclonedx-<package-type>-<package-manager>.json`, and are saved in the same directory
+as the detected lock or build files.
+
+For example, if your project has the following structure:
+
+```plaintext
+.
+├── ruby-project/
+│ └── Gemfile.lock
+├── ruby-project-2/
+│ └── Gemfile.lock
+├── php-project/
+│ └── composer.lock
+└── go-project/
+ └── go.sum
+```
+
+Then the Gemnasium scanner generates the following CycloneDX reports:
+
+```plaintext
+.
+├── ruby-project/
+│ ├── Gemfile.lock
+│ └── cyclonedx-gem-bundler.json
+├── ruby-project-2/
+│ ├── Gemfile.lock
+│ └── cyclonedx-gem-bundler.json
+├── php-project/
+│ ├── composer.lock
+│ └── cyclonedx-packagist-composer.json
+└── go-project/
+ ├── go.sum
+ └── cyclonedx-go-go.json
+```
+
+The CycloneDX reports can be downloaded [the same way as other job artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
+
+### Merging multiple CycloneDX Reports
+
+You can use a CI/CD job to merge multiple CycloneDX Reports into a single report.
+For example:
+
+```yaml
+stages:
+ - test
+ - merge-cyclonedx-reports
+
+include:
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+
+merge cyclonedx reports:
+ stage: merge-cyclonedx-reports
+ image: alpine:latest
+ script:
+ - wget https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.22.0/cyclonedx-linux-musl-x64 -O /usr/local/bin/cyclonedx-cli
+ - chmod 755 /usr/local/bin/cyclonedx-cli
+ - apk --update add --no-cache icu-dev libstdc++
+ - find * -name "cyclonedx-*.json" -exec cyclonedx-cli merge --input-files {} --output-file cyclonedx-all.json +
+ artifacts:
+ paths:
+ - cyclonedx-all.json
+```
+
+GitLab uses [CycloneDX Properties](https://cyclonedx.org/use-cases/#properties--name-value-store)
+to store implementation-specific details in the metadata of each CycloneDX report,
+such as the location of build and lock files. If multiple CycloneDX reports are merged together,
+this information is removed from the resulting merged file.
+
+NOTE:
+CycloneDX reports are a [Beta](../../../policy/alpha-beta-support.md#beta-features) feature,
+and the reports are subject to change during the beta period. Do not build integrations
+that rely on the format of these reports staying consistent, as the format might change
+before the feature is made generally available.
+
## Versioning and release process
Please check the [Release Process documentation](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md).
@@ -789,7 +902,7 @@ registry.gitlab.com/gitlab-org/security-products/analyzers/bundler-audit:2
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
process by which external resources can be imported or temporarily accessed.
-These scanners are [periodically updated](../vulnerabilities/index.md#vulnerability-scanner-maintenance)
+These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
For details on saving and transporting Docker images as a file, see Docker's documentation on
diff --git a/doc/user/application_security/iac_scanning/index.md b/doc/user/application_security/iac_scanning/index.md
index 4d5c1da3c47..89d3531bccd 100644
--- a/doc/user/application_security/iac_scanning/index.md
+++ b/doc/user/application_security/iac_scanning/index.md
@@ -36,9 +36,15 @@ GitLab IaC scanning supports a variety of IaC configuration files. Our IaC secur
|------------------------------------------|----------------------------------|-------------------------------|
| Ansible | [KICS](https://kics.io/) | 14.5 |
| AWS CloudFormation | [KICS](https://kics.io/) | 14.5 |
+| Azure Resource Manager <sup>1</sup> | [KICS](https://kics.io/) | 14.5 |
+| Dockerfile | [KICS](https://kics.io/) | 14.5 |
+| Google Deployment Manager | [KICS](https://kics.io/) | 14.5 |
| Kubernetes | [KICS](https://kics.io/) | 14.5 |
+| OpenAPI | [KICS](https://kics.io/) | 14.5 |
| Terraform | [KICS](https://kics.io/) | 14.5 |
+1. IaC scanning can analyze Azure Resource Manager templates in JSON format. If you write templates in the [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) language, you must use [the bicep CLI](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-cli) to convert your Bicep files into JSON before GitLab IaC scanning can analyze them.
+
### Making IaC analyzers available to all GitLab tiers
All open source (OSS) analyzers are available with the GitLab Free tier. Future proprietary analyzers may be restricted to higher tiers.
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index f5c727a1418..6a0b81335fd 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -2,7 +2,6 @@
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
---
# Secure your application **(ULTIMATE)**
@@ -46,6 +45,25 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
| [Coverage fuzzing](coverage_fuzzing/index.md) | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
| [Cluster Image Scanning](cluster_image_scanning/index.md) | Scan Kubernetes clusters for known vulnerabilities. |
+## 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) | A job runs on a daily basis to build new images with the latest vulnerability database updates from the upstream scanner. For more details, see [Vulnerabilities database update](container_scanning/index.md#vulnerabilities-database-update). |
+| [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 on a daily basis using [data from NVD, the `ruby-advisory-db` and the GitHub Security Advisory Database as data sources](https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/blob/master/SOURCES.md). 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/main/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. |
+
+In versions of GitLab that use the same major version of the analyzer, you do not have to update
+GitLab to benefit from the latest vulnerabilities definitions. The security tools are released as
+Docker images. The vendored job definitions that enable them use major release tags according to
+[semantic versioning](https://semver.org/). Each new release of the tools overrides these tags.
+Although in a major analyzer version you automatically get the latest versions of the scanning
+tools, there are some [known issues](https://gitlab.com/gitlab-org/gitlab/-/issues/9725) with this
+approach.
+
## Security scanning with Auto DevOps
To enable all GitLab Security scanning tools, with default settings, enable
@@ -98,10 +116,10 @@ base address for Docker images. You can override this globally by setting the CI
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
+### Use security scanning tools with merge request pipelines
By default, the application security jobs are configured to run for branch pipelines only.
-To use them with [pipelines for merge requests](../../ci/pipelines/merge_request_pipelines.md),
+To use them with [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md),
you may need to override the default `rules:` configuration to add:
```yaml
@@ -149,8 +167,8 @@ The artifact generated by the secure analyzer contains all findings it discovers
### All tiers
Merge requests which have run security scans let you know that the generated
-reports are available to download. To download a report, click on the
-**Download results** dropdown, and select the desired report.
+reports are available to download. To download a report, select
+**Download results**, and select the desired report.
![Security widget](img/security_widget_v13_7.png)
@@ -200,12 +218,17 @@ security issues:
### Vulnerability-Check rule
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](../../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](policies/#scan-result-policy-editor).
+
To prevent a merge request introducing a security vulnerability in a project, enable the
Vulnerability-Check rule. While this rule is enabled, additional merge request approval by
[eligible approvers](../project/merge_requests/approvals/rules.md#eligible-approvers)
is required when the latest security report in a merge request:
-- Contains vulnerabilities with states (for example, `previously detected`, `dismissed`) matching the rule's vulnerability states. Only `newly detected` will be considered if the target branch differs from the project default branch.
+- Contains vulnerabilities with states (for example, `previously detected`, `dismissed`) matching the rule's vulnerability states. Only `newly detected` are considered if the target branch differs from the project default branch.
- Contains vulnerabilities with severity levels (for example, `high`, `critical`, or `unknown`)
matching the rule's severity levels.
- Contains a vulnerability count higher than the rule allows.
@@ -218,7 +241,7 @@ An approval is optional when the security report:
the rule's severity levels.
- Contains a vulnerability count equal to or less than what the rule allows.
-Project members assigned [at least the Maintainer role](../permissions.md#project-members-permissions) can enable or edit
+Project members with at least the Maintainer role can enable or edit
the Vulnerability-Check rule.
#### Enable the Vulnerability-Check rule
@@ -451,28 +474,24 @@ GitLab provides two methods of accomplishing this, each with advantages and disa
- [Compliance framework pipelines](../project/settings/#compliance-pipeline-configuration)
are recommended when:
- - Scan execution enforcement is required for SAST IaC, Container Scanning, Dependency Scanning,
+ - Scan execution enforcement is required for SAST IaC, Dependency Scanning,
License Compliance, API Fuzzing, or Coverage-guided Fuzzing.
- - Scan execution enforcement of SAST or Secret Detection when customization of the default scan
- variables is required.
- Scan execution enforcement is required for scanners external to GitLab.
- Enforced execution is required for custom jobs other than security scans.
-- [Scan execution policies](policies/#scan-execution-policies)
+- [Scan execution policies](policies/scan-execution-policies.md)
are recommended when:
- - Scan execution enforcement is required for DAST.
- - Scan execution enforcement is required for SAST or Secret Detection with the default scan
- variables.
+ - Scan execution enforcement is required for DAST, SAST, Secret Detection, or Container Scanning.
- Scans are required to run on a regular, scheduled cadence.
Additional details about the differences between the two solutions are outlined below:
| | Compliance Framework Pipelines | Scan Execution Policies |
| ------ | ------ | ------ |
-| **Flexibility** | Supports anything that can be done in a CI file. | Limited to only the items for which GitLab has explicitly added support. DAST, SAST, and Secret Detection scans are supported. |
+| **Flexibility** | Supports anything that can be done in a CI file. | Limited to only the items for which GitLab has explicitly added support. DAST, SAST, Secret Detection, and Container Scanning scans are supported. |
| **Usability** | Requires knowledge of CI YAML. | Follows a `rules` and `actions`-based YAML structure. |
-| **Inclusion in CI pipeline** | The compliance pipeline is executed instead of the project's `gitlab-ci.yml` file. To include the project's `gitlab-ci.yml` file, use an `include` statement. Defined variables aren't allowed to be overwritten by the included project's YAML file. | Forced inclusion of a new job into the CI pipeline. DAST jobs that must be customized on a per-project basis can have project-level Site Profiles and Scan Profiles defined. To ensure separation of duties, these profiles are immutable when referenced in a scan execution policy. |
+| **Inclusion in CI pipeline** | The compliance pipeline is executed instead of the project's `gitlab-ci.yml` file. To include the project's `gitlab-ci.yml` file, use an `include` statement. Defined variables aren't allowed to be overwritten by the included project's YAML file. | Forced inclusion of a new job into the CI pipeline. DAST jobs that must be customized on a per-project basis can have project-level Site Profiles and Scan Profiles defined. To ensure separation of duties, these profiles are immutable when referenced in a scan execution policy. All jobs can be customized as part of the security policy itself with the same variables that are normally available to the CI job. |
| **Schedulable** | Can be scheduled through a scheduled pipeline on the group. | Can be scheduled natively through the policy configuration itself. |
| **Separation of Duties** | Only group owners can create compliance framework labels. Only project owners can apply compliance framework labels to projects. The ability to make or approve changes to the compliance pipeline definition is limited to individuals who are explicitly given access to the project that contains the compliance pipeline. | Only project owners can define a linked security policy project. The ability to make or approve changes to security policies is limited to individuals who are explicitly given access to the security policy project. |
| **Ability to apply one standard to multiple projects** | The same compliance framework label can be applied to multiple projects inside a group. | The same security policy project can be used for multiple projects across GitLab with no requirement of being located in the same group. |
diff --git a/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png b/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png
new file mode 100644
index 00000000000..57649c58d8b
--- /dev/null
+++ b/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png
Binary files differ
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 11f2b91177a..803f3983b96 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -17,8 +17,9 @@ can access these by navigating to your project's **Security & Compliance > Polic
GitLab supports the following security policies:
-- [Container Network Policy](#container-network-policy)
-- [Scan Execution Policy](#scan-execution-policy-schema)
+- [Scan Execution Policy](scan-execution-policies.md)
+- [Scan Result Policy](scan-result-policies.md)
+- [Container Network Policy](#container-network-policy) (DEPRECATED)
## Policy management
@@ -77,9 +78,62 @@ by the Rule mode, Rule mode is automatically
disabled. If the YAML is incorrect, you must use YAML
mode to fix your policy before Rule mode is available again.
+## Security Policies project
+
+NOTE:
+We recommend using the [Security Policies project](#security-policies-project)
+exclusively for managing policies for the project. Do not add your application's source code to such
+projects.
+
+The Security Policies feature is a repository to store policies. All security policies are stored in
+the `.gitlab/security-policies/policy.yml` YAML file. The format for this YAML is specific to the type of policy that is being stored there. Examples and schema information are available for the following policy types:
+
+- [Scan execution policy](scan-execution-policies.md#example-security-policies-project)
+- [Scan result policy](scan-result-policies.md#example-security-scan-result-policies-project)
+
+Policies created in this project are applied through a background job that runs once every 10
+minutes. Allow up to 10 minutes for any policy changes committed to this project to take effect.
+
+## Security Policy project selection
+
+NOTE:
+Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
+to select Security Policy Project.
+
+When the Security Policy project is created and policies are created within that repository, you
+must create an association between that project and the project you want to apply policies to:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Security & Compliance > Policies**.
+1. Select **Edit Policy Project**, and search for and select the
+ project you would like to link from the dropdown menu.
+1. Select **Save**.
+
+ ![Security Policy Project](img/security_policy_project_v14_6.png)
+
+### Unlink Security Policy projects
+
+Project owners can unlink Security Policy projects from development projects. To do this, follow
+the steps described in [Security Policy project selection](#security-policy-project-selection),
+but select the trash can icon in the modal.
+
+## Scan execution policies
+
+See [Scan execution policies](scan-execution-policies.md).
+
+## Scan result policy editor
+
+See [Scan result policies](scan-result-policies.md).
+
## Container Network Policy
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab 12.9.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Container Network Policy is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
The **Container Network Policy** section provides packet flow metrics for
your application's Kubernetes namespace. This section has the following
@@ -159,7 +213,7 @@ at the bottom of the editor.
You can use policy alerts to track your policy's impact. Alerts are only available if you've
[installed](../../clusters/agent/repository.md)
-and [configured](../../clusters/agent/install/index.md#register-an-agent-with-gitlab)
+and [configured](../../clusters/agent/install/index.md#register-the-agent-with-gitlab)
an agent for this project.
There are two ways to create policy alerts:
@@ -176,276 +230,7 @@ There are two ways to create policy alerts:
Once added, the UI updates and displays a warning about the dangers of too many alerts.
-## Security Policies project
-
-NOTE:
-We recommend using the [Security Policies project](#security-policies-project)
-exclusively for managing policies for the project. Do not add your application's source code to such
-projects.
-
-The Security Policies feature is a repository to store policies. All security policies are stored as
-the `.gitlab/security-policies/policy.yml` YAML file with this format:
-
-```yaml
----
-scan_execution_policy:
-- name: Enforce DAST in every pipeline
- description: This policy enforces pipeline configuration to have a job with DAST scan
- enabled: true
- rules:
- - type: pipeline
- branches:
- - master
- actions:
- - scan: dast
- scanner_profile: Scanner Profile A
- site_profile: Site Profile B
-- name: Enforce DAST in every pipeline in main branch
- description: This policy enforces pipeline configuration to have a job with DAST scan for main branch
- enabled: true
- rules:
- - type: pipeline
- branches:
- - main
- actions:
- - scan: dast
- scanner_profile: Scanner Profile C
- site_profile: Site Profile D
-```
-
-## Security Policy project selection
-
-NOTE:
-Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
-to select Security Policy Project.
-
-When the Security Policy project is created and policies are created within that repository, you
-must create an association between that project and the project you want to apply policies to:
-
-1. On the top bar, select **Menu > Projects** and find your project.
-1. On the left sidebar, select **Security & Compliance > Policies**.
-1. Select **Edit Policy Project**, and search for and select the
- project you would like to link from the dropdown menu.
-1. Select **Save**.
-
- ![Security Policy Project](img/security_policy_project_v14_6.png)
-
-### Unlink Security Policy projects
-
-Project owners can unlink Security Policy projects from development projects. To do this, follow
-the steps described in [Security Policy project selection](#security-policy-project-selection),
-but select the trash can icon in the modal.
-
-## Scan execution policies
-
-Project owners can use scan execution policies to require that security scans run on a specified
-schedule or with the project pipeline. Required scans are injected into the CI pipeline as new jobs
-with a long, random job name. In the unlikely event of a job name collision, the security policy job
-overwrites any pre-existing job in the pipeline.
-
-This feature has some overlap with [compliance framework pipelines](../../project/settings/#compliance-pipeline-configuration),
-as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
-For details on the similarities and differences between these features, see
-[Enforce scan execution](../#enforce-scan-execution).
-
-### Scan Execution Policy editor
-
-NOTE:
-Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
-to select Security Policy Project.
-
-Once your policy is complete, save it by selecting **Create via merge request**
-at the bottom of the editor. You are redirected to the merge request on the project's
-configured security policy project. If one does not link to your project, a security
-policy project is automatically created. Existing policies can also be
-removed from the editor interface by selecting **Delete policy**
-at the bottom of the editor.
-
-![Scan Execution Policy Editor YAML Mode](img/scan_execution_policy_yaml_mode_v14_7.png)
-
-The policy editor currently only supports the YAML mode. The Rule mode is tracked in the [Allow Users to Edit Rule-mode Scan Execution Policies in the Policy UI](https://gitlab.com/groups/gitlab-org/-/epics/5363) epic.
-
-### Scan Execution Policies Schema
-
-The YAML file with Scan Execution Policies consists of an array of objects matching Scan Execution Policy Schema nested under the `scan_execution_policy` key. You can configure a maximum of 5 policies under the `scan_execution_policy` key.
-
-When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json).
-If you're not familiar with how to read [JSON schemas](https://json-schema.org/),
-the following sections and tables provide an alternative.
-
-| Field | Type | Possible values | Description |
-|-------|------|-----------------|-------------|
-| `scan_execution_policy` | `array` of Scan Execution Policy | | List of scan execution policies (maximum 5) |
-
-### Scan Execution Policy Schema
-
-| Field | Type | Possible values | Description |
-|-------|------|-----------------|-------------|
-| `name` | `string` | | Name of the policy. |
-| `description` (optional) | `string` | | Description of the policy. |
-| `enabled` | `boolean` | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
-| `rules` | `array` of rules | | List of rules that the policy applies. |
-| `actions` | `array` of actions | | List of actions that the policy enforces. |
-
-### `pipeline` rule type
-
-This rule enforces the defined actions whenever the pipeline runs for a selected branch.
-
-| Field | Type | Possible values | Description |
-|-------|------|-----------------|-------------|
-| `type` | `string` | `pipeline` | The rule's type. |
-| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
-
-### `schedule` rule type
-
-This rule enforces the defined actions and schedules a scan on the provided date/time.
-
-| Field | Type | Possible values | Description |
-|------------|------|-----------------|-------------|
-| `type` | `string` | `schedule` | The rule's type. |
-| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
-| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. |
-| `clusters` | `object` | | The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. |
-
-#### `cluster` schema
-
-Use this schema to define `clusters` objects in the [`schedule` rule type](#schedule-rule-type).
-
-| Field | Type | Possible values | Description |
-|--------------|---------------------|--------------------------|-------------|
-| `containers` | `array` of `string` | | The container name that is scanned (only the first value is currently supported). |
-| `resources` | `array` of `string` | | The resource name that is scanned (only the first value is currently supported). |
-| `namespaces` | `array` of `string` | | The namespace that is scanned (only the first value is currently supported). |
-| `kinds` | `array` of `string` | `deployment`/`daemonset` | The resource kind that should be scanned (only the first value is currently supported). |
-
-### `scan` action type
-
-This action executes the selected `scan` with additional parameters when conditions for at least one
-rule in the defined policy are met.
-
-| Field | Type | Possible values | Description |
-|-------|------|-----------------|-------------|
-| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_scanning`, `cluster_image_scanning` | The action's type. |
-| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/index.md#site-profile). | The DAST site profile to execute the DAST scan. This field should only be set if `scan` type is `dast`. |
-| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/index.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. This field should only be set if `scan` type is `dast`.|
-| `variables` | `object` | | Set of variables applied and enforced for the selected scan. The object's key is the variable name with a value provided as a string. |
-
-Note the following:
-
-- You must create the [site profile](../dast/index.md#site-profile) and [scanner profile](../dast/index.md#scanner-profile)
- with selected names for each project that is assigned to the selected Security Policy Project.
- Otherwise, the policy is not applied and a job with an error message is created instead.
-- Once you associate the site profile and scanner profile by name in the policy, it is not possible
- to modify or delete them. If you want to modify them, you must first disable the policy by setting
- the `active` flag to `false`.
-- When configuring policies with a scheduled DAST scan, the author of the commit in the security
- policy project's repository must have access to the scanner and site profiles. Otherwise, the scan
- is not scheduled successfully.
-- For a secret detection scan, only rules with the default ruleset are supported. [Custom rulesets](../secret_detection/index.md#custom-rulesets)
- are not supported.
-- A secret detection scan runs in `normal` mode when executed as part of a pipeline, and in
- [`historic`](../secret_detection/index.md#full-history-secret-detection)
- mode when executed as part of a scheduled scan.
-- A container scanning and cluster image scanning scans configured for the `pipeline` rule type ignores the cluster defined in the `clusters` object.
- They use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type.
- Cluster with name provided in `clusters` object must be created and configured for the project. To be able to successfully perform the `container_scanning`/`cluster_image_scanning` scans for the cluster you must follow instructions for the [Cluster Image Scanning feature](../cluster_image_scanning/index.md#prerequisites).
-- The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/parent_child_pipelines.md).
-
-### Example security policies project
-
-You can use this example in a `.gitlab/security-policies/policy.yml`, as described in
-[Security policies project](#security-policies-project).
-
-```yaml
----
-scan_execution_policy:
-- name: Enforce DAST in every release pipeline
- description: This policy enforces pipeline configuration to have a job with DAST scan for release branches
- enabled: true
- rules:
- - type: pipeline
- branches:
- - release/*
- actions:
- - scan: dast
- scanner_profile: Scanner Profile A
- site_profile: Site Profile B
-- name: Enforce DAST and secret detection scans every 10 minutes
- description: This policy enforces DAST and secret detection scans to run every 10 minutes
- enabled: true
- rules:
- - type: schedule
- branches:
- - main
- cadence: "*/10 * * * *"
- actions:
- - scan: dast
- scanner_profile: Scanner Profile C
- site_profile: Site Profile D
- - scan: secret_detection
-- name: Enforce Secret Detection and Container Scanning in every default branch pipeline
- description: This policy enforces pipeline configuration to have a job with Secret Detection and Container Scanning scans for the default branch
- enabled: true
- rules:
- - type: pipeline
- branches:
- - main
- actions:
- - scan: secret_detection
- - scan: sast
- variables:
- SAST_EXCLUDED_ANALYZERS: brakeman
- - scan: container_scanning
-- name: Enforce Cluster Image Scanning on production-cluster every 24h
- description: This policy enforces Cluster Image Scanning scan to run every 24 hours
- enabled: true
- rules:
- - type: schedule
- cadence: "15 3 * * *"
- clusters:
- production-cluster:
- containers:
- - database
- resources:
- - production-application
- namespaces:
- - production-namespace
- kinds:
- - deployment
- actions:
- - scan: cluster_image_scanning
-```
-
-In this example:
-
-- For every pipeline executed on branches that match the `release/*` wildcard (for example, branch
- `release/v1.2.1`), DAST scans run with `Scanner Profile A` and `Site Profile B`.
-- DAST and secret detection scans run every 10 minutes. The DAST scan runs with `Scanner Profile C`
- and `Site Profile D`.
-- Secret detection, container scanning, and SAST scans run for every pipeline executed on the `main`
- branch. The SAST scan runs with the `SAST_EXCLUDED_ANALYZER` variable set to `"brakeman"`.
-- Cluster Image Scanning scan runs every 24h. The scan runs on the `production-cluster` cluster and fetches vulnerabilities
- from the container with the name `database` configured for deployment with the name `production-application` in the `production-namespace` namespace.
-
-### Example for scan execution policy editor
-
-You can use this example in the YAML mode of the [Scan Execution Policy editor](#scan-execution-policy-editor).
-It corresponds to a single object from the previous example.
-
-```yaml
-name: Enforce Secret Detection and Container Scanning in every default branch pipeline
-description: This policy enforces pipeline configuration to have a job with Secret Detection and Container Scanning scans for the default branch
-enabled: true
-rules:
- - type: pipeline
- branches:
- - main
-actions:
- - scan: secret_detection
- - scan: container_scanning
-```
-
## Roadmap
-See the [Category Direction page](https://about.gitlab.com/direction/protect/container_network_security/)
-for more information on the product direction of Container Network Security.
+See the [Category Direction page](https://about.gitlab.com/direction/protect/security_orchestration/)
+for more information on the product direction of security policies within GitLab.
diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md
new file mode 100644
index 00000000000..4e44162d5c5
--- /dev/null
+++ b/doc/user/application_security/policies/scan-execution-policies.md
@@ -0,0 +1,219 @@
+---
+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
+---
+
+# Scan execution policies **(ULTIMATE)**
+
+Project owners can use scan execution policies to require that security scans run on a specified
+schedule or with the project pipeline. Required scans are injected into the CI pipeline as new jobs
+with a long, random job name. In the unlikely event of a job name collision, the security policy job
+overwrites any pre-existing job in the pipeline.
+
+This feature has some overlap with [compliance framework pipelines](../../project/settings/#compliance-pipeline-configuration),
+as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
+For details on the similarities and differences between these features, see
+[Enforce scan execution](../#enforce-scan-execution).
+
+## Scan execution policy editor
+
+NOTE:
+Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
+to select Security Policy Project.
+
+Once your policy is complete, save it by selecting **Create via merge request**
+at the bottom of the editor. You are redirected to the merge request on the project's
+configured security policy project. If one does not link to your project, a security
+policy project is automatically created. Existing policies can also be
+removed from the editor interface by selecting **Delete policy**
+at the bottom of the editor.
+
+All scan execution policy changes are applied through a background job that runs once every 10
+minutes. Allow up to 10 minutes for any policy changes committed to this project to take effect.
+
+![Scan Execution Policy Editor YAML Mode](img/scan_execution_policy_yaml_mode_v14_7.png)
+
+The policy editor currently only supports the YAML mode. The Rule mode is tracked in the [Allow Users to Edit Rule-mode Scan Execution Policies in the Policy UI](https://gitlab.com/groups/gitlab-org/-/epics/5363) epic.
+
+## Scan execution policies schema
+
+The YAML file with scan execution policies consists of an array of objects matching scan execution
+policy schema nested under the `scan_execution_policy` key. You can configure a maximum of 5
+policies under the `scan_execution_policy` key.
+
+When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json).
+If you're not familiar with how to read [JSON schemas](https://json-schema.org/),
+the following sections and tables provide an alternative.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan_execution_policy` | `array` of scan execution policy | | List of scan execution policies (maximum 5) |
+
+## Scan execution policy schema
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `name` | `string` | | Name of the policy. |
+| `description` (optional) | `string` | | Description of the policy. |
+| `enabled` | `boolean` | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
+| `rules` | `array` of rules | | List of rules that the policy applies. |
+| `actions` | `array` of actions | | List of actions that the policy enforces. |
+
+## `pipeline` rule type
+
+This rule enforces the defined actions whenever the pipeline runs for a selected branch.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `type` | `string` | `pipeline` | The rule's type. |
+| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
+
+## `schedule` rule type
+
+This rule enforces the defined actions and schedules a scan on the provided date/time.
+
+| Field | Type | Possible values | Description |
+|------------|------|-----------------|-------------|
+| `type` | `string` | `schedule` | The rule's type. |
+| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
+| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. |
+| `clusters` | `object` | | The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. |
+
+### `cluster` schema
+
+Use this schema to define `clusters` objects in the [`schedule` rule type](#schedule-rule-type).
+
+| Field | Type | Possible values | Description |
+|--------------|---------------------|--------------------------|-------------|
+| `containers` | `array` of `string` | | The container name that is scanned (only the first value is currently supported). |
+| `resources` | `array` of `string` | | The resource name that is scanned (only the first value is currently supported). |
+| `namespaces` | `array` of `string` | | The namespace that is scanned (only the first value is currently supported). |
+| `kinds` | `array` of `string` | `deployment`/`daemonset` | The resource kind that should be scanned (only the first value is currently supported). |
+
+## `scan` action type
+
+This action executes the selected `scan` with additional parameters when conditions for at least one
+rule in the defined policy are met.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_scanning`, `cluster_image_scanning` | The action's type. |
+| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/index.md#site-profile). | The DAST site profile to execute the DAST scan. This field should only be set if `scan` type is `dast`. |
+| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/index.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. This field should only be set if `scan` type is `dast`.|
+| `variables` | `object` | | A set of CI variables, supplied as an array of `key: value` pairs, to apply and enforce for the selected scan. The `key` is the variable name, with its `value` provided as a string. This parameter supports any variable that the GitLab CI job supports for the specified scan. |
+
+Note the following:
+
+- You must create the [site profile](../dast/index.md#site-profile) and [scanner profile](../dast/index.md#scanner-profile)
+ with selected names for each project that is assigned to the selected Security Policy Project.
+ Otherwise, the policy is not applied and a job with an error message is created instead.
+- Once you associate the site profile and scanner profile by name in the policy, it is not possible
+ to modify or delete them. If you want to modify them, you must first disable the policy by setting
+ the `active` flag to `false`.
+- When configuring policies with a scheduled DAST scan, the author of the commit in the security
+ policy project's repository must have access to the scanner and site profiles. Otherwise, the scan
+ is not scheduled successfully.
+- For a secret detection scan, only rules with the default ruleset are supported. [Custom rulesets](../secret_detection/index.md#custom-rulesets)
+ are not supported.
+- A secret detection scan runs in `normal` mode when executed as part of a pipeline, and in
+ [`historic`](../secret_detection/index.md#full-history-secret-detection)
+ mode when executed as part of a scheduled scan.
+- A container scanning and cluster image scanning scans configured for the `pipeline` rule type ignores the cluster defined in the `clusters` object.
+ They use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type.
+ Cluster with name provided in `clusters` object must be created and configured for the project. To be able to successfully perform the `container_scanning`/`cluster_image_scanning` scans for the cluster you must follow instructions for the [Cluster Image Scanning feature](../cluster_image_scanning/index.md#prerequisites).
+- The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/parent_child_pipelines.md).
+
+## Example security policies project
+
+You can use this example in a `.gitlab/security-policies/policy.yml`, as described in
+[Security policies project](index.md#security-policies-project).
+
+```yaml
+---
+scan_execution_policy:
+- name: Enforce DAST in every release pipeline
+ description: This policy enforces pipeline configuration to have a job with DAST scan for release branches
+ enabled: true
+ rules:
+ - type: pipeline
+ branches:
+ - release/*
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile A
+ site_profile: Site Profile B
+- name: Enforce DAST and secret detection scans every 10 minutes
+ description: This policy enforces DAST and secret detection scans to run every 10 minutes
+ enabled: true
+ rules:
+ - type: schedule
+ branches:
+ - main
+ cadence: "*/10 * * * *"
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile C
+ site_profile: Site Profile D
+ - scan: secret_detection
+- name: Enforce Secret Detection and Container Scanning in every default branch pipeline
+ description: This policy enforces pipeline configuration to have a job with Secret Detection and Container Scanning scans for the default branch
+ enabled: true
+ rules:
+ - type: pipeline
+ branches:
+ - main
+ actions:
+ - scan: secret_detection
+ - scan: sast
+ variables:
+ SAST_EXCLUDED_ANALYZERS: brakeman
+ - scan: container_scanning
+- name: Enforce Cluster Image Scanning on production-cluster every 24h
+ description: This policy enforces Cluster Image Scanning scan to run every 24 hours
+ enabled: true
+ rules:
+ - type: schedule
+ cadence: "15 3 * * *"
+ clusters:
+ production-cluster:
+ containers:
+ - database
+ resources:
+ - production-application
+ namespaces:
+ - production-namespace
+ kinds:
+ - deployment
+ actions:
+ - scan: cluster_image_scanning
+```
+
+In this example:
+
+- For every pipeline executed on branches that match the `release/*` wildcard (for example, branch
+ `release/v1.2.1`), DAST scans run with `Scanner Profile A` and `Site Profile B`.
+- DAST and secret detection scans run every 10 minutes. The DAST scan runs with `Scanner Profile C`
+ and `Site Profile D`.
+- Secret detection, container scanning, and SAST scans run for every pipeline executed on the `main`
+ branch. The SAST scan runs with the `SAST_EXCLUDED_ANALYZER` variable set to `"brakeman"`.
+- Cluster Image Scanning scan runs every 24h. The scan runs on the `production-cluster` cluster and fetches vulnerabilities
+ from the container with the name `database` configured for deployment with the name `production-application` in the `production-namespace` namespace.
+
+## Example for scan execution policy editor
+
+You can use this example in the YAML mode of the [scan execution policy editor](#scan-execution-policy-editor).
+It corresponds to a single object from the previous example.
+
+```yaml
+name: Enforce Secret Detection and Container Scanning in every default branch pipeline
+description: This policy enforces pipeline configuration to have a job with Secret Detection and Container Scanning scans for the default branch
+enabled: true
+rules:
+ - type: pipeline
+ branches:
+ - main
+actions:
+ - scan: secret_detection
+ - scan: container_scanning
+```
diff --git a/doc/user/application_security/policies/scan-result-policies.md b/doc/user/application_security/policies/scan-result-policies.md
new file mode 100644
index 00000000000..7857de8c780
--- /dev/null
+++ b/doc/user/application_security/policies/scan-result-policies.md
@@ -0,0 +1,175 @@
+---
+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
+---
+
+# Scan result policies **(ULTIMATE)**
+
+You can use scan result policies to take action based on scan results. For example, one type of scan
+result policy is a security approval policy that allows approval to be required based on the
+findings of one or more security scan jobs. Scan result policies are evaluated after a CI scanning
+job is fully executed.
+
+## Scan result policy editor
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77814) in GitLab 14.8 with a flag named `scan_result_policy`. Disabled by default.
+
+NOTE:
+Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
+to select Security Policy Project.
+
+Once your policy is complete, save it by selecting **Create merge request** at the bottom of the
+editor. This redirects you to the merge request on the project's configured security policy project.
+If a security policy project doesn't link to your project, GitLab creates such a project for you.
+Existing policies can also be removed from the editor interface by selecting **Delete policy** at
+the bottom of the editor.
+
+All scan result policy changes are applied through a background job that runs once every 10 minutes.
+Allow up to 10 minutes for any policy changes committed to this project to take effect.
+
+The policy editor only supports YAML mode. To follow work on Rule mode, see the epic
+[Allow Users to Edit Rule-mode scan result policies in the Policy UI](https://gitlab.com/groups/gitlab-org/-/epics/5363).
+
+![Scan Result Policy Editor YAML Mode](img/scan_result_policy_yaml_mode_v14_6.png)
+
+## Scan result policies schema
+
+The YAML file with scan result policies consists of an array of objects matching the scan result
+policy schema nested under the `scan_result_policy` key. You can configure a maximum of five
+policies under the `scan_result_policy` key.
+
+When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json).
+If you're not familiar with how to read [JSON schemas](https://json-schema.org/),
+the following sections and tables provide an alternative.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan_result_policy` | `array` of Scan Result Policy | | List of scan result policies (maximum 5). |
+
+## Scan result policy schema
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `name` | `string` | | Name of the policy. |
+| `description` (optional) | `string` | | Description of the policy. |
+| `enabled` | `boolean` | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
+| `rules` | `array` of rules | | List of rules that the policy applies. |
+| `actions` | `array` of actions | | List of actions that the policy enforces. |
+
+## `scan_finding` rule type
+
+This rule enforces the defined actions based on the information provided.
+
+| Field | Type | Possible values | Description |
+|------------|------|-----------------|-------------|
+| `type` | `string` | `scan_finding` | The rule's type. |
+| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
+| `scanners` | `array` of `string` | `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing` | The security scanners for this rule to consider. |
+| `vulnerabilities_allowed` | `integer` | Greater than or equal to zero | Number of vulnerabilities allowed before this rule is considered. |
+| `severity_levels` | `array` of `string` | `info`, `unknown`, `low`, `medium`, `high`, `critical`| The severity levels for this rule to consider. |
+| `vulnerability_states` | `array` of `string` | `newly_detected`, `detected`, `confirmed`, `resolved`, `dismissed` | The vulnerability states for this rule to consider when the target branch is set to the default branch. |
+
+## `require_approval` action type
+
+This action sets an approval rule to be required when conditions are met for at least one rule in
+the defined policy.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `type` | `string` | `require_approval` | The action's type. |
+| `approvals_required` | `integer` | Greater than or equal to zero | The number of MR approvals required. |
+| `user_approvers` | `array` of `string` | Username of one of more users | The users to consider as approvers. |
+| `user_approvers_ids` | `array` of `integer` | ID of one of more users | The IDs of users to consider as approvers. |
+| `group_approvers` | `array` of `string` | Path of one of more groups | The groups to consider as approvers. |
+| `group_approvers_ids` | `array` of `integer` | ID of one of more groups | The IDs of groups to consider as approvers. |
+
+Requirements and limitations:
+
+- You must add the respective [security scanning tools](../index.md#security-scanning-tools).
+ Otherwise, scan result policies won't have any effect.
+- The maximum number of policies is five.
+- Each policy can have a maximum of five rules.
+
+## Example security scan result policies project
+
+You can use this example in a `.gitlab/security-policies/policy.yml`, as described in
+[Security policies project](index.md#security-policies-project):
+
+```yaml
+---
+scan_result_policy:
+- name: critical vulnerability CS approvals
+ description: critical severity level only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 0
+ severity_levels:
+ - critical
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - adalberto.dare
+- name: secondary CS approvals
+ description: secondary only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - low
+ - unknown
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - sam.white
+```
+
+In this example:
+
+- Every MR that contains new `critical` vulnerabilities identified by container scanning requires
+ one approval from `alberto.dare`.
+- Every MR that contains more than one new `low` or `unknown` vulnerability identified by container
+ scanning requires one approval from `sam.white`.
+
+## Example for Scan Result Policy editor
+
+You can use this example in the YAML mode of the [Scan Result Policy editor](#scan-result-policy-editor).
+It corresponds to a single object from the previous example:
+
+```yaml
+- name: critical vulnerability CS approvals
+ description: critical severity level only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - critical
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - adalberto.dare
+```
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index de2f9af82c7..3c0a2caf114 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -288,12 +288,14 @@ brakeman-sast:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8.
You can customize the default scanning rules provided by our SAST analyzers.
-Ruleset customization supports two capabilities that can be used
+Ruleset customization supports the following that can be used
simultaneously:
- [Disabling predefined rules](index.md#disable-predefined-analyzer-rules). Available for all analyzers.
+- [Overriding predefined rules](index.md#override-predefined-analyzer-rules). Available for all analyzers.
- Modifying the default behavior of a given analyzer by [synthesizing and passing a custom configuration](index.md#synthesize-a-custom-configuration). Available for only `nodejs-scan`, `gosec`, and `semgrep`.
To customize the default scanning rules, create a file containing custom rules. These rules
@@ -343,6 +345,50 @@ and `sobelow` by matching the `type` and `value` of identifiers:
value = "sql_injection"
```
+#### Override predefined analyzer rules
+
+To override analyzer rules:
+
+1. In one or more `ruleset.identifier` subsections, list the rules that you want to override. Every `ruleset.identifier` section has:
+
+ - a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
+ - a `value` field, to name the rule to be overridden.
+
+1. In the `ruleset.override` context of a `ruleset` section,
+ provide the keys to override. Any combination of keys can be
+ overridden. Valid keys are:
+
+ - description
+ - message
+ - name
+ - severity (valid options are: Critical, High, Medium, Low, Unknown, Info)
+
+##### Example: Override predefined rules of SAST analyzers
+
+In the following example, rules from `eslint`
+and `gosec` are matched by the `type` and `value` of identifiers and
+then overridden:
+
+```toml
+[eslint]
+ [[eslint.ruleset]]
+ [eslint.ruleset.identifier]
+ type = "eslint_rule_id"
+ value = "security/detect-object-injection"
+ [eslint.ruleset.override]
+ description = "OVERRIDDEN description"
+ message = "OVERRIDDEN message"
+ name = "OVERRIDDEN name"
+ severity = "Critical"
+[gosec]
+ [[gosec.ruleset]]
+ [gosec.ruleset.identifier]
+ type = "CWE"
+ value = "CWE-79"
+ [gosec.ruleset.override]
+ severity = "Critical"
+```
+
#### Synthesize a custom configuration
To create a custom configuration, you can use passthrough chains.
@@ -639,15 +685,33 @@ variables:
### Pre-compilation
-If your project requires custom build configurations, it can be preferable to avoid
-compilation during your SAST execution and instead pass all job artifacts from an
-earlier stage in the pipeline. This is the current strategy when requiring
-a `before_script` execution to prepare your scan job.
+Most GitLab SAST analyzers directly scan your source code without compiling it first.
+However, for technical reasons, some analyzers can only scan compiled code.
+
+By default, these analyzers automatically attempt to fetch dependencies and compile your code so it can be scanned.
+Automatic compilation can fail if:
+
+- your project requires custom build configurations.
+- you use language versions that aren't built into the analyzer.
+
+To resolve these issues, you can skip the analyzer's compilation step and directly provide artifacts from an earlier stage in your pipeline instead.
+This strategy is called _pre-compilation_.
+
+Pre-compilation is available for the analyzers that support the `COMPILE` CI/CD variable.
+See [Analyzer settings](#analyzer-settings) for the current list.
+
+To use pre-compilation:
+
+1. Output your project's dependencies to a directory in the project's working directory, then save that directory as an artifact by [setting the `artifacts: paths` configuration](../../../ci/yaml/index.md#artifactspaths).
+1. Provide the `COMPILE: "false"` CI/CD variable to the analyzer to disable automatic compilation.
+1. Add your compilation stage as a dependency for the analyzer job.
+
+To allow the analyzer to recognize the compiled artifacts, you must explicitly specify the path to
+the vendored directory.
+This configuration can vary per analyzer. For Maven projects, you can use `MAVEN_REPO_PATH`.
+See [Analyzer settings](#analyzer-settings) for the complete list of available options.
-To pass your project's dependencies as artifacts, the dependencies must be included
-in the project's working directory and specified using the `artifacts:path` configuration.
-If all dependencies are present, the `COMPILE=false` CI/CD variable can be provided to the
-analyzer and compilation is skipped:
+The following example pre-compiles a Maven project and provides it to the SpotBugs SAST analyzer:
```yaml
stages:
@@ -678,11 +742,6 @@ spotbugs-sast:
sast: gl-sast-report.json
```
-To allow the analyzer to recognize the compiled artifacts, you must explicitly specify the path to
-the vendored directory. This configuration can vary per analyzer but in the case of Java above, you
-can use `MAVEN_REPO_PATH`. See
-[Analyzer settings](#analyzer-settings) for the complete list of available options.
-
### Available CI/CD variables
SAST can be configured using the [`variables`](../../../ci/yaml/index.md#variables) parameter in
@@ -779,7 +838,7 @@ Some analyzers can be customized with CI/CD variables.
| `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 | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64025)** in GitLab 13.5 |
-| `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. |
+| `SAST_SEMGREP_METRICS` | Semgrep | Set to `"false"` to disable sending anonymized scan metrics to [r2c](https://r2c.dev/). Default: `true`. Introduced in GitLab 14.0 from the [confidential issue](../../project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab/-/issues/330565`. |
#### Custom CI/CD variables
@@ -819,86 +878,18 @@ variables:
## Reports JSON format
-The SAST tool emits a JSON report file. For more information, see the
-[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json).
-
-The JSON report file can be downloaded from the CI pipelines page, or the
-pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/yaml/index.md#artifactspaths) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
-
-Here's an example SAST report:
-
-```json-doc
-{
- "version": "2.0",
- "vulnerabilities": [
- {
- "id": "9e96e0ab-23da-4d7d-a09e-0acbaa5e83ca",
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "description": "The use of java.util.Random is predictable",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
- "file": "groovy/src/main/groovy/com/gitlab/security_products/tests/App.groovy",
- "start_line": 47,
- "end_line": 47,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken2",
- "dependency": {
- "package": {}
- }
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- },
- {
- "type": "cwe",
- "name": "CWE-330",
- "value": "330",
- "url": "https://cwe.mitre.org/data/definitions/330.html"
- }
- ]
- },
- {
- "id": "e6dbf91f-4c07-46f7-a365-0169489c27d1",
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 10,
- "end_line": 10,
- "dependency": {
- "package": {}
- }
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ]
- },
- ],
- "remediations": []
-}
-```
+SAST outputs a report file in JSON format. The report file contains details of all found vulnerabilities.
+To download the report file, you can either:
+
+- Download the file from the CI/CD pipelines page.
+- In the pipelines tab on merge requests, set [`artifacts: paths`](../../../ci/yaml/index.md#artifactspaths) to `gl-sast-report.json`.
+
+For information, see [Download job artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
+
+For details of the report file's schema, see
+[SAST report file schema](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json).
+
+For an example SAST report file, see [`gl-secret-detection-report.json`](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/master/qa/expect/secrets/gl-secret-detection-report.json) example.
## Running SAST in an offline environment
@@ -945,7 +936,7 @@ registry.gitlab.com/security-products/sast/spotbugs:2
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
-process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../vulnerabilities/index.md#vulnerability-scanner-maintenance)
+process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
For details on saving and transporting Docker images as a file, see Docker's documentation on
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index c5761a5743f..2ce2d59898f 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -63,7 +63,7 @@ as shown in the following table:
| [Configure Secret Detection Scanners](#configuration) | **{check-circle}** | **{check-circle}** |
| [Customize Secret Detection Settings](#customizing-settings) | **{check-circle}** | **{check-circle}** |
| View [JSON Report](../sast/index.md#reports-json-format) | **{check-circle}** | **{check-circle}** |
-| Presentation of JSON Report in Merge Request | **{dotted-circle}** | **{check-circle}** |
+| Presentation of JSON Report in merge request | **{dotted-circle}** | **{check-circle}** |
| View identified secrets in the pipelines' **Security** tab | **{dotted-circle}** | **{check-circle}** |
| [Interaction with Vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
| [Access to Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
@@ -182,14 +182,89 @@ Secret Detection can be customized by defining available CI/CD variables:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8.
You can customize the default secret detection rules provided with GitLab.
+Ruleset customization supports the following capabilities that can be used
+simultaneously:
+
+- [Disabling predefined rules](index.md#disable-predefined-analyzer-rules).
+- [Overriding predefined rules](index.md#override-predefined-analyzer-rules).
+- Modifying the default behavior of the Secret Detection analyzer by [synthesizing and passing a custom configuration](index.md#synthesize-a-custom-configuration). Available for only `nodejs-scan`, `gosec`, and `semgrep`.
+
Customization allows replacing the default secret detection rules with rules that you define.
To create a custom ruleset:
1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist.
1. Create a custom ruleset file named `secret-detection-ruleset.toml` in the `.gitlab` directory.
+
+#### Disable predefined analyzer rules
+
+To disable analyzer rules:
+
+1. Set the `disabled` flag to `true` in the context of a `ruleset` section.
+
+1. In one or more `ruleset.identifier` subsections, list the rules that you want disabled. Every `ruleset.identifier` section has:
+
+ - a `type` field, to name the predefined rule identifier.
+ - a `value` field, to name the rule to be disabled.
+
+##### Example: Disable predefined rules of Secret Detection analyzer
+
+In the following example, the disabled rules is assigned to `secrets`
+by matching the `type` and `value` of identifiers:
+
+```toml
+[secrets]
+ [[secrets.ruleset]]
+ disable = true
+ [secrets.ruleset.identifier]
+ type = "gitleaks_rule_id"
+ value = "RSA private key"
+```
+
+#### Override predefined analyzer rules
+
+To override rules:
+
+1. In one or more `ruleset.identifier` subsections, list the rules that you want to override. Every `ruleset.identifier` section has:
+
+ - a `type` field, to name the predefined rule identifier that the Secret Detection analyzer uses.
+ - a `value` field, to name the rule to be overridden.
+
+1. In the `ruleset.override` context of a `ruleset` section,
+ provide the keys to override. Any combination of keys can be
+ overridden. Valid keys are:
+
+ - description
+ - message
+ - name
+ - severity (valid options are: Critical, High, Medium, Low, Unknown, Info)
+
+##### Example: Override predefined rules of Secret Detection analyzer
+
+In the following example, rules
+are matched by the `type` and `value` of identifiers and
+then overridden:
+
+```toml
+[secrets]
+ [[secrets.ruleset]]
+ [secrets.ruleset.identifier]
+ type = "gitleaks_rule_id"
+ value = "RSA private key"
+ [secrets.ruleset.override]
+ description = "OVERRIDDEN description"
+ message = "OVERRIDDEN message"
+ name = "OVERRIDDEN name"
+ severity = "Info"
+```
+
+#### Synthesize a custom configuration
+
+To create a custom configuration, you can use passthrough chains.
+
1. In the `secret-detection-ruleset.toml` file, do one of the following:
- Define a custom ruleset:
@@ -239,31 +314,8 @@ From highest to lowest severity, the logging levels are:
## Post-processing and revocation
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
-
-Upon detection of a secret, GitLab supports post-processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
-
-GitLab currently supports post-processing for following service providers:
-
-- Amazon Web Services (AWS)
-
-Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
-
-NOTE:
-Post-processing is currently limited to a project's default branch, see the above epic for future efforts to support additional branches.
-
-```mermaid
-sequenceDiagram
- autonumber
- Rails->>+Sidekiq: gl-secret-detection-report.json
- Sidekiq-->+Sidekiq: Ci::BuildFinishedWorker
- Sidekiq-->+RevocationAPI: GET revocable keys types
- RevocationAPI-->>-Sidekiq: OK
- Sidekiq->>+RevocationAPI: POST revoke revocable keys
- RevocationAPI-->>-Sidekiq: ACCEPTED
- RevocationAPI-->>+Cloud Vendor: revoke revocable keys
- Cloud Vendor-->>+RevocationAPI: ACCEPTED
-```
+Upon detection of a secret, GitLab SaaS supports post-processing hooks.
+For more information, see [Post-processing and revocation](post_processing.md).
## Full History Secret Detection
@@ -316,7 +368,7 @@ registry.gitlab.com/security-products/secret-detection:3
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
-process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../vulnerabilities/index.md#vulnerability-scanner-maintenance)
+process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
For details on saving and transporting Docker images as a file, see Docker's documentation on
@@ -370,7 +422,7 @@ For information on this, see the [general Application Security troubleshooting s
### Error: `Couldn't run the gitleaks command: exit status 2`
-If a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` variable's
+If a pipeline is triggered from a merge request containing 60 commits while the `GIT_DEPTH` variable's
value is less than that, the Secret Detection job fails as the clone is not deep enough to contain all of the
relevant commits. For information on the current default value, see the
[pipeline configuration documentation](../../../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone).
@@ -395,3 +447,12 @@ secret_detection:
variables:
GIT_DEPTH: 100
```
+
+### `secret-detection` job fails with `ERR fatal: ambiguous argument` message
+
+Your `secret-detection` job can fail with `ERR fatal: ambiguous argument` error if your
+repository's default branch is unrelated to the branch the job was triggered for.
+See issue [!352014](https://gitlab.com/gitlab-org/gitlab/-/issues/352014) for more details.
+
+To resolve the issue, make sure to correctly [set your default branch](../../project/repository/branches/default.md#change-the-default-branch-name-for-a-project) on your repository. You should set it to a branch
+that has related history with the branch you run the `secret-detection` job on.
diff --git a/doc/user/application_security/secret_detection/post_processing.md b/doc/user/application_security/secret_detection/post_processing.md
new file mode 100644
index 00000000000..972558c3b95
--- /dev/null
+++ b/doc/user/application_security/secret_detection/post_processing.md
@@ -0,0 +1,179 @@
+---
+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
+---
+
+# Secret Detection post-processing and revocation **(FREE SAAS)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
+
+GitLab supports running post-processing hooks after detecting a secret. These
+hooks can perform actions, like notifying the cloud service that issued the secret.
+The cloud provider can then confirm the credentials and take remediation actions, like:
+
+- Revoking a secret.
+- Reissuing a secret.
+- Notifying the creator of the secret.
+
+GitLab SaaS supports post-processing for Amazon Web Services (AWS).
+Post-processing workflows vary by supported cloud providers.
+
+Post-processing is limited to a project's default branch. The epic
+[Post-processing of leaked secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
+contains:
+
+- Technical details of post-processing secrets.
+- Discussions of efforts to support additional branches.
+
+NOTE:
+Post-processing is currently limited to a project's default branch
+
+## High-level architecture
+
+This diagram describes how a post-processing hook revokes a secret within the GitLab application:
+
+```mermaid
+sequenceDiagram
+ autonumber
+ GitLab Rails->>+Sidekiq: gl-secret-detection-report.json
+ Sidekiq-->+Sidekiq: StoreSecurityReportsWorker
+ Sidekiq-->+RevocationAPI: GET revocable keys types
+ RevocationAPI-->>-Sidekiq: OK
+ Sidekiq->>+RevocationAPI: POST revoke revocable keys
+ RevocationAPI-->>-Sidekiq: ACCEPTED
+ RevocationAPI-->>+Cloud Vendor: revoke revocable keys
+ Cloud Vendor-->>+RevocationAPI: ACCEPTED
+```
+
+## Integrate your cloud provider service with GitLab Saas
+
+Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9).
+
+### Implement a vendor revocation receiver service
+
+A vendor revocation receiver service integrates with a GitLab instance to receive
+a web notification and respond to leaked token requests.
+
+To implement a receiver service to revoke leaked tokens:
+
+1. Create a publicly accessible HTTP service matching the corresponding API contract
+ below. Your service should be idempotent and rate-limited.
+1. When a pipeline corresponding to its revocable token type (in the example, `my_api_token`)
+ completes, GitLab sends a request to your receiver service.
+1. The included URL should be publicly accessible, and contain the commit where the
+ leaked token can be found. For example:
+
+ ```plaintext
+ POST / HTTP/2
+ Accept: */*
+ Content-Type: application/json
+ X-Gitlab-Token: MYSECRETTOKEN
+
+ [
+ {"type": "my_api_token", "token":"XXXXXXXXXXXXXXXX","url": "https://example.com/some-repo/blob/abcdefghijklmnop/compromisedfile1.java"}
+ ]
+ ```
+
+## Implement a revocation service for self-managed
+
+Self-managed instances interested in using the revocation capabilities must:
+
+- Deploy the [RevocationAPI](#high-level-architecture).
+- Configure the GitLab instance to use the RevocationAPI.
+
+A RevocationAPI must:
+
+- Match a minimal API specification.
+- Provide two endpoints:
+ - Fetching revocable token types.
+ - Revoking leaked tokens.
+- Be rate-limited and idempotent.
+
+Requests to the documented endpoints are authenticated via API tokens passed in
+the `Authorization` header. Request and response bodies, if present, are
+expected to have the content type `application/json`.
+
+All endpoints may return these responses:
+
+- `401 Unauthorized`
+- `405 Method Not Allowed`
+- `500 Internal Server Error`
+
+### `GET /v1/revocable_token_types`
+
+Returns the valid `type` values for use in the `revoke_tokens` endpoint.
+
+NOTE:
+These values match the concatenation of [the `secrets` analyzer's](index.md)
+[primary identifier](../../../development/integrations/secure.md#identifiers) by means
+of concatenating the `primary_identifier.type` and `primary_identifier.value`.
+In the case below, a finding identifier matches:
+
+```json
+{"type": "gitleaks_rule_id", "name": "Gitleaks rule ID GitLab Personal Access Token", "value": "GitLab Personal Access Token"}
+```
+
+| Status Code | Description |
+| ----- | --- |
+| `200` | The response body contains the valid token `type` values. |
+
+Example response body:
+
+```json
+{
+ "types": ["gitleaks_rule_id_gitlab_personal_access_token"]
+}
+```
+
+### `POST /v1/revoke_tokens`
+
+Accepts a list of tokens to be revoked by the appropriate provider.
+
+| Status Code | Description |
+| ----- | --- |
+| `204` | All submitted tokens have been accepted for eventual revocation. |
+| `400` | The request body is invalid or one of the submitted token types is not supported. The request should not be retried. |
+| `429` | The provider has received too many requests. The request should be retried later. |
+
+Example request body:
+
+```json
+[{
+ "type": "gitleaks_rule_id_gitlab_personal_access_token",
+ "token": "glpat--8GMtG8Mf4EnMJzmAWDU",
+ "location": "https://example.com/some-repo/blob/abcdefghijklmnop/compromisedfile1.java"
+},
+{
+ "type": "gitleaks_rule_id_gitlab_personal_access_token",
+ "token": "glpat--tG84EGK33nMLLDE70zU",
+ "location": "https://example.com/some-repo/blob/abcdefghijklmnop/compromisedfile2.java"
+}]
+```
+
+### Configure GitLab to interface with RevocationAPI
+
+You must configure the following database settings in the GitLab instance:
+
+- `secret_detection_token_revocation_enabled`
+- `secret_detection_token_revocation_url`
+- `secret_detection_token_revocation_token`
+- `secret_detection_revocation_token_types_url`
+
+For example, to configure these values in the
+[Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+::Gitlab::CurrentSettings.update!(secret_detection_token_revocation_token: 'MYSECRETTOKEN')
+::Gitlab::CurrentSettings.update!(secret_detection_token_revocation_url: 'https://example.gitlab.com/revocation_service/v1/revoke_tokens')
+::Gitlab::CurrentSettings.update!(secret_detection_revocation_token_types_url: 'https://example.gitlab.com/revocation_service/v1/revocable_token_types')
+::Gitlab::CurrentSettings.update!(secret_detection_token_revocation_enabled: true)
+```
+
+After you configure these values, completing a pipeline performs these actions:
+
+1. The revocation service is triggered once.
+1. A request is made to `secret_detection_revocation_token_types_url` to fetch a
+ list of revocable tokens.
+1. Any Secret Detection findings matching the results of the `token_types` request
+ are included in the subsequent revocation request.
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 937ca33c3a1..a0cfd6d9d77 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -75,7 +75,7 @@ To view the total number of vulnerabilities per scan:
Depending on the type of security scanner, you can download:
-- A JSON artifact that contains the security scanner [report]('https://docs.gitlab.com/ee/development/integrations/secure.html#report').
+- A JSON artifact that contains the security scanner [report](../../../development/integrations/secure.md#report).
- A CSV file that contains URLs and endpoints scanned by the security scanner.
To download a security scan output:
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index ae5f6ba0fe1..390882d4326 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -7,7 +7,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Threat Monitoring **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in GitLab 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in GitLab 12.9.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Threat Monitoring is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
The **Threat Monitoring** page provides alerts and metrics
for the GitLab application runtime security features. You can access
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 9aa8a0cd3cd..7b39002bac3 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -1,5 +1,4 @@
---
-type: reference, howto
stage: Secure
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
@@ -160,23 +159,3 @@ To manually apply the patch that GitLab generated for a vulnerability:
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.
-
-## 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) | 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 on a daily basis using [data from NVD, the `ruby-advisory-db` and the GitHub Security Advisory Database as data sources](https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/blob/master/SOURCES.md). 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/main/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. |
-
-You do not have to update GitLab to benefit from the latest vulnerabilities definitions.
-The security tools are released as Docker images. The vendored job definitions that enable them use
-major release tags according to [semantic versioning](https://semver.org/). Each new release of the
-tools overrides these tags.
-The Docker images are updated to match the previous GitLab releases. Although
-you automatically get the latest versions of the scanning tools,
-there are some [known issues](https://gitlab.com/gitlab-org/gitlab/-/issues/9725)
-with this approach.
diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md
index f3e8e98bce3..89464064ea3 100644
--- a/doc/user/application_security/vulnerabilities/severities.md
+++ b/doc/user/application_security/vulnerabilities/severities.md
@@ -35,10 +35,10 @@ the following tables:
## SAST
-| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
-|--------------------------------------------------------------------------------------------------------|--------------------------|----------------------------|------------------------------------|
-| [`security-code-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) | **{dotted-circle}** No | N/A | N/A |
-| [`brakeman`](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) | **{dotted-circle}** No | N/A | N/A |
+| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
+|----------------------------------------------------------------------------------------------------------|--------------------------|----------------------------|------------------------------------|
+| [`security-code-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) | **{check-circle}** Yes | String | `CRITICAL`, `HIGH`, `MEDIUM` in [analyzer version 3.2.0 and later](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/blob/master/CHANGELOG.md#v320). In earlier versions, hardcoded to `Unknown`. |
+| [`brakeman`](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` |
| [`sobelow`](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Unknown` |
| [`nodejs-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan) | **{check-circle}** Yes | String | `INFO`, `WARNING`, `ERROR` |
| [`flawfinder`](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder) | **{check-circle}** Yes | Integer | `0`, `1`, `2`, `3`, `4`, `5` |
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index 05ff5c511f9..ba1455ab70a 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -7,7 +7,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Vulnerability Report **(ULTIMATE)**
-The Vulnerability Report provides information about vulnerabilities from scans of the default branch. It is available for projects, groups, and the Security Center.
+The Vulnerability Report provides information about vulnerabilities from scans of the default branch. It contains cumulative results of all successful jobs, regardless of whether the pipeline was successful.
+
+The scan results from a pipeline are only ingested after all the jobs in the pipeline complete. Partial results for a pipeline with jobs in progress can be seen in the pipeline security tab.
+
+The report is available for projects, groups, and the Security Center.
At all levels, the Vulnerability Report contains:
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index da75c008ed1..80c85358fcb 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -232,6 +232,11 @@ v1.0, 2019-01-01
#### Includes
+NOTE:
+[Wiki pages](project/wiki/index.md#create-a-new-wiki-page) created with the AsciiDoc
+format are saved with the file extension `.asciidoc`. When working with AsciiDoc wiki
+pages, change the file name from `.adoc` to `.asciidoc`.
+
```plaintext
include::basics.adoc[]
diff --git a/doc/user/clusters/agent/ci_cd_tunnel.md b/doc/user/clusters/agent/ci_cd_tunnel.md
index f1c49b87383..5fe772d9686 100644
--- a/doc/user/clusters/agent/ci_cd_tunnel.md
+++ b/doc/user/clusters/agent/ci_cd_tunnel.md
@@ -12,53 +12,52 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
> - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5.
-The CI/CD Tunnel enables users to access Kubernetes clusters from GitLab CI/CD jobs even if there is no network
-connectivity between GitLab Runner and a cluster. GitLab Runner does not have to be running in the same cluster.
+To use GitLab CI/CD to safely deploy your application to a cluster, you can use the CI/CD Tunnel.
-Only CI/CD jobs set in the configuration project can access one of the configured agents.
+You can authorize multiple projects to access the same cluster, so you
+can keep your application's codebase in one repository and configure
+your cluster in another. This method is scalable and can save you resources.
-## Prerequisites
-
-- An existing Kubernetes cluster.
-- An agent [installed on your cluster](install/index.md#install-the-agent-into-the-cluster).
+To ensure access to your cluster is safe, only the projects you
+authorize can access your Agent through the CI/CD Tunnel.
-## Use the CI/CD Tunnel to run Kubernetes commands from GitLab CI/CD
-
-If your project has access to one or more Agent records available, its CI/CD
-jobs provide a `KUBECONFIG` variable compatible with `kubectl`.
+## Prerequisites
-Also, each Agent has a separate context (`kubecontext`). By default,
-there isn't any context selected.
-Contexts are named in the following format: `<agent-configuration-project-path>:<agent-name>`.
-To get the list of available contexts, run `kubectl config get-contexts`.
+To use the CI/CD Tunnel, you need an existing Kubernetes cluster connected to GitLab through the
+[GitLab Agent](install/index.md#install-the-agent-onto-the-cluster).
-## Share the CI/CD Tunnel provided by an Agent with other projects and groups
+To run your CI/CD jobs using the CI/CD Tunnel, you do not need to have a runner in the same cluster.
-The Agent can be configured to enable access to the CI/CD Tunnel to other projects or all the projects under a given group. This way you can have a single agent serving all the requests for several projects saving on resources and maintenance.
+## How the CI/CD Tunnel works
-You can read more on how to [authorize access in the Agent configuration reference](repository.md#authorize-projects-and-groups-to-use-an-agent).
+When you authorize a project to use an Agent, the Tunnel automatically
+injects a `KUBECONFIG` variable into its CI/CD jobs. This way, you can
+run `kubectl` commands from GitLab CI/CD scripts that belong to the
+authorized project.
-## Restrict access of authorized projects and groups **(PREMIUM)**
+When you authorize a group, all the projects that belong to that group
+become authorized to access the selected Agent.
-You can [configure various impersonations](repository.md#use-impersonation-to-restrict-project-and-group-access) to restrict the permissions of a shared CI/CD Tunnel.
+An Agent can only authorize projects or groups in the same group
+hierarchy as the Agent's configuration project. You can authorize
+up to 100 projects and 100 groups per Agent.
-## Example for a `kubectl` command using the CI/CD Tunnel
+Also, each Agent has a separate context (`kubecontext`).
+The Tunnel uses this information to safely allow access to the cluster from
+jobs running in the projects you authorized.
-The following example shows a CI/CD job that runs a `kubectl` command using the CI/CD Tunnel.
-You can run any Kubernetes-specific commands similarly, such as `kubectl`, `helm`,
-`kpt`, and so on. To do so:
+### `~/.kube/cache` permissions
+
+`kubectl` and other tools based on the same libraries (such as Helm, `kpt`, and `kustomize`) cache information about
+the cluster in `~/.kube/cache`. If this directory is not writable, the tool fetches information on each invocation,
+making interactions slower and creating unnecessary load on the cluster. Make sure that this directory in the container image
+you use is writable for the best experience.
-1. Set your Agent's context in the first command with the format `<agent-configuration-project-path>:<agent-name>`.
-1. Run Kubernetes commands.
+## Configure the CI/CD Tunnel
-For example:
+The CI/CD Tunnel is configured directly through the
+Agent's configuration file ([`config.yaml`](repository.md)) to:
-```yaml
- deploy:
- image:
- name: bitnami/kubectl:latest
- entrypoint: [""]
- script:
- - kubectl config use-context path/to/agent-configuration-project:your-agent-name
- - kubectl get pods
-```
+- Authorize [projects](repository.md#authorize-projects-to-use-an-agent) and [groups](repository.md#authorize-groups-to-use-an-agent) to use the same Agent.
+- [Run `kubectl` commands using the CI/CD Tunnel](repository.md#run-kubectl-commands-using-the-cicd-tunnel).
+- [Restrict access of authorized projects and groups through impersonation strategies](repository.md#use-impersonation-to-restrict-project-and-group-access).
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index a235c0ef6f8..3fb141e402f 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -4,60 +4,71 @@ 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
---
-# GitLab Agent for Kubernetes **(FREE)**
+# Connecting a Kubernetes cluster with GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in GitLab 13.4.
> - Support for `grpcs` [introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) in GitLab 13.10, KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
-> - Introduced in GitLab 13.11, the GitLab Agent became available to every project on GitLab.com.
+> - Agent Server [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program in GitLab 13.10.
+> - The agent became available to every project on GitLab.com in GitLab 13.11.
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
-> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab Agent for Kubernetes" in GitLab 14.6.
+> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab agent for Kubernetes" in GitLab 14.6.
-The [GitLab Agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) ("Agent", for short)
-is an active in-cluster component for connecting Kubernetes clusters to GitLab safely to support cloud-native deployment, management, and monitoring.
+You can connect your Kubernetes cluster with GitLab to deploy, manage,
+and monitor your cloud-native solutions. You can choose from two primary workflows.
-The Agent is installed into the cluster through code, providing you with a fast, safe, stable, and scalable solution.
+In a **GitOps workflow**, you keep your Kubernetes manifests in GitLab. You install a GitLab agent in your cluster, and
+any time you update your manifests, the agent updates the cluster. This workflow is fully driven with Git and is considered pull-based,
+because the cluster is pulling updates from your GitLab repository.
+
+In a **CI/CD** workflow, you use GitLab CI/CD to query and update your cluster by using the Kubernetes API.
+This workflow is considered push-based, because GitLab is pushing requests from GitLab CI/CD to your cluster.
+
+Both of these workflows require you to [install an agent in your cluster](install/index.md).
+
+## Supported cluster versions
+
+GitLab supports the following Kubernetes versions. You can upgrade your
+Kubernetes version to a supported version at any time:
+
+- 1.20 (support ends on July 22, 2022)
+- 1.19 (support ends on February 22, 2022)
+- 1.18 (support ends on November 22, 2021)
+- 1.17 (support ends on September 22, 2021)
+
+GitLab supports at least two production-ready Kubernetes minor
+versions at any given time. GitLab regularly reviews the supported versions and
+provides a three-month deprecation period before removing support for a specific
+version. The list of supported versions is based on:
+
+- The versions supported by major managed Kubernetes providers.
+- The versions [supported by the Kubernetes community](https://kubernetes.io/releases/version-skew-policy/#supported-versions).
+
+[This epic](https://gitlab.com/groups/gitlab-org/-/epics/4827) tracks support for other Kubernetes versions.
+
+Some GitLab features might work on versions not listed here.
+
+## Using Kubernetes with GitOps **(PREMIUM)**
With GitOps, you can manage containerized clusters and applications from a Git repository that:
- Is the single source of truth of your system.
- Is the single place where you operate your system.
-- Is a single resource to monitor your system.
-By combining GitLab, Kubernetes, and GitOps, it results in a robust infrastructure:
+By combining GitLab, Kubernetes, and GitOps, you can have:
- GitLab as the GitOps operator.
- Kubernetes as the automation and convergence system.
-- GitLab CI/CD as the Continuous Integration and Continuous Deployment engine.
+- GitLab CI/CD for Continuous Integration and the agent for Continuous Deployment.
Beyond that, you can use all the features offered by GitLab as
the all-in-one DevOps platform for your product and your team.
-## Agent's features
+### GitOps workflow **(PREMIUM)**
-By using the Agent, you can:
-
-- Connect GitLab with a Kubernetes cluster behind a firewall or a
-Network Address Translation (NAT).
-- Have real-time access to API endpoints in your cluster from GitLab CI/CD.
-- Use GitOps to configure your cluster through the [Agent's repository](repository.md).
-- Perform pull-based or push-based GitOps deployments.
-- Configure [Network Security Alerts](#kubernetes-network-security-alerts)
-based on [Container Network Policies](../../application_security/policies/index.md#container-network-policy).
-- Track objects applied to your cluster through [inventory objects](../../infrastructure/clusters/deploy/inventory_object.md).
-- Use the [CI/CD Tunnel](ci_cd_tunnel.md) to access Kubernetes clusters
-from GitLab CI/CD jobs while keeping the cluster's APIs safe and unexposed
-to the internet.
-- [Deploy the GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
-
-See the [Agent roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) to track its development.
-
-To contribute to the Agent, see the [Agent's development documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc).
-
-## Agent's GitOps workflow **(PREMIUM)**
-
-The Agent uses multiple GitLab projects to provide a flexible workflow
+The agent uses multiple GitLab projects to provide a flexible workflow
that can suit various needs. This diagram shows these repositories and the main
+The agent uses multiple GitLab projects to provide a flexible workflow.
+This diagram shows these repositories and the main
actors involved in a deployment:
```mermaid
@@ -65,7 +76,7 @@ sequenceDiagram
participant D as Developer
participant A as Application code repository
participant M as Manifest repository
- participant K as GitLab Agent
+ participant K as GitLab agent
participant C as Agent configuration repository
loop Regularly
K-->>C: Grab the configuration
@@ -78,61 +89,28 @@ sequenceDiagram
end
```
-For more details, refer to our [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture) in the Agent project.
-
-## Install the Agent in your cluster
-
-See how to [install the Agent in your cluster](install/index.md).
-
-## GitOps deployments **(PREMIUM)**
-
-To perform GitOps deployments with the Agent, you need:
+For details, view the [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture).
-- A properly-configured Kubernetes cluster where the Agent is running.
-- A [configuration repository](repository.md) that contains a
-`config.yaml` file, which tells the Agent the repositories to synchronize
-with the cluster.
-- A manifest repository that contains manifest files. Any changes to manifest files are applied to the cluster.
+To perform GitOps deployments, you need:
-You can use a single GitLab project or different projects for the Agent
-configuration and manifest files, as follows:
+- A properly-configured Kubernetes cluster where the GitLab agent is running.
+- A project that contains the agent's configuration file (`config.yaml`) in the repository.
+ This file tells the agent which repositories to synchronize with the cluster.
+- A project that contains Kubernetes manifests. Any changes to manifests are applied to the cluster.
-- Single GitLab project (recommended): When you use a single repository to hold
- both the manifest and the configuration files, these projects can be either
- private or public.
-- Two GitLab projects: When you use two different GitLab projects (one for
- manifest files and another for configuration files), the manifests project must
- be public, while the configuration project can be either private or public.
+You can keep the agent's configuration file and Kubernetes manifests in one project, or you can use multiple.
-Support for separated private manifest and configuration repositories is tracked in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
+- One GitLab project (recommended): When you use one project for both the Kubernetes manifests
+ and the agent's configuration file, the projects can be either private or public.
+- Two GitLab projects: When you use two different GitLab projects (one for Kubernetes
+ manifests and another for the agent's configuration file), the project with Kubernetes manifests must
+ be public. The project with the agent's configuration file can be either private or public.
-## Kubernetes Network Security Alerts **(ULTIMATE)**
-
-The GitLab Agent also provides an integration with Cilium. This integration provides a simple way to
-generate network policy-related alerts and to surface those alerts in GitLab.
-
-There are several components that work in concert for the Agent to generate the alerts:
-
-- A working Kubernetes cluster.
-- Cilium integration through either of these options:
- - Installation through [cluster management template](../../project/clusters/protect/container_network_security/quick_start_guide.md#use-the-cluster-management-template-to-install-cilium).
- - Enablement of [hubble-relay](https://docs.cilium.io/en/v1.8/concepts/overview/#hubble) on an
- existing installation.
-- One or more network policies through any of these options:
- - Use the [Container Network Policy editor](../../application_security/policies/index.md#container-network-policy-editor) to create and manage policies.
- - Use an [AutoDevOps](../../application_security/policies/index.md#container-network-policy) configuration.
- - Add the required labels and annotations to existing network policies.
-- A configuration repository with [Cilium configured in `config.yaml`](repository.md#surface-network-security-alerts-from-cluster-to-gitlab)
-
-The setup process follows the same [Agent's installation steps](install/index.md),
-with the following differences:
-
-- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab).
-- You do not need to specify the `gitops` configuration section.
+Support for separate private projects is tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/283885).
## Remove an agent
-You can remove an agent using the [GitLab UI](#remove-an-agent-through-the-gitlab-ui) or through the [GraphQL API](#remove-an-agent-with-the-gitlab-graphql-api).
+You can remove an agent by using the [GitLab UI](#remove-an-agent-through-the-gitlab-ui) or the [GraphQL API](#remove-an-agent-with-the-gitlab-graphql-api).
### Remove an agent through the GitLab UI
@@ -140,16 +118,16 @@ You can remove an agent using the [GitLab UI](#remove-an-agent-through-the-gitla
To remove an agent from the UI:
-1. Go to your agent's configuration repository.
-1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**.
-1. Select your agent from the table, and then in the **Options** column, click the vertical ellipsis
-(**{ellipsis_v}**) button and select **Delete agent**.
+1. On the top bar, select **Menu > Projects** and find the project that contains the agent's configuration file.
+1. From the left sidebar, select **Infrastructure > Kubernetes clusters**.
+1. In the table, in the row for your agent, in the **Options** column, select the vertical ellipsis (**{ellipsis_v}**).
+1. Select **Delete agent**.
### Remove an agent with the GitLab GraphQL API
1. Get the `<cluster-agent-token-id>` from a query in the interactive GraphQL explorer.
-For GitLab.com, go to <https://gitlab.com/-/graphql-explorer> to open GraphQL Explorer.
-For self-managed GitLab instances, go to `https://gitlab.example.com/-/graphql-explorer`, replacing `gitlab.example.com` with your own instance's URL.
+ - For GitLab.com, go to <https://gitlab.com/-/graphql-explorer> to open GraphQL Explorer.
+ - For self-managed GitLab, go to `https://gitlab.example.com/-/graphql-explorer`, replacing `gitlab.example.com` with your instance's URL.
```graphql
query{
@@ -195,185 +173,48 @@ For self-managed GitLab instances, go to `https://gitlab.example.com/-/graphql-e
}
```
-1. Delete the Agent in your cluster:
+1. Delete the agent in your cluster:
```shell
kubectl delete -n gitlab-kubernetes-agent -f ./resources.yml
```
-## Migrating to the GitLab Agent from the legacy certificate-based integration
-
-Find out how to [migrate to the GitLab Agent for Kubernetes](../../infrastructure/clusters/migrate_to_gitlab_agent.md) from the certificate-based integration depending on the features you use.
-
-## Troubleshooting
-
-If you face any issues while using the Agent, read the
-service logs with the following command:
-
-```shell
-kubectl logs -f -l=app=gitlab-kubernetes-agent -n gitlab-kubernetes-agent
-```
-
-GitLab administrators can additionally view the [GitLab Agent Server logs](../../../administration/clusters/kas.md#troubleshooting).
-
-### Agent logs
-
-#### Transport: Error while dialing failed to WebSocket dial
+## Migrating to the agent from the legacy certificate-based integration
-```json
-{
- "level": "warn",
- "time": "2020-11-04T10:14:39.368Z",
- "msg": "GetConfiguration failed",
- "error": "rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://gitlab-kas:443/-/kubernetes-agent\\\": dial tcp: lookup gitlab-kas on 10.60.0.10:53: no such host\""
-}
-```
-
-This error is shown if there are some connectivity issues between the address
-specified as `kas-address`, and your Agent pod. To fix it, make sure that you
-specified the `kas-address` correctly.
-
-```json
-{
- "level": "error",
- "time": "2021-06-25T21:15:45.335Z",
- "msg": "Reverse tunnel",
- "mod_name": "reverse_tunnel",
- "error": "Connect(): rpc error: code = Unavailable desc = connection error: desc= \"transport: Error while dialing failed to WebSocket dial: expected handshake response status code 101 but got 301\""
-}
-```
-
-This error occurs if the `kas-address` doesn't include a trailing slash. To fix it, make sure that the
-`wss` or `ws` URL ends with a trailing slash, such as `wss://GitLab.host.tld:443/-/kubernetes-agent/`
-or `ws://GitLab.host.tld:80/-/kubernetes-agent/`.
-
-#### ValidationError(Deployment.metadata)
-
-```json
-{
- "level": "info",
- "time": "2020-10-30T08:56:54.329Z",
- "msg": "Synced",
- "project_id": "root/kas-manifest001",
- "resource_key": "apps/Deployment/kas-test001/nginx-deployment",
- "sync_result": "error validating data: [ValidationError(Deployment.metadata): unknown field \"replicas\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"selector\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"template\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta]"
-}
-```
+Find out how to [migrate to the agent for Kubernetes](../../infrastructure/clusters/migrate_to_gitlab_agent.md) from the certificate-based integration.
-This error is shown if a manifest file is malformed, and Kubernetes can't
-create specified objects. Make sure that your manifest files are valid. You
-may try using them to create objects in Kubernetes directly for more troubleshooting.
+## Kubernetes network security alerts **(ULTIMATE)**
-#### Error while dialing failed to WebSocket dial: failed to send handshake request
-
-```json
-{
- "level": "warn",
- "time": "2020-10-30T09:50:51.173Z",
- "msg": "GetConfiguration failed",
- "error": "rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent\\\": net/http: HTTP/1.x transport connection broken: malformed HTTP response \\\"\\\\x00\\\\x00\\\\x06\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x05\\\\x00\\\\x00@\\\\x00\\\"\""
-}
-```
-
-This error is shown if you configured `wss` as `kas-address` on the agent side,
-but KAS on the server side is not available via `wss`. To fix it, make sure the
-same schemes are configured on both sides.
-
-It's not possible to set the `grpc` scheme due to the issue
-[It is not possible to configure KAS to work with `grpc` without directly editing GitLab KAS deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/276888). To use `grpc` while the
-issue is in progress, directly edit the deployment with the
-`kubectl edit deployment gitlab-kas` command, and change `--listen-websocket=true` to `--listen-websocket=false`. After running that command, you should be able to use
-`grpc://gitlab-kas.<YOUR-NAMESPACE>:8150`.
-
-#### Decompressor is not installed for grpc-encoding
-
-```json
-{
- "level": "warn",
- "time": "2020-11-05T05:25:46.916Z",
- "msg": "GetConfiguration.Recv failed",
- "error": "rpc error: code = Unimplemented desc = grpc: Decompressor is not installed for grpc-encoding \"gzip\""
-}
-```
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
-This error is shown if the version of the agent is newer that the version of KAS.
-To fix it, make sure that both `agentk` and KAS use the same versions.
+WARNING:
+Cilium integration is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
-#### Certificate signed by unknown authority
+The agent for Kubernetes also provides an integration with Cilium. This integration provides a simple way to
+generate network policy-related alerts and to surface those alerts in GitLab.
-```json
-{
- "level": "error",
- "time": "2021-02-25T07:22:37.158Z",
- "msg": "Reverse tunnel",
- "mod_name": "reverse_tunnel",
- "error": "Connect(): rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent/\\\": x509: certificate signed by unknown authority\""
-}
-```
+Several components work in concert for the agent to generate the alerts:
-This error is shown if your GitLab instance is using a certificate signed by an internal CA that
-is unknown to the agent. One approach to fixing it is to present the CA certificate file to the agent
-via a Kubernetes `configmap` and mount the file in the agent `/etc/ssl/certs` directory from where it
-will be picked up automatically.
+- A working Kubernetes cluster.
+- Cilium integration through either of these options:
+ - Installation through [cluster management template](../../project/clusters/protect/container_network_security/quick_start_guide.md#use-the-cluster-management-template-to-install-cilium).
+ - Enablement of [hubble-relay](https://docs.cilium.io/en/v1.8/concepts/overview/#hubble) on an
+ existing installation.
+- One or more network policies through any of these options:
+ - Use the [Container Network Policy editor](../../application_security/policies/index.md#container-network-policy-editor) to create and manage policies.
+ - Use an [AutoDevOps](../../application_security/policies/index.md#container-network-policy) configuration.
+ - Add the required labels and annotations to existing network policies.
+- A configuration repository with [Cilium configured in `config.yaml`](repository.md#surface-network-security-alerts-from-cluster-to-gitlab)
-For example, if your internal CA certificate is `myCA.pem`:
+The setup process follows the same [agent's installation steps](install/index.md),
+with the following differences:
-```plaintext
-kubectl -n gitlab-kubernetes-agent create configmap ca-pemstore --from-file=myCA.pem
-```
+- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab).
+- You do not need to specify the `gitops` configuration section.
-Then in `resources.yml`:
-
-```yaml
- spec:
- serviceAccountName: gitlab-kubernetes-agent
- containers:
- - name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
- args:
- - --token-file=/config/token
- - --kas-address
- - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
- # - wss://gitlab.host.tld:443/-/kubernetes-agent/
- # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
- # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
- volumeMounts:
- - name: token-volume
- mountPath: /config
- - name: ca-pemstore-volume
- mountPath: /etc/ssl/certs/myCA.pem
- subPath: myCA.pem
- volumes:
- - name: token-volume
- secret:
- secretName: gitlab-kubernetes-agent-token
- - name: ca-pemstore-volume
- configMap:
- name: ca-pemstore
- items:
- - key: myCA.pem
- path: myCA.pem
-```
+## Related topics
-Alternatively, you can mount the certificate file at a different location and include it using the
-`--ca-cert-file` agent parameter:
-
-```yaml
- containers:
- - name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
- args:
- - --ca-cert-file=/tmp/myCA.pem
- - --token-file=/config/token
- - --kas-address
- - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
- # - wss://gitlab.host.tld:443/-/kubernetes-agent/
- # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
- # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
- volumeMounts:
- - name: token-volume
- mountPath: /config
- - name: ca-pemstore-volume
- mountPath: /tmp/myCA.pem
- subPath: myCA.pem
-```
+- [Troubleshooting](troubleshooting.md)
+- [Contribute to the GitLab agent's development](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc)
diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md
index b2372789284..4d196e57f8f 100644
--- a/doc/user/clusters/agent/install/index.md
+++ b/doc/user/clusters/agent/install/index.md
@@ -6,112 +6,140 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Install the GitLab Agent **(FREE)**
-> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
+> - [Introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/merge_requests/594) multi-arch images in GitLab 14.8. The first multi-arch release is `v14.8.1`. It supports AMD64 and ARM64 architectures.
-To get started with the Agent, install it in your cluster.
+To connect a cluster to GitLab, you need to install the GitLab Agent
+onto your cluster.
-## Prerequisites **(SELF)**
+## Prerequisites
-- An existing Kubernetes cluster.
+- An existing Kubernetes cluster. If you don't have a cluster yet, you can create a new cluster on cloud providers, such as:
+ - [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/docs/quickstart)
+ - [Amazon Elastic Kubernetes Service (EKS)](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)
+ - [Digital Ocean](https://docs.digitalocean.com/products/kubernetes/quickstart/)
- On self-managed GitLab instances, a GitLab administrator needs to set up the [GitLab Agent Server (KAS)](../../../../administration/clusters/kas.md).
## Installation steps
-To install the [Agent](../index.md) in your cluster:
+To install the GitLab Agent on your cluster:
1. [Define a configuration repository](#define-a-configuration-repository).
-1. [Register an agent with GitLab](#register-an-agent-with-gitlab).
-1. [Install the agent into the cluster](#install-the-agent-into-the-cluster).
+1. [Register the Agent with GitLab](#register-the-agent-with-gitlab).
+1. [Install the Agent onto the cluster](#install-the-agent-onto-the-cluster).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a GitLab 14.2 [walking-through video](https://www.youtube.com/watch?v=XuBpKtsgGkE) with this process.
+When you complete the installation process, you can
+[view your Agent's status and activity information](#view-your-agents).
+You can also [configure](#configure-the-agent) it to your needs.
+
### Define a configuration repository
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the Agent manifest configuration can be added to multiple directories (or subdirectories) of its repository.
> - Group authorization was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-To create an agent, you need a GitLab repository to hold the configuration file.
+To create an Agent, you need a GitLab repository to hold its
+configuration file. If you already have a repository holding your
+cluster's manifest files, you can use it to store your
+Agent's configuration file and sync them with no further steps.
-After installed, when you update the configuration file, GitLab transmits the
-information to the cluster automatically without downtime.
+#### Create the Agent's configuration file
-In your repository, add the Agent configuration file under:
+To create an Agent, go to the repository where you want to store
+it and add the Agent's configuration file under:
```plaintext
.gitlab/agents/<agent-name>/config.yaml
```
-Make sure that `<agent-name>` conforms to the [Agent's naming format](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name).
-
-WARNING:
-The agent is only recognized if you use `.yaml` extension for the `config.yaml` file. The extension `.yml` is **not** recognized.
-
-You **don't have to add any content** to this file when you create it. The fact that the file exists
-tells GitLab that this is an agent configuration file and enables the [CI/CD tunnel](../ci_cd_tunnel.md#example-for-a-kubectl-command-using-the-cicd-tunnel). Later on, you can use this
-file to [configure the agent](../repository.md) by setting up parameters such as:
+You **don't have to add any content** to this file at the moment you
+create it. The fact that the file exists tells GitLab that this is
+an Agent. You can edit it later to [configure the Agent](#configure-the-agent).
-- Groups and projects that can access the agent via the [CI/CD Tunnel](../ci_cd_tunnel.md).
-- [Manifest projects to synchronize](../repository.md#synchronize-manifest-projects).
-- The address of the `hubble-relay` for the [Network Security policy integrations](../../../project/clusters/protect/index.md).
+When creating this file, pay special attention to:
-To see all the settings available, read the [Agent configuration repository documentation](../repository.md).
+- The [Agent's naming format](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name).
+- The file extension: use the `.yaml` extension (`config.yaml`). The `.yml` extension is **not** recognized.
-### Register an agent with GitLab
+### Register the Agent with GitLab
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5786) in GitLab 14.1, you can create a new Agent record directly from the GitLab UI.
-Next, create a GitLab Rails Agent record to associate it with
-the configuration repository project. Creating this record also creates a Secret needed to configure
-the Agent in subsequent steps.
+Now that you've created your Agent's configuration file, register it
+with GitLab.
+When you register the Agent, GitLab generates a token that you need for
+installing the Agent onto your cluster.
-In GitLab:
+In GitLab, go to the project where you added your Agent's configuration
+file and:
1. Ensure that [GitLab CI/CD is enabled in your project](../../../../ci/enable_or_disable_ci.md#enable-cicd-in-a-project).
1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**.
1. Select **Actions**.
-1. From the **Select an agent** dropdown, select the agent you want to connect and select **Register an agent** to access the installation form.
-1. The form reveals your registration token. Securely store this secret token as you cannot view it again.
-1. Copy the command under **Recommended installation method**.
+1. From the **Select an Agent** dropdown list, select the Agent you want to register and select **Register an Agent**.
+1. GitLab generates a registration token for this Agent. Securely store this secret token, as you need it to install the Agent onto your cluster and to [update the Agent](#update-the-agent-version) to another version.
+1. Copy the command under **Recommended installation method**. You need it to install the Agent onto your cluster through the one-liner installation method.
+
+### Install the Agent onto the cluster
-### Install the agent into the cluster
+To connect your cluster to GitLab, install the registered Agent
+onto your cluster. To install it, you can use either:
-In your computer:
+- [The one-liner installation method](#one-liner-installation).
+- [The advanced installation method](#advanced-installation).
-1. Open your local terminal and connect to your cluster.
+You can use the one-liner installation for trying to use the Agent for the first time, to do internal setups with
+high trust, and to quickly get started. For long-term production usage, you may want to use the advanced installation
+method to benefit from more configuration options.
+
+#### One-liner installation
+
+The one-liner installation is the simplest process, but you need
+Docker installed locally. If you don't have it, you can either install
+it or opt to the [advanced installation method](#advanced-installation).
+
+To install the Agent on your cluster using the one-liner installation:
+
+1. In your computer, open the terminal and connect to your cluster.
1. Run the command you copied when registering your cluster in the previous step.
-See the following sections to learn about customizing the installation.
+Optionally, you can [customize the one-liner installation command](#customize-the-one-liner-installation).
-## Simple installation method
+##### Customize the one-liner installation
-The command provided by GitLab does the following things:
+The one-liner command generated by GitLab:
- Creates a namespace for the deployment (`gitlab-kubernetes-agent`).
-- Sets up a service account with `cluster-admin` rights. Read more on [how you can restrict this service account](#customize-the-permissions-for-the-agentk-service-account).
-- Creates a `Secret` resource for the agent registration token.
+- Sets up a service account with `cluster-admin` rights (see [how to restrict this service account](#customize-the-permissions-for-the-agentk-service-account)).
+- Creates a `Secret` resource for the Agent's registration token.
- Creates a `Deployment` resource for the `agentk` pod.
-The one-liner installer can be customized at the command line. To find out the various options the above Docker container supports, run:
+You can edit these parameters according to your needs to customize the
+one-liner installation command at the command line. To find all available
+options, run in your terminal:
```shell
docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
```
WARNING:
-`--agent-version stable` can be used to refer to the latest stable release at the time when the command runs. It's fine for
-testing purposes but for production please make sure to specify a matching version explicitly.
-
-## Advanced installation method
+`--agent-version stable` can be used to refer to the latest stable
+release at the time when the command runs. It's fine for testing
+purposes but for production please make sure to specify a matching
+version explicitly.
-For more advanced configurations, we recommend to use [the `kpt` based installation method](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent).
+#### Advanced installation
-Otherwise, follow the manual installation steps described below.
+For advanced installation options, use [the `kpt` installation method](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent).
-### Customize the permissions for the `agentk` service account
+##### Customize the permissions for the `agentk` service account
-The GitLab Agent for Kubernetes allows you to fully own your cluster and requires only the permissions you give. Still, for easy getting started, by default the generated manifests provide `cluster-admin` rights to the agent.
+The GitLab Agent allows you to fully own your cluster and grant GitLab
+the permissions you want. Still, to facilitate the process, by default the
+generated manifests provide `cluster-admin` rights to the Agent.
-As part of the advanced installation method, you can restrict the agent access rights using Kustomize overlays. [An example is commented out](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/build/deployment/gitlab-agent/cluster/kustomization.yaml) in the `kpt` package you retrieved as part of the installation.
+You can restrict the Agent's access rights using Kustomize overlays. [An example is commented out](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/build/deployment/gitlab-agent/cluster/kustomization.yaml) in the `kpt` package you retrieved as part of the installation.
To create restricted permissions:
@@ -121,50 +149,115 @@ To create restricted permissions:
The above setup allows you to regularly update from the upstream package using `kpt pkg update gitlab-agent --strategy resource-merge` and maintain your customizations at the same time.
-## Example projects
+## Configure the Agent
-The following example projects can help you get started with the Agent.
+When successfully installed, you can [configure the Agent](../repository.md)
+by editing its configuration file.
+When you update the configuration file, GitLab transmits the
+information to the cluster automatically without downtime.
-- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
-- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
+## View your Agents
-## View installed Agents
+> The version of installed `agentk` shown on the Agent tab [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340882) in GitLab 14.8.
+If you have at least the Developer role, you can access the Agent's
+configuration repository and view the Agent's list:
-Users with at least the [Developer](../../../permissions.md) can access the user interface
-for the Agent at **Infrastructure > Kubernetes clusters**, under the
-**Agent** tab. This page lists all registered agents for the current project,
-and the configuration directory for each agent:
+1. On the left sidebar, select **Infrastructure > Kubernetes clusters**.
+1. Select **Agent** tab to view clusters connected to GitLab through the Agent.
-![GitLab Agent list UI](../../img/kubernetes-agent-ui-list_v14_5.png)
+On this page, you can view:
-Additional management interfaces are planned for the GitLab Agent.
-[Provide more feedback in the related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
+- All the registered Agents for the current project.
+- The connection status.
+- The version of `agentk` installed on your cluster.
+- The path to each Agent's configuration file.
-## View Agent activity information
+Furthermore, if you select one of the Agents on your list, you can view its
+[activity information](#view-the-agents-activity-information).
+
+### View the Agent's activity information
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/277323) in GitLab 14.6.
-Users with at least the [Developer](../../../permissions.md) can view the Agent's activity events.
-The activity logs help you to identify problems and get the information you need for troubleshooting.
-You can see events from a week before the current date.
-To access an agent's activity:
+The activity logs help you to identify problems and get the information
+you need for troubleshooting. You can see events from a week before the
+current date. To access an Agent's activity:
+
+1. In your Agent's repository, go to the Agents list as described [above](#view-your-agents).
+1. Select the Agent you want to see the activity.
+
+The activity list includes:
+
+- Agent registration events: when a new token is **created**.
+- Connection events: when an Agent is successfully **connected** to a cluster.
+
+Note that the connection status is logged when you connect an Agent for
+the first time or after more than an hour of inactivity.
-1. Go to your agent's configuration repository.
-1. From the sidebar, select **Infrastructure > Kubernetes clusters**.
+To check what else is planned for the Agent's UI and provide feedback,
+see the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
+
+### View vulnerabilities in cluster images **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6346) in GitLab 14.8 [with a flag](../../../../administration/feature_flags.md) named `cluster_vulnerabilities`. Enabled by default.
+
+Users with at least the [Developer role](../../../permissions.md)
+can view cluster vulnerabilities. You can access them through the [vulnerability report](../../../application_security/vulnerabilities/index.md)
+or in your cluster's image through the following process:
+
+1. Configure [cluster image scanning](../../../application_security/cluster_image_scanning/index.md)
+ to your build process.
+1. Go to your Agent's configuration repository.
+1. On the left sidebar, select **Infrastructure > Kubernetes clusters**.
1. Select the **Agent** tab.
-1. Select the agent you want to see the activity.
+1. Select the Agent you want to see the vulnerabilities for.
+
+![Cluster Agent security tab UI](../../img/cluster_agent_security_tab_v14_8.png)
+
+## Create multiple Agents
+
+You can create and install multiple Agents using the same process
+documented above. Give each Agent's configuration file a unique name
+and you're good to go. You can create multiple Agents, for example:
+
+- To reach your cluster from different projects.
+- To connect multiple clusters to GitLab.
+
+## Update the Agent version
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340882) in GitLab 14.8, GitLab warns you on the Agent's list page to update the Agent version installed on your cluster.
+
+To update the Agent's version on your cluster, you need to re-run the [installation command](#install-the-agent-onto-the-cluster)
+with a newer `--agent-version`. Make sure to specify the other required parameters: `--kas-address`, `--namespace`, and `--agent-token`.
+You can find the available `agentk` versions in [the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205?sort=desc).
-You can see the following events on the activity list:
+If you don't have access to your Agent's token, you can retrieve it from your cluster:
-- Agent registration:
- - When a new token is **created**.
-- Connection events:
- - When an agent is successfully **connected** to a cluster.
+1. On your computer, open the terminal and connect to your cluster.
+1. To retrieve the namespace, run:
-Note that the connection status is logged when you connect an agent for the first time
-or after more than an hour of inactivity.
+ ```shell
+ kubectl get namespaces
+ ```
-![GitLab Agent activity events UI](../../img/gitlab_agent_activity_events_v14_6.png)
+1. To retrieve the secret, run:
+
+ ```shell
+ kubectl -n <namespace> get secrets
+ ```
+
+1. To retrieve the token, run:
+
+ ```shell
+ kubectl -n <namespace> get secret <secret-name> --template={{.data.token}} | base64 --decode
+ ```
+
+## Example projects
+
+The following example projects can help you get started with the Agent.
+
+- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
+- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
## Upgrades and version compatibility
@@ -178,7 +271,8 @@ A feature introduced in a given GitLab minor version might work with other `agen
To make sure that it works, use at least the same `agentk` and `kas` minor version. For example,
if your GitLab version is 14.2, use at least `agentk` 14.2 and `kas` 14.2.
-We recommend upgrading your `kas` installations together with GitLab instances' upgrades, and to upgrade the `agentk` installations after upgrading GitLab.
+We recommend upgrading your `kas` installations together with GitLab instances' upgrades, and to
+[upgrade the `agentk` installations](#update-the-agent-version) after upgrading GitLab.
The available `agentk` and `kas` versions can be found in
[the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/).
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index 22964fde395..a9d9fd1c13d 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -40,6 +40,9 @@ 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.
+WARNING:
+When using separate GitLab projects for manifest files and configuration repository, the manifests project must be public.
+
To use multiple YAML files, specify a `paths` attribute in the `gitops.manifest_projects` section.
```yaml
@@ -150,26 +153,19 @@ gitops:
## Authorize projects and groups to use an Agent
-> - Group authorization [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-> - Project authorization [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327850) in GitLab 14.4.
-
-If you use the same cluster across multiple projects, you can set up the [CI/CD Tunnel](ci_cd_tunnel.md)
-to grant access to an Agent from one or more projects or groups. This way, all the authorized
-projects can access the same Agent, which facilitates you to save resources and have a scalable setup.
+With the [CI/CD Tunnel](ci_cd_tunnel.md), you can authorize [projects](#authorize-projects-to-use-an-agent)
+and [groups](#authorize-groups-to-use-an-agent) to use an Agent.
-When you authorize a project to use an agent through the [CI/CD Tunnel](ci_cd_tunnel.md),
-the selected Kubernetes context is automatically injected into CI/CD jobs, allowing you to
-run Kubernetes commands from your authorized projects' scripts. When you authorize a group,
-all the projects that belong to that group can access the selected agent.
-
-An Agent can only authorize projects or groups in the same group hierarchy as the Agent's configuration
-project. You can authorize up to 100 projects and 100 groups per Agent.
+Then, you can reach your cluster from authorized projects and [run Kubernetes commands from GitLab CI/CD scripts](#run-kubectl-commands-using-the-cicd-tunnel)
+in these projects.
### Authorize projects to use an Agent
-To grant projects access to the Agent through the [CI/CD Tunnel](ci_cd_tunnel.md):
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327850) in GitLab 14.4.
+
+To grant projects access to the Agent through the CI/CD Tunnel:
-1. Go to your Agent's configuration project.
+1. Go to your Agent's configuration repository.
1. Edit the Agent's configuration file (`config.yaml`).
1. Add the `projects` attribute into `ci_access`.
1. Identify the project through its path:
@@ -182,9 +178,11 @@ To grant projects access to the Agent through the [CI/CD Tunnel](ci_cd_tunnel.md
### Authorize groups to use an Agent
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
+
To grant access to all projects within a group:
-1. Go to your Agent's configuration project.
+1. Go to your Agent's configuration repository.
1. Edit the Agent's configuration file (`config.yaml`).
1. Add the `groups` attribute into `ci_access`.
1. Identify the group or subgroup through its path:
@@ -195,7 +193,64 @@ To grant access to all projects within a group:
- id: path/to/group/subgroup
```
-### Use impersonation to restrict project and group access **(PREMIUM)**
+## Run `kubectl` commands using the CI/CD Tunnel
+
+After you authorize your project or group to use the Agent, you need to
+configure the project's `.gitlab-ci.yaml` file to access the Agent.
+This makes it possible to deploy applications to your cluster and run
+any Kubernetes-specific commands from the authorized project.
+
+First, configure your Agent:
+
+1. Go to your Agent's configuration repository.
+1. Edit your Agent's `config.yaml` file authorizing the [project](#authorize-projects-to-use-an-agent) or [group](#authorize-groups-to-use-an-agent) you want to run Kubernetes commands from.
+
+Then, configure the other project:
+
+1. Go to the project where you want to run Kubernetes commands from.
+1. Edit your project's `.gitlab-ci.yml` file.
+1. Set your Agent's context in the first command of the script with the format `path/to/agent/repository:agent-name`.
+1. Run Kubernetes commands.
+
+For example:
+
+```yaml
+ deploy:
+ image:
+ name: bitnami/kubectl:latest
+ entrypoint: [""]
+ script:
+ - kubectl config use-context path/to/agent/repository:agent-name
+ - kubectl get pods
+```
+
+When you use the Agent, KubeContexts are named as `path/to/agent/repository:agent-name`.
+
+To get the list of available contexts:
+
+1. Open your terminal and connect to your cluster.
+1. Run `kubectl config get-contexts`.
+
+### `kubectl` commands not supported
+
+The commands `kubectl exec`, `kubectl cp`, and `kubectl attach` are not supported by the CI/CD tunnel.
+Anything else that uses the same API endpoints does not work either as they use the deprecated
+SPDY protocol.
+We [plan to add support for these features](https://gitlab.com/gitlab-org/gitlab/-/issues/346248)
+in a future version of GitLab.
+
+### `kubectl` requires TLS
+
+`kubectl` would never send credentials over an unencrypted connection. Self-managed users should ensure that their
+GitLab instance is configured with TLS for the CI/CD tunnel feature to work. Trying to use it without TLS
+would produce errors:
+
+```shell
+$ kubectl get pods
+error: You must be logged in to the server (the server has asked for the client to provide credentials)
+```
+
+## Use impersonation to restrict project and group access **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
@@ -211,11 +266,11 @@ You can impersonate:
- The CI job that accesses the cluster.
- A specific user or system account defined within the cluster.
-#### Impersonate the Agent
+### Impersonate the Agent
The Agent is impersonated by default. You don't need to do anything to impersonate it.
-#### Impersonate the CI job that accesses the cluster
+### Impersonate the CI job that accesses the cluster
To impersonate the CI job that accesses the cluster, add the `ci_job: {}` key-value
under the `access_as` key.
@@ -261,7 +316,7 @@ ci_access:
ci_job: {}
```
-#### Impersonate a static identity
+### Impersonate a static identity
For the given CI/CD Tunnel connection, you can use a static identity for the impersonation.
@@ -278,6 +333,13 @@ See the [official Kubernetes documentation for more details](https://kubernetes.
## Surface network security alerts from cluster to GitLab **(ULTIMATE)**
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Cilium integration is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
+
The GitLab Agent provides an [integration with Cilium](index.md#kubernetes-network-security-alerts).
To integrate, add a top-level `cilium` section to your `config.yml` file. Currently, the
only configuration option is the Hubble relay address:
diff --git a/doc/user/clusters/agent/troubleshooting.md b/doc/user/clusters/agent/troubleshooting.md
new file mode 100644
index 00000000000..2c9f98b7c45
--- /dev/null
+++ b/doc/user/clusters/agent/troubleshooting.md
@@ -0,0 +1,193 @@
+---
+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
+---
+
+# Troubleshooting the GitLab Agent for Kubernetes
+
+When you are using the GitLab Agent for Kubernetes, you might experience issues you need to troubleshoot.
+
+You can start by viewing the service logs:
+
+```shell
+kubectl logs -f -l=app=gitlab-agent -n gitlab-kubernetes-agent
+```
+
+If you are a GitLab administrator, you can also view the [GitLab Agent Server logs](../../../administration/clusters/kas.md#troubleshooting).
+
+## Transport: Error while dialing failed to WebSocket dial
+
+```json
+{
+ "level": "warn",
+ "time": "2020-11-04T10:14:39.368Z",
+ "msg": "GetConfiguration failed",
+ "error": "rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://gitlab-kas:443/-/kubernetes-agent\\\": dial tcp: lookup gitlab-kas on 10.60.0.10:53: no such host\""
+}
+```
+
+This error is shown if there are some connectivity issues between the address
+specified as `kas-address`, and your Agent pod. To fix it, make sure that you
+specified the `kas-address` correctly.
+
+```json
+{
+ "level": "error",
+ "time": "2021-06-25T21:15:45.335Z",
+ "msg": "Reverse tunnel",
+ "mod_name": "reverse_tunnel",
+ "error": "Connect(): rpc error: code = Unavailable desc = connection error: desc= \"transport: Error while dialing failed to WebSocket dial: expected handshake response status code 101 but got 301\""
+}
+```
+
+This error occurs if the `kas-address` doesn't include a trailing slash. To fix it, make sure that the
+`wss` or `ws` URL ends with a trailing slash, such as `wss://GitLab.host.tld:443/-/kubernetes-agent/`
+or `ws://GitLab.host.tld:80/-/kubernetes-agent/`.
+
+## ValidationError(Deployment.metadata)
+
+```json
+{
+ "level": "info",
+ "time": "2020-10-30T08:56:54.329Z",
+ "msg": "Synced",
+ "project_id": "root/kas-manifest001",
+ "resource_key": "apps/Deployment/kas-test001/nginx-deployment",
+ "sync_result": "error validating data: [ValidationError(Deployment.metadata): unknown field \"replicas\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"selector\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta, ValidationError(Deployment.metadata): unknown field \"template\" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta]"
+}
+```
+
+This error is shown if a manifest file is malformed, and Kubernetes can't
+create specified objects. Make sure that your manifest files are valid. You
+may try using them to create objects in Kubernetes directly for more troubleshooting.
+
+## Error while dialing failed to WebSocket dial: failed to send handshake request
+
+```json
+{
+ "level": "warn",
+ "time": "2020-10-30T09:50:51.173Z",
+ "msg": "GetConfiguration failed",
+ "error": "rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent\\\": net/http: HTTP/1.x transport connection broken: malformed HTTP response \\\"\\\\x00\\\\x00\\\\x06\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x05\\\\x00\\\\x00@\\\\x00\\\"\""
+}
+```
+
+This error is shown if you configured `wss` as `kas-address` on the agent side,
+but KAS on the server side is not available via `wss`. To fix it, make sure the
+same schemes are configured on both sides.
+
+It's not possible to set the `grpc` scheme due to the issue
+[It is not possible to configure KAS to work with `grpc` without directly editing GitLab KAS deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/276888). To use `grpc` while the
+issue is in progress, directly edit the deployment with the
+`kubectl edit deployment gitlab-kas` command, and change `--listen-websocket=true` to `--listen-websocket=false`. After running that command, you should be able to use
+`grpc://gitlab-kas.<YOUR-NAMESPACE>:8150`.
+
+## Decompressor is not installed for grpc-encoding
+
+```json
+{
+ "level": "warn",
+ "time": "2020-11-05T05:25:46.916Z",
+ "msg": "GetConfiguration.Recv failed",
+ "error": "rpc error: code = Unimplemented desc = grpc: Decompressor is not installed for grpc-encoding \"gzip\""
+}
+```
+
+This error is shown if the version of the agent is newer that the version of KAS.
+To fix it, make sure that both `agentk` and KAS use the same versions.
+
+## Certificate signed by unknown authority
+
+```json
+{
+ "level": "error",
+ "time": "2021-02-25T07:22:37.158Z",
+ "msg": "Reverse tunnel",
+ "mod_name": "reverse_tunnel",
+ "error": "Connect(): rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent/\\\": x509: certificate signed by unknown authority\""
+}
+```
+
+This error is shown if your GitLab instance is using a certificate signed by an internal CA that
+is unknown to the agent. One approach to fixing it is to present the CA certificate file to the agent
+via a Kubernetes `configmap` and mount the file in the agent `/etc/ssl/certs` directory from where it
+will be picked up automatically.
+
+For example, if your internal CA certificate is `myCA.pem`:
+
+```plaintext
+kubectl -n gitlab-kubernetes-agent create configmap ca-pemstore --from-file=myCA.pem
+```
+
+Then in `resources.yml`:
+
+```yaml
+ spec:
+ serviceAccountName: gitlab-kubernetes-agent
+ containers:
+ - name: agent
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
+ args:
+ - --token-file=/config/token
+ - --kas-address
+ - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent/
+ # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
+ # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
+ volumeMounts:
+ - name: token-volume
+ mountPath: /config
+ - name: ca-pemstore-volume
+ mountPath: /etc/ssl/certs/myCA.pem
+ subPath: myCA.pem
+ volumes:
+ - name: token-volume
+ secret:
+ secretName: gitlab-kubernetes-agent-token
+ - name: ca-pemstore-volume
+ configMap:
+ name: ca-pemstore
+ items:
+ - key: myCA.pem
+ path: myCA.pem
+```
+
+Alternatively, you can mount the certificate file at a different location and include it using the
+`--ca-cert-file` agent parameter:
+
+```yaml
+ containers:
+ - name: agent
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
+ args:
+ - --ca-cert-file=/tmp/myCA.pem
+ - --token-file=/config/token
+ - --kas-address
+ - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent/
+ # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
+ # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
+ volumeMounts:
+ - name: token-volume
+ mountPath: /config
+ - name: ca-pemstore-volume
+ mountPath: /tmp/myCA.pem
+ subPath: myCA.pem
+```
+
+## Project not found
+
+```json
+{
+ "level ":"error ",
+ "time ":"2022-01-05T15:18:11.331Z",
+ "msg ":"GetObjectsToSynchronize.Recv failed ",
+ "mod_name ":"gitops ",
+ "error ":"rpc error: code = NotFound desc = project not found ",
+}
+```
+
+This error is shown if the manifest project is not public. To fix it,
+[make sure your manifest project is public](repository.md#synchronize-manifest-projects) or your manifest files
+are stored in the Agent's configuration repository.
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 14850ca85b3..c99eef385ce 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -22,7 +22,7 @@ insights within GitLab:
## Configure cluster cost management
-To get started with cluster cost management, you need the [Maintainer role](../permissions.md) in a project or group.
+To get started with cluster cost management, you need the Maintainer role for a project or group.
1. Clone the [`kubecost-cost-model`](https://gitlab.com/gitlab-examples/kubecost-cost-model/)
example repository, which contains minor modifications to the upstream Kubecost
diff --git a/doc/user/clusters/img/cluster_agent_security_tab_v14_8.png b/doc/user/clusters/img/cluster_agent_security_tab_v14_8.png
new file mode 100644
index 00000000000..91d7e40429e
--- /dev/null
+++ b/doc/user/clusters/img/cluster_agent_security_tab_v14_8.png
Binary files differ
diff --git a/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png b/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png
deleted file mode 100644
index 90b41ee849c..00000000000
--- a/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png b/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png
deleted file mode 100644
index 3463eeb5d93..00000000000
--- a/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/clusters/img/kubernetes-agent-ui-list_v14_8.png b/doc/user/clusters/img/kubernetes-agent-ui-list_v14_8.png
new file mode 100644
index 00000000000..5b5ba3a9804
--- /dev/null
+++ b/doc/user/clusters/img/kubernetes-agent-ui-list_v14_8.png
Binary files differ
diff --git a/doc/user/clusters/migrating_from_gma_to_project_template.md b/doc/user/clusters/migrating_from_gma_to_project_template.md
index 20c4408d57e..b2ba1bef338 100644
--- a/doc/user/clusters/migrating_from_gma_to_project_template.md
+++ b/doc/user/clusters/migrating_from_gma_to_project_template.md
@@ -23,16 +23,16 @@ See also [video walk-throughs](#video-walk-throughs) with examples.
1. Create a new project based on the [Cluster Management Project template](management_project_template.md#create-a-new-project-based-on-the-cluster-management-template).
1. [Associate your new Cluster Management Project with your cluster](management_project.md#associate-the-cluster-management-project-with-the-cluster).
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:
+ - 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>
- ```
+ ```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.
+ - 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.
@@ -53,7 +53,7 @@ See also [video walk-throughs](#video-walk-throughs) with examples.
```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
```
@@ -67,39 +67,42 @@ See also [video walk-throughs](#video-walk-throughs) with examples.
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):
+ 1. Copy the output of the following command (it might be big):
- ```shell
- helm get values runner -n gitlab-managed-apps -a --output yaml
- ```
+ ```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.
+ 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`.
-
- - Cert-manager:
- - For users on Kubernetes version 1.20 or above, the deprecated cert-manager v0.10 is no longer valid and
- and the upgrade includes a breaking change. So we suggest that you [backup and uninstall cert-manager v0.10](#backup-and-uninstall-cert-manager-v010)
- , and install cert-manager v1.4 instead. To install this version, uncomment the `applications/cert-manager-1-4/helmfile.yaml`
- from the [`./helmfile.yaml`](management_project_template.md#the-main-helmfileyml-file).
- This triggers a pipeline to install the new version.
- - For users on Kubernetes versions lower than 1.20, you can stick to v0.10 by uncommenting
- `applications/cert-manager/helmfile.yaml`
- in your project's main Helmfile ([`./helmfile.yaml`](management_project_template.md#the-main-helmfileyml-file)).
+ - 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`.
+
+ - Cert-manager:
+ - For users on Kubernetes version 1.20 or above, the deprecated cert-manager v0.10 is no longer valid
+ and the upgrade includes a breaking change. So we suggest that you [backup and uninstall cert-manager v0.10](#backup-and-uninstall-cert-manager-v010),
+ and install the latest cert-manager instead. To install this version, uncomment `applications/cert-manager/helmfile.yaml`
+ from [`./helmfile.yaml`](management_project_template.md#the-main-helmfileyml-file).
+ This triggers a pipeline to install the new version.
+ - For users on Kubernetes versions lower than 1.20, you can stick to v0.10 by uncommenting
+ `applications/cert-manager-legacy/helmfile.yaml`
+ in your project's main Helmfile ([`./helmfile.yaml`](management_project_template.md#the-main-helmfileyml-file)).
+
+ WARNING:
+ Cert-manager v0.10 breaks when Kubernetes is upgraded to version 1.20 or later.
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
@@ -118,7 +121,7 @@ you want to manage with the Cluster Management Project.
## Backup and uninstall cert-manager v0.10
1. Follow the [official docs](https://docs.cert-manager.io/en/release-0.10/tasks/backup-restore-crds.html) on how to
- backup your cert-manager v0.10 data.
+ backup your cert-manager v0.10 data.
1. Uninstall cert-manager by editing the setting all the occurrences of `installed: true` to `installed: false` in the
`applications/cert-manager/helmfile.yaml` file.
1. Search for any left-over resources by executing the following command `kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges,Secrets,ConfigMaps -n gitlab-managed-apps | grep certmanager`.
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 04d3cc0595e..18de33ea03b 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -14,15 +14,9 @@ project's dependencies for their licenses. You can then decide whether to allow
each license. For example, if your application uses an external (open source) library whose license
is incompatible with yours, then you can deny the use of that license.
-You can take advantage of License Compliance by either:
+To detect the licenses in use, License Compliance uses the [License Finder](https://github.com/pivotal/LicenseFinder) scan tool that runs as part of the CI/CD pipeline. The License Compliance job is not dependent on any other job in
+a pipeline.
-- [Including the job](#configuration)
- in your existing `.gitlab-ci.yml` file.
-- Implicitly using
- [Auto License Compliance](../../../topics/autodevops/stages.md#auto-license-compliance),
- provided by [Auto DevOps](../../../topics/autodevops/index.md).
-
-To detect the licenses in use, License Compliance uses the [License Finder](https://github.com/pivotal/LicenseFinder) scan tool that runs as part of the CI/CD pipeline.
For the job to activate, License Finder needs to find a compatible package definition in the project directory. For details, see the [Activation on License Finder documentation](https://github.com/pivotal/LicenseFinder#activation).
GitLab checks the License Compliance report, compares the
licenses between the source and target branches, and shows the information right on the merge
@@ -39,6 +33,14 @@ is displayed in the merge request area. That is the case when you add the
Consecutive merge requests have something to compare to and the license
compliance report is shown properly.
+The results are saved as a
+[License Compliance report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportslicense_scanning)
+that you can later download and analyze. Due to implementation limitations, we
+always take the latest License Compliance artifact available.
+
+WARNING:
+License Compliance Scanning does not support run-time installation of compilers and interpreters.
+
![License Compliance Widget](img/license_compliance_v13_0.png)
You can select a license to see more information.
@@ -91,27 +93,26 @@ The reported licenses might be incomplete or inaccurate.
| Rust | [Cargo](https://crates.io) |
| PHP | [Composer](https://getcomposer.org/) |
-## Requirements
+## Enable License Compliance
-WARNING:
-License Compliance Scanning does not support run-time installation of compilers and interpreters.
+To enable License Compliance in your project's pipeline, either:
-To run a License Compliance scanning job, you need GitLab Runner with the
-[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
+- Enable [Auto License Compliance](../../../topics/autodevops/stages.md#auto-license-compliance)
+ (provided by [Auto DevOps](../../../topics/autodevops/index.md)).
+- Include 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) in your `.gitlab-ci.yml` file.
-## Configuration
+### Include the License Scanning template
-For GitLab 12.8 and later, to enable License Compliance, you must
-[include](../../../ci/yaml/index.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)
-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/index.md#includetemplate) the
-[`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.
+Prerequisites:
-Add the following to your `.gitlab-ci.yml` file:
+- [GitLab Runner](../../../ci/runners/index.md) available, with the
+ [`docker` executor](https://docs.gitlab.com/runner/executors/docker.html). If you're using the
+ shared runners on GitLab.com, this is enabled by default.
+- License Scanning runs in the `test` stage, which is available by default. If you redefine the stages in the
+ `.gitlab-ci.yml` file, the `test` stage is required.
+
+To [include](../../../ci/yaml/index.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), add it to your `.gitlab-ci.yml` file:
```yaml
include:
@@ -121,26 +122,6 @@ include:
The included template creates a `license_scanning` job in your CI/CD pipeline and scans your
dependencies to find their licenses.
-NOTE:
-Before GitLab 12.8, the `license_scanning` job was named `license_management`. GitLab 13.0 removes
-the `license_management` job, so you must migrate to the `license_scanning` job and use the new
-`License-Scanning.gitlab-ci.yml` template.
-
-The results are saved as a
-[License Compliance report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportslicense_scanning)
-that you can later download and analyze. Due to implementation limitations, we
-always take the latest License Compliance artifact available. Behind the scenes, the
-[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-cicd-variables) by using the
-[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
-
-### When License Compliance runs
-
-When using the GitLab `License-Scanning.gitlab-ci.yml` template, the License Compliance job doesn't
-wait for other stages to complete.
-
### Available CI/CD variables
License Compliance can be configured using CI/CD variables.
@@ -651,7 +632,7 @@ successfully run. For more information, see [Offline environments](../../applica
To use License Compliance in an offline environment, you need:
-- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
+- To meet the standard [License Compliance prerequisites](#include-the-license-scanning-template).
- Docker Container Registry with locally available copies of License Compliance [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images.
NOTE:
@@ -674,7 +655,7 @@ registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:latest
The process for importing Docker images into a local offline Docker registry depends on
**your network security policy**. Please consult your IT staff to find an accepted and approved
-process by which external resources can be imported or temporarily accessed. Note that these scanners are [updated periodically](../../application_security/vulnerabilities/index.md#vulnerability-scanner-maintenance)
+process by which external resources can be imported or temporarily accessed. Note that these scanners are [updated periodically](../../application_security/index.md#vulnerability-scanner-maintenance)
with new definitions, so consider if you are able to make periodic updates yourself.
For details on saving and transporting Docker images as a file, see Docker's documentation on
@@ -729,7 +710,7 @@ details about them.
For the licenses to appear under the license list, the following
requirements must be met:
-1. The License Compliance CI job must be [configured](#configuration) for your project.
+1. The License Compliance CI/CD job must be [enabled](#enable-license-compliance) for your project.
1. Your project must use at least one of the
[supported languages and package managers](#supported-languages-and-package-managers).
@@ -772,7 +753,7 @@ Developers of the project can view the policies configured in a project.
Prerequisites:
-- Maintainer or Owner [role](../../permissions.md#project-members-permissions).
+- Maintainer or Owner role.
`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`
diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md
index f0f9a907a73..305cca33dd5 100644
--- a/doc/user/crm/index.md
+++ b/doc/user/crm/index.md
@@ -6,7 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Customer relations management (CRM) **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.6 [with a flag](../../administration/feature_flags.md) named `customer_relations`. Disabled by default.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.6 [with a flag](../../administration/feature_flags.md) named `customer_relations`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `customer_relations`.
+On GitLab.com, this feature is not available.
With customer relations management (CRM) you can create a record of contacts
(individuals) and organizations (companies) and relate them to issues.
@@ -133,7 +137,7 @@ API.
### Add contacts to an issue
-To add contacts to an issue use the `/add_contacts`
+To add contacts to an issue use the `/add_contacts [contact:address@example.com]`
[quick action](../project/quick_actions.md).
You can also add, remove, or replace issue contacts using the
@@ -142,9 +146,25 @@ API.
### Remove contacts from an issue
-To remove contacts from an issue use the `/remove_contacts`
+To remove contacts from an issue use the `/remove_contacts [contact:address@example.com]`
[quick action](../project/quick_actions.md).
You can also add, remove, or replace issue contacts using the
[GraphQL](../../api/graphql/reference/index.md#mutationissuesetcrmcontacts)
API.
+
+## Autocomplete contacts **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `contacts_autocomplete`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `contacts_autocomplete`.
+On GitLab.com, this feature is not available.
+This feature is not ready for production use.
+
+When you use the `/add_contacts` or `/remove_contacts` quick actions, follow them with `[contact:` and an autocomplete list appears:
+
+```plaintext
+/add_contacts [contact:
+/remove_contacts [contact:
+```
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 7831fdff249..37047e9f8d0 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -115,8 +115,7 @@ You can use [Markdown](../markdown.md) and [quick actions](../project/quick_acti
You can edit your own comment at any time.
-Anyone with the [Maintainer role](../permissions.md) or
-higher can also edit a comment made by someone else.
+Anyone with at least the Maintainer role can also edit a comment made by someone else.
## Prevent comments by locking an issue
@@ -209,7 +208,7 @@ When you reply to a standard comment, you create a thread.
Prerequisites:
-- You must have at least the [Guest role](../permissions.md#project-members-permissions).
+- You must have at least the Guest role.
- You must be in an issue, merge request, or epic. Threads in commits and snippets are not supported.
To create a thread by replying to a comment:
@@ -231,7 +230,7 @@ You can create a thread without replying to a standard comment.
Prerequisites:
-- You must have at least the [Guest role](../permissions.md#project-members-permissions).
+- You must have at least the Guest role.
- You must be in an issue, merge request, commit, or snippet.
To create a thread:
@@ -253,7 +252,7 @@ In a merge request, you can resolve a thread when you want to finish a conversat
Prerequisites:
-- You must have at least the [Developer role](../permissions.md#project-members-permissions)
+- You must have at least the Developer role
or be the author of the change being reviewed.
- Resolvable threads can be added only to merge requests. It doesn't work
for comments in issues, commits, or snippets.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index f02073b477b..80ee8d23a35 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -122,6 +122,8 @@ Below are the settings for [GitLab Pages](https://about.gitlab.com/stages-devops
The maximum size of your Pages site is regulated by the artifacts maximum size,
which is part of [GitLab CI/CD](#gitlab-cicd).
+There are also [rate limits set for GitLab Pages](#gitlabcom-specific-rate-limits).
+
## GitLab CI/CD
Below are the current settings regarding [GitLab CI/CD](../../ci/index.md).
@@ -310,17 +312,19 @@ limiting responses](#rate-limiting-responses).
The following table describes the rate limits for GitLab.com, both before and
after the limits change in January, 2021:
-| Rate limit | Before 2021-01-18 | From 2021-01-18 | From 2021-02-12 |
-|:--------------------------------------------------------------------------|:----------------------------|:------------------------------|:------------------------------|
-| **Protected paths** (for a given **IP address**) | **10** requests per minute | **10** requests per minute | **10** requests per minute |
-| **Raw endpoint** traffic (for a given **project, commit, and file path**) | **300** requests per minute | **300** requests per minute | **300** requests per minute |
-| **Unauthenticated** traffic (from a given **IP address**) | No specific limit | **500** requests per minute | **500** requests per minute |
-| **Authenticated** API traffic (for a given **user**) | No specific limit | **2,000** requests per minute | **2,000** requests per minute |
-| **Authenticated** non-API HTTP traffic (for a given **user**) | No specific limit | **1,000** requests per minute | **1,000** requests per minute |
-| **All** traffic (from a given **IP address**) | **600** requests per minute | **2,000** requests per minute | **2,000** requests per minute |
-| **Issue creation** | | **300** requests per minute | **300** requests per minute |
-| **Note creation** (on issues and merge requests) | | **300** requests per minute | **60** requests per minute |
-| **Advanced, project, and group search** API (for a given **IP address**) | | | **10** requests per minute |
+| Rate limit | Before 2021-02-12 | From 2021-02-12 | From 2022-02-03 |
+|:--------------------------------------------------------------------------|:------------------------------|:------------------------------|:----------------------------------------|
+| **Protected paths** (for a given **IP address**) | **10** requests per minute | **10** requests per minute | **10** requests per minute |
+| **Raw endpoint** traffic (for a given **project, commit, and file path**) | **300** requests per minute | **300** requests per minute | **300** requests per minute |
+| **Unauthenticated** traffic (from a given **IP address**) | **500** requests per minute | **500** requests per minute | **500** requests per minute |
+| **Authenticated** API traffic (for a given **user**) | **2,000** requests per minute | **2,000** requests per minute | **2,000** requests per minute |
+| **Authenticated** non-API HTTP traffic (for a given **user**) | **1,000** requests per minute | **1,000** requests per minute | **1,000** requests per minute |
+| **All** traffic (from a given **IP address**) | **2,000** requests per minute | **2,000** requests per minute | **2,000** requests per minute |
+| **Issue creation** | **300** requests per minute | **300** requests per minute | **300** requests per minute |
+| **Note creation** (on issues and merge requests) | **300** requests per minute | **60** requests per minute | **60** requests per minute |
+| **Advanced, project, and group search** API (for a given **IP address**) | | **10** requests per minute | **10** requests per minute |
+| **GitLab Pages** requests (for a given **IP address**) | | | **1000** requests per **50 seconds** |
+| **GitLab Pages** requests (for a given **GitLab Pages domain**) | | | **5000** requests per **10 seconds** |
More details are available on the rate limits for [protected
paths](#protected-paths-throttle) and [raw
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index 76a8eb77e72..3b866c4a1b0 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -11,8 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
With Contribution Analytics, you can get an overview of the [contribution events](../../index.md#user-contribution-events) in your
group.
-- Analyze your team's contributions over a period of time, and offer a bonus for the top
- contributors.
+- Analyze your team's contributions over a period of time.
- Identify opportunities for improvement with group members who may benefit from additional
support.
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 2214a18475a..00e6bc671c1 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -24,7 +24,7 @@ You can also configure [custom templates for the instance](../admin_area/custom_
Prerequisite:
-- You must have the [Owner role for the group](../permissions.md#group-members-permissions).
+- You must have the Owner role for the group.
To set up custom project templates in a group, add the subgroup that contains the
project templates to the group settings:
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index 4151745189d..333bef84dcc 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Group DevOps Adoption **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321083) in GitLab 13.11 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321083) in GitLab 13.11 as a [Beta feature](../../../policy/alpha-beta-support.md#beta-features).
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/333556) in GitLab 14.1.
> - The Overview tab [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330401) in GitLab 14.1.
> - DAST and SAST metrics [added](https://gitlab.com/gitlab-org/gitlab/-/issues/328033) in GitLab 14.1.
@@ -32,7 +32,7 @@ how to use those features.
Prerequisite:
-- You must have at least the [Reporter role](../../permissions.md) for the group.
+- You must have at least the Reporter role for the group.
To view DevOps Adoption:
diff --git a/doc/user/group/epics/epic_boards.md b/doc/user/group/epics/epic_boards.md
index d184030718a..f03a56d8a00 100644
--- a/doc/user/group/epics/epic_boards.md
+++ b/doc/user/group/epics/epic_boards.md
@@ -24,7 +24,7 @@ To view an epic board:
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
To create a new epic board:
@@ -49,7 +49,7 @@ To change these options later, [edit the board](#edit-the-scope-of-an-epic-board
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
- A minimum of two boards present in a group.
To delete the active epic board:
@@ -73,7 +73,7 @@ To delete the active epic board:
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
To create a new list:
@@ -91,7 +91,7 @@ list view that's removed. You can always create it again later if you need.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
To remove a list from an epic board:
@@ -106,7 +106,7 @@ To remove a list from an epic board:
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
- You must have [created a list](#create-a-new-list) first.
To create an epic from a list in epic board:
@@ -147,7 +147,7 @@ You can move epics and lists by dragging them.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
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).
@@ -170,7 +170,7 @@ and the target list.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md#group-members-permissions) for a group.
+- You must have at least the Reporter role for a group.
To edit the scope of an epic board:
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index caca10a05a2..3350b0f1169 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -83,7 +83,7 @@ To edit an epic's start date, due date, or labels:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7250) in GitLab 12.2.
-Users with at least the [Reporter role](../../permissions.md) can manage epics.
+Users with at least the Reporter role can manage epics.
When bulk editing epics in a group, you can edit their labels.
@@ -98,8 +98,7 @@ To update multiple epics at the same time:
## Delete an epic
NOTE:
-To delete an epic, you must be an [Owner](../../permissions.md#group-members-permissions) of a group
-or subgroup.
+To delete an epic, you must be an Owner of a group or subgroup.
To delete the epic:
@@ -165,6 +164,7 @@ than 1000. The cached value is rounded to thousands or millions and updated ever
> - Sorting by epic titles [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.1.
> - Searching by milestone and confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268372) in GitLab 14.2 [with a flag](../../../administration/feature_flags.md) named `vue_epics_list`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/276189) in GitLab 14.7.
+> - [Feature flag `vue_epics_list`](https://gitlab.com/gitlab-org/gitlab/-/issues/327320) removed in GitLab 14.8.
You can search for an epic from the list of epics using filtered search bar based on following
parameters:
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 70406cfe8e8..cdc3fe02a53 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -10,20 +10,81 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7 [with a flag](../../feature_flags.md) named `bulk_import`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338985) in GitLab 14.3.
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `bulk_import`. On GitLab.com, this feature is available.
+
+You can migrate your existing top-level groups to any of the following:
+
+- Another GitLab instance, including GitLab.com.
+- Another top-level group.
+- The subgroup of any existing top-level group.
+
+Migrating groups is not the same as [group import/export](../settings/import_export.md).
+
+- Group import/export requires you to export a group to a file and then import that file in
+ another GitLab instance.
+- Group migration automates this process.
+
+## Import your groups into GitLab
+
+When you migrate a group, you connect to your GitLab instance and then choose
+groups to import. Not all the data is migrated. View the
+[Migrated resources](#migrated-resources) list for details.
+
+Leave feedback about group migration in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495).
+
NOTE:
-The importer migrates **only** the group data listed on this page. To leave feedback on this
-feature, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495).
+You might need to reconfigure your firewall to prevent blocking the connection on the self-managed
+instance.
+
+### Connect to the remote GitLab instance
-Using GitLab Group Migration, you can migrate existing top-level groups from GitLab.com or a self-managed instance. Groups can be migrated to a target instance, as a top-level group, or as a subgroup of any existing top-level group.
+Before you begin, ensure that the target GitLab instance can communicate with the source over HTTPS
+(HTTP is not supported). You might need to reconfigure your firewall to prevent blocking the connection on the self-managed
+instance.
-The following resources are migrated to the target instance:
+Then create the group you want to import into, and connect:
+
+1. Create a new group or subgroup:
+
+ - On the top bar, select `+` and then **New group**.
+ - Or, on an existing group's page, in the top right, select **New subgroup**.
+
+1. Select **Import group**.
+1. Enter the source URL of your GitLab instance.
+1. Generate or copy a [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the `api` and `read_repository` scopes on your remote GitLab instance.
+1. Enter the [personal access token](../../../user/profile/personal_access_tokens.md) for your remote GitLab instance.
+1. Select **Connect instance**.
+
+### Select the groups to import
+
+After you have authorized access to the GitLab instance, you are redirected to the GitLab Group
+Migration importer page. The remote groups you have the Owner role for 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.
+1. Next to the groups you want to import, select **Import**.
+1. The **Status** column shows the import status of each group. If you leave the page open, it updates in real-time.
+1. After a group has been imported, select its GitLab path to open its GitLab URL.
+
+![Group Importer page](img/bulk_imports_v14_1.png)
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](../../project/import/index.md#automate-group-and-project-import).
+
+## Migrated resources
+
+Only the following resources are migrated to the target instance. Any other items are **not**
+migrated:
- Groups ([Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4374) in 13.7)
- description
- attributes
- subgroups
- avatar ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322904) in 14.0)
-- Group Labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) in 13.9)
+- Group labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) in 13.9)
- title
- description
- color
@@ -71,67 +132,3 @@ The following resources are migrated to the target instance:
- image URL
- Boards
- Board Lists
-
-Any other items are **not** migrated.
-
-## Enable or disable GitLab Group Migration
-
-GitLab Migration is deployed behind the `bulk_import` feature flag, which 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(:bulk_import)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:bulk_import)
-```
-
-## Import your groups into GitLab
-
-Before you begin, ensure that the target instance of GitLab can communicate with the source
-over HTTPS (HTTP is not supported).
-
-NOTE:
-This might involve reconfiguring your firewall to prevent blocking connection on the side of self-managed instance.
-
-### Connect to the remote GitLab instance
-
-1. Go to the New Group page:
-
- - On the top bar, select `+` and then **New group**.
- - Or, on an existing group's page, in the top right, select **New subgroup**.
-
- ![Navigation paths to create a new group](img/new_group_navigation_v13_8.png)
-
-1. On the New Group page, select **Import group**.
-
- ![Fill in import details](img/import_panel_v14_1.png)
-
-1. Enter the source URL of your GitLab instance.
-1. Generate or copy a [personal access token](../../../user/profile/personal_access_tokens.md)
- with the `api` and `read_repository` scopes on your remote GitLab instance.
-1. Enter the [personal access token](../../../user/profile/personal_access_tokens.md) for your remote GitLab instance.
-1. Select **Connect instance**.
-
-### Selecting which groups to import
-
-After you have authorized access to the GitLab instance, you are redirected to the GitLab Group
-Migration importer page. The remote groups you have the Owner role for 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.
-1. Next to the groups you want to import, select **Import**.
-1. The **Status** column shows the import status of each group. If you leave the page open, it updates in real-time.
-1. After a group has been imported, select its GitLab path to open its GitLab URL.
-
-![Group Importer page](img/bulk_imports_v14_1.png)
-
-## Automate group and project import **(PREMIUM)**
-
-For information on automating user, group, and project import API calls, see
-[Automate group and project import](../../project/import/index.md#automate-group-and-project-import).
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 8aa9b8e799d..ec76dc52516 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -68,19 +68,9 @@ To create a group:
- 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
- - Underscores
- - Dashes, dots, spaces, and parentheses (however, it cannot start with any of these characters)
-
- For a list of words that cannot be used as group names, see [reserved names](../reserved_names.md).
-
-1. For the **Group URL**, which is used for the [namespace](#namespaces),
- use only:
- - Alphanumeric characters
- - Underscores
- - Dashes and dots (it cannot start with dashes or end in a dot)
+1. Enter a name for the group in **Group name**. For a list of words that cannot be used as group names, see
+ [reserved names](../reserved_names.md).
+1. Enter a path for the group in **Group URL**, which is used for the [namespace](#namespaces).
1. Choose the [visibility level](../../public_access/public_access.md).
1. Personalize your GitLab experience by answering the following questions:
- What is your role?
@@ -138,7 +128,7 @@ 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 the [Owner role](../permissions.md#group-members-permissions).
+member with the Owner role.
- As an administrator:
1. Go to the group and from the left menu, select **Group information > Members**.
@@ -153,7 +143,7 @@ member with the [Owner role](../permissions.md#group-members-permissions).
Prerequisites:
-- You must have the [Owner role](../permissions.md#group-members-permissions).
+- You must have the Owner role.
- 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.
@@ -250,7 +240,7 @@ There are two different ways to add a new project to a group:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) in GitLab 10.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) from GitLab Premium to GitLab Free in 11.10.
-By default, [Developers and Maintainers](../permissions.md#group-members-permissions) can create projects under a group.
+By default, users with at least the Developer role can create projects under a group.
To change this setting for a specific group:
@@ -290,10 +280,15 @@ To view the activity feed in Atom format, select the
## Share a group with another group
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../feature_flags.md). Disabled by default.
+> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
-NOTE:
-In GitLab 13.11, you can [replace this form with a modal window](#share-a-group-modal-window).
+FLAG:
+On self-managed GitLab, by default the modal window feature is available.
+To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md)
+named `invite_members_group_modal`.
+On GitLab.com, this feature is available.
Similar to how you [share a project with a group](../project/members/share_project_with_groups.md),
you can share a group with another group. Members get direct access
@@ -303,35 +298,14 @@ To share a given group, for example, `Frontend` with another group, for example,
`Engineering`:
1. Go to the `Frontend` group.
-1. From the left menu, select **Group information > Members**.
-1. Select the **Invite group** tab.
+1. On the left sidebar, select **Group information > Members**.
+1. Select **Invite a group**.
1. In the **Select a group to invite** list, select `Engineering`.
-1. For the **Max role**, select a [role](../permissions.md).
+1. Select a [role](../permissions.md).
1. Select **Invite**.
All the members of the `Engineering` group are added to the `Frontend` group.
-### Share a group modal window
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
-> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - Enabled on GitLab.com.
-> - Recommended for production use.
-> - Replaces the existing form with buttons to open a modal window.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../project/members/index.md#enable-or-disable-modal-window).
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-In GitLab 13.11, you can optionally replace the sharing form with a modal window.
-To share a group after enabling this feature:
-
-1. Go to your group's page.
-1. On the left sidebar, go to **Group information > Members**, and then select **Invite a group**.
-1. Select a group, and select a **Max role**.
-1. Optional. Select an **Access expiration date**.
-1. Select **Invite**.
-
## Manage group memberships via LDAP **(PREMIUM SELF)**
Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that will be associated with GitLab groups.
@@ -432,10 +406,22 @@ for the group's projects to meet your group's needs.
To remove a group and its contents:
-1. Go to your group's **Settings > General** page.
-1. Expand the **Path, transfer, remove** section.
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Advanced** section.
+1. In the **Remove group** section, select **Remove group**.
+1. Type the group name.
+1. Select **Confirm**.
+
+A group can also be removed from the groups dashboard:
+
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Select (**{ellipsis_v}**) for the group you want to delete.
+1. Select **Delete**.
1. In the Remove group section, select **Remove group**.
-1. Confirm the action.
+1. Type the group name.
+1. Select **Confirm**.
This action removes the group. It also adds a background job to delete all projects in the group.
@@ -534,7 +520,7 @@ disabled for the group and its subgroups.
Prerequisite:
-- You must be assigned the [Owner role](../permissions.md#group-members-permissions) for the group.
+- You must be assigned the Owner role) for the group.
To specify a user cap:
@@ -556,7 +542,7 @@ You can remove the user cap, so there is no limit on the number of members you c
Prerequisite:
-- You must be assigned the [Owner role](../permissions.md#group-members-permissions) for the group.
+- You must be assigned the Owner role) for the group.
To remove the user cap:
@@ -575,7 +561,7 @@ and must be approved.
Prerequisite:
-- You must be assigned the [Owner role](../permissions.md#group-members-permissions) for the group.
+- You must be assigned the Owner role) for the group.
To approve members that are pending because they've exceeded the user cap:
@@ -651,7 +637,7 @@ To restrict group access by IP address:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
-1. In the **Allow access to the following IP addresses** field, enter IP address ranges in CIDR notation.
+1. In the **Allow access to the following IP addresses** field, enter IPv4 or IPv6 address ranges in CIDR notation.
1. Select **Save changes**.
![Domain restriction by IP address](img/restrict-by-ip.gif)
@@ -803,7 +789,7 @@ Existing forks are not removed.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
Group push rules allow group maintainers to set
-[push rules](../../push_rules/push_rules.md) for newly created projects in the specific group.
+[push rules](../project/repository/push_rules.md) for newly created projects in the specific group.
To configure push rules for a group:
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 8a79effba15..c0bd6f1a672 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -52,7 +52,7 @@ With iteration cadences enabled, you must first
Prerequisites:
-- You must have at least the [Developer role](../../permissions.md) for a group.
+- You must have at least the Developer role for a group.
To create an iteration cadence:
@@ -65,7 +65,7 @@ To create an iteration cadence:
Prerequisites:
-- You must have at least the [Developer role](../../permissions.md) for a group.
+- You must have at least the Developer role for a group.
Deleting an iteration cadence also deletes all iterations within that cadence.
@@ -86,7 +86,7 @@ From there you can create a new iteration or select an iteration to get a more d
Prerequisites:
-- You must have at least the [Developer role](../../permissions.md) for a group.
+- You must have at least the Developer role for a group.
For manually scheduled iteration cadences, you create and add iterations yourself.
@@ -104,7 +104,7 @@ To create an iteration:
Prerequisites:
-- You must have at least the [Developer role](../../permissions.md) for a group.
+- You must have at least the Developer role for a group.
To edit an iteration, select the three-dot menu (**{ellipsis_v}**) > **Edit**.
@@ -114,7 +114,7 @@ To edit an iteration, select the three-dot menu (**{ellipsis_v}**) > **Edit**.
Prerequisites:
-- You must have at least the [Developer role](../../permissions.md) for a group.
+- You must have at least the Developer role for a group.
To delete an iteration, select the three-dot menu (**{ellipsis_v}**) > **Delete**.
diff --git a/doc/user/group/planning_hierarchy/img/view-project-work-item-hierarchy_v14_8.png b/doc/user/group/planning_hierarchy/img/view-project-work-item-hierarchy_v14_8.png
new file mode 100644
index 00000000000..2ddd551ee46
--- /dev/null
+++ b/doc/user/group/planning_hierarchy/img/view-project-work-item-hierarchy_v14_8.png
Binary files differ
diff --git a/doc/user/group/planning_hierarchy/index.md b/doc/user/group/planning_hierarchy/index.md
index 5887328abe4..934421e8a9a 100644
--- a/doc/user/group/planning_hierarchy/index.md
+++ b/doc/user/group/planning_hierarchy/index.md
@@ -5,7 +5,7 @@ group: Product Planning
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
---
-# Planning hierarchies **(PREMIUM)**
+# Planning hierarchies **(FREE)**
Planning hierarchies are an integral part of breaking down your work in GitLab.
To understand how you can use epics and issues together in hierarchies, remember the following:
@@ -20,7 +20,21 @@ To learn about hierarchies in general, common frameworks, and using GitLab for
portfolio management, see
[How to use GitLab for Agile portfolio planning and project management](https://about.gitlab.com/blog/2020/11/11/gitlab-for-agile-portfolio-planning-project-management/).
-## Hierarchies with epics
+## View planning hierarchies
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340844/) in GitLab 14.8.
+
+To view the planning hierarchy in a project:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Planning hierarchy**.
+
+Under **Current structure**, you can see a hierarchy diagram that matches your current planning hierarchy.
+The work items outside your subscription plan show up below **Unavailable structure**.
+
+![Screenshot showing hierarchy page](img/view-project-work-item-hierarchy_v14_8.png)
+
+## Hierarchies with epics **(PREMIUM)**
With epics, you can achieve the following hierarchy:
@@ -54,14 +68,14 @@ Epic "1"*-- "0..*" Issue
![Diagram showing possible relationships of multi-level epics](img/hierarchy_with_multi_level_epics.png)
-## View ancestry of an epic
-
-In an epic, you can view the ancestors as parents in the right sidebar under **Ancestors**.
-
-![epics state dropdown](img/epic-view-ancestors-in-sidebar_v14_6.png)
-
## View ancestry of an issue
In an issue, you can view the parented epic above the issue in the right sidebar under **Epic**.
![epics state dropdown](img/issue-view-parent-epic-in-sidebar_v14_6.png)
+
+## View ancestry of an epic **(PREMIUM)**
+
+In an epic, you can view the ancestors as parents in the right sidebar under **Ancestors**.
+
+![epics state dropdown](img/epic-view-ancestors-in-sidebar_v14_6.png)
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index 2487ab188e8..6e3ea7d6c0f 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -1,7 +1,6 @@
---
-type: reference
stage: Verify
-group: Testing
+group: Pipeline 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
---
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 7d489bc5b2d..f10dc3bc22a 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -72,6 +72,26 @@ You can also filter epics in the Roadmap view by the epics':
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
+### Roadmap settings
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345158) in GitLab 14.8 [with a flag](../../../administration/feature_flags.md) named `roadmap_settings`. Enabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `roadmap_settings`.
+On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
+
+When you enable the roadmap settings sidebar, you can use it to refine epics shown in the roadmap.
+
+You can configure the following:
+
+- Select date range.
+- Turn milestones on or off and select whether to show all, group, sub-group, or project milestones.
+- Show all, open, or closed epics.
+- Turn progress tracking for child issues on or off and select whether
+ to use issue weights or counts.
+
+ The progress tracking setting is not saved in user preferences but is saved or shared using URL parameters.
+
## Timeline duration
> - Introduced in GitLab 11.0.
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 06e666f4d24..aeb7db923a9 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 20ff4a201f5..14c4447c5c6 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -1,7 +1,7 @@
---
type: reference, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -21,7 +21,7 @@ SAML SSO is only configurable at the top-level group.
If required, you can find [a glossary of common terms](../../../integration/saml.md#glossary-of-common-terms).
-## Configuring your identity provider
+## Configure your identity provider
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > SAML SSO**.
@@ -32,7 +32,7 @@ If required, you can find [a glossary of common terms](../../../integration/saml
1. Configure the required [user attributes](#user-attributes), ensuring you include the user's email address.
1. While the default is enabled for most SAML providers, please ensure the app is set to have service provider
initiated calls in order to link existing GitLab accounts.
-1. Once the identity provider is set up, move on to [configuring GitLab](#configuring-gitlab).
+1. Once the identity provider is set up, move on to [configuring GitLab](#configure-gitlab).
![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png)
@@ -82,7 +82,7 @@ GitLab provides metadata XML that can be used to configure your identity provide
1. Copy the provided **GitLab metadata URL**.
1. Follow your identity provider's documentation and paste the metadata URL when it's requested.
-## Configuring GitLab
+## Configure GitLab
After you set up your identity provider to work with GitLab, you must configure GitLab to use it for authentication:
@@ -108,7 +108,9 @@ The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-co
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/339888) in GitLab 14.7 to not enforce SSO checks for Git activity originating from CI/CD jobs.
-With this option enabled, users (except users with the Owner role) must access GitLab using your group GitLab single sign-on URL to access group resources. Users added manually as members can't access group resources.
+With this option enabled, users must access GitLab using your group GitLab single sign-on URL to access group resources.
+Users can't be added as new members manually.
+Users with the Owner role can use the standard sign in process to make necessary changes to top-level group settings.
SSO enforcement does not affect sign in or access to any resources outside of the group. Users can view which groups and projects they are a member of without SSO sign in.
@@ -116,7 +118,7 @@ However, users are not prompted to sign in through SSO on each visit. GitLab che
has authenticated through SSO. If it's been more than 1 day since the last sign-in, GitLab
prompts the user to sign in again through SSO.
-We intend to add a similar SSO requirement for [API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/297389).
+An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/297389) to add a similar SSO requirement for API activity.
SSO has the following effects when enabled:
@@ -127,7 +129,6 @@ SSO has the following effects when enabled:
- Git activity originating from CI/CD jobs do not have the SSO check enforced.
- Credentials that are not tied to regular users (for example, access tokens and deploy keys) do not have the SSO check enforced.
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
-<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
When SSO is enforced, users are not immediately revoked. If the user:
@@ -139,7 +140,7 @@ When SSO is enforced, users are not immediately revoked. If the user:
The SAML standard means that you can use a wide range of identity providers with GitLab. Your identity provider might have relevant documentation. It can be generic SAML documentation or specifically targeted for GitLab.
-When [configuring your identity provider](#configuring-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
+When [configuring your identity provider](#configure-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#notes-on-configuring-your-identity-provider)
for additional guidance on information your identity provider may require.
@@ -293,12 +294,16 @@ convert the information to XML. An example SAML response is shown here.
### Role
-Starting from [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/214523), group owners can set a 'Default membership role' other than 'Guest'. To do so, [configure the SAML SSO for the group](#configuring-gitlab). That role becomes the starting access level of all users added to the group.
+Starting from [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/214523), group owners can set a
+"Default membership role" other than Guest. To do so, [configure the SAML SSO for the group](#configure-gitlab).
+That role becomes the starting access level of all users added to the group.
Existing members with appropriate privileges can promote or demote users, as needed.
If a user is already a member of the group, linking the SAML identity does not change their role.
+Users given a "minimal access" role have [specific restrictions](../../permissions.md#users-with-minimal-access).
+
### Blocking access
To rescind a user's access to the group when only SAML SSO is configured, either:
@@ -336,6 +341,13 @@ For example, to unlink the `MyOrg` account:
## Group Sync
+WARNING:
+Changing Group Sync configuration can remove users from the relevant GitLab group.
+Removal happens if there is any mismatch between the group names and the list of `groups` in the SAML response.
+If changes must be made, ensure either the SAML response includes the `groups` attribute
+and the `AttributeValue` value matches the **SAML Group Name** in GitLab,
+or that all groups are removed from GitLab to disable Group Sync.
+
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of Group Sync using Azure, see [Demo: SAML Group Sync](https://youtu.be/Iqvo2tJfXjg).
@@ -353,10 +365,6 @@ Ensure your SAML identity provider sends an attribute statement named `Groups` o
</saml:AttributeStatement>
```
-WARNING:
-Setting up Group Sync can disconnect users from SAML IDP if there is any mismatch in the configuration. Ensure the
-`Groups` attribute is included in the SAML response, and the **SAML Group Name** matches the `AttributeValue` attribute.
-
Other attribute names such as `http://schemas.microsoft.com/ws/2008/06/identity/claims/groups`
are not accepted as a source of groups.
See the [SAML troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md)
@@ -533,7 +541,7 @@ This can then be compared to the [NameID](#nameid) being sent by the identity pr
If you receive a `404` during setup when using "verify configuration", make sure you have used the correct
[SHA-1 generated fingerprint](../../../integration/saml.md#notes-on-configuring-your-identity-provider).
-If a user is trying to sign in for the first time and the GitLab single sign-on URL has not [been configured](#configuring-your-identity-provider), they may see a 404.
+If a user is trying to sign in for the first time and the GitLab single sign-on URL has not [been configured](#configure-your-identity-provider), they may see a 404.
As outlined in the [user access section](#linking-saml-to-your-existing-gitlabcom-account), a group Owner needs to provide the URL to users.
### Message: "SAML authentication failed: Extern UID has already been taken"
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index d7d663f4115..d1e9ba29378 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -1,7 +1,7 @@
---
type: howto, reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -49,22 +49,21 @@ Once [Group Single Sign-On](index.md) has been configured, we can:
### Azure configuration steps
-The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM.
+The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM. You can refer to [Azure SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#getting-started).
-1. Enable automatic provisioning and administrative credentials by following the
- [Azure's SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim).
+1. In your app, go to the Provisioning tab, and set the **Provisioning Mode** to **Automatic**.
+ Then fill in the **Admin Credentials**, and save. The **Tenant URL** and **secret token** are the items
+ retrieved in the [previous step](#gitlab-configuration).
-During this configuration, note the following:
+1. After saving, two more tabs appear:
-- The `Tenant URL` and `secret token` are the items retrieved in the
- [previous step](#gitlab-configuration).
-- We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox.
-- For mappings, we only leave `Synchronize Azure Active Directory Users to AppName` enabled.
- `Synchronize Azure Active Directory Groups to AppName` is usually disabled. However, this
- does not mean Azure AD users cannot be provisioned in groups. Leaving it enabled does not break
- the SCIM user provisioning, but causes errors in Azure AD that may be confusing and misleading.
+ - **Settings**: We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox.
+ You also control what is actually synced by selecting the **Scope**. For example, **Sync only assigned users and groups** only syncs the users and groups assigned to the application. Otherwise, it syncs the whole Active Directory.
-You can then test the connection by clicking on **Test Connection**. If the connection is successful, be sure to save your configuration before moving on. See below for [troubleshooting](#troubleshooting).
+ - **Mappings**: We recommend keeping **Provision Azure Active Directory Users** enabled, and disable **Provision Azure Active Directory Groups**.
+ Leaving **Provision Azure Active Directory Groups** enabled does not break the SCIM user provisioning, but it causes errors in Azure AD that may be confusing and misleading.
+
+1. You can then test the connection by selecting **Test Connection**. If the connection is successful, save your configuration before moving on. See below for [troubleshooting](#troubleshooting).
#### Configure attribute mapping
@@ -93,11 +92,6 @@ For guidance, you can view [an example configuration in the troubleshooting refe
1. Save all changes.
1. In the **Provisioning** step, set the `Provisioning Status` to `On`.
- NOTE:
- You can control what is actually synced by selecting the `Scope`. For example,
- `Sync only assigned users and groups` only syncs the users assigned to
- the application (`Users and groups`), otherwise, it syncs the whole Active Directory.
-
Once enabled, the synchronization details and any errors appears on the
bottom of the **Provisioning** screen, together with a link to the audit events.
diff --git a/doc/user/group/settings/group_access_tokens.md b/doc/user/group/settings/group_access_tokens.md
index 816edb629f5..769943cd5d8 100644
--- a/doc/user/group/settings/group_access_tokens.md
+++ b/doc/user/group/settings/group_access_tokens.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -140,8 +140,11 @@ To enable or disable group access token creation for all sub-groups in a top-lev
Even when creation is disabled, you can still use and revoke existing group access tokens.
-## Bot users
+## Bot users for groups
Each time you create a group access token, a bot user is created and added to the group.
-These bot users are similar to [project bot users](../../project/settings/project_access_tokens.md#project-bot-users), but are added to groups instead of projects. For more information, see
-[Project bot users](../../project/settings/project_access_tokens.md#project-bot-users).
+These bot users are similar to [bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects),
+except they are added to groups instead of projects.
+These bot users do not count as licensed seats.
+
+For more information, see [Bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects).
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 5745c499c5c..7b63466656d 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -16,7 +16,7 @@ You can also [export projects](../../project/settings/import_export.md).
Prerequisite:
-- You must have the [Owner role](../../permissions.md) for the group.
+- You must have the Owner role for the group.
To enable import and export for a group:
@@ -69,7 +69,7 @@ in GitLab 14.6 and replaced by [GitLab Migration](../import/).
Prerequisites:
-- You must have the [Owner role](../../permissions.md) for the group.
+- You must have the Owner role for the group.
To export the contents of a group:
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index ef984a76a7d..46dea81ae9f 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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, concepts
---
@@ -158,7 +158,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 the [Maintainer role](../../permissions.md) for group `one/two/three/four`,
+of `one/two`. To give them the Maintainer role 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/index.md b/doc/user/group/value_stream_analytics/index.md
index 4663cfc8bfd..ccf77f79fd9 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -117,16 +117,15 @@ production environment for all merge requests deployed in the given time period.
The "Recent Activity" metrics near the top of the page are measured as follows:
- **New Issues:** the number of issues created in the date range.
-- **Deploys:** the number of deployments <sup>1</sup> to production <sup>2</sup> in the date range.
-- **Deployment Frequency:** the average number of deployments <sup>1</sup> to production <sup>2</sup>
+- **Deploys:** the number of deployments to production in the date range.
+- **Deployment Frequency:** the average number of deployments to production
per day in the date range.
-1. To give a more accurate representation of deployments that actually completed successfully,
- the calculation for these two metrics changed in GitLab 13.9 from using the time a deployment was
- created to the time a deployment finished. If you were referencing this metric prior to 13.9, please
- keep this slight change in mind.
-1. To see deployment metrics, you must have a
- [production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
+To see deployment metrics, you must have a [production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
+
+NOTE:
+In GitLab 13.9 and later, deployment metrics are calculated based on when the deployment was finished.
+In GitLab 13.8 and earlier, deployment metrics are calculated based on when the deployment was created.
You can learn more about these metrics in our [analytics definitions](../../analytics/index.md).
diff --git a/doc/user/index.md b/doc/user/index.md
index a3b7cfc4b3c..f4a7cd6a5d9 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -44,7 +44,7 @@ GitLab is a Git-based platform that integrates a great number of essential tools
- Tracking proposals for new implementations, bug reports, and feedback with a
fully featured [Issue tracker](project/issues/index.md).
- Organizing and prioritizing with [issue boards](project/issue_board.md).
-- Reviewing code in [Merge Requests](project/merge_requests/index.md) with live-preview changes per
+- Reviewing code in [merge requests](project/merge_requests/index.md) with live-preview changes per
branch with [Review Apps](../ci/review_apps/index.md).
- Building, testing, and deploying with built-in [Continuous Integration](../ci/index.md).
- Deploying personal and professional static websites with [GitLab Pages](project/pages/index.md).
@@ -56,7 +56,7 @@ GitLab is a Git-based platform that integrates a great number of essential tools
With GitLab Enterprise Edition, you can also:
- Improve collaboration with:
- - [Merge Request Approvals](project/merge_requests/approvals/index.md).
+ - [Merge request approvals](project/merge_requests/approvals/index.md).
- [Multiple Assignees for Issues](project/issues/multiple_assignees_for_issues.md).
- [Multiple issue boards](project/issue_board.md#multiple-issue-boards).
- Create formal relationships between issues with [linked issues](project/issues/related_issues.md).
@@ -152,8 +152,8 @@ it all at once, from one single project.
- [Repositories](project/repository/index.md): Host your codebase in
repositories with version control and as part of a fully integrated platform.
- [Issues](project/issues/index.md): Explore the best of GitLab Issues' features.
-- [Merge Requests](project/merge_requests/index.md): Collaborate on code,
- reviews, live preview changes per branch, and request approvals with Merge Requests.
+- [Merge requests](project/merge_requests/index.md): Collaborate on code,
+ reviews, live preview changes per branch, and request approvals with merge requests.
- [Milestones](project/milestones/index.md): Work on multiple issues and merge
requests towards the same target date with Milestones.
diff --git a/doc/user/infrastructure/clusters/connect/index.md b/doc/user/infrastructure/clusters/connect/index.md
index 9e57622875d..06d1307984d 100644
--- a/doc/user/infrastructure/clusters/connect/index.md
+++ b/doc/user/infrastructure/clusters/connect/index.md
@@ -15,28 +15,6 @@ If you don't have a cluster yet, create one and connect it to GitLab through the
You can also create a new cluster from GitLab using [Infrastructure as Code](../../iac/index.md#create-a-new-cluster-through-iac).
-->
-## Supported cluster versions
-
-GitLab is committed to support at least two production-ready Kubernetes minor
-versions at any given time. We regularly review the versions we support, and
-provide a three-month deprecation period before we remove support of a specific
-version. The range of supported versions is based on the evaluation of:
-
-- The versions supported by major managed Kubernetes providers.
-- The versions [supported by the Kubernetes community](https://kubernetes.io/releases/version-skew-policy/#supported-versions).
-
-GitLab supports the following Kubernetes versions, and you can upgrade your
-Kubernetes version to any supported version at any time:
-
-- 1.20 (support ends on July 22, 2022)
-- 1.19 (support ends on February 22, 2022)
-- 1.18 (support ends on November 22, 2021)
-- 1.17 (support ends on September 22, 2021)
-
-[Adding support to other versions of Kubernetes is managed under this epic](https://gitlab.com/groups/gitlab-org/-/epics/4827).
-
-Some GitLab features may support versions outside the range provided here.
-
## Cluster levels (DEPRECATED)
> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
index 12f99af8d8d..58de5f5e368 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
@@ -8,48 +8,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
> - Support for cert-manager v1.4 was [introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/69405) in GitLab 14.3.
+> - [Upgraded](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/23) to cert-manager 1.7 in GitLab 14.8.
Assuming you already have a [Cluster management project](../../../../../user/clusters/management_project.md) created from a
[management project template](../../../../../user/clusters/management_project_template.md), to install cert-manager you should
uncomment this line from your `helmfile.yaml`:
```yaml
- - path: applications/cert-manager-1-4/helmfile.yaml
+ - path: applications/cert-manager/helmfile.yaml
```
NOTE:
-We kept the `- path: applications/cert-manager/helmfile.yaml` with cert-manager v0.10 to facilitate
-the [migration from GitLab Managed Apps to a cluster management project](../../../../clusters/migrating_from_gma_to_project_template.md).
+If your Kubernetes version is earlier than 1.20 and you are [migrating from GitLab
+Managed Apps to a cluster management
+project](../../../../clusters/migrating_from_gma_to_project_template.md), then
+you can instead use `- path: applications/cert-manager-legacy/helmfile.yaml` to
+take over an existing release of cert-manager v0.10.
cert-manager:
- Is installed by default into the `gitlab-managed-apps` namespace of your cluster.
-- Can be installed with or without a default
- [Let's Encrypt `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/), which requires an
- email address to be specified. The email address is used by Let's Encrypt to
+- Includes a
+ [Let's Encrypt
+ `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/) enabled by
+ default. In the `certmanager-issuer` release, the issuer requires a valid email address
+ for `letsEncryptClusterIssuer.email`. Let's Encrypt uses this email address to
contact you about expiring certificates and issues related to your account.
-
-To install cert-manager in your cluster, configure your `applications/cert-manager-1-4/helmfile.yaml` to:
-
-```yaml
-certManager:
- installed: true
- letsEncryptClusterIssuer:
- installed: true
- email: "user@example.com"
-```
-
-Or without the default `ClusterIssuer`:
-
-```yaml
-certManager:
- installed: true
- letsEncryptClusterIssuer:
- installed: false
-```
-
-You can customize the installation of cert-manager by defining a
-`.gitlab/managed-apps/cert-manager/values.yaml` file in your cluster
-management project. Refer to the
-[chart](https://github.com/jetstack/cert-manager) for the
-available configuration options.
+- Can be customized in `applications/cert-manager/helmfile.yaml` by passing custom
+ `values` to the `certmanager` release. Refer to the
+ [chart](https://github.com/jetstack/cert-manager) for the available
+ configuration options.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md b/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
index 3bd675b7439..f9d0948a2bb 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/infrastructure/clusters/manage/management_project_applications/prometheus.md b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
index fd2eed25997..f76c7363a83 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/infrastructure/clusters/manage/management_project_applications/sentry.md b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
index 9e5d7860a67..b968e63d632 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/infrastructure/iac/index.md b/doc/user/infrastructure/iac/index.md
index ceb6101688b..6fef1aa7879 100644
--- a/doc/user/infrastructure/iac/index.md
+++ b/doc/user/infrastructure/iac/index.md
@@ -6,36 +6,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Infrastructure as Code with Terraform and GitLab **(FREE)**
-## Motivation
+With Terraform in GitLab, you can use GitLab authentication and authorization with
+your GitOps and Infrastructure-as-Code (IaC) workflows.
+Use these features if you want to collaborate on Terraform code within GitLab or would like to use GitLab as a Terraform state storage that incorporates best practices out of the box.
-The Terraform integration features in GitLab enable your GitOps / Infrastructure-as-Code (IaC)
-workflows to tie into GitLab authentication and authorization. These features focus on
-lowering the barrier to entry for teams to adopt Terraform, collaborate effectively in
-GitLab, and support Terraform best practices.
-
-## Quick Start
+## Integrate your project with Terraform
> SAST test was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.6.
-Use the following `.gitlab-ci.yml` to set up a basic Terraform project integration
-for GitLab versions 14.0 and later:
+In GitLab 14.0 and later, to integrate your project with Terraform, add the following
+to your `.gitlab-ci.yml` file:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
variables:
- # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
+ # If you do not use the GitLab HTTP backend, remove this line and specify TF_HTTP_* variables
TF_STATE_NAME: default
TF_CACHE_KEY: default
# If your terraform files are in a subdirectory, set TF_ROOT accordingly
# TF_ROOT: terraform/production
```
-This template includes the following parameters that you can override:
+The `Terraform.latest.gitlab-ci.yml` template:
- Uses the latest [GitLab Terraform image](https://gitlab.com/gitlab-org/terraform-images).
-- Uses the [GitLab-managed Terraform State](#gitlab-managed-terraform-state) as
+- Uses the [GitLab-managed Terraform state](#gitlab-managed-terraform-state) as
the Terraform state storage backend.
- Creates [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
`test`, `validate`, `build`, and `deploy`. These stages
@@ -44,10 +41,12 @@ This template includes the following parameters that you can override:
- Runs the [Terraform SAST scanner](../../application_security/iac_scanning/index.md#configure-iac-scanning-manually),
that you can disable by creating a `SAST_DISABLED` environment variable and setting it to `1`.
-The latest template described above might contain breaking changes between major GitLab releases. For users requiring more stable setups, we
-recommend using the stable templates:
+You can override the values in the default template by updating your `.gitlab-ci.yml` file.
+
+The latest template might contain breaking changes between major GitLab releases.
+For a more stable template, we recommend:
-- [A ready to use version](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml)
+- [A ready-to-use version](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml)
- [A base template for customized setups](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml)
This video from January 2021 walks you through all the GitLab Terraform integration features:
@@ -59,7 +58,7 @@ This video from January 2021 walks you through all the GitLab Terraform integrat
<iframe src="https://www.youtube.com/embed/iGXjUrkkzDI" frameborder="0" allowfullscreen="true"> </iframe>
</figure>
-## GitLab Managed Terraform state
+## GitLab-managed Terraform state
[Terraform remote backends](https://www.terraform.io/docs/language/settings/backends/index.html)
enable you to store the state file in a remote, shared store. GitLab uses the
@@ -67,7 +66,7 @@ enable you to store the state file in a remote, shared store. GitLab uses the
to securely store the state files in local storage (the default) or
[the remote store of your choice](../../../administration/terraform_state.md).
-The GitLab managed Terraform state backend can store your Terraform state easily and
+The GitLab-managed Terraform state backend can store your Terraform state easily and
securely. It spares you from setting up additional remote resources like
Amazon S3 or Google Cloud Storage. Its features include:
@@ -75,7 +74,7 @@ Amazon S3 or Google Cloud Storage. Its features include:
- Locking and unlocking state.
- Remote Terraform plan and apply execution.
-Read more on setting up and [using GitLab Managed Terraform states](terraform_state.md).
+Read more about setting up and [using GitLab-managed Terraform states](terraform_state.md).
## Terraform module registry
@@ -83,12 +82,12 @@ GitLab can be used as a [Terraform module registry](../../packages/terraform_mod
to create and publish Terraform modules to a private registry specific to your
top-level namespace.
-## Terraform integration in Merge Requests
+## Terraform integration in merge requests
Collaborating around Infrastructure as Code (IaC) changes requires both code changes
and expected infrastructure changes to be checked and approved. GitLab provides a
solution to help collaboration around Terraform code changes and their expected
-effects using the Merge Request pages. This way users don't have to build custom
+effects using the merge request pages. This way users don't have to build custom
tools or rely on 3rd party solutions to streamline their IaC workflows.
Read more on setting up and [using the merge request integrations](mr_integration.md).
@@ -104,7 +103,7 @@ to manage various aspects of GitLab using Terraform. The provider is an open sou
owned by GitLab, where everyone can contribute.
The [documentation of the provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs)
-is available as part of the official Terraform provider documentations.
+is available as part of the official Terraform provider documentation.
## Create a new cluster through IaC (DEPRECATED)
@@ -114,66 +113,9 @@ NOTE:
The linked tutorial connects the cluster to GitLab through cluster certificates,
and this method was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
in GitLab 14.5. You can still create a cluster through IaC and then connect it to GitLab
-through the [Agent](../../clusters/agent/index.md), the default and fully supported
+through the [agent](../../clusters/agent/index.md), the default and fully supported
method to connect clusters to GitLab.
## Troubleshooting
-### `gitlab_group_share_group` resources not detected when subgroup state is refreshed
-
-The GitLab Terraform provider can fail to detect existing `gitlab_group_share_group` resources
-due to the issue ["User with permissions cannot retrieve `share_with_groups` from the API"](https://gitlab.com/gitlab-org/gitlab/-/issues/328428).
-This results in an error when running `terraform apply` because Terraform attempts to recreate an
-existing resource.
-
-For example, consider the following group/subgroup configuration:
-
-```plaintext
-parent-group
-├── subgroup-A
-└── subgroup-B
-```
-
-Where:
-
-- User `user-1` creates `parent-group`, `subgroup-A`, and `subgroup-B`.
-- `subgroup-A` is shared with `subgroup-B`.
-- User `terraform-user` is member of `parent-group` with inherited `owner` access to both subgroups.
-
-When the Terraform state is refreshed, the API query `GET /groups/:subgroup-A_id` issued by the provider does not return the
-details of `subgroup-B` in the `shared_with_groups` array. This leads to the error.
-
-To workaround this issue, make sure to apply one of the following conditions:
-
-1. The `terraform-user` creates all subgroup resources.
-1. Grant Maintainer or Owner role to the `terraform-user` user on `subgroup-B`.
-1. The `terraform-user` inherited access to `subgroup-B` and `subgroup-B` contains at least one project.
-
-### Invalid CI/CD syntax error when using the "latest" base template
-
-On GitLab 14.2 and later, you might get a CI/CD syntax error when using the
-`latest` Base Terraform template:
-
-```yaml
-include:
- - template: Terraform/Base.latest.gitlab-ci.yml
-
-my-Terraform-job:
- extends: .init
-```
-
-The base template's [jobs were renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67719/)
-with better Terraform-specific names. To resolve the syntax error, you can:
-
-- Use the stable `Terraform/Base.gitlab-ci.yml` template, which has not changed.
-- Update your pipeline configuration to use the new job names in
- `https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml`.
- For example:
-
- ```yaml
- include:
- - template: Terraform/Base.latest.gitlab-ci.yml
-
- my-Terraform-job:
- extends: .terraform:init # The updated name.
- ```
+See the [troubleshooting](troubleshooting.md) documentation.
diff --git a/doc/user/infrastructure/iac/mr_integration.md b/doc/user/infrastructure/iac/mr_integration.md
index ab59f8ad64b..8c135f18bc1 100644
--- a/doc/user/infrastructure/iac/mr_integration.md
+++ b/doc/user/infrastructure/iac/mr_integration.md
@@ -4,9 +4,9 @@ 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 integration in Merge Requests **(FREE)**
+# Terraform integration in merge requests **(FREE)**
-Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the Merge Request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows.
+Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the merge request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows.
## Output Terraform Plan information into a merge request
@@ -16,14 +16,14 @@ enabling you to see statistics about the resources that Terraform creates,
modifies, or destroys.
WARNING:
-Like any other job artifact, Terraform Plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
+Like any other job artifact, Terraform Plan data is viewable by anyone with the Guest role for the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform Plan
includes sensitive data such as passwords, access tokens, or certificates, we strongly
recommend encrypting plan output or modifying the project visibility settings.
## Configure Terraform report artifacts
-GitLab ships with a [pre-built CI template](index.md#quick-start) that uses GitLab Managed Terraform state and integrates Terraform changes into merge requests. We recommend customizing the pre-built image and relying on the `gitlab-terraform` helper provided within for a quick setup.
+GitLab ships with a [pre-built CI template](index.md#integrate-your-project-with-terraform) that uses GitLab Managed Terraform state and integrates Terraform changes into merge requests. We recommend customizing the pre-built image and relying on the `gitlab-terraform` helper provided within for a quick setup.
To manually configure a GitLab Terraform Report artifact:
@@ -83,7 +83,7 @@ To manually configure a GitLab Terraform Report artifact:
1. Running the pipeline displays the widget in the merge request, like this:
- ![Merge Request Terraform widget](img/terraform_plan_widget_v13_2.png)
+ ![merge request Terraform widget](img/terraform_plan_widget_v13_2.png)
1. Clicking the **View Full Log** button in the widget takes you directly to the
plan output present in the pipeline logs:
@@ -151,8 +151,8 @@ apply:
### Multiple Terraform Plan reports
-Starting with GitLab version 13.2, you can display multiple reports on the Merge Request
-page. The reports also display the `artifacts: name:`. See example below for a suggested setup.
+Starting with GitLab version 13.2, you can display multiple reports on a merge request.
+The reports also display the `artifacts: name:`. See example below for a suggested setup.
```yaml
default:
diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index a45ef02622f..8fd38215b04 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -4,7 +4,7 @@ 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
---
-# GitLab managed Terraform State **(FREE)**
+# GitLab-managed Terraform state **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2673) in GitLab 13.0.
@@ -19,7 +19,7 @@ Using local storage (the default) on clustered deployments of GitLab will result
a split state across nodes, making subsequent executions of Terraform inconsistent.
You are highly advised to use a remote storage resource in that case.
-The GitLab managed Terraform state backend can store your Terraform state easily and
+The GitLab-managed Terraform state backend can store your Terraform state easily and
securely, and spares you from setting up additional remote resources like
Amazon S3 or Google Cloud Storage. Its features include:
@@ -33,11 +33,13 @@ before using this feature.
## Permissions for using Terraform
-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`).
+In GitLab version 13.1, at least the Maintainer role was required to use a
+GitLab managed Terraform state backend.
+
+In GitLab versions 13.2 and later, at least:
+
+- The Maintainer role is required to lock, unlock, and write to the state (using `terraform apply`).
+- The Developer role is required to read the state (using `terraform plan -lock=false`).
## Set up GitLab-managed Terraform state
@@ -72,9 +74,8 @@ local machine, this is a simple way to get started:
1. On your local machine, run `terraform init`, passing in the following options,
replacing `<YOUR-STATE-NAME>`, `<YOUR-PROJECT-ID>`, `<YOUR-USERNAME>` and
`<YOUR-ACCESS-TOKEN>` with the relevant values. This command initializes your
- Terraform state, and stores that state in your GitLab project. The name of
- your state can contain only uppercase and lowercase letters, decimal digits,
- hyphens, and underscores. This example uses `gitlab.com`:
+ Terraform state, and stores that state in your GitLab project. This example
+ uses `gitlab.com`:
```shell
terraform init \
@@ -88,6 +89,10 @@ local machine, this is a simple way to get started:
-backend-config="retry_wait_min=5"
```
+ WARNING:
+ The name of your state can contain only uppercase and lowercase letters, decimal digits,
+ hyphens, and underscores.
+
If you already have a GitLab-managed Terraform state, you can use the `terraform init` command
with the pre-populated parameters values:
@@ -205,7 +210,7 @@ and the CI YAML file:
The output from the above `terraform` commands should be viewable in the job logs.
WARNING:
-Like any other job artifact, Terraform plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
+Like any other job artifact, Terraform plan data is viewable by anyone with the Guest role on the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
recommends encrypting plan output or modifying the project visibility settings.
@@ -214,7 +219,7 @@ recommends encrypting plan output or modifying the project visibility settings.
See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 in a custom VPC.
-## Using a GitLab managed Terraform state backend as a remote data source
+## Using a GitLab-managed Terraform state backend as a remote data source
You can use a GitLab-managed Terraform state as a
[Terraform data source](https://www.terraform.io/docs/language/state/remote-state-data.html).
@@ -255,16 +260,16 @@ An example setup is shown below:
Outputs from the data source can now be referenced in your Terraform resources
using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
-You need at least the [Developer role](../../permissions.md) in the target project
+You need at least the Developer role in the target project
to read the Terraform state.
-## Migrating to GitLab Managed Terraform state
+## Migrating to GitLab-managed Terraform state
Terraform supports copying the state when the backend is changed or
reconfigured. This can be useful if you need to migrate from another backend to
-GitLab managed Terraform state. Using a local terminal is recommended to run the commands needed for migrating to GitLab Managed Terraform state.
+GitLab-managed Terraform state. Using a local terminal is recommended to run the commands needed for migrating to GitLab-managed Terraform state.
-The following example demonstrates how to change the state name, the same workflow is needed to migrate to GitLab Managed Terraform state from a different state storage backend.
+The following example demonstrates how to change the state name, the same workflow is needed to migrate to GitLab-managed Terraform state from a different state storage backend.
### Setting up the initial backend
@@ -313,6 +318,7 @@ the old state is, you can tell it about the new location:
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/new-state-name"
terraform init \
+ -migrate-state \
-backend-config=address=${TF_ADDRESS} \
-backend-config=lock_address=${TF_ADDRESS}/lock \
-backend-config=unlock_address=${TF_ADDRESS}/lock \
@@ -364,7 +370,7 @@ 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
+Users with at least the Developer role can view the
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:
@@ -383,9 +389,27 @@ Additional improvements to the
[graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563)
are planned.
+## Manage individual Terraform state versions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207347) in GitLab 13.4.
+
+Individual state versions can be managed using the GitLab REST API.
+
+Users with the [Developer role](../../permissions.md) can retrieve state versions using their serial number. To retrieve a version:
+
+```shell
+curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"
+```
+
+Users with the [Maintainer role](../../permissions.md) can remove state versions using their serial number. To remove a version:
+
+```shell
+curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"
+```
+
## Remove a state file
-Users with Maintainer and greater [permissions](../../permissions.md) can use the
+Users with at least the Maintainer role can use the
following options to remove a state file:
- **GitLab UI**: Go to **Infrastructure > Terraform**. In the **Actions** column,
@@ -444,3 +468,15 @@ This happens because the value of `$CI_JOB_TOKEN` is only valid for the duration
As a workaround, use [http backend configuration variables](https://www.terraform.io/docs/language/settings/backends/http.html#configuration-variables) in your CI job,
which is what happens behind the scenes when following the
[Get started using GitLab CI](#get-started-using-gitlab-ci) instructions.
+
+### Error: "address": required field is not set
+
+By default, we set `TF_ADDRESS` to `${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}`.
+If you don't set `TF_STATE_NAME` or `TF_ADDRESS` in your job, the job fails with the error message
+`Error: "address": required field is not set`.
+
+To resolve this, ensure that either `TF_ADDRESS` or `TF_STATE_NAME` is accessible in the
+job that returned the error:
+
+1. Configure the [CI/CD environment scope](../../../ci/variables/#add-a-cicd-variable-to-a-project) for the job.
+1. Set the job's [environment](../../../ci/yaml/#environment), matching the environment scope from the previous step.
diff --git a/doc/user/infrastructure/iac/troubleshooting.md b/doc/user/infrastructure/iac/troubleshooting.md
new file mode 100644
index 00000000000..ecefa20db99
--- /dev/null
+++ b/doc/user/infrastructure/iac/troubleshooting.md
@@ -0,0 +1,68 @@
+---
+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
+---
+
+# Troubleshooting the Terraform integration with GitLab
+
+When you are using the integration with Terraform and GitLab, you might experience issues you need to troubleshoot.
+
+## `gitlab_group_share_group` resources not detected when subgroup state is refreshed
+
+The GitLab Terraform provider can fail to detect existing `gitlab_group_share_group` resources
+due to the issue ["User with permissions cannot retrieve `share_with_groups` from the API"](https://gitlab.com/gitlab-org/gitlab/-/issues/328428).
+This results in an error when running `terraform apply` because Terraform attempts to recreate an
+existing resource.
+
+For example, consider the following group/subgroup configuration:
+
+```plaintext
+parent-group
+├── subgroup-A
+└── subgroup-B
+```
+
+Where:
+
+- User `user-1` creates `parent-group`, `subgroup-A`, and `subgroup-B`.
+- `subgroup-A` is shared with `subgroup-B`.
+- User `terraform-user` is member of `parent-group` with inherited `owner` access to both subgroups.
+
+When the Terraform state is refreshed, the API query `GET /groups/:subgroup-A_id` issued by the provider does not return the
+details of `subgroup-B` in the `shared_with_groups` array. This leads to the error.
+
+To workaround this issue, make sure to apply one of the following conditions:
+
+1. The `terraform-user` creates all subgroup resources.
+1. Grant Maintainer or Owner role to the `terraform-user` user on `subgroup-B`.
+1. The `terraform-user` inherited access to `subgroup-B` and `subgroup-B` contains at least one project.
+
+### Invalid CI/CD syntax error when using the `latest` base template
+
+On GitLab 14.2 and later, you might get a CI/CD syntax error when using the
+`latest` Base Terraform template:
+
+```yaml
+include:
+ - template: Terraform/Base.latest.gitlab-ci.yml
+
+my-Terraform-job:
+ extends: .init
+```
+
+The base template's [jobs were renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67719/)
+with better Terraform-specific names. To resolve the syntax error, you can:
+
+- Use the stable `Terraform/Base.gitlab-ci.yml` template, which has not changed.
+- Update your pipeline configuration to use the new job names in
+ `https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml`.
+ For example:
+
+ ```yaml
+ include:
+ - template: Terraform/Base.latest.gitlab-ci.yml
+
+ my-Terraform-job:
+ extends: .terraform:init # The updated name.
+ ```
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 3d640185a55..a16f8fd39b1 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -539,6 +539,7 @@ GitLab Flavored Markdown recognizes the following:
| 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` |
+| contact | `[contact:test@example.com]` | | |
1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 23bd140d4b7..5cfb4278a2c 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -349,6 +349,16 @@ used to access them:
subgroups.
- A project deploy token only has access to packages published to that particular project.
+## Troubleshooting
+
+To improve performance, Composer caches files related to a package. Note that Composer doesn't remove data by
+itself. The cache grows as new packages are installed. If you encounter issues, clear the cache with
+this command:
+
+```shell
+composer clearcache
+```
+
## Supported CLI commands
The GitLab Composer repository supports the following Composer CLI commands:
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index c77fc5a0f4b..b28f0cbfb35 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -489,11 +489,13 @@ Container Registry.
## Limitations
- Moving or renaming existing Container Registry repositories is not supported
-once you have pushed images, because the images are stored in a path that matches
-the repository path. To move or rename a repository with a
-Container Registry, you must delete all existing images.
+ once you have pushed images, because the images are stored in a path that matches
+ the repository path. To move or rename a repository with a
+ Container Registry, you must delete all existing images.
+ Community suggestions to work around this limitation have been shared in
+ [issue 18383](https://gitlab.com/gitlab-org/gitlab/-/issues/18383#possible-workaround).
- Prior to GitLab 12.10, any tags that use the same image ID as the `latest` tag
-are not deleted by the cleanup policy.
+ are not deleted by the cleanup policy.
## Disable the Container Registry for a project
@@ -581,103 +583,27 @@ For information on how to update your images, see the [Docker help](https://docs
### `Blob unknown to registry` error when pushing a manifest list
-When [pushing a Docker manifest list](https://docs.docker.com/engine/reference/commandline/manifest/#create-and-push-a-manifest-list) to the GitLab Container Registry, you may receive the error `manifest blob unknown: blob unknown to registry`. [This issue](https://gitlab.com/gitlab-org/gitlab/-/issues/209008) occurs when the individual child manifests referenced in the manifest list were not pushed to the same repository.
+When [pushing a Docker manifest list](https://docs.docker.com/engine/reference/commandline/manifest/#create-and-push-a-manifest-list)
+to the GitLab Container Registry, you may receive the error
+`manifest blob unknown: blob unknown to registry`. This is likely caused by having multiple images
+with different architectures, spread out over several repositories instead of the same repository.
-For example, you may have two individual images, one for `amd64` and another for `arm64v8`, and you want to build a multi-arch image with them. The `amd64` and `arm64v8` images must be pushed to the same repository where you want to push the multi-arch image.
+For example, you may have two images, each representing an architecture:
-As a workaround, you should include the architecture in the tag name of individual images. For example, use `mygroup/myapp:1.0.0-amd64` instead of using sub repositories, like `mygroup/myapp/amd64:1.0.0`. You can then tag the manifest list with `mygroup/myapp:1.0.0`.
+- The `amd64` platform
+- The `arm64v8` platform
-### The cleanup policy doesn't delete any tags
+To build a multi-arch image with these images, you must push them to the same repository as the
+multi-arch image.
-There can be different reasons behind this:
-
-- In GitLab 13.6 and earlier, when you run the cleanup policy you may expect it to delete tags and
- it does not. This occurs when the cleanup policy is saved without editing the value in the
- **Remove tags matching** field. This field has a grayed out `.*` value as a placeholder. Unless
- `.*` (or another regex pattern) is entered explicitly into the field, a `nil` value is submitted.
- This value prevents the saved cleanup policy from matching any tags. As a workaround, edit the
- cleanup policy. In the **Remove tags matching** field, enter `.*` and save. This value indicates
- that all tags should be removed.
-
-- If you are on GitLab self-managed instances and you have 1000+ tags in a container repository, you
- might run into a [Container Registry token expiration issue](https://gitlab.com/gitlab-org/gitlab/-/issues/288814),
- with `error authorizing context: invalid token` in the logs.
-
- To fix this, there are two workarounds:
-
- - If you are on GitLab 13.9 or later, you can [set limits for the cleanup policy](reduce_container_registry_storage.md#set-cleanup-limits-to-conserve-resources).
- This limits the cleanup execution in time, and avoids the expired token error.
-
- - Extend the expiration delay of the Container Registry authentication tokens. This defaults to 5
- minutes. You can set a custom value by running
- `ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)` in the Rails
- console, where `<integer>` is the desired number of minutes. For reference, 15 minutes is the
- value currently in use for GitLab.com. Be aware that by extending this value you increase the
- time required to revoke permissions.
-
-If the previous fixes didn't work or you are on earlier versions of GitLab, you can generate a list
-of the tags that you want to delete, and then use that list to delete the tags. To do this, follow
-these steps:
-
-1. Run the following shell script. The command just before the `for` loop ensures that
- `list_o_tags.out` is always reinitialized when starting the loop. After running this command, all
- the tags' names will be in the `list_o_tags.out` file:
-
- ```shell
- # Get a list of all tags in a certain container repository while considering [pagination](../../../api/index.md#pagination)
- echo -n "" > list_o_tags.out; for i in {1..N}; do curl --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags?per_page=100&page=${i}" | jq '.[].name' | sed 's:^.\(.*\).$:\1:' >> list_o_tags.out; done
- ```
-
- If you have Rails console access, you can enter the following commands to retrieve a list of tags limited by date:
-
- ```shell
- output = File.open( "/tmp/list_o_tags.out","w" )
- Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag|
- output << tag.name + "\n" if tag.created_at < 1.month.ago
- end;nil
- output.close
- ```
-
- This set of commands creates a `/tmp/list_o_tags.out` file listing all tags with a `created_at` date of older than one month.
-
-1. Remove from the `list_o_tags.out` file any tags that you want to keep. Here are some example
- `sed` commands for this. Note that these commands are simply examples. You may change them to
- best suit your needs:
-
- ```shell
- # Remove the `latest` tag from the file
- sed -i '/latest/d' list_o_tags.out
-
- # Remove the first N tags from the file
- sed -i '1,Nd' list_o_tags.out
-
- # Remove the tags starting with `Av` from the file
- sed -i '/^Av/d' list_o_tags.out
-
- # Remove the tags ending with `_v3` from the file
- sed -i '/_v3$/d' list_o_tags.out
- ```
-
- If you are running macOS, you must add `.bak` to the commands. For example:
-
- ```shell
- sed -i .bak '/latest/d' list_o_tags.out
- ```
-
-1. Double-check the `list_o_tags.out` file to make sure it contains only the tags that you want to
- delete.
-
-1. Run this shell script to delete the tags in the `list_o_tags.out` file:
-
- ```shell
- # loop over list_o_tags.out to delete a single tag at a time
- while read -r LINE || [[ -n $LINE ]]; do echo ${LINE}; curl --request DELETE --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags/${LINE}"; sleep 0.1; echo; done < list_o_tags.out > delete.logs
- ```
+To address the `Blob unknown to registry` error, include the architecture in the tag name of
+individual images. For example, use `mygroup/myapp:1.0.0-amd64` and `mygroup/myapp:1.0.0-arm64v8`.
+You can then tag the manifest list with `mygroup/myapp:1.0.0`.
### Troubleshoot as a GitLab server administrator
Troubleshooting the GitLab Container Registry, most of the times, requires
-you to log in to GitLab server with the Administrator role.
+you to log in to GitLab server with administrator access.
[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.md#troubleshooting).
diff --git a/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md b/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md
new file mode 100644
index 00000000000..5f678a661f8
--- /dev/null
+++ b/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md
@@ -0,0 +1,133 @@
+---
+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
+---
+
+# Reduce Container Registry data transfers **(FREE)**
+
+Depending on the frequency with which images or tags are downloaded from the Container Registry,
+data transfers can exceed the GitLab limit. This page offers several recommendations and tips for
+reducing the amount of data you transfer with the Container Registry.
+are downloaded from the Container Registry, data transfers can exceed the GitLab limit. This page
+offers several recommendations and tips for reducing the amount of data you transfer with the
+Container Registry.
+
+## Check data transfer use
+
+Transfer usage is not available within the GitLab UI. [GitLab-#350905](https://gitlab.com/gitlab-org/gitlab/-/issues/350905)
+is the epic tracking the work to surface this information. In the interim, GitLab team members may reach out to customers that have
+significantly exceeded their transfer limits to better understand their use case and offer ways to reduce data transfer
+usage.
+
+## Determine image size
+
+Use these tools and techniques to determine your image's size:
+
+- [Skopeo](https://github.com/containers/skopeo):
+ use Skopeo's `inspect` command to examine layer count and sizes through API calls. You can
+ therefore inspect this data prior to running `docker pull IMAGE`.
+
+- Docker in CI: examine and record the image size when using GitLab CI prior to pushing an image
+ with Docker. For example:
+
+ ```yaml
+ docker inspect "$CI_REGISTRY_IMAGE:$IMAGE_TAG" \
+ | awk '/"Size": ([0-9]+)[,]?/{ printf "Final Image Size: %d\n", $2 }'
+ ```
+
+- [Dive](https://github.com/wagoodman/dive)
+ is a tool for exploring a Docker image, layer contents, and discovering ways to reduce its size.
+
+## Reduce image size
+
+### Use a smaller base image
+
+Consider using a smaller base image, such as [Alpine Linux](https://alpinelinux.org/).
+An Alpine image is around 5MB, which is several times smaller than popular base images such as
+[Debian](https://hub.docker.com/_/debian).
+If your application is distributed as a self-contained static binary, such as for Go applications,
+you can also consider using Docker's [scratch](https://hub.docker.com/_/scratch/)
+base image.
+
+If you need to use a specific base image OS, look for `-slim` or `-minimal` variants, as this helps
+to reduce the image size.
+
+Also be mindful about the operating system packages you install on top of your base image. These can
+add up to hundreds of megabytes. Try keeping the number of installed packages to the bare minimum.
+
+[Multi-stage builds](#use-multi-stage-builds) can be a powerful ally in cleaning up transient build
+dependencies.
+
+You may also consider using tools such as these:
+
+- [DockerSlim](https://github.com/docker-slim/docker-slim)
+ provides a set of commands to reduce the size of your container images.
+- [Distroless](https://github.com/GoogleContainerTools/distroless) images contain only your
+ application and its runtime dependencies. They don't contain package managers, shells, or any
+ other programs you would expect to find in a standard Linux distribution.
+
+### Minimize layers
+
+Every instruction in your Dockerfile leads to a new layer, which records the file system changes
+applied during such an instruction. In general, more or larger layers lead to larger images. Try to
+minimize the number of layers to install the packages in the Dockerfile. Otherwise, this may cause
+each step in the build process to increase the image size.
+
+There are multiple strategies to reduce the number and size of layers. For example, instead of using
+a `RUN` command per operating system package that you want to install (which would lead to a layer
+per package), you can install all the packages on a single `RUN` command to reduce the number of
+steps in the build process and reduce the size of the image.
+
+Another useful strategy is to ensure that you remove all transient build dependencies and disable or
+empty the operating system package manager cache before and after installing a package.
+
+When building your images, make sure you only copy the relevant files. For Docker, using a
+[`.dockerignore`](https://docs.docker.com/engine/reference/builder/#dockerignore-file)
+helps ensure that the build process ignores irrelevant files.
+
+You can use other third-party tools to minify your images, such as [DockerSlim](https://github.com/docker-slim/docker-slim).
+Be aware that if used improperly, such tools may remove dependencies that your application needs to
+operate under certain conditions. Therefore, it's preferable to strive for smaller images during the
+build process instead of trying to minify images afterward.
+
+### Use multi-stage builds
+
+With [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/),
+you use multiple `FROM` statements in your Dockerfile. Each `FROM` instruction can use a different
+base, and each begins a new build stage. You can selectively copy artifacts from one stage to
+another, leaving behind everything you don't want in the final image. This is especially useful when
+you need to install build dependencies, but you don't need them to be present in your final image.
+
+## Use an image pull policy
+
+When using the `docker` or `docker+machine` executors, you can set a [`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+parameter in your runner `config.toml` that defines how the runner works when pulling Docker images.
+To avoid transferring data when using large and rarely updated images, consider using the
+`if-not-present` pull policy when pulling images from remote registries.
+
+## Use Docker layer caching
+
+When running `docker build`, each command in `Dockerfile` results in a layer. These layers are kept
+as a cache and can be reused if there haven't been any changes. You can specify a tagged image to be
+used as a cache source for the `docker build` command by using the `--cache-from` argument. Multiple
+images can be specified as a cache source by using multiple `--cache-from` arguments. This can speed
+up your builds and reduce the amount of data transferred. For more information, see the
+[documentation on Docker layer caching](../../../ci/docker/using_docker_build.md#make-docker-in-docker-builds-faster-with-docker-layer-caching).
+
+## Move to GitLab Premium or Ultimate
+
+GitLab data transfer limits are set at the tier level. If you need a higher limit, consider
+upgrading to [GitLab Premium or Ultimate](https://about.gitlab.com/upgrade/).
+
+## Purchase additional data transfer
+
+Read more about managing your [data transfer limits](../../../subscriptions/gitlab_com/#purchase-more-storage-and-transfer).
+
+## Related issues
+
+- You may want to rebuild your image when the base Docker image is updated. However, the
+ [pipeline subscription limit is too low](https://gitlab.com/gitlab-org/gitlab/-/issues/225278)
+ to leverage this feature. As a workaround, you can rebuild daily or multiple times per day.
+ [GitLab-#225278](https://gitlab.com/gitlab-org/gitlab/-/issues/225278)
+ proposes raising the limit to help with this workflow.
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index e2242a85b75..a2a22f138e3 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -16,8 +16,9 @@ to automatically manage your container registry usage.
## Check Container Registry Storage Use
-The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages, which includes Container Registry,
-however, the storage is not being calculated.
+The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages,
+which doesn't include the Container Registry. To track work on this, see the epic
+[Storage management for the Container Registry](https://gitlab.com/groups/gitlab-org/-/epics/7226).
## Cleanup policy
@@ -252,21 +253,108 @@ It is recommended you only enable container cleanup
policies for projects that were created before GitLab 12.8 if you are confident the number of tags
being cleaned up is minimal.
-## Related topics
+## More Container Registry storage reduction options
-- [Delete images](index.md#delete-images)
-- [Delete registry repository](../../../api/container_registry.md#delete-registry-repository)
-- [Delete a registry repository tag](../../../api/container_registry.md#delete-a-registry-repository-tag)
-- [Delete registry repository tags in bulk](../../../api/container_registry.md#delete-registry-repository-tags-in-bulk)
-- [Delete a package](../package_registry/index.md#delete-a-package)
+Here are some other options to reduce your project's use of Container Registry storage:
-## Troubleshooting cleanup policies
+- Use the [GitLab UI](index.md#delete-images)
+ to delete individual image tags or the entire repository containing all the tags.
+- Use the API to [delete individual image tags](../../../api/container_registry.md#delete-a-registry-repository-tag).
+- Use the API to [delete the entire container registry repository containing all the tags](../../../api/container_registry.md#delete-registry-repository).
+- Use the API to [delete registry repository tags in bulk](../../../api/container_registry.md#delete-registry-repository-tags-in-bulk).
-If you see the following message:
+## Troubleshooting cleanup policies
-"Something went wrong while updating the cleanup policy."
+### `Something went wrong while updating the cleanup policy.`
-Check the regex patterns to ensure they are valid.
+If you see this error message, check the regex patterns to ensure they are valid.
GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in the cleanup policy. You can test them with the [regex101 regex tester](https://regex101.com/).
View some common [regex pattern examples](#regex-pattern-examples).
+
+### The cleanup policy doesn't delete any tags
+
+There can be different reasons behind this:
+
+- In GitLab 13.6 and earlier, when you run the cleanup policy you may expect it to delete tags and
+ it does not. This occurs when the cleanup policy is saved without editing the value in the
+ **Remove tags matching** field. This field has a grayed out `.*` value as a placeholder. Unless
+ `.*` (or another regex pattern) is entered explicitly into the field, a `nil` value is submitted.
+ This value prevents the saved cleanup policy from matching any tags. As a workaround, edit the
+ cleanup policy. In the **Remove tags matching** field, enter `.*` and save. This value indicates
+ that all tags should be removed.
+
+- If you are on GitLab self-managed instances and you have 1000+ tags in a container repository, you
+ might run into a [Container Registry token expiration issue](https://gitlab.com/gitlab-org/gitlab/-/issues/288814),
+ with `error authorizing context: invalid token` in the logs.
+
+ To fix this, there are two workarounds:
+
+ - If you are on GitLab 13.9 or later, you can [set limits for the cleanup policy](reduce_container_registry_storage.md#set-cleanup-limits-to-conserve-resources).
+ This limits the cleanup execution in time, and avoids the expired token error.
+
+ - Extend the expiration delay of the Container Registry authentication tokens. This defaults to 5
+ minutes. You can set a custom value by running
+ `ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)` in the Rails
+ console, where `<integer>` is the desired number of minutes. For reference, 15 minutes is the
+ value currently in use for GitLab.com. Be aware that by extending this value you increase the
+ time required to revoke permissions.
+
+If the previous fixes didn't work or you are on earlier versions of GitLab, you can generate a list
+of the tags that you want to delete, and then use that list to delete the tags. To do this, follow
+these steps:
+
+1. Run the following shell script. The command just before the `for` loop ensures that
+ `list_o_tags.out` is always reinitialized when starting the loop. After running this command, all
+ the tags' names will be in the `list_o_tags.out` file:
+
+ ```shell
+ # Get a list of all tags in a certain container repository while considering [pagination](../../../api/index.md#pagination)
+ echo -n "" > list_o_tags.out; for i in {1..N}; do curl --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags?per_page=100&page=${i}" | jq '.[].name' | sed 's:^.\(.*\).$:\1:' >> list_o_tags.out; done
+ ```
+
+ If you have Rails console access, you can enter the following commands to retrieve a list of tags limited by date:
+
+ ```shell
+ output = File.open( "/tmp/list_o_tags.out","w" )
+ Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag|
+ output << tag.name + "\n" if tag.created_at < 1.month.ago
+ end;nil
+ output.close
+ ```
+
+ This set of commands creates a `/tmp/list_o_tags.out` file listing all tags with a `created_at` date of older than one month.
+
+1. Remove from the `list_o_tags.out` file any tags that you want to keep. Here are some example
+ `sed` commands for this. Note that these commands are simply examples. You may change them to
+ best suit your needs:
+
+ ```shell
+ # Remove the `latest` tag from the file
+ sed -i '/latest/d' list_o_tags.out
+
+ # Remove the first N tags from the file
+ sed -i '1,Nd' list_o_tags.out
+
+ # Remove the tags starting with `Av` from the file
+ sed -i '/^Av/d' list_o_tags.out
+
+ # Remove the tags ending with `_v3` from the file
+ sed -i '/_v3$/d' list_o_tags.out
+ ```
+
+ If you are running macOS, you must add `.bak` to the commands. For example:
+
+ ```shell
+ sed -i .bak '/latest/d' list_o_tags.out
+ ```
+
+1. Double-check the `list_o_tags.out` file to make sure it contains only the tags that you want to
+ delete.
+
+1. Run this shell script to delete the tags in the `list_o_tags.out` file:
+
+ ```shell
+ # loop over list_o_tags.out to delete a single tag at a time
+ while read -r LINE || [[ -n $LINE ]]; do echo ${LINE}; curl --request DELETE --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags/${LINE}"; sleep 0.1; echo; done < list_o_tags.out > delete.logs
+ ```
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 52f5a1fcc0d..925a1b3e8e6 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -93,9 +93,8 @@ You can authenticate using:
- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `read_registry` and `write_registry`.
- A [group deploy token](../../../user/project/deploy_tokens/index.md#group-deploy-token) with the scope set to `read_registry` and `write_registry`.
-Users accessing the Dependency Proxy with a personal access token or username and password require
-at least [Guest membership](../../permissions.md#group-members-permissions)
-to the group they pull images from.
+Users accessing the Dependency Proxy with a personal access token or username and password must
+have at least the Guest role for the group they pull images from.
#### SAML SSO
@@ -210,65 +209,8 @@ from the GitLab server.
## Reduce storage usage
-Blobs are kept forever on the GitLab server, and there is no hard limit on how much data can be
-stored.
-
-### Using the API to clear the cache
-
-To reclaim disk space used by image blobs that are no longer needed, use
-the [Dependency Proxy API](../../../api/dependency_proxy.md) to clear the entire
-cache.
-
-If you clear the cache, the next time a pipeline runs it must pull an image or tag from Docker Hub.
-
-### Cleanup policies
-
-#### Enable cleanup policies from within GitLab
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340777) in GitLab 14.6
-
-You can enable an automatic time-to-live (TTL) policy for the Dependency Proxy from the user
-interface. To do this, navigate to your group's **Settings > Packages & Registries > Dependency Proxy**
-and enable the setting to automatically clear items from the cache after 90 days.
-
-#### Enable cleanup policies with GraphQL
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294187) in GitLab 14.4.
-
-The cleanup policy is a scheduled job you can use to clear cached images that are no longer used,
-freeing up additional storage space. The policies use time-to-live (TTL) logic:
-
-- The number of days is configured.
-- All cached dependency proxy files that have not been pulled in that many days are deleted.
-
-Use the [GraphQL API](../../../api/graphql/reference/index.md#mutationupdatedependencyproxyimagettlgrouppolicy)
-to enable and configure cleanup policies:
-
-```graphql
-mutation {
- updateDependencyProxyImageTtlGroupPolicy(input:
- {
- groupPath: "<your-full-group-path>",
- enabled: true,
- ttl: 90
- }
- ) {
- dependencyProxyImageTtlPolicy {
- enabled
- ttl
- }
- errors
- }
-}
-```
-
-See the [Getting started with GraphQL](../../../api/graphql/getting_started.md)
-guide to learn how to make GraphQL queries.
-
-When the policy is initially enabled, the default TTL setting is 90 days. Once enabled, stale
-dependency proxy files are queued for deletion each day. Deletion may not occur right away due to
-processing time. If the image is pulled after the cached files are marked as expired, the expired
-files are ignored and new files are downloaded and cached from the external registry.
+For information on reducing your storage use on the Dependency Proxy, see
+[Reduce Dependency Proxy storage use](reduce_dependency_proxy_storage.md).
## Docker Hub rate limits and the Dependency Proxy
diff --git a/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md b/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md
new file mode 100644
index 00000000000..cd04d2e696b
--- /dev/null
+++ b/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md
@@ -0,0 +1,74 @@
+---
+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
+---
+
+# Reduce Dependency Proxy Storage **(FREE)**
+
+There's no automatic removal process for blobs. Unless you delete them manually, they're stored
+indefinitely. Since this impacts your
+[storage usage quota](../../usage_quotas.md),
+it's important that you clear unused items from the cache. This page covers several options for
+doing so.
+
+## Check Dependency Proxy Storage Use
+
+The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages, which includes the Dependency Proxy,
+however, the storage is not yet displayed.
+
+## Use the API to clear the cache
+
+To reclaim disk space used by image blobs that are no longer needed, use the
+[Dependency Proxy API](../../../api/dependency_proxy.md)
+to clear the entire cache. If you clear the cache, the next time a pipeline runs it must pull an
+image or tag from Docker Hub.
+
+## Cleanup policies
+
+### Enable cleanup policies from within GitLab
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340777) in GitLab 14.6
+
+You can enable an automatic time-to-live (TTL) policy for the Dependency Proxy from the user
+interface. To do this, navigate to your group's **Settings > Packages & Registries > Dependency Proxy**
+and enable the setting to automatically clear items from the cache after 90 days.
+
+### Enable cleanup policies with GraphQL
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294187) in GitLab 14.4.
+
+The cleanup policy is a scheduled job you can use to clear cached images that are no longer used,
+freeing up additional storage space. The policies use time-to-live (TTL) logic:
+
+- The number of days is configured.
+- All cached dependency proxy files that have not been pulled in that many days are deleted.
+
+Use the [GraphQL API](../../../api/graphql/reference/index.md#mutationupdatedependencyproxyimagettlgrouppolicy)
+to enable and configure cleanup policies:
+
+```graphql
+mutation {
+ updateDependencyProxyImageTtlGroupPolicy(input:
+ {
+ groupPath: "<your-full-group-path>",
+ enabled: true,
+ ttl: 90
+ }
+ ) {
+ dependencyProxyImageTtlPolicy {
+ enabled
+ ttl
+ }
+ errors
+ }
+}
+```
+
+See the [Getting started with GraphQL](../../../api/graphql/getting_started.md)
+guide to learn how to make GraphQL queries.
+
+When the policy is initially enabled, the default TTL setting is 90 days. Once enabled, stale
+dependency proxy files are queued for deletion each day. Deletion may not occur right away due to
+processing time. If the image is pulled after the cached files are marked as expired, the expired
+files are ignored and new files are downloaded and cached from the external registry.
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 7b44b5bcbb7..ada6f033288 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -57,7 +57,7 @@ Example request using a personal access token:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--upload-file path/to/file.txt \
- "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt?status=hidden"
+ "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
```
Example response without attribute `select`:
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 21fecc16602..6e3af6a92d5 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -263,7 +263,7 @@ The `name` must be `Job-Token`.
<httpHeaders>
<property>
<name>Job-Token</name>
- <value>${env.CI_JOB_TOKEN}</value>
+ <value>${CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
@@ -725,7 +725,7 @@ You can create a new package each time the `main` branch is updated.
<httpHeaders>
<property>
<name>Job-Token</name>
- <value>${env.CI_JOB_TOKEN}</value>
+ <value>${CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
@@ -742,17 +742,17 @@ You can create a new package each time the `main` branch is updated.
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>${CI_API_V4_URL}/projects/${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 5338e546625..1f37e5639c6 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -255,7 +255,8 @@ This regex allows almost all of the characters that npm allows, with a few excep
The regex also allows for capital letters, while npm does not.
-WARNING:
+## Limitations
+
When you update the path of a user or group, or transfer a subgroup or project,
you must remove any npm packages first. You cannot update the root namespace
of a project with npm packages. Make sure you update your `.npmrc` files to follow
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 3311b271126..a2228148447 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -12,6 +12,15 @@ With the GitLab Package Registry, you can use GitLab as a private or public regi
of [supported package managers](#supported-package-managers).
You can publish and share packages, which can be consumed as a dependency in downstream projects.
+## Package workflows
+
+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.
+
+- Publish multiple different packages from one [monorepo project](../workflows/working_with_monorepos.md).
+
## View packages
You can view packages for your project or group.
@@ -77,46 +86,10 @@ when you view the package details:
You can view which pipeline published the package, and the commit and user who triggered it. However, the history is limited to five updates of a given package.
-## Download a package
+## Reduce storage usage
-To download a package:
-
-1. Go to **Packages & Registries > Package 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 Package 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 > Package Registry**.
-1. Find the name of the package you want to delete.
-1. Click **Delete**.
-
-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.
+For information on reducing your storage use for the Package Registry, see
+[Reduce Package Registry storage use](reduce_package_registry_storage.md).
## Disable the Package Registry
@@ -135,15 +108,6 @@ You can also remove the Package Registry for your project specifically:
The **Packages & Registries > Package Registry** entry is removed from the sidebar.
-## Package workflows
-
-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.
-
-- Publish multiple different packages from one [monorepo project](../workflows/working_with_monorepos.md).
-
## Supported package managers
WARNING:
@@ -166,7 +130,7 @@ The Package Registry supports the following formats:
| [Go](../go_proxy/index.md) | 13.1+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3043) |
| [Ruby gems](../rubygems_registry/index.md) | 13.10+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3200) |
-[Status](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga):
+[Status](../../../policy/alpha-beta-support.md):
- Alpha: behind a feature flag and not officially supported.
- Beta: several known issues that may prevent expected use.
diff --git a/doc/user/packages/package_registry/reduce_package_registry_storage.md b/doc/user/packages/package_registry/reduce_package_registry_storage.md
new file mode 100644
index 00000000000..c2e4cd8d889
--- /dev/null
+++ b/doc/user/packages/package_registry/reduce_package_registry_storage.md
@@ -0,0 +1,52 @@
+---
+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
+---
+
+# Reduce Package Registry Storage **(FREE)**
+
+Without cleanup, package registries become large over time. When a large number of packages and
+their files are added:
+
+- Fetching the list of packages becomes slower.
+- They take up a large amount of storage space on the server, impacting your [storage usage quota](../../usage_quotas.md).
+
+We recommend deleting unnecessary packages and files. This page offers examples of how to do so.
+
+## Check Package Registry Storage Use
+
+The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages.
+
+## Delete a package
+
+You cannot edit a package after you publish it in the Package 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 > Package Registry**.
+1. Find the name of the package you want to delete.
+1. Click **Delete**.
+
+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.
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 4151346ec98..bf007572ac7 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -407,6 +407,16 @@ characters are removed.
A `pip install` request for `my.package` looks for packages that match any of
the three characters, such as `my-package`, `my_package`, and `my....package`.
+## Troubleshooting
+
+To improve performance, PyPI caches files related to a package. Note that PyPI doesn't remove data by
+itself. The cache grows as new packages are installed. If you encounter issues, clear the cache with
+this command:
+
+```shell
+pip cache purge
+```
+
## Supported CLI commands
The GitLab PyPI repository supports the following CLI commands:
diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md
index bb9f32d1144..6fc47a23373 100644
--- a/doc/user/packages/terraform_module_registry/index.md
+++ b/doc/user/packages/terraform_module_registry/index.md
@@ -41,7 +41,7 @@ PUT /projects/:id/packages/terraform/modules/:module-name/:module-system/:module
Provide the file content in the request body.
-Note that, in the following example, the request must end with `/file`.
+As the following example shows, requests must end with `/file`.
If you send a request ending with something else, it results in a 404
error `{"error":"404 Not Found"}`.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 36c49e39151..4476b0dd75b 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -46,199 +46,266 @@ The following table lists project permissions available for each role:
<!-- Keep this table sorted: By topic first, then by minimum role, then alphabetically. -->
-| Action | Guest | Reporter | Developer | Maintainer | Owner |
-|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|-----------|------------|-------|
-| [Analytics](analytics/index.md):<br>View issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View [code review analytics](analytics/code_review_analytics.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| [Analytics](analytics/index.md):<br>View [repository analytics](analytics/repository_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>View licenses in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>Create and run [on-demand DAST scans](application_security/dast/index.md#on-demand-scans) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>Manage [security policy](application_security/policies/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>View [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>View [threats list](application_security/threat_monitoring/index.md#threat-monitoring) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>Create a [CVE ID Request](application_security/cve_id_request.md) **(FREE SAAS)** | | | | ✓ | ✓ |
-| [Application security](application_security/index.md):<br>Create or assign [security policy project](application_security/policies/index.md) **(ULTIMATE)** | | | | | ✓ |
-| [CI/CD](../ci/index.md):<br>Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>View a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>View list of jobs | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>View [environments](../ci/environments/index.md) | | ✓ | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Cancel and retry jobs | | | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Create new [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Run CI/CD pipeline against a protected branch | | | ✓ (*5*) | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Stop [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>View a job with [debug logging](../ci/variables/index.md#debug-logging) | | | ✓ | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Manage CI/CD variables | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Manage job triggers | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Manage group runners | | | | | ✓ |
-| [CI/CD](../ci/index.md):<br>Manage project runners | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Delete pipelines | | | | | ✓ |
-| [Clusters](infrastructure/clusters/index.md):<br>View [pod logs](project/clusters/kubernetes_pod_logs.md) | | | ✓ | ✓ | ✓ |
-| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ |
-| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete cleanup policies | | | ✓ | ✓ | ✓ |
-| [Container Registry](packages/container_registry/index.md):<br>Remove a container registry image | | | ✓ | ✓ | ✓ |
-| [Container Registry](packages/container_registry/index.md):<br>Update container registry | | | ✓ | ✓ | ✓ |
-| [GitLab Pages](project/pages/index.md):<br>View Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control) | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [GitLab Pages](project/pages/index.md):<br>Manage | | | | ✓ | ✓ |
-| [GitLab Pages](project/pages/index.md):<br>Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
-| [GitLab Pages](project/pages/index.md):<br>Remove GitLab Pages | | | | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>View [alerts](../operations/incident_management/alerts.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>Assign an alert | ✓| ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>View [incident](../operations/incident_management/incidents.md) | ✓| ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>Create [incident](../operations/incident_management/incidents.md) | (*17*) | ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>View [on-call schedules](../operations/incident_management/oncall_schedules.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>Participate in on-call rotation | ✓| ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>View [escalation policies](../operations/incident_management/escalation_policies.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>Manage [on-call schedules](../operations/incident_management/oncall_schedules.md) | | | | ✓ | ✓ |
-| [Incident Management](../operations/incident_management/index.md):<br>Manage [escalation policies](../operations/incident_management/escalation_policies.md) | | | | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Assign | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Create | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Create [confidential issues](project/issues/confidential_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>View related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Set weight | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Close / reopen | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Manage related issues | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Move issues (*15*) | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Delete | | | | | ✓ |
-| [License Compliance](compliance/license_compliance/index.md):<br>View allowed and denied licenses **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [License Compliance](compliance/license_compliance/index.md):<br>View License Compliance reports **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [License Compliance](compliance/license_compliance/index.md):<br>View License list **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| [License Compliance](compliance/license_compliance/index.md):<br>Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Assign reviewer | | ✓ | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>See list | | ✓ | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Apply code change suggestions | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Approve (*9*) | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Assign | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Create (*18*) | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Add labels | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Lock threads | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Manage or accept | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Manage merge approval rules (project settings) | | | | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Delete | | | | | ✓ |
-| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
-| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
-| [Package registry](packages/index.md):<br>Pull package | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Package registry](packages/index.md):<br>Publish package | | | ✓ | ✓ | ✓ |
-| [Package registry](packages/index.md):<br>Delete package | | | | ✓ | ✓ |
-| [Project operations](../operations/index.md):<br>View [Error Tracking](../operations/error_tracking.md) list | | ✓ | ✓ | ✓ | ✓ |
-| [Project operations](../operations/index.md):<br>Manage [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
-| [Project operations](../operations/index.md):<br>Manage [Error Tracking](../operations/error_tracking.md) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Reposition comments on images (posted by any user) | ✓ (*10*) | ✓ (*10*) | ✓ (*10*) | ✓ | ✓ |
-| [Projects](project/index.md):<br>View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View [releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View Requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View [time tracking](project/time_tracking.md) reports | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View [wiki](project/wiki/index.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Create [snippets](snippets.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Manage labels | | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View [project traffic statistics](../api/project_statistics.md) | | ✓ | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Create, edit, delete [milestones](project/milestones/index.md). | | | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Create, edit, delete [releases](project/releases/index.md) | | | ✓ (*13*) | ✓ (*13*) | ✓ (*13*) |
-| [Projects](project/index.md):<br>Create, edit [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Enable Review Apps | | | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>View project [Audit Events](../administration/audit_events.md) | | | ✓ (*11*) | ✓ | ✓ |
-| [Projects](project/index.md):<br>Add deploy keys | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Add new team members | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Change [project features visibility](../public_access/public_access.md) level | | | | ✓ (14) | ✓ |
-| [Projects](project/index.md):<br>Configure [webhooks](project/integrations/webhooks.md) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ |
-| [Projects](project/index.md):<br>Edit comments (posted by any user) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Edit project badges | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Edit project settings | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Export project | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** **(PREMIUM SAAS)** (*12*) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Manage [Project Operations](../operations/index.md) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*8*) | ✓ (*8*) |
-| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Administer project compliance frameworks | | | | | ✓ |
-| [Projects](project/index.md):<br>Archive project | | | | | ✓ |
-| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ |
-| [Projects](project/index.md):<br>Delete project | | | | | ✓ |
-| [Projects](project/index.md):<br>Disable notification emails | | | | | ✓ |
-| [Projects](project/index.md):<br>Rename project | | | | | ✓ |
-| [Projects](project/index.md):<br>Transfer project to another namespace | | | | | ✓ |
-| [Repository](project/repository/index.md):<br>Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>View a commit status | | ✓ | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Add tags | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Create new branches | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Create or update commit status | | | ✓ (*5*) | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Force push to non-protected branches | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Push to non-protected branches | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Remove non-protected branches | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Rewrite or remove Git tags | | | ✓ | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Enable or disable branch protection | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Enable or disable tag protection | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Push to protected branches (*5*) | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Turn on or off protected branch push for developers | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Remove fork relationship | | | | | ✓ |
-| [Repository](project/repository/index.md):<br>Force push to protected branches (*4*) | | | | | |
-| [Repository](project/repository/index.md):<br>Remove protected branches (*4*) | | | | | |
-| [Requirements Management](project/requirements/index.md):<br>Archive / reopen **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| [Requirements Management](project/requirements/index.md):<br>Create / edit **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| [Requirements Management](project/requirements/index.md):<br>Import / export **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>View Security reports **(ULTIMATE)** | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Create issue from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Create vulnerability from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Resolve vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Revert vulnerability to detected state **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability findings in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| [Terraform](infrastructure/index.md):<br>Read Terraform state | | | ✓ | ✓ | ✓ |
-| [Terraform](infrastructure/index.md):<br>Manage Terraform state | | | | ✓ | ✓ |
-| [Test cases](../ci/test_cases/index.md):<br>Archive | | ✓ | ✓ | ✓ | ✓ |
-| [Test cases](../ci/test_cases/index.md):<br>Create | | ✓ | ✓ | ✓ | ✓ |
-| [Test cases](../ci/test_cases/index.md):<br>Move | | ✓ | ✓ | ✓ | ✓ |
-| [Test cases](../ci/test_cases/index.md):<br>Reopen | | ✓ | ✓ | ✓ | ✓ |
+| Action | Guest | Reporter | Developer | Maintainer | Owner |
+|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|-----------|------------|-------|
+| [Analytics](analytics/index.md):<br>View issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View [code review analytics](analytics/code_review_analytics.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| [Analytics](analytics/index.md):<br>View [repository analytics](analytics/repository_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>View licenses in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>Create and run [on-demand DAST scans](application_security/dast/index.md#on-demand-scans) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>Manage [security policy](application_security/policies/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>View [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>View [threats list](application_security/threat_monitoring/index.md#threat-monitoring) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>Create a [CVE ID Request](application_security/cve_id_request.md) **(FREE SAAS)** | | | | ✓ | ✓ |
+| [Application security](application_security/index.md):<br>Create or assign [security policy project](application_security/policies/index.md) **(ULTIMATE)** | | | | | ✓ |
+| [Clusters](infrastructure/clusters/index.md):<br>View [pod logs](project/clusters/kubernetes_pod_logs.md) | | | ✓ | ✓ | ✓ |
+| [Clusters](infrastructure/clusters/index.md):<br>View clusters | | | ✓ | ✓ | ✓ |
+| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ |
+| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete cleanup policies | | | ✓ | ✓ | ✓ |
+| [Container Registry](packages/container_registry/index.md):<br>Push an image to the Container Registry | | | ✓ | ✓ | ✓ |
+| [Container Registry](packages/container_registry/index.md):<br>Pull an image from the Container Registry | ✓ (*20*) | ✓ (*20*) | ✓ | ✓ | ✓ |
+| [Container Registry](packages/container_registry/index.md):<br>Remove a Container Registry image | | | ✓ | ✓ | ✓ |
+| [GitLab Pages](project/pages/index.md):<br>View Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [GitLab Pages](project/pages/index.md):<br>Manage | | | | ✓ | ✓ |
+| [GitLab Pages](project/pages/index.md):<br>Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
+| [GitLab Pages](project/pages/index.md):<br>Remove GitLab Pages | | | | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [alerts](../operations/incident_management/alerts.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Assign an alert | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [incident](../operations/incident_management/incidents.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Create [incident](../operations/incident_management/incidents.md) | (*16*) | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [on-call schedules](../operations/incident_management/oncall_schedules.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Participate in on-call rotation | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [escalation policies](../operations/incident_management/escalation_policies.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Manage [on-call schedules](../operations/incident_management/oncall_schedules.md) | | | | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Manage [escalation policies](../operations/incident_management/escalation_policies.md) | | | | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Assign | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Create (*18*) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Create [confidential issues](project/issues/confidential_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>View related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Set weight | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Close / reopen (*19*) | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Manage related issues | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Move issues (*14*) | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Delete | | | | | ✓ |
+| [License Compliance](compliance/license_compliance/index.md):<br>View allowed and denied licenses **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [License Compliance](compliance/license_compliance/index.md):<br>View License Compliance reports **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [License Compliance](compliance/license_compliance/index.md):<br>View License list **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| [License Compliance](compliance/license_compliance/index.md):<br>Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Assign reviewer | | ✓ | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>See list | | ✓ | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Apply code change suggestions | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Approve (*8*) | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Assign | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Create (*17*) | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Add labels | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Lock threads | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Manage or accept | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Manage merge approval rules (project settings) | | | | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Delete | | | | | ✓ |
+| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Manage user-starred metrics dashboards (*6*) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
+| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
+| [Package registry](packages/index.md):<br>Pull a package | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Package registry](packages/index.md):<br>Publish a package | | | ✓ | ✓ | ✓ |
+| [Package registry](packages/index.md):<br>Delete a package | | | | ✓ | ✓ |
+| [Package registry](packages/index.md):<br>Delete a file associated with a package | | | | ✓ | ✓ |
+| [Project operations](../operations/index.md):<br>View [Error Tracking](../operations/error_tracking.md) list | | ✓ | ✓ | ✓ | ✓ |
+| [Project operations](../operations/index.md):<br>Manage [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| [Project operations](../operations/index.md):<br>Manage [Error Tracking](../operations/error_tracking.md) | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Reposition comments on images (posted by any user) | ✓ (*9*) | ✓ (*9*) | ✓ (*9*) | ✓ | ✓ |
+| [Projects](project/index.md):<br>View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View [releases](project/releases/index.md) | ✓ (*5*) | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View Requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View [time tracking](project/time_tracking.md) reports | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View [wiki](project/wiki/index.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Create [snippets](snippets.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Manage labels | | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View [project traffic statistics](../api/project_statistics.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Create, edit, delete [milestones](project/milestones/index.md). | | | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Create, edit, delete [releases](project/releases/index.md) | | | ✓ (*12*) | ✓ (*12*) | ✓ (*12*) |
+| [Projects](project/index.md):<br>Create, edit [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Enable Review Apps | | | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>View project [Audit Events](../administration/audit_events.md) | | | ✓ (*10*) | ✓ | ✓ |
+| [Projects](project/index.md):<br>Add deploy keys | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Add new team members | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Change [project features visibility](../public_access/public_access.md) level | | | | ✓ (*13*) | ✓ |
+| [Projects](project/index.md):<br>Configure [webhooks](project/integrations/webhooks.md) | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ |
+| [Projects](project/index.md):<br>Edit comments (posted by any user) | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Edit project badges | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Edit project settings | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Export project | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** **(PREMIUM SAAS)** (*11*) | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Manage [Project Operations](../operations/index.md) | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Rename project | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*7*) | ✓ (*7*) |
+| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Administer project compliance frameworks | | | | | ✓ |
+| [Projects](project/index.md):<br>Archive project | | | | | ✓ |
+| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ |
+| [Projects](project/index.md):<br>Delete project | | | | | ✓ |
+| [Projects](project/index.md):<br>Disable notification emails | | | | | ✓ |
+| [Projects](project/index.md):<br>Transfer project to another namespace | | | | | ✓ |
+| [Repository](project/repository/index.md):<br>Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>View a commit status | | ✓ | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Add tags | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Create new branches | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Create or update commit status | | | ✓ (*4*) | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Force push to non-protected branches | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Push to non-protected branches | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Remove non-protected branches | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Rewrite or remove Git tags | | | ✓ | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Enable or disable branch protection | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Enable or disable tag protection | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Manage [push rules](project/repository/push_rules.md) | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Push to protected branches (*4*) | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Turn on or off protected branch push for developers | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Remove fork relationship | | | | | ✓ |
+| [Repository](project/repository/index.md):<br>Force push to protected branches (*3*) | | | | | |
+| [Repository](project/repository/index.md):<br>Remove protected branches (*3*) | | | | | |
+| [Requirements Management](project/requirements/index.md):<br>Archive / reopen **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| [Requirements Management](project/requirements/index.md):<br>Create / edit **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| [Requirements Management](project/requirements/index.md):<br>Import / export **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Create issue from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Create vulnerability from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Resolve vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Revert vulnerability to detected state **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability findings in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| [Terraform](infrastructure/index.md):<br>Read Terraform state | | | ✓ | ✓ | ✓ |
+| [Terraform](infrastructure/index.md):<br>Manage Terraform state | | | | ✓ | ✓ |
+| [Test cases](../ci/test_cases/index.md):<br>Archive | | ✓ | ✓ | ✓ | ✓ |
+| [Test cases](../ci/test_cases/index.md):<br>Create | | ✓ | ✓ | ✓ | ✓ |
+| [Test cases](../ci/test_cases/index.md):<br>Move | | ✓ | ✓ | ✓ | ✓ |
+| [Test cases](../ci/test_cases/index.md):<br>Reopen | | ✓ | ✓ | ✓ | ✓ |
+
+<!-- markdownlint-disable MD029 -->
1. On self-managed GitLab instances, guest users are able to perform this action only on
public and internal projects (not on private projects). [External users](#external-users)
must be given explicit access even if the project is internal. For GitLab.com, see the
[GitLab.com visibility settings](gitlab_com/index.md#visibility-settings).
-1. Guest users can only view the [confidential issues](project/issues/confidential_issues.md) they created themselves.
-1. If **Public pipelines** is enabled in **Project Settings > CI/CD**.
-1. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [protected branches](project/protected_branches.md).
-1. If the [branch is protected](project/protected_branches.md), this depends on the access Developers and Maintainers are given.
-1. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see [repository information like commits and release evidence](project/releases/index.md#view-a-release-and-download-assets).
-1. Actions are limited only to records owned (referenced) by user.
-1. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
-1. For information on eligible approvers for merge requests, see
+2. Guest users can only view the [confidential issues](project/issues/confidential_issues.md) they created themselves.
+3. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [protected branches](project/protected_branches.md).
+4. If the [branch is protected](project/protected_branches.md), this depends on the access Developers and Maintainers are given.
+5. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see [repository information like commits and release evidence](project/releases/index.md#view-a-release-and-download-assets).
+6. Actions are limited only to records owned (referenced) by user.
+7. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
+8. For information on eligible approvers for merge requests, see
[Eligible approvers](project/merge_requests/approvals/rules.md#eligible-approvers).
-1. Applies only to comments on [Design Management](project/issues/design_management.md) designs.
-1. Users can only view events based on their individual actions.
-1. Project access tokens are supported for self-managed instances on Free and above. They are also
- supported on GitLab SaaS Premium and above (excluding [trial licenses](https://about.gitlab.com/free-trial/)).
-1. If the [tag is protected](#release-permissions-with-protected-tags), this depends on the access Developers and Maintainers are given.
-1. A Maintainer can't change project features visibility level if
- [project visibility](../public_access/public_access.md) is set to private.
-1. Attached design files are moved together with the issue even if the user doesn't have the
- Developer role.
-1. Guest users can only set metadata (for example, labels, assignees, or milestones)
- when creating an issue. They cannot change the metadata on existing issues.
-1. In GitLab 14.5 or later, Guests are not allowed to [create incidents](../operations/incident_management/incidents.md#incident-creation).
-1. In projects that accept contributions from external members, users can create, edit, and close their own merge requests.
+9. Applies only to comments on [Design Management](project/issues/design_management.md) designs.
+10. Users can only view events based on their individual actions.
+11. Project access tokens are supported for self-managed instances on Free and above. They are also
+ supported on GitLab SaaS Premium and above (excluding [trial licenses](https://about.gitlab.com/free-trial/)).
+12. If the [tag is protected](#release-permissions-with-protected-tags), this depends on the access Developers and Maintainers are given.
+13. A Maintainer can't change project features visibility level if
+ [project visibility](../public_access/public_access.md) is set to private.
+14. Attached design files are moved together with the issue even if the user doesn't have the
+ Developer role.
+15. Guest users can only set metadata (for example, labels, assignees, or milestones)
+ when creating an issue. They cannot change the metadata on existing issues.
+16. In GitLab 14.5 or later, Guests are not allowed to [create incidents](../operations/incident_management/incidents.md#incident-creation).
+ A guest who created an incident when they had the Reporter role or who is assigned to the incident can modify the title, description and metrics. They can also close and reopen the incident.
+17. In projects that accept contributions from external members, users can create, edit, and close their own merge requests.
+18. Authors and assignees of issues can modify the title and description even if they don't have the Reporter role.
+19. Authors and assignees can close and reopen issues even if they don't have the Reporter role.
+20. The ability to view the Container Registry and pull images is controlled by the [Container Registry's visibility permissions](packages/container_registry/index.md#container-registry-visibility-permissions).
+
+<!-- markdownlint-enable MD029 -->
## Project features permissions
+More details about the permissions for some project-level features follow.
+
+### GitLab CI/CD permissions
+
+[GitLab CI/CD](../ci/index.md) permissions for some roles can be modified by these settings:
+
+- [Public pipelines](../ci/pipelines/settings.md#change-which-users-can-view-your-pipelines):
+ When set to public, gives access to certain CI/CD features to *Guest* project members.
+- [Pipeline visibility](../ci/enable_or_disable_ci.md#enable-cicd-in-a-project): When set to **Everyone with Access**,
+ gives access to certain CI/CD "view" features to *non-project* members.
+
+| Action | Non-member | Guest | Reporter | Developer | Maintainer | Owner |
+|-----------------------------------------------------------------------------------|------------|---------|----------|-----------|------------|-------|
+| See that artifacts exist | ✓ (*3*) | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| View a list of jobs | ✓ (*1*) | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| View and download artifacts | ✓ (*1*) | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| View [environments](../ci/environments/index.md) | ✓ (*3*) | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| View job logs and job details page | ✓ (*1*) | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| View pipeline details page | ✓ (*1*) | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| View pipelines page | ✓ (*1*) | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| View pipelines tab in MR | ✓ (*3*) | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| [View vulnerabilities in a pipeline](application_security/security_dashboard/index.md#view-vulnerabilities-in-a-pipeline) | | ✓ (*2*) | ✓ | ✓ | ✓ | ✓ |
+| Cancel and retry jobs | | | | ✓ | ✓ | ✓ |
+| Create new [environments](../ci/environments/index.md) | | | | ✓ | ✓ | ✓ |
+| Delete job logs or job artifacts | | | | ✓ (*4*) | ✓ | ✓ |
+| Run CI/CD pipeline for a protected branch | | | | ✓ (*5*) | ✓ (*5*) | ✓ |
+| Stop [environments](../ci/environments/index.md) | | | | ✓ | ✓ | ✓ |
+| View a job with [debug logging](../ci/variables/index.md#debug-logging) | | | | ✓ | ✓ | ✓ |
+| Use pipeline editor | | | | ✓ | ✓ | ✓ |
+| Add specific runners to project | | | | | ✓ | ✓ |
+| Clear runner caches manually | | | | | ✓ | ✓ |
+| Enable shared runners in project | | | | | ✓ | ✓ |
+| Manage CI/CD settings | | | | | ✓ | ✓ |
+| Manage job triggers | | | | | ✓ | ✓ |
+| Manage project-level CI/CD variables | | | | | ✓ | ✓ |
+| Run [interactive web terminals](../ci/interactive_web_terminal/index.md) | | | | | ✓ | ✓ |
+| Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | | ✓ | ✓ |
+| Delete pipelines | | | | | | ✓ |
+
+<!-- markdownlint-disable MD029 -->
+
+1. If the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.
+2. If **Public pipelines** is enabled in **Project Settings > CI/CD**.
+3. If the project is public.
+4. Only if the job was both:
+ - Triggered by the user.
+ - [In GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/35069) and later,
+ run for a non-protected branch.
+5. If the user is [allowed to merge or push to the protected branch](../ci/pipelines/index.md#pipeline-security-on-protected-branches).
+
+<!-- markdownlint-enable MD029 -->
+
+#### Job permissions
+
+This table shows granted privileges for jobs triggered by specific types of users:
+
+| Action | Guest, Reporter | Developer | Maintainer| Administrator |
+|---------------------------------------------|-----------------|-----------|-----------|---------------|
+| Run CI job | | ✓ | ✓ | ✓ |
+| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
+| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
+| Clone source and LFS from internal projects | | ✓ (*1*) | ✓ (*1*) | ✓ |
+| Clone source and LFS from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
+| Pull container images from current project | | ✓ | ✓ | ✓ |
+| Pull container images from public projects | | ✓ | ✓ | ✓ |
+| Pull container images from internal projects| | ✓ (*1*) | ✓ (*1*) | ✓ |
+| Pull container images from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
+| Push container images to current project | | ✓ | ✓ | ✓ |
+| Push container images to other projects | | | | |
+| Push source and LFS | | | | |
+
+1. Only if the triggering user is not an external one.
+1. Only if the triggering user is a member of the project.
+
### Wiki and issues
Project features like [wikis](project/wiki/index.md) and issues can be hidden from users depending on
@@ -257,9 +324,9 @@ Maintainers and Developers from pushing to a protected branch. Read through the
[protected branches](project/protected_branches.md)
to learn more.
-### Value Stream Analytics permissions
+### Value stream analytics permissions
-Find the current permissions on the Value Stream Analytics dashboard, as described in
+Find the current permissions on the value stream analytics dashboard, as described in
[related documentation](analytics/value_stream_analytics.md#permissions).
### Issue board permissions
@@ -281,7 +348,8 @@ read through the documentation on [permissions and access to confidential issues
### Container Registry visibility permissions
-Find the visibility permissions for the Container Registry, as described in the
+The ability to view the Container Registry and pull images is controlled by the Container Registry's
+visibility permissions. Find these permissions for the Container Registry as described in the
[related documentation](packages/container_registry/index.md#container-registry-visibility-permissions).
## Group members permissions
@@ -293,67 +361,74 @@ The following table lists group permissions available for each role:
<!-- Keep this table sorted: first, by minimum role, then alphabetically. -->
-| Action | Guest | Reporter | Developer | Maintainer | Owner |
-|--------------------------------------------------------|-------|----------|-----------|------------|-------|
-| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
-| Pull a container image using the dependency proxy | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View group wiki pages **(PREMIUM)** | ✓ (6) | ✓ | ✓ | ✓ | ✓ |
-| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Insights charts **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Create/edit group epic **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| Create/edit/delete epic boards **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
-| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
-| View a container registry | | ✓ | ✓ | ✓ | ✓ |
-| View Group DevOps Adoption **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
-| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| Create and edit group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
-| Create project in group | | | ✓ (3)(5) | ✓ (3) | ✓ (3) |
-| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
-| Create/edit/delete iterations | | | ✓ | ✓ | ✓ |
-| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
-| Enable/disable a dependency proxy | | | ✓ | ✓ | ✓ |
-| Purge the dependency proxy for a group | | | | | ✓ |
-| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
-| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
-| Create subgroup | | | | ✓ (1) | ✓ |
-| Delete group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
-| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
-| List group deploy tokens | | | | ✓ | ✓ |
-| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
-| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
-| Administer project compliance frameworks | | | | | ✓ |
-| Create/Delete group deploy tokens | | | | | ✓ |
-| Change group visibility level | | | | | ✓ |
-| Delete group | | | | | ✓ |
-| Delete group epic **(PREMIUM)** | | | | | ✓ |
-| Disable notification emails | | | | | ✓ |
-| Edit group settings | | | | | ✓ |
-| Filter members by 2FA status | | | | | ✓ |
-| Manage group level CI/CD variables | | | | | ✓ |
-| Manage group members | | | | | ✓ |
-| Share (invite) groups with groups | | | | | ✓ |
-| View 2FA status of members | | | | | ✓ |
-| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
-| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
+| Action | Guest | Reporter | Developer | Maintainer | Owner |
+|--------------------------------------------------------------------------|-------|----------|-----------|------------|-------|
+| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Pull a container image using the dependency proxy | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View group wiki pages **(PREMIUM)** | ✓ (6) | ✓ | ✓ | ✓ | ✓ |
+| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Insights charts **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create/edit group epic **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Create/edit/delete epic boards **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
+| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
+| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
+| Delete [packages](packages/index.md | | | | ✓ | ✓ |
+| Pull a Container Registry image | ✓ (7) | ✓ | ✓ | ✓ | ✓ |
+| Remove a Container Registry image | | | ✓ | ✓ | ✓ |
+| View Group DevOps Adoption **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
+| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Create and edit group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Create project in group | | | ✓ (3)(5) | ✓ (3) | ✓ (3) |
+| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
+| Create/edit/delete iterations | | | ✓ | ✓ | ✓ |
+| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
+| Enable/disable a dependency proxy | | | ✓ | ✓ | ✓ |
+| Purge the dependency proxy for a group | | | | | ✓ |
+| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
+| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
+| Create subgroup | | | | ✓ (1) | ✓ |
+| Delete group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
+| List group deploy tokens | | | | ✓ | ✓ |
+| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
+| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
+| Administer project compliance frameworks | | | | | ✓ |
+| Create/Delete group deploy tokens | | | | | ✓ |
+| Change group visibility level | | | | | ✓ |
+| Delete group | | | | | ✓ |
+| Delete group epic **(PREMIUM)** | | | | | ✓ |
+| Disable notification emails | | | | | ✓ |
+| Edit group settings | | | | | ✓ |
+| Edit SAML SSO **(PREMIUM SAAS)** | | | | | ✓ (4) |
+| Filter members by 2FA status | | | | | ✓ |
+| Manage group level CI/CD variables | | | | | ✓ |
+| Manage group members | | | | | ✓ |
+| Share (invite) groups with groups | | | | | ✓ |
+| View 2FA status of members | | | | | ✓ |
+| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
+| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
+| Manage runners | | | | | ✓ |
+
+<!-- markdownlint-disable MD029 -->
1. Groups can be set to [allow either Owners or Owners and
Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup)
-1. Introduced in GitLab 12.2.
-1. Default project creation role can be changed at:
+2. Introduced in GitLab 12.2.
+3. Default project creation role can be changed at:
- The [instance level](admin_area/settings/visibility_and_access_controls.md#define-which-roles-can-create-projects).
- The [group level](group/index.md#specify-who-can-add-projects-to-a-group).
-1. Does not apply to subgroups.
-1. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#change-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected".
-1. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages.
-1. Users can only view events based on their individual actions.
+4. Does not apply to subgroups.
+5. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#change-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected".
+6. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages.
+7. Users can only view events based on their individual actions.
+
+<!-- markdownlint-enable MD029 -->
### Subgroup permissions
@@ -470,11 +545,16 @@ with the permissions described on the documentation on [auditor users permission
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
-Owners can add members with a "minimal access" role to a parent group. Such users don't
-automatically have access to projects and subgroups underneath. To support such access, owners must explicitly add these "minimal access" users to the specific subgroups/projects.
+Owners can add members with a "minimal access" role to a parent group. Such users don't automatically have access to
+projects and subgroups underneath. Owners must explicitly add these "minimal access" users to the specific subgroups and
+projects.
+
+Because of an [outstanding issue](https://gitlab.com/gitlab-org/gitlab/-/issues/267996), when minimal access users:
-Users with minimal access can list the group in the UI and through the API. However, they cannot see
-details such as projects or subgroups. They do not have access to the group's page or list any of its subgroups or projects.
+- Sign in with standard web authentication, they receive a `404` error when accessing the parent group.
+- Sign in with Group SSO, they receive a `404` error immediately because they are redirected to the parent group page.
+
+To work around the issue, give these users the Guest role or higher to any project or subgroup within the parent group.
### Minimal access users take license seats
@@ -492,66 +572,6 @@ which visibility level you select on project settings.
- Everyone with access: everyone can see depending on your project visibility level.
- Everyone: enabled for everyone (only available for GitLab Pages).
-## GitLab CI/CD permissions
-
-GitLab CI/CD permissions rely on the role the user has in GitLab:
-
-- Maintainer
-- Developer
-- Guest/Reporter
-
-GitLab administrators 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 | | | | ✓ |
-| Clear runner caches manually | | | ✓ | ✓ |
-| 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, run for a non-protected branch.
-
-### Job permissions
-
-This table shows granted privileges for jobs triggered by specific types of
-users:
-
-| Action | Guest, Reporter | Developer |Maintainer| Administrator |
-|---------------------------------------------|-----------------|-------------|----------|---------|
-| Run CI job | | ✓ | ✓ | ✓ |
-| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
-| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
-| Clone source and LFS from internal projects | | ✓ (*1*) | ✓ (*1*) | ✓ |
-| Clone source and LFS from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
-| Pull container images from current project | | ✓ | ✓ | ✓ |
-| Pull container images from public projects | | ✓ | ✓ | ✓ |
-| Pull container images from internal projects| | ✓ (*1*) | ✓ (*1*) | ✓ |
-| Pull container images from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
-| Push container images to current project | | ✓ | ✓ | ✓ |
-| Push container images to other projects | | | | |
-| Push source and LFS | | | | |
-
-1. Only if the triggering user is not an external one
-1. Only if the triggering user is a member of the project
-
-## Running pipelines on protected branches
-
-The permission to merge or push to protected branches is used to define if a user can
-run CI/CD pipelines and execute actions on jobs that are related to those branches.
-
-See [Security on protected branches](../ci/pipelines/index.md#pipeline-security-on-protected-branches)
-for details about the pipelines security model.
-
## Release permissions with protected tags
[The permission to create tags](project/protected_tags.md) is used to define if a user can
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 32b8d2b33ee..7e1074aa50f 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -1,7 +1,7 @@
---
type: reference
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 365f96b48b3..c116b1fc00d 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -1,7 +1,7 @@
---
type: howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -55,16 +55,17 @@ There are two options for deleting users:
- **Delete user and contributions**
When using the **Delete user** option, not all associated records are deleted with the user.
-Here's a list of things that are **not** deleted:
+Here's a list of things created by the user that are **not** deleted:
-- Issues that the user created.
-- Merge requests that the user created.
-- Notes that the user created.
-- Abuse reports that the user reported.
-- Award emoji that the user created.
+- Abuse reports
+- Award emoji
+- Epics
+- Issues
+- Merge requests
+- Notes
Instead of being deleted, these records are moved to a system-wide
-user with the username "Ghost User", whose sole purpose is to act as a container
+user with the username Ghost User, whose sole purpose is to act as a container
for such records. Any commits made by a deleted user still display the
username of the original user.
@@ -81,14 +82,21 @@ is a sole owner of. Administrators can also request this behavior when
deleting users from the [API](../../../api/users.md#user-deletion) or the
Admin Area.
-<!-- ## Troubleshooting
+## 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.
+### Deleting a user results in a PostgreSQL null value error
-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. -->
+There is [a known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/349411) that results
+in users not being deleted, and the following error generated:
+
+```plaintext
+ERROR: null value in column "user_id" violates not-null constraint
+```
+
+The error can be found in the [PostgreSQL log](../../../administration/logs.md#postgresql-logs) and
+in the **Retries** section of the [background jobs view](../../admin_area/index.md#background-jobs) in the Admin Area.
+
+If the user being deleted used the [iterations](../../group/iterations/index.md) feature, such
+as adding an issue to an iteration, you must use
+[the workaround documented in the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/349411#workaround)
+to delete the user.
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 3af8c1c1b5a..a820cf150e9 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/user/profile/img/personal_readme_setup_v14_5.png b/doc/user/profile/img/personal_readme_setup_v14_5.png
new file mode 100644
index 00000000000..92d8e0ec936
--- /dev/null
+++ b/doc/user/profile/img/personal_readme_setup_v14_5.png
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 89e4ea6ea5b..f201e04183c 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -1,7 +1,7 @@
---
type: index, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -104,16 +104,34 @@ user profiles are only visible to signed-in users.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232157) in GitLab 14.5.
-If you want to add more information to your profile page, you can create a README file. When you populate the README file with information, it's included on your profile page.
+You can add more information to your profile page with a README file. When you populate
+the README file with information, it's included on your profile page.
-To add a README to your profile:
+### From a new project
-1. Create a new public project with the same project path as your GitLab username.
+To create a new project and add its README to your profile:
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
+1. Select **Create blank project**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name for your new project.
+ - In the **Project URL** field, select your GitLab username.
+ - In the **Project slug** field, enter your GitLab username.
+1. For **Visibility Level**, select **Public**.
+ ![Proper project path for an individual on the hosted product](img/personal_readme_setup_v14_5.png)
+1. For **Project Configuration**, ensure **Initialize repository with a README** is selected.
+1. Select **Create project**.
1. Create a README file inside this project. The file can be any valid [README or index file](../project/repository/index.md#readme-and-index-files).
1. Populate the README file with [Markdown](../markdown.md).
-To use an existing project, [update the path](../project/settings/index.md#renaming-a-repository) of the project to match
-your username.
+GitLab displays the contents of your README below your contribution graph.
+
+### From an existing project
+
+To add the README from an existing project to your profile,
+[update the path](../project/settings/index.md#renaming-a-repository) of the project
+to match your username.
## Add external accounts to your user profile page
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 45cff326332..10d718fdf1a 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -1,7 +1,7 @@
---
type: concepts, howto
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -97,7 +97,7 @@ A personal access token can perform actions based on the assigned scopes.
| `read_user` | Read-only for endpoints under `/users`. Essentially, access to any of the `GET` requests in the [Users API](../../api/users.md). |
| `read_api` | Read-only for the complete API, including all groups and projects, the Container Registry, and the Package Registry. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28944) in GitLab 12.10.) |
| `read_repository` | Read-only (pull) for the repository through `git clone`. |
-| `write_repository` | Read-write (pull, push) for the repository through `git clone`. Required for accessing Git repositories over HTTP when 2FA is enabled. |
+| `write_repository` | Read-write (pull, push) for the repository through `git clone`. |
| `read_registry` | Read-only (pull) for [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. |
| `write_registry` | Read-write (push) for [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28958) in GitLab 12.10.) |
| `sudo` | API actions as any user in the system (if the authenticated user is an administrator). |
@@ -111,7 +111,7 @@ Personal access tokens expire on the date you define, at midnight UTC.
- In GitLab Ultimate, administrators can
[limit the lifetime of personal access tokens](../admin_area/settings/account_and_limit_settings.md#limit-the-lifetime-of-personal-access-tokens).
- In GitLab Ultimate, administrators can choose whether or not to
- [enforce personal access token expiration](../admin_area/settings/account_and_limit_settings.md#allow-expired-personal-access-tokens-to-be-used).
+ [enforce personal access token expiration](../admin_area/settings/account_and_limit_settings.md#allow-expired-personal-access-tokens-to-be-used-deprecated).
## Create a personal access token programmatically **(FREE SELF)**
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index 63be88f90d6..52baf5189e1 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -43,7 +43,7 @@ The default theme is Indigo. You can choose between 10 themes:
GitLab has started work on dark mode! The dark mode Alpha release is available in the
spirit of iteration and the lower expectations of
-[Alpha versions](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
+[Alpha versions](../../policy/alpha-beta-support.md#alpha-features).
Progress on dark mode is tracked in the [Dark theme epic](https://gitlab.com/groups/gitlab-org/-/epics/2902).
See the epic for:
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index 0ed2a11d363..37bde3ce846 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index a5473629d4f..e14a71a7e10 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -34,7 +34,7 @@ Prerequisites:
- An [Amazon Web Services](https://aws.amazon.com/) account.
- Permissions to manage IAM resources.
-For instance-level clusters, see [additional requirements for self-managed instances](#additional-requirements-for-self-managed-instances). **(FREE SELF)**
+For instance-level clusters, see [additional requirements for self-managed instances](#additional-requirements-for-self-managed-instances).
To create new Kubernetes clusters for your project, group, or instance through the certificate-based method:
@@ -174,7 +174,7 @@ When you create a new cluster, you have the following settings:
| Kubernetes cluster name | Your cluster's name. |
| Environment scope | The [associated environment](multiple_kubernetes_clusters.md#setting-the-environment-scope). |
| Service role | The **EKS IAM role** (**role A**). |
-| Kubernetes version | The [Kubernetes version](../../infrastructure/clusters/connect/index.md#supported-cluster-versions) for your cluster. |
+| Kubernetes version | The [Kubernetes version](../../clusters/agent/index.md#supported-cluster-versions) for your cluster. |
| Key pair name | The [key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) that you can use to connect to your worker nodes. |
| VPC | The [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) to use for your EKS Cluster resources. |
| Subnets | The [subnets](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) in your VPC where your worker nodes run. Two are required. |
@@ -256,7 +256,7 @@ IAM user in the Amazon AWS console, and follow these steps:
#### EKS access key and ID
-> Instance profiles were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291015) in GitLab 13.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291015) instance profiles in GitLab 13.7.
If you're using GitLab 13.7 or later, you can use instance profiles to
dynamically retrieve temporary credentials from AWS when needed.
diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md
index acc5ed4cb30..0c3827bcbb1 100644
--- a/doc/user/project/clusters/add_existing_cluster.md
+++ b/doc/user/project/clusters/add_existing_cluster.md
@@ -4,7 +4,7 @@ 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
---
-# Connect existing clusters through cluster certificates **(DEPRECATED)**
+# Connect existing clusters through cluster certificates (DEPRECATED) **(FREE)**
> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
@@ -27,7 +27,7 @@ To add any cluster to GitLab, you need:
- Either a GitLab.com account or an account for a self-managed installation
running GitLab 12.5 or later.
- The Maintainer role for group-level and project-level clusters.
-- Access to the Admin area for instance-level clusters. **(FREE SELF)**
+- Access to the Admin area for instance-level clusters.
- A Kubernetes cluster.
- Cluster administration access to the cluster with `kubectl`.
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index 19166a1ff8c..b5e2a1bad51 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -1,13 +1,13 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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
---
# Kubernetes Logs (DEPRECATED) **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) to [GitLab Free](https://about.gitlab.com/pricing/) 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) in GitLab 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) from GitLab Ultimate to GitLab Free 12.9.
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
diff --git a/doc/user/project/clusters/multiple_kubernetes_clusters.md b/doc/user/project/clusters/multiple_kubernetes_clusters.md
index 12527853b40..a56eaa9b953 100644
--- a/doc/user/project/clusters/multiple_kubernetes_clusters.md
+++ b/doc/user/project/clusters/multiple_kubernetes_clusters.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Multiple clusters per project with cluster certificates (DEPRECATED) **(FREE)**
-> - Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) to GitLab Free in 13.2.
+> - Introduced in GitLab 10.3
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) from GitLab Premium to GitLab Free in 13.2.
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
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 98ba4a1f84d..a0297a7a86f 100644
--- a/doc/user/project/clusters/protect/container_host_security/index.md
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -6,11 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Host Security **(FREE)**
-NOTE:
-In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
-You can continue using Container Host Security, even though it relies on this certificate-based
-method. The work to allow all aspects of Container Host Security to function through the [GitLab Agent](../../../../clusters/agent/index.md)
-instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350).
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Container Host Security is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
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
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 466bcb7916f..4e56b7e5140 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
@@ -6,6 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Getting started with Container Host Security **(FREE)**
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Container Host Security is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
+
The following steps are recommended for installing Container Host Security.
## Installation steps
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 06dc6b24620..7176a1cf1b9 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -6,11 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Network Security **(FREE)**
-NOTE:
-In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
-You can continue using Container Network Security, even though it relies on this certificate-based
-method. The work to allow all aspects of Container Network Security to function through the [GitLab Agent](../../../../clusters/agent/index.md)
-instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350) and [this GitLab Epic](https://gitlab.com/groups/gitlab-org/-/epics/7057).
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Container Network Security is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
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
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 340c9397e9c..e6c91302d7b 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
@@ -6,6 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Getting started with Container Network Security **(FREE)**
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+Container Network Security is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
+
The following steps are recommended for installing Container Network Security.
## Installation steps
diff --git a/doc/user/project/clusters/protect/index.md b/doc/user/project/clusters/protect/index.md
index 1314a1948d5..473195f4c17 100644
--- a/doc/user/project/clusters/protect/index.md
+++ b/doc/user/project/clusters/protect/index.md
@@ -6,6 +6,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Protecting your deployed applications **(FREE)**
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0.
+
+WARNING:
+The Container Network Security and Container Host Security features are in their end-of-life
+processes. They're
+[deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476)
+for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477)
+in GitLab 15.0.
+
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
the network layer, the Container Network Security capabilities in GitLab provide basic firewall
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 265a60c6f2c..29164da307b 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/6) in GitLab 14.3.
WARNING:
-Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
+Serverless is currently in [alpha](../../../../policy/alpha-beta-support.md#alpha-features).
## Overview
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index 4068d8e056c..eb18834cc6b 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -281,7 +281,7 @@ README.md @docs
### Approvals shown as optional
-A Code Owner approval rule is optional if these conditions are not met:
+A Code Owner approval rule is optional if any of these conditions are true:
- The user or group are not a member of the project or parent group.
- [Code Owner approval on a protected branch](protected_branches.md#require-code-owner-approval-on-a-protected-branch) has not been set up.
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index 2e876b24b53..57f6efa3092 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -29,7 +29,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 at least the [Maintainer role](../../permissions.md)
+and make sure that the allowed users have at least the Maintainer role
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 f57fa5aa57d..4d69209aafa 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -14,7 +14,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Deploy tokens allow you to download (`git clone`) or push and pull packages and
container registry images of a project without having a user and a password.
-Deploy tokens can be managed by [maintainers only](../../permissions.md).
+Deploy tokens can be managed only by users with the Maintainer role.
Deploy tokens cannot be used with the GitLab API.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 6c17964f3a5..539f5230063 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -114,7 +114,9 @@ To re-use templates [you've created](../project/description_templates.md#create-
You might also be interested in templates for various
[file types in groups](../group/index.md#group-file-templates).
-### Set a default template for merge requests and issues **(PREMIUM)**
+### Set a default template for merge requests and issues
+
+> `Default.md` template [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78302) in GitLab 14.8.
In a project, you can choose a default description template for new issues and merge requests.
As a result, every time a new merge request or issue is created, it's pre-filled with the text you
@@ -125,17 +127,29 @@ Prerequisites:
- On your project's left sidebar, select **Settings > General** and expand **Visibility, project features, permissions**.
Ensure issues or merge requests are set to either **Everyone with access** or **Only Project Members**.
-To set a default description template for merge requests:
+To set a default description template for merge requests, either:
-1. Go to your project's **Settings**.
-1. Select **Expand** under the **Merge requests** header.
-1. Fill in the **Default description template for merge requests** text area.
-1. Select **Save changes**.
+- [Create a merge request template](#create-a-merge-request-template) named `Default.md` and save it in `.gitlab/merge_request_templates/`.
+ This will not overwrite the default template if one has been set in the project settings.
+- Users on GitLab Premium and higher: set the default template in project settings:
+
+ 1. On the top bar, select **Menu > Projects** and find your project.
+ 1. On the left sidebar, select **Settings**.
+ 1. Expand **Merge requests**.
+ 1. Fill in the **Default description template for merge requests** text area.
+ 1. Select **Save changes**.
+
+To set a default description template for issues, either:
-To set a default description template for issues:
+- [Create an issue template](#create-an-issue-template) named `Default.md` and save it in `.gitlab/issue_templates/`.
+ This will not overwrite the default template if one has been set in the project settings.
+- Users on GitLab Premium and higher: set the default template in project settings:
-1. Select **Expand** under **Default issue template**.
-1. Fill in the **Default description template for issues** text area.
+ 1. On the top bar, select **Menu > Projects** and find your project.
+ 1. On the left sidebar, select **Settings**.
+ 1. Expand **Default issue template**.
+ 1. Fill in the **Default description template for issues** text area.
+ 1. Select **Save changes**.
Because GitLab merge request and issues support [Markdown](../markdown.md), you can use it to format
headings, lists, and so on.
@@ -143,6 +157,16 @@ headings, lists, and so on.
You can also provide `issues_template` and `merge_requests_template` attributes in the
[Projects REST API](../../api/projects.md) to keep your default issue and merge request templates up to date.
+#### Priority of description templates
+
+When you set [merge request and issue description templates](#set-a-default-template-for-merge-requests-and-issues)
+in various places, they have the following priorities in a project.
+The ones higher up override the ones below:
+
+1. Template selected in project settings.
+1. `Default.md` from the parent group.
+1. `Default.md` from the project repository.
+
## Example description template
We use description templates for issues and merge requests in the
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index 1d06b605aa9..9911c90863d 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -33,7 +33,7 @@ GitLab supports two different modes of file locking:
## Permissions
Locks can be created by any person who has at least
-[Developer role](../permissions.md) in the repository.
+Developer role in the repository.
Only the user who locked the file or directory can edit locked files. Other
users are prevented from modifying locked files by pushing, merging,
@@ -77,7 +77,7 @@ Check this document to learn more about [using Git LFS](../../topics/git/lfs/ind
### Configure Exclusive File Locks
-You need the [Maintainer role](../permissions.md) to configure
+You need the Maintainer role
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
@@ -226,4 +226,4 @@ To view and remove file locks:
This list shows all the files locked either through LFS or GitLab UI.
Locks can be removed by their author, or any user
-with at least the [Maintainer role](../permissions.md).
+with at least the Maintainer role.
diff --git a/doc/user/project/img/time_tracking_example_v12_2.png b/doc/user/project/img/time_tracking_example_v12_2.png
deleted file mode 100644
index 31d8c490ed1..00000000000
--- a/doc/user/project/img/time_tracking_example_v12_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index 0c50fc77e33..62495872659 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -42,7 +42,7 @@ When issues/pull requests are being imported, the Bitbucket importer tries to fi
the Bitbucket author/assignee in the GitLab database using the Bitbucket `nickname`.
For this to work, the Bitbucket author/assignee should have signed in beforehand in GitLab
and **associated their Bitbucket account**. Their `nickname` must also match their Bitbucket
-`username.`. If the user is not found in the GitLab database, the project creator
+`username`. If the user is not found in the GitLab database, the project creator
(most of the times the current user that started the import process) is set as the author,
but a reference on the issue about the original Bitbucket author is kept.
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index da47b673c29..4e3642eb3bd 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -5,130 +5,110 @@ 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 **(FREE)**
+# Import your project from Bitbucket Server **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20164) in GitLab 11.2.
NOTE:
-The Bitbucket Server importer does not work with [Bitbucket Cloud](https://bitbucket.org).
-Use the [Bitbucket Cloud importer](bitbucket.md) for that.
+This process is different than [importing from Bitbucket Cloud](bitbucket.md).
-Import your projects from Bitbucket Server to GitLab with minimal effort.
+From Bitbucket Server, you can import:
-The Bitbucket importer can import:
-
-- Repository description (GitLab 11.2+)
-- Git repository data (GitLab 11.2+)
-- Pull requests (GitLab 11.2+)
-- Pull request comments (GitLab 11.2+)
+- Repository description
+- Git repository data
+- Pull requests
+- Pull request comments
When importing, repository public access is retained. If a repository is private in Bitbucket, it's
created as private in GitLab as well.
-## Limitations
+## Import your Bitbucket repositories
-- GitLab doesn't allow comments on arbitrary lines of code, so any Bitbucket comments out of bounds
- are inserted as comments in the merge request.
-- Bitbucket Server allows multiple levels of threading. GitLab import collapses this into one thread
- and quote part of the original comment.
-- Declined pull requests have unreachable commits, which prevents the GitLab importer from
- generating a proper diff. These pull requests show up as empty changes.
-- Pull request approvals are not imported.
-- Attachments in Markdown are not imported.
-- Task lists are not imported.
-- Emoji reactions are not imported.
-- Project filtering does not support fuzzy search (only `starts with` or `full match strings` are
- supported).
+Prerequisites:
-## How it works
+- An administrator must have enabled the **Bitbucket Server** in
+ **Admin > Settings > General > Visibility and access controls > Import sources**.
+- Review the importer's [limitations](#limitations).
-The Bitbucket Server importer works as follows:
+To import your Bitbucket repositories:
-1. The user is prompted to enter the URL, username, and password (or personal access token) to log in to Bitbucket.
- These credentials are preserved only as long as the importer is running.
-1. The importer attempts to list all the current repositories on the Bitbucket Server.
-1. Upon selection, the importer clones the repository and import pull requests and comments.
+1. Sign in to GitLab.
+1. On the top bar, select **New** (**{plus}**).
+1. Select **New project/repository**.
+1. Select **Import project**.
+1. Select **Bitbucket Server**.
+1. Log in to Bitbucket and grant GitLab access to your Bitbucket account.
+1. Select the projects to import, or import all projects. You can filter projects by name and select
+ the namespace for which to import each project.
-### User assignment
+## Limitations
-When issues/pull requests are being imported, the Bitbucket importer tries to
-find the author's email address with a confirmed email address in the GitLab
-user database. If no such user is available, the project creator is set as
-the author. The importer appends a note in the comment to mark the original
-creator.
+- GitLab doesn't allow comments on arbitrary lines of code. Any out-of-bounds Bitbucket comments are
+ inserted as comments in the merge request.
+- Bitbucket Server allows multiple threading levels. The importer collapses this into one thread and
+ quotes part of the original comment.
+- Declined pull requests have unreachable commits. This prevents the importer from generating a
+ proper diff. These pull requests show up as empty changes.
+- Project filtering doesn't support fuzzy search. Only starts with or full match strings are
+ supported.
-The importer creates any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository is imported under the user's
-namespace that started the import process.
+The following aren't imported:
-#### User assignment by username
+- Pull request approvals
+- Attachments in Markdown
+- Task lists
+- Emoji reactions
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218609) in GitLab 13.4.
-> - 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.
+## User assignment
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+When issues and pull requests are importing, the importer tries to find the author's email address
+with a confirmed email address in the GitLab user database. If no such user is available, the
+project creator is set as the author. The importer appends a note in the comment to mark the
+original creator.
-If you've enabled this feature, the importer tries to find a user in the GitLab user database with
-the author's:
+The importer creates any new namespaces (groups) if they don't exist. If the namespace is taken, the
+repository imports under the namespace of the user who started the import process.
-- `username`
-- `slug`
-- `displayName`
+### User assignment by username
-If the user is not found by any of these properties, the project creator is set as the author.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218609) in GitLab 13.4 [with a flag](../../../administration/feature_flags.md) named `bitbucket_server_user_mapping_by_username`. Disabled by default.
+> - Not recommended for production use.
-##### Enable or disable User assignment by username
+FLAG:
+On self-managed GitLab and GitLab.com, by default this feature is not available. To make it
+available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md)
+named `bitbucket_server_user_mapping_by_username`. This feature is not ready for production use.
-User assignment by username 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.
+With this feature enabled, the importer tries to find a user in the GitLab user database with the
+author's:
-To enable it:
+- `username`
+- `slug`
+- `displayName`
-```ruby
-Feature.enable(:bitbucket_server_user_mapping_by_username)
-```
+If no user matches these properties, the project creator is set as the author.
-To disable it:
+## Troubleshooting
-```ruby
-Feature.disable(:bitbucket_server_user_mapping_by_username)
-```
+### General
-## Import your Bitbucket repositories
+If the GUI-based import tool does not work, you can try to:
-Prerequisite:
+- Use the [GitLab Import API](../../../api/import.md#import-repository-from-bitbucket-server)
+ Bitbucket Server endpoint.
+- Set up [repository mirroring](../repository/mirror/index.md).
+ It provides verbose error output.
-- An administrator must have enabled the importer in
- **Admin > Application Settings > Visibility and access controls > Import sources**.
+See the [troubleshooting section](bitbucket.md#troubleshooting)
+for Bitbucket Cloud.
-To import your Bitbucket repositories:
+### LFS objects not imported
-1. Sign in to GitLab.
-1. On the top bar, select **New** (**{plus}**).
-1. Select **New project/repository**.
-1. Select **Import project**.
-1. Select **Bitbucket Server**.
-1. Log in to Bitbucket and grant GitLab access to your Bitbucket account.
-1. Select the projects that you'd like to import or import all projects.
- You can filter projects by name and select the namespace
- each project will be imported for.
+If the project import completes but LFS objects can't be downloaded or cloned, you may be using a
+password or personal access token containing special characters. For more information, see
+[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/337769).
-## Automate group and project import **(PREMIUM)**
+## Related topics
For information on automating user, group, and project import API calls, see
[Automate group and project import](index.md#automate-group-and-project-import).
-
-## Troubleshooting
-
-If the GUI-based import tool does not work, you can try to:
-
-- Use the [GitLab Import API](../../../api/import.md#import-repository-from-bitbucket-server) Bitbucket server endpoint.
-- Set up [Repository Mirroring](../repository/mirror/index.md), which provides verbose error output.
-
-See the [troubleshooting](bitbucket.md#troubleshooting) section for [Bitbucket](bitbucket.md).
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index d4cca723333..9f1c049045c 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -26,7 +26,7 @@ The following aspects of a project are imported:
- Regular issue and pull request comments
- [Git Large File Storage (LFS) Objects](../../../topics/git/lfs/index.md)
- Pull request comments replies in discussions ([GitLab.com & 14.5+](https://gitlab.com/gitlab-org/gitlab/-/issues/336596))
-- Diff Notes suggestions ([GitLab.com & 14.7+](https://gitlab.com/gitlab-org/gitlab/-/issues/340624)) [with a flag](../../../administration/feature_flags.md) named `github_importer_use_diff_note_with_suggestions`. Enabled by default.
+- Diff Notes suggestions ([GitLab.com & 14.7+](https://gitlab.com/gitlab-org/gitlab/-/issues/340624))
References to pull requests and issues are preserved (GitLab.com & 8.7+), and
each imported repository maintains visibility level unless that [visibility
@@ -181,8 +181,7 @@ Mirroring does not sync any new or updated pull requests from your GitHub projec
## Improve the speed of imports on self-managed instances
-NOTE:
-An administrator role on the GitLab server is required for this process.
+Administrator access on the GitLab server is required for this process.
For large projects it may take a while to import all data. To reduce the time necessary, you can increase the number of
Sidekiq workers that process the following queues:
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 001f0d56cc5..41ef15108ec 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -50,7 +50,7 @@ information, see the prerequisites and important notes in these sections:
NOTE:
When migrating to GitLab.com, you must create users manually unless [SCIM](../../../user/group/saml_sso/scim_setup.md)
will be used. Creating users with the API is limited to self-managed instances as it requires
-the Administrator role.
+administrator access.
To migrate all data from self-managed to GitLab.com, you can leverage the [API](../../../api/index.md).
Migrate the assets in this order:
diff --git a/doc/user/project/import/jira.md b/doc/user/project/import/jira.md
index c6992422733..5f7475eac36 100644
--- a/doc/user/project/import/jira.md
+++ b/doc/user/project/import/jira.md
@@ -40,9 +40,8 @@ iterations of the GitLab Jira importer.
### Permissions
-In order to be able to import issues from a Jira project you need to have read access on Jira
-issues and a [Maintainer or higher](../../permissions.md#project-members-permissions) role in the
-GitLab project that you wish to import into.
+To be able to import issues from a Jira project you must have read access on Jira
+issues and at least the Maintainer role in the GitLab project that you wish to import into.
### Jira integration
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index 80f2d6d7e62..96b38b49960 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
The Phabricator task importer is in
-[beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta) and is
+[beta](../../../policy/alpha-beta-support.md#beta-features) and is
[**not** complete](https://gitlab.com/gitlab-org/gitlab/-/issues/284406). It imports
only an issue's title and description. The GitLab project created during the import
process contains only issues, and the associated repository is disabled.
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index bee097cdcbe..801c2520bda 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -105,7 +105,6 @@ Projects include the following [features](https://about.gitlab.com/features/):
- [License Compliance](../compliance/license_compliance/index.md): Approve and deny licenses for projects. **(ULTIMATE)**
- [Dependency List](../application_security/dependency_list/index.md): View project dependencies. **(ULTIMATE)**
- [Requirements](requirements/index.md): Create criteria to check your products against. **(ULTIMATE)**
-- [Static Site Editor](static_site_editor/index.md): Edit content on static websites without prior knowledge of the codebase or Git commands.
- [Code Intelligence](code_intelligence.md): Navigate code.
## Project integrations
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 38de8d9f1af..bf343078634 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -46,6 +46,7 @@ integration in GitLab.
1. Select **Atlassian Bamboo**.
1. Ensure the **Active** checkbox is selected.
1. Enter the base URL of your Bamboo server. For example, `https://bamboo.example.com`.
+1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](overview.md#ssl-verification).
1. Enter the [build key](#identify-the-bamboo-build-plan-build-key) from your Bamboo
build plan.
1. If necessary, enter a username and password for a Bamboo user that has
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index ac6e18e8e6a..9764c4d44a0 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
-the [Maintainer role](../../permissions.md) on the project.
+the Maintainer role on the project.
## Integrations
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index 1ff558b569b..b317e65bdf2 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -67,7 +67,7 @@ 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 role](../../permissions.md).
+ GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. In the left menu, select **Settings > Integrations**, then select
**Mattermost slash commands**.
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index 5b83df9b22e..8ecc16050be 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -82,6 +82,15 @@ instance configuration or provide custom settings.
Read more about [Project integration management](../../admin_area/settings/project_integration_management.md).
+## SSL verification
+
+By default, the SSL certificate for outgoing HTTP requests is verified based on
+an internal list of Certificate Authorities. This means the certificate cannot
+be self-signed.
+
+You can turn off SSL verification in the configuration settings for [webhooks](webhooks.md#configure-a-webhook)
+and some integrations.
+
## 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. Learn more about [troubleshooting service hooks](webhooks.md#troubleshoot-webhooks).
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index de7ac6782d6..760b5030416 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/cloudwatch.md b/doc/user/project/integrations/prometheus_library/cloudwatch.md
index a07abf26fba..e8d611af30d 100644
--- a/doc/user/project/integrations/prometheus_library/cloudwatch.md
+++ b/doc/user/project/integrations/prometheus_library/cloudwatch.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md
index 97f69d65412..76d13d5487c 100644
--- a/doc/user/project/integrations/prometheus_library/haproxy.md
+++ b/doc/user/project/integrations/prometheus_library/haproxy.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index a5fc398e558..9bdd4945f5d 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 26d006adeb9..33a06958e0c 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index ad89543e9a6..ecf75d7b17a 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 03bf9258659..e123000e0c5 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
index 89c174f8fb9..fda7744e847 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Monitor
+group: Respond
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/user/project/integrations/webex_teams.md b/doc/user/project/integrations/webex_teams.md
index de152aabde5..dd4cdb632e6 100644
--- a/doc/user/project/integrations/webex_teams.md
+++ b/doc/user/project/integrations/webex_teams.md
@@ -13,7 +13,7 @@ You can configure GitLab to send notifications to a Webex Teams space:
## Create a webhook for the space
-1. Go to the [Incoming Webhooks app page](https://apphub.webex.com/applications/incoming-webhooks-cisco-systems-38054).
+1. Go to the [Incoming Webhooks app page](https://apphub.webex.com/applications/incoming-webhooks-cisco-systems-38054-23307).
1. Select **Connect** and log in to Webex Teams, if required.
1. Enter a name for the webhook and select the space to receive the notifications.
1. Select **ADD**.
diff --git a/doc/user/project/integrations/webhook_events.md b/doc/user/project/integrations/webhook_events.md
index ab70a2d43f4..9d8b98edba1 100644
--- a/doc/user/project/integrations/webhook_events.md
+++ b/doc/user/project/integrations/webhook_events.md
@@ -773,6 +773,7 @@ Merge request events are triggered when:
- A new merge request is created.
- An existing merge request is updated, approved, unapproved, merged, or closed.
- A commit is added in the source branch.
+- All threads are resolved on the merge request.
The available values for `object_attributes.action` in the payload are:
@@ -838,6 +839,7 @@ Payload example:
"updated_at": "2013-12-03T17:23:34Z",
"milestone_id": null,
"state": "opened",
+ "blocking_discussions_resolved": true,
"merge_status": "unchecked",
"target_project_id": 14,
"iid": 1,
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 8bc2b51276a..ace5783c852 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -57,7 +57,7 @@ You can configure a webhook for a group or a project.
The URL must be percent-encoded if it contains one or more special characters.
1. In **Secret token**, enter the [secret token](#validate-payloads-by-using-a-secret-token) to validate payloads.
1. In the **Trigger** section, select the [events](webhook_events.md) to trigger the webhook.
-1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](#verify-an-ssl-certificate).
+1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](overview.md#ssl-verification).
1. Select **Add webhook**.
## Test a webhook
@@ -123,15 +123,6 @@ The token is sent with the hook request in the
`X-Gitlab-Token` HTTP header. Your webhook endpoint can check the token to verify
that the request is legitimate.
-## Verify an SSL certificate
-
-By default, the SSL certificate of the webhook endpoint is verified based on
-an internal list of Certificate Authorities. This means the certificate cannot
-be self-signed.
-
-You can turn off SSL verification in the [webhook settings](#configure-a-webhook)
-in your GitLab projects.
-
## Filter push events by branch
Push events can be filtered by branch using a branch name or wildcard pattern
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 47a2d215024..71440298d85 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -194,7 +194,7 @@ card includes:
## Permissions
-Users with the [Reporter and higher roles](../permissions.md) can use all the functionality of the
+Users with at least the Reporter role can use all the functionality of the
issue board feature to create or delete lists. They can also drag issues from one list to another.
## Ordering issues in a list
@@ -402,7 +402,7 @@ To set a WIP limit for a list:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) in GitLab 12.8.
> - [View blocking issues when hovering over blocked icon](https://gitlab.com/gitlab-org/gitlab/-/issues/210452) in GitLab 13.10.
-If an issue is blocked by another issue, an icon appears next to its title to indicate its blocked
+If an issue is [blocked by another issue](issues/related_issues.md#blocking-issues), an icon appears next to its title to indicate its blocked
status.
When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
@@ -496,6 +496,9 @@ The steps depend on the scope of the list:
### Filter issues
+> - Filtering by iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6.
+> - Filtering by issue type [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268152) in GitLab 14.6.
+
You can use the filters on top of your issue board to show only
the results you want. It's similar to the filtering used in the [issue tracker](issues/index.md).
@@ -504,11 +507,12 @@ You can filter by the following:
- Assignee
- Author
- Epic
-- Iteration ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)
+- Iteration
- Label
- Milestone
- My Reaction
- Release
+- Type (issue/incident)
- Weight
#### Filtering issues in a group board
@@ -565,7 +569,7 @@ You can move issues and lists by dragging them.
Prerequisites:
-- You must have at least the Reporter [role](../permissions.md#project-members-permissions) for a project in GitLab.
+- You must have at least the Reporter role for a project in GitLab.
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).
diff --git a/doc/user/project/issues/associate_zoom_meeting.md b/doc/user/project/issues/associate_zoom_meeting.md
index aba8c45699c..41de91d9bd7 100644
--- a/doc/user/project/issues/associate_zoom_meeting.md
+++ b/doc/user/project/issues/associate_zoom_meeting.md
@@ -25,7 +25,7 @@ In an issue, leave a comment using the `/zoom` quick action followed by a valid
/zoom https://zoom.us/j/123456789
```
-If the Zoom meeting URL is valid and you have at least the Reporter [role](../../permissions.md),
+If the Zoom meeting URL is valid and you have at least the Reporter role,
a system alert notifies you of its successful addition.
The issue's description is automatically edited to include the Zoom link, and a button
appears right under the issue's title.
@@ -44,5 +44,5 @@ Similarly to adding a Zoom meeting, you can remove it with a quick action:
/remove_zoom
```
-If you have at least the Reporter [role](../../permissions.md),
+If you have at least the Reporter role,
a system alert notifies you that the meeting URL was successfully removed.
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index e8c58f2feb9..15130523da6 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -11,19 +11,20 @@ Confidential issues are [issues](index.md) visible only to members of a project
Confidential issues can be used by open source projects and companies alike to
keep security vulnerabilities private or prevent surprises from leaking out.
-## Making an issue confidential
+## Make an issue confidential
-You can make an issue confidential during issue creation or by editing
-an existing one.
+You can make an issue confidential when you create or edit an issue.
When you create a new issue, a checkbox right below the text area is available
to mark the issue as confidential. Check that box and hit the **Create issue**
button to create the issue. For existing issues, edit them, check the
confidential checkbox and hit **Save changes**.
+When you create a confidential issue in a project, the project becomes listed in the **Contributed projects** section in your [profile](../../profile/index.md). **Contributed projects** does not show information about the confidential issue; it only shows the project name.
+
![Creating a new confidential issue](img/confidential_issues_create.png)
-## Modifying issue confidentiality
+## Modify issue confidentiality
There are two ways to change an issue's confidentiality.
@@ -42,15 +43,15 @@ system note in the issue's comments.
![Confidential issues system notes](img/confidential_issues_system_notes.png)
-When an issue is made confidential, only users with at least the [Reporter role](../../permissions.md)
+When an issue is made confidential, only users with at least the Reporter role
for the project have access to the issue.
Users with Guest or [Minimal](../../permissions.md#users-with-minimal-access) roles can't access
the issue even if they were actively participating before the change.
-## Indications of a confidential issue
+## Confidential issue indicators
There are a few things that visually separate a confidential issue from a
-regular one. In the issues index page view, you can see the eye-slash (**(eye-slash)**) icon
+regular one. In the issues index page view, you can see the eye-slash (**{eye-slash}**) icon
next to the issues that are marked as confidential:
![Confidential issues index page](img/confidential_issues_index_page.png)
@@ -74,19 +75,18 @@ There is also an indicator on the sidebar denoting confidentiality.
## Merge requests for confidential issues
-Although you can make issues be confidential in public projects, you cannot make
-confidential merge requests. Learn how to create [merge requests for confidential issues](../merge_requests/confidential.md)
-that prevent leaks of private data.
+Although you can create confidential issues (and make existing issues confidential) in a public project, you cannot make confidential merge requests.
+Learn how to create [merge requests for confidential issues](../merge_requests/confidential.md) that prevent leaks of private data.
## Permissions and access to confidential issues
There are two kinds of level access for confidential issues. The general rule
is that confidential issues are visible only to members of a project with at
-least the Reporter [role](../../permissions.md#project-members-permissions). However, a guest user can also create
+least the Reporter role. However, a guest user can also create
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 the [Maintainer role](../../permissions.md) and the Guest role
+For example, here's what a user with the Maintainer role and the Guest role
sees in the project's search results respectively.
| Maintainer role | Guest role |
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index a9fca4f2b75..947fbdcc2d1 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -61,29 +61,29 @@ fields if needed, and newlines to separate rows. The first row contains the
headers, which are listed in the following table along with a description of
the values:
-| Column | Description |
-|-------------------|-------------|
-| Issue ID | Issue `iid` |
-| URL | A link to the issue on GitLab |
-| Title | Issue `title` |
-| State | `Open` or `Closed` |
-| Description | Issue `description` |
-| Author | Full name of the issue author |
-| Author Username | Username of the author, with the `@` symbol omitted |
-| Assignee | Full name of the issue assignee |
-| Assignee Username | Username of the author, with the `@` symbol omitted |
-| Confidential | `Yes` or `No` |
-| Locked | `Yes` or `No` |
-| Due Date | Formatted as `YYYY-MM-DD` |
-| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
-| Updated At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
-| Milestone | Title of the issue milestone |
-| Weight | Issue weight |
-| Labels | Title of any labels joined with a `,` |
-| Time Estimate | [Time estimate](../time_tracking.md#estimates) in seconds |
-| Time Spent | [Time spent](../time_tracking.md#time-spent) in seconds |
-| Epic ID | ID of the parent epic **(ULTIMATE)**, introduced in 12.7 |
-| Epic Title | Title of the parent epic **(ULTIMATE)**, introduced in 12.7 |
+| Column | Description |
+|------------------------------------------|-----------------------------------------------------------|
+| Issue ID | Issue `iid` |
+| URL | A link to the issue on GitLab |
+| Title | Issue `title` |
+| State | `Open` or `Closed` |
+| Description | Issue `description` |
+| Author | Full name of the issue author |
+| Author Username | Username of the author, with the `@` symbol omitted |
+| Assignee | Full name of the issue assignee |
+| Assignee Username | Username of the author, with the `@` symbol omitted |
+| Confidential | `Yes` or `No` |
+| Locked | `Yes` or `No` |
+| Due Date | Formatted as `YYYY-MM-DD` |
+| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
+| Updated At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
+| Milestone | Title of the issue milestone |
+| Weight | Issue weight |
+| Labels | Title of any labels joined with a `,` |
+| Time Estimate | [Time estimate](../time_tracking.md#estimates) in seconds |
+| Time Spent | [Time spent](../time_tracking.md#time-spent) in seconds |
+| [Epic](../../group/epics/index.md) ID | ID of the parent epic, introduced in 12.7 |
+| [Epic](../../group/epics/index.md) Title | Title of the parent epic, introduced in 12.7 |
## Limitations
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 69dc0cbafd8..e4b8efd27ed 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -14,9 +14,7 @@ retain columns such as labels and milestones, consider the [Move Issue feature](
The user uploading the CSV file is set as the author of the imported issues.
-NOTE:
-A permission level of [Developer](../../permissions.md), or higher, is required
-to import issues.
+You must have at least the Developer role for a project to import issues.
## Prepare for the import
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index ecf35fc4dcf..e7bb5ad4eeb 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Design Management **(FREE)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in GitLab Premium 12.2.
-> - Support for SVGs [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12771) in GitLab Premium 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in GitLab 12.2.
+> - Support for SVGs [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12771) in GitLab 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
Design Management allows you to upload design assets (including wireframes and mockups)
to GitLab issues and keep them stored in a single place, accessed by the Design
@@ -84,10 +84,10 @@ You can find to the **Design Management** section in the issue description:
## Adding designs
-> - Drag and drop uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.9.
-> - New version creation on upload [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.9.
+> - Drag and drop uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab 12.9.
+> - New version creation on upload [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab 12.9.
> - Copy and paste uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202634) in GitLab 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
To upload Design images, drag files from your computer and drop them in the Design Management section,
or select **click to upload** to select images from your file browser:
@@ -142,9 +142,9 @@ to help summarize changes between versions.
### Exploring designs by zooming
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in GitLab Premium 12.7.
-> - Drag to move a zoomed image [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) in GitLab 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in GitLab 12.7.
+> - Ability to drag a zoomed image to move it [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) in GitLab 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
Designs can be explored in greater detail by zooming in and out of the image.
Control the amount of zoom with the `+` and `-` buttons at the bottom of the image.
@@ -155,8 +155,8 @@ While zoomed in, you can drag the image to move around it.
## Deleting designs
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in GitLab Premium 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in GitLab 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
There are two ways to delete designs: manually delete them
individually, or select a few of them to delete at once,
@@ -190,8 +190,8 @@ You can change the order of designs by dragging them to a new position.
## Starting discussions on designs
-> - Adjusting a pin's position [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - Adjusting a pin's position [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) adjusting a pin's position in GitLab 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
When a design is uploaded, you can start a discussion by selecting
the image on the exact location you would like the discussion to be focused on.
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 2c20ccdcee0..2630052d806 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Due dates **(FREE)**
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 the Reporter [role](../../permissions.md)
+shipped on time. Users need at least the Reporter role
to be able to edit the due date. All users with permission to view
the issue can view the due date.
diff --git a/doc/user/project/issues/issue_weight.md b/doc/user/project/issues/issue_weight.md
index 8f17f399cb0..756fe9699f1 100644
--- a/doc/user/project/issues/issue_weight.md
+++ b/doc/user/project/issues/issue_weight.md
@@ -15,10 +15,8 @@ value, or complexity a given issue has or costs.
You can set the weight of an issue during its creation, by changing the
value in the dropdown menu. You can set it to a non-negative integer
-value from 0, 1, 2, and so on. (The database stores a 4-byte value, so the
-upper bound is essentially limitless.)
-You can remove weight from an issue
-as well.
+value from 0, 1, 2, and so on.
+You can remove weight from an issue as well.
This value appears on the right sidebar of an individual issue, as well as
in the issues page next to a weight icon (**{weight}**).
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index d120df82dbf..155d6260a5c 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -29,7 +29,7 @@ You can create an issue in many ways in GitLab:
Prerequisites:
-- You must have at least the [Guest role](../../permissions.md) for the project.
+- You must have at least the Guest role for the project.
To create an issue:
@@ -52,7 +52,7 @@ to the projects in the group.
Prerequisites:
-- You must have at least the [Guest role](../../permissions.md) for the project in the group.
+- You must have at least the Guest role for the project in the group.
To create an issue from a group:
@@ -78,7 +78,7 @@ You can create a new issue from an existing one. The two issues can then be mark
Prerequisites:
-- You must have at least the [Guest role](../../permissions.md) for the project.
+- You must have at least the Guest role for the project.
To create an issue from another issue:
@@ -98,7 +98,7 @@ You can create a new issue from an [issue board](../issue_board.md).
Prerequisites:
-- You must have at least the [Guest role](../../permissions.md) for the project.
+- You must have at least the Guest role for the project.
To create an issue from a project issue board:
@@ -133,7 +133,7 @@ Prerequisites:
- Your GitLab instance must have [incoming email](../../../administration/incoming_email.md)
configured.
- There must be at least one issue in the issue list.
-- You must have at least the [Guest role](../../permissions.md) for the project.
+- You must have at least the Guest role for the project.
To email an issue to a project:
@@ -224,7 +224,7 @@ You can edit an issue's title and description.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project, be the author of the issue, or be assigned to the issue.
To edit an issue:
@@ -242,7 +242,7 @@ You can edit multiple issues at a time when you're in a project.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project.
To edit multiple issues at the same time:
@@ -275,7 +275,7 @@ You can edit multiple issues across multiple projects when you're in a group.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for a group.
+- You must have at least the Reporter role for a group.
To edit multiple issues at the same time:
@@ -300,9 +300,11 @@ When you move an issue, it's closed and copied to the target project.
The original issue is not deleted. A system note, which indicates
where it came from and went to, is added to both issues.
+Be careful when moving an issue to a project with different access rules. Before moving the issue, make sure it does not contain sensitive data.
+
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project.
To move an issue:
@@ -317,7 +319,7 @@ You can move all open issues from one project to another.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have access to the Rails console of the GitLab instance.
To do it:
@@ -351,7 +353,7 @@ The issue is marked as closed but is not deleted.
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project, be the author of the issue, or be assigned to the issue.
To close an issue, you can do the following:
@@ -364,7 +366,7 @@ To close an issue, you can do the following:
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project, be the author of the issue, or be assigned to the issue.
To reopen a closed issue, at the top of the issue, select **Reopen issue**.
A reopened issue is no different from any other open issue.
@@ -440,7 +442,7 @@ in the [project's settings](../settings/index.md).
Prerequisites:
-- You must have at least the [Maintainer role](../../permissions.md) for the project.
+- You must have at least the Maintainer role for the project.
To disable automatic issue closing:
@@ -466,7 +468,7 @@ Merge requests in other projects can still close another project's issues.
Prerequisites:
-- You must have the [administrator access level](../../../administration/index.md) for your GitLab instance.
+- You must have [administrator access](../../../administration/index.md) to your GitLab instance.
To change the default issue closing pattern, edit the
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
@@ -476,7 +478,7 @@ of your installation.
Prerequisites:
-- You must be the issue author or have at least the [Reporter role](../../permissions.md) for the project.
+- You must be the issue author or have at least the Reporter role for the project, be the author of the issue, or be assigned to the issue.
To change issue type:
@@ -494,7 +496,7 @@ To change issue type:
Prerequisites:
-- You must have the [Owner role](../../permissions.md) for a project.
+- You must have the Owner role for a project.
To delete an issue:
@@ -508,9 +510,9 @@ Alternatively:
## Promote an issue to an epic **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in GitLab Ultimate 11.6.
-> - Moved to GitLab Premium in 12.8.
-> - Promoting issues to epics via the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233974) in GitLab Premium 13.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in GitLab 11.6.
+> - Moved from GitLab Ultimate to GitLab Premium in 12.8.
+> - Promoting issues to epics via the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233974) in GitLab 13.6.
You can promote an issue to an [epic](../../group/epics/index.md) in the immediate parent group.
@@ -622,7 +624,7 @@ This status marks issues as progressing as planned or needing attention to keep
Prerequisites:
-- You must have at least the [Reporter role](../../permissions.md) for the project.
+- You must have at least the Reporter role for the project.
To edit health status of an issue:
diff --git a/doc/user/project/issues/multiple_assignees_for_issues.md b/doc/user/project/issues/multiple_assignees_for_issues.md
index 98e940b6b51..f957d701a3b 100644
--- a/doc/user/project/issues/multiple_assignees_for_issues.md
+++ b/doc/user/project/issues/multiple_assignees_for_issues.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Multiple Assignees for Issues **(PREMIUM)**
-> - Moved to GitLab Premium in 13.9.
+> Moved to GitLab Premium in 13.9.
In large teams, where there is shared ownership of an issue, it can be difficult
to track who is working on it, who already completed their contributions, who
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 8a2a104c54d..f83ebc5e8a8 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -6,10 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Linked issues **(FREE)**
-> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.4.
+> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) from GitLab Premium to GitLab Free in 13.4.
Linked issues are a bi-directional relationship between any two issues and appear in a block below
-the issue description. Issues can be across groups and projects.
+the issue description. You can link issues in different projects.
The relationship only shows up in the UI if the user can see both issues. When you try to close an
issue that has open blockers, a warning is displayed.
@@ -23,13 +23,18 @@ To manage linked issues through our API, visit the [issue links API documentatio
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/34239) to warn when attempting to close an issue that is blocked by others in GitLab 13.0.
> When you try to close an issue with open blockers, you see a warning that you can dismiss.
-1. Link one issue to another by selecting the add linked issue button (**{plus}**) in the
- **Linked issues** section of an issue.
+Prerequisites:
+- You must have at least the Reporter role for both projects.
+
+To link one issue to another:
+
+1. In the **Linked issues** section of an issue,
+ select the add linked issue button (**{plus}**).
1. Select the relationship between the two issues. Either:
- **relates to**
- - **blocks** **(PREMIUM)**
- - **is blocked by** **(PREMIUM)**
+ - **[blocks](#blocking-issues)**
+ - **[is blocked by](#blocking-issues)**
1. Input the issue number or paste in the full URL of the issue.
![Adding a related issue](img/related_issues_add_v12_8.png)
@@ -64,3 +69,10 @@ Due to the bi-directional relationship, the relationship no longer appears in ei
![Removing a related issue](img/related_issues_remove_v12_8.png)
Access our [permissions](../../permissions.md) page for more information.
+
+## Blocking issues **(PREMIUM)**
+
+When you [add a linked issue](#add-a-linked-issue), you can show that it **blocks** or
+**is blocked by** another issue.
+
+Issues that block other issues have an icon (**{issue-block}**) shown in the issue lists and [boards](../issue_board.md).
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index 0340f15c25c..329f65bfacd 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -27,7 +27,7 @@ The available sorting options can change based on the context of the list.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34247/) in GitLab 13.7.
When you sort by **Blocking**, the issue list changes to sort descending by the
-number of issues each issue is blocking.
+number of issues each issue is [blocking](related_issues.md#blocking-issues).
## Sorting by created date
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 2dc29f5d725..8be2ade3f2f 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -12,20 +12,30 @@ Each member gets a role, which determines what they can do in the project.
## Add users to a project
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
+> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
+
+FLAG:
+On self-managed GitLab, by default the modal window feature is available.
+To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md)
+named `invite_members_group_modal`.
+On GitLab.com, this feature is available.
+
Add users to a project so they become members and have permission
to perform actions.
Prerequisite:
-- You must have the [Maintainer or Owner role](../../permissions.md).
+- You must have the Maintainer or Owner role.
To add a user to a project:
-1. Go to your project and select **Project information > Members**.
-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. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
+1. Select **Invite members**.
+1. Enter an email address and select a [role](../../permissions.md).
+1. Optional. Select an **Access expiration date**.
+ On that date, the user can no longer access the project.
1. Select **Invite**.
If the user has a GitLab account, they are added to the members list.
@@ -40,6 +50,15 @@ using the email address the invitation was sent to.
## Add groups to a project
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
+> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
+
+FLAG:
+On self-managed GitLab, by default the modal window feature is available.
+To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md)
+named `invite_members_group_modal`.
+On GitLab.com, this feature is available.
+
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:
@@ -48,15 +67,16 @@ Each user's access is based on:
Prerequisite:
-- You must have the [Maintainer or Owner role](../../permissions.md).
+- You must have the Maintainer or Owner role.
To add groups to a project:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Project information > Members**.
-1. On the **Invite group** tab, under **Select a group to invite**, choose a group.
-1. Select the highest max [role](../../permissions.md) for users in the group.
-1. Optional. Choose an expiration date. On that date, the user can no longer access the project.
+1. Select **Invite a group**.
+1. Select a group.
+1. Select the highest [role](../../permissions.md) for users in the group.
+1. Optional. Select an **Access expiration date**. On that date, the group can no longer access the project.
1. Select **Invite**.
The members of the group are not displayed on the **Members** tab.
@@ -72,7 +92,7 @@ retain the same permissions as the project you import them from.
Prerequisite:
-- You must have the [Maintainer or Owner role](../../permissions.md).
+- You must have the Maintainer or Owner role.
To import users:
@@ -111,7 +131,7 @@ group itself.
Prerequisites:
-- You must have the [Owner role](../../permissions.md).
+- You must have the Owner role.
- Optional. Unassign the member from all issues and merge requests that
are assigned to them.
@@ -203,44 +223,3 @@ Prerequisite:
## 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
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
-> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - Enabled on GitLab.com.
-> - Recommended for production use.
-> - Replaces the existing form with buttons to open a modal window.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-modal-window).
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-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. On the top bar, select **Menu > Projects** and find your project.
-1. On the left sidebar, select **Project information > 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)**
-
-The modal window for adding a member is under development and is 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(:invite_members_group_modal)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:invite_members_group_modal)
-```
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
index e67af8dc936..612f499bb65 100644
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ b/doc/user/project/merge_requests/accessibility_testing.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Accessibility testing **(FREE)**
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index b10d6597c1e..5826ebcab49 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -50,7 +50,7 @@ You can push directly to the branch of the forked repository if:
- The author of the merge request has enabled contributions from upstream
members.
-- You have at least the [Developer role](../../permissions.md) in the
+- You have at least the Developer role in the
upstream project.
In the following example:
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index dddd3925dbb..e940426dc67 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -8,7 +8,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/appro
# Merge request approvals **(FREE)**
-> Redesign [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8 and [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/10685) in 12.0.
+> Redesign [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in GitLab 11.8 and [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/10685) in 12.0.
You can configure your merge requests so that they must be approved before
they can be merged. While [GitLab Free](https://about.gitlab.com/pricing/) allows
@@ -89,7 +89,7 @@ a merge request from merging without approval.
## Required approvals **(PREMIUM)**
-> Moved to [GitLab Premium](https://about.gitlab.com/pricing/) in 13.9.
+> Moved to GitLab Premium in 13.9.
Required approvals enforce code reviews by the number and type of users you specify.
Without the approvals, the work cannot merge. Required approvals enable multiple use cases:
@@ -103,7 +103,7 @@ Without the approvals, the work cannot merge. Required approvals enable multiple
to determine who should review the work.
- Require an [approval before merging code that causes test coverage to decline](../../../../ci/pipelines/settings.md#coverage-check-approval-rule)
- [Require approval from a security team](../../../application_security/index.md#security-approvals-in-merge-requests)
- before merging code that could introduce a vulnerability. **(ULTIMATE)**
+ before merging code that could introduce a vulnerability.
## Related topics
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index 129010010e7..fa447ea35af 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -76,9 +76,9 @@ To edit a merge request approval rule:
select **{remove}** **Remove**.
1. Select **Update approval rule**.
-## Add multiple approval rules **(PREMIUM)**
+## Add multiple approval rules
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in GitLab Premium 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in GitLab 11.10.
In GitLab Premium and higher tiers, you can enforce multiple approval rules on a
merge request, and multiple default approval rules for a project. If your tier
@@ -127,8 +127,8 @@ users were not explicitly listed in the approval rules.
### Group approvers
You can add a group of users as approvers, but those users count as approvers only if
-they have direct membership to the group. In the future, group approvers may be
-restricted to only groups [with share access to the project](https://gitlab.com/gitlab-org/gitlab/-/issues/2048).
+they have direct membership to the group. Group approvers are
+restricted to only groups [with share access to the project](../../members/share_project_with_groups.md).
A user's membership in an approvers group affects their individual ability to
approve in these ways:
@@ -143,7 +143,7 @@ approve in these ways:
[**Prevent committers approval**](settings.md#prevent-approvals-by-users-who-add-commits)
project setting.
-### Code owners as eligible approvers **(PREMIUM)**
+### Code owners as eligible approvers
> Moved to GitLab Premium in 13.9.
@@ -158,14 +158,14 @@ become eligible approvers in the project. To enable this merge request approval
You can also
[require code owner approval](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch)
-for protected branches. **(PREMIUM)**
+for protected branches.
-## Merge request approval segregation of duties **(PREMIUM)**
+## Merge request approval segregation of duties
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
> - Moved to GitLab Premium in 13.9.
-You may have to grant users with the Reporter [role](../../../permissions.md#project-members-permissions)
+You may have to grant users with the Reporter role
permission to approve merge requests before they can merge to a protected branch.
Some users (like managers) may not need permission to push or merge code, but still need
oversight on proposed work. To enable approval permissions for these users without
@@ -202,7 +202,7 @@ on a merge request, you can either add or remove approvers:
Administrators can change the [merge request approvals settings](settings.md#prevent-editing-approval-rules-in-merge-requests)
to prevent users from overriding approval rules for merge requests.
-## Configure optional approval rules **(PREMIUM)**
+## Configure optional approval rules
Merge request approvals can be optional for projects where approvals are
appreciated, but not required. To make an approval rule optional:
@@ -211,9 +211,9 @@ appreciated, but not required. To make an approval rule optional:
- Use the [Merge requests approvals API](../../../../api/merge_request_approvals.md#update-merge-request-level-rule)
to set the `approvals_required` attribute to `0`.
-## Approvals for protected branches **(PREMIUM)**
+## Approvals for protected branches
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab Premium 12.8.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab 12.8.
Approval rules are often relevant only to specific branches, like your
[default branch](../../repository/branches/default.md). To configure an
@@ -229,3 +229,16 @@ approval rule for certain branches:
![Scoped to protected branch](img/scoped_to_protected_branch_v13_10.png)
1. To enable this configuration, read
[Code Owner's approvals for protected branches](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch).
+
+## Troubleshooting
+
+### Approval rule name can't be blank
+
+As a workaround for this validation error, you can delete the approval rule through
+the API.
+
+1. [GET a project-level rule](../../../../api/merge_request_approvals.md#get-a-single-project-level-rule).
+1. [DELETE the rule](../../../../api/merge_request_approvals.md#delete-project-level-rule).
+
+For more information about this validation error, read
+[issue 285129](https://gitlab.com/gitlab-org/gitlab/-/issues/285129).
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 4ae59a76a9a..37ecc1b8d06 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -16,7 +16,7 @@ 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 the [Maintainer role](../../permissions.md) and the regular developers
+The project maintainers get the Maintainer role and the regular developers
get the Developer role.
Maintainers mark the authoritative branches as 'Protected'.
@@ -25,7 +25,7 @@ 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 the [Maintainer role](../../permissions.md) can merge changes into a
+By default, only users with the Maintainer role can merge changes into a
protected branch.
**Advantages**
@@ -39,7 +39,7 @@ protected branch.
## Forking workflow
-With the forking workflow, maintainers get the [Maintainer role](../../permissions.md) and regular
+With the forking workflow, maintainers get the Maintainer role and regular
developers get the Reporter role on the authoritative repository, which prohibits
them from pushing any changes to it.
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index 6668e1736cf..9c7d9e2bf19 100644
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -1,13 +1,12 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Browser Performance Testing **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3507) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3507) in GitLab 10.3.
If your application offers a web interface and you're using
[GitLab CI/CD](../../../ci/index.md), you can quickly determine the rendering performance
diff --git a/doc/user/project/merge_requests/changes.md b/doc/user/project/merge_requests/changes.md
index d348c00bdc2..8796ea0635b 100644
--- a/doc/user/project/merge_requests/changes.md
+++ b/doc/user/project/merge_requests/changes.md
@@ -5,149 +5,151 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# Changes tab in merge requests **(FREE)**
+# Changes 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
-file is also known as a **diff**. By default, the diff view compares the file in the
-merge request branch and the file in the target branch.
+A [merge request](index.md) proposes a set of changes to files in a branch in your repository. These
+changes are shown as a _diff_ (difference) between the current state and the proposed
+changes.
-The diff view includes the following:
+By default, the diff view compares the versions of files in the merge request source branch
+to the files in the target branch, and shows only the parts of a file that have changed.
-- The file's name and path.
-- The number of lines added and deleted.
-- Buttons for the following options:
- - Toggle comments for this file; useful for inline reviews.
- - Edit the file in the merge request's branch.
- - Show full file, in case you want to look at the changes in context with the rest of the file.
- - View file at the current commit.
- - Preview the changes with [Review Apps](../../../ci/review_apps/index.md).
-- The changed lines, with the specific changes highlighted.
+![Example screenshot of a source code diff](img/mr-diff-example_v14_8.png)
-![Example screenshot of a source code diff](img/merge_request_diff_v12_2.png)
+## Show all changes in a merge request
-## Merge request diff file navigation
+To view the diff of changes included in a merge request:
-When reviewing changes in the **Changes** tab, the diff can be navigated using
-the file tree or file list. As you scroll through large diffs with many
-changes, you can quickly jump to any changed file using the file tree or file
-list.
+1. Go to your merge request.
+1. Below the merge request title, select **Changes**.
+1. If the merge request changes many files, you can jump directly to a specific file:
+ 1. Select **Show file browser** (**{file-tree}**) to display the file tree.
+ 1. Select the file you want to view.
+ 1. To hide the file browser, select **Show file browser** again.
-![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
+In [GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/232820) and later, files
+with many changes are collapsed to improve performance. GitLab displays the message:
+**Some changes are not shown**. To view the changes for that file, select **Expand file**.
-## Collapsed files in the Changes view
+## Show one file at a time
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232820) in GitLab 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) in GitLab 13.2.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229848) in GitLab 13.7.
-When you review changes in the **Changes** tab, files with a large number of changes are collapsed
-to improve performance. When files are collapsed, a warning appears at the top of the changes.
-Select **Expand file** on any file to view the changes for that file.
+For larger merge requests, you can review one file at a time. You can change this setting
+[temporarily in a merge request](#in-a-merge-request-show-only-one-file-at-a-time), or
+so it [applies to all merge requests](#in-all-merge-requests-show-only-one-file-at-a-time).
-## File-by-file diff navigation
+### In a merge request, show only one file at a time
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) in GitLab 13.2.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229848) in GitLab 13.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233898) in GitLab 13.7.
+
+To temporarily change your viewing preferences for a specific merge request:
+
+1. Go to your merge request, and below the merge request title, select **Changes**.
+1. Select **Preferences** (**{settings}**).
+1. Select or clear the **Show one file at a time** checkbox.
-For larger merge requests, consider reviewing one file at a time. To enable this feature:
+This change overrides your choice in your user preferences. It persists until you
+clear your browser's cookies or change this behavior again.
+
+### In all merge requests, show only one file at a time
+
+To view one file at a time for all of your merge requests:
1. In the top-right corner, select your avatar.
1. Select **Preferences**.
-1. Scroll to the **Behavior** section and select **Show one file at a time on merge request's Changes tab**.
+1. Scroll to the **Behavior** section and select the **Show one file at a time on merge request's Changes tab** checkbox.
1. Select **Save changes**.
-After you enable this setting, GitLab displays only one file at a time in the **Changes** tab when you review merge requests. You can select **Prev** and **Next** to view other changed files.
+After you enable this setting, GitLab displays only one file at a time when you review
+merge requests. To view other changed files, either:
+
+- Scroll to the end of the file and select either **Prev** or **Next**.
+- Select **Show file browser** (**{file-tree}**) and select another file to view.
+
+## Compare changes inline
+
+You can view the changes inline:
-![File-by-file diff navigation](img/file_by_file_v13_2.png)
+1. Go to your merge request, and below the title, select **Changes**.
+1. Select **Preferences** (**{settings}**).
+1. In the **Compare changes** area, select **Inline**.
-In [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/233898) and later, if you want to change
-this behavior, you can do so from your **User preferences** (as explained above) or directly in a
-merge request:
+The changes are displayed after the original text.
-1. Go to the merge request's **Changes** tab.
-1. Select the cog icon (**{settings}**) to reveal the merge request's settings dropdown.
-1. Select or clear the checkbox **Show one file at a time** to change the setting accordingly.
+![inline changes](img/changes-inline_v14_8.png)
-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.
+## Compare changes side-by-side
-## Incrementally expand merge request diffs
+Depending on the length of the changes in your merge request, you may find it
+easier to view the changes inline, or side-by-side:
-By default, the diff shows only the parts of a file which are changed.
-To view more unchanged lines above or below a change select the
-**Expand up** or **Expand down** icons. You can also select **Show unchanged lines**
-to expand the entire file.
+1. Go to your merge request, and below the title, select **Changes**.
+1. Select **Preferences** (**{settings}**).
+1. In the **Compare changes** area, select **Side-by-side**.
-![Incrementally expand merge request diffs](img/incrementally_expand_merge_request_diffs_v12_2.png)
+The changes are displayed across from one another.
-In GitLab [versions 13.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/205401), when viewing a
-merge request's **Changes** tab, if a certain file was only renamed, you can expand it to see the
-entire content by selecting **Show file contents**.
+![side-by-side changes](img/changes-sidebyside_v14_8.png)
-## Ignore whitespace changes in Merge Request diff view
+## Expand or collapse comments
+
+When reviewing code changes, you can hide inline comments:
+
+1. Go to your merge request, and below the title, select **Changes**.
+1. Scroll to the file that contains the comments you want to hide.
+1. Scroll to the line the comment is attached to, and select **Collapse** (**{collapse}**):
+ ![collapse a comment](img/collapse-comment_v14_8.png)
+
+To expand inline comments and show them again:
+
+1. Go to your merge request, and below the title, select **Changes**.
+1. Scroll to the file that contains the collapsed comments you want to show.
+1. Scroll to the line the comment is attached to, and select the user avatar:
+ ![expand a comment](img/expand-comment_v14_8.png)
+
+## Ignore whitespace changes
Whitespace changes can make it more difficult to see the substantive changes in
a merge request. You can choose to hide or show whitespace changes:
-1. Go to your merge request, and select the **Changes** tab.
-1. Above the list of changed files, select **(settings)** **Preferences** to
- display the preferences menu.
-1. Select or deselect **Show whitespace changes**:
+1. Go to your merge request, and below the title, select **Changes**.
+1. Before the list of changed files, select **Preferences** (**{settings}**).
+1. Select or clear the **Show whitespace changes** checkbox:
![MR diff](img/merge_request_diff_v14_2.png)
## Mark files as viewed
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.9 behind a feature flag, enabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.9 [with a flag](../../../administration/feature_flags.md) named `local_file_reviews`. Enabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/296674) in GitLab 14.3.
-When reviewing a merge request with many files multiple times, it may be useful to the reviewer
-to focus on new changes and ignore the files that they have already reviewed and don't want to
-see anymore unless they are changed again.
+When reviewing a merge request with many files multiple times, you can ignore files
+you've already reviewed. To hide files that haven't changed since your last review:
-To mark a file as viewed:
+1. Go to your merge request, and below the title, select **Changes**.
+1. In the file's header, select the **Viewed** checkbox.
-1. Go to the merge request's **Diffs** tab.
-1. On the right-top of the file, locate the **Viewed** checkbox.
-1. Select it to mark the file as viewed.
+Files marked as viewed are not shown to you again unless either:
-Once checked, the file remains marked for that reviewer unless there are newly introduced
-changes to its content or the checkbox is unchecked.
+- New changes are made to its content.
+- You clear the **Viewed** checkbox.
-## Show merge request conflicts in diff
+## Show merge request conflicts in diff **(FREE SELF)**
-> - [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)**
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232484) in GitLab 13.5 [with a flag](../../../administration/feature_flags.md) named `display_merge_conflicts_in_diff`. Disabled by default.
-This in-development feature might not be available for your use. There can be
-[risks when enabling features still in development](../../../administration/feature_flags.md#risks-when-enabling-features-still-in-development).
-Refer to this feature's version history for more details.
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../../administration/feature_flags.md)
+named `display_merge_conflicts_in_diff`. On GitLab.com, this feature is not available.
+The feature is not ready for production use.
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:
+conflicts on the merge request diff:
![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/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 30d463efa69..d735ce0ef91 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -53,7 +53,7 @@ See also the Code Climate list of [Supported Languages for Maintainability](http
## Code Quality in diff view **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267612) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.11, disabled by default behind the `codequality_mr_diff` [feature flag](../../../administration/feature_flags.md).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267612) in GitLab 13.11, disabled by default behind the `codequality_mr_diff` [feature flag](../../../administration/feature_flags.md).
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/284140) in GitLab 13.12.
> - [Disabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/2526) in GitLab 14.0 due to [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/334116).
> - [Inline annotation added](https://gitlab.com/gitlab-org/gitlab/-/issues/2526) and [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284140) in GitLab 14.1.
@@ -248,9 +248,9 @@ This can be done:
### Using with merge request pipelines
The configuration provided by the Code Quality template does not let the `code_quality` job
-run on [pipelines for merge requests](../../../ci/pipelines/merge_request_pipelines.md).
+run on [merge request pipelines](../../../ci/pipelines/merge_request_pipelines.md).
-If pipelines for merge requests is enabled, the `code_quality:rules` must be redefined.
+If merge request pipelines is enabled, the `code_quality:rules` must be redefined.
The template has these [`rules`](../../../ci/yaml/index.md#rules) for the `code quality` job:
@@ -379,7 +379,7 @@ at the beginning of the file.
## Code Quality reports **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21527) in GitLab Premium 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21527) in GitLab 12.9.
![Code Quality Report](img/code_quality_report_13_11.png)
@@ -392,7 +392,7 @@ After the Code Quality job completes:
[downloadable artifact](../../../ci/pipelines/job_artifacts.md#download-job-artifacts)
for the `code_quality` job.
- The full list of code quality violations generated by a pipeline is shown in the
- Code Quality tab of the Pipeline Details page. **(PREMIUM)**
+ Code Quality tab of the Pipeline Details page.
## Generate an HTML report
@@ -591,3 +591,22 @@ plugins:
If your merge requests do not show any code quality changes when using a custom tool,
ensure that the line property is an `integer`.
+
+### Code Quality CI job with Code Climate plugins enabled fails with error "engine <plugin_name> ran for 900 seconds and was killed"
+
+If you enabled any of the Code Climate plugins, and the Code Quality CI job fails with the error below,
+it's likely the job takes longer than the default timeout of 900 seconds.
+
+```shell
+error: (CC::CLI::Analyze::EngineFailure) engine pmd ran for 900 seconds and was killed
+Could not analyze code quality for the repository at /code
+```
+
+To work around this problem, set `TIMEOUT_SECONDS` to a higher value in your `.gitlab.-ci.yml` file.
+
+For example:
+
+```yaml
+variables:
+ TIMEOUT_SECONDS: 3600
+```
diff --git a/doc/user/project/merge_requests/commits.md b/doc/user/project/merge_requests/commits.md
index 3d3032bb193..0014c1ba994 100644
--- a/doc/user/project/merge_requests/commits.md
+++ b/doc/user/project/merge_requests/commits.md
@@ -29,21 +29,17 @@ To seamlessly navigate among commits in a merge request:
## View merge request commits in context
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29274) in GitLab 13.12.
-> - [Deployed behind a feature flag](../../feature_flags.md), enabled 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-viewing-merge-request-commits-in-context). **(FREE SELF)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29274) in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `context_commits`. Enabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.8.
WARNING:
-This feature is in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+This feature is in [beta](../../../policy/alpha-beta-support.md#beta-features)
and is [incomplete](https://gitlab.com/groups/gitlab-org/-/epics/1192).
-Previously merged commits can be added, but they can't be removed due to
-[this bug](https://gitlab.com/gitlab-org/gitlab/-/issues/325538).
-This in-development feature might not be available for your use. There can be
-[risks when enabling features still in development](../../../administration/feature_flags.md#risks-when-enabling-features-still-in-development).
-Refer to this feature's version history for more details.
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature,
+ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `context_commits`.
+On GitLab.com, this feature is available.
When reviewing a merge request, it helps to have more context about the changes
made. That includes unchanged lines in unchanged files, and previous commits
@@ -66,22 +62,3 @@ To view the changes done on those previously merged commits:
1. Scroll to **(file-tree)** **Compare** and select **previously merged commits**:
![Previously merged commits](img/previously_merged_commits_v14_1.png)
-
-### Enable or disable viewing merge request commits in context **(FREE SELF)**
-
-Viewing merge request commits in context 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(:context_commits)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:context_commits)
-```
diff --git a/doc/user/project/merge_requests/confidential.md b/doc/user/project/merge_requests/confidential.md
index 10c63421876..6900880417f 100644
--- a/doc/user/project/merge_requests/confidential.md
+++ b/doc/user/project/merge_requests/confidential.md
@@ -4,7 +4,7 @@ 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
---
-# Merge requests for confidential issues
+# Merge requests for confidential issues **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58583) in GitLab 12.1.
diff --git a/doc/user/project/merge_requests/drafts.md b/doc/user/project/merge_requests/drafts.md
index a91679ffd63..637b682d603 100644
--- a/doc/user/project/merge_requests/drafts.md
+++ b/doc/user/project/merge_requests/drafts.md
@@ -17,7 +17,8 @@ the **Merge** button until you remove the **Draft** flag:
## Mark merge requests as drafts
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32692) in GitLab 13.2, Work-In-Progress (WIP) merge requests were renamed to **Draft**. Support for using **WIP** is scheduled for removal in GitLab 14.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32692) in GitLab 13.2, Work-In-Progress (WIP) merge requests were renamed to **Draft**.
+> - [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/228685) all support for using **WIP** in GitLab 14.8.
> - **Mark as draft** and **Mark as ready** buttons [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227421) in GitLab 13.5.
There are several ways to flag a merge request as a draft:
@@ -35,16 +36,12 @@ There are several ways to flag a merge request as a draft:
is not a toggle, and adding this text again in a later commit doesn't mark the
merge request as ready.
-WARNING:
-Adding `WIP:` to the start of the merge request's title still marks a merge request
-as a draft. This feature is scheduled for removal in GitLab 14.0. Use `Draft:` instead.
-
## Mark merge requests as ready
When a merge request is ready to be merged, you can remove the `Draft` flag in several ways:
- **Viewing a merge request**: In the top right corner of the merge request, click **Mark as ready**.
- Users with [Developer or greater permissions](../../permissions.md)
+ Users with at least the Developer role
can also scroll to the bottom of the merge request description and click **Mark as ready**:
![Mark as ready](img/draft_blocked_merge_button_v13_10.png)
@@ -79,11 +76,11 @@ draft merge requests:
## Pipelines for drafts
-When the [pipelines for merged results](../../../ci/pipelines/pipelines_for_merged_results.md)
+When the [merged results pipelines](../../../ci/pipelines/merged_results_pipelines.md)
feature is enabled, draft merge requests run
[merge request pipelines](../../../ci/pipelines/merge_request_pipelines.md) only.
-To run pipelines for merged results, you must
+To run merged results pipelines, you must
[mark the merge request as ready](#mark-merge-requests-as-ready).
<!-- ## Troubleshooting
diff --git a/doc/user/project/merge_requests/fail_fast_testing.md b/doc/user/project/merge_requests/fail_fast_testing.md
index 3cb50195f5a..355661516a7 100644
--- a/doc/user/project/merge_requests/fail_fast_testing.md
+++ b/doc/user/project/merge_requests/fail_fast_testing.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Fail Fast Testing **(PREMIUM)**
@@ -42,8 +41,8 @@ This template requires:
- A project built in Rails that uses RSpec for testing.
- CI/CD configured to:
- Use a Docker image with Ruby available.
- - Use [Pipelines for merge requests](../../../ci/pipelines/merge_request_pipelines.md#prerequisites)
-- [Pipelines for Merged Results](../../../ci/pipelines/pipelines_for_merged_results.md#enable-pipelines-for-merged-results)
+ - Use [Merge request pipelines](../../../ci/pipelines/merge_request_pipelines.md#prerequisites)
+- [Merged results pipelines](../../../ci/pipelines/merged_results_pipelines.md#enable-merged-results-pipelines)
enabled in the project settings.
- A Docker image with Ruby available. The template uses `image: ruby:2.6` by default, but you [can override](../../../ci/yaml/includes.md#override-included-configuration-values) this.
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index ec509f58723..8699a42dd5d 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -56,7 +56,7 @@ request's page at the top-right side, or by using
- [Assign](#assignee) the merge request to a colleague for review. With [multiple assignees](#multiple-assignees), you can assign it to more than one person at a time.
- Set a [milestone](../milestones/index.md) to track time-sensitive changes.
- Add [labels](../labels.md) to help contextualize and filter your merge requests over time.
-- [Require approval](approvals/index.md#required-approvals) from your team. **(PREMIUM)**
+- [Require approval](approvals/index.md#required-approvals) from your team.
- [Close issues automatically](#merge-requests-to-close-issues) when they are merged.
- Enable the [delete source branch when merge request is accepted](#deleting-the-source-branch) option to keep your repository clean.
- Enable the [squash commits when merge request is accepted](squash_and_merge.md) option to combine all the commits into one before merging, thus keep a clean commit history in your repository.
@@ -66,7 +66,7 @@ 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).
-- Add [merge request dependencies](merge_request_dependencies.md) to restrict it to be merged only when other merge requests have been merged. **(PREMIUM)**
+- Add [merge request dependencies](merge_request_dependencies.md) to restrict it to be merged only when other merge requests have been merged.
- 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).
@@ -162,7 +162,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 the [Maintainer role](../../permissions.md)
+It is only visible to users with the Maintainer role
in the source project.
If the user viewing the merge request does not have the correct
diff --git a/doc/user/project/merge_requests/img/changes-inline_v14_8.png b/doc/user/project/merge_requests/img/changes-inline_v14_8.png
new file mode 100644
index 00000000000..f3b6515283c
--- /dev/null
+++ b/doc/user/project/merge_requests/img/changes-inline_v14_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/changes-sidebyside_v14_8.png b/doc/user/project/merge_requests/img/changes-sidebyside_v14_8.png
new file mode 100644
index 00000000000..981274dbb86
--- /dev/null
+++ b/doc/user/project/merge_requests/img/changes-sidebyside_v14_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/collapse-comment_v14_8.png b/doc/user/project/merge_requests/img/collapse-comment_v14_8.png
new file mode 100644
index 00000000000..93a802454f2
--- /dev/null
+++ b/doc/user/project/merge_requests/img/collapse-comment_v14_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/expand-comment_v14_8.png b/doc/user/project/merge_requests/img/expand-comment_v14_8.png
new file mode 100644
index 00000000000..a800eab83e9
--- /dev/null
+++ b/doc/user/project/merge_requests/img/expand-comment_v14_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/file_by_file_v13_2.png b/doc/user/project/merge_requests/img/file_by_file_v13_2.png
deleted file mode 100644
index e3114ebabad..00000000000
--- a/doc/user/project/merge_requests/img/file_by_file_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/incrementally_expand_merge_request_diffs_v12_2.png b/doc/user/project/merge_requests/img/incrementally_expand_merge_request_diffs_v12_2.png
deleted file mode 100644
index e3a2ff7960c..00000000000
--- a/doc/user/project/merge_requests/img/incrementally_expand_merge_request_diffs_v12_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
deleted file mode 100644
index 1cdac5ef573..00000000000
--- a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/mr-diff-example_v14_8.png b/doc/user/project/merge_requests/img/mr-diff-example_v14_8.png
new file mode 100644
index 00000000000..1984defde9a
--- /dev/null
+++ b/doc/user/project/merge_requests/img/mr-diff-example_v14_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 8222d696853..9872bd2e936 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -94,7 +94,7 @@ 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).
+1. Sign in to GitLab as a user with the project Owner role.
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**.
@@ -137,3 +137,4 @@ For a web developer writing a webpage for your company's website:
- [Suggest code changes](reviews/suggestions.md)
- [Commits](commits.md)
- [CI/CD pipelines](../../../ci/index.md)
+- [Push options](../push_options.md) for merge requests
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 40859c6b572..cc4ad186771 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -1,13 +1,12 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Load Performance Testing **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in GitLab 13.2.
With Load Performance Testing, you can test the impact of any pending code changes
to your application's backend in [GitLab CI/CD](../../../ci/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 aace1f58c62..6bfef6ab134 100644
--- a/doc/user/project/merge_requests/merge_request_dependencies.md
+++ b/doc/user/project/merge_requests/merge_request_dependencies.md
@@ -7,9 +7,9 @@ type: reference, concepts
# Merge request dependencies **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9688) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
-> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17291) from "Cross-project dependencies" to "Merge request dependencies" in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4.
-> - Intra-project MR dependencies were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16799) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9688) in GitLab 12.2.
+> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17291) from "Cross-project dependencies" to "Merge request dependencies" in GitLab 12.4.
+> - Intra-project MR dependencies were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16799) in GitLab 12.4.
Merge request dependencies allows a required order of merging
between merge requests to be expressed. If a merge request "depends on" another,
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index c34a8116625..280ae07b401 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -23,8 +23,8 @@ review merge requests in Visual Studio Code.
## Review a merge request
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in GitLab Premium 11.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) to GitLab Free in 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in GitLab 11.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) from GitLab Premium to GitLab Free in 13.1.
When you review a merge request, you can create comments that are visible only
to you. When you're ready, you can publish them together in a single action.
@@ -160,7 +160,7 @@ Multiline comments display the comment's line numbers above the body of the comm
## Bulk edit merge requests at the project level
-Users with permission level of [Developer or higher](../../../permissions.md) can manage merge requests.
+Users with at least the Developer role can manage merge requests.
When bulk-editing merge requests in a project, you can edit the following attributes:
@@ -179,11 +179,11 @@ To update multiple project merge requests at the same time:
1. Select the appropriate fields and their values from the sidebar.
1. Click **Update all**.
-## Bulk edit merge requests at the group level
+## Bulk edit merge requests at the group level **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12719) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12719) in GitLab 12.2.
-Users with permission level of [Developer or higher](../../../permissions.md) can manage merge requests.
+Users with at least the Developer role can manage merge requests.
When bulk editing merge requests in a group, you can edit the following attributes:
diff --git a/doc/user/project/merge_requests/reviews/suggestions.md b/doc/user/project/merge_requests/reviews/suggestions.md
index 1b2a35ba139..9868f2619ba 100644
--- a/doc/user/project/merge_requests/reviews/suggestions.md
+++ b/doc/user/project/merge_requests/reviews/suggestions.md
@@ -42,7 +42,7 @@ After the author applies a suggestion:
1. The suggestion is marked as **Applied**.
1. The thread is resolved.
1. GitLab creates a new commit with the changes.
-1. If the user has the [Developer role](../../../permissions.md), GitLab pushes
+1. If the user has the Developer role, GitLab pushes
the suggested change directly into the codebase in the merge request's branch.
## Multi-line suggestions
@@ -114,7 +114,7 @@ introduced by [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381).
## Batch suggestions
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) with a flag named `batch_suggestions`, disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](../../../../policy/alpha-beta-support.md#alpha-features) with a flag named `batch_suggestions`, disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) in GitLab 13.2.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) in GitLab 13.11. [Feature flag `batch_suggestions`](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) removed.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326168) custom commit messages for batch suggestions in GitLab 14.4.
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index f5ebfb3668c..a952c0550bc 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -28,6 +28,32 @@ You can configure merge request status checks for each individual project. These
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).
+## Lifecycle
+
+External status checks have an **asynchronous** workflow. Merge requests emit a merge request webhook payload to an external service whenever:
+
+- The merge request is changed. For example, title or description.
+- Code is pushed to the source branch of the merge request.
+- A comment is made in the merge request discussion.
+
+```mermaid
+sequenceDiagram
+ Merge request->>+External service: Merge request payload
+ External service-->>-Merge request: Status check response
+ Note over External service,Merge request: Response includes SHA at HEAD
+```
+
+When the payload is received, the external service can then run any required processes before posting its response back to the merge request [using the REST API](../../../api/status_checks.md#set-status-of-an-external-status-check).
+
+Merge requests return a `409 Conflict` error to any responses that do not refer to the current `HEAD` of the source branch. As a result, it's safe for the external service to process and respond to out-of-date commits.
+
+External status checks have the following states:
+
+- `pending` - The default state. No response can been received by the merge request from the external service.
+- `response received` - A response from the external service has been received and approved by it.
+
+Support for adding a `failed` state is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338827).
+
## View the status checks on a project
Within each project's settings, you can see a list of status checks added to the project:
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 1f84964c619..bd54eda42f5 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: reference, howto
---
# Test coverage visualization **(FREE)**
@@ -40,6 +39,7 @@ Other coverage analysis frameworks support the format out of the box, for exampl
- [Istanbul](https://istanbul.js.org/docs/advanced/alternative-reporters/#cobertura) (JavaScript)
- [Coverage.py](https://coverage.readthedocs.io/en/coverage-5.0.4/cmd.html#xml-reporting) (Python)
+- [PHPUnit](https://github.com/sebastianbergmann/phpunit-documentation-english/blob/master/src/textui.rst#command-line-options) (PHP)
Once configured, if you create a merge request that triggers a pipeline which collects
coverage reports, the coverage is shown in the diff view. This includes reports
@@ -52,6 +52,8 @@ from any job in any stage in the pipeline. The coverage displays for each line:
Hovering over the coverage bar provides further information, such as the number
of times the line was checked by tests.
+Uploading a test coverage report does not enable [test coverage results in Merge Requests](../../../ci/pipelines/settings.md#add-test-coverage-results-to-a-merge-request-deprecated) or [code coverage history](../../../ci/pipelines/settings.md#view-code-coverage-history). You must configure these separately.
+
### Limits
A limit of 100 `<source>` nodes for Cobertura format XML files applies. If your Cobertura report exceeds
@@ -133,6 +135,9 @@ The `source` is ignored if the path does not follow this pattern. The parser ass
## Example test coverage configurations
+This section provides test coverage configuration examples for different programming languages. You can also see a working example in
+the [`coverage-report`](https://gitlab.com/gitlab-org/ci-sample-projects/coverage-report/) demonstration project.
+
### JavaScript example
The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example uses [Mocha](https://mochajs.org/)
@@ -236,7 +241,7 @@ run tests:
image: python:3
script:
- pip install pytest pytest-cov
- - coverage run -m pytest
+ - coverage run -m pytest
- coverage report
- coverage xml
artifacts:
@@ -244,6 +249,42 @@ run tests:
cobertura: coverage.xml
```
+### PHP example
+
+The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for PHP uses [PHPUnit](https://phpunit.readthedocs.io/)
+to collect test coverage data and generate the report.
+
+With a minimal [`phpunit.xml`](https://phpunit.readthedocs.io/en/9.5/configuration.html) file (you may reference
+[this example repository](https://gitlab.com/yookoala/code-coverage-visualization-with-php/)), you can run the test and
+generate the coverage xml:
+
+```yaml
+run tests:
+ stage: test
+ image: php:latest
+ variables:
+ XDEBUG_MODE: coverage
+ before_script:
+ - apt-get update && apt-get -yq install git unzip zip libzip-dev zlib1g-dev
+ - docker-php-ext-install zip
+ - pecl install xdebug && docker-php-ext-enable xdebug
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php --install-dir=/usr/local/bin --filename=composer
+ - composer install
+ - composer require --dev phpunit/phpunit phpunit/php-code-coverage
+ script:
+ - php ./vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml
+ artifacts:
+ reports:
+ cobertura: coverage.cobertura.xml
+```
+
+[Codeception](https://codeception.com/), through PHPUnit, also supports generating Cobertura report with
+[`run`](https://codeception.com/docs/reference/Commands#run). The path for the generated file
+depends on the `--coverage-cobertura` option and [`paths`](https://codeception.com/docs/reference/Configuration#paths)
+configuration for the [unit test suite](https://codeception.com/docs/05-UnitTests). Configure `.gitlab-ci.yml`
+to find Cobertura in the appropriate path.
+
### C/C++ example
The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for C/C++ with
@@ -272,3 +313,62 @@ run tests:
reports:
cobertura: build/coverage.xml
```
+
+### Go example
+
+The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for Go uses:
+
+- [`go test`](https://go.dev/doc/tutorial/add-a-test) to run tests.
+- [`gocover-cobertura`](https://github.com/t-yuki/gocover-cobertura) to convert Go's coverage profile into the Cobertura XML format.
+
+This example assumes that [Go modules](https://go.dev/ref/mod) are being used.
+Using Go modules causes paths within the coverage profile to be prefixed with your
+project's module identifier, which can be found in the `go.mod` file. This
+prefix must be removed for GitLab to parse the Cobertura XML file correctly. You can use the following `sed` command to remove the prefix:
+
+```shell
+sed -i 's;filename=\"<YOUR_MODULE_ID>/;filename=\";g' coverage.xml
+```
+
+Replace the `gitlab.com/my-group/my-project` placeholder in the following example with your own module identifier to make it work.
+
+```yaml
+run tests:
+ stage: test
+ image: golang:1.17
+ script:
+ - go install
+ - go test . -coverprofile=coverage.txt -covermode count
+ - go run github.com/t-yuki/gocover-cobertura < coverage.txt > coverage.xml
+ - sed -i 's;filename=\"gitlab.com/my-group/my-project/;filename=\";g' coverage.xml
+ artifacts:
+ reports:
+ cobertura: coverage.xml
+```
+
+### Ruby example
+
+The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for Ruby uses
+
+- [`rspec`](https://rspec.info/) to run tests.
+- [`simplecov`](https://github.com/simplecov-ruby/simplecov) and [`simplecov-cobertura`](https://github.com/dashingrocket/simplecov-cobertura)
+ to record the coverage profile and create a report in the Cobertura XML format.
+
+This example assumes:
+
+- That [`bundler`](https://bundler.io/) is being used for dependency management.
+ The `rspec`, `simplecov` and `simplecov-cobertura` gems have been added to your `Gemfile`.
+- The `CoberturaFormatter` has been added to your `SimpleCov.formatters`
+ configuration within the `spec_helper.rb` file.
+
+```yaml
+run tests:
+ stage: test
+ image: ruby:3.1
+ script:
+ - bundle install
+ - bundle exec rspec
+ artifacts:
+ reports:
+ cobertura: coverage/coverage.xml
+```
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 0a9a2a37bfe..741ac325cca 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
@@ -1,8 +1,7 @@
---
stage: Verify
-group: Testing
+group: Pipeline 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
-type: index
description: "Test your code and display reports in merge requests"
---
@@ -11,21 +10,21 @@ description: "Test your code and display reports in merge requests"
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:
-| Feature | Description |
-|--------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Accessibility Testing](accessibility_testing.md) | Automatically report A11y violations for changed pages in merge requests. |
-| [Browser Performance Testing](browser_performance_testing.md) **(PREMIUM)** | Quickly determine the browser performance impact of pending code changes. |
-| [Load Performance Testing](load_performance_testing.md) **(PREMIUM)** | Quickly determine the server performance impact of pending code changes. |
-| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
-| [Display arbitrary job artifacts](../../../ci/yaml/index.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../../../ci/pipelines/job_artifacts.md) in merge requests. |
-| [GitLab CI/CD](../../../ci/index.md) | Build, test, and deploy your code in a per-branch basis with built-in CI/CD. |
-| [Unit test reports](../../../ci/unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it's easier and faster to identify the failure without having to check the entire job log. |
-| [License Compliance](../../compliance/license_compliance/index.md) **(ULTIMATE)** | Manage the licenses of your dependencies. |
-| [Metrics Reports](../../../ci/metrics_reports.md) **(PREMIUM)** | Display the Metrics Report on the merge request so that it's fast and easy to identify changes to important metrics. |
-| [Multi-Project pipelines](../../../ci/pipelines/multi_project_pipelines.md) **(PREMIUM)** | When you set up GitLab CI/CD across multiple projects, you can visualize the entire pipeline, including all cross-project interdependencies. |
-| [Pipelines for merge requests](../../../ci/pipelines/merge_request_pipelines.md) | Customize a specific pipeline structure for merge requests in order to speed the cycle up by running only important jobs. |
-| [Pipeline Graphs](../../../ci/pipelines/index.md#visualize-pipelines) | View the status of pipelines within the merge request, including the deployment process. |
-| [Test Coverage visualization](test_coverage_visualization.md) | See test coverage results for merge requests, within the file diff. |
+| Feature | Description |
+|----------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Accessibility Testing](accessibility_testing.md) | Automatically report A11y violations for changed pages in merge requests. |
+| [Browser Performance Testing](browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
+| [Load Performance Testing](load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
+| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
+| [Display arbitrary job artifacts](../../../ci/yaml/index.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../../../ci/pipelines/job_artifacts.md) in merge requests. |
+| [GitLab CI/CD](../../../ci/index.md) | Build, test, and deploy your code in a per-branch basis with built-in CI/CD. |
+| [Unit test reports](../../../ci/unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it's easier and faster to identify the failure without having to check the entire job log. |
+| [License Compliance](../../compliance/license_compliance/index.md) | Manage the licenses of your dependencies. |
+| [Metrics Reports](../../../ci/metrics_reports.md) | Display the Metrics Report on the merge request so that it's fast and easy to identify changes to important metrics. |
+| [Multi-Project pipelines](../../../ci/pipelines/multi_project_pipelines.md) | When you set up GitLab CI/CD across multiple projects, you can visualize the entire pipeline, including all cross-project interdependencies. |
+| [Merge request pipelines](../../../ci/pipelines/merge_request_pipelines.md) | Customize a specific pipeline structure for merge requests in order to speed the cycle up by running only important jobs. |
+| [Pipeline Graphs](../../../ci/pipelines/index.md#visualize-pipelines) | View the status of pipelines within the merge request, including the deployment process. |
+| [Test Coverage visualization](test_coverage_visualization.md) | See test coverage results for merge requests, within the file diff. |
## Security Reports **(ULTIMATE)**
diff --git a/doc/user/project/milestones/burndown_and_burnup_charts.md b/doc/user/project/milestones/burndown_and_burnup_charts.md
index 7c22b271ec2..05cc424e5ee 100644
--- a/doc/user/project/milestones/burndown_and_burnup_charts.md
+++ b/doc/user/project/milestones/burndown_and_burnup_charts.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
![burndown and burnup chart](img/burndown_and_burnup_charts_v13_6.png)
-## Burndown charts **(PREMIUM)**
+## Burndown charts
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6495) to GitLab 11.2 for group milestones.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) [fixed burndown charts](#fixed-burndown-charts) in GitLab 13.6.
@@ -73,10 +73,8 @@ The chart indicates the project's progress throughout that milestone (for issues
In particular, it shows how many issues were or are still open for a given day in the
milestone's corresponding period.
-The burndown chart can also be toggled to display the cumulative open issue
-weight for a given day. When using this feature, make sure issue weights have
-been properly assigned, since an open issue with no weight adds zero to the
-cumulative value.
+You can also toggle the burndown chart to display the
+[cumulative open issue weight](#switch-between-number-of-issues-and-issue-weight) for a given day.
### Fixed burndown charts
@@ -100,7 +98,7 @@ Therefore, when the milestone start date is changed, the number of opened issues
change.
Reopened issues are considered as having been opened on the day after they were last closed.
-## Burnup charts **(PREMIUM)**
+## Burnup charts
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268350) in GitLab 13.7.
@@ -123,12 +121,21 @@ To view a group's burnup chart:
### How burnup charts work
Burnup charts have separate lines for total work and completed work. The total line
-shows when scope is reduced or added to a milestone. The completed work is a count
-of issues closed.
+shows changes to the scope of a milestone. When an open issue is moved to another
+milestone, the "total issues" goes down but the "completed issues" stays the same.
+The completed work is a count of issues closed. When an issue is closed, the "total
+issues" remains the same and "completed issues" goes up.
-Burnup charts can show either the total number of issues or total weight for each
-day of the milestone. Use the toggle above the charts to switch between total
-and weight.
+## Switch between number of issues and issue weight
+
+In both burndown or burnup charts you can view them
+either by the total number of issues
+or the total weight for each day of the milestone.
+
+To switch between the two settings, select either **Issues** or **Issue weight** above the charts.
+
+When sorting by weight, make sure all your issues
+have weight assigned, because issues with no weight don't show on the chart.
<!-- ## Troubleshooting
diff --git a/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png b/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png
deleted file mode 100644
index ffe1328b7d3..00000000000
--- a/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index fb61e123faf..4501cf500b0 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -53,35 +53,23 @@ If you're in a project and select **Issues > Milestones**, GitLab displays only
## Creating milestones
-NOTE:
-A permission level of [Developer or higher](../../permissions.md) is required to create milestones.
-
-### New project milestone
-
-To create a project milestone:
-
-1. In a project, go to **{issues}** **Issues > Milestones**.
-1. Select **New milestone**.
-1. Enter the title, an optional description, an optional start date, and an optional due date.
-1. Select **New milestone**.
-
-![New project milestone](img/milestones_new_project_milestone.png)
+Users with at least the Developer role can create milestones.
-### New group milestone
+Milestones can be created either at project or group level.
-To create a group milestone:
+To create a milestone:
-1. In a group, go to **{issues}** **Issues > Milestones**.
+1. On the top bar, select **Menu > Projects** and find your project or **Menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Milestones**.
1. Select **New milestone**.
1. Enter the title, an optional description, an optional start date, and an optional due date.
1. Select **New milestone**.
-![New group milestone](img/milestones_new_group_milestone_v13_5.png)
+![New milestone](img/milestones_new_project_milestone.png)
## Editing milestones
-NOTE:
-A permission level of [Developer or higher](../../permissions.md) is required to edit milestones.
+Users with at least the Developer role can edit milestones.
To edit a milestone:
@@ -155,23 +143,18 @@ There are also tabs below these that show the following:
- Completed Issues (closed)
- **Merge Requests**: Shows all merge requests assigned to the milestone. These are displayed in four columns named:
- Work in progress (open and unassigned)
- - Waiting for merge (open and unassigned)
+ - Waiting for merge (open and assigned)
- Rejected (closed)
- Merged
- **Participants**: Shows all assignees of issues assigned to the milestone.
- **Labels**: Shows all labels that are used in issues assigned to the milestone.
-### Project Burndown Charts
+### Burndown Charts
-For project milestones, a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view,
+The milestone view contains a [burndown and burnup chart](burndown_and_burnup_charts.md),
showing the progress of completing a milestone.
-![burndown chart](img/burndown_chart_v13_6.png)
-
-### Group Burndown Charts
-
-For group milestones, a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view,
-showing the progress of completing a milestone.
+![burndown chart](img/burndown_and_burnup_charts_v13_6.png)
### Milestone sidebar
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 283ed0b61b9..82b1a824f7a 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -81,7 +81,7 @@ GitLab Pages website.
You can either use the GitLab [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-default-domain-names),
`*.gitlab.io`, or your own domain (`example.com`). In that case, you
-must have the Administrator role in your domain's registrar (or control panel) to set it up with Pages.
+must be an administrator in your domain's registrar (or control panel) to set it up with Pages.
The following diagrams show the workflows you might follow to get started with Pages.
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 10fbc57fa0b..65e1579001b 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -63,7 +63,7 @@ If the case of `404.html`, there are different scenarios. For example:
You can configure redirects for your site using a `_redirects` file. To learn more, read
the [redirects documentation](redirects.md).
-## GitLab Pages Access Control **(FREE)**
+## GitLab Pages Access Control
To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 6c18fc158f5..8bb18905222 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -18,7 +18,7 @@ When a branch is protected, the default behavior enforces these restrictions on
| Action | Who can do it |
|:-------------------------|:------------------------------------------------------------------|
-| Protect a branch | Maintainers only. |
+| Protect a branch | At least the Maintainer role. |
| Push to the branch | GitLab administrators and anyone with **Allowed** permission. (1) |
| Force push to the branch | No one. |
| Delete the branch | No one. |
@@ -35,7 +35,7 @@ Administrators can set a default branch protection level in the
Prerequisite:
-- You must have at least the [Maintainer role](../permissions.md).
+- You must have at least the Maintainer role.
To protect a branch:
@@ -52,7 +52,7 @@ The protected branch displays in the list of protected branches.
Prerequisite:
-- You must have at least the [Maintainer role](../permissions.md).
+- You must have at least the Maintainer role.
To protect multiple branches at the same time:
@@ -75,7 +75,7 @@ The protected branch displays in the list of protected branches.
## Create a protected branch
-Users with the Developer or higher [role](../permissions.md) can create a protected branch.
+Users with at least the Developer role can create a protected branch.
Prerequisites:
@@ -217,16 +217,16 @@ for details about the pipelines security model.
## Delete a protected branch
-Users with the [Maintainer role](../permissions.md) and greater can manually delete protected
+Users with at least the Maintainer role can manually delete protected
branches by using the GitLab web interface:
1. Go to **Repository > Branches**.
1. Next to the branch you want to delete, select the **Delete** button (**{remove}**).
1. On the confirmation dialog, type the branch name and select **Delete protected branch**.
-You can delete a protected branch from the UI only.
-This prevents you from accidentally deleting a branch
-from the command line or from a Git client application.
+Protected branches can only be deleted by using GitLab either from the UI or API.
+This prevents accidentally deleting a branch through local Git commands or
+third-party Git clients.
<!-- ## Troubleshooting
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index e4743c82a3b..7d071a45d63 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -22,12 +22,12 @@ This feature evolved out of [protected branches](protected_branches.md)
By default:
-- To create tags, you must have the [Maintainer role](../permissions.md).
+- To create tags, you must have the Maintainer role.
- No one can update or delete tags.
## Configuring protected tags
-To protect a tag, you need to have at least the [Maintainer role](../permissions.md).
+To protect a tag, you need to have at least the Maintainer role.
1. Go to the project's **Settings > Repository**.
@@ -66,6 +66,26 @@ all matching tags:
![Protected tag matches](img/protected_tag_matches.png)
+## Prevent tag creation with the same name as branches
+
+A tag and a branch with identical names can contain different commits. If your
+tags and branches use the same names, users running `git checkout`
+commands might check out the _tag_ `qa` when they instead meant to check out
+the _branch_ `qa`.
+
+To prevent this problem:
+
+1. Identify the branch names you do not want used as tags.
+1. As described in [Configuring protected tags](#configuring-protected-tags),
+ create a protected tag:
+
+ - For the **Name**, provide a name, such as `stable`. You can also create a wildcard
+ like `stable-*` to match multiple names, like `stable-v1` and `stable-v2`.
+ - For **Allowed to Create**, select **No one**.
+ - Select **Protect**.
+
+Users can still create branches, but not tags, with the protected names.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index 846d4732533..20dd37578fd 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Push Options **(FREE)**
GitLab supports using client-side [Git push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)
-to perform various actions at the same time as pushing changes. Additionally, [Push Rules](../../push_rules/push_rules.md) offer server-side control and enforcement options.
+to perform various actions at the same time as pushing changes. Additionally, [Push Rules](repository/push_rules.md) offer server-side control and enforcement options.
Currently, there are push options available for:
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 21a080de404..8070c37db78 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -49,7 +49,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| Command | Issue | Merge request | Epic | Action |
|:-------------------------------------------------------------------------------------------------|:-----------------------|:-----------------------|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `/add_contacts email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
+| `/add_contacts [contact:email1@example.com] [contact:email2@example.com]` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
| `/approve` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Approve the merge request. |
| `/assign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users. |
| `/assign me` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself. |
@@ -78,7 +78,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/lock` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Lock the discussions. |
| `/merge` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Merge changes. Depending on the project setting, this may be [when the pipeline succeeds](merge_requests/merge_when_pipeline_succeeds.md), or adding to a [Merge Train](../../ci/pipelines/merge_trains.md). |
| `/milestone %milestone` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set milestone. |
-| `/move <path/to/project>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Move this issue to another project. |
+| `/move <path/to/project>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Move this issue to another project. Be careful when moving an issue to a project with different access rules. Before moving the issue, make sure it does not contain sensitive data. |
| `/parent_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Set parent epic to `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.1](https://gitlab.com/gitlab-org/gitlab/-/issues/10556)). |
| `/promote` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Promote issue to epic. |
| `/promote_to_incident` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Promote issue to incident ([introduced in GitLab 14.5](https://gitlab.com/gitlab-org/gitlab/-/issues/296787)). |
@@ -89,7 +89,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/relabel ~label1 ~label2` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Replace current labels with those specified. |
| `/relate #issue1 #issue2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Mark issues as related. |
| `/remove_child_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Remove child epic from `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). |
-| `/remove_contacts email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
+| `/remove_contacts [contact:email1@example.com] [contact:email2@example.com]` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
| `/remove_due_date` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove due date. |
| `/remove_epic` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove from epic. |
| `/remove_estimate` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time estimate. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 747b41d07f2..8049ee9726d 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -393,7 +393,7 @@ deploy_to_production:
To set a deploy freeze window in the UI, complete these steps:
-1. Sign in to GitLab as a user with the [Maintainer role](../../permissions.md).
+1. Sign in to GitLab as a user with the Maintainer role.
1. On the left sidebar, select **Project information**.
1. In the left navigation menu, navigate to **Settings > CI/CD**.
1. Scroll to **Deploy freezes**.
@@ -480,7 +480,7 @@ to use the same URL. This is defined during [link creation](../../../api/release
The format of the URL is:
```plaintext
-https://host/namespace/project/releases/:release/downloads/:filepath
+https://host/namespace/project/-/releases/:release/downloads/:filepath
```
If you have an asset for the `v11.9.0-rc2` release in the `gitlab-org`
@@ -498,7 +498,7 @@ namespace and `gitlab-runner` project on `gitlab.com`, for example:
This asset has a direct link of:
```plaintext
-https://gitlab.com/gitlab-org/gitlab-runner/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64
+https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64
```
The physical location of the asset can change at any time and the direct link remains unchanged.
@@ -706,7 +706,7 @@ Here is an example of a release evidence object:
### Collect release evidence **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in GitLab 12.10.
When a release is created, release evidence is automatically collected. To initiate evidence collection any other time, use an [API call](../../../api/releases/index.md#collect-release-evidence). You can collect release evidence multiple times for one release.
@@ -714,7 +714,7 @@ Evidence collection snapshots are visible on the Releases page, along with the t
### Include report artifacts as release evidence **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in GitLab 13.2.
When you create a release, if [job artifacts](../../../ci/yaml/index.md#artifactsreports) are included in the last pipeline that ran, they are automatically included in the release as release evidence.
@@ -767,22 +767,22 @@ In the API:
> [Changes were made to the Guest role access](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
-- Users with the [Reporter role or above](../../../user/permissions.md#project-members-permissions)
+- Users with at least the Reporter role
have read and download access to the project releases.
-- Users with the [Guest role](../../../user/permissions.md#project-members-permissions)
+- Users with the Guest role
have read and download access to the project releases.
This includes associated Git-tag-names, release description, author information of the releases.
However, other repository-related information, such as [source code](#source-code), [release evidence](#release-evidence) are redacted.
### Create, update, and delete a release and its assets
-- Users with [Developer role or above](../../../user/permissions.md#project-members-permissions)
+- Users with at least the Developer role
have write access to the project releases and assets.
- If a release is associated with a [protected tag](../protected_tags.md),
the user must be [allowed to create the protected tag](../protected_tags.md#configuring-protected-tags) too.
As an example of release permission control, you can allow only
-[Maintainer role or above](../../../user/permissions.md#project-members-permissions)
+users with at least the Maintainer role
to create, update, and delete releases by protecting the tag with a wildcard (`*`),
and set **Maintainer** in the **Allowed to create** column.
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index 65b7c4a9881..d706a0e8f8a 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -38,7 +38,7 @@ the [Git commands you need](#update-the-default-branch-name-in-your-repository)
To update the default branch name for an individual [project](../../index.md):
-1. Sign in to GitLab with at least the [Maintainer](../../../permissions.md) role.
+1. Sign in to GitLab with at least the Maintainer role.
1. In the left navigation menu, go to **Settings > Repository**.
1. Expand **Default branch**, and select a new default branch.
1. Optional. Select the **Auto-close referenced issues on default branch** checkbox to close
@@ -57,8 +57,8 @@ GitLab administrators can configure a new default branch name at the
### Instance-level custom initial branch name **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) in GitLab 13.2.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/325163) in GitLab 13.12.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) in GitLab 13.2 [with a flag](../../../../administration/feature_flags.md) named `global_default_branch_name`. Enabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/325163) in GitLab 13.12. Feature flag `global_default_branch_name` removed.
GitLab [administrators](../../../permissions.md) of self-managed instances can
customize the initial branch for projects hosted on that instance. Individual
@@ -129,7 +129,7 @@ renames a Git repository's (`example`) default branch.
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
```
-1. Sign in to GitLab with at least the [Maintainer](../../../permissions.md)
+1. Sign in to GitLab with at least the Maintainer
role and follow the instructions to
[change the default branch for this project](#change-the-default-branch-name-for-a-project).
Select `main` as your new default branch.
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index 1ab21286a8e..b085372c8f2 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -27,16 +27,15 @@ To fork an existing project in GitLab:
1. Select the project to fork to:
- Recommended method. Below **Select a namespace to fork the project**, identify
- the project you want to fork to, and click **Select**. Only namespaces you have
- Developer and higher [permissions](../../permissions.md) for are shown.
+ the project you want to fork to, and click **Select**. Only namespaces where you have
+ at least the Developer role for are shown.
![Choose namespace](img/forking_workflow_choose_namespace_v13_10.png)
- Experimental method. If your GitLab administrator has
- [enabled the experimental fork project form](#enable-or-disable-the-fork-project-form), read
+ enabled the experimental fork project form, read
[Create a fork with the fork project form](#create-a-fork-with-the-fork-project-form).
- Only namespaces you have at least the Developer
- [role](../../permissions.md) for are shown.
+ Only namespaces where you have at least the Developer role for are shown.
NOTE:
The project path must be unique in the namespace.
@@ -85,14 +84,14 @@ You can unlink your fork from its upstream project in the [advanced settings](..
## Create a fork with the fork project form **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15013) in GitLab 13.11.
-> - 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-the-fork-project-form). **(FREE SELF)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15013) in GitLab 13.11 [with a flag](../../../administration/feature_flags.md) named `fork_project_form`. Disabled by default.
+> - [Enabled on self-managed and GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64967) in GitLab 13.8.
-This experimental version of the fork project form is available only if your GitLab
-administrator has [enabled it](#enable-or-disable-the-fork-project-form):
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `fork_project_form`.
+On GitLab.com, this feature is available.
+
+This version of the fork project form is experimental:
![Choose namespace](img/fork_form_v13_10.png)
@@ -103,23 +102,3 @@ To use it, follow the instructions at [Creating a fork](#creating-a-fork) and pr
- The project slug.
- Optional. The project description.
- The visibility level for your fork.
-
-### Enable or disable the fork project form **(FREE SELF)**
-
-The new [fork project form](#create-a-fork-with-the-fork-project-form) 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(:fork_project_form)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:fork_project_form)
-```
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 0c5c0d5fa7c..f5cea8a8075 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -273,7 +273,7 @@ To remove a GPG key from your account:
## Rejecting commits that are not signed **(PREMIUM)**
You can configure your project to reject commits that aren't GPG-signed
-via [push rules](../../../../push_rules/push_rules.md).
+via [push rules](../push_rules.md).
## GPG signing API
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index c8950d39f28..cddbc6fd891 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -37,7 +37,7 @@ Mirror a repository when:
Prerequisite:
-- You must have at least the [Maintainer role](../../../permissions.md) for the project.
+- You must have at least the Maintainer role for the project.
- If your mirror connects with `ssh://`, the host key must be detectable on the server,
or you must have a local copy of the key.
@@ -45,8 +45,8 @@ Prerequisite:
1. On the left sidebar, select **Settings > Repository**.
1. Expand **Mirroring repositories**.
1. Enter a **Git repository URL**. 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.
+ repository is only displayed to users with the Maintainer role
+ or the Owner role for the mirrored project.
1. Select a **Mirror direction**.
1. If you entered a `ssh://` URL, select either:
- **Detect host keys**: GitLab fetches the host keys from the server and displays the fingerprints.
@@ -87,7 +87,7 @@ While mirrors are scheduled to update automatically, you can force an immediate
Prerequisite:
-- You must have at least the [Maintainer role](../../../permissions.md) for the project.
+- You must have at least the Maintainer role for the project.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > Repository**.
diff --git a/doc/user/project/repository/push_rules.md b/doc/user/project/repository/push_rules.md
new file mode 100644
index 00000000000..bb473a2830b
--- /dev/null
+++ b/doc/user/project/repository/push_rules.md
@@ -0,0 +1,288 @@
+---
+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"
+---
+
+# Push rules **(PREMIUM)**
+
+Gain additional control over what can and can't be pushed to your repository by using
+regular expressions to reject pushes based on commit contents, branch names or file details.
+
+GitLab already offers [protected branches](../protected_branches.md), but there are
+cases when you need some specific rules. Some common scenarios: preventing Git tag removal, or
+enforcing a special format for commit messages.
+
+Push rules are [pre-receive Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you
+can enable in a user-friendly interface. They are defined either:
+
+- Globally if you are an administrator.
+- Per project, so you can have different rules applied to different
+ projects depending on your needs.
+
+## Use cases
+
+Every push rule could have its own use case, but let's consider some examples.
+
+### Commit messages with a specific reference
+
+Let's assume you have the following requirements for your workflow:
+
+- every commit should reference a Jira issue, for example: `Refactored css. Fixes JIRA-123.`
+- users should not be able to remove Git tags with `git push`
+
+Write a regular expression that requires the mention
+of a Jira issue in the commit message, like `JIRA\-\d+`.
+
+Now when a user tries to push a commit with a message `Bugfix`, their push is
+declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
+is accepted.
+
+### Restrict branch names
+
+If your company has a strict policy for branch names, you may want the branches to start
+with a certain name. This approach enables different
+GitLab CI/CD jobs (such as `feature`, `hotfix`, `docker`, `android`) that rely on the
+branch name.
+
+Your developers may not remember that policy, so they might push to
+various branches, and CI pipelines might not work as expected. By restricting the
+branch names globally in Push Rules, such mistakes are prevented.
+All branch names that don't match your push rule are rejected.
+
+Note that the name of your default branch is always allowed, regardless of the branch naming
+regular expression (regex) specified. GitLab is configured this way
+because merges typically have the default branch as their target.
+If you have other target branches, include them in your regex. (See [Enabling push rules](#enabling-push-rules)).
+
+The default branch also defaults to being a [protected branch](../protected_branches.md),
+which already limits users from pushing directly.
+
+Some example regular expressions you can use in push rules:
+
+- `^JIRA-` Branches must start with `JIRA-`.
+- `-JIRA$` Branches must end with `-JIRA`.
+- `^[a-z0-9\\-]{4,15}$` Branches must be between `4` and `15` characters long,
+ accepting only lowercase letters, numbers and dashes.
+
+#### Default restricted branch names
+
+> Introduced in GitLab 12.10.
+
+By default, GitLab restricts certain formats of branch names for security purposes.
+40-character hexadecimal names, similar to Git commit hashes, are prohibited.
+
+### Custom Push Rules **(PREMIUM SELF)**
+
+It's possible to create custom push rules rather than the push rules available in
+**Admin Area > Push Rules** by using more advanced server hooks.
+
+See [server hooks](../../../administration/server_hooks.md) for more information.
+
+## Enabling 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](../../group/index.md#group-push-rules).
+
+To create global push rules:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Push Rules**.
+
+To override global push rules in a project's settings:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Push rules**.
+1. Set the rule you want.
+1. Select **Save push rules**.
+
+The following options are available:
+
+| Push rule | Description |
+|---------------------------------|-------------|
+| Removal of tags with `git push` | Forbid users to remove Git tags with `git push`. Tags can be deleted through the web UI. |
+| Check whether the commit author is a GitLab user | Restrict commits to existing GitLab users (checked against their emails). <sup>1</sup> |
+| Reject unverified users | GitLab rejects any commit that was not committed by the same user as the user who pushed it, or where the committer's email address is not [confirmed](../../../security/user_email_confirmation.md). |
+| Check whether commit is signed through GPG | Reject commit when it is not signed through GPG. Read [signing commits with GPG](gpg_signed_commits/index.md). |
+| Prevent pushing secret files | GitLab rejects any files that are likely to contain secrets. See the [forbidden file names](#prevent-pushing-secrets-to-the-repository). |
+| Require expression in commit messages | Only commit messages that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Reject expression in commit messages | Only commit messages that do not match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Restrict by branch name | Only branch names that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow all branch names. |
+| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. <sup>1</sup> <sup>2</sup> Leave empty to allow any email. |
+| Prohibited file names | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. <sup>2</sup> Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
+| Maximum file size | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
+
+1. Checks both the commit author and committer.
+1. GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
+
+### Caveat to "Reject unsigned commits" push rule
+
+This push rule ignores commits that are authenticated and created by GitLab
+(either through the UI or API). When the **Reject unsigned commits** push rule is
+enabled, unsigned commits may still show up in the commit history if a commit was
+created **in** GitLab itself. As expected, commits created outside GitLab and
+pushed to the repository are rejected. For more information about how GitLab
+plans to fix this issue, read [issue #19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
+
+#### "Reject unsigned commits" push rule disables Web IDE
+
+In 13.10, if a project has the "Reject unsigned commits" push rule, the user is not allowed to
+commit through GitLab Web IDE.
+
+To allow committing through the Web IDE on a project with this push rule, a GitLab administrator
+must disable the feature flag `reject_unsigned_commits_by_gitlab`. This can be done through a
+[rails console](../../../administration/operations/rails_console.md) and running:
+
+```ruby
+Feature.disable(:reject_unsigned_commits_by_gitlab)
+```
+
+## Prevent pushing secrets to the repository
+
+> Moved to GitLab Premium in 13.9.
+
+Secrets, such as credential files and SSH private keys, should never be committed to a version control
+system. In GitLab, you can use a predefined list of files to block those files from a
+repository. Any merge request containing a file matching the list is blocked from being merged.
+Files already committed to the repository are not restricted by this push rule.
+
+Files blocked by this rule are listed below. For a complete list of criteria, see
+[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml).
+
+- AWS CLI credential blobs:
+
+ - `.aws/credentials`
+ - `aws/credentials`
+ - `homefolder/aws/credentials`
+
+- Private RSA SSH keys:
+
+ - `/ssh/id_rsa`
+ - `/.ssh/personal_rsa`
+ - `/config/server_rsa`
+ - `id_rsa`
+ - `.id_rsa`
+
+- Private DSA SSH keys:
+
+ - `/ssh/id_dsa`
+ - `/.ssh/personal_dsa`
+ - `/config/server_dsa`
+ - `id_dsa`
+ - `.id_dsa`
+
+- Private ED25519 SSH keys:
+
+ - `/ssh/id_ed25519`
+ - `/.ssh/personal_ed25519`
+ - `/config/server_ed25519`
+ - `id_ed25519`
+ - `.id_ed25519`
+
+- Private ECDSA SSH keys:
+
+ - `/ssh/id_ecdsa`
+ - `/.ssh/personal_ecdsa`
+ - `/config/server_ecdsa`
+ - `id_ecdsa`
+ - `.id_ecdsa`
+
+- Private ECDSA_SK SSH keys (GitLab 14.8 and later):
+
+ - `/ssh/id_ecdsa_sk`
+ - `/.ssh/personal_ecdsa_sk`
+ - `/config/server_ecdsa_sk`
+ - `id_ecdsa_sk`
+ - `.id_ecdsa_sk`
+
+- Private ED25519_SK SSH keys (GitLab 14.8 and later):
+
+ - `/ssh/id_ed25519_sk`
+ - `/.ssh/personal_ed25519_sk`
+ - `/config/server_ed25519_sk`
+ - `id_ed25519_sk`
+ - `.id_ed25519_sk`
+
+- Any files ending with these suffixes:
+
+ - `*.pem`
+ - `*.key`
+ - `*.history`
+ - `*_history`
+
+### Prevent pushing secrets to all projects
+
+To set a global push rule to prevent pushing secrets to all projects:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Push Rules**.
+1. Expand **Push rules**.
+1. Select **Prevent pushing secret files**.
+1. Select **Save push rules**.
+
+### Prevent pushing secrets to a project
+
+The push rule of a project overrides the global push rule.
+
+To prevent pushing secrets to a project:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Push rules**.
+1. Select **Prevent pushing secret files**.
+1. Select **Save push rules**.
+
+## Prohibited file names
+
+> Moved to GitLab Premium in 13.9.
+
+Each filename contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension.
+
+The following examples make use of regex string boundary characters which match the beginning of a string (`^`), and the end (`$`). They also include instances where either the directory path or the filename can include `.` or `/`. Both of these special regex characters have to be escaped with a backslash `\\` to be used as normal characters in a match condition.
+
+Example: prevent pushing any `.exe` files to any location in the repository. This uses a partial match, which matches any filename that contains `.exe` at the end:
+
+```plaintext
+\.exe$
+```
+
+Example: prevent a specific configuration file in the repository root from being pushed:
+
+```plaintext
+^config\.yml$
+```
+
+Example: prevent a specific configuration file in a known directory from being pushed:
+
+```plaintext
+^directory-name\/config\.yml$
+```
+
+Example: prevent the specific file named `install.exe` from being pushed to any
+location in the repository. The parenthesized expression `(^|\/)` matches either
+a file following a directory separator or a file in the root directory of the repository:
+
+```plaintext
+(^|\/)install\.exe$
+```
+
+Example: combining all of the above in a single expression. The preceding expressions rely
+on the end-of-string character `$`. We can move that part of each expression to the
+end of the grouped collection of match conditions where it is appended to all matches:
+
+```plaintext
+(\.exe|^config\.yml|^directory-name\/config\.yml|(^|\/)install\.exe)$
+```
+
+<!-- ## 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/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 23cead7e8a7..37b16d90d93 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Reduce repository size
+# Reduce repository size **(FREE)**
Git repositories become larger over time. When large files are added to a Git repository:
@@ -193,7 +193,7 @@ When using repository cleanup, note:
Repository size limits:
- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings)
- on self-managed instances. **(PREMIUM SELF)**
+- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md) on self-managed instances.
- Are [set for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings).
When a project has reached its size limit, you cannot:
diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md
index f9d9af3e672..27ef14d31c5 100644
--- a/doc/user/project/repository/x509_signed_commits/index.md
+++ b/doc/user/project/repository/x509_signed_commits/index.md
@@ -1,8 +1,7 @@
---
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"
-type: concepts, howto
+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
---
# Sign commits and tags with X.509 certificates **(FREE)**
@@ -335,7 +334,7 @@ step of the previous [main verification checks](#main-verification-checks).
signature.__send__(:p7).verify([], signature.__send__(:cert_store), signature.__send__(:signed_text))
```
- 1. If this fails, add the missing certificate(s) required to establish trust
+ 1. If this fails, add the missing certificates required to establish trust
[to the GitLab certificate store](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
1. After adding more certificates, (if these troubleshooting steps then pass)
@@ -347,7 +346,7 @@ step of the previous [main verification checks](#main-verification-checks).
pp signature.__send__(:p7).certificates ; nil
```
-Ensure any additional intermediate certificate(s) and the root certificate are added
+Ensure any additional intermediate certificates and the root certificate are added
to the certificate store. For consistency with how certificate chains are built on
web servers:
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index 5fe0e0ef3a2..d549a22910a 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -40,7 +40,7 @@ can create a new requirement.
Prerequisite:
-- You must have at least the Reporter [role](../../permissions.md).
+- You must have at least the Reporter role.
To create a requirement:
@@ -70,7 +70,7 @@ You can edit a requirement from the requirements list page.
Prerequisite:
-- You must have at least the Reporter [role](../../permissions.md).
+- You must have at least the Reporter role.
To edit a requirement:
@@ -86,7 +86,7 @@ you're in the **Open** tab.
Prerequisite:
-- You must have at least the Reporter [role](../../permissions.md).
+- You must have at least the Reporter role.
To archive a requirement, select **Archive** (**{archive}**).
@@ -98,7 +98,7 @@ You can view the list of archived requirements in the **Archived** tab.
Prerequisite:
-- You must have at least the Reporter [role](../../permissions.md).
+- You must have at least the Reporter role.
![archived requirements list](img/requirements_archived_list_view_v13_1.png)
@@ -217,7 +217,7 @@ requirements_confirmation:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/246857) in GitLab 13.7.
-You must have at least the Reporter [role](../../permissions.md).
+You must have at least the Reporter role.
You can import requirements to a project by uploading a [CSV file](https://en.wikipedia.org/wiki/Comma-separated_values)
with the columns `title` and `description`.
@@ -291,7 +291,7 @@ audit and regulatory compliance tasks.
Prerequisite:
-- You must have at least the Reporter [role](../../permissions.md).
+- You must have at least the Reporter role.
To export requirements:
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 1b30f14ac90..1e5b818c99d 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -87,7 +87,7 @@ To improve your project's security, we recommend the following:
Unblocked email spam can result in many spam issues being created.
The unique internal email address is visible to project members at least
-the Reporter [role](../permissions.md) in your GitLab instance.
+the Reporter role in your GitLab instance.
An external user (issue creator) cannot see the internal email address
displayed in the information note.
@@ -333,3 +333,10 @@ Note that:
Behind the scenes, Service Desk works by the special Support Bot user creating issues. This user
does not count toward the license limit count.
+
+## Troubleshooting Service Desk
+
+### Emails to Service Desk do not create issues
+
+Your emails might be ignored because they contain one of the
+[email headers that GitLab ignores](../../administration/incoming_email.md#rejected-headers).
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 06bdf4ca14b..8cee567ae93 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -122,8 +122,7 @@ As described in the API documentation, the query may return an import error or e
The following items are imported but changed slightly:
-- Project members with the [Owner role](../../permissions.md)
- are imported as Maintainers.
+- Project members with the Owner role are imported as Maintainers.
- If an imported project contains merge requests originating from forks, then new branches
associated with such merge requests are created in a project during the import/export. Thus, the
number of branches in the exported project might be bigger than in the original project.
@@ -160,6 +159,8 @@ Imported users can be mapped by their public email addresses on self-managed ins
for mapping to work correctly.
- For contributions to be mapped correctly, users must be an existing member of the namespace,
or they can be added as a member of the project. Otherwise, a supplementary comment is left to mention that the original author and the MRs, notes, or issues that are owned by the importer.
+- Imported users are set as [direct members](../members/index.md)
+ in the imported project.
For project migration imports performed over GitLab.com groups, preserving author information is
possible through a [professional services engagement](https://about.gitlab.com/services/migration/).
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 9df545b52ec..4c6be3511f2 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -16,7 +16,7 @@ In GitLab versions [13.10 and later](https://gitlab.com/groups/gitlab-org/-/epic
GitLab displays a search box to help you find the settings you want to view.
NOTE:
-Only users who have the [Maintainer role](../../permissions.md) for the project and administrators can
+Only users who have the Maintainer role for the project and administrators can
access project settings.
## General settings
@@ -93,7 +93,7 @@ executed in place of the local project's `gitlab-ci.yml` file. As part of this p
files are merged together any time the pipeline runs. Jobs and variables defined in the compliance
pipeline can't be changed by variables in the local project's `gitlab-ci.yml` file.
-When used to enforce scan execution, this feature has some overlap with [scan execution policies](../../application_security/policies/#scan-execution-policies),
+When used to enforce scan execution, this feature has some overlap with [scan execution policies](../../application_security/policies/scan-execution-policies.md),
as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
For details on the similarities and differences between these features, see
[Enforce scan execution](../../application_security/#enforce-scan-execution).
@@ -249,7 +249,7 @@ Use the switches to enable or disable the following features:
|:---------------------------------|:--------------------------|:--------------|
| **Issues** | ✓ | Activates the GitLab issues tracker. |
| **Repository** | ✓ | Enables [repository](../repository/) functionality |
-| **Merge Requests** | ✓ | Enables [merge request](../merge_requests/) functionality; also see [Merge request settings](#merge-request-settings). |
+| **Merge requests** | ✓ | Enables [merge request](../merge_requests/) functionality; also see [Merge request settings](#merge-request-settings). |
| **Forks** | ✓ | Enables [forking](../repository/forking_workflow.md) functionality. |
| **Git Large File Storage (LFS)** | | Enables the use of [large files](../../../topics/git/lfs/index.md#git-large-file-storage-lfs). |
| **Packages** | | Supports configuration of a [package registry](../../../administration/packages/index.md#gitlab-package-registry-administration) functionality. |
@@ -281,7 +281,7 @@ Some features depend on others:
- If you disable **Repository** functionality, GitLab also disables the following
features for your project:
- - **Merge Requests**
+ - **Merge requests**
- **CI/CD**
- **Container Registry**
- **Git Large File Storage**
@@ -360,7 +360,7 @@ available in project listings. Only project owners and administrators have the
To find an archived project:
-1. Sign in to GitLab as the project owner or a user with the Administrator role.
+1. Sign in to GitLab as the project owner or a user with administrator access.
1. If you:
- Have the project's URL, open the project's page in your browser.
- Don't have the project's URL:
@@ -404,11 +404,17 @@ NOTE:
Only project owners and administrators have the [permissions](../../permissions.md#project-members-permissions)
to transfer a project.
-You can transfer an existing project into a [group](../../group/index.md) if:
+You can transfer an existing project into a [group](../../group/index.md).
-- You have at least **Maintainer** [role](../../permissions.md#project-members-permissions) in that group.
-- You're at least an **Owner** of the project to be transferred.
+Prerequisites:
+
+- You must have at least the Maintainer role in that group.
+- You must be the Owner of that project.
- The group to which the project is being transferred to must allow creation of new projects.
+- The project must not contain any [container images](../../packages/container_registry/index.md#limitations).
+ - If you transfer a project to a different root namespace,
+ the project must not contain any
+ [NPM packages](../../packages/npm_registry/index.md#limitations).
To transfer a project:
@@ -423,8 +429,8 @@ read what happens with the
[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
-namespace if needed.
+GitLab administrators can use the [administration interface](../../admin_area/index.md#administering-projects)
+to move any project to any namespace if needed.
##### Transferring a GitLab.com project to a different subscription tier
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index 3fcfe202d38..aa30c576c7c 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -1,6 +1,6 @@
---
stage: Manage
-group: Authentication & Authorization
+group: Authentication and Authorization
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
---
@@ -42,7 +42,7 @@ To create a project access token:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > Access Tokens**.
-1. Enter a name.
+1. Enter a name. The token name is visible to any user with permissions to view the project.
1. Optional. Enter an expiry date for the token. The token will expire on that date at midnight UTC.
1. Select a role for the token.
1. Select the [desired scopes](#scopes-for-a-project-access-token).
@@ -84,16 +84,16 @@ To enable or disable project access token creation for all projects in a top-lev
Even when creation is disabled, you can still use and revoke existing project access tokens.
-## Project bot users
+## Bot users for projects
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210181) in GitLab 13.0.
> - [Excluded from license seat use](https://gitlab.com/gitlab-org/gitlab/-/issues/223695) in GitLab 13.5.
-Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users).
+Bot users for projects are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users).
Each time you create a project access token, a bot user is created and added to the project.
These bot users do not count as licensed seats.
-The bot users have [permissions](../../permissions.md#project-members-permissions) that correspond with the
+The bot users for projects have [permissions](../../permissions.md#project-members-permissions) that correspond with the
selected role and [scope](#scopes-for-a-project-access-token) of the project access token.
- The name is set to the name of the token.
@@ -106,7 +106,7 @@ selected role and [scope](#scopes-for-a-project-access-token) of the project acc
API calls made with a project access token are associated with the corresponding bot user.
-Bot users:
+Bot users for projects:
- Are included in a project's member list but cannot be modified.
- Cannot be added to any other project.
@@ -114,5 +114,6 @@ Bot users:
When the project access token is [revoked](#revoke-a-project-access-token):
- The bot user is deleted.
-- All records are moved to a system-wide user with the username `Ghost User`. For more information, see
- [associated records](../../profile/account/delete_account.md#associated-records).
+- All records are moved to a system-wide user with the username [Ghost User](../../profile/account/delete_account.md#associated-records).
+
+See also [Bot users for groups](../../group/settings/group_access_tokens.md#bot-users-for-groups).
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
index 50b1a3a929d..072f5bf1927 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -12,6 +12,14 @@ description: "The static site editor enables users to edit content on static web
> - WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214559) in GitLab 13.0.
> - Non-Markdown content blocks not editable on the WYSIWYG mode [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216836) in GitLab 13.3.
> - Formatting Markdown [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49052) in GitLab 13.7.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77246) in GitLab 14.7.
+
+WARNING:
+This feature is in its end-of-life process. It is
+[deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77246)
+for use in GitLab 14.7, and is planned for
+[removal](https://gitlab.com/groups/gitlab-org/-/epics/7351) in GitLab 15.0.
+Users should instead use the [Web Editor](../repository/web_editor.md) or [Web IDE](../web_ide/index.md).
Static Site Editor (SSE) enables users to edit content on static websites without
prior knowledge of the underlying templating language, site architecture, or
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index 6ceb8c94934..5f747d99ce7 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -8,76 +8,81 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Time tracking **(FREE)**
-With time tracking you can track estimates and time spent on issues and merge
-requests in GitLab.
+You can estimate and track the time you spend on [issues](issues/index.md)
+and [merge requests](merge_requests/index.md).
+
+Then you can [view a report](#view-a-time-tracking-report) that shows totals over time.
Use time tracking for these tasks:
- Record the time spent working on an issue or a merge request.
- Add or update an estimate of the total time to complete an issue or a merge
-request.
+ 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.
-Data about time tracking shows up on the issue and merge request sidebar:
+To enter and remove time tracking data, you must use [quick actions](quick_actions.md).
+Type all quick actions on their own lines.
+If you use any quick action more than once in a single comment, only its last occurrence is applied.
+
+You can see the data about time tracking on the right sidebar in issues and merge requests:
![Time tracking in the sidebar](img/time_tracking_sidebar_v13_12.png)
-## How to enter data
+## Estimates
-Time tracking uses two [quick actions](quick_actions.md): `/spend` and `/estimate`.
+The estimate is designed to show the total time needed to complete an issue or merge request.
-If you use either quick action more than once in a single comment, only the last occurrence is applied.
+You can see the estimated time remaining when you hover over the time tracking information in the right sidebar.
-Below is an example of how you can use those new quick actions inside a comment.
+![Estimated time remaining](img/remaining_time_v14_2.png)
-![Time tracking example in a comment](img/time_tracking_example_v12_2.png)
+### Add an estimate
-Adding time entries (time spent or estimates) is limited to project members
-with [Reporter and higher permission levels](../permissions.md).
+Prerequisites:
-### Estimates
+- You must have at least the Reporter role for the project.
-To enter an estimate, type `/estimate`, followed by the time.
+To enter an estimate, use the `/estimate` [quick action](quick_actions.md), followed by the time.
For example, if you need to enter an estimate of 1 month, 2 weeks, 3 days, 4 hours, and 5 minutes,
type `/estimate 1mo 2w 3d 4h 5m`.
-Check the [time units you can use](#configuration).
+Check the [time units you can use](#available-time-units).
-The estimate is designed to show the total estimated time. The estimated
-time remaining is automatically calculated and displayed when hovering over
-the time tracking information in the right sidebar.
+An issue or a merge request can have only one estimate.
+Every time you enter a new time estimate, it overwrites the previous value.
-![Estimated time remaining](img/remaining_time_v14_2.png)
+### Remove an estimate
-An issue or a merge request can have only one estimate. Every time you enter a
-new time estimate, it overwrites the previous value.
+Prerequisites:
-To remove an estimation entirely, use `/remove_estimate`.
+- You must have at least the Reporter role for the project.
-### Time spent
+To remove an estimate entirely, use the `/remove_estimate` [quick action](quick_actions.md).
-To enter time spent, type `/spend`, followed by the time.
+## Time spent
-For example, if you need
-to log 1 month, 2 weeks, 3 days, 4 hours, and 5 minutes, type `/spend 1mo 2w 3d 4h 5m`.
-Check the [time units you can use](#configuration).
+As you work, you can log the time you've spent.
Every new time spent entry is added to the current total time spent for the
issue or the merge request.
-To subtract time, enter a negative value. For example, `/spend -3d` removes three
-days from the total time spent. You can't go below 0 minutes of time spent,
-so if you remove more time than already entered, GitLab ignores the subtraction.
+### Add time spent
-You can log time in the past by providing a date after the time.
-For example, if you want to log 1 hour of time spent on the 31 January 2021,
-you would type `/spend 1h 2021-01-31`. If you supply a date in the future, the
-command fails and no time is logged.
+Prerequisites:
+
+- You must have at least the Reporter role for the project.
+
+To enter time spent, use the `/spend` [quick action](quick_actions.md), followed by the time.
+
+For example, if you need
+to log 1 month, 2 weeks, 3 days, 4 hours, and 5 minutes, type `/spend 1mo 2w 3d 4h 5m`.
+Check the [time units you can use](#available-time-units).
-To add a timelog entry with a note, create a comment with a description and the quick action.
-It then shows in the timelog "Summary/Notes" column. For example:
+To add a [time tracking report](#view-a-time-tracking-report) entry with a note, create a comment
+with a description and the quick action.
+It then shows in the time tracking report **Summary/Notes** column. For example:
```plaintext
Draft MR and respond to initial comments
@@ -85,7 +90,29 @@ Draft MR and respond to initial comments
/spend 30m
```
-To remove all the time spent at once, use `/remove_time_spent`.
+### Add time spent on a specific date
+
+Prerequisites:
+
+- You must have at least the Reporter role for the project.
+
+You can log time in the past by providing a date after the time.
+For example, to log 1 hour of time spent on 31 January 2021,
+type `/spend 1h 2021-01-31`.
+
+If you type a future date, no time is logged.
+
+### Remove time spent
+
+Prerequisites:
+
+- You must have at least the Reporter role for the project.
+
+To subtract time, enter a negative value. For example, `/spend -3d` removes three
+days from the total time spent. You can't go below 0 minutes of time spent,
+so if you remove more time than already entered, GitLab ignores the subtraction.
+
+To remove all the time spent at once, use the `/remove_time_spent` [quick action](quick_actions.md).
## View a time tracking report
@@ -93,35 +120,32 @@ 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:
-To view a time tracking report, go to an issue or a merge request and select **Time tracking report**
-in the right sidebar.
+1. Go to an issue or a merge request.
+1. In the right sidebar, select **Time tracking report**.
![Time tracking report](img/time_tracking_report_v13_12.png)
The breakdown of spent time is limited to a maximum of 100 entries.
-## Configuration
+## Available time units
The following time units are available:
-| Time unit | What to type | Default conversion rate |
-| --------- | ------------ | ----------------------- |
-| Month | `mo` | 4w |
-| Week | `w` | 5d |
-| Day | `d` | 8h |
-| Hour | `h` | 60m |
-| Minute | `m` | |
+| Time unit | What to type | Conversion rate |
+| --------- | --------------------------- | --------------- |
+| Month | `mo`, `month`, or `months` | 4w (160h) |
+| Week | `w`, `week`, or `weeks` | 5d (40h) |
+| Day | `d`, `day`, or `days` | 8h |
+| Hour | `h`, `hour`, or `hours` | 60m |
+| Minute | `m`, `minute`, or `minutes` | |
### Limit displayed units to hours **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29469/) in GitLab 12.1.
-In GitLab self-managed instances, you can limit the display of time units to
-hours.
+In GitLab self-managed instances, you can limit the display of time units to hours.
To do so:
1. On the top bar, select **Menu > Admin**.
diff --git a/doc/user/project/wiki/group.md b/doc/user/project/wiki/group.md
index 731fed2595a..2c499af123c 100644
--- a/doc/user/project/wiki/group.md
+++ b/doc/user/project/wiki/group.md
@@ -22,7 +22,7 @@ Group wikis are similar to [project wikis](index.md), with a few limitations:
For updates, follow [the epic that tracks feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
-Similar to project wikis, group members with the [Developer role](../../permissions.md#group-members-permissions)
+Similar to project wikis, group members with at least the Developer role
and higher can edit group wikis. Group wiki repositories can be moved using the
[Group repository storage moves API](../../../api/group_repository_storage_moves.md).
@@ -40,7 +40,7 @@ To access a group wiki:
> Introduced in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247).
-Users with the [Owner role](../../permissions.md) in a group can
+Users with the Owner role in a group can
[import and export group wikis](../../group/settings/import_export.md) when importing
or exporting a group.
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 95ea1b4d0bc..33f6c32d334 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -74,7 +74,7 @@ to be used as your wiki's home page. To create it:
## Create a new wiki page
-Users with the [Developer role](../../permissions.md) can create new wiki pages:
+Users with at least the Developer role can create new wiki pages:
1. On the top bar, select **Menu**.
- For project wikis, select **Projects** and find your project.
@@ -137,7 +137,7 @@ may not be able to check out the wiki locally afterward.
## Edit a wiki page
-You need at least the [Developer role](../../permissions.md) to edit a wiki page:
+You need at least the Developer role to edit a wiki page:
1. On the top bar, select **Menu**.
- For project wikis, select **Projects** and find your project.
@@ -156,7 +156,7 @@ For an example, read [Table of contents](../../markdown.md#table-of-contents).
## Delete a wiki page
-You need at least the [Developer role](../../permissions.md) to delete a wiki page:
+You need at least the Developer role to delete a wiki page:
1. On the top bar, select **Menu**.
- For project wikis, select **Projects** and find your project.
@@ -169,7 +169,7 @@ You need at least the [Developer role](../../permissions.md) to delete a wiki pa
## Move a wiki page
-You need at least the [Developer role](../../permissions.md) to move a wiki page:
+You need at least the Developer role to move a wiki page:
1. On the top bar, select **Menu**.
- For project wikis, select **Projects** and find your project.
@@ -239,7 +239,7 @@ Commits to wikis are not counted in [repository analytics](../../analytics/repos
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23109) in GitLab 13.8, the sidebar can be customized by selecting the **Edit sidebar** button.
-You need at least the [Developer role](../../permissions.md) to customize the wiki
+You need at least the Developer role to customize the wiki
navigation sidebar. This process creates a wiki page named `_sidebar` which fully
replaces the default sidebar navigation:
@@ -323,9 +323,17 @@ 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)**
+## Content Editor
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5643) in GitLab 14.0.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5643) in GitLab 14.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345398) switching between editing experiences in GitLab 14.7 [with a flag](../../../administration/feature_flags.md) named `wiki_switch_between_content_editor_raw_markdown`. Enabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is available.
+To hide the feature, ask an administrator to
+[disable the feature flag](../../../administration/feature_flags.md) named
+`wiki_switch_between_content_editor_raw_markdown`.
+On GitLab.com, this feature is available.
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).
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index 61eca19a67b..9cfcaf4ee81 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -99,6 +99,8 @@ To create a blank project:
slug as the URL path to the project. To change the slug, first enter the project name,
then change the slug.
- In the **Project description (optional)** field, enter the description of your project's dashboard.
+ - In the **Project target (optional)** field, select your project's deployment target.
+ This information helps GitLab better understand its users and their deployment requirements.
- To modify the project's [viewing and access rights](../../public_access/public_access.md) for
users, change the **Visibility Level**.
- To create README file so that the Git repository is initialized, has a default branch, and
@@ -297,6 +299,29 @@ To delete a project:
1. Select **Delete project**
1. Confirm this action by completing the field.
+## Projects pending deletion **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37014) in GitLab 13.3 for Administrators.
+> - [Tab renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/347468) from **Deleted projects** in GitLab 14.6.
+> - [Available to all users](https://gitlab.com/gitlab-org/gitlab/-/issues/346976) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `project_owners_list_project_pending_deletion`. Enabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is available to all users. To make it available for administrators only,
+ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `project_owners_list_project_pending_deletion`.
+On GitLab.com, this feature is available to all users.
+
+When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-deletion),
+projects within that group are not deleted immediately, but only after a delay. To access a list of all projects that are pending deletion:
+
+1. On the top bar, select **Menu > Projects > Explore projects**.
+1. Select the **Pending deletion** tab (in GitLab 14.6 and later) or the **Deleted projects** tab (GitLab 14.5 and earlier).
+
+Listed for each project is:
+
+- The time the project was marked for deletion.
+- The time the project is scheduled for final deletion.
+- A **Restore** link to stop the project being eventually deleted.
+
## View project activity
To view the activity of a project:
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index 13fba126169..05579696d35 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -140,3 +140,28 @@ its performance:
| Issues | `global_search_issues_tab` | When enabled, the global search includes issues as part of the search. |
| Merge Requests | `global_search_merge_requests_tab` | When enabled, the global search includes merge requests as part of the search. |
| Wiki | `global_search_wiki_tab` | When enabled, the global search includes wiki as part of the search. [Group wikis](../project/wiki/group.md) are not included. |
+
+## Global Search validation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346263) in GitLab 14.6 [with a flag](../../administration/feature_flags.md) named `prevent_abusive_searches`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `prevent_abusive_searches`.
+ The feature is not ready for production use.
+
+To prevent abusive searches, such as searches that may result in a Distributed Denial of Service (DDoS), Global Search ignores, logs, and
+doesn't return any results for searches considered abusive according to the following criteria, if `prevent_abusive_searches` feature flag is enabled:
+
+- Searches with less than 2 characters.
+- Searches with any term greater than 100 characters. URL search terms have a maximum of 200 characters.
+- Searches with a stop word as the only term (ie: "the", "and", "if", etc.).
+- Searches with a `group_id` or `project_id` parameter that is not completely numeric.
+- Searches with a `repository_ref` or `project_ref` parameter that has special characters not allowed by [Git refname](https://git-scm.com/docs/git-check-ref-format).
+- Searches with a `scope` that is unknown.
+
+Regardless of the status of the `prevent_abusive_searches` feature flag, searches that don't
+comply with the criteria described below aren't logged as abusive but are flagged with an error:
+
+- Searches with more than 4096 characters.
+- Searches with more than 64 terms.
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 0e2be455a0c..0a799843d3c 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Search issues and merge requests
-To search through issues and merge requests in multiple projects, on the top bar, select the **Issues** or **Merge Requests** links.
+To search through issues and merge requests in multiple projects, on the top bar, select the **Issues** or **Merge requests** links.
The numbers indicate how many issues, merge requests, and to-do items are assigned to you:
@@ -32,24 +32,33 @@ in the search field in the upper right corner:
### Filter issue and merge request lists
-> - Filter by Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab Ultimate 12.9.
-> - Filter by child Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab Ultimate 13.0.
-> - Filter by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. Moved to GitLab Premium in 13.9.
+> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9.
+> - Filtering by child epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab 13.0.
+> - Filtering by iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. Moved from GitLab Ultimate to Premium in 13.9.
+> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default.
-Follow these steps to filter the **Issues** and **Merge Requests** list pages in projects and
+Follow these steps to filter the **Issues** and **Merge requests** list pages in projects and
groups:
1. Click in the field **Search or filter results...**.
1. In the dropdown menu that appears, select the attribute you wish to filter by:
- - Author
- Assignee
- - [Milestone](../project/milestones/index.md)
+ - Author
+ - Confidential
+ - [Epic and child Epic](../group/epics/index.md) (available only for the group the Epic was created, not for [higher group levels](https://gitlab.com/gitlab-org/gitlab/-/issues/233729)).
- [Iteration](../group/iterations/index.md)
- - Release
- [Label](../project/labels.md)
+ - [Milestone](../project/milestones/index.md)
- My-reaction
- - Confidential
- - [Epic and child Epic](../group/epics/index.md) (available only for the group the Epic was created, not for [higher group levels](https://gitlab.com/gitlab-org/gitlab/-/issues/233729)).
+ - Release
+ - Type
+
+ FLAG:
+ On self-managed GitLab, by default filtering by type is not available.
+ To make it available per group, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `vue_issues_list`.
+ On GitLab.com, this feature is not available.
+
+ - Weight
- Search for this text
1. Select or type the operator to use for filtering the attribute. The following operators are
available:
@@ -95,7 +104,7 @@ You can add this URL to your feed reader.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1.
-You can filter the **Issues** list to individual instances by their ID. For example, enter filter `#10` to return only issue 10. The same applies to the **Merge Requests** list. Enter filter `#30` to return only merge request 30.
+You can filter the **Issues** list to individual instances by their ID. For example, enter filter `#10` to return only issue 10. The same applies to the **Merge requests** list. Enter filter `#30` to return only merge request 30.
![filter issues by specific ID](img/issue_search_by_id.png)
@@ -270,8 +279,13 @@ search, or choose a specific group or project.
To search through code or other documents in a single project, you can use
the search field on the top-right of your screen while the project page is open.
-Code search shows only the first result in the file. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327052)
-in GitLab 14.7, you can access Git blame from any line that returned a result from the code search:
+Code search shows only the first result in the file.
+
+#### Git blame from code search **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327052) in GitLab 14.7.
+
+You can access Git blame from any line that returned a result from the code search:
![code search results](img/code_search.png)
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index d6cbbf352fc..ebaa5da8e05 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+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
type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html'
@@ -149,6 +149,57 @@ This shortcut is available when viewing a [wiki page](project/wiki/index.md):
|-------------------|-------------|
| <kbd>e</kbd> | Edit wiki page. |
+### Content editor
+
+These shortcuts are available when editing a file with the [Content Editor](https://about.gitlab.com/direction/create/editor/content_editor/):
+
+| Keyboard shortcut | Description |
+|-------------------|-------------|
+| <kbd>⌘</kbd> + <kbd>C</kbd> (Mac) / <kbd>Control</kbd> + <kbd>C</kbd> | Copy |
+| <kbd>⌘</kbd> + <kbd>X</kbd> (Mac) / <kbd>Control</kbd> + <kbd>X</kbd> | Cut |
+| <kbd>⌘</kbd> + <kbd>V</kbd> (Mac) / <kbd>Control</kbd> + <kbd>V</kbd> | Paste |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd> | Paste without formatting |
+| <kbd>⌘</kbd> + <kbd>Z</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Z</kbd> | Undo |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd> | Redo |
+| <kbd>Shift</kbd> + <kbd>Enter</kbd> | Add a line break |
+
+#### Formatting
+
+| Mac | Windows/Linux | Description |
+|-----|---------------|-------------|
+| <kbd>⌘</kbd> + <kbd>b</kbd> | <kbd>Control</kbd> + <kbd>b</kbd> | Bold |
+| <kbd>⌘</kbd> + <kbd>i</kbd> | <kbd>Control</kbd> + <kbd>i</kbd> | Italic |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>s</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>s</kbd> | Strikethrough |
+| <kbd>⌘</kbd> + <kbd>e</kbd> | <kbd>Control</kbd> + <kbd>e</kbd> | Code |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>0</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>0</kbd> | Apply normal text style |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>1</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>1</kbd> | Apply heading style 1 |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>2</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>2</kbd> | Apply heading style 2 |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>3</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>3</kbd> | Apply heading style 3 |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>4</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>4</kbd> | Apply heading style 4 |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>5</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>5</kbd> | Apply heading style 5 |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>6</kbd> | <kbd>Control</kbd> + <kbd>Alt</kbd> + <kbd>6</kbd> | Apply heading style 6 |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>7</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>7</kbd> | Ordered list |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>8</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>7</kbd> | Bullet list |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>9</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>7</kbd> | Task list |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>b</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>b</kbd> | Blockquote |
+| <kbd>⌘</kbd> + <kbd>Alt</kbd> + <kbd>c</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>c</kbd> | Code block |
+| <kbd>⌘</kbd> + <kbd>,</kbd> | <kbd>Control</kbd> + <kbd>,</kbd> | Subscript |
+| <kbd>⌘</kbd> + <kbd>.</kbd> | <kbd>Control</kbd> + <kbd>,</kbd> | Superscript |
+| <kbd>Tab</kbd> | | Indent list |
+| <kbd>Shift</kbd> + <kbd>Tab</kbd> | | Outdent list |
+
+#### Text selection
+
+| Keyboard shortcut | Description |
+|-------------------|-------------|
+| <kbd>⌘</kbd> + <kbd>a</kbd> (Mac) / <kbd>Control</kbd> + <kbd>a</kbd> | Select all |
+| <kbd>Shift</kbd> + <kbd>â†</kbd> | Extend selection one character to left |
+| <kbd>Shift</kbd> + <kbd>→</kbd> | Extend selection one character to right |
+| <kbd>Shift</kbd> + <kbd>↑</kbd> | Extend selection one line up |
+| <kbd>Shift</kbd> + <kbd>↓</kbd> | Extend selection one line down |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>↑</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>↑</kbd> | Extend selection to the beginning of the document |
+| <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>↓</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>↓</kbd> | Extend selection to the end of the document |
+
### Filtered search
These shortcuts are available when using a [filtered search input](search/index.md):
@@ -158,7 +209,7 @@ These shortcuts are available when using a [filtered search input](search/index.
| <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd> | Clear entire search filter. |
| <kbd>⌥</kbd> (Mac) / <kbd>Control</kbd> + <kbd>⌫</kbd> | Clear one token at a time. |
-## Epics **(ULTIMATE)**
+## Epics **(PREMIUM)**
These shortcuts are available when viewing [epics](group/epics/index.md):
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index 3272ff30e72..8cd9a47f3e6 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -58,7 +58,7 @@ User.where(confirmed_at: nil).where('LENGTH(confirmation_token) = 32')
## What does it look like when a user is blocked?
-A regular user might receive a message that says "You have to confirm your email address before continuing". This message could includes a 404 or 422 error code, when the user tries to sign in.
+A user might receive a message that says "You have to confirm your email address before continuing". This message could includes a 404 or 422 error code, when the user tries to sign in.
NOTE:
We hope to improve the [sign-in experience for an unverified user](https://gitlab.com/gitlab-org/gitlab/-/issues/29279) in a future release.
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 16b6424b232..75d10084328 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -49,7 +49,7 @@ The following storage usage statistics are available to an owner:
Excess storage usage is the amount that a project's repository exceeds the free storage quota. If no
purchased storage is available the project is locked. You cannot push changes to a locked project.
-To unlock a project you must [purchase more storage](../subscriptions/gitlab_com/index.md#purchase-more-storage)
+To unlock a project you must [purchase more storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer)
for the namespace. When the purchase is completed, locked projects are automatically unlocked. The
amount of purchased storage available must always be greater than zero.
diff --git a/doc/user/workspace/img/1.1-Instance_overview.png b/doc/user/workspace/img/1.1-Instance_overview.png
deleted file mode 100644
index a3c642cda3f..00000000000
--- a/doc/user/workspace/img/1.1-Instance_overview.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/workspace/img/1.2-Groups_overview.png b/doc/user/workspace/img/1.2-Groups_overview.png
deleted file mode 100644
index 7771e5f4c3c..00000000000
--- a/doc/user/workspace/img/1.2-Groups_overview.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/workspace/img/1.3-Admin.png b/doc/user/workspace/img/1.3-Admin.png
deleted file mode 100644
index 5f531e4ef5e..00000000000
--- a/doc/user/workspace/img/1.3-Admin.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/workspace/img/Admin_Settings.png b/doc/user/workspace/img/Admin_Settings.png
deleted file mode 100644
index b0d13f43ccb..00000000000
--- a/doc/user/workspace/img/Admin_Settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/workspace/img/hardware_settings.png b/doc/user/workspace/img/hardware_settings.png
deleted file mode 100644
index 919ff46f8c8..00000000000
--- a/doc/user/workspace/img/hardware_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index cf35f082880..0befcbe25d2 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -14,6 +14,9 @@ As with all projects, the items mentioned on this page are subject to change or
The development, release, and timing of any products, features, or functionality remain at the
sole discretion of GitLab Inc.
+NOTE:
+Workspace is currently in development.
+
Workspace will be above the [top-level namespaces](../group/index.md#namespaces) for you to manage
everything you do as a GitLab administrator, including:
@@ -27,33 +30,12 @@ Our goal is to reach feature parity between SaaS and self-managed installations,
- Hardware Controls. For functionality that does not apply to groups, Hardware Controls are only
applicable to self-managed installations. There is one Hardware Controls section per installation.
-NOTE:
-Workspace is currently in development.
-
-## Demo: New hierarchy concept for groups and projects for epics
-
-The following demo introduces the new hierarchy concept for groups and projects for epics.
-
-<div class="video-fallback">
- See the video: <a href="https://www.youtube.com/embed/fE74lsG_8yM">Consolidating groups and projects update (2021-08-23)</a>.
-</div>
-<figure class="video-container">
- <iframe src="https://www.youtube.com/embed/fE74lsG_8yM" frameborder="0" allowfullscreen="true"> </iframe>
-</figure>
-
-## Concept previews
-
-The following provide a preview to the Workspace concept.
-
-![Workspace Overview](img/1.1-Instance_overview.png)
-
-![Groups Overview](img/1.2-Groups_overview.png)
-
-![Admin Overview](img/1.3-Admin.png)
-
-![Admin Overview](img/Admin_Settings.png)
+To learn about the current state of workspace development,
+see [epic 4257](https://gitlab.com/groups/gitlab-org/-/epics/4257).
-![Admin Overview](img/hardware_settings.png)
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a video introduction to the new hierarchy concept for groups and projects for epics, see
+[Consolidating groups and projects update (August 2021)](https://www.youtube.com/watch?v=fE74lsG_8yM).
## Related topics
diff --git a/lefthook.yml b/lefthook.yml
index c5c51b53fb3..ce4aa14ea69 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -54,3 +54,13 @@ pre-push:
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
glob: 'doc/*.md'
run: scripts/lint-docs-metadata.sh {files}
+ docs-deprecations:
+ tags: documentation
+ files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
+ glob: 'data/deprecations/*.yml'
+ run: echo "Changes to deprecation files detected. Checking deprecations..\n"; bundle exec rake gitlab:docs:check_deprecations
+ docs-removals:
+ tags: documentation
+ files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
+ glob: 'data/removals/**/*.yml'
+ run: echo "Changes to removals files detected. Checking removals..\n"; bundle exec rake gitlab:docs:check_removals
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 5984879413f..5100ec9ec9d 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -76,6 +76,10 @@ module API
Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
end
+ after do
+ Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
+ end
+
# The locale is set to the current user's locale when `current_user` is loaded
after { Gitlab::I18n.use_default_locale }
@@ -171,6 +175,7 @@ module API
mount ::API::Ci::ResourceGroups
mount ::API::Ci::Runner
mount ::API::Ci::Runners
+ mount ::API::Ci::SecureFiles
mount ::API::Ci::Triggers
mount ::API::Ci::Variables
mount ::API::Commits
@@ -300,6 +305,7 @@ module API
mount ::API::Internal::Pages
mount ::API::Internal::Kubernetes
mount ::API::Internal::MailRoom
+ mount ::API::Internal::ContainerRegistry::Migration
version 'v3', using: :path do
# Although the following endpoints are kept behind V3 namespace,
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 462c4a3de4c..a2c9020ac84 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -24,7 +24,7 @@ module API
helpers do
params :filter_params do
optional :search, type: String, desc: 'Return list of branches matching the search criteria'
- optional :sort, type: String, desc: 'Return list of branches sorted by the given field'
+ optional :sort, type: String, desc: 'Return list of branches sorted by the given field', values: %w[name_asc updated_asc updated_desc]
end
end
@@ -42,9 +42,7 @@ module API
optional :page_token, type: String, desc: 'Name of branch to start the paginaition from'
end
get ':id/repository/branches', urgency: :low do
- ff_enabled = Feature.enabled?(:api_caching_rate_limit_branches, user_project, default_enabled: :yaml)
-
- cache_action_if(ff_enabled, [user_project, :branches, current_user, declared_params], expires_in: 30.seconds) do
+ cache_action([user_project, :branches, current_user, declared_params], expires_in: 30.seconds) do
user_project.preload_protected_branches
repository = user_project.repository
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb
index ca76d2664f8..9f59eea5013 100644
--- a/lib/api/ci/job_artifacts.rb
+++ b/lib/api/ci/job_artifacts.rb
@@ -47,7 +47,7 @@ module API
requires :artifact_path, type: String, desc: 'Artifact path'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/artifacts/:ref_name/raw/*artifact_path',
+ get ':id/jobs/artifacts/:ref_name/raw/*artifact_path', urgency: :low,
format: false,
requirements: { ref_name: /.+/ } do
authorize_download_artifacts!
@@ -70,7 +70,7 @@ module API
requires :job_id, type: Integer, desc: 'The ID of a job'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/:job_id/artifacts' do
+ get ':id/jobs/:job_id/artifacts', urgency: :low do
authorize_download_artifacts!
build = find_build!(params[:job_id])
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 4e5d6c264bf..e0086f624a8 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -179,7 +179,7 @@ module API
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
- get ':id/pipelines/:pipeline_id/test_report', feature_category: :code_testing do
+ get ':id/pipelines/:pipeline_id/test_report', feature_category: :code_testing, urgency: :low do
authorize! :read_build, pipeline
present pipeline.test_reports, with: TestReportEntity, details: true
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index fef6a7891c2..4df9600322c 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -15,20 +15,29 @@ module API
params do
requires :token, type: String, desc: 'Registration token'
optional :description, type: String, desc: %q(Runner's description)
- optional :maintainer_note, type: String, desc: %q(Runner's maintainer notes)
+ optional :maintainer_note, type: String, desc: %q(Deprecated: Use :maintenance_note instead. Runner's maintenance notes)
+ optional :maintenance_note, type: String, desc: %q(Runner's maintenance notes)
optional :info, type: Hash, desc: %q(Runner's metadata)
- optional :active, type: Boolean, desc: 'Should Runner be active'
- optional :locked, type: Boolean, desc: 'Should Runner be locked for current project'
+ optional :active, type: Boolean, desc: 'Deprecated: Use `:paused` instead. Should runner be active'
+ optional :paused, type: Boolean, desc: 'Whether the runner should ignore new jobs'
+ optional :locked, type: Boolean, desc: 'Whether the runner should be locked for current project'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
- desc: 'The access_level of the runner'
- optional :run_untagged, type: Boolean, desc: 'Should Runner handle untagged jobs'
+ desc: 'The access_level of the runner; `not_protected` or `ref_protected`'
+ optional :run_untagged, type: Boolean, desc: 'Whether the runner should handle untagged jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: %q(List of Runner's tags)
- optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
+ optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this runner handles the job'
+ mutually_exclusive :maintainer_note, :maintainer_note
+ mutually_exclusive :active, :paused
end
post '/', feature_category: :runner do
- attributes = attributes_for_keys(%i[description maintainer_note active locked run_untagged tag_list access_level maximum_timeout])
+ attributes = attributes_for_keys(%i[description maintainer_note maintenance_note active paused locked run_untagged tag_list access_level maximum_timeout])
.merge(get_runner_details_from_request)
+ # Pull in deprecated maintainer_note if that's the only note value available
+ deprecated_note = attributes.delete(:maintainer_note)
+ attributes[:maintenance_note] ||= deprecated_note if deprecated_note
+ attributes[:active] = !attributes.delete(:paused) if attributes.include?(:paused)
+
@runner = ::Ci::RegisterRunnerService.new.execute(params[:token], attributes)
forbidden! unless @runner
@@ -48,7 +57,7 @@ module API
delete '/', feature_category: :runner do
authenticate_runner!
- destroy_conditionally!(current_runner)
+ destroy_conditionally!(current_runner) { ::Ci::UnregisterRunnerService.new(current_runner).execute }
end
desc 'Validates authentication credentials' do
@@ -235,7 +244,7 @@ module API
optional :artifact_type, type: String, desc: %q(The type of artifact),
default: 'archive', values: ::Ci::JobArtifact.file_types.keys
end
- post '/:id/artifacts/authorize', feature_category: :build_artifacts do
+ post '/:id/artifacts/authorize', feature_category: :build_artifacts, urgency: :low do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
@@ -271,7 +280,7 @@ module API
default: 'zip', values: ::Ci::JobArtifact.file_formats.keys
optional :metadata, type: ::API::Validations::Types::WorkhorseFile, desc: %(The artifact metadata to store (generated by Multipart middleware))
end
- post '/:id/artifacts', feature_category: :build_artifacts do
+ post '/:id/artifacts', feature_category: :build_artifacts, urgency: :low do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index f21782a698f..8a7ffab97dd 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -18,6 +18,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -26,9 +27,7 @@ module API
get do
runners = current_user.ci_owned_runners
runners = filter_runners(runners, params[:scope], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
- runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
+ runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
end
@@ -41,6 +40,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -51,9 +51,7 @@ module API
runners = ::Ci::Runner.all
runners = filter_runners(runners, params[:scope])
- runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
- runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
+ runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
end
@@ -77,18 +75,21 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of the runner'
optional :description, type: String, desc: 'The description of the runner'
- optional :active, type: Boolean, desc: 'The state of a runner'
+ optional :active, type: Boolean, desc: 'Deprecated: Use `:paused` instead. Flag indicating whether the runner is allowed to receive jobs'
+ optional :paused, type: Boolean, desc: 'Flag indicating whether the runner should ignore new jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of tags for a runner'
- optional :run_untagged, type: Boolean, desc: 'Flag indicating the runner can execute untagged jobs'
+ optional :run_untagged, type: Boolean, desc: 'Flag indicating whether the runner can execute untagged jobs'
optional :locked, type: Boolean, desc: 'Flag indicating the runner is locked'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
desc: 'The access_level of the runner'
optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
- at_least_one_of :description, :active, :tag_list, :run_untagged, :locked, :access_level, :maximum_timeout
+ at_least_one_of :description, :active, :paused, :tag_list, :run_untagged, :locked, :access_level, :maximum_timeout
+ mutually_exclusive :active, :paused
end
put ':id' do
runner = get_runner(params.delete(:id))
authenticate_update_runner!(runner)
+ params[:active] = !params.delete(:paused) if params.include?(:paused)
update_service = ::Ci::UpdateRunnerService.new(runner)
if update_service.update(declared_params(include_missing: false))
@@ -109,7 +110,7 @@ module API
authenticate_delete_runner!(runner)
- destroy_conditionally!(runner)
+ destroy_conditionally!(runner) { ::Ci::UnregisterRunnerService.new(runner).execute }
end
desc 'List jobs running on a runner' do
@@ -142,7 +143,7 @@ module API
authenticate_update_runner!(runner)
runner.reset_token!
- present runner.token, with: Entities::Ci::ResetTokenResult
+ present runner.token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -160,6 +161,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -223,18 +225,14 @@ module API
params do
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
use :pagination
end
get ':id/runners' do
- runners = if ::Feature.enabled?(:ci_find_runners_by_ci_mirrors, user_group, default_enabled: :yaml)
- ::Ci::Runner.belonging_to_group_and_ancestors(user_group.id)
- else
- ::Ci::Runner.legacy_belonging_to_group(user_group.id, include_ancestors: true)
- end
-
+ runners = ::Ci::Runner.group_or_instance_wide(user_group)
runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
@@ -251,7 +249,7 @@ module API
authorize! :update_runners_registration_token
ApplicationSetting.current.reset_runners_registration_token!
- present ApplicationSetting.current_without_cache.runners_registration_token, with: Entities::Ci::ResetTokenResult
+ present ApplicationSetting.current_without_cache.runners_registration_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -269,7 +267,7 @@ module API
authorize! :update_runners_registration_token, project
project.reset_runners_token!
- present project.runners_token, with: Entities::Ci::ResetTokenResult
+ present project.runners_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -287,7 +285,7 @@ module API
authorize! :update_runners_registration_token, group
group.reset_runners_token!
- present group.runners_token, with: Entities::Ci::ResetTokenResult
+ present group.runners_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -310,6 +308,7 @@ module API
def apply_filter(runners, params)
runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
+ runners = filter_runners(runners, params[:paused] ? 'paused' : 'active', allowed_scopes: %w[paused active]) if params.include?(:paused)
runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
runners
diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb
new file mode 100644
index 00000000000..715a8b37fae
--- /dev/null
+++ b/lib/api/ci/secure_files.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module API
+ module Ci
+ class SecureFiles < ::API::Base
+ include PaginationParams
+
+ before do
+ authenticate!
+ authorize! :admin_build, user_project
+ feature_flag_enabled?
+ end
+
+ feature_category :pipeline_authoring
+
+ default_format :json
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'List all Secure Files for a Project'
+ params do
+ use :pagination
+ end
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files' do
+ secure_files = user_project.secure_files
+ present paginate(secure_files), with: Entities::Ci::SecureFile
+ end
+
+ desc 'Get an individual Secure File'
+ params do
+ requires :id, type: Integer, desc: 'The Secure File ID'
+ end
+
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files/:secure_file_id' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+ present secure_file, with: Entities::Ci::SecureFile
+ end
+
+ desc 'Download a Secure File'
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files/:secure_file_id/download' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+
+ content_type 'application/octet-stream'
+ env['api.format'] = :binary
+ header['Content-Disposition'] = "attachment; filename=#{secure_file.name}"
+ body secure_file.file.read
+ end
+
+ desc 'Upload a Secure File'
+ params do
+ requires :name, type: String, desc: 'The name of the file'
+ requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file to be uploaded'
+ optional :permissions, type: String, desc: 'The file permissions', default: 'read_only', values: %w[read_only read_write execute]
+ end
+
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ post ':id/secure_files' do
+ secure_file = user_project.secure_files.new(
+ name: params[:name],
+ permissions: params[:permissions] || :read_only
+ )
+
+ secure_file.file = params[:file]
+
+ file_too_large! unless secure_file.file.size < ::Ci::SecureFile::FILE_SIZE_LIMIT.to_i
+
+ if secure_file.save
+ present secure_file, with: Entities::Ci::SecureFile
+ else
+ render_validation_error!(secure_file)
+ end
+ end
+
+ desc 'Delete an individual Secure File'
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ delete ':id/secure_files/:secure_file_id' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+
+ secure_file.destroy!
+
+ no_content!
+ end
+ end
+
+ helpers do
+ def feature_flag_enabled?
+ service_unavailable! unless Feature.enabled?(:ci_secure_files, user_project, default_enabled: :yaml)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 486ff5d89bc..6939853c06b 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -47,7 +47,7 @@ module API
desc 'Gets a specific deployment' do
detail 'This feature was introduced in GitLab 8.11.'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :deployment_id, type: Integer, desc: 'The deployment ID'
@@ -57,12 +57,12 @@ module API
deployment = user_project.deployments.find(params[:deployment_id])
- present deployment, with: Entities::Deployment
+ present deployment, with: Entities::DeploymentExtended
end
desc 'Creates a new deployment' do
detail 'This feature was introduced in GitLab 12.4'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :environment,
@@ -106,7 +106,7 @@ module API
deployment = service.execute
if deployment.persisted?
- present(deployment, with: Entities::Deployment, current_user: current_user)
+ present(deployment, with: Entities::DeploymentExtended, current_user: current_user)
else
render_validation_error!(deployment)
end
@@ -114,7 +114,7 @@ module API
desc 'Updates an existing deployment' do
detail 'This feature was introduced in GitLab 12.4'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :status,
@@ -136,7 +136,7 @@ module API
service = ::Deployments::UpdateService.new(deployment, declared_params)
if service.execute
- present(deployment, with: Entities::Deployment, current_user: current_user)
+ present(deployment, with: Entities::DeploymentExtended, current_user: current_user)
else
render_validation_error!(deployment)
end
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 0709a8c2036..f73e4b621ab 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -252,7 +252,7 @@ module API
.fresh
# Without RendersActions#prepare_notes_for_rendering,
- # Note#system_note_with_references_visible_for? will attempt to render
+ # Note#system_note_visible_for? will attempt to render
# Markdown references mentioned in the note to see whether they
# should be redacted. For notes that reference a commit, this
# would also incur a Gitaly call to verify the commit exists.
diff --git a/lib/api/entities/ci/reset_token_result.rb b/lib/api/entities/ci/reset_token_result.rb
index 4dbf831582b..f0b1de6a5a7 100644
--- a/lib/api/entities/ci/reset_token_result.rb
+++ b/lib/api/entities/ci/reset_token_result.rb
@@ -4,7 +4,8 @@ module API
module Entities
module Ci
class ResetTokenResult < Grape::Entity
- expose(:token) {|object| object}
+ expose(:token)
+ expose(:token_expires_at, if: -> (object, options) { object.expirable? })
end
end
end
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index c17ff513479..a6944b8c925 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -7,7 +7,10 @@ module API
expose :id
expose :description
expose :ip_address
- expose :active
+ expose :active # TODO Remove in %15.0 in favor of `paused` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/351109
+ expose :paused do |runner|
+ !runner.active
+ end
expose :instance_type?, as: :is_shared
expose :runner_type
expose :name
diff --git a/lib/api/entities/ci/runner_details.rb b/lib/api/entities/ci/runner_details.rb
index 6ded1296f2a..9b1decca274 100644
--- a/lib/api/entities/ci/runner_details.rb
+++ b/lib/api/entities/ci/runner_details.rb
@@ -15,18 +15,18 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
expose :projects, with: Entities::BasicProjectDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ runner.projects
else
- options[:current_user].authorized_projects.where(id: runner.projects).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ options[:current_user].authorized_projects.where(id: runner.runner_projects.pluck(:project_id))
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
expose :groups, with: Entities::BasicGroupDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.groups.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ runner.groups
else
- options[:current_user].authorized_groups.where(id: runner.groups).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ options[:current_user].authorized_groups.where(id: runner.runner_namespaces.pluck(:namespace_id))
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/entities/ci/runner_registration_details.rb b/lib/api/entities/ci/runner_registration_details.rb
index fa7e44c9e40..53be918406f 100644
--- a/lib/api/entities/ci/runner_registration_details.rb
+++ b/lib/api/entities/ci/runner_registration_details.rb
@@ -4,7 +4,7 @@ module API
module Entities
module Ci
class RunnerRegistrationDetails < Grape::Entity
- expose :id, :token
+ expose :id, :token, :token_expires_at
end
end
end
diff --git a/lib/api/entities/ci/secure_file.rb b/lib/api/entities/ci/secure_file.rb
new file mode 100644
index 00000000000..041c864156b
--- /dev/null
+++ b/lib/api/entities/ci/secure_file.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class SecureFile < Grape::Entity
+ expose :id
+ expose :name
+ expose :permissions
+ expose :checksum
+ expose :checksum_algorithm
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/deployment_extended.rb b/lib/api/entities/deployment_extended.rb
new file mode 100644
index 00000000000..74cfb61388b
--- /dev/null
+++ b/lib/api/entities/deployment_extended.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class DeploymentExtended < Deployment
+ end
+ end
+end
+
+API::Entities::DeploymentExtended.prepend_mod
diff --git a/lib/api/entities/user_safe.rb b/lib/api/entities/user_safe.rb
index 6006a076020..c7349026a88 100644
--- a/lib/api/entities/user_safe.rb
+++ b/lib/api/entities/user_safe.rb
@@ -7,7 +7,7 @@ module API
expose :name do |user|
next user.name unless user.project_bot?
- next user.name if options[:current_user]&.can?(:read_resource_access_tokens, user.projects.first)
+ next user.name if options[:current_user]&.can?(:read_project, user.projects.first)
# If the requester does not have permission to read the project bot name,
# the API returns an arbitrary string. UI changes will be addressed in a follow up issue:
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index d3d1f03585b..5fbf222be5d 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -84,10 +84,11 @@ module API
paginate(projects)
end
- def present_projects(params, projects)
+ def present_projects(params, projects, single_hierarchy: false)
options = {
with: params[:simple] ? Entities::BasicProjectDetails : Entities::Project,
- current_user: current_user
+ current_user: current_user,
+ single_hierarchy: single_hierarchy
}
projects, options = with_custom_attributes(projects, options)
@@ -292,6 +293,7 @@ module API
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
optional :with_shared, type: Boolean, default: true, desc: 'Include projects shared to this group'
optional :include_subgroups, type: Boolean, default: false, desc: 'Includes projects in subgroups of this group'
+ optional :include_ancestor_groups, type: Boolean, default: false, desc: 'Includes projects in ancestors of this group'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user on projects'
use :pagination
@@ -301,12 +303,13 @@ module API
get ":id/projects" do
finder_options = {
only_owned: !params[:with_shared],
- include_subgroups: params[:include_subgroups]
+ include_subgroups: params[:include_subgroups],
+ include_ancestor_groups: params[:include_ancestor_groups]
}
projects = find_group_projects(params, finder_options)
- present_projects(params, projects)
+ present_projects(params, projects, single_hierarchy: true)
end
desc 'Get a list of shared projects in this group' do
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 76840091112..184fe7868a5 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -117,6 +117,8 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_project(id)
+ return unless id
+
projects = Project.without_deleted
if id.is_a?(Integer) || id =~ /^\d+$/
@@ -561,7 +563,7 @@ module API
def increment_counter(event_name)
feature_name = "usage_data_#{event_name}"
- return unless Feature.enabled?(feature_name)
+ return unless Feature.enabled?(feature_name, default_enabled: :yaml)
Gitlab::UsageDataCounters.count(event_name)
rescue StandardError => error
diff --git a/lib/api/helpers/container_registry_helpers.rb b/lib/api/helpers/container_registry_helpers.rb
index 9c844e364eb..78daf2c8cb1 100644
--- a/lib/api/helpers/container_registry_helpers.rb
+++ b/lib/api/helpers/container_registry_helpers.rb
@@ -6,7 +6,7 @@ module API
extend ActiveSupport::Concern
included do
- rescue_from Faraday::Error, ContainerRegistry::Path::InvalidRegistryPathError do |e|
+ rescue_from Faraday::Error, ::ContainerRegistry::Path::InvalidRegistryPathError do |e|
service_unavailable!('We are having trouble connecting to the Container Registry. If this error persists, please review the troubleshooting documentation.')
end
end
diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb
index 72b16a23dd6..86dedc12fca 100644
--- a/lib/api/helpers/integrations_helpers.rb
+++ b/lib/api/helpers/integrations_helpers.rb
@@ -346,7 +346,13 @@ module API
required: false,
name: :datadog_env,
type: String,
- desc: 'For self-managed deployments, set the env tag for all the data sent to Datadog. How do I use tags?'
+ desc: 'For self-managed deployments, set the env tag for all the data sent to Datadog'
+ },
+ {
+ required: false,
+ name: :datadog_tags,
+ type: String,
+ desc: 'Custom tags in Datadog. Specify one tag per line in the format: "key:value\nkey2:value2"'
}
],
'discord' => [
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index e03f029a6ef..46685df0989 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -124,7 +124,8 @@ module API
repository: repository.gitaly_repository.to_h,
address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(repository.shard),
- features: Feature::Gitaly.server_feature_flags(repository.project)
+ features: Feature::Gitaly.server_feature_flags(repository.project),
+ use_sidechannel: Feature.enabled?(:gitlab_shell_upload_pack_sidechannel, repository.project, default_enabled: :yaml)
}
end
end
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 6c20993431d..f26ac1318b1 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -23,7 +23,7 @@ module API
def retrieve_members(source, params:, deep: false)
members = deep ? find_all_members(source) : source_members(source).connected_to_user
members = members.includes(:user)
- members = members.references(:user).merge(User.search(params[:query])) if params[:query].present?
+ members = members.references(:user).merge(User.search(params[:query], use_minimum_char_limit: false)) if params[:query].present?
members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?
members
end
diff --git a/lib/api/helpers/merge_requests_helpers.rb b/lib/api/helpers/merge_requests_helpers.rb
index f8fe40f7135..00d9f49adf0 100644
--- a/lib/api/helpers/merge_requests_helpers.rb
+++ b/lib/api/helpers/merge_requests_helpers.rb
@@ -47,9 +47,9 @@ module API
desc: 'Return opened, closed, locked, merged, or all merge requests'
optional :order_by,
type: String,
- values: %w[created_at updated_at],
+ values: Helpers::MergeRequestsHelpers.sort_options,
default: 'created_at',
- desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
+ desc: "Return merge requests ordered by #{Helpers::MergeRequestsHelpers.sort_options_help} fields."
optional :sort,
type: String,
values: %w[asc desc],
@@ -115,6 +115,22 @@ module API
render_validation_error!(merge_request)
end
+
+ def self.sort_options
+ %w[
+ created_at
+ label_priority
+ milestone_due
+ popularity
+ priority
+ title
+ updated_at
+ ]
+ end
+
+ def self.sort_options_help
+ sort_options.map {|y| "`#{y}`" }.to_sentence(last_word_connector: ' or ')
+ end
end
end
end
diff --git a/lib/api/helpers/rate_limiter.rb b/lib/api/helpers/rate_limiter.rb
index 0ad4f089907..03f3cd649b1 100644
--- a/lib/api/helpers/rate_limiter.rb
+++ b/lib/api/helpers/rate_limiter.rb
@@ -5,7 +5,7 @@ module API
# == RateLimiter
#
# Helper that checks if the rate limit for a given endpoint is throttled by calling the
- # Gitlab::ApplicationRateLimiter class. If the action is throttled for the current user, the request
+ # Gitlab::ApplicationRateLimiter module. If the action is throttled for the current user, the request
# will be logged and an error message will be rendered with a Too Many Requests response status.
# See app/controllers/concerns/check_rate_limit.rb for Rails controllers version
module RateLimiter
diff --git a/lib/api/internal/container_registry/migration.rb b/lib/api/internal/container_registry/migration.rb
new file mode 100644
index 00000000000..b84e14c6f31
--- /dev/null
+++ b/lib/api/internal/container_registry/migration.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module API
+ module Internal
+ module ContainerRegistry
+ class Migration < ::API::Base
+ feature_category :container_registry
+
+ STATUS_PRE_IMPORT_COMPLETE = 'pre_import_complete'
+ STATUS_PRE_IMPORT_FAILED = 'pre_import_failed'
+ STATUS_IMPORT_COMPLETE = 'import_complete'
+ STATUS_IMPORT_FAILED = 'import_failed'
+ POSSIBLE_VALUES = [
+ STATUS_PRE_IMPORT_COMPLETE,
+ STATUS_PRE_IMPORT_FAILED,
+ STATUS_IMPORT_COMPLETE,
+ STATUS_IMPORT_FAILED
+ ].freeze
+
+ before { authenticate! }
+
+ helpers do
+ def authenticate!
+ secret_token = Gitlab.config.registry.notification_secret
+
+ unauthorized! unless Devise.secure_compare(secret_token, headers['Authorization'])
+ end
+
+ def find_repository!(path)
+ ::ContainerRepository.find_by_path!(::ContainerRegistry::Path.new(path))
+ end
+ end
+
+ params do
+ requires :repository_path, type: String, desc: 'The container repository path'
+ requires :status, type: String, values: POSSIBLE_VALUES, desc: 'The migration step status'
+ end
+ put 'internal/registry/repositories/*repository_path/migration/status' do
+ repository = find_repository!(declared_params[:repository_path])
+
+ unless repository.migration_in_active_state?
+ bad_request!("Wrong migration state (#{repository.migration_state})")
+ end
+
+ case declared_params[:status]
+ when STATUS_PRE_IMPORT_COMPLETE
+ unless repository.finish_pre_import_and_start_import
+ bad_request!("Couldn't transition from pre_importing to importing")
+ end
+ when STATUS_IMPORT_COMPLETE
+ unless repository.finish_import
+ bad_request!("Couldn't transition from importing to import_done")
+ end
+ when STATUS_IMPORT_FAILED, STATUS_PRE_IMPORT_FAILED
+ repository.abort_import
+ end
+
+ status 200
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 46124a74e9d..a5d6a6d7cf3 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -80,7 +80,7 @@ module API
desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return issues sorted in `asc` or `desc` order.'
- optional :due_date, type: String, values: %w[0 overdue week month next_month_and_previous_two_weeks] << '',
+ optional :due_date, type: String, values: %w[0 any today tomorrow overdue week month next_month_and_previous_two_weeks] << '',
desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}"
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index bfd457a3092..6de78c81cac 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -42,14 +42,18 @@ module API
params do
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
+ optional :ref, type: String, desc: 'Branch or tag used to execute a dry run. Defaults to the default branch of the project. Only used when dry_run is true'
end
get ':id/ci/lint', urgency: :low do
authorize! :download_code, user_project
- content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default)
+ if user_project.commit.present?
+ content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default)
+ end
+
result = Gitlab::Ci::Lint
.new(project: user_project, current_user: current_user)
- .validate(content, dry_run: params[:dry_run])
+ .validate(content, dry_run: params[:dry_run], ref: params[:ref] || user_project.default_branch)
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
end
@@ -63,13 +67,14 @@ module API
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
+ optional :ref, type: String, desc: 'Branch or tag used to execute a dry run. Defaults to the default branch of the project. Only used when dry_run is true'
end
post ':id/ci/lint', urgency: :low do
authorize! :create_pipeline, user_project
result = Gitlab::Ci::Lint
.new(project: user_project, current_user: current_user)
- .validate(params[:content], dry_run: params[:dry_run])
+ .validate(params[:content], dry_run: params[:dry_run], ref: params[:ref] || user_project.default_branch)
status 200
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 3f39af7f909..f7df8d33418 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -117,6 +117,9 @@ module API
forbidden!('Cannot push to source branch') unless
user_access.can_push_to_branch?(merge_request.source_branch)
+
+ forbidden!('Source branch is protected from force push') unless
+ merge_request.permits_force_push?
end
params :merge_requests_params do
@@ -204,11 +207,7 @@ module API
options = serializer_options_for(merge_requests).merge(project: user_project)
options[:project] = user_project
- if Feature.enabled?(:api_caching_merge_requests, user_project, type: :development, default_enabled: :yaml)
- present_cached merge_requests, expires_in: 2.days, **options
- else
- present merge_requests, options
- end
+ present_cached merge_requests, expires_in: 2.days, **options
end
desc 'Create a merge request' do
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index 3bf47fe1e8b..e80355e80c7 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -28,13 +28,8 @@ module API
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- package_files = package_files.preload_pipelines
+ package_files = package.installable_package_files
+ .preload_pipelines
present paginate(package_files), with: ::API::Entities::PackageFile
end
@@ -55,13 +50,8 @@ module API
not_found! unless package
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- package_file = package_files.find_by_id(params[:package_file_id])
+ package_file = package.installable_package_files
+ .find_by_id(params[:package_file_id])
not_found! unless package_file
diff --git a/lib/api/pagination_params.rb b/lib/api/pagination_params.rb
index a232b58d3f7..85ac50d5bec 100644
--- a/lib/api/pagination_params.rb
+++ b/lib/api/pagination_params.rb
@@ -18,7 +18,7 @@ module API
helpers do
params :pagination do
optional :page, type: Integer, default: 1, desc: 'Current page number'
- optional :per_page, type: Integer, default: 20, desc: 'Number of items per page'
+ optional :per_page, type: Integer, default: 20, desc: 'Number of items per page', except_values: [0]
end
end
end
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 7bdcaa5a26f..a3d76e571a9 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -133,7 +133,7 @@ module API
success Entities::ProjectImportStatus
end
post 'remote-import' do
- not_found! unless ::Feature.enabled?(:import_project_from_remote_file)
+ not_found! unless ::Feature.enabled?(:import_project_from_remote_file, default_enabled: :yaml)
check_rate_limit! :project_import, scope: [current_user, :project_import]
diff --git a/lib/api/projects_relation_builder.rb b/lib/api/projects_relation_builder.rb
index a4bd06aec10..aabecb43653 100644
--- a/lib/api/projects_relation_builder.rb
+++ b/lib/api/projects_relation_builder.rb
@@ -13,6 +13,7 @@ module API
preload_repository_cache(projects_relation)
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]
+ Preloaders::SingleHierarchyProjectGroupPlansPreloader.new(projects_relation).execute if options[:single_hierarchy]
projects_relation
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index fc976c23726..c3632c812f3 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -171,7 +171,6 @@ module API
optional :straight, type: Boolean, desc: 'Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)', default: false
end
get ':id/repository/compare', urgency: :low do
- ff_enabled = Feature.enabled?(:api_caching_rate_limit_repository_compare, user_project, default_enabled: :yaml)
target_project = fetch_target_project(current_user, user_project, params)
if target_project.blank?
@@ -180,7 +179,7 @@ module API
cache_key = compare_cache_key(current_user, user_project, target_project, declared_params)
- cache_action_if(ff_enabled, cache_key, expires_in: 1.minute) do
+ cache_action(cache_key, expires_in: 1.minute) do
compare = CompareService.new(user_project, params[:to]).execute(target_project, params[:from], straight: params[:straight])
if compare
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index 3effa370e84..6ac5ad0518b 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -69,9 +69,7 @@ module API
package_files = ::Packages::PackageFile
.for_rubygem_with_file_name(user_project, params[:file_name])
- package_files = package_files.installable if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
-
- package_file = package_files.last!
+ package_file = package_files.installable.last!
track_package_event('pull_package', :rubygems, project: user_project, namespace: user_project.namespace)
diff --git a/lib/api/scope.rb b/lib/api/scope.rb
index 707775e5d15..62aefcceb4b 100644
--- a/lib/api/scope.rb
+++ b/lib/api/scope.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
# Encapsulate a scope used for authorization, such as `api`, or `read_user`
+# See Gitlab::Auth for the set of available scopes, and their purposes.
module API
class Scope
attr_reader :name, :if
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 508ccdb4b33..b256432fbf1 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -177,6 +177,10 @@ module API
optional :floc_enabled, type: Grape::API::Boolean, desc: 'Enable FloC (Federated Learning of Cohorts)'
optional :user_deactivation_emails_enabled, type: Boolean, desc: 'Send emails to users upon account deactivation'
optional :suggest_pipeline_enabled, type: Boolean, desc: 'Enable pipeline suggestion banner'
+ optional :users_get_by_id_limit, type: Integer, desc: "Maximum number of calls to the /users/:id API per 10 minutes per user. Set to 0 for unlimited requests."
+ optional :runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for shared runners, in seconds'
+ optional :group_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for group runners, in seconds'
+ optional :project_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for project runners, in seconds'
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",
diff --git a/lib/api/support/token_with_expiration.rb b/lib/api/support/token_with_expiration.rb
new file mode 100644
index 00000000000..2cbd562c608
--- /dev/null
+++ b/lib/api/support/token_with_expiration.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module API
+ module Support
+ class TokenWithExpiration
+ def initialize(strategy, instance)
+ @strategy = strategy
+ @instance = instance
+ end
+
+ def token
+ @strategy.get_token(@instance)
+ end
+
+ def token_expires_at
+ @strategy.expires_at(@instance)
+ end
+
+ def expirable?
+ @strategy.expirable?
+ end
+ end
+ end
+end
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 1b37d38ef06..0fa8c21f8d7 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -33,11 +33,7 @@ module API
paginated_tags = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(tags_finder)
- if Feature.enabled?(:api_caching_tags, user_project, type: :development)
- present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
- else
- present paginated_tags, with: Entities::Tag, project: user_project
- end
+ present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
rescue Gitlab::Git::InvalidPageToken => e
unprocessable_entity!(e.message)
diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb
index 970fdeba734..797b4aad033 100644
--- a/lib/api/terraform/modules/v1/packages.rb
+++ b/lib/api/terraform/modules/v1/packages.rb
@@ -21,7 +21,7 @@ module API
module_version: SEMVER_REGEX
}.freeze
- feature_category :package_registry
+ feature_category :infrastructure_as_code
after_validation do
require_packages_enabled!
@@ -71,11 +71,7 @@ module API
def package_file
strong_memoize(:package_file) do
- if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files.first
- else
- package.package_files.first
- end
+ package.installable_package_files.first
end
end
end
diff --git a/lib/api/usage_data_non_sql_metrics.rb b/lib/api/usage_data_non_sql_metrics.rb
index d9e0d153e58..983038e0263 100644
--- a/lib/api/usage_data_non_sql_metrics.rb
+++ b/lib/api/usage_data_non_sql_metrics.rb
@@ -18,7 +18,7 @@ module API
get 'non_sql_metrics' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
- data = Gitlab::UsageDataNonSqlMetrics.uncached_data
+ data = Gitlab::Usage::ServicePingReport.for(output: :non_sql_metrics_values)
present data
end
diff --git a/lib/api/usage_data_queries.rb b/lib/api/usage_data_queries.rb
index 22e83fe0294..3432e71eb28 100644
--- a/lib/api/usage_data_queries.rb
+++ b/lib/api/usage_data_queries.rb
@@ -18,7 +18,7 @@ module API
get 'queries' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
- queries = Gitlab::UsageDataQueries.uncached_data
+ queries = Gitlab::Usage::ServicePingReport.for(output: :metrics_queries)
present queries
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index eeb5244466a..d540978931e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -143,7 +143,12 @@ module API
forbidden!('Not authorized!') unless current_user
if Feature.enabled?(:rate_limit_user_by_id_endpoint, type: :development)
- check_rate_limit! :users_get_by_id, scope: current_user unless current_user.admin?
+ unless current_user.admin?
+ check_rate_limit!(:users_get_by_id,
+ scope: current_user,
+ users_allowlist: Gitlab::CurrentSettings.current_application_settings.users_get_by_id_limit_allowlist
+ )
+ end
end
user = User.find_by(id: params[:id])
diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb
index 6a45baa60ec..163446998e9 100644
--- a/lib/backup/artifacts.rb
+++ b/lib/backup/artifacts.rb
@@ -9,5 +9,9 @@ module Backup
super('artifacts', JobArtifactUploader.root, excludes: ['tmp'])
end
+
+ def human_name
+ _('artifacts')
+ end
end
end
diff --git a/lib/backup/builds.rb b/lib/backup/builds.rb
index 9c3b7165de7..51a68ca933d 100644
--- a/lib/backup/builds.rb
+++ b/lib/backup/builds.rb
@@ -9,5 +9,9 @@ module Backup
super('builds', Settings.gitlab_ci.builds_path)
end
+
+ def human_name
+ _('builds')
+ end
end
end
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index a4ac404d245..de26dbab038 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -90,7 +90,26 @@ module Backup
report_success(success)
raise Backup::Error, 'Restore failed' unless success
- errors
+ if errors.present?
+ warning = <<~MSG
+ There were errors in restoring the schema. This may cause
+ issues if this results in missing indexes, constraints, or
+ columns. Please record the errors above and contact GitLab
+ Support if you have questions:
+ https://about.gitlab.com/support/
+ MSG
+
+ warn warning.color(:red)
+ Gitlab::TaskHelpers.ask_to_continue
+ end
+ end
+
+ def enabled
+ true
+ end
+
+ def human_name
+ _('database')
end
protected
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index 4e51dcfb79e..880522bc0f5 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -63,6 +63,10 @@ module Backup
end
end
+ def enabled
+ true
+ end
+
def tar
if system(*%w[gtar --version], out: '/dev/null')
# It looks like we can get GNU tar by running 'gtar'
diff --git a/lib/backup/lfs.rb b/lib/backup/lfs.rb
index 514d52d7f65..17f7b8bf8b0 100644
--- a/lib/backup/lfs.rb
+++ b/lib/backup/lfs.rb
@@ -9,5 +9,9 @@ module Backup
super('lfs', Settings.lfs.storage_path)
end
+
+ def human_name
+ _('lfs objects')
+ end
end
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index ed2e001cefc..5b393cf9477 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -10,6 +10,137 @@ module Backup
def initialize(progress)
@progress = progress
+
+ max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i
+ max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i
+
+ @tasks = {
+ 'db' => Database.new(progress),
+ 'repositories' => Repositories.new(progress,
+ strategy: repository_backup_strategy,
+ max_concurrency: max_concurrency,
+ max_storage_concurrency: max_storage_concurrency),
+ 'uploads' => Uploads.new(progress),
+ 'builds' => Builds.new(progress),
+ 'artifacts' => Artifacts.new(progress),
+ 'pages' => Pages.new(progress),
+ 'lfs' => Lfs.new(progress),
+ 'terraform_state' => TerraformState.new(progress),
+ 'registry' => Registry.new(progress),
+ 'packages' => Packages.new(progress)
+ }.freeze
+ end
+
+ def create
+ @tasks.keys.each do |task_name|
+ run_create_task(task_name)
+ end
+
+ write_info
+
+ if ENV['SKIP'] && ENV['SKIP'].include?('tar')
+ upload
+ else
+ pack
+ upload
+ cleanup
+ remove_old
+ end
+
+ progress.puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need these files to restore a backup.\n" \
+ "Please back them up manually.".color(:red)
+ progress.puts "Backup task is done."
+ end
+
+ def run_create_task(task_name)
+ task = @tasks[task_name]
+
+ puts_time "Dumping #{task.human_name} ... ".color(:blue)
+
+ unless task.enabled
+ puts_time "[DISABLED]".color(:cyan)
+ return
+ end
+
+ if ENV["SKIP"] && ENV["SKIP"].include?(task_name)
+ puts_time "[SKIPPED]".color(:cyan)
+ return
+ end
+
+ task.dump
+ puts_time "done".color(:green)
+
+ rescue Backup::DatabaseBackupError, Backup::FileBackupError => e
+ progress.puts "#{e.message}"
+ end
+
+ def restore
+ cleanup_required = unpack
+ verify_backup_version
+
+ unless skipped?('db')
+ begin
+ unless ENV['force'] == 'yes'
+ warning = <<-MSG.strip_heredoc
+ Be sure to stop Puma, Sidekiq, and any other process that
+ connects to the database before proceeding. For Omnibus
+ installs, see the following link for more information:
+ https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
+
+ Before restoring the database, we will remove all existing
+ tables to avoid future upgrade problems. Be aware that if you have
+ custom tables in the GitLab database these tables and all data will be
+ removed.
+ MSG
+ puts warning.color(:red)
+ Gitlab::TaskHelpers.ask_to_continue
+ puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
+ sleep(5)
+ end
+
+ # Drop all tables Load the schema to ensure we don't have any newer tables
+ # hanging out from a failed upgrade
+ puts_time 'Cleaning the database ... '.color(:blue)
+ Rake::Task['gitlab:db:drop_tables'].invoke
+ puts_time 'done'.color(:green)
+ run_restore_task('db')
+ rescue Gitlab::TaskAbortedByUserError
+ puts "Quitting...".color(:red)
+ exit 1
+ end
+ end
+
+ @tasks.except('db').keys.each do |task_name|
+ run_restore_task(task_name) unless skipped?(task_name)
+ end
+
+ Rake::Task['gitlab:shell:setup'].invoke
+ Rake::Task['cache:clear'].invoke
+
+ if cleanup_required
+ cleanup
+ end
+
+ remove_tmp
+
+ puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need to restore these files manually.".color(:red)
+ puts "Restore task is done."
+ end
+
+ def run_restore_task(task_name)
+ task = @tasks[task_name]
+
+ puts_time "Restoring #{task.human_name} ... ".color(:blue)
+
+ unless task.enabled
+ puts_time "[DISABLED]".color(:cyan)
+ return
+ end
+
+ task.restore
+ puts_time "done".color(:green)
end
def write_info
@@ -188,11 +319,15 @@ module Backup
end
def skipped?(item)
- settings[:skipped] && settings[:skipped].include?(item) || disabled_features.include?(item)
+ settings[:skipped] && settings[:skipped].include?(item) || !enabled_task?(item)
end
private
+ def enabled_task?(task_name)
+ @tasks[task_name].enabled
+ end
+
def backup_file?(file)
file.match(/^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/)
end
@@ -256,12 +391,6 @@ module Backup
FOLDERS_TO_BACKUP.select { |name| !skipped?(name) && Dir.exist?(File.join(backup_path, name)) }
end
- def disabled_features
- features = []
- features << 'registry' unless Gitlab.config.registry.enabled
- features
- end
-
def settings
@settings ||= YAML.load_file("backup_information.yml")
end
@@ -317,6 +446,21 @@ module Backup
def google_provider?
Gitlab.config.backup.upload.connection&.provider&.downcase == 'google'
end
+
+ def repository_backup_strategy
+ if Feature.enabled?(:gitaly_backup, default_enabled: :yaml)
+ max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence
+ max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence
+ Backup::GitalyBackup.new(progress, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
+ else
+ Backup::GitalyRpcBackup.new(progress)
+ end
+ end
+
+ def puts_time(msg)
+ progress.puts "#{Time.now} -- #{msg}"
+ Gitlab::BackupLogger.info(message: "#{Rainbow.uncolor(msg)}")
+ end
end
end
diff --git a/lib/backup/packages.rb b/lib/backup/packages.rb
index 7b6a8f086ed..037ff31fd9b 100644
--- a/lib/backup/packages.rb
+++ b/lib/backup/packages.rb
@@ -9,5 +9,9 @@ module Backup
super('packages', Settings.packages.storage_path, excludes: ['tmp'])
end
+
+ def human_name
+ _('packages')
+ end
end
end
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
index 393cf4108a1..724972d212d 100644
--- a/lib/backup/pages.rb
+++ b/lib/backup/pages.rb
@@ -13,5 +13,9 @@ module Backup
super('pages', Gitlab.config.pages.path, excludes: [LEGACY_PAGES_TMP_PATH])
end
+
+ def human_name
+ _('pages')
+ end
end
end
diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb
index 9645a07dfb8..7ba3a9e9c60 100644
--- a/lib/backup/registry.rb
+++ b/lib/backup/registry.rb
@@ -9,5 +9,13 @@ module Backup
super('registry', Settings.registry.path)
end
+
+ def human_name
+ _('container registry images')
+ end
+
+ def enabled
+ Gitlab.config.registry.enabled
+ end
end
end
diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb
index 4c39e58c87d..e7c3e869928 100644
--- a/lib/backup/repositories.rb
+++ b/lib/backup/repositories.rb
@@ -4,12 +4,14 @@ require 'yaml'
module Backup
class Repositories
- def initialize(progress, strategy:)
+ def initialize(progress, strategy:, max_concurrency: 1, max_storage_concurrency: 1)
@progress = progress
@strategy = strategy
+ @max_concurrency = max_concurrency
+ @max_storage_concurrency = max_storage_concurrency
end
- def dump(max_concurrency:, max_storage_concurrency:)
+ def dump
strategy.start(:create)
# gitaly-backup is designed to handle concurrency on its own. So we want
@@ -19,6 +21,11 @@ module Backup
return enqueue_consecutive
end
+ if max_concurrency < 1 || max_storage_concurrency < 1
+ puts "GITLAB_BACKUP_MAX_CONCURRENCY and GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY must have a value of at least 1".color(:red)
+ exit 1
+ end
+
check_valid_storages!
semaphore = Concurrent::Semaphore.new(max_concurrency)
@@ -54,9 +61,17 @@ module Backup
restore_object_pools
end
+ def enabled
+ true
+ end
+
+ def human_name
+ _('repositories')
+ end
+
private
- attr_reader :progress, :strategy
+ attr_reader :progress, :strategy, :max_concurrency, :max_storage_concurrency
def check_valid_storages!
repository_storage_klasses.each do |klass|
diff --git a/lib/backup/terraform_state.rb b/lib/backup/terraform_state.rb
index 5f71e18f1b4..be82793fe03 100644
--- a/lib/backup/terraform_state.rb
+++ b/lib/backup/terraform_state.rb
@@ -9,5 +9,9 @@ module Backup
super('terraform_state', Settings.terraform_state.storage_path, excludes: ['tmp'])
end
+
+ def human_name
+ _('terraform states')
+ end
end
end
diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb
index 9665624f71b..7048a9a8ff5 100644
--- a/lib/backup/uploads.rb
+++ b/lib/backup/uploads.rb
@@ -9,5 +9,9 @@ module Backup
super('uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"), excludes: ['tmp'])
end
+
+ def human_name
+ _('uploads')
+ end
end
end
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index dc65e2abb46..d1a0f8e5859 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -64,8 +64,8 @@ module Banzai
def internal_url?(uri)
return false if uri.nil?
- # Relative URLs miss a hostname
- return true unless uri.hostname
+ # Relative URLs miss a hostname AND a scheme
+ return true if !uri.hostname && !uri.scheme
uri.hostname == internal_url.hostname
end
diff --git a/lib/banzai/filter/inline_embeds_filter.rb b/lib/banzai/filter/inline_embeds_filter.rb
index cb9a493e8c6..c1077674cf0 100644
--- a/lib/banzai/filter/inline_embeds_filter.rb
+++ b/lib/banzai/filter/inline_embeds_filter.rb
@@ -2,7 +2,7 @@
module Banzai
module Filter
- # HTML filter that inserts a node for each occurence of
+ # HTML filter that inserts a node for each occurrence of
# a given link format. To transform references to DB
# resources in place, prefer to inherit from AbstractReferenceFilter.
class InlineEmbedsFilter < HTML::Pipeline::Filter
@@ -26,7 +26,7 @@ module Banzai
# Return a Nokogiri::XML::Element to embed in the
# markdown which provides a url to the metric_dashboard endpoint where
# data can be requested through a prometheus proxy. InlineMetricsRedactorFilter
- # is responsible for premissions to see this div (and relies on the class 'js-render-metrics' ).
+ # is responsible for permissions to see this div (and relies on the class 'js-render-metrics' ).
def create_element(params)
doc.document.create_element(
'div',
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index 13ca9cde567..179afd840a5 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -32,7 +32,7 @@ module Banzai
doc.xpath(XPATH).each do |node|
if header_content = node.children.first
- id = string_to_anchor(node.text)
+ id = string_to_anchor(node.text[0...255])
uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
headers[id] += 1
diff --git a/lib/bitbucket_server/representation/repo.rb b/lib/bitbucket_server/representation/repo.rb
index dab7f8f22a1..4cd5b75bbed 100644
--- a/lib/bitbucket_server/representation/repo.rb
+++ b/lib/bitbucket_server/representation/repo.rb
@@ -30,7 +30,7 @@ module BitbucketServer
end
def description
- project['description']
+ raw['description']
end
def full_name
diff --git a/lib/bulk_imports/common/extractors/graphql_extractor.rb b/lib/bulk_imports/common/extractors/graphql_extractor.rb
index cde3d1cad5b..bfdc0b13603 100644
--- a/lib/bulk_imports/common/extractors/graphql_extractor.rb
+++ b/lib/bulk_imports/common/extractors/graphql_extractor.rb
@@ -5,15 +5,16 @@ module BulkImports
module Extractors
class GraphqlExtractor
def initialize(options = {})
- @query = options[:query]
+ @query_klass = options[:query]
end
def extract(context)
client = graphql_client(context)
+ query = query_klass.new(context: context)
response = client.execute(
client.parse(query.to_s),
- query.variables(context)
+ query.variables
).original_hash.deep_dup
BulkImports::Pipeline::ExtractedData.new(
@@ -24,7 +25,7 @@ module BulkImports
private
- attr_reader :query
+ attr_reader :query_klass
def graphql_client(context)
@graphql_client ||= BulkImports::Clients::Graphql.new(
diff --git a/lib/bulk_imports/groups/graphql/get_members_query.rb b/lib/bulk_imports/common/graphql/get_members_query.rb
index e76c87cc521..00977f694d7 100644
--- a/lib/bulk_imports/groups/graphql/get_members_query.rb
+++ b/lib/bulk_imports/common/graphql/get_members_query.rb
@@ -1,15 +1,20 @@
# frozen_string_literal: true
module BulkImports
- module Groups
+ module Common
module Graphql
- module GetMembersQuery
- extend self
+ class GetMembersQuery
+ attr_reader :context
+
+ def initialize(context:)
+ @context = context
+ end
+
def to_s
- <<-'GRAPHQL'
+ <<-GRAPHQL
query($full_path: ID!, $cursor: String, $per_page: Int) {
- group(fullPath: $full_path) {
- group_members: groupMembers(relations: DIRECT, first: $per_page, after: $cursor) {
+ portable: #{context.entity.entity_type}(fullPath: $full_path) {
+ members: #{members_type}(relations: [DIRECT, INHERITED], first: $per_page, after: $cursor) {
page_info: pageInfo {
next_page: endCursor
has_next_page: hasNextPage
@@ -32,7 +37,7 @@ module BulkImports
GRAPHQL
end
- def variables(context)
+ def variables
{
full_path: context.entity.source_full_path,
cursor: context.tracker.next_page,
@@ -40,10 +45,6 @@ module BulkImports
}
end
- def base_path
- %w[data group group_members]
- end
-
def data_path
base_path << 'nodes'
end
@@ -51,6 +52,20 @@ module BulkImports
def page_info_path
base_path << 'page_info'
end
+
+ private
+
+ def base_path
+ %w[data portable members]
+ end
+
+ def members_type
+ if context.entity.group?
+ 'groupMembers'
+ else
+ 'projectMembers'
+ end
+ end
end
end
end
diff --git a/lib/bulk_imports/common/pipelines/lfs_objects_pipeline.rb b/lib/bulk_imports/common/pipelines/lfs_objects_pipeline.rb
new file mode 100644
index 00000000000..2e6a29f4738
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/lfs_objects_pipeline.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class LfsObjectsPipeline
+ include Pipeline
+
+ def extract(_context)
+ download_service.execute
+ decompression_service.execute
+ extraction_service.execute
+
+ file_paths = Dir.glob(File.join(tmpdir, '*'))
+
+ BulkImports::Pipeline::ExtractedData.new(data: file_paths)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def load(_context, file_path)
+ Gitlab::Utils.check_path_traversal!(file_path)
+ Gitlab::Utils.check_allowed_absolute_path!(file_path, [Dir.tmpdir])
+
+ return if tar_filepath?(file_path)
+ return if lfs_json_filepath?(file_path)
+ return if File.directory?(file_path)
+ return if File.lstat(file_path).symlink?
+
+ size = File.size(file_path)
+ oid = LfsObject.calculate_oid(file_path)
+
+ lfs_object = LfsObject.find_or_initialize_by(oid: oid, size: size)
+ lfs_object.file = File.open(file_path) unless lfs_object.file&.exists?
+ lfs_object.save! if lfs_object.changed?
+
+ repository_types(oid)&.each do |type|
+ create_lfs_objects_project(lfs_object, type)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def after_run(_)
+ FileUtils.remove_entry(tmpdir) if Dir.exist?(tmpdir)
+ end
+
+ private
+
+ def download_service
+ BulkImports::FileDownloadService.new(
+ configuration: context.configuration,
+ relative_url: context.entity.relation_download_url_path(relation),
+ tmpdir: tmpdir,
+ filename: targz_filename
+ )
+ end
+
+ def decompression_service
+ BulkImports::FileDecompressionService.new(tmpdir: tmpdir, filename: targz_filename)
+ end
+
+ def extraction_service
+ BulkImports::ArchiveExtractionService.new(tmpdir: tmpdir, filename: tar_filename)
+ end
+
+ def lfs_json
+ @lfs_json ||= Gitlab::Json.parse(File.read(lfs_json_filepath))
+ rescue StandardError
+ raise BulkImports::Error, 'LFS Objects JSON read failed'
+ end
+
+ def tmpdir
+ @tmpdir ||= Dir.mktmpdir('bulk_imports')
+ end
+
+ def relation
+ BulkImports::FileTransfer::ProjectConfig::LFS_OBJECTS_RELATION
+ end
+
+ def tar_filename
+ "#{relation}.tar"
+ end
+
+ def targz_filename
+ "#{tar_filename}.gz"
+ end
+
+ def lfs_json_filepath?(file_path)
+ file_path == lfs_json_filepath
+ end
+
+ def tar_filepath?(file_path)
+ File.join(tmpdir, tar_filename) == file_path
+ end
+
+ def lfs_json_filepath
+ File.join(tmpdir, "#{relation}.json")
+ end
+
+ def create_lfs_objects_project(lfs_object, repository_type)
+ return unless allowed_repository_types.include?(repository_type)
+
+ lfs_objects_project = LfsObjectsProject.create(
+ project: portable,
+ lfs_object: lfs_object,
+ repository_type: repository_type
+ )
+
+ return if lfs_objects_project.persisted?
+
+ logger.warn(
+ project_id: portable.id,
+ message: 'Failed to save lfs objects project',
+ errors: lfs_objects_project.errors.full_messages.to_sentence,
+ **Gitlab::ApplicationContext.current
+ )
+ end
+
+ def repository_types(oid)
+ types = lfs_json[oid]
+
+ return [] unless types
+ return [] unless types.is_a?(Array)
+
+ # only return allowed repository types
+ types.uniq & allowed_repository_types
+ end
+
+ def allowed_repository_types
+ @allowed_repository_types ||= LfsObjectsProject.repository_types.values.push(nil)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/pipelines/members_pipeline.rb b/lib/bulk_imports/common/pipelines/members_pipeline.rb
new file mode 100644
index 00000000000..f35eb5ccf5e
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/members_pipeline.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class MembersPipeline
+ include Pipeline
+
+ transformer Common::Transformers::ProhibitedAttributesTransformer
+ transformer BulkImports::Groups::Transformers::MemberAttributesTransformer
+
+ def extract(context)
+ graphql_extractor.extract(context)
+ end
+
+ def load(_context, data)
+ return unless data
+
+ user_id = data[:user_id]
+
+ # Current user is already a member
+ return if user_id == current_user.id
+
+ user_membership = existing_user_membership(user_id)
+
+ # User is already a member with higher existing (inherited) membership
+ return if user_membership && user_membership[:access_level] >= data[:access_level]
+
+ # Create new membership for any other access level
+ portable.members.create!(data)
+ end
+
+ private
+
+ def graphql_extractor
+ @graphql_extractor ||= BulkImports::Common::Extractors::GraphqlExtractor
+ .new(query: BulkImports::Common::Graphql::GetMembersQuery)
+ end
+
+ def existing_user_membership(user_id)
+ members_finder.execute.find_by_user_id(user_id)
+ end
+
+ def members_finder
+ @members_finder ||= if context.entity.group?
+ ::GroupMembersFinder.new(portable, current_user)
+ else
+ ::MembersFinder.new(portable, current_user)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/graphql/get_group_query.rb b/lib/bulk_imports/groups/graphql/get_group_query.rb
index 6852e25c87f..911b2b67d8c 100644
--- a/lib/bulk_imports/groups/graphql/get_group_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_group_query.rb
@@ -3,8 +3,12 @@
module BulkImports
module Groups
module Graphql
- module GetGroupQuery
- extend self
+ class GetGroupQuery
+ attr_reader :context
+
+ def initialize(context:)
+ @context = context
+ end
def to_s
<<-'GRAPHQL'
@@ -29,7 +33,7 @@ module BulkImports
GRAPHQL
end
- def variables(context)
+ def variables
{ full_path: context.entity.source_full_path }
end
diff --git a/lib/bulk_imports/groups/graphql/get_projects_query.rb b/lib/bulk_imports/groups/graphql/get_projects_query.rb
index 4cec1ad1462..3f74bbb8cce 100644
--- a/lib/bulk_imports/groups/graphql/get_projects_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_projects_query.rb
@@ -3,8 +3,12 @@
module BulkImports
module Groups
module Graphql
- module GetProjectsQuery
- extend self
+ class GetProjectsQuery
+ attr_reader :context
+
+ def initialize(context:)
+ @context = context
+ end
def to_s
<<-'GRAPHQL'
@@ -25,7 +29,7 @@ module BulkImports
GRAPHQL
end
- def variables(context)
+ def variables
{
full_path: context.entity.source_full_path,
cursor: context.tracker.next_page,
diff --git a/lib/bulk_imports/groups/pipelines/members_pipeline.rb b/lib/bulk_imports/groups/pipelines/members_pipeline.rb
deleted file mode 100644
index 265abd5e3a7..00000000000
--- a/lib/bulk_imports/groups/pipelines/members_pipeline.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Groups
- module Pipelines
- class MembersPipeline
- include Pipeline
-
- extractor BulkImports::Common::Extractors::GraphqlExtractor,
- query: BulkImports::Groups::Graphql::GetMembersQuery
-
- transformer Common::Transformers::ProhibitedAttributesTransformer
- transformer BulkImports::Groups::Transformers::MemberAttributesTransformer
-
- def load(context, data)
- return unless data
-
- # Current user is already a member
- return if data['user_id'].to_i == context.current_user.id
-
- context.group.members.create!(data)
- end
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/stage.rb b/lib/bulk_imports/groups/stage.rb
index 1a3babe1679..bc27220391d 100644
--- a/lib/bulk_imports/groups/stage.rb
+++ b/lib/bulk_imports/groups/stage.rb
@@ -16,7 +16,7 @@ module BulkImports
stage: 1
},
members: {
- pipeline: BulkImports::Groups::Pipelines::MembersPipeline,
+ pipeline: BulkImports::Common::Pipelines::MembersPipeline,
stage: 1
},
labels: {
diff --git a/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb b/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb
index b9de375d0e9..da50a19ee62 100644
--- a/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb
+++ b/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb
@@ -5,50 +5,35 @@ module BulkImports
module Transformers
class MemberAttributesTransformer
def transform(context, data)
- data
- .then { |data| add_user(data, context) }
- .then { |data| add_access_level(data) }
- .then { |data| add_author(data, context) }
- end
-
- private
-
- def add_user(data, context)
user = find_user(data&.dig('user', 'public_email'))
+ access_level = data&.dig('access_level', 'integer_value')
+ return unless data
return unless user
+ return unless valid_access_level?(access_level)
cache_source_user_id(data, user, context)
- data
- .except('user')
- .merge('user_id' => user.id)
+ {
+ user_id: user.id,
+ access_level: access_level,
+ created_at: data['created_at'],
+ updated_at: data['updated_at'],
+ expires_at: data['expires_at'],
+ created_by_id: context.current_user.id
+ }
end
+ private
+
def find_user(email)
return unless email
User.find_by_any_email(email, confirmed: true)
end
- def add_access_level(data)
- access_level = data&.dig('access_level', 'integer_value')
-
- return unless valid_access_level?(access_level)
-
- data.merge('access_level' => access_level)
- end
-
def valid_access_level?(access_level)
- Gitlab::Access
- .options_with_owner
- .value?(access_level)
- end
-
- def add_author(data, context)
- return unless data
-
- data.merge('created_by_id' => context.current_user.id)
+ Gitlab::Access.options_with_owner.value?(access_level)
end
def cache_source_user_id(data, user, context)
diff --git a/lib/bulk_imports/projects/graphql/get_project_query.rb b/lib/bulk_imports/projects/graphql/get_project_query.rb
index 04ac0916bbc..b3d7f3f4683 100644
--- a/lib/bulk_imports/projects/graphql/get_project_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_project_query.rb
@@ -3,9 +3,8 @@
module BulkImports
module Projects
module Graphql
- module GetProjectQuery
- extend Queryable
- extend self
+ class GetProjectQuery
+ include Queryable
def to_s
<<-'GRAPHQL'
diff --git a/lib/bulk_imports/projects/graphql/get_repository_query.rb b/lib/bulk_imports/projects/graphql/get_repository_query.rb
index 24efce9e276..ca777c1a7e0 100644
--- a/lib/bulk_imports/projects/graphql/get_repository_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_repository_query.rb
@@ -3,9 +3,8 @@
module BulkImports
module Projects
module Graphql
- module GetRepositoryQuery
- extend Queryable
- extend self
+ class GetRepositoryQuery
+ include Queryable
def to_s
<<-'GRAPHQL'
diff --git a/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb b/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb
index 1ba57789612..c105b04c731 100644
--- a/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb
@@ -3,9 +3,8 @@
module BulkImports
module Projects
module Graphql
- module GetSnippetRepositoryQuery
- extend Queryable
- extend self
+ class GetSnippetRepositoryQuery
+ include Queryable
def to_s
<<-'GRAPHQL'
@@ -27,7 +26,7 @@ module BulkImports
GRAPHQL
end
- def variables(context)
+ def variables
{
full_path: context.entity.source_full_path,
cursor: context.tracker.next_page,
diff --git a/lib/bulk_imports/projects/graphql/queryable.rb b/lib/bulk_imports/projects/graphql/queryable.rb
index a897632dff3..bd3116cb838 100644
--- a/lib/bulk_imports/projects/graphql/queryable.rb
+++ b/lib/bulk_imports/projects/graphql/queryable.rb
@@ -4,7 +4,13 @@ module BulkImports
module Projects
module Graphql
module Queryable
- def variables(context)
+ attr_reader :context
+
+ def initialize(context:)
+ @context = context
+ end
+
+ def variables
{ full_path: context.entity.source_full_path }
end
diff --git a/lib/bulk_imports/projects/stage.rb b/lib/bulk_imports/projects/stage.rb
index 0556395ca66..b920c1bf355 100644
--- a/lib/bulk_imports/projects/stage.rb
+++ b/lib/bulk_imports/projects/stage.rb
@@ -19,6 +19,10 @@ module BulkImports
pipeline: BulkImports::Projects::Pipelines::ProjectAttributesPipeline,
stage: 1
},
+ members: {
+ pipeline: BulkImports::Common::Pipelines::MembersPipeline,
+ stage: 1
+ },
labels: {
pipeline: BulkImports::Common::Pipelines::LabelsPipeline,
stage: 2
@@ -83,6 +87,10 @@ module BulkImports
pipeline: BulkImports::Common::Pipelines::UploadsPipeline,
stage: 5
},
+ lfs_objects: {
+ pipeline: BulkImports::Common::Pipelines::LfsObjectsPipeline,
+ stage: 5
+ },
auto_devops: {
pipeline: BulkImports::Projects::Pipelines::AutoDevopsPipeline,
stage: 5
diff --git a/lib/container_registry/base_client.rb b/lib/container_registry/base_client.rb
new file mode 100644
index 00000000000..22d4510fe71
--- /dev/null
+++ b/lib/container_registry/base_client.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'faraday'
+require 'faraday_middleware'
+require 'digest'
+
+module ContainerRegistry
+ class BaseClient
+ DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE = 'application/vnd.docker.distribution.manifest.v2+json'
+ DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE = 'application/vnd.docker.distribution.manifest.list.v2+json'
+ OCI_MANIFEST_V1_TYPE = 'application/vnd.oci.image.manifest.v1+json'
+ CONTAINER_IMAGE_V1_TYPE = 'application/vnd.docker.container.image.v1+json'
+
+ ACCEPTED_TYPES = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE].freeze
+ ACCEPTED_TYPES_RAW = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE, DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE].freeze
+
+ RETRY_EXCEPTIONS = [Faraday::Request::Retry::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed].flatten.freeze
+ RETRY_OPTIONS = {
+ max: 1,
+ interval: 5,
+ exceptions: RETRY_EXCEPTIONS
+ }.freeze
+
+ ERROR_CALLBACK_OPTIONS = {
+ callback: -> (env, exception) do
+ Gitlab::ErrorTracking.log_exception(
+ exception,
+ class: name,
+ url: env[:url]
+ )
+ end
+ }.freeze
+
+ # Taken from: FaradayMiddleware::FollowRedirects
+ REDIRECT_CODES = Set.new [301, 302, 303, 307]
+
+ class << self
+ private
+
+ def with_dummy_client(return_value_if_disabled: nil)
+ registry_config = Gitlab.config.registry
+ unless registry_config.enabled && registry_config.api_url.present?
+ return return_value_if_disabled
+ end
+
+ token = Auth::ContainerRegistryAuthenticationService.access_token([], [])
+ yield new(registry_config.api_url, token: token)
+ end
+ end
+
+ def initialize(base_uri, options = {})
+ @base_uri = base_uri
+ @options = options
+ end
+
+ private
+
+ def faraday(timeout_enabled: true)
+ @faraday ||= faraday_base(timeout_enabled: timeout_enabled) do |conn|
+ initialize_connection(conn, @options, &method(:configure_connection))
+ end
+ end
+
+ def faraday_base(timeout_enabled: true, &block)
+ request_options = timeout_enabled ? Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS : nil
+
+ Faraday.new(
+ @base_uri,
+ headers: { user_agent: "GitLab/#{Gitlab::VERSION}" },
+ request: request_options,
+ &block
+ )
+ end
+
+ def initialize_connection(conn, options)
+ conn.request :json
+
+ if options[:user] && options[:password]
+ conn.request(:basic_auth, options[:user].to_s, options[:password].to_s)
+ elsif options[:token]
+ conn.request(:authorization, :bearer, options[:token].to_s)
+ end
+
+ yield(conn) if block_given?
+
+ conn.request(:retry, RETRY_OPTIONS)
+ conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
+ conn.adapter :net_http
+ end
+
+ def response_body(response, allow_redirect: false)
+ if allow_redirect && REDIRECT_CODES.include?(response.status)
+ response = redirect_response(response.headers['location'])
+ end
+
+ response.body if response && response.success?
+ end
+
+ def redirect_response(location)
+ return unless location
+
+ uri = URI(@base_uri).merge(location)
+ raise ArgumentError, "Invalid scheme for #{location}" unless %w[http https].include?(uri.scheme)
+
+ faraday_redirect.get(uri)
+ end
+
+ def configure_connection(conn)
+ conn.headers['Accept'] = ACCEPTED_TYPES
+
+ conn.response :json, content_type: 'application/json'
+ conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+prettyjws'
+ conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+json'
+ conn.response :json, content_type: DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
+ conn.response :json, content_type: OCI_MANIFEST_V1_TYPE
+ end
+
+ # Create a new request to make sure the Authorization header is not inserted
+ # via the Faraday middleware
+ def faraday_redirect
+ @faraday_redirect ||= faraday_base do |conn|
+ conn.request :json
+
+ conn.request(:retry, RETRY_OPTIONS)
+ conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
+ conn.adapter :net_http
+ end
+ end
+
+ def delete_if_exists(path)
+ result = faraday.delete(path)
+
+ result.success? || result.status == 404
+ end
+ end
+end
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index c2ad9e6ae89..add238350dd 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -1,68 +1,25 @@
# frozen_string_literal: true
-require 'faraday'
-require 'faraday_middleware'
-require 'digest'
-
module ContainerRegistry
- class Client
+ class Client < BaseClient
include Gitlab::Utils::StrongMemoize
attr_accessor :uri
- DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE = 'application/vnd.docker.distribution.manifest.v2+json'
- DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE = 'application/vnd.docker.distribution.manifest.list.v2+json'
- OCI_MANIFEST_V1_TYPE = 'application/vnd.oci.image.manifest.v1+json'
- CONTAINER_IMAGE_V1_TYPE = 'application/vnd.docker.container.image.v1+json'
REGISTRY_VERSION_HEADER = 'gitlab-container-registry-version'
REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features'
REGISTRY_TAG_DELETE_FEATURE = 'tag_delete'
- ACCEPTED_TYPES = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE].freeze
-
- ACCEPTED_TYPES_RAW = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE, DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE].freeze
-
- # Taken from: FaradayMiddleware::FollowRedirects
- REDIRECT_CODES = Set.new [301, 302, 303, 307]
-
- RETRY_EXCEPTIONS = [Faraday::Request::Retry::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed].flatten.freeze
- RETRY_OPTIONS = {
- max: 1,
- interval: 5,
- exceptions: RETRY_EXCEPTIONS
- }.freeze
-
- ERROR_CALLBACK_OPTIONS = {
- callback: -> (env, exception) do
- Gitlab::ErrorTracking.log_exception(
- exception,
- class: name,
- url: env[:url]
- )
- end
- }.freeze
-
def self.supports_tag_delete?
- registry_config = Gitlab.config.registry
- return false unless registry_config.enabled && registry_config.api_url.present?
-
- token = Auth::ContainerRegistryAuthenticationService.access_token([], [])
- client = new(registry_config.api_url, token: token)
- client.supports_tag_delete?
+ with_dummy_client(return_value_if_disabled: false) do |client|
+ client.supports_tag_delete?
+ end
end
def self.registry_info
- registry_config = Gitlab.config.registry
- return unless registry_config.enabled && registry_config.api_url.present?
-
- token = Auth::ContainerRegistryAuthenticationService.access_token([], [])
- client = new(registry_config.api_url, token: token)
- client.registry_info
- end
-
- def initialize(base_uri, options = {})
- @base_uri = base_uri
- @options = options
+ with_dummy_client do |client|
+ client.registry_info
+ end
end
def registry_info
@@ -176,89 +133,11 @@ module ContainerRegistry
private
- def initialize_connection(conn, options)
- conn.request :json
-
- if options[:user] && options[:password]
- conn.request(:basic_auth, options[:user].to_s, options[:password].to_s)
- elsif options[:token]
- conn.request(:authorization, :bearer, options[:token].to_s)
- end
-
- yield(conn) if block_given?
-
- conn.request(:retry, RETRY_OPTIONS)
- conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
- conn.adapter :net_http
- end
-
- def accept_manifest(conn)
- conn.headers['Accept'] = ACCEPTED_TYPES
-
- conn.response :json, content_type: 'application/json'
- conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+prettyjws'
- conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+json'
- conn.response :json, content_type: DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
- conn.response :json, content_type: OCI_MANIFEST_V1_TYPE
- end
-
- def response_body(response, allow_redirect: false)
- if allow_redirect && REDIRECT_CODES.include?(response.status)
- response = redirect_response(response.headers['location'])
- end
-
- response.body if response && response.success?
- end
-
- def redirect_response(location)
- return unless location
-
- uri = URI(@base_uri).merge(location)
- raise ArgumentError, "Invalid scheme for #{location}" unless %w[http https].include?(uri.scheme)
-
- faraday_redirect.get(uri)
- end
-
- def faraday(timeout_enabled: true)
- @faraday ||= faraday_base(timeout_enabled: timeout_enabled) do |conn|
- initialize_connection(conn, @options, &method(:accept_manifest))
- end
- end
-
def faraday_blob
@faraday_blob ||= faraday_base do |conn|
initialize_connection(conn, @options)
end
end
-
- # Create a new request to make sure the Authorization header is not inserted
- # via the Faraday middleware
- def faraday_redirect
- @faraday_redirect ||= faraday_base do |conn|
- conn.request :json
-
- conn.request(:retry, RETRY_OPTIONS)
- conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
- conn.adapter :net_http
- end
- end
-
- def faraday_base(timeout_enabled: true, &block)
- request_options = timeout_enabled ? Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS : nil
-
- Faraday.new(
- @base_uri,
- headers: { user_agent: "GitLab/#{Gitlab::VERSION}" },
- request: request_options,
- &block
- )
- end
-
- def delete_if_exists(path)
- result = faraday.delete(path)
-
- result.success? || result.status == 404
- end
end
end
diff --git a/lib/container_registry/gitlab_api_client.rb b/lib/container_registry/gitlab_api_client.rb
new file mode 100644
index 00000000000..20b8e1d419b
--- /dev/null
+++ b/lib/container_registry/gitlab_api_client.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ class GitlabApiClient < BaseClient
+ include Gitlab::Utils::StrongMemoize
+
+ JSON_TYPE = 'application/json'
+
+ IMPORT_RESPONSES = {
+ 200 => :already_imported,
+ 202 => :ok,
+ 401 => :unauthorized,
+ 404 => :not_found,
+ 409 => :already_being_imported,
+ 424 => :pre_import_failed,
+ 425 => :already_being_imported,
+ 429 => :too_many_imports
+ }.freeze
+
+ REGISTRY_GITLAB_V1_API_FEATURE = 'gitlab_v1_api'
+
+ def self.supports_gitlab_api?
+ with_dummy_client(return_value_if_disabled: false) do |client|
+ client.supports_gitlab_api?
+ end
+ end
+
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#compliance-check
+ def supports_gitlab_api?
+ strong_memoize(:supports_gitlab_api) do
+ registry_features = Gitlab::CurrentSettings.container_registry_features || []
+ next true if ::Gitlab.com? && registry_features.include?(REGISTRY_GITLAB_V1_API_FEATURE)
+
+ response = faraday.get('/gitlab/v1/')
+ response.success? || response.status == 401
+ end
+ end
+
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#import-repository
+ def pre_import_repository(path)
+ response = start_import_for(path, pre: true)
+ IMPORT_RESPONSES.fetch(response.status, :error)
+ end
+
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#import-repository
+ def import_repository(path)
+ response = start_import_for(path, pre: false)
+ IMPORT_RESPONSES.fetch(response.status, :error)
+ end
+
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#get-repository-import-status
+ def import_status(path)
+ body_hash = response_body(faraday.get(import_url_for(path)))
+ body_hash['status'] || 'error'
+ end
+
+ private
+
+ def start_import_for(path, pre:)
+ faraday.put(import_url_for(path)) do |req|
+ req.params['pre'] = pre.to_s
+ end
+ end
+
+ def import_url_for(path)
+ "/gitlab/v1/import/#{path}/"
+ end
+
+ # overrides the default configuration
+ def configure_connection(conn)
+ conn.headers['Accept'] = [JSON_TYPE]
+
+ conn.response :json, content_type: JSON_TYPE
+ end
+ end
+end
diff --git a/lib/container_registry/migration.rb b/lib/container_registry/migration.rb
new file mode 100644
index 00000000000..b03c94e5ebf
--- /dev/null
+++ b/lib/container_registry/migration.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Migration
+ class << self
+ delegate :container_registry_import_max_tags_count, to: ::Gitlab::CurrentSettings
+ delegate :container_registry_import_max_retries, to: ::Gitlab::CurrentSettings
+ delegate :container_registry_import_start_max_retries, to: ::Gitlab::CurrentSettings
+ delegate :container_registry_import_max_step_duration, to: ::Gitlab::CurrentSettings
+ delegate :container_registry_import_target_plan, to: ::Gitlab::CurrentSettings
+ delegate :container_registry_import_created_before, to: ::Gitlab::CurrentSettings
+
+ alias_method :max_tags_count, :container_registry_import_max_tags_count
+ alias_method :max_retries, :container_registry_import_max_retries
+ alias_method :start_max_retries, :container_registry_import_start_max_retries
+ alias_method :max_step_duration, :container_registry_import_max_step_duration
+ alias_method :target_plan_name, :container_registry_import_target_plan
+ alias_method :created_before, :container_registry_import_created_before
+ end
+
+ def self.enabled?
+ Feature.enabled?(:container_registry_migration_phase2_enabled)
+ end
+
+ def self.limit_gitlab_org?
+ Feature.enabled?(:container_registry_migration_limit_gitlab_org)
+ end
+
+ def self.enqueue_waiting_time
+ return 0 if Feature.enabled?(:container_registry_migration_phase2_enqueue_speed_fast)
+ return 6.hours if Feature.enabled?(:container_registry_migration_phase2_enqueue_speed_slow)
+
+ 1.hour
+ end
+
+ def self.capacity
+ # Increasing capacity numbers will increase the n+1 API calls we can have
+ # in ContainerRegistry::Migration::GuardWorker#external_migration_in_progress?
+ #
+ # TODO: See https://gitlab.com/gitlab-org/container-registry/-/issues/582
+ #
+ return 25 if Feature.enabled?(:container_registry_migration_phase2_capacity_25)
+ return 10 if Feature.enabled?(:container_registry_migration_phase2_capacity_10)
+ return 1 if Feature.enabled?(:container_registry_migration_phase2_capacity_1)
+
+ 0
+ end
+
+ def self.target_plan
+ Plan.find_by_name(target_plan_name)
+ end
+ end
+end
diff --git a/lib/container_registry/registry.rb b/lib/container_registry/registry.rb
index 523364ac7c7..710f8169a00 100644
--- a/lib/container_registry/registry.rb
+++ b/lib/container_registry/registry.rb
@@ -2,12 +2,26 @@
module ContainerRegistry
class Registry
+ include Gitlab::Utils::StrongMemoize
+
attr_reader :uri, :client, :path
def initialize(uri, options = {})
@uri = uri
- @path = options[:path] || default_path
- @client = ContainerRegistry::Client.new(uri, options)
+ @options = options
+ @path = @options[:path] || default_path
+ @client = ContainerRegistry::Client.new(@uri, @options)
+ end
+
+ def gitlab_api_client
+ strong_memoize(:gitlab_api_client) do
+ token = Auth::ContainerRegistryAuthenticationService.import_access_token
+
+ url = Gitlab.config.registry.api_url
+ host_port = Gitlab.config.registry.host_port
+
+ ContainerRegistry::GitlabApiClient.new(url, token: token, path: host_port)
+ end
end
private
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 8f6576c2206..db5c3bb1d4a 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -16,6 +16,8 @@ module ExtractsPath
id_without_atom = id.sub(/\.atom$/, '')
valid_refs = ref_names.select { |v| "#{id_without_atom}/".start_with?("#{v}/") }
+ raise InvalidPathError if valid_refs.blank?
+
valid_refs.max_by(&:length)
end
diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb
index daba0452318..9799116038e 100644
--- a/lib/extracts_ref.rb
+++ b/lib/extracts_ref.rb
@@ -126,8 +126,10 @@ module ExtractsRef
# overridden in subclasses, do not remove
def get_id
- id = [params[:id] || params[:ref]]
- id << "/" + params[:path] unless params[:path].blank?
+ allowed_params = params.permit(:id, :ref, :path)
+
+ id = [allowed_params[:id] || allowed_params[:ref]]
+ id << "/" + allowed_params[:path] unless allowed_params[:path].blank?
id.join
end
diff --git a/lib/feature.rb b/lib/feature.rb
index 12b4ef07dd6..47fee23c7ea 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -245,11 +245,11 @@ class Feature
end
def gate_specified?
- %i(user project group feature_group).any? { |key| params.key?(key) }
+ %i(user project group feature_group namespace).any? { |key| params.key?(key) }
end
def targets
- [feature_group, user, project, group].compact
+ [feature_group, user, project, group, namespace].compact
end
private
@@ -279,6 +279,13 @@ class Feature
Group.find_by_full_path(params[:group])
end
+
+ def namespace
+ return unless params.key?(:namespace)
+
+ # We are interested in Group or UserNamespace
+ Namespace.without_project_namespaces.find_by_full_path(params[:namespace])
+ end
end
end
diff --git a/lib/generators/gitlab/snowplow_event_definition_generator.rb b/lib/generators/gitlab/snowplow_event_definition_generator.rb
index 497d0cd512a..827e87dc313 100644
--- a/lib/generators/gitlab/snowplow_event_definition_generator.rb
+++ b/lib/generators/gitlab/snowplow_event_definition_generator.rb
@@ -65,7 +65,12 @@ module Gitlab
end
def file_name
- "#{event_category}_#{event_action}.yml".underscore.gsub("/", "__")
+ name = remove_special_chars("#{Time.current.to_i}_#{event_category}_#{event_action}")
+ "#{name[0..95]}.yml" # max 100 chars, see https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/2030#note_679501200
+ end
+
+ def remove_special_chars(input)
+ input.gsub("::", "__").gsub(/[^A-Za-z0-9_]/, '')
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
index 1e50c980a3a..dd8149aba94 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
@@ -37,6 +37,16 @@ module Gitlab
filter_assignees(query)
end
+ def build_sorted_query
+ direction = params[:direction] || :desc
+
+ if params[:sort] == :duration
+ build.order_by_duration(direction)
+ else
+ build.order_by_end_event(direction)
+ end
+ end
+
def filter_author(query)
return query if params[:author_username].blank?
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
index 2441b7a7497..22d8874db57 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
@@ -32,7 +32,7 @@ module Gitlab
def records_fetcher
strong_memoize(:records_fetcher) do
- RecordsFetcher.new(stage: stage, query: query, params: params)
+ RecordsFetcher.new(stage: stage, query: query_builder.build_sorted_query, params: params)
end
end
@@ -41,7 +41,11 @@ module Gitlab
attr_reader :stage, :params
def query
- BaseQueryBuilder.new(stage: stage, params: params).build
+ query_builder.build
+ end
+
+ def query_builder
+ @query_builder = BaseQueryBuilder.new(stage: stage, params: params)
end
def limit_count
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
index 1742d396c10..55e421173d7 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
@@ -36,7 +36,13 @@ module Gitlab
def serialized_records
strong_memoize(:serialized_records) do
- records = ordered_and_limited_query.select(stage_event_model.arel_table[Arel.star], duration_in_seconds.as('total_time'))
+ # When RecordsFetcher is used with query sourced from
+ # InOperatorOptimization::QueryBuilder only columns
+ # used in ORDER BY statement would be selected by Arel.start operation
+ selections = [stage_event_model.arel_table[Arel.star]]
+ selections << duration_in_seconds.as('total_time') if params[:sort] != :duration # duration sorting already exposes this data
+
+ records = limited_query.select(*selections)
yield records if block_given?
issuables_and_records = load_issuables(records)
@@ -56,27 +62,12 @@ module Gitlab
end
end
- # rubocop: disable CodeReuse/ActiveRecord
- def ordered_and_limited_query
- sorting_options = {
- end_event: {
- asc: -> { query.order(end_event_timestamp: :asc) },
- desc: -> { query.order(end_event_timestamp: :desc) }
- },
- duration: {
- asc: -> { query.order(duration.asc) },
- desc: -> { query.order(duration.desc) }
- }
- }
-
- sort_lambda = sorting_options.dig(sort, direction) || sorting_options.dig(:end_event, :desc)
-
- sort_lambda.call
+ def limited_query
+ query
.page(page)
.per(per_page)
.without_count
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/lib/gitlab/analytics/cycle_analytics/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
index a20481dd39e..ae675b6ad27 100644
--- a/lib/gitlab/analytics/cycle_analytics/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
@@ -62,7 +62,11 @@ module Gitlab
attr_reader :stage, :params
def query
- BaseQueryBuilder.new(stage: stage, params: params).build
+ query_builder.build
+ end
+
+ def query_builder
+ @query_builder ||= BaseQueryBuilder.new(stage: stage, params: params)
end
# Limiting the maximum number of records so the COUNT(*) query stays efficient for large groups.
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index c3415c45b28..d93067c7e2f 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -9,7 +9,17 @@ module Gitlab
Attribute = Struct.new(:name, :type)
LOG_KEY = Labkit::Context::LOG_KEY
- KNOWN_KEYS = Labkit::Context::KNOWN_KEYS
+ KNOWN_KEYS = [
+ :user,
+ :project,
+ :root_namespace,
+ :client_id,
+ :caller_id,
+ :remote_ip,
+ :related_class,
+ :feature_category
+ ].freeze
+ private_constant :KNOWN_KEYS
APPLICATION_ATTRIBUTES = [
Attribute.new(:project, Project),
@@ -22,6 +32,10 @@ module Gitlab
Attribute.new(:feature_category, String)
].freeze
+ def self.known_keys
+ KNOWN_KEYS
+ end
+
def self.with_context(args, &block)
application_context = new(**args)
application_context.use(&block)
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 12f1b15f820..d2a31938e89 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -1,37 +1,20 @@
# frozen_string_literal: true
module Gitlab
- # This class implements a simple rate limiter that can be used to throttle
+ # This module implements a simple rate limiter that can be used to throttle
# certain actions. Unlike Rack Attack and Rack::Throttle, which operate at
# the middleware level, this can be used at the controller or API level.
# See CheckRateLimit concern for usage.
- class ApplicationRateLimiter
+ module ApplicationRateLimiter
InvalidKeyError = Class.new(StandardError)
- def initialize(key, **options)
- @key = key
- @options = options
- end
-
- def throttled?
- self.class.throttled?(key, **options)
- end
-
- def threshold_value
- options[:threshold] || self.class.threshold(key)
- end
-
- def interval_value
- self.class.interval(key)
- end
-
class << self
# Application rate limits
#
# Threshold value can be either an Integer or a Proc
# in order to not evaluate it's value every time this method is called
# and only do that when it's needed.
- def rate_limits
+ def rate_limits # rubocop:disable Metrics/AbcSize
{
issues_create: { threshold: -> { application_settings.issues_create_limit }, interval: 1.minute },
notes_create: { threshold: -> { application_settings.notes_create_limit }, interval: 1.minute },
@@ -49,7 +32,7 @@ module Gitlab
group_testing_hook: { threshold: 5, interval: 1.minute },
profile_add_new_email: { threshold: 5, interval: 1.minute },
web_hook_calls: { interval: 1.minute },
- users_get_by_id: { threshold: 10, interval: 1.minute },
+ users_get_by_id: { threshold: -> { application_settings.users_get_by_id_limit }, interval: 10.minutes },
username_exists: { threshold: 20, interval: 1.minute },
user_sign_up: { threshold: 20, interval: 1.minute },
profile_resend_email_confirmation: { threshold: 5, interval: 1.minute },
@@ -201,9 +184,5 @@ module Gitlab
scoped_user.username.downcase.in?(users_allowlist)
end
end
-
- private
-
- attr_reader :key, :options
end
end
diff --git a/lib/gitlab/audit/ci_runner_token_author.rb b/lib/gitlab/audit/ci_runner_token_author.rb
new file mode 100644
index 00000000000..5f83725b5a3
--- /dev/null
+++ b/lib/gitlab/audit/ci_runner_token_author.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Audit
+ class CiRunnerTokenAuthor < Gitlab::Audit::NullAuthor
+ # Represents a CI Runner token (registration or authentication)
+ #
+ # @param [AuditEvent] audit_event event representing a runner registration/un-registration operation
+ def initialize(audit_event)
+ if audit_event.details.include?(:runner_authentication_token)
+ token = audit_event.details[:runner_authentication_token]
+ name = "Authentication token: #{token}"
+ elsif audit_event.details.include?(:runner_registration_token)
+ token = audit_event.details[:runner_registration_token]
+ name = "Registration token: #{token}"
+ else
+ raise ArgumentError, 'Runner token missing'
+ end
+
+ super(id: -1, name: name)
+
+ @entity_type = audit_event.entity_type
+ @entity_path = audit_event.entity_path
+ end
+
+ def full_path
+ url_helpers = ::Gitlab::Routing.url_helpers
+
+ case @entity_type
+ when 'Group'
+ url_helpers.group_settings_ci_cd_path(@entity_path, anchor: 'js-runners-settings')
+ when 'Project'
+ project = Project.find_by_full_path(@entity_path)
+ url_helpers.project_settings_ci_cd_path(project, anchor: 'js-runners-settings') if project
+ else
+ url_helpers.admin_runners_path
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/audit/null_author.rb b/lib/gitlab/audit/null_author.rb
index 0b0e6a46fe4..80e0c4ddf58 100644
--- a/lib/gitlab/audit/null_author.rb
+++ b/lib/gitlab/audit/null_author.rb
@@ -14,9 +14,13 @@ module Gitlab
# @param [Integer] id
# @param [String] name
#
- # @return [Gitlab::Audit::UnauthenticatedAuthor, Gitlab::Audit::DeletedAuthor]
- def self.for(id, name)
- if id == -1
+ # @return [Gitlab::Audit::UnauthenticatedAuthor, Gitlab::Audit::DeletedAuthor, Gitlab::Audit::CiRunnerTokenAuthor]
+ def self.for(id, audit_event)
+ name = audit_event[:author_name] || audit_event.details[:author_name]
+
+ if audit_event.target_type == ::Ci::Runner.name
+ Gitlab::Audit::CiRunnerTokenAuthor.new(audit_event)
+ elsif id == -1
Gitlab::Audit::UnauthenticatedAuthor.new(name: name)
else
Gitlab::Audit::DeletedAuthor.new(id: id, name: name)
@@ -31,6 +35,10 @@ module Gitlab
def current_sign_in_ip
nil
end
+
+ def full_path
+ nil
+ end
end
end
end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 38bc50a2cb8..5d5a431f206 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -6,25 +6,35 @@ module Gitlab
IpBlacklisted = Class.new(StandardError)
# Scopes used for GitLab API access
- API_SCOPES = [:api, :read_user, :read_api].freeze
+ API_SCOPE = :api
+ READ_API_SCOPE = :read_api
+ READ_USER_SCOPE = :read_user
+ API_SCOPES = [API_SCOPE, READ_API_SCOPE, READ_USER_SCOPE].freeze
+
+ PROFILE_SCOPE = :profile
+ EMAIL_SCOPE = :email
+ OPENID_SCOPE = :openid
+ # Scopes used for OpenID Connect
+ OPENID_SCOPES = [OPENID_SCOPE].freeze
+ # OpenID Connect profile scopes
+ PROFILE_SCOPES = [PROFILE_SCOPE, EMAIL_SCOPE].freeze
# Scopes used for GitLab Repository access
- REPOSITORY_SCOPES = [:read_repository, :write_repository].freeze
+ READ_REPOSITORY_SCOPE = :read_repository
+ WRITE_REPOSITORY_SCOPE = :write_repository
+ REPOSITORY_SCOPES = [READ_REPOSITORY_SCOPE, WRITE_REPOSITORY_SCOPE].freeze
# Scopes used for GitLab Docker Registry access
- REGISTRY_SCOPES = [:read_registry, :write_registry].freeze
+ READ_REGISTRY_SCOPE = :read_registry
+ WRITE_REGISTRY_SCOPE = :write_registry
+ REGISTRY_SCOPES = [READ_REGISTRY_SCOPE, WRITE_REGISTRY_SCOPE].freeze
# Scopes used for GitLab as admin
- ADMIN_SCOPES = [:sudo].freeze
-
- # Scopes used for OpenID Connect
- OPENID_SCOPES = [:openid].freeze
-
- # OpenID Connect profile scopes
- PROFILE_SCOPES = [:profile, :email].freeze
+ SUDO_SCOPE = :sudo
+ ADMIN_SCOPES = [SUDO_SCOPE].freeze
# Default scopes for OAuth applications that don't define their own
- DEFAULT_SCOPES = [:api].freeze
+ DEFAULT_SCOPES = [API_SCOPE].freeze
CI_JOB_USER = 'gitlab-ci-token'
@@ -207,7 +217,7 @@ module Gitlab
return unless valid_scoped_token?(token, all_available_scopes)
if project && token.user.project_bot?
- return unless token_bot_in_project?(token.user, project) || token_bot_in_group?(token.user, project)
+ return unless token_bot_in_resource?(token.user, project)
end
if token.user.can_log_in_with_non_expired_password? || token.user.project_bot?
@@ -229,6 +239,10 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ def token_bot_in_resource?(user, project)
+ token_bot_in_project?(user, project) || token_bot_in_group?(user, project)
+ end
+
def valid_oauth_token?(token)
token && token.accessible? && valid_scoped_token?(token, Doorkeeper.configuration.scopes)
end
@@ -309,7 +323,7 @@ module Gitlab
return unless build.project.builds_enabled?
if build.user
- return unless build.user.can_log_in_with_non_expired_password? || (build.user.project_bot? && build.project.bots&.include?(build.user))
+ return unless build.user.can_log_in_with_non_expired_password? || (build.user.project_bot? && token_bot_in_resource?(build.user, build.project))
# If user is assigned to build, use restricted credentials of user
Gitlab::Auth::Result.new(build.user, build.project, :build, build_authentication_abilities)
diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb
index 1a9259a4f0e..b6ed6bbf2df 100644
--- a/lib/gitlab/auth/request_authenticator.rb
+++ b/lib/gitlab/auth/request_authenticator.rb
@@ -108,3 +108,5 @@ module Gitlab
end
end
end
+
+Gitlab::Auth::RequestAuthenticator.prepend_mod
diff --git a/lib/gitlab/background_migration/backfill_ci_queuing_tables.rb b/lib/gitlab/background_migration/backfill_ci_queuing_tables.rb
new file mode 100644
index 00000000000..63112b52584
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_ci_queuing_tables.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Ensure queuing entries are present even if admins skip upgrades.
+ class BackfillCiQueuingTables
+ class Namespace < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'namespaces'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'projects'
+
+ belongs_to :namespace
+ has_one :ci_cd_settings, class_name: 'Gitlab::BackgroundMigration::BackfillCiQueuingTables::ProjectCiCdSetting'
+
+ def group_runners_enabled?
+ return false unless ci_cd_settings
+
+ ci_cd_settings.group_runners_enabled?
+ end
+ end
+
+ class ProjectCiCdSetting < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'project_ci_cd_settings'
+ end
+
+ class Taggings < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'taggings'
+ end
+
+ module Ci
+ class Build < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'ci_builds'
+ self.inheritance_column = :_type_disabled
+
+ belongs_to :project
+
+ scope :pending, -> do
+ where(status: :pending, type: 'Ci::Build', runner_id: nil)
+ end
+
+ def self.each_batch(of: 1000, column: :id, order: { runner_id: :asc, id: :asc }, order_hint: nil)
+ start = except(:select).select(column).reorder(order)
+ start = start.take
+ return unless start
+
+ start_id = start[column]
+ arel_table = self.arel_table
+
+ 1.step do |index|
+ start_cond = arel_table[column].gteq(start_id)
+ stop = except(:select).select(column).where(start_cond).reorder(order)
+ stop = stop.offset(of).limit(1).take
+ relation = where(start_cond)
+
+ if stop
+ stop_id = stop[column]
+ start_id = stop_id
+ stop_cond = arel_table[column].lt(stop_id)
+ relation = relation.where(stop_cond)
+ end
+
+ # Any ORDER BYs are useless for this relation and can lead to less
+ # efficient UPDATE queries, hence we get rid of it.
+ relation = relation.except(:order)
+
+ # Using unscoped is necessary to prevent leaking the current scope used by
+ # ActiveRecord to chain `each_batch` method.
+ unscoped { yield relation, index }
+
+ break unless stop
+ end
+ end
+
+ def tags_ids
+ BackfillCiQueuingTables::Taggings
+ .where(taggable_id: id, taggable_type: 'CommitStatus')
+ .pluck(:tag_id)
+ end
+ end
+
+ class PendingBuild < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'ci_pending_builds'
+
+ class << self
+ def upsert_from_build!(build)
+ entry = self.new(args_from_build(build))
+
+ self.upsert(
+ entry.attributes.compact,
+ returning: %w[build_id],
+ unique_by: :build_id)
+ end
+
+ def args_from_build(build)
+ project = build.project
+
+ {
+ build_id: build.id,
+ project_id: build.project_id,
+ protected: build.protected?,
+ namespace_id: project.namespace_id,
+ tag_ids: build.tags_ids,
+ instance_runners_enabled: project.shared_runners_enabled?,
+ namespace_traversal_ids: namespace_traversal_ids(project)
+ }
+ end
+
+ def namespace_traversal_ids(project)
+ if project.group_runners_enabled?
+ project.namespace.traversal_ids
+ else
+ []
+ end
+ end
+ end
+ end
+ end
+
+ BATCH_SIZE = 100
+
+ def perform(start_id, end_id)
+ scope = BackfillCiQueuingTables::Ci::Build.pending.where(id: start_id..end_id)
+ pending_builds_query = BackfillCiQueuingTables::Ci::PendingBuild
+ .where('ci_builds.id = ci_pending_builds.build_id')
+ .select(1)
+
+ scope.each_batch(of: BATCH_SIZE) do |builds|
+ builds = builds.where('NOT EXISTS (?)', pending_builds_query)
+ builds = builds.includes(:project, project: [:namespace, :ci_cd_settings])
+
+ builds.each do |build|
+ BackfillCiQueuingTables::Ci::PendingBuild.upsert_from_build!(build)
+ end
+ end
+
+ mark_job_as_succeeded(start_id, end_id)
+ end
+
+ private
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ self.class.name.demodulize,
+ arguments)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_designs_relative_position.rb b/lib/gitlab/background_migration/backfill_designs_relative_position.rb
deleted file mode 100644
index efbb1b950ad..00000000000
--- a/lib/gitlab/background_migration/backfill_designs_relative_position.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration is not needed anymore and was disabled, because we're now
- # also backfilling design positions immediately before moving a design.
- #
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39555
- class BackfillDesignsRelativePosition
- def perform(issue_ids)
- # no-op
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_integrations_type_new.rb b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
index d1a939af58e..a234cebfce5 100644
--- a/lib/gitlab/background_migration/backfill_integrations_type_new.rb
+++ b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
@@ -9,7 +9,7 @@ module Gitlab
include Gitlab::Database::DynamicModelHelpers
def perform(start_id, stop_id, batch_table, batch_column, sub_batch_size, pause_ms)
- parent_batch_relation = define_batchable_model(batch_table)
+ parent_batch_relation = define_batchable_model(batch_table, connection: connection)
.where(batch_column => start_id..stop_id)
parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size) do |sub_batch|
diff --git a/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb b/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb
deleted file mode 100644
index 6dc92672929..00000000000
--- a/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class that will fill the project_repositories table for projects that
- # are on legacy storage and an entry is is missing in this table.
- class BackfillLegacyProjectRepositories < BackfillProjectRepositories
- private
-
- def projects
- Project.with_parent.on_legacy_storage
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route.rb b/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route.rb
new file mode 100644
index 00000000000..fe3edd3322b
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfills the `routes.namespace_id` column, by copying source_id value
+ # (for groups and user namespaces source_id == namespace_id)
+ class BackfillNamespaceIdForNamespaceRoute
+ include Gitlab::Database::DynamicModelHelpers
+
+ def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, pause_ms)
+ parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id)
+
+ parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size) do |sub_batch|
+ batch_metrics.time_operation(:update_all) do
+ sub_batch.update_all('namespace_id=source_id')
+ end
+
+ pause_ms = [0, pause_ms].max
+ sleep(pause_ms * 0.001)
+ end
+ end
+
+ def batch_metrics
+ @batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new
+ end
+
+ private
+
+ def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
+ define_batchable_model(source_table, connection: ActiveRecord::Base.connection)
+ .joins('inner join namespaces on routes.source_id = namespaces.id')
+ .where(source_key_column => start_id..stop_id)
+ .where(namespace_id: nil)
+ .where(source_type: 'Namespace')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb b/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
deleted file mode 100644
index 030dfd2d99b..00000000000
--- a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Update existent project update_at column after their repository storage was moved
- class BackfillProjectUpdatedAtAfterRepositoryStorageMove
- def perform(*project_ids)
- updated_repository_storages = Projects::RepositoryStorageMove.select("project_id, MAX(updated_at) as updated_at").where(project_id: project_ids).group(:project_id)
-
- Project.connection.execute <<-SQL
- WITH repository_storage_cte as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- #{updated_repository_storages.to_sql}
- )
- UPDATE projects
- SET updated_at = (repository_storage_cte.updated_at + interval '1 second')
- FROM repository_storage_cte
- WHERE projects.id = repository_storage_cte.project_id AND projects.updated_at <= repository_storage_cte.updated_at
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_user_namespace.rb b/lib/gitlab/background_migration/backfill_user_namespace.rb
index f55eaa3b14e..ab569e236fb 100644
--- a/lib/gitlab/background_migration/backfill_user_namespace.rb
+++ b/lib/gitlab/background_migration/backfill_user_namespace.rb
@@ -29,7 +29,7 @@ module Gitlab
end
def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
- define_batchable_model(source_table)
+ define_batchable_model(source_table, connection: connection)
.where(source_key_column => start_id..stop_id)
.where(type: nil)
end
diff --git a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
deleted file mode 100644
index 41f7f7f2f24..00000000000
--- a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class BackfillVersionDataFromGitaly
- def perform(issue_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly.prepend_mod_with('Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly')
diff --git a/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb
new file mode 100644
index 00000000000..f352c527b54
--- /dev/null
+++ b/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module BatchingStrategies
+ # Batching class to use for back-filling project namespaces for a single group.
+ # Batches over the projects table and id column combination, scoped to a given group returning the MIN() and MAX()
+ # values for the next batch as an array.
+ #
+ # If no more batches exist in the table, returns nil.
+ class BackfillProjectNamespacePerGroupBatchingStrategy < PrimaryKeyBatchingStrategy
+ # Finds and returns the next batch in the table.
+ #
+ # table_name - The table to batch over
+ # column_name - The column to batch over
+ # batch_min_value - The minimum value which the next batch will start at
+ # batch_size - The size of the next batch
+ # job_arguments - The migration job arguments
+ def next_batch(table_name, column_name, batch_min_value:, batch_size:, job_arguments:)
+ next_batch_bounds = nil
+ model_class = ::Gitlab::BackgroundMigration::ProjectNamespaces::Models::Project
+ quoted_column_name = model_class.connection.quote_column_name(column_name)
+ projects_table = model_class.arel_table
+ hierarchy_cte_sql = Arel::Nodes::SqlLiteral.new(::Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces.hierarchy_cte(job_arguments.first))
+ relation = model_class.where(projects_table[:namespace_id].in(hierarchy_cte_sql)).where("#{quoted_column_name} >= ?", batch_min_value)
+
+ relation.each_batch(of: batch_size, column: column_name) do |batch| # rubocop:disable Lint/UnreachableLoop
+ next_batch_bounds = batch.pluck(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})")).first
+
+ break
+ end
+
+ next_batch_bounds
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
index 80693728e86..09700438d47 100644
--- a/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
+++ b/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
@@ -17,8 +17,9 @@ module Gitlab
# column_name - The column to batch over
# batch_min_value - The minimum value which the next batch will start at
# batch_size - The size of the next batch
- def next_batch(table_name, column_name, batch_min_value:, batch_size:)
- model_class = define_batchable_model(table_name)
+ # job_arguments - The migration job arguments
+ def next_batch(table_name, column_name, batch_min_value:, batch_size:, job_arguments:)
+ model_class = define_batchable_model(table_name, connection: ActiveRecord::Base.connection)
quoted_column_name = model_class.connection.quote_column_name(column_name)
relation = model_class.where("#{quoted_column_name} >= ?", batch_min_value)
diff --git a/lib/gitlab/background_migration/calculate_wiki_sizes.rb b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
deleted file mode 100644
index 7b334b9c1d0..00000000000
--- a/lib/gitlab/background_migration/calculate_wiki_sizes.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CalculateWikiSizes
- def perform(start_id, stop_id)
- ::ProjectStatistics.where(wiki_size: nil)
- .where(id: start_id..stop_id)
- .includes(project: [:route, :group, namespace: [:owner]]).find_each do |statistics|
- statistics.refresh!(only: [:wiki_size])
- rescue StandardError => e
- Gitlab::AppLogger.error "Failed to update wiki statistics. id: #{statistics.id} message: #{e.message}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb b/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb
deleted file mode 100644
index bf69ef352cc..00000000000
--- a/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CleanupOptimisticLockingNulls
- QUERY_ITEM_SIZE = 1_000
-
- # table - The name of the table the migration is performed for.
- # start_id - The ID of the object to start at
- # stop_id - The ID of the object to end at
- def perform(start_id, stop_id, table)
- model = define_model_for(table)
-
- # After analysis done, a batch size of 1,000 items per query was found to be
- # the most optimal. Discussion in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18418#note_282285336
- (start_id..stop_id).each_slice(QUERY_ITEM_SIZE).each do |range|
- model
- .where(lock_version: nil)
- .where("ID BETWEEN ? AND ?", range.first, range.last)
- .update_all(lock_version: 0)
- end
- end
-
- def define_model_for(table)
- Class.new(ActiveRecord::Base) do
- self.table_name = table
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
index 529b8cdf8d4..137b4d4bc4e 100644
--- a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
+++ b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
@@ -13,7 +13,7 @@ module Gitlab
# - We skip the NULL checks as they may result in not using an index scan
# - The table that is migrated does _not_ need `id` as the primary key
# We use the provided primary_key column to perform the update.
- class CopyColumnUsingBackgroundMigrationJob
+ class CopyColumnUsingBackgroundMigrationJob < BaseJob
include Gitlab::Database::DynamicModelHelpers
# start_id - The start ID of the range of rows to update.
@@ -52,12 +52,8 @@ module Gitlab
private
- def connection
- ActiveRecord::Base.connection
- end
-
def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
- define_batchable_model(source_table).where(source_key_column => start_id..stop_id)
+ define_batchable_model(source_table, connection: connection).where(source_key_column => start_id..stop_id)
end
def column_assignment_clauses(copy_from, copy_to)
diff --git a/lib/gitlab/background_migration/delete_orphaned_deployments.rb b/lib/gitlab/background_migration/delete_orphaned_deployments.rb
index 9ac4111ff0f..5d41a46c8cd 100644
--- a/lib/gitlab/background_migration/delete_orphaned_deployments.rb
+++ b/lib/gitlab/background_migration/delete_orphaned_deployments.rb
@@ -15,7 +15,7 @@ module Gitlab
end
def orphaned_deployments
- define_batchable_model('deployments')
+ define_batchable_model('deployments', connection: ActiveRecord::Base.connection)
.where('NOT EXISTS (SELECT 1 FROM environments WHERE deployments.environment_id = environments.id)')
end
diff --git a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
deleted file mode 100644
index 7b5c32e3d6d..00000000000
--- a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # save validity time pages domain
- class FillValidTimeForPagesDomainCertificate
- # define PagesDomain with only needed code
- class PagesDomain < ActiveRecord::Base
- self.table_name = 'pages_domains'
-
- def x509
- return unless certificate.present?
-
- @x509 ||= OpenSSL::X509::Certificate.new(certificate)
- rescue OpenSSL::X509::CertificateError
- nil
- end
- end
-
- def perform(start_id, stop_id)
- PagesDomain.where(id: start_id..stop_id).find_each do |domain|
- # for some reason activerecord doesn't append timezone, iso8601 forces this
- domain.update_columns(
- certificate_valid_not_before: domain.x509&.not_before&.iso8601,
- certificate_valid_not_after: domain.x509&.not_after&.iso8601
- )
- rescue StandardError => e
- Gitlab::AppLogger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb b/lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb
new file mode 100644
index 00000000000..2c09b8c0b24
--- /dev/null
+++ b/lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class FixIncorrectMaxSeatsUsed
+ def perform(batch = nil)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::FixIncorrectMaxSeatsUsed.prepend_mod_with('Gitlab::BackgroundMigration::FixIncorrectMaxSeatsUsed')
diff --git a/lib/gitlab/background_migration/fix_pages_access_level.rb b/lib/gitlab/background_migration/fix_pages_access_level.rb
deleted file mode 100644
index 8e46021bd93..00000000000
--- a/lib/gitlab/background_migration/fix_pages_access_level.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # corrects stored pages access level on db depending on project visibility
- class FixPagesAccessLevel
- # Copy routable here to avoid relying on application logic
- module Routable
- def build_full_path
- if parent && path
- parent.build_full_path + '/' + path
- else
- path
- end
- end
- end
-
- # Namespace
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
- self.inheritance_column = :_type_disabled
-
- include Routable
-
- belongs_to :parent, class_name: "Namespace"
- end
-
- # Project
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- self.inheritance_column = :_type_disabled
-
- include Routable
-
- belongs_to :namespace
- alias_method :parent, :namespace
- alias_attribute :parent_id, :namespace_id
-
- PRIVATE = 0
- INTERNAL = 10
- PUBLIC = 20
-
- def pages_deployed?
- Dir.exist?(public_pages_path)
- end
-
- def public_pages_path
- File.join(pages_path, 'public')
- end
-
- def pages_path
- # TODO: when we migrate Pages to work with new storage types, change here to use disk_path
- File.join(Settings.pages.path, build_full_path)
- end
- end
-
- # ProjectFeature
- class ProjectFeature < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'project_features'
-
- belongs_to :project
-
- PRIVATE = 10
- ENABLED = 20
- PUBLIC = 30
- end
-
- def perform(start_id, stop_id)
- fix_public_access_level(start_id, stop_id)
-
- make_internal_projects_public(start_id, stop_id)
-
- fix_private_access_level(start_id, stop_id)
- end
-
- private
-
- def access_control_is_enabled
- @access_control_is_enabled = Gitlab.config.pages.access_control
- end
-
- # Public projects are allowed to have only enabled pages_access_level
- # which is equivalent to public
- def fix_public_access_level(start_id, stop_id)
- project_features(start_id, stop_id, ProjectFeature::PUBLIC, Project::PUBLIC).each_batch do |features|
- features.update_all(pages_access_level: ProjectFeature::ENABLED)
- end
- end
-
- # If access control is disabled and project has pages deployed
- # project will become unavailable when access control will become enabled
- # we make these projects public to avoid negative surprise to user
- def make_internal_projects_public(start_id, stop_id)
- return if access_control_is_enabled
-
- project_features(start_id, stop_id, ProjectFeature::ENABLED, Project::INTERNAL).find_each do |project_feature|
- next unless project_feature.project.pages_deployed?
-
- project_feature.update(pages_access_level: ProjectFeature::PUBLIC)
- end
- end
-
- # Private projects are not allowed to have enabled access level, only `private` and `public`
- # If access control is enabled, these projects currently behave as if they have `private` pages_access_level
- # if access control is disabled, these projects currently behave as if they have `public` pages_access_level
- # so we preserve this behaviour for projects with pages already deployed
- # for project without pages we always set `private` access_level
- def fix_private_access_level(start_id, stop_id)
- project_features(start_id, stop_id, ProjectFeature::ENABLED, Project::PRIVATE).find_each do |project_feature|
- if access_control_is_enabled
- project_feature.update!(pages_access_level: ProjectFeature::PRIVATE)
- else
- fixed_access_level = project_feature.project.pages_deployed? ? ProjectFeature::PUBLIC : ProjectFeature::PRIVATE
- project_feature.update!(pages_access_level: fixed_access_level)
- end
- end
- end
-
- def project_features(start_id, stop_id, pages_access_level, project_visibility_level)
- ProjectFeature.where(id: start_id..stop_id).joins(:project)
- .where(pages_access_level: pages_access_level)
- .where(projects: { visibility_level: project_visibility_level })
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
deleted file mode 100644
index 160e6d2fe8b..00000000000
--- a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class GenerateGitlabSubscriptions
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::GenerateGitlabSubscriptions.prepend_mod_with('Gitlab::BackgroundMigration::GenerateGitlabSubscriptions')
diff --git a/lib/gitlab/background_migration/job_coordinator.rb b/lib/gitlab/background_migration/job_coordinator.rb
index 5dc77f935e3..b7d47c389df 100644
--- a/lib/gitlab/background_migration/job_coordinator.rb
+++ b/lib/gitlab/background_migration/job_coordinator.rb
@@ -10,28 +10,32 @@ module Gitlab
# Also provides a database connection to the correct tracking database.
class JobCoordinator # rubocop:disable Metrics/ClassLength
class << self
+ def for_tracking_database(tracking_database)
+ worker_class = worker_for_tracking_database[tracking_database]
+
+ if worker_class.nil?
+ raise ArgumentError, "tracking_database must be one of [#{worker_for_tracking_database.keys.join(', ')}]"
+ end
+
+ new(worker_class)
+ end
+
+ private
+
def worker_classes
@worker_classes ||= [
- BackgroundMigrationWorker
+ ::BackgroundMigrationWorker,
+ ::BackgroundMigration::CiDatabaseWorker
].freeze
end
def worker_for_tracking_database
@worker_for_tracking_database ||= worker_classes
+ .select { |worker_class| Gitlab::Database.has_config?(worker_class.tracking_database) }
.index_by(&:tracking_database)
.with_indifferent_access
.freeze
end
-
- def for_tracking_database(tracking_database)
- worker_class = worker_for_tracking_database[tracking_database]
-
- if worker_class.nil?
- raise ArgumentError, "tracking_database must be one of [#{worker_for_tracking_database.keys.join(', ')}]"
- end
-
- new(worker_class)
- end
end
attr_reader :worker_class
@@ -146,7 +150,7 @@ module Gitlab
def connection
@connection ||= Gitlab::Database
.database_base_models
- .fetch(worker_class.tracking_database, Gitlab::Database::PRIMARY_DATABASE_NAME)
+ .fetch(worker_class.tracking_database)
.connection
end
end
diff --git a/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb b/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
deleted file mode 100644
index d85f980d3f1..00000000000
--- a/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-module Gitlab
- module BackgroundMigration
- # EE-specific migration
- class MigrateDevopsSegmentsToGroups
- def perform
- # no-op for CE
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups.prepend_mod_with('Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups')
diff --git a/lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb b/lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb
new file mode 100644
index 00000000000..bcc02c1dbf2
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MigrateJobArtifactRegistryToSsf
+ def perform(*job_artifact_ids)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MigrateJobArtifactRegistryToSsf.prepend_mod_with('Gitlab::BackgroundMigration::MigrateJobArtifactRegistryToSsf')
diff --git a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
deleted file mode 100644
index 909bf10341a..00000000000
--- a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class populates the `finding_uuid` attribute for
- # the existing `vulnerability_feedback` records.
- class PopulateFindingUuidForVulnerabilityFeedback
- REPORT_TYPES = {
- sast: 0,
- dependency_scanning: 1,
- container_scanning: 2,
- dast: 3,
- secret_detection: 4,
- coverage_fuzzing: 5,
- api_fuzzing: 6
- }.freeze
-
- class VulnerabilityFeedback < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'vulnerability_feedback'
-
- enum category: REPORT_TYPES
-
- scope :in_range, -> (start, stop) { where(id: start..stop) }
- scope :without_uuid, -> { where(finding_uuid: nil) }
-
- def self.load_vulnerability_findings
- all.to_a.tap { |collection| collection.each(&:vulnerability_finding) }
- end
-
- def set_finding_uuid
- return unless vulnerability_finding.present? && vulnerability_finding.primary_identifier.present?
-
- update_column(:finding_uuid, calculated_uuid)
- rescue StandardError => error
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
- end
-
- def vulnerability_finding
- BatchLoader.for(finding_key).batch do |finding_keys, loader|
- project_ids = finding_keys.map { |key| key[:project_id] }
- categories = finding_keys.map { |key| key[:category] }
- fingerprints = finding_keys.map { |key| key[:project_fingerprint] }
-
- findings = Finding.with_primary_identifier.where(
- project_id: project_ids.uniq,
- report_type: categories.uniq,
- project_fingerprint: fingerprints.uniq
- ).to_a
-
- finding_keys.each do |finding_key|
- loader.call(
- finding_key,
- findings.find { |f| finding_key == f.finding_key }
- )
- end
- end
- end
-
- private
-
- def calculated_uuid
- ::Security::VulnerabilityUUID.generate(
- report_type: category,
- primary_identifier_fingerprint: vulnerability_finding.primary_identifier.fingerprint,
- location_fingerprint: vulnerability_finding.location_fingerprint,
- project_id: project_id
- )
- end
-
- def finding_key
- {
- project_id: project_id,
- category: category,
- project_fingerprint: project_fingerprint
- }
- end
- end
-
- class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
- include ShaAttribute
-
- self.table_name = 'vulnerability_occurrences'
-
- sha_attribute :project_fingerprint
- sha_attribute :location_fingerprint
-
- belongs_to :primary_identifier, class_name: 'Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback::Identifier'
-
- enum report_type: REPORT_TYPES
-
- scope :with_primary_identifier, -> { includes(:primary_identifier) }
-
- def finding_key
- {
- project_id: project_id,
- category: report_type,
- project_fingerprint: project_fingerprint
- }
- end
- end
-
- class Identifier < ActiveRecord::Base # rubocop:disable Style/Documentation
- self.table_name = 'vulnerability_identifiers'
- end
-
- def perform(*range)
- feedback = VulnerabilityFeedback.without_uuid.in_range(*range).load_vulnerability_findings
- feedback.each(&:set_finding_uuid)
-
- log_info(feedback.count)
- end
-
- def log_info(feedback_count)
- ::Gitlab::BackgroundMigration::Logger.info(
- migrator: self.class.name,
- message: '`finding_uuid` attributes has been set',
- count: feedback_count
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_issue_email_participants.rb b/lib/gitlab/background_migration/populate_issue_email_participants.rb
deleted file mode 100644
index 2b959b81f45..00000000000
--- a/lib/gitlab/background_migration/populate_issue_email_participants.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class to migrate service_desk_reply_to email addresses to issue_email_participants
- class PopulateIssueEmailParticipants
- # rubocop:disable Style/Documentation
- class TmpIssue < ActiveRecord::Base
- self.table_name = 'issues'
- end
-
- def perform(start_id, stop_id)
- issues = TmpIssue.select(:id, :service_desk_reply_to, :created_at).where(id: (start_id..stop_id)).where.not(service_desk_reply_to: nil)
-
- rows = issues.map do |issue|
- {
- issue_id: issue.id,
- email: issue.service_desk_reply_to,
- created_at: issue.created_at,
- updated_at: issue.created_at
- }
- end
-
- ApplicationRecord.legacy_bulk_insert(:issue_email_participants, rows, on_conflict: :do_nothing) # rubocop:disable Gitlab/BulkInsert
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb b/lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb
new file mode 100644
index 00000000000..769ca4be7f3
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # The class to populates the non private projects counter of topics
+ class PopulateTopicsNonPrivateProjectsCount
+ SUB_BATCH_SIZE = 100
+
+ # Temporary AR model for topics
+ class Topic < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'topics'
+ end
+
+ def perform(start_id, stop_id)
+ Topic.where(id: start_id..stop_id).each_batch(of: SUB_BATCH_SIZE) do |batch|
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ WITH batched_relation AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (#{batch.select(:id).limit(SUB_BATCH_SIZE).to_sql})
+ UPDATE topics
+ SET non_private_projects_count = (
+ SELECT COUNT(*)
+ FROM project_topics
+ INNER JOIN projects
+ ON project_topics.project_id = projects.id
+ WHERE project_topics.topic_id = batched_relation.id
+ AND projects.visibility_level > 0
+ )
+ FROM batched_relation
+ WHERE topics.id = batched_relation.id
+ SQL
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_vulnerability_reads.rb b/lib/gitlab/background_migration/populate_vulnerability_reads.rb
new file mode 100644
index 00000000000..7b6d4c1ff81
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_vulnerability_reads.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop:disable Style/Documentation
+ class PopulateVulnerabilityReads
+ include Gitlab::Database::DynamicModelHelpers
+
+ PAUSE_SECONDS = 0.1
+
+ def perform(start_id, end_id, sub_batch_size)
+ vulnerability_model.where(id: start_id..end_id).each_batch(of: sub_batch_size) do |sub_batch|
+ first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ connection.execute(insert_query(first, last))
+
+ sleep PAUSE_SECONDS
+ end
+
+ mark_job_as_succeeded(start_id, end_id, sub_batch_size)
+ end
+
+ private
+
+ def vulnerability_model
+ define_batchable_model('vulnerabilities', connection: connection)
+ end
+
+ def connection
+ ActiveRecord::Base.connection
+ end
+
+ def insert_query(start_id, end_id)
+ <<~SQL
+ INSERT INTO vulnerability_reads (
+ vulnerability_id,
+ project_id,
+ scanner_id,
+ report_type,
+ severity,
+ state,
+ has_issues,
+ resolved_on_default_branch,
+ uuid,
+ location_image
+ )
+ SELECT
+ vulnerabilities.id,
+ vulnerabilities.project_id,
+ vulnerability_scanners.id,
+ vulnerabilities.report_type,
+ vulnerabilities.severity,
+ vulnerabilities.state,
+ CASE
+ WHEN
+ vulnerability_issue_links.vulnerability_id IS NOT NULL
+ THEN
+ true
+ ELSE
+ false
+ END
+ has_issues,
+ vulnerabilities.resolved_on_default_branch,
+ vulnerability_occurrences.uuid::uuid,
+ vulnerability_occurrences.location ->> 'image'
+ FROM
+ vulnerabilities
+ INNER JOIN vulnerability_occurrences ON vulnerability_occurrences.vulnerability_id = vulnerabilities.id
+ INNER JOIN vulnerability_scanners ON vulnerability_scanners.id = vulnerability_occurrences.scanner_id
+ LEFT JOIN vulnerability_issue_links ON vulnerability_issue_links.vulnerability_id = vulnerabilities.id
+ WHERE vulnerabilities.id BETWEEN #{start_id} AND #{end_id}
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ SQL
+ end
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ self.class.name.demodulize,
+ arguments
+ )
+ end
+ end
+ # rubocop:enable Style/Documentation
+ end
+end
diff --git a/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
index 8e94c16369e..ba3f7c47047 100644
--- a/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
+++ b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
@@ -5,19 +5,15 @@ module Gitlab
module ProjectNamespaces
# Back-fill project namespaces for projects that do not yet have a namespace.
#
- # TODO: remove this comment when an actuall backfill migration is added.
- #
- # This is first being added without an actual migration as we need to initially test
- # if backfilling project namespaces affects performance in any significant way.
# rubocop: disable Metrics/ClassLength
class BackfillProjectNamespaces
- BATCH_SIZE = 100
- DELETE_BATCH_SIZE = 10
+ SUB_BATCH_SIZE = 25
PROJECT_NAMESPACE_STI_NAME = 'Project'
IsolatedModels = ::Gitlab::BackgroundMigration::ProjectNamespaces::Models
- def perform(start_id, end_id, namespace_id, migration_type = 'up')
+ def perform(start_id, end_id, migration_table_name, migration_column_name, sub_batch_size, pause_ms, namespace_id, migration_type = 'up')
+ @sub_batch_size = sub_batch_size || SUB_BATCH_SIZE
load_project_ids(start_id, end_id, namespace_id)
case migration_type
@@ -34,10 +30,13 @@ module Gitlab
private
- attr_accessor :project_ids
+ attr_accessor :project_ids, :sub_batch_size
def backfill_project_namespaces(namespace_id)
- project_ids.each_slice(BATCH_SIZE) do |project_ids|
+ project_ids.each_slice(sub_batch_size) do |project_ids|
+ ActiveRecord::Base.connection.execute("select gin_clean_pending_list('index_namespaces_on_name_trigram')")
+ ActiveRecord::Base.connection.execute("select gin_clean_pending_list('index_namespaces_on_path_trigram')")
+
# We need to lock these project records for the period when we create project namespaces
# and link them to projects so that if a project is modified in the time between creating
# project namespaces `batch_insert_namespaces` and linking them to projects `batch_update_projects`
@@ -45,18 +44,17 @@ module Gitlab
#
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72527#note_730679469
Project.transaction do
- Project.where(id: project_ids).select(:id).lock!('FOR UPDATE')
+ Project.where(id: project_ids).select(:id).lock!('FOR UPDATE').load
batch_insert_namespaces(project_ids)
batch_update_projects(project_ids)
+ batch_update_project_namespaces_traversal_ids(project_ids)
end
-
- batch_update_project_namespaces_traversal_ids(project_ids)
end
end
def cleanup_backfilled_project_namespaces(namespace_id)
- project_ids.each_slice(BATCH_SIZE) do |project_ids|
+ project_ids.each_slice(sub_batch_size) do |project_ids|
# IMPORTANT: first nullify project_namespace_id in projects table to avoid removing projects when records
# from namespaces are deleted due to FK/triggers
nullify_project_namespaces_in_projects(project_ids)
@@ -109,7 +107,10 @@ module Gitlab
end
def delete_project_namespace_records(project_ids)
- project_ids.each_slice(DELETE_BATCH_SIZE) do |p_ids|
+ # keep the deletes a 10x smaller batch as deletes seem to be much more expensive
+ delete_batch_size = (sub_batch_size / 10).to_i + 1
+
+ project_ids.each_slice(delete_batch_size) do |p_ids|
IsolatedModels::Namespace.where(type: PROJECT_NAMESPACE_STI_NAME).where(tmp_project_id: p_ids).delete_all
end
end
@@ -117,7 +118,7 @@ module Gitlab
def load_project_ids(start_id, end_id, namespace_id)
projects = IsolatedModels::Project.arel_table
relation = IsolatedModels::Project.where(projects[:id].between(start_id..end_id))
- relation = relation.where(projects[:namespace_id].in(Arel::Nodes::SqlLiteral.new(hierarchy_cte(namespace_id)))) if namespace_id
+ relation = relation.where(projects[:namespace_id].in(Arel::Nodes::SqlLiteral.new(self.class.hierarchy_cte(namespace_id)))) if namespace_id
@project_ids = relation.pluck(:id)
end
@@ -126,7 +127,7 @@ module Gitlab
::Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillProjectNamespaces', arguments)
end
- def hierarchy_cte(root_namespace_id)
+ def self.hierarchy_cte(root_namespace_id)
<<-SQL
WITH RECURSIVE "base_and_descendants" AS (
(
diff --git a/lib/gitlab/background_migration/recalculate_project_authorizations.rb b/lib/gitlab/background_migration/recalculate_project_authorizations.rb
deleted file mode 100644
index 6a250a96c94..00000000000
--- a/lib/gitlab/background_migration/recalculate_project_authorizations.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop:disable Style/Documentation
- class RecalculateProjectAuthorizations
- def perform(user_ids)
- # no-op
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb b/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb
index 31fb5e97c5d..323f109449b 100644
--- a/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb
+++ b/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb
@@ -10,7 +10,9 @@ module Gitlab
include Gitlab::Database::DynamicModelHelpers
def perform(start_id, stop_id)
- define_batchable_model('vulnerability_finding_links').where(id: start_id..stop_id).delete_all
+ define_batchable_model('vulnerability_finding_links', connection: ActiveRecord::Base.connection)
+ .where(id: start_id..stop_id)
+ .delete_all
end
end
end
diff --git a/lib/gitlab/background_migration/sync_blocking_issues_count.rb b/lib/gitlab/background_migration/sync_blocking_issues_count.rb
deleted file mode 100644
index 49a632952fb..00000000000
--- a/lib/gitlab/background_migration/sync_blocking_issues_count.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncBlockingIssuesCount
- def perform(start_id, end_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::SyncBlockingIssuesCount.prepend_mod_with('Gitlab::BackgroundMigration::SyncBlockingIssuesCount')
diff --git a/lib/gitlab/background_migration/sync_issues_state_id.rb b/lib/gitlab/background_migration/sync_issues_state_id.rb
deleted file mode 100644
index 2a0751928b8..00000000000
--- a/lib/gitlab/background_migration/sync_issues_state_id.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncIssuesStateId
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE issues
- SET state_id =
- CASE state
- WHEN 'opened' THEN 1
- WHEN 'closed' THEN 2
- END
- WHERE state_id IS NULL
- AND id BETWEEN #{start_id} AND #{end_id}
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/sync_merge_requests_state_id.rb b/lib/gitlab/background_migration/sync_merge_requests_state_id.rb
deleted file mode 100644
index 6707e178d8b..00000000000
--- a/lib/gitlab/background_migration/sync_merge_requests_state_id.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncMergeRequestsStateId
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE merge_requests
- SET state_id =
- CASE state
- WHEN 'opened' THEN 1
- WHEN 'closed' THEN 2
- WHEN 'merged' THEN 3
- WHEN 'locked' THEN 4
- END
- WHERE state_id IS NULL
- AND id BETWEEN #{start_id} AND #{end_id}
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
index c95ef9f5515..f54bb8256d0 100644
--- a/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
+++ b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
@@ -9,7 +9,9 @@ module Gitlab
BATCH_SIZE = 100
def perform(start_id, stop_id)
- define_batchable_model('timelogs').where(spent_at: nil, id: start_id..stop_id).each_batch(of: 100) do |subbatch|
+ define_batchable_model('timelogs', connection: connection)
+ .where(spent_at: nil, id: start_id..stop_id)
+ .each_batch(of: 100) do |subbatch|
batch_start, batch_end = subbatch.pluck('min(id), max(id)').first
update_timelogs(batch_start, batch_end)
@@ -25,9 +27,12 @@ module Gitlab
SQL
end
- def execute(sql)
+ def connection
@connection ||= ::ActiveRecord::Base.connection
- @connection.execute(sql)
+ end
+
+ def execute(sql)
+ connection.execute(sql)
end
end
end
diff --git a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
deleted file mode 100644
index 665ad7abcbb..00000000000
--- a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class WrongfullyConfirmedEmailUnconfirmer
- class UserModel < ActiveRecord::Base
- alias_method :reset, :reload
-
- self.table_name = 'users'
-
- scope :active, -> { where(state: 'active', user_type: nil) } # only humans, skip bots
-
- devise :confirmable
- end
-
- class EmailModel < ActiveRecord::Base
- alias_method :reset, :reload
-
- self.table_name = 'emails'
-
- belongs_to :user
-
- devise :confirmable
-
- def self.wrongfully_confirmed_emails(start_id, stop_id)
- joins(:user)
- .merge(UserModel.active)
- .where(id: (start_id..stop_id))
- .where.not('emails.confirmed_at' => nil)
- .where('emails.confirmed_at = users.confirmed_at')
- .where('emails.email <> users.email')
- .where('NOT EXISTS (SELECT 1 FROM user_synced_attributes_metadata WHERE user_id=users.id AND email_synced IS true)')
- end
- end
-
- def perform(start_id, stop_id)
- email_records = EmailModel
- .wrongfully_confirmed_emails(start_id, stop_id)
- .to_a
-
- user_ids = email_records.map(&:user_id).uniq
-
- ActiveRecord::Base.transaction do
- update_email_records(start_id, stop_id)
- update_user_records(user_ids)
- end
-
- # Refind the records with the "real" Email model so devise will notice that the user / email is unconfirmed
- unconfirmed_email_records = ::Email.where(id: email_records.map(&:id))
- ActiveRecord::Associations::Preloader.new.preload(unconfirmed_email_records, [:user])
-
- send_emails(unconfirmed_email_records)
- end
-
- private
-
- def update_email_records(start_id, stop_id)
- EmailModel.connection.execute <<-SQL
- WITH md5_strings as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- #{email_query_for_update(start_id, stop_id).to_sql}
- )
- UPDATE #{EmailModel.connection.quote_table_name(EmailModel.table_name)}
- SET confirmed_at = NULL,
- confirmation_token = md5_strings.md5_string,
- confirmation_sent_at = NOW()
- FROM md5_strings
- WHERE id = md5_strings.email_id
- SQL
- end
-
- def update_user_records(user_ids)
- UserModel
- .where(id: user_ids)
- .update_all("confirmed_at = NULL, confirmation_sent_at = NOW(), unconfirmed_email = NULL, confirmation_token=md5(users.id::varchar || users.created_at || users.encrypted_password || '#{Integer(Time.now.to_i)}')")
- end
-
- def email_query_for_update(start_id, stop_id)
- EmailModel
- .wrongfully_confirmed_emails(start_id, stop_id)
- .select('emails.id as email_id', "md5(emails.id::varchar || emails.created_at || users.encrypted_password || '#{Integer(Time.now.to_i)}') as md5_string")
- end
-
- def send_emails(email_records)
- user_records = email_records.map(&:user).uniq
-
- user_records.each do |user|
- Gitlab::BackgroundMigration::Mailers::UnconfirmMailer.unconfirm_notification_email(user).deliver_later
- DeviseMailer.confirmation_instructions(user, user.confirmation_token).deliver_later(wait: 1.minute)
- end
-
- email_records.each do |email|
- DeviseMailer.confirmation_instructions(email, email.confirmation_token).deliver_later(wait: 1.minute)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/buffered_io.rb b/lib/gitlab/buffered_io.rb
new file mode 100644
index 00000000000..91d5d8acc52
--- /dev/null
+++ b/lib/gitlab/buffered_io.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # Net::BufferedIO is overwritten by webmock but in order to test this class, it needs to inherit from the original BufferedIO.
+ # https://github.com/bblimke/webmock/blob/867f4b290fd133658aa9530cba4ba8b8c52c0d35/lib/webmock/http_lib_adapters/net_http.rb#L266
+ parent_class = if const_defined?('WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetBufferedIO') && Rails.env.test?
+ WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetBufferedIO
+ else
+ Net::BufferedIO
+ end
+
+ class BufferedIo < parent_class
+ extend ::Gitlab::Utils::Override
+
+ HEADER_READ_TIMEOUT = 20
+
+ # rubocop: disable Style/RedundantReturn
+ # rubocop: disable Cop/LineBreakAfterGuardClauses
+ # rubocop: disable Layout/EmptyLineAfterGuardClause
+
+ # Original method:
+ # https://github.com/ruby/ruby/blob/cdb7d699d0641e8f081d590d06d07887ac09961f/lib/net/protocol.rb#L190-L200
+ override :readuntil
+ def readuntil(terminator, ignore_eof = false)
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ begin
+ until idx = @rbuf.index(terminator)
+ if (elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) > HEADER_READ_TIMEOUT
+ raise Gitlab::HTTP::HeaderReadTimeout, "Request timed out after reading headers for #{elapsed} seconds"
+ end
+
+ rbuf_fill
+ end
+
+ return rbuf_consume(idx + terminator.size)
+ rescue EOFError
+ raise unless ignore_eof
+ return rbuf_consume(@rbuf.size)
+ end
+ end
+ # rubocop: enable Style/RedundantReturn
+ # rubocop: enable Cop/LineBreakAfterGuardClauses
+ # rubocop: enable Layout/EmptyLineAfterGuardClause
+ end
+end
diff --git a/lib/gitlab/changelog/config.rb b/lib/gitlab/changelog/config.rb
index fd5d701b858..9cb3d71f5c3 100644
--- a/lib/gitlab/changelog/config.rb
+++ b/lib/gitlab/changelog/config.rb
@@ -37,7 +37,7 @@ module Gitlab
attr_accessor :date_format, :categories, :template, :tag_regex, :always_credit_user_ids
def self.from_git(project, user = nil)
- if (yaml = project.repository.changelog_config)
+ if (yaml = project.repository.changelog_config.presence)
from_hash(project, YAML.safe_load(yaml), user)
else
new(project)
diff --git a/lib/gitlab/changelog/release.rb b/lib/gitlab/changelog/release.rb
index a0d598c7464..f782197cc8e 100644
--- a/lib/gitlab/changelog/release.rb
+++ b/lib/gitlab/changelog/release.rb
@@ -67,7 +67,7 @@ module Gitlab
markdown =
begin
@config.template.evaluate(state, data).strip
- rescue TemplateParser::ParseError => e
+ rescue TemplateParser::Error => e
raise Error, e.message
end
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
index 237a6bbb0f2..e8f13a92ee7 100644
--- a/lib/gitlab/checks/branch_check.rb
+++ b/lib/gitlab/checks/branch_check.rb
@@ -41,7 +41,6 @@ module Gitlab
def prohibited_branch_checks
return if deletion?
- return unless Feature.enabled?(:prohibit_hexadecimal_branch_names, project, default_enabled: true)
if branch_name =~ /\A\h{40}\z/
raise GitAccess::ForbiddenError, ERROR_MESSAGES[:prohibited_hex_branch_name]
diff --git a/lib/gitlab/ci/badge/release/latest_release.rb b/lib/gitlab/ci/badge/release/latest_release.rb
new file mode 100644
index 00000000000..e73bb2a912a
--- /dev/null
+++ b/lib/gitlab/ci/badge/release/latest_release.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Release
+ class LatestRelease < Badge::Base
+ attr_reader :project, :release, :customization
+
+ def initialize(project, current_user, opts: {})
+ @project = project
+ @customization = {
+ key_width: opts[:key_width] ? opts[:key_width].to_i : nil,
+ key_text: opts[:key_text]
+ }
+
+ # In the future, we should support `order_by=semver` for showing the
+ # latest release based on Semantic Versioning.
+ @release = ::ReleasesFinder.new(
+ project,
+ current_user,
+ order_by: opts[:order_by]).execute.first
+ end
+
+ def entity
+ 'Latest Release'
+ end
+
+ def tag
+ @release&.tag
+ end
+
+ def metadata
+ @metadata ||= Release::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Release::Template.new(self)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/release/metadata.rb b/lib/gitlab/ci/badge/release/metadata.rb
new file mode 100644
index 00000000000..e02959b5741
--- /dev/null
+++ b/lib/gitlab/ci/badge/release/metadata.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Release
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ end
+
+ def title
+ 'Latest Release'
+ end
+
+ def image_url
+ release_project_badges_url(@project, format: :svg)
+ end
+
+ def link_url
+ project_releases_url(@project)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/release/template.rb b/lib/gitlab/ci/badge/release/template.rb
new file mode 100644
index 00000000000..65bff4371cf
--- /dev/null
+++ b/lib/gitlab/ci/badge/release/template.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Release
+ # Template object will be passed to badge.svg.erb template.
+ class Template < Badge::Template
+ STATUS_COLOR = {
+ latest: '#3076af',
+ none: '#e05d44'
+ }.freeze
+ KEY_WIDTH_DEFAULT = 90
+ VALUE_WIDTH_DEFAULT = 54
+
+ def initialize(badge)
+ @entity = badge.entity
+ @tag = badge.tag || "none"
+ @key_width = badge.customization.dig(:key_width)
+ @key_text = badge.customization.dig(:key_text)
+ end
+
+ def key_text
+ @key_text || @entity.to_s
+ end
+
+ def key_width
+ @key_width || KEY_WIDTH_DEFAULT
+ end
+
+ def value_text
+ @tag.to_s
+ end
+
+ def value_width
+ VALUE_WIDTH_DEFAULT
+ end
+
+ def value_color
+ STATUS_COLOR[@tag.to_sym] || STATUS_COLOR[:latest]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/artifacts/expire_in_parser.rb b/lib/gitlab/ci/build/artifacts/expire_in_parser.rb
index 3e8a1fb86fc..848208c5cdd 100644
--- a/lib/gitlab/ci/build/artifacts/expire_in_parser.rb
+++ b/lib/gitlab/ci/build/artifacts/expire_in_parser.rb
@@ -16,9 +16,7 @@ module Gitlab
def validate_duration
return true if never?
- parse
- rescue ChronicDuration::DurationParseError
- false
+ cached_parse
end
def seconds_from_now
@@ -29,12 +27,28 @@ module Gitlab
attr_reader :value
+ def cached_parse
+ return validation_cache[value] if validation_cache.key?(value)
+
+ validation_cache[value] = safe_parse
+ end
+
+ def safe_parse
+ parse
+ rescue ChronicDuration::DurationParseError
+ false
+ end
+
def parse
return if never?
ChronicDuration.parse(value)
end
+ def validation_cache
+ Gitlab::SafeRequestStore[:ci_expire_in_parser_cache] ||= {}
+ end
+
def never?
value.to_s.casecmp('never') == 0
end
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 82a59fdb4e1..4c5f02b4f7b 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -9,7 +9,7 @@ module Gitlab
end
def satisfied_by?(pipeline, context)
- return true if pipeline.modified_paths.nil?
+ return true unless pipeline&.modified_paths
expanded_globs = expand_globs(context)
pipeline.modified_paths.any? do |path|
diff --git a/lib/gitlab/ci/build/rules/rule/clause/if.rb b/lib/gitlab/ci/build/rules/rule/clause/if.rb
index 499a265a1e2..dd131448287 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/if.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/if.rb
@@ -8,7 +8,7 @@ module Gitlab
@expression = expression
end
- def satisfied_by?(pipeline, context)
+ def satisfied_by?(_pipeline, context)
::Gitlab::Ci::Pipeline::Expression::Statement.new(
@expression, context.variables_hash).truthful?
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 4c98941e032..2b190d89fa4 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -158,7 +158,7 @@ module Gitlab
# See more detail in the docs: https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables) if pipeline
- variables.concat(project.ci_instance_variables_for(ref: source_ref_path))
+ variables.concat(secret_variables(project: project, pipeline: pipeline))
variables.concat(project.group.ci_variables_for(source_ref_path, project)) if project.group
variables.concat(project.ci_variables_for(ref: source_ref_path))
variables.concat(pipeline.variables) if pipeline
@@ -166,6 +166,14 @@ module Gitlab
end
end
+ def secret_variables(project:, pipeline:)
+ if pipeline
+ pipeline.variables_builder.secret_instance_variables
+ else
+ Gitlab::Ci::Variables::Builder::Instance.new.secret_variables
+ end
+ end
+
def track_and_raise_for_dev_exception(error)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, @context.sentry_payload)
end
diff --git a/lib/gitlab/ci/config/entry/default.rb b/lib/gitlab/ci/config/entry/default.rb
index 145772c7a92..12d68b755b3 100644
--- a/lib/gitlab/ci/config/entry/default.rb
+++ b/lib/gitlab/ci/config/entry/default.rb
@@ -21,7 +21,7 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS
end
- entry :before_script, Entry::Script,
+ entry :before_script, Entry::Commands,
description: 'Script that will be executed before each job.',
inherit: true
@@ -33,7 +33,7 @@ module Gitlab
description: 'Docker images that will be linked to the container.',
inherit: true
- entry :after_script, Entry::Script,
+ entry :after_script, Entry::Commands,
description: 'Script that will be executed after each job.',
inherit: true
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 75bbe2ccb1b..8dd1f686132 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -45,7 +45,7 @@ module Gitlab
end
end
- entry :before_script, Entry::Script,
+ entry :before_script, Entry::Commands,
description: 'Global before script overridden in this job.',
inherit: true
@@ -55,9 +55,10 @@ module Gitlab
entry :type, Entry::Stage,
description: 'Deprecated: stage this job will be executed into.',
- inherit: false
+ inherit: false,
+ deprecation: { deprecated: '9.0', warning: '14.8', removed: '15.0' }
- entry :after_script, Entry::Script,
+ entry :after_script, Entry::Commands,
description: 'Commands that will be executed when finishing job.',
inherit: true
@@ -134,8 +135,11 @@ module Gitlab
def compose!(deps = nil)
super do
+ # The type keyword will be removed in 15.0:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/346823
if type_defined? && !stage_defined?
@entries[:stage] = @entries[:type]
+ log_and_warn_deprecated_entry(@entries[:type])
end
@entries.delete(:type)
diff --git a/lib/gitlab/ci/config/entry/jobs.rb b/lib/gitlab/ci/config/entry/jobs.rb
index b0fd9cef10b..d2a25d59669 100644
--- a/lib/gitlab/ci/config/entry/jobs.rb
+++ b/lib/gitlab/ci/config/entry/jobs.rb
@@ -15,7 +15,7 @@ module Gitlab
validate do
each_unmatched_job do |name|
- errors.add(name, 'config should implement a script: or a trigger: keyword')
+ errors.add(name.to_s, 'config should implement a script: or a trigger: keyword')
end
unless has_visible_job?
diff --git a/lib/gitlab/ci/config/entry/root.rb b/lib/gitlab/ci/config/entry/root.rb
index 41a3c87037b..7b58ef0b8ab 100644
--- a/lib/gitlab/ci/config/entry/root.rb
+++ b/lib/gitlab/ci/config/entry/root.rb
@@ -32,7 +32,7 @@ module Gitlab
description: 'List of external YAML files to include.',
reserved: true
- entry :before_script, Entry::Script,
+ entry :before_script, Entry::Commands,
description: 'Script that will be executed before each job.',
reserved: true
@@ -44,7 +44,7 @@ module Gitlab
description: 'Docker images that will be linked to the container.',
reserved: true
- entry :after_script, Entry::Script,
+ entry :after_script, Entry::Commands,
description: 'Script that will be executed after each job.',
reserved: true
@@ -60,7 +60,7 @@ module Gitlab
entry :types, Entry::Stages,
description: 'Deprecated: stages for this pipeline.',
reserved: true,
- deprecation: { deprecated: '9.0', warning: '14.8', removed: '15.0', documentation: 'https://docs.gitlab.com/ee/ci/yaml/#deprecated-keywords' }
+ deprecation: { deprecated: '9.0', warning: '14.8', removed: '15.0' }
entry :cache, Entry::Caches,
description: 'Configure caching between build jobs.',
@@ -122,6 +122,8 @@ module Gitlab
##
# Deprecated `:types` key workaround - if types are defined and
# stages are not defined we use types definition as stages.
+ # This keyword will be removed in 15.0:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/346823
#
if types_defined?
@entries[:stages] = @entries[:types] unless stages_defined?
diff --git a/lib/gitlab/ci/config/entry/script.rb b/lib/gitlab/ci/config/entry/script.rb
deleted file mode 100644
index 285e18218b3..00000000000
--- a/lib/gitlab/ci/config/entry/script.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Entry that represents a script.
- #
- class Script < ::Gitlab::Config::Entry::Node
- include ::Gitlab::Config::Entry::Validatable
-
- validations do
- validates :config, nested_array_of_strings: true
- end
-
- def value
- config.flatten(1)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index a5bf066c81f..7f1de6ce1ab 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -19,7 +19,6 @@ module Gitlab
Error = Class.new(StandardError)
AmbigiousSpecificationError = Class.new(Error)
- DuplicateIncludesError = Class.new(Error)
TooManyIncludesError = Class.new(Error)
def initialize(values, context)
@@ -114,25 +113,22 @@ module Gitlab
def verify_duplicates!(location)
logger.instrument(:config_mapper_verify) do
- verify_duplicates_without_instrumentation!(location)
+ verify_max_includes_and_add_location!(location)
end
end
- def verify_duplicates_without_instrumentation!(location)
+ def verify_max_includes_and_add_location!(location)
if expandset.count >= MAX_INCLUDES
raise TooManyIncludesError, "Maximum of #{MAX_INCLUDES} nested includes are allowed!"
end
- # We scope location to context, as this allows us to properly support
- # relative includes, and similarly looking relative in another project
- # does not trigger duplicate error
+ # Scope location to context to allow support of
+ # relative includes
scoped_location = location.merge(
context_project: context.project,
context_sha: context.sha)
- unless expandset.add?(scoped_location)
- raise DuplicateIncludesError, "Include `#{location.to_json}` was already included!"
- end
+ expandset.add(scoped_location)
end
def select_first_matching(location)
diff --git a/lib/gitlab/ci/lint.rb b/lib/gitlab/ci/lint.rb
index 8c1067b9bc6..5591ed62436 100644
--- a/lib/gitlab/ci/lint.rb
+++ b/lib/gitlab/ci/lint.rb
@@ -18,15 +18,17 @@ module Gitlab
end
end
+ LOG_MAX_DURATION_THRESHOLD = 2.seconds
+
def initialize(project:, current_user:, sha: nil)
@project = project
@current_user = current_user
@sha = sha || project&.repository&.commit&.sha
end
- def validate(content, dry_run: false)
+ def validate(content, dry_run: false, ref: @project&.default_branch)
if dry_run
- simulate_pipeline_creation(content)
+ simulate_pipeline_creation(content, ref)
else
static_validation(content)
end
@@ -34,9 +36,9 @@ module Gitlab
private
- def simulate_pipeline_creation(content)
+ def simulate_pipeline_creation(content, ref)
pipeline = ::Ci::CreatePipelineService
- .new(@project, @current_user, ref: @project.default_branch)
+ .new(@project, @current_user, ref: ref)
.execute(:push, dry_run: true, content: content)
.payload
@@ -49,12 +51,9 @@ module Gitlab
end
def static_validation(content)
- result = Gitlab::Ci::YamlProcessor.new(
- content,
- project: @project,
- user: @current_user,
- sha: @sha
- ).execute
+ logger = build_logger
+
+ result = yaml_processor_result(content, logger)
Result.new(
jobs: static_validation_convert_to_jobs(result),
@@ -62,6 +61,17 @@ module Gitlab
errors: result.errors,
warnings: result.warnings.take(::Gitlab::Ci::Warnings::MAX_LIMIT) # rubocop: disable CodeReuse/ActiveRecord
)
+ ensure
+ logger.commit(pipeline: ::Ci::Pipeline.new, caller: self.class.name)
+ end
+
+ def yaml_processor_result(content, logger)
+ logger.instrument(:yaml_process) do
+ Gitlab::Ci::YamlProcessor.new(content, project: @project,
+ user: @current_user,
+ sha: @sha,
+ logger: logger).execute
+ end
end
def dry_run_convert_to_jobs(stages)
@@ -109,6 +119,17 @@ module Gitlab
jobs
end
+
+ def build_logger
+ Gitlab::Ci::Pipeline::Logger.new(project: @project) do |l|
+ l.log_when do |observations|
+ values = observations['yaml_process_duration_s']
+ next false if values.empty?
+
+ values.max >= LOG_MAX_DURATION_THRESHOLD
+ end
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/parsers/security/common.rb b/lib/gitlab/ci/parsers/security/common.rb
index 0c969daf7fd..9aec615d012 100644
--- a/lib/gitlab/ci/parsers/security/common.rb
+++ b/lib/gitlab/ci/parsers/security/common.rb
@@ -42,11 +42,22 @@ module Gitlab
attr_reader :json_data, :report, :validate
def valid?
- return true if !validate || schema_validator.valid?
+ if Feature.enabled?(:enforce_security_report_validation)
+ if !validate || schema_validator.valid?
+ report.schema_validation_status = :valid_schema
+ true
+ else
+ report.schema_validation_status = :invalid_schema
+ schema_validator.errors.each { |error| report.add_error('Schema', error) }
+ false
+ end
+ else
+ return true if !validate || schema_validator.valid?
- schema_validator.errors.each { |error| report.add_error('Schema', error) }
+ schema_validator.errors.each { |error| report.add_error('Schema', error) }
- false
+ false
+ end
end
def schema_validator
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/container-scanning-report-format.json
new file mode 100644
index 00000000000..14eb376485f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/container-scanning-report-format.json
@@ -0,0 +1,741 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..296a895c7cb
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/coverage-fuzzing-report-format.json
@@ -0,0 +1,711 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dast-report-format.json
new file mode 100644
index 00000000000..4d3868be019
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dast-report-format.json
@@ -0,0 +1,1128 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..f0c1a90adcc
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/dependency-scanning-report-format.json
@@ -0,0 +1,805 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/sast-report-format.json
new file mode 100644
index 00000000000..a7159be0190
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/sast-report-format.json
@@ -0,0 +1,706 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/secret-detection-report-format.json
new file mode 100644
index 00000000000..462e23a151c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.0/secret-detection-report-format.json
@@ -0,0 +1,729 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/container-scanning-report-format.json
new file mode 100644
index 00000000000..d01e7818866
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/container-scanning-report-format.json
@@ -0,0 +1,809 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..d496b62ee7f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/coverage-fuzzing-report-format.json
@@ -0,0 +1,779 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dast-report-format.json
new file mode 100644
index 00000000000..a4d59f39a15
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dast-report-format.json
@@ -0,0 +1,1196 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..c83d5195be4
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/dependency-scanning-report-format.json
@@ -0,0 +1,873 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/sast-report-format.json
new file mode 100644
index 00000000000..7c2cd2b78cf
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/sast-report-format.json
@@ -0,0 +1,774 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/secret-detection-report-format.json
new file mode 100644
index 00000000000..b4449d0d59c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.1/secret-detection-report-format.json
@@ -0,0 +1,797 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.1"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "type": "object",
+ "description": "The vendor/maintainer of the scanner.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/container-scanning-report-format.json
new file mode 100644
index 00000000000..696fa214abd
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/container-scanning-report-format.json
@@ -0,0 +1,871 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..1312696d642
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/coverage-fuzzing-report-format.json
@@ -0,0 +1,841 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dast-report-format.json
new file mode 100644
index 00000000000..a7e9f83e557
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dast-report-format.json
@@ -0,0 +1,1258 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..d6ff5248358
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/dependency-scanning-report-format.json
@@ -0,0 +1,935 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/sast-report-format.json
new file mode 100644
index 00000000000..2be6801d2f6
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/sast-report-format.json
@@ -0,0 +1,836 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/secret-detection-report-format.json
new file mode 100644
index 00000000000..c44554489ce
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.2/secret-detection-report-format.json
@@ -0,0 +1,859 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.2"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/container-scanning-report-format.json
new file mode 100644
index 00000000000..959b7b8f6f2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/container-scanning-report-format.json
@@ -0,0 +1,904 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..20038dcb21c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/coverage-fuzzing-report-format.json
@@ -0,0 +1,874 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dast-report-format.json
new file mode 100644
index 00000000000..37b98a73233
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dast-report-format.json
@@ -0,0 +1,1291 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..5e9bbeec1a9
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/dependency-scanning-report-format.json
@@ -0,0 +1,968 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/sast-report-format.json
new file mode 100644
index 00000000000..8aa98646818
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/sast-report-format.json
@@ -0,0 +1,869 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/secret-detection-report-format.json
new file mode 100644
index 00000000000..5a315e39385
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.3/secret-detection-report-format.json
@@ -0,0 +1,892 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.3"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..3736eac0ba0
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/cluster-image-scanning-report-format.json
@@ -0,0 +1,977 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/container-scanning-report-format.json
new file mode 100644
index 00000000000..e324201b04b
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/container-scanning-report-format.json
@@ -0,0 +1,904 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..7ac5d2b7783
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/coverage-fuzzing-report-format.json
@@ -0,0 +1,874 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dast-report-format.json
new file mode 100644
index 00000000000..b3ce7609aea
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dast-report-format.json
@@ -0,0 +1,1291 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..605d379e497
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/dependency-scanning-report-format.json
@@ -0,0 +1,968 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/sast-report-format.json
new file mode 100644
index 00000000000..2d9e1af6663
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/sast-report-format.json
@@ -0,0 +1,869 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/secret-detection-report-format.json
new file mode 100644
index 00000000000..70f22b243c6
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.4/secret-detection-report-format.json
@@ -0,0 +1,892 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.4"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..882a21e430a
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/cluster-image-scanning-report-format.json
@@ -0,0 +1,977 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/container-scanning-report-format.json
new file mode 100644
index 00000000000..08f38650340
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/container-scanning-report-format.json
@@ -0,0 +1,910 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ },
+ "default_branch_image": {
+ "type": "string",
+ "maxLength": 255,
+ "pattern": "^[a-zA-Z0-9/_.-]+:[a-zA-Z0-9_.-]+$",
+ "description": "The name of the image on the default branch."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..a442d38c134
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/coverage-fuzzing-report-format.json
@@ -0,0 +1,874 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dast-report-format.json
new file mode 100644
index 00000000000..9a4d1515bc2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dast-report-format.json
@@ -0,0 +1,1291 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..e84dd9c87d8
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/dependency-scanning-report-format.json
@@ -0,0 +1,968 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/sast-report-format.json
new file mode 100644
index 00000000000..b10b199a97c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/sast-report-format.json
@@ -0,0 +1,869 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/secret-detection-report-format.json
new file mode 100644
index 00000000000..5bd945c8ab5
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.5/secret-detection-report-format.json
@@ -0,0 +1,892 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.5"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability.",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..951b0fea013
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/cluster-image-scanning-report-format.json
@@ -0,0 +1,977 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/container-scanning-report-format.json
new file mode 100644
index 00000000000..fb412af44e3
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/container-scanning-report-format.json
@@ -0,0 +1,910 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ },
+ "default_branch_image": {
+ "type": "string",
+ "maxLength": 255,
+ "pattern": "^[a-zA-Z0-9/_.-]+:[a-zA-Z0-9_.-]+$",
+ "description": "The name of the image on the default branch."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..de79d4b52ab
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/coverage-fuzzing-report-format.json
@@ -0,0 +1,874 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dast-report-format.json
new file mode 100644
index 00000000000..598f162aad2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dast-report-format.json
@@ -0,0 +1,1291 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..80d6fc9c7d2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/dependency-scanning-report-format.json
@@ -0,0 +1,968 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/sast-report-format.json
new file mode 100644
index 00000000000..b87182bb237
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/sast-report-format.json
@@ -0,0 +1,869 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/secret-detection-report-format.json
new file mode 100644
index 00000000000..191d94aad5f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.0.6/secret-detection-report-format.json
@@ -0,0 +1,892 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.0.6"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..3f78ff0354f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/cluster-image-scanning-report-format.json
@@ -0,0 +1,977 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/container-scanning-report-format.json
new file mode 100644
index 00000000000..6e8a1c54fb4
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/container-scanning-report-format.json
@@ -0,0 +1,911 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^[^:]+(:\\d+[^:]*)?:[^:]+$",
+ "description": "The analyzed Docker image."
+ },
+ "default_branch_image": {
+ "type": "string",
+ "maxLength": 255,
+ "pattern": "^[a-zA-Z0-9/_.-]+(:\\d+[a-zA-Z0-9/_.-]*)?:[a-zA-Z0-9_.-]+$",
+ "description": "The name of the image on the default branch."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..f63ebfa2cc2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/coverage-fuzzing-report-format.json
@@ -0,0 +1,874 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dast-report-format.json
new file mode 100644
index 00000000000..73c03082d32
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dast-report-format.json
@@ -0,0 +1,1291 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ },
+ "discovered_at": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss.sss, representing when the vulnerability was discovered",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}$",
+ "examples": [
+ "2020-01-28T03:26:02.956"
+ ]
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..6f2c3740b09
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/dependency-scanning-report-format.json
@@ -0,0 +1,968 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "dependency_files",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/sast-report-format.json
new file mode 100644
index 00000000000..5c7f636e169
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/sast-report-format.json
@@ -0,0 +1,869 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/secret-detection-report-format.json
new file mode 100644
index 00000000000..a87388c45e7
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/14.1.0/secret-detection-report-format.json
@@ -0,0 +1,892 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "14.1.0"
+ },
+ "required": [
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "format": "uri"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "category",
+ "cve",
+ "identifiers",
+ "location",
+ "scanner"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Describes where this vulnerability belongs (for example, SAST, Dependency Scanning, and so on)."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "message": {
+ "type": "string",
+ "description": "A short text section that describes the vulnerability. This may include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "confidence": {
+ "type": "string",
+ "description": "How reliable the vulnerability's assessment is. Possible values are Ignore, Unknown, Experimental, Low, Medium, High, and Confirmed. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Ignore",
+ "Unknown",
+ "Experimental",
+ "Low",
+ "Medium",
+ "High",
+ "Confirmed"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "scanner": {
+ "description": "Describes the scanner used to find this vulnerability.",
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The scanner's ID, as a snake_case string."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Human-readable name of the scanner."
+ }
+ }
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "format": "uri"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "format": "uri"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "cve"
+ ],
+ "properties": {
+ "cve": {
+ "type": "string",
+ "description": "(Deprecated - use vulnerabilities[].id instead) A fingerprint string value that represents a concrete finding. This is used to determine whether two findings are same, which may not be 100% accurate. Note that this is NOT a CVE as described by https://cve.mitre.org/."
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/dependency-scanning-report-format.json
new file mode 120000
index 00000000000..11e0a6846fb
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/dependency-scanning-report-format.json
@@ -0,0 +1 @@
+14.0.0/dependency-scanning-report-format.json \ No newline at end of file
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb
index 364ae66844e..999ffff85d2 100644
--- a/lib/gitlab/ci/parsers/test/junit.rb
+++ b/lib/gitlab/ci/parsers/test/junit.rb
@@ -64,11 +64,11 @@ module Gitlab
def create_test_case(data, test_suite, job)
if data.key?('failure')
status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
- system_output = data['failure']
+ system_output = data['failure'] || data['system_err']
attachment = attachment_path(data['system_out'])
elsif data.key?('error')
status = ::Gitlab::Ci::Reports::TestCase::STATUS_ERROR
- system_output = data['error']
+ system_output = data['error'] || data['system_err']
attachment = attachment_path(data['system_out'])
elsif data.key?('skipped')
status = ::Gitlab::Ci::Reports::TestCase::STATUS_SKIPPED
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index bbdc6b65b96..6feb693221b 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -21,10 +21,6 @@ module Gitlab
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
locked: @command.project.default_pipeline_lock)
-
- # Initialize the feature flag at the beginning of the pipeline creation process
- # so that the flag references in the latter chains return the same value.
- @pipeline.create_deployment_in_separate_transaction?
end
def break?
diff --git a/lib/gitlab/ci/pipeline/chain/create_deployments.rb b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
index b913ba3c87d..a8276d84b87 100644
--- a/lib/gitlab/ci/pipeline/chain/create_deployments.rb
+++ b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class CreateDeployments < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
create_deployments!
end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_environments.rb b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
index 424e1d87fb4..245ef32f06b 100644
--- a/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
+++ b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class EnsureEnvironments < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_environment))
end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
index f4e5e6e467a..8e60cafb65b 100644
--- a/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
+++ b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class EnsureResourceGroups < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_resource_group))
end
diff --git a/lib/gitlab/ci/pipeline/logger.rb b/lib/gitlab/ci/pipeline/logger.rb
index fbba12c11a9..10c0fe295f8 100644
--- a/lib/gitlab/ci/pipeline/logger.rb
+++ b/lib/gitlab/ci/pipeline/logger.rb
@@ -59,7 +59,7 @@ module Gitlab
attributes = {
class: self.class.name.to_s,
pipeline_creation_caller: caller,
- project_id: project.id,
+ project_id: project&.id, # project is not available when called from `/ci/lint`
pipeline_persisted: pipeline.persisted?,
pipeline_source: pipeline.source,
pipeline_creation_service_duration_s: age
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 5a0ad695741..901208f325a 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -79,9 +79,7 @@ module Gitlab
def to_resource
strong_memoize(:resource) do
- processable = initialize_processable
- assign_resource_group(processable) unless @pipeline.create_deployment_in_separate_transaction?
- processable
+ initialize_processable
end
end
@@ -89,39 +87,10 @@ module Gitlab
if bridge?
::Ci::Bridge.new(attributes)
else
- ::Ci::Build.new(attributes).tap do |build|
- unless @pipeline.create_deployment_in_separate_transaction?
- build.assign_attributes(self.class.deployment_attributes_for(build))
- end
- end
+ ::Ci::Build.new(attributes)
end
end
- def assign_resource_group(processable)
- processable.resource_group =
- Seed::Processable::ResourceGroup.new(processable, @resource_group_key)
- .to_resource
- end
-
- def self.deployment_attributes_for(build, environment = nil)
- return {} unless build.has_environment?
-
- environment = Seed::Environment.new(build).to_resource if environment.nil?
-
- unless environment.persisted?
- return { status: :failed, failure_reason: :environment_creation_failure }
- end
-
- build.persisted_environment = environment
-
- {
- deployment: Seed::Deployment.new(build, environment).to_resource,
- metadata_attributes: {
- expanded_environment_name: environment.name
- }
- }
- end
-
private
delegate :logger, to: :@context
diff --git a/lib/gitlab/ci/reports/codequality_reports.rb b/lib/gitlab/ci/reports/codequality_reports.rb
index 27c41c384b8..353d359fde8 100644
--- a/lib/gitlab/ci/reports/codequality_reports.rb
+++ b/lib/gitlab/ci/reports/codequality_reports.rb
@@ -6,7 +6,7 @@ module Gitlab
class CodequalityReports
attr_reader :degradations, :error_message
- SEVERITY_PRIORITIES = %w(blocker critical major minor info).map.with_index.to_h.freeze # { "blocker" => 0, "critical" => 1 ... }
+ SEVERITY_PRIORITIES = %w(blocker critical major minor info unknown).map.with_index.to_h.freeze # { "blocker" => 0, "critical" => 1 ... }
CODECLIMATE_SCHEMA_PATH = Rails.root.join('app', 'validators', 'json_schemas', 'codeclimate.json').to_s
def initialize
@@ -32,7 +32,8 @@ module Gitlab
def sort_degradations!
@degradations = @degradations.sort_by do |_fingerprint, degradation|
- SEVERITY_PRIORITIES[degradation.dig(:severity)]
+ severity = degradation.dig(:severity)&.downcase
+ SEVERITY_PRIORITIES[severity] || SEVERITY_PRIORITIES['unknown']
end.to_h
end
diff --git a/lib/gitlab/ci/reports/security/finding.rb b/lib/gitlab/ci/reports/security/finding.rb
index 47ec82ac86c..69fb8474cde 100644
--- a/lib/gitlab/ci/reports/security/finding.rb
+++ b/lib/gitlab/ci/reports/security/finding.rb
@@ -122,9 +122,11 @@ module Gitlab
end
def keys
- @keys ||= identifiers.reject(&:type_identifier?).map do |identifier|
- FindingKey.new(location_fingerprint: location&.fingerprint, identifier_fingerprint: identifier.fingerprint)
- end
+ @keys ||= identifiers.reject(&:type_identifier?).flat_map do |identifier|
+ location_fingerprints.map do |location_fingerprint|
+ FindingKey.new(location_fingerprint: location_fingerprint, identifier_fingerprint: identifier.fingerprint)
+ end
+ end.push(uuid)
end
def primary_identifier_fingerprint
@@ -171,11 +173,28 @@ module Gitlab
original_data['location']
end
+ # Returns either the max priority signature hex
+ # or the location fingerprint
+ def location_fingerprint
+ location_fingerprints.first
+ end
+
private
def generate_project_fingerprint
Digest::SHA1.hexdigest(compare_key)
end
+
+ def location_fingerprints
+ @location_fingerprints ||= signature_hexes << location&.fingerprint
+ end
+
+ # Returns the signature hexes in reverse priority order
+ def signature_hexes
+ return [] unless @vulnerability_finding_signatures_enabled && signatures.present?
+
+ signatures.sort_by(&:priority).map(&:signature_hex).reverse
+ end
end
end
end
diff --git a/lib/gitlab/ci/reports/security/finding_key.rb b/lib/gitlab/ci/reports/security/finding_key.rb
index 0acd923a60f..ad047fbf904 100644
--- a/lib/gitlab/ci/reports/security/finding_key.rb
+++ b/lib/gitlab/ci/reports/security/finding_key.rb
@@ -11,6 +11,8 @@ module Gitlab
end
def ==(other)
+ return false unless other.is_a?(self.class)
+
has_fingerprints? && other.has_fingerprints? &&
location_fingerprint == other.location_fingerprint &&
identifier_fingerprint == other.identifier_fingerprint
diff --git a/lib/gitlab/ci/reports/security/report.rb b/lib/gitlab/ci/reports/security/report.rb
index 3e4a44a2e70..fbf8c81ac36 100644
--- a/lib/gitlab/ci/reports/security/report.rb
+++ b/lib/gitlab/ci/reports/security/report.rb
@@ -6,7 +6,7 @@ module Gitlab
module Security
class Report
attr_reader :created_at, :type, :pipeline, :findings, :scanners, :identifiers
- attr_accessor :scan, :scanned_resources, :errors, :analyzer, :version
+ attr_accessor :scan, :scanned_resources, :errors, :analyzer, :version, :schema_validation_status
delegate :project_id, to: :pipeline
diff --git a/lib/gitlab/ci/runner_instructions/templates/linux/install.sh b/lib/gitlab/ci/runner_instructions/templates/linux/install.sh
index 6c8a0796d23..a8ba2592128 100644
--- a/lib/gitlab/ci/runner_instructions/templates/linux/install.sh
+++ b/lib/gitlab/ci/runner_instructions/templates/linux/install.sh
@@ -1,12 +1,12 @@
# Download the binary for your system
sudo curl -L --output /usr/local/bin/gitlab-runner ${GITLAB_CI_RUNNER_DOWNLOAD_LOCATION}
-# Give it permissions to execute
+# Give it permission to execute
sudo chmod +x /usr/local/bin/gitlab-runner
-# Create a GitLab CI user
+# Create a GitLab Runner user
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
-# Install and run as service
+# Install and run as a service
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
diff --git a/lib/gitlab/ci/runner_instructions/templates/osx/install.sh b/lib/gitlab/ci/runner_instructions/templates/osx/install.sh
index de4ee3e52fc..76c893bacfc 100644
--- a/lib/gitlab/ci/runner_instructions/templates/osx/install.sh
+++ b/lib/gitlab/ci/runner_instructions/templates/osx/install.sh
@@ -1,11 +1,11 @@
# Download the binary for your system
sudo curl --output /usr/local/bin/gitlab-runner ${GITLAB_CI_RUNNER_DOWNLOAD_LOCATION}
-# Give it permissions to execute
+# Give it permission to execute
sudo chmod +x /usr/local/bin/gitlab-runner
-# The rest of commands execute as the user who will run the Runner
-# Register the Runner (steps below), then run
+# The rest of the commands execute as the user who will run the runner
+# Register the runner (steps below), then run
cd ~
gitlab-runner install
gitlab-runner start
diff --git a/lib/gitlab/ci/runner_instructions/templates/windows/install.ps1 b/lib/gitlab/ci/runner_instructions/templates/windows/install.ps1
index dc37f88543c..019363fc3f7 100644
--- a/lib/gitlab/ci/runner_instructions/templates/windows/install.ps1
+++ b/lib/gitlab/ci/runner_instructions/templates/windows/install.ps1
@@ -1,13 +1,13 @@
# Run PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/starting-windows-powershell?view=powershell-7#with-administrative-privileges-run-as-administrator
-# Create a folder somewhere in your system ex.: C:\GitLab-Runner
+# Create a folder somewhere on your system, for example: C:\GitLab-Runner
New-Item -Path 'C:\GitLab-Runner' -ItemType Directory
-# Enter the folder
+# Change to the folder
cd 'C:\GitLab-Runner'
-# Dowload binary
+# Download binary
Invoke-WebRequest -Uri "${GITLAB_CI_RUNNER_DOWNLOAD_LOCATION}" -OutFile "gitlab-runner.exe"
-# Register the Runner (steps below), then run
+# Register the runner (steps below), then run
.\gitlab-runner.exe install
.\gitlab-runner.exe start
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index fddcc1492a8..8020ffee36f 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -178,6 +178,7 @@ include:
- template: Jobs/Helm-2to3.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
- template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+ - template: Security/Cluster-Image-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index 5efa557d7eb..d5ca93a0a3b 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_BUILD_IMAGE_VERSION: 'v1.0.0'
+ AUTO_BUILD_IMAGE_VERSION: 'v1.5.0'
build:
stage: build
@@ -19,6 +19,9 @@ build:
export CI_APPLICATION_TAG=${CI_APPLICATION_TAG:-$CI_COMMIT_TAG}
fi
- /build/build.sh
+ artifacts:
+ reports:
+ dotenv: gl-auto-build-variables.env
rules:
- if: '$BUILD_DISABLED'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
index 211adc9bd5b..d5ca93a0a3b 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
@@ -1,7 +1,3 @@
-# WARNING: This latest template is for internal FEATURE-FLAG TESTING ONLY.
-# It is not meant to be used with `include:`.
-# This template is scheduled for removal when testing is complete: https://gitlab.com/gitlab-org/gitlab/-/issues/337987
-
variables:
AUTO_BUILD_IMAGE_VERSION: 'v1.5.0'
diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
new file mode 100644
index 00000000000..65c9232f3b9
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
@@ -0,0 +1,177 @@
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# https://docs.gitlab.com/ee/development/cicd/templates.html
+# This specific template is located at:
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
+
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/
+#
+# Configure dependency scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.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
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ DS_DEFAULT_ANALYZERS: "bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python"
+ DS_EXCLUDED_ANALYZERS: ""
+ DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
+ DS_MAJOR_VERSION: 2
+
+dependency_scanning:
+ stage: test
+ script:
+ - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
+ - exit 1
+ artifacts:
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
+ dependencies: []
+ rules:
+ - when: never
+
+.ds-analyzer:
+ extends: dependency_scanning
+ allow_failure: true
+ # `rules` must be overridden explicitly by each child job
+ # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
+ script:
+ - /analyzer run
+
+.cyclone-dx-reports:
+ artifacts:
+ paths:
+ - "**/cyclonedx-*.json"
+
+gemnasium-dependency_scanning:
+ extends:
+ - .ds-analyzer
+ - .cyclone-dx-reports
+ image:
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ # DS_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.
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
+ GEMNASIUM_LIBRARY_SCAN_ENABLED: "true"
+ rules:
+ - if: $DEPENDENCY_SCANNING_DISABLED
+ when: never
+ - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /gemnasium([^-]|$)/
+ exists:
+ - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
+ - '{composer.lock,*/composer.lock,*/*/composer.lock}'
+ - '{gems.locked,*/gems.locked,*/*/gems.locked}'
+ - '{go.sum,*/go.sum,*/*/go.sum}'
+ - '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
+ - '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
+ - '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
+ - '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
+ - '{conan.lock,*/conan.lock,*/*/conan.lock}'
+
+gemnasium-maven-dependency_scanning:
+ extends:
+ - .ds-analyzer
+ - .cyclone-dx-reports
+ image:
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ # DS_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.
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
+ # Stop reporting Gradle as "maven".
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
+ DS_REPORT_PACKAGE_MANAGER_MAVEN_WHEN_JAVA: "false"
+ rules:
+ - if: $DEPENDENCY_SCANNING_DISABLED
+ when: never
+ - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-maven/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /gemnasium-maven/
+ exists:
+ - '{build.gradle,*/build.gradle,*/*/build.gradle}'
+ - '{build.gradle.kts,*/build.gradle.kts,*/*/build.gradle.kts}'
+ - '{build.sbt,*/build.sbt,*/*/build.sbt}'
+ - '{pom.xml,*/pom.xml,*/*/pom.xml}'
+
+gemnasium-python-dependency_scanning:
+ extends:
+ - .ds-analyzer
+ - .cyclone-dx-reports
+ image:
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ # DS_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.
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
+ # Stop reporting Pipenv and Setuptools as "pip".
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
+ DS_REPORT_PACKAGE_MANAGER_PIP_WHEN_PYTHON: "false"
+ rules:
+ - if: $DEPENDENCY_SCANNING_DISABLED
+ when: never
+ - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /gemnasium-python/
+ exists:
+ - '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
+ - '{requirements.pip,*/requirements.pip,*/*/requirements.pip}'
+ - '{Pipfile,*/Pipfile,*/*/Pipfile}'
+ - '{requires.txt,*/requires.txt,*/*/requires.txt}'
+ - '{setup.py,*/setup.py,*/*/setup.py}'
+ # Support passing of $PIP_REQUIREMENTS_FILE
+ # See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /gemnasium-python/ &&
+ $PIP_REQUIREMENTS_FILE
+
+bundler-audit-dependency_scanning:
+ extends: .ds-analyzer
+ image:
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ # DS_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.
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
+ rules:
+ - if: $DEPENDENCY_SCANNING_DISABLED
+ when: never
+ - if: $DS_EXCLUDED_ANALYZERS =~ /bundler-audit/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /bundler-audit/
+ exists:
+ - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
+
+retire-js-dependency_scanning:
+ extends: .ds-analyzer
+ image:
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ # DS_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.
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
+ rules:
+ - if: $DEPENDENCY_SCANNING_DISABLED
+ when: never
+ - if: $DS_EXCLUDED_ANALYZERS =~ /retire.js/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
+ $DS_DEFAULT_ANALYZERS =~ /retire.js/
+ exists:
+ - '{package.json,*/package.json,*/*/package.json}'
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 973db26bf2d..075e13e87f0 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 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.17.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.18.1'
.auto-deploy:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
@@ -103,7 +103,7 @@ canary:
name: production
url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
rules:
- - if: '$CI_DEPLOY_FREEZE != null'
+ - if: '$CI_DEPLOY_FREEZE'
when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
@@ -135,7 +135,7 @@ canary:
production:
<<: *production_template
rules:
- - if: '$CI_DEPLOY_FREEZE != null'
+ - if: '$CI_DEPLOY_FREEZE'
when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
@@ -153,7 +153,7 @@ production_manual:
<<: *production_template
allow_failure: false
rules:
- - if: '$CI_DEPLOY_FREEZE != null'
+ - if: '$CI_DEPLOY_FREEZE'
when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
@@ -192,7 +192,7 @@ production_manual:
resource_group: production
allow_failure: true
rules:
- - if: '$CI_DEPLOY_FREEZE != null'
+ - if: '$CI_DEPLOY_FREEZE'
when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
@@ -207,7 +207,7 @@ production_manual:
.timed_rollout_template: &timed_rollout_template
<<: *rollout_template
rules:
- - if: '$CI_DEPLOY_FREEZE != null'
+ - if: '$CI_DEPLOY_FREEZE'
when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 248040b8b18..e9c5d970c21 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -1,5 +1,8 @@
+variables:
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.18.1'
+
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v2.6.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
dependencies: []
review:
@@ -8,6 +11,7 @@ review:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -35,6 +39,7 @@ stop_review:
variables:
GIT_STRATEGY: none
script:
+ - auto-deploy use_kube_context
- auto-deploy initialize_tiller
- auto-deploy delete
environment:
@@ -63,6 +68,7 @@ staging:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -88,6 +94,7 @@ canary:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -96,6 +103,8 @@ canary:
name: production
url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
rules:
+ - if: '$CI_DEPLOY_FREEZE'
+ when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
@@ -109,6 +118,7 @@ canary:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -125,6 +135,8 @@ canary:
production:
<<: *production_template
rules:
+ - if: '$CI_DEPLOY_FREEZE'
+ when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$STAGING_ENABLED'
@@ -141,6 +153,8 @@ production_manual:
<<: *production_template
allow_failure: false
rules:
+ - if: '$CI_DEPLOY_FREEZE'
+ when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_ENABLED'
@@ -159,6 +173,7 @@ production_manual:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -177,6 +192,8 @@ production_manual:
resource_group: production
allow_failure: true
rules:
+ - if: '$CI_DEPLOY_FREEZE'
+ when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
@@ -190,6 +207,8 @@ production_manual:
.timed_rollout_template: &timed_rollout_template
<<: *rollout_template
rules:
+ - if: '$CI_DEPLOY_FREEZE'
+ when: never
- if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "manual"'
diff --git a/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
new file mode 100644
index 00000000000..fc51f5adb3c
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
@@ -0,0 +1,38 @@
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# https://docs.gitlab.com/ee/development/cicd/templates.html
+# This specific template is located at:
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
+
+# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
+#
+# Configure license scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.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
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+
+ LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
+ LICENSE_MANAGEMENT_VERSION: 3
+
+license_scanning:
+ stage: test
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/license-finder:$LICENSE_MANAGEMENT_VERSION"
+ entrypoint: [""]
+ variables:
+ LM_REPORT_VERSION: '2.1'
+ SETUP_CMD: $LICENSE_MANAGEMENT_SETUP_CMD
+ allow_failure: true
+ script:
+ - /run.sh analyze .
+ artifacts:
+ reports:
+ license_scanning: gl-license-scanning-report.json
+ dependencies: []
+ rules:
+ - if: $LICENSE_MANAGEMENT_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\blicense_scanning\b/
diff --git a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
index 37a746a223c..25d20563010 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
@@ -221,14 +221,22 @@ security-code-scan-sast:
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
- SAST_ANALYZER_IMAGE_TAG: 2
+ 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
+ # This rule shim will be removed in %15.0,
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350935
+ - if: $CI_COMMIT_BRANCH && $CI_SERVER_VERSION_MAJOR == '14'
+ exists:
+ - '**/*.csproj'
+ - '**/*.vbproj'
- if: $CI_COMMIT_BRANCH
+ variables:
+ SAST_ANALYZER_IMAGE_TAG: '3'
exists:
- '**/*.csproj'
- '**/*.vbproj'
diff --git a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
index 42487cc0c67..4e4f96bc7c7 100644
--- a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
@@ -32,15 +32,22 @@ secret_detection:
- if [ -n "$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
- if [[ $(wc -l <${CI_COMMIT_SHA}_commit_list.txt) -eq "0" ]]; then
- # if git log produces 0 or 1 commits we should scan $CI_COMMIT_SHA only
- export SECRET_DETECTION_COMMITS=$CI_COMMIT_SHA
- else
- # +1 because busybox wc only counts \n and there is no trailing \n
- echo "scanning $(($(wc -l <${CI_COMMIT_SHA}_commit_list.txt) + 1)) commits"
- export SECRET_DETECTION_COMMITS_FILE=${CI_COMMIT_SHA}_commit_list.txt
- fi
+ # we don't need the whole history when excluding in the next `git fetch` line,
+ # so git depth=1
+ git fetch origin --depth=1 $CI_DEFAULT_BRANCH
+ # shallow clone $CI_COMMIT_REF_NAME to get commits associated with MR or push
+ git fetch --shallow-exclude=${CI_DEFAULT_BRANCH} origin $CI_COMMIT_REF_NAME
+ # determine what commits we need to scan using "git log A..B"
+ git log --no-merges --pretty=format:"%H" refs/remotes/origin/${CI_DEFAULT_BRANCH}..refs/remotes/origin/${CI_COMMIT_REF_NAME} >${CI_COMMIT_SHA}_commit_list.txt
+
+ # we need to extend the git fetch depth to the number of commits + 2 for the following reasons:
+ # because busybox wc only counts \n and there is no trailing \n (+1)
+ # include the parent commit of the base commit in this MR/Push event. This is needed because
+ # `git diff -p` needs something to compare changes in that commit against (+1)
+ git fetch --depth=$(($(wc -l <${CI_COMMIT_SHA}_commit_list.txt) + 2)) origin $CI_COMMIT_REF_NAME
+
+ # +1 because busybox wc only counts \n and there is no trailing \n
+ echo "scanning $(($(wc -l <${CI_COMMIT_SHA}_commit_list.txt) + 1)) commits"
+ 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/Kaniko.gitlab-ci.yml b/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
index f1b1c20b4e0..d46ac97ad1b 100644
--- a/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
@@ -11,6 +11,7 @@ kaniko-build:
# Additional options for Kaniko executor.
# For more details see https://github.com/GoogleContainerTools/kaniko/blob/master/README.md#additional-flags
KANIKO_ARGS: ""
+ KANIKO_BUILD_CONTEXT: $CI_PROJECT_DIR
stage: build
image:
# For latest releases see https://github.com/GoogleContainerTools/kaniko/releases
@@ -18,30 +19,40 @@ kaniko-build:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
+ # if the user provide IMAGE_TAG then use it, else build the image tag using the default logic.
+ # Default logic
# Compose docker tag name
# Git Branch/Tag to Docker Image Tag Mapping
# * Default Branch: main -> latest
# * Branch: feature/my-feature -> branch-feature-my-feature
# * Tag: v1.0.0/beta2 -> v1.0.0-beta2
- |
- if [ "$CI_COMMIT_REF_NAME" = $CI_DEFAULT_BRANCH ]; then
- VERSION="latest"
- elif [ -n "$CI_COMMIT_TAG" ];then
- NOSLASH=$(echo "$CI_COMMIT_TAG" | tr -s / - )
- SANITIZED="${NOSLASH//[^a-zA-Z0-9\-\.]/}"
- VERSION="$SANITIZED"
- else \
- NOSLASH=$(echo "$CI_COMMIT_REF_NAME" | tr -s / - )
- SANITIZED="${NOSLASH//[^a-zA-Z0-9\-]/}"
- VERSION="branch-$SANITIZED"
+ if [ -z ${IMAGE_TAG+x} ]; then
+ if [ "$CI_COMMIT_REF_NAME" = $CI_DEFAULT_BRANCH ]; then
+ VERSION="latest"
+ elif [ -n "$CI_COMMIT_TAG" ];then
+ NOSLASH=$(echo "$CI_COMMIT_TAG" | tr -s / - )
+ SANITIZED="${NOSLASH//[^a-zA-Z0-9\-\.]/}"
+ VERSION="$SANITIZED"
+ else \
+ NOSLASH=$(echo "$CI_COMMIT_REF_NAME" | tr -s / - )
+ SANITIZED="${NOSLASH//[^a-zA-Z0-9\-]/}"
+ VERSION="branch-$SANITIZED"
+ fi
+ export IMAGE_TAG=$CI_REGISTRY_IMAGE:$VERSION
fi
- - echo $VERSION
+ - echo $IMAGE_TAG
- mkdir -p /kaniko/.docker
# Write credentials to access Gitlab Container Registry within the runner/ci
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
# Build and push the container. To disable push add --no-push
- - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$VERSION $KANIKO_ARGS
+ - DOCKERFILE_PATH=${DOCKERFILE_PATH:-"$KANIKO_BUILD_CONTEXT/Dockerfile"}
+ - /kaniko/executor --context $KANIKO_BUILD_CONTEXT --dockerfile $DOCKERFILE_PATH --destination $IMAGE_TAG $KANIKO_ARGS
# Run this job in a branch/tag where a Dockerfile exists
rules:
- exists:
- Dockerfile
+ # custom Dockerfile path
+ - if: $DOCKERFILE_PATH
+ # custom build context without an explicit Dockerfile path
+ - if: $KANIKO_BUILD_CONTEXT != $CI_PROJECT_DIR
diff --git a/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml b/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml
new file mode 100644
index 00000000000..6dbd0ce9561
--- /dev/null
+++ b/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml
@@ -0,0 +1,47 @@
+# This template is provided and maintained by Qualys Inc., an official Technology Partner with GitLab.
+# See https://about.gitlab.com/partners/technology-partners/#security for more information.
+#
+# This template shows how to use Qualys IaC Scan with a GitLab CI/CD pipeline.
+# Qualys and GitLab users can use this to scan their IaC templates for misconfigurations.
+# Documentation about this integration: https://www.qualys.com/documentation/qualys-iac-gitlab-integration.pdf
+#
+# This template should not need editing to work in your project.
+# It is not designed to be included in an existing CI/CD configuration with the "include:" keyword.
+#
+# The `qualys_iac_sast` job runs for branch (push) pipelines, including scheduled
+# and manually run branch pipelines.
+#
+# The sast-report output complies with GitLab's format. This report displays Qualys IaC Scan's
+# results in the Security tab in the pipeline view, if you have that feature enabled (GitLab Ultimate only).
+# The Qualys IaC Scan output is available in the Jobs tab in the pipeline view.
+#
+# Requirements:
+# Before you can use this template, add the following CI/CD variables to your
+# project CI/CD settings:
+#
+# - QUALYS_URL: The Qualys guard URL.
+# - QUALYS_USERNAME: The Qualys username.
+# - QUALYS_PASSWORD: The Qualys password. Make this variable masked.
+# - BREAK_ON_ERROR: (optional) If you don't want the pipeline to fail on an error,
+# then add this variable and set it to "false". Otherwise set it
+# to "true", or omit the variable.
+
+stages:
+ - build
+ - test
+ - qualys_iac_scan
+ - deploy
+
+qualys_iac_sast:
+ stage: qualys_iac_scan
+ image:
+ name: qualys/qiac_security_cli:latest
+ entrypoint: [""]
+ script:
+ - sh /home/qiac/gitlab.sh
+ artifacts:
+ name: "qualys-iac-sast-artifacts"
+ paths:
+ - qualys_iac_ci_result.json
+ reports:
+ sast: gl-sast-qualys-iac-ci-report.json
diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
index 6888e955467..7ffec7d2e6b 100644
--- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
@@ -12,8 +12,6 @@ variables:
dast:
stage: dast
image: $DAST_API_IMAGE
- variables:
- GIT_STRATEGY: none
allow_failure: true
script:
- /peach/analyzer-dast-api
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 197ce2438e6..1785d4216e7 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -1,165 +1,5 @@
-# To contribute improvements to CI/CD templates, please follow the Development guide at:
-# https://docs.gitlab.com/ee/development/cicd/templates.html
-# This specific template is located at:
-# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+# This template moved to Jobs/Dependency-Scanning.gitlab-ci.yml in GitLab 14.8
+# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/292977
-# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/
-#
-# Configure dependency scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.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
- # (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- DS_DEFAULT_ANALYZERS: "bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python"
- DS_EXCLUDED_ANALYZERS: ""
- DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
- DS_MAJOR_VERSION: 2
-
-dependency_scanning:
- stage: test
- script:
- - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
- - exit 1
- artifacts:
- reports:
- dependency_scanning: gl-dependency-scanning-report.json
- dependencies: []
- rules:
- - when: never
-
-.ds-analyzer:
- extends: dependency_scanning
- allow_failure: true
- # `rules` must be overridden explicitly by each child job
- # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
- script:
- - /analyzer run
-
-gemnasium-dependency_scanning:
- extends: .ds-analyzer
- image:
- name: "$DS_ANALYZER_IMAGE"
- variables:
- # DS_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.
- DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
- rules:
- - if: $DEPENDENCY_SCANNING_DISABLED
- when: never
- - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /gemnasium([^-]|$)/
- exists:
- - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
- - '{composer.lock,*/composer.lock,*/*/composer.lock}'
- - '{gems.locked,*/gems.locked,*/*/gems.locked}'
- - '{go.sum,*/go.sum,*/*/go.sum}'
- - '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
- - '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
- - '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
- - '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
- - '{conan.lock,*/conan.lock,*/*/conan.lock}'
-
-gemnasium-maven-dependency_scanning:
- extends: .ds-analyzer
- image:
- name: "$DS_ANALYZER_IMAGE"
- variables:
- # DS_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.
- DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
- # Stop reporting Gradle as "maven".
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
- DS_REPORT_PACKAGE_MANAGER_MAVEN_WHEN_JAVA: "false"
- rules:
- - if: $DEPENDENCY_SCANNING_DISABLED
- when: never
- - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-maven/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /gemnasium-maven/
- exists:
- - '{build.gradle,*/build.gradle,*/*/build.gradle}'
- - '{build.gradle.kts,*/build.gradle.kts,*/*/build.gradle.kts}'
- - '{build.sbt,*/build.sbt,*/*/build.sbt}'
- - '{pom.xml,*/pom.xml,*/*/pom.xml}'
-
-gemnasium-python-dependency_scanning:
- extends: .ds-analyzer
- image:
- name: "$DS_ANALYZER_IMAGE"
- variables:
- # DS_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.
- DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
- # Stop reporting Pipenv and Setuptools as "pip".
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
- DS_REPORT_PACKAGE_MANAGER_PIP_WHEN_PYTHON: "false"
- rules:
- - if: $DEPENDENCY_SCANNING_DISABLED
- when: never
- - if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /gemnasium-python/
- exists:
- - '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
- - '{requirements.pip,*/requirements.pip,*/*/requirements.pip}'
- - '{Pipfile,*/Pipfile,*/*/Pipfile}'
- - '{requires.txt,*/requires.txt,*/*/requires.txt}'
- - '{setup.py,*/setup.py,*/*/setup.py}'
- # Support passing of $PIP_REQUIREMENTS_FILE
- # See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /gemnasium-python/ &&
- $PIP_REQUIREMENTS_FILE
-
-bundler-audit-dependency_scanning:
- extends: .ds-analyzer
- image:
- name: "$DS_ANALYZER_IMAGE"
- variables:
- # DS_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.
- DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
- rules:
- - if: $DEPENDENCY_SCANNING_DISABLED
- when: never
- - if: $DS_EXCLUDED_ANALYZERS =~ /bundler-audit/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /bundler-audit/
- exists:
- - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
-
-retire-js-dependency_scanning:
- extends: .ds-analyzer
- image:
- name: "$DS_ANALYZER_IMAGE"
- variables:
- # DS_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.
- DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
- rules:
- - if: $DEPENDENCY_SCANNING_DISABLED
- when: never
- - if: $DS_EXCLUDED_ANALYZERS =~ /retire.js/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
- $DS_DEFAULT_ANALYZERS =~ /retire.js/
- exists:
- - '{package.json,*/package.json,*/*/package.json}'
+include:
+ template: Jobs/Dependency-Scanning.gitlab-ci.yml
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 1249b8d6fdc..a99fe4a6dcf 100644
--- a/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
@@ -1,38 +1,5 @@
-# To contribute improvements to CI/CD templates, please follow the Development guide at:
-# https://docs.gitlab.com/ee/development/cicd/templates.html
-# This specific template is located at:
-# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
+# This template moved to Jobs/License-Scanning.gitlab-ci.yml in GitLab 14.8
+# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/292977
-# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
-#
-# Configure license scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.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
- # (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
-
- LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
- LICENSE_MANAGEMENT_VERSION: 3
-
-license_scanning:
- stage: test
- image:
- name: "$SECURE_ANALYZERS_PREFIX/license-finder:$LICENSE_MANAGEMENT_VERSION"
- entrypoint: [""]
- variables:
- LM_REPORT_VERSION: '2.1'
- SETUP_CMD: $LICENSE_MANAGEMENT_SETUP_CMD
- allow_failure: true
- script:
- - /run.sh analyze .
- artifacts:
- reports:
- license_scanning: gl-license-scanning-report.json
- dependencies: []
- rules:
- - if: $LICENSE_MANAGEMENT_DISABLED
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\blicense_scanning\b/
+include:
+ template: Jobs/License-Scanning.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 86b7d57d3cb..82c7bfd0620 100644
--- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
@@ -109,6 +109,8 @@ phpcs-security-audit:
security-code-scan:
extends: .download_images
+ variables:
+ SECURE_BINARIES_ANALYZER_VERSION: "3"
only:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
diff --git a/lib/gitlab/ci/variables/builder.rb b/lib/gitlab/ci/variables/builder.rb
index 4c777527ebc..9ef6e7f5fa9 100644
--- a/lib/gitlab/ci/variables/builder.rb
+++ b/lib/gitlab/ci/variables/builder.rb
@@ -8,14 +8,13 @@ module Gitlab
def initialize(pipeline)
@pipeline = pipeline
+ @instance_variables_builder = Builder::Instance.new
+ @project_variables_builder = Builder::Project.new(project)
end
def scoped_variables(job, environment:, dependencies:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.concat(predefined_variables(job))
-
- next variables unless pipeline.use_variables_builder_definitions?
-
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables)
variables.concat(job.runner.predefined_variables) if job.runnable? && job.runner
@@ -24,7 +23,7 @@ module Gitlab
variables.concat(job.yaml_variables)
variables.concat(user_variables(job.user))
variables.concat(job.dependency_variables) if dependencies
- variables.concat(secret_instance_variables(ref: job.git_ref))
+ variables.concat(secret_instance_variables)
variables.concat(secret_group_variables(environment: environment, ref: job.git_ref))
variables.concat(secret_project_variables(environment: environment, ref: job.git_ref))
variables.concat(job.trigger_request.user_variables) if job.trigger_request
@@ -65,8 +64,11 @@ module Gitlab
end
end
- def secret_instance_variables(ref:)
- project.ci_instance_variables_for(ref: ref)
+ def secret_instance_variables
+ strong_memoize(:secret_instance_variables) do
+ instance_variables_builder
+ .secret_variables(protected_ref: protected_ref?)
+ end
end
def secret_group_variables(environment:, ref:)
@@ -76,12 +78,18 @@ module Gitlab
end
def secret_project_variables(environment:, ref:)
- project.ci_variables_for(ref: ref, environment: environment)
+ if memoize_secret_variables?
+ memoized_secret_project_variables(environment: environment)
+ else
+ project.ci_variables_for(ref: ref, environment: environment)
+ end
end
private
attr_reader :pipeline
+ attr_reader :instance_variables_builder
+ attr_reader :project_variables_builder
delegate :project, to: :pipeline
def predefined_variables(job)
@@ -102,11 +110,44 @@ module Gitlab
end
end
+ def memoized_secret_project_variables(environment:)
+ strong_memoize_with(:secret_project_variables, environment) do
+ project_variables_builder
+ .secret_variables(
+ environment: environment,
+ protected_ref: protected_ref?)
+ end
+ end
+
def ci_node_total_value(job)
parallel = job.options&.dig(:parallel)
parallel = parallel.dig(:total) if parallel.is_a?(Hash)
parallel || 1
end
+
+ def protected_ref?
+ strong_memoize(:protected_ref) do
+ project.protected_for?(pipeline.jobs_git_ref)
+ end
+ end
+
+ def memoize_secret_variables?
+ strong_memoize(:memoize_secret_variables) do
+ ::Feature.enabled?(:ci_variables_builder_memoize_secret_variables,
+ project,
+ default_enabled: :yaml)
+ end
+ end
+
+ def strong_memoize_with(name, *args)
+ container = strong_memoize(name) { {} }
+
+ if container.key?(args)
+ container[args]
+ else
+ container[args] = yield
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/variables/builder/instance.rb b/lib/gitlab/ci/variables/builder/instance.rb
new file mode 100644
index 00000000000..db4d54b9692
--- /dev/null
+++ b/lib/gitlab/ci/variables/builder/instance.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ class Builder
+ class Instance
+ include Gitlab::Utils::StrongMemoize
+
+ def secret_variables(protected_ref: false)
+ variables = if protected_ref
+ ::Ci::InstanceVariable.all_cached
+ else
+ ::Ci::InstanceVariable.unprotected_cached
+ end
+
+ Gitlab::Ci::Variables::Collection.new(variables)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/variables/builder/project.rb b/lib/gitlab/ci/variables/builder/project.rb
new file mode 100644
index 00000000000..832e68ea6a2
--- /dev/null
+++ b/lib/gitlab/ci/variables/builder/project.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ class Builder
+ class Project
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(project)
+ @project = project
+ end
+
+ def secret_variables(environment:, protected_ref: false)
+ variables = @project.variables
+ variables = variables.unprotected unless protected_ref
+ variables = variables.for_environment(environment)
+
+ Gitlab::Ci::Variables::Collection.new(variables)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
index 5d2bf3cfebf..b2bc56f46ee 100644
--- a/lib/gitlab/config/entry/validators.rb
+++ b/lib/gitlab/config/entry/validators.rb
@@ -213,7 +213,7 @@ module Gitlab
def validate_each(record, attribute, value)
unless validate_regexp(value)
- record.errors.add(attribute, 'must be a regular expression')
+ record.errors.add(attribute, 'must be a regular expression with re2 syntax')
end
end
@@ -238,12 +238,16 @@ module Gitlab
class ArrayOfStringsOrRegexpsValidator < RegexpValidator
def validate_each(record, attribute, value)
unless validate_array_of_strings_or_regexps(value)
- record.errors.add(attribute, 'should be an array of strings or regexps')
+ record.errors.add(attribute, validation_message)
end
end
private
+ def validation_message
+ 'should be an array of strings or regular expressions using re2 syntax'
+ end
+
def validate_array_of_strings_or_regexps(values)
values.is_a?(Array) && values.all?(&method(:validate_string_or_regexp))
end
@@ -259,6 +263,19 @@ module Gitlab
class ArrayOfStringsOrRegexpsWithFallbackValidator < ArrayOfStringsOrRegexpsValidator
protected
+ # TODO
+ #
+ # Remove ArrayOfStringsOrRegexpsWithFallbackValidator class too when
+ # you are removing the `:allow_unsafe_ruby_regexp` feature flag.
+ #
+ def validation_message
+ if ::Feature.enabled?(:allow_unsafe_ruby_regexp, default_enabled: :yaml)
+ 'should be an array of strings or regular expressions'
+ else
+ super
+ end
+ end
+
def fallback
true
end
@@ -278,20 +295,6 @@ module Gitlab
end
end
- class NestedArrayOfStringsValidator < ArrayOfStringsOrStringValidator
- def validate_each(record, attribute, value)
- unless validate_nested_array_of_strings(value)
- record.errors.add(attribute, 'should be an array containing strings and arrays of strings')
- end
- end
-
- private
-
- def validate_nested_array_of_strings(values)
- values.is_a?(Array) && values.all? { |element| validate_array_of_strings_or_string(element) }
- end
- end
-
class StringOrNestedArrayOfStringsValidator < ActiveModel::EachValidator
include LegacyValidationHelpers
include NestedArrayHelpers
diff --git a/lib/gitlab/console.rb b/lib/gitlab/console.rb
new file mode 100644
index 00000000000..c3c34bb0f61
--- /dev/null
+++ b/lib/gitlab/console.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+# rubocop:disable Rails/Output
+module Gitlab
+ module Console
+ class << self
+ def welcome!
+ return unless Gitlab::Runtime.console?
+
+ # note that this will not print out when using `spring`
+ justify = 15
+
+ puts '-' * 80
+ puts " Ruby:".ljust(justify) + RUBY_DESCRIPTION
+ puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision}) #{Gitlab.ee? ? 'EE' : 'FOSS'}"
+ puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.version)}"
+
+ if ApplicationRecord.database.exists?
+ puts " #{ApplicationRecord.database.human_adapter_name}:".ljust(justify) + ApplicationRecord.database.version
+
+ Gitlab.ee do
+ if Gitlab::Geo.connected? && Gitlab::Geo.enabled?
+ puts " Geo enabled:".ljust(justify) + 'yes'
+ puts " Geo server:".ljust(justify) + EE::GeoHelper.current_node_human_status
+ end
+ end
+ end
+
+ if RUBY_PLATFORM.include?('darwin')
+ # Sorry, macOS users. The current implementation requires procfs.
+ puts '-' * 80
+ else
+ boot_time_seconds = Gitlab::Metrics::BootTimeTracker.instance.startup_time
+ booted_in = "[ booted in %.2fs ]" % [boot_time_seconds]
+ puts '-' * (80 - booted_in.length) + booted_in
+ end
+ end
+ end
+ end
+end
+# rubocop:enable Rails/Output
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 2d2d8c41236..0d6767ad564 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -62,7 +62,7 @@ module Gitlab
# need to be added to the application settings. To prevent Rake tasks
# and other callers from failing, use any loaded settings and return
# defaults for missing columns.
- if Gitlab::Runtime.rake? && ActiveRecord::Base.connection.migration_context.needs_migration?
+ if Gitlab::Runtime.rake? && ::ApplicationSetting.connection.migration_context.needs_migration?
db_attributes = current_settings&.attributes || {}
fake_application_settings(db_attributes)
elsif current_settings.present?
@@ -82,7 +82,7 @@ module Gitlab
def connect_to_db?
# When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised
- active_db_connection = ActiveRecord::Base.connection.active? rescue false
+ active_db_connection = ::ApplicationSetting.connection.active? rescue false
active_db_connection &&
ApplicationSetting.database.cached_table_exists?
diff --git a/lib/gitlab/cycle_analytics/summary/base.rb b/lib/gitlab/cycle_analytics/summary/base.rb
index f2ff86a40a2..f867dbd4d68 100644
--- a/lib/gitlab/cycle_analytics/summary/base.rb
+++ b/lib/gitlab/cycle_analytics/summary/base.rb
@@ -9,6 +9,10 @@ module Gitlab
@options = options
end
+ def identifier
+ self.class.name.demodulize.underscore.to_sym
+ end
+
def title
raise NotImplementedError, "Expected #{self.name} to implement title"
end
diff --git a/lib/gitlab/cycle_analytics/summary/commit.rb b/lib/gitlab/cycle_analytics/summary/commit.rb
index fb55c3df869..476f72fb2ba 100644
--- a/lib/gitlab/cycle_analytics/summary/commit.rb
+++ b/lib/gitlab/cycle_analytics/summary/commit.rb
@@ -4,6 +4,10 @@ module Gitlab
module CycleAnalytics
module Summary
class Commit < Base
+ def identifier
+ :commits
+ end
+
def title
n_('Commit', 'Commits', value.to_i)
end
diff --git a/lib/gitlab/cycle_analytics/summary/deploy.rb b/lib/gitlab/cycle_analytics/summary/deploy.rb
index 403cec5ed19..5b4865523c0 100644
--- a/lib/gitlab/cycle_analytics/summary/deploy.rb
+++ b/lib/gitlab/cycle_analytics/summary/deploy.rb
@@ -4,6 +4,10 @@ module Gitlab
module CycleAnalytics
module Summary
class Deploy < Base
+ def identifier
+ :deploys
+ end
+
def title
n_('Deploy', 'Deploys', value.to_i)
end
diff --git a/lib/gitlab/cycle_analytics/summary/issue.rb b/lib/gitlab/cycle_analytics/summary/issue.rb
index 34e0d34b960..ed6c985009c 100644
--- a/lib/gitlab/cycle_analytics/summary/issue.rb
+++ b/lib/gitlab/cycle_analytics/summary/issue.rb
@@ -10,6 +10,10 @@ module Gitlab
@current_user = current_user
end
+ def identifier
+ :issues
+ end
+
def title
n_('New Issue', 'New Issues', value.to_i)
end
diff --git a/lib/gitlab/daemon.rb b/lib/gitlab/daemon.rb
index 058fe1c8139..5f579f90629 100644
--- a/lib/gitlab/daemon.rb
+++ b/lib/gitlab/daemon.rb
@@ -20,6 +20,8 @@ module Gitlab
!thread.nil?
end
+ # Possible options:
+ # - synchronous [Boolean] if true, turns `start` into a blocking call
def initialize(**options)
@synchronous = options[:synchronous]
@mutex = Mutex.new
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index f9c346a272f..9b32d285ec0 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -109,6 +109,26 @@ module Gitlab
name.to_s == CI_DATABASE_NAME
end
+ class PgUser < ApplicationRecord
+ self.table_name = 'pg_user'
+ self.primary_key = :usename
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def self.check_for_non_superuser
+ user = PgUser.find_by('usename = CURRENT_USER')
+ am_i_superuser = user.usesuper
+
+ Gitlab::AppLogger.info(
+ "Account details: User: \"#{user.usename}\", UseSuper: (#{am_i_superuser})"
+ )
+
+ raise 'Error: detected superuser' if am_i_superuser
+ rescue ActiveRecord::StatementInvalid
+ raise 'User CURRENT_USER not found'
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def self.check_postgres_version_and_print_warning
return if Gitlab::Runtime.rails_runner?
diff --git a/lib/gitlab/database/background_migration/batch_optimizer.rb b/lib/gitlab/database/background_migration/batch_optimizer.rb
index 0668490dda8..58c4a214077 100644
--- a/lib/gitlab/database/background_migration/batch_optimizer.rb
+++ b/lib/gitlab/database/background_migration/batch_optimizer.rb
@@ -20,7 +20,8 @@ module Gitlab
TARGET_EFFICIENCY = (0.9..0.95).freeze
# Lower and upper bound for the batch size
- ALLOWED_BATCH_SIZE = (1_000..2_000_000).freeze
+ MIN_BATCH_SIZE = 1_000
+ MAX_BATCH_SIZE = 2_000_000
# Limit for the multiplier of the batch size
MAX_MULTIPLIER = 1.2
@@ -43,7 +44,8 @@ module Gitlab
return unless Feature.enabled?(:optimize_batched_migrations, type: :ops, default_enabled: :yaml)
if multiplier = batch_size_multiplier
- migration.batch_size = (migration.batch_size * multiplier).to_i.clamp(ALLOWED_BATCH_SIZE)
+ max_batch = migration.max_batch_size || MAX_BATCH_SIZE
+ migration.batch_size = (migration.batch_size * multiplier).to_i.clamp(MIN_BATCH_SIZE, max_batch)
migration.save!
end
end
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 290fa51692a..185b6d9629f 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -12,22 +12,58 @@ module Gitlab
MAX_ATTEMPTS = 3
STUCK_JOBS_TIMEOUT = 1.hour.freeze
- enum status: {
- pending: 0,
- running: 1,
- failed: 2,
- succeeded: 3
- }
-
belongs_to :batched_migration, foreign_key: :batched_background_migration_id
+ has_many :batched_job_transition_logs, foreign_key: :batched_background_migration_job_id
- scope :active, -> { where(status: [:pending, :running]) }
+ scope :active, -> { with_statuses(:pending, :running) }
scope :stuck, -> { active.where('updated_at <= ?', STUCK_JOBS_TIMEOUT.ago) }
- scope :retriable, -> { from_union([failed.where('attempts < ?', MAX_ATTEMPTS), self.stuck]) }
- scope :except_succeeded, -> { where(status: self.statuses.except(:succeeded).values) }
- scope :successful_in_execution_order, -> { where.not(finished_at: nil).succeeded.order(:finished_at) }
+ scope :retriable, -> { from_union([with_status(:failed).where('attempts < ?', MAX_ATTEMPTS), self.stuck]) }
+ scope :except_succeeded, -> { without_status(:succeeded) }
+ scope :successful_in_execution_order, -> { where.not(finished_at: nil).with_status(:succeeded).order(:finished_at) }
scope :with_preloads, -> { preload(:batched_migration) }
+ state_machine :status, initial: :pending do
+ state :pending, value: 0
+ state :running, value: 1
+ state :failed, value: 2
+ state :succeeded, value: 3
+
+ event :succeed do
+ transition any => :succeeded
+ end
+
+ event :failure do
+ transition any => :failed
+ end
+
+ event :run do
+ transition any => :running
+ end
+
+ before_transition any => [:failed, :succeeded] do |job|
+ job.finished_at = Time.current
+ end
+
+ before_transition any => :running do |job|
+ job.attempts += 1
+ job.started_at = Time.current
+ job.finished_at = nil
+ job.metrics = {}
+ end
+
+ after_transition do |job, transition|
+ error_hash = transition.args.find { |arg| arg[:error].present? }
+
+ exception = error_hash&.fetch(:error)
+
+ job.batched_job_transition_logs.create(previous_status: transition.from, next_status: transition.to, exception_class: exception&.class, exception_message: exception&.message)
+
+ Gitlab::ErrorTracking.track_exception(exception, batched_job_id: job.id) if exception
+
+ Gitlab::AppLogger.info(message: 'BatchedJob transition', batched_job_id: job.id, previous_state: transition.from_name, new_state: transition.to_name)
+ end
+ end
+
delegate :job_class, :table_name, :column_name, :job_arguments,
to: :batched_migration, prefix: :migration
diff --git a/lib/gitlab/database/background_migration/batched_job_transition_log.rb b/lib/gitlab/database/background_migration/batched_job_transition_log.rb
new file mode 100644
index 00000000000..418bf1a101f
--- /dev/null
+++ b/lib/gitlab/database/background_migration/batched_job_transition_log.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module BackgroundMigration
+ class BatchedJobTransitionLog < ApplicationRecord
+ include PartitionedTable
+
+ self.table_name = :batched_background_migration_job_transition_logs
+
+ self.primary_key = :id
+
+ partitioned_by :created_at, strategy: :monthly, retain_for: 6.months
+
+ belongs_to :batched_job, foreign_key: :batched_background_migration_job_id
+
+ validates :previous_status, :next_status, :batched_job, presence: true
+
+ validates :exception_class, length: { maximum: 100 }
+ validates :exception_message, length: { maximum: 1000 }
+
+ enum previous_status: Gitlab::Database::BackgroundMigration::BatchedJob.state_machine.states.map(&:name), _prefix: true
+ enum next_status: Gitlab::Database::BackgroundMigration::BatchedJob.state_machine.states.map(&:name), _prefix: true
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index 2f066039874..1f8ca982ed5 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -47,7 +47,7 @@ module Gitlab
def self.successful_rows_counts(migrations)
BatchedJob
- .succeeded
+ .with_status(:succeeded)
.where(batched_background_migration_id: migrations)
.group(:batched_background_migration_id)
.sum(:batch_size)
@@ -71,7 +71,7 @@ module Gitlab
end
def retry_failed_jobs!
- batched_jobs.failed.each_batch(of: 100) do |batch|
+ batched_jobs.with_status(:failed).each_batch(of: 100) do |batch|
self.class.transaction do
batch.lock.each(&:split_and_retry!)
self.active!
@@ -102,7 +102,7 @@ module Gitlab
end
def migrated_tuple_count
- batched_jobs.succeeded.sum(:batch_size)
+ batched_jobs.with_status(:succeeded).sum(:batch_size)
end
def prometheus_labels
diff --git a/lib/gitlab/database/background_migration/batched_migration_runner.rb b/lib/gitlab/database/background_migration/batched_migration_runner.rb
index 14e3919986e..9308bae20cf 100644
--- a/lib/gitlab/database/background_migration/batched_migration_runner.rb
+++ b/lib/gitlab/database/background_migration/batched_migration_runner.rb
@@ -67,7 +67,7 @@ module Gitlab
Gitlab::AppLogger.warn "Batched background migration for the given configuration is already finished: #{configuration}"
else
migration.finalizing!
- migration.batched_jobs.pending.each { |job| migration_wrapper.perform(job) }
+ migration.batched_jobs.with_status(:pending).each { |job| migration_wrapper.perform(job) }
run_migration_while(migration, :finalizing)
@@ -95,7 +95,8 @@ module Gitlab
active_migration.table_name,
active_migration.column_name,
batch_min_value: batch_min_value,
- batch_size: active_migration.batch_size)
+ batch_size: active_migration.batch_size,
+ job_arguments: active_migration.job_arguments)
return if next_batch_bounds.nil?
@@ -115,7 +116,7 @@ module Gitlab
def finish_active_migration(active_migration)
return if active_migration.batched_jobs.active.exists?
- if active_migration.batched_jobs.failed.exists?
+ if active_migration.batched_jobs.with_status(:failed).exists?
active_migration.failed!
else
active_migration.finished!
diff --git a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
index e37df102872..057f856d859 100644
--- a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
+++ b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
@@ -6,6 +6,10 @@ module Gitlab
class BatchedMigrationWrapper
extend Gitlab::Utils::StrongMemoize
+ def initialize(connection: ApplicationRecord.connection)
+ @connection = connection
+ end
+
# Wraps the execution of a batched_background_migration.
#
# Updates the job's tracking records with the status of the migration
@@ -18,24 +22,25 @@ module Gitlab
execute_batch(batch_tracking_record)
- batch_tracking_record.status = :succeeded
- rescue Exception # rubocop:disable Lint/RescueException
- batch_tracking_record.status = :failed
+ batch_tracking_record.succeed!
+ rescue Exception => error # rubocop:disable Lint/RescueException
+ batch_tracking_record.failure!(error: error)
raise
ensure
- finish_tracking_execution(batch_tracking_record)
track_prometheus_metrics(batch_tracking_record)
end
private
+ attr_reader :connection
+
def start_tracking_execution(tracking_record)
- tracking_record.update!(attempts: tracking_record.attempts + 1, status: :running, started_at: Time.current, finished_at: nil, metrics: {})
+ tracking_record.run!
end
def execute_batch(tracking_record)
- job_instance = tracking_record.migration_job_class.new
+ job_instance = migration_instance_for(tracking_record.migration_job_class)
job_instance.perform(
tracking_record.min_value,
@@ -51,9 +56,12 @@ module Gitlab
end
end
- def finish_tracking_execution(tracking_record)
- tracking_record.finished_at = Time.current
- tracking_record.save!
+ def migration_instance_for(job_class)
+ if job_class < Gitlab::BackgroundMigration::BaseJob
+ job_class.new(connection: connection)
+ else
+ job_class.new
+ end
end
def track_prometheus_metrics(tracking_record)
diff --git a/lib/gitlab/database/dynamic_model_helpers.rb b/lib/gitlab/database/dynamic_model_helpers.rb
index 220062f1bc6..ad7dea8f0d9 100644
--- a/lib/gitlab/database/dynamic_model_helpers.rb
+++ b/lib/gitlab/database/dynamic_model_helpers.rb
@@ -5,16 +5,19 @@ module Gitlab
module DynamicModelHelpers
BATCH_SIZE = 1_000
- def define_batchable_model(table_name)
- Class.new(ActiveRecord::Base) do
+ def define_batchable_model(table_name, connection:)
+ klass = Class.new(ActiveRecord::Base) do
include EachBatch
self.table_name = table_name
self.inheritance_column = :_type_disabled
end
+
+ klass.connection = connection
+ klass
end
- def each_batch(table_name, scope: ->(table) { table.all }, of: BATCH_SIZE)
+ def each_batch(table_name, connection:, scope: ->(table) { table.all }, of: BATCH_SIZE)
if transaction_open?
raise <<~MSG.squish
each_batch should not run inside a transaction, you can disable
@@ -23,12 +26,12 @@ module Gitlab
MSG
end
- scope.call(define_batchable_model(table_name))
+ scope.call(define_batchable_model(table_name, connection: connection))
.each_batch(of: of) { |batch| yield batch }
end
- def each_batch_range(table_name, scope: ->(table) { table.all }, of: BATCH_SIZE)
- each_batch(table_name, scope: scope, of: of) do |batch|
+ def each_batch_range(table_name, connection:, scope: ->(table) { table.all }, of: BATCH_SIZE)
+ each_batch(table_name, connection: connection, scope: scope, of: of) do |batch|
yield batch.pluck('MIN(id), MAX(id)').first
end
end
diff --git a/lib/gitlab/database/each_database.rb b/lib/gitlab/database/each_database.rb
index 7c9e65e6691..c3eea0515d4 100644
--- a/lib/gitlab/database/each_database.rb
+++ b/lib/gitlab/database/each_database.rb
@@ -14,18 +14,40 @@ module Gitlab
end
end
- def each_model_connection(models)
+ def each_model_connection(models, &blk)
models.each do |model|
- connection_name = model.connection.pool.db_config.name
-
- with_shared_connection(model.connection, connection_name) do
- yield model, connection_name
+ # If model is shared, iterate all available base connections
+ # Example: `LooseForeignKeys::DeletedRecord`
+ if model < ::Gitlab::Database::SharedModel
+ with_shared_model_connections(model, &blk)
+ else
+ with_model_connection(model, &blk)
end
end
end
private
+ def with_shared_model_connections(shared_model, &blk)
+ Gitlab::Database.database_base_models.each_pair do |connection_name, connection_model|
+ if shared_model.limit_connection_names
+ next unless shared_model.limit_connection_names.include?(connection_name.to_sym)
+ end
+
+ with_shared_connection(connection_model.connection, connection_name) do
+ yield shared_model, connection_name
+ end
+ end
+ end
+
+ def with_model_connection(model, &blk)
+ connection_name = model.connection.pool.db_config.name
+
+ with_shared_connection(model.connection, connection_name) do
+ yield model, connection_name
+ end
+ end
+
def with_shared_connection(connection, connection_name)
Gitlab::Database::SharedModel.using_connection(connection) do
Gitlab::AppLogger.debug(message: 'Switched database connection', connection_name: connection_name)
diff --git a/lib/gitlab/database/gitlab_schema.rb b/lib/gitlab/database/gitlab_schema.rb
index 14807494a79..7adf6ba6afb 100644
--- a/lib/gitlab/database/gitlab_schema.rb
+++ b/lib/gitlab/database/gitlab_schema.rb
@@ -78,7 +78,11 @@ module Gitlab
# All tables from `information_schema.` are `:gitlab_shared`
return :gitlab_shared if schema_name == 'information_schema'
- # All tables that start with `_test_` are shared and ignored
+ return :gitlab_main if table_name.start_with?('_test_gitlab_main_')
+
+ return :gitlab_ci if table_name.start_with?('_test_gitlab_ci_')
+
+ # All tables that start with `_test_` without a following schema are shared and ignored
return :gitlab_shared if table_name.start_with?('_test_')
# All `pg_` tables are marked as `shared`
diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml
index fb5d8cfa32f..93cd75ce5a7 100644
--- a/lib/gitlab/database/gitlab_schemas.yml
+++ b/lib/gitlab/database/gitlab_schemas.yml
@@ -4,6 +4,7 @@ agent_group_authorizations: :gitlab_main
agent_project_authorizations: :gitlab_main
alert_management_alert_assignees: :gitlab_main
alert_management_alerts: :gitlab_main
+alert_management_alert_metric_images: :gitlab_main
alert_management_alert_user_mentions: :gitlab_main
alert_management_http_integrations: :gitlab_main
allowed_email_domains: :gitlab_main
@@ -84,6 +85,7 @@ ci_instance_variables: :gitlab_ci
ci_job_artifacts: :gitlab_ci
ci_job_token_project_scope_links: :gitlab_ci
ci_job_variables: :gitlab_ci
+ci_job_artifact_states: :gitlab_ci
ci_minutes_additional_packs: :gitlab_ci
ci_namespace_monthly_usages: :gitlab_ci
ci_namespace_mirrors: :gitlab_ci
@@ -552,3 +554,4 @@ x509_commit_signatures: :gitlab_main
x509_issuers: :gitlab_main
zentao_tracker_data: :gitlab_main
zoom_meetings: :gitlab_main
+batched_background_migration_job_transition_logs: :gitlab_main
diff --git a/lib/gitlab/database/load_balancing/configuration.rb b/lib/gitlab/database/load_balancing/configuration.rb
index e769cb5c35c..63444ebe169 100644
--- a/lib/gitlab/database/load_balancing/configuration.rb
+++ b/lib/gitlab/database/load_balancing/configuration.rb
@@ -74,11 +74,24 @@ module Gitlab
# With connection re-use the primary connection can be overwritten
# to be used from different model
def primary_connection_specification_name
- (@primary_model || @model).connection_specification_name
+ primary_model_or_model_if_enabled.connection_specification_name
end
- def primary_db_config
- (@primary_model || @model).connection_db_config
+ def primary_model_or_model_if_enabled
+ if force_no_sharing_primary_model?
+ @model
+ else
+ @primary_model || @model
+ end
+ end
+
+ def force_no_sharing_primary_model?
+ return false unless @primary_model # Doesn't matter since we don't have an overriding primary model
+ return false unless ::Gitlab::SafeRequestStore.active?
+
+ ::Gitlab::SafeRequestStore.fetch(:force_no_sharing_primary_model) do
+ ::Feature::FlipperFeature.table_exists? && ::Feature.enabled?(:force_no_sharing_primary_model, default_enabled: :yaml)
+ end
end
def replica_db_config
diff --git a/lib/gitlab/database/loose_foreign_keys.rb b/lib/gitlab/database/loose_foreign_keys.rb
index 1ecfb5ce47f..1338b18a099 100644
--- a/lib/gitlab/database/loose_foreign_keys.rb
+++ b/lib/gitlab/database/loose_foreign_keys.rb
@@ -28,7 +28,11 @@ module Gitlab
end
def self.loose_foreign_keys_yaml
- @loose_foreign_keys_yaml ||= YAML.load_file(Rails.root.join('lib/gitlab/database/gitlab_loose_foreign_keys.yml'))
+ @loose_foreign_keys_yaml ||= YAML.load_file(self.loose_foreign_keys_yaml_path)
+ end
+
+ def self.loose_foreign_keys_yaml_path
+ @loose_foreign_keys_yaml_path ||= Rails.root.join('config/gitlab_loose_foreign_keys.yml')
end
private_class_method :build_definition
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index aa5ac1e3486..63c031a6d0b 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -9,6 +9,18 @@ module Gitlab
include RenameTableHelpers
include AsyncIndexes::MigrationHelpers
+ def define_batchable_model(table_name, connection: self.connection)
+ super(table_name, connection: connection)
+ end
+
+ def each_batch(table_name, connection: self.connection, **kwargs)
+ super(table_name, connection: connection, **kwargs)
+ end
+
+ def each_batch_range(table_name, connection: self.connection, **kwargs)
+ super(table_name, connection: connection, **kwargs)
+ end
+
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
MAX_IDENTIFIER_NAME_LENGTH = 63
DEFAULT_TIMESTAMP_COLUMNS = %i[created_at updated_at].freeze
@@ -429,6 +441,7 @@ module Gitlab
def with_lock_retries(*args, **kwargs, &block)
raise_on_exhaustion = !!kwargs.delete(:raise_on_exhaustion)
merged_args = {
+ connection: connection,
klass: self.class,
logger: Gitlab::BackgroundMigration::Logger,
allow_savepoints: true
@@ -1054,9 +1067,18 @@ module Gitlab
Arel::Nodes::SqlLiteral.new(replace.to_sql)
end
- def remove_foreign_key_if_exists(...)
- if foreign_key_exists?(...)
- remove_foreign_key(...)
+ def remove_foreign_key_if_exists(source, target = nil, **kwargs)
+ reverse_lock_order = kwargs.delete(:reverse_lock_order)
+ return unless foreign_key_exists?(source, target, **kwargs)
+
+ if target && reverse_lock_order && transaction_open?
+ execute("LOCK TABLE #{target}, #{source} IN ACCESS EXCLUSIVE MODE")
+ end
+
+ if target
+ remove_foreign_key(source, target, **kwargs)
+ else
+ remove_foreign_key(source, **kwargs)
end
end
diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
index dcaf7fad05f..a2a4a37ab87 100644
--- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
@@ -66,6 +66,7 @@ module Gitlab
batch_max_value: nil,
batch_class_name: BATCH_CLASS_NAME,
batch_size: BATCH_SIZE,
+ max_batch_size: nil,
sub_batch_size: SUB_BATCH_SIZE
)
@@ -86,7 +87,7 @@ module Gitlab
migration_status = batch_max_value.nil? ? :finished : :active
batch_max_value ||= batch_min_value
- migration = Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
+ migration = Gitlab::Database::BackgroundMigration::BatchedMigration.new(
job_class_name: job_class_name,
table_name: batch_table_name,
column_name: batch_column_name,
@@ -97,19 +98,28 @@ module Gitlab
batch_class_name: batch_class_name,
batch_size: batch_size,
sub_batch_size: sub_batch_size,
- status: migration_status)
+ status: migration_status
+ )
- # This guard is necessary since #total_tuple_count was only introduced schema-wise,
- # after this migration helper had been used for the first time.
- return migration unless migration.respond_to?(:total_tuple_count)
+ # Below `BatchedMigration` attributes were introduced after the
+ # initial `batched_background_migrations` table was created, so any
+ # migrations that ran relying on initial table schema would not know
+ # about columns introduced later on because this model is not
+ # isolated in migrations, which is why we need to check for existence
+ # of these columns first.
+ if migration.respond_to?(:max_batch_size)
+ migration.max_batch_size = max_batch_size
+ end
- # We keep track of the estimated number of tuples to reason later
- # about the overall progress of a migration.
- migration.total_tuple_count = Gitlab::Database::SharedModel.using_connection(connection) do
- Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
+ if migration.respond_to?(:total_tuple_count)
+ # We keep track of the estimated number of tuples to reason later
+ # about the overall progress of a migration.
+ migration.total_tuple_count = Gitlab::Database::SharedModel.using_connection(connection) do
+ Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
+ end
end
- migration.save!
+ migration.save!
migration
end
end
diff --git a/lib/gitlab/database/migrations/instrumentation.rb b/lib/gitlab/database/migrations/instrumentation.rb
index 1f7e81cae84..7f34768350b 100644
--- a/lib/gitlab/database/migrations/instrumentation.rb
+++ b/lib/gitlab/database/migrations/instrumentation.rb
@@ -15,30 +15,26 @@ module Gitlab
end
def observe(version:, name:, connection:, &block)
- observation = Observation.new(version, name)
- observation.success = true
+ observation = Observation.new(version: version, name: name, success: false)
observers = observer_classes.map { |c| c.new(observation, @result_dir, connection) }
- exception = nil
-
on_each_observer(observers) { |observer| observer.before }
- observation.walltime = Benchmark.realtime do
- yield
- rescue StandardError => e
- exception = e
- observation.success = false
- end
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ yield
+
+ observation.success = true
+
+ observation
+ ensure
+ observation.walltime = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
on_each_observer(observers) { |observer| observer.after }
on_each_observer(observers) { |observer| observer.record }
record_observation(observation)
-
- raise exception if exception
-
- observation
end
private
diff --git a/lib/gitlab/database/migrations/lock_retry_mixin.rb b/lib/gitlab/database/migrations/lock_retry_mixin.rb
index fff0f35e33c..9774797676a 100644
--- a/lib/gitlab/database/migrations/lock_retry_mixin.rb
+++ b/lib/gitlab/database/migrations/lock_retry_mixin.rb
@@ -9,6 +9,10 @@ module Gitlab
migration.class
end
+ def migration_connection
+ migration.connection
+ end
+
def enable_lock_retries?
# regular AR migrations don't have this,
# only ones inheriting from Gitlab::Database::Migration have
@@ -24,6 +28,7 @@ module Gitlab
def ddl_transaction(migration, &block)
if use_transaction?(migration) && migration.enable_lock_retries?
Gitlab::Database::WithLockRetries.new(
+ connection: migration.migration_connection,
klass: migration.migration_class,
logger: Gitlab::BackgroundMigration::Logger
).run(raise_on_exhaustion: false, &block)
diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb
index a494c357950..228eea3393c 100644
--- a/lib/gitlab/database/migrations/observation.rb
+++ b/lib/gitlab/database/migrations/observation.rb
@@ -10,7 +10,8 @@ module Gitlab
:walltime,
:success,
:total_database_size_change,
- :query_statistics
+ :query_statistics,
+ keyword_init: true
)
end
end
diff --git a/lib/gitlab/database/partitioning.rb b/lib/gitlab/database/partitioning.rb
index 1343354715a..c7d8bdf30bc 100644
--- a/lib/gitlab/database/partitioning.rb
+++ b/lib/gitlab/database/partitioning.rb
@@ -3,19 +3,8 @@
module Gitlab
module Database
module Partitioning
- class TableWithoutModel
- include PartitionedTable::ClassMethods
-
- attr_reader :table_name
-
- def initialize(table_name:, partitioned_column:, strategy:)
- @table_name = table_name
- partitioned_by(partitioned_column, strategy: strategy)
- end
-
- def connection
- Gitlab::Database::SharedModel.connection
- end
+ class TableWithoutModel < Gitlab::Database::SharedModel
+ include PartitionedTable
end
class << self
@@ -77,7 +66,15 @@ module Gitlab
def registered_for_sync
registered_models + registered_tables.map do |table|
- TableWithoutModel.new(**table)
+ table_without_model(**table)
+ end
+ end
+
+ def table_without_model(table_name:, partitioned_column:, strategy:, limit_connection_names: nil)
+ Class.new(TableWithoutModel).tap do |klass|
+ klass.table_name = table_name
+ klass.partitioned_by(partitioned_column, strategy: strategy)
+ klass.limit_connection_names = limit_connection_names
end
end
end
diff --git a/lib/gitlab/database/partitioning/partition_manager.rb b/lib/gitlab/database/partitioning/partition_manager.rb
index ba6fa0cf278..ab414f91169 100644
--- a/lib/gitlab/database/partitioning/partition_manager.rb
+++ b/lib/gitlab/database/partitioning/partition_manager.rb
@@ -12,10 +12,15 @@ module Gitlab
def initialize(model)
@model = model
+ @connection_name = model.connection.pool.db_config.name
end
def sync_partitions
- Gitlab::AppLogger.info(message: "Checking state of dynamic postgres partitions", table_name: model.table_name)
+ Gitlab::AppLogger.info(
+ message: "Checking state of dynamic postgres partitions",
+ table_name: model.table_name,
+ connection_name: @connection_name
+ )
# Double-checking before getting the lease:
# The prevailing situation is no missing partitions and no extra partitions
@@ -29,10 +34,13 @@ module Gitlab
detach(partitions_to_detach) unless partitions_to_detach.empty?
end
rescue StandardError => e
- Gitlab::AppLogger.error(message: "Failed to create / detach partition(s)",
- table_name: model.table_name,
- exception_class: e.class,
- exception_message: e.message)
+ Gitlab::AppLogger.error(
+ message: "Failed to create / detach partition(s)",
+ table_name: model.table_name,
+ exception_class: e.class,
+ exception_message: e.message,
+ connection_name: @connection_name
+ )
end
private
@@ -98,9 +106,12 @@ module Gitlab
Postgresql::DetachedPartition.create!(table_name: partition.partition_name,
drop_after: RETAIN_DETACHED_PARTITIONS_FOR.from_now)
- Gitlab::AppLogger.info(message: "Detached Partition",
- partition_name: partition.partition_name,
- table_name: partition.table)
+ Gitlab::AppLogger.info(
+ message: "Detached Partition",
+ partition_name: partition.partition_name,
+ table_name: partition.table,
+ connection_name: @connection_name
+ )
end
def assert_partition_detachable!(partition)
diff --git a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
index f551fa06cad..9cab2c51b3f 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
@@ -49,7 +49,7 @@ module Gitlab
end
def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
- define_batchable_model(source_table)
+ define_batchable_model(source_table, connection: connection)
.where(source_key_column => start_id..stop_id)
end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
index 984c708aa48..e56ffddac4f 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -5,7 +5,6 @@ module Gitlab
module PartitioningMigrationHelpers
module TableManagementHelpers
include ::Gitlab::Database::SchemaHelpers
- include ::Gitlab::Database::DynamicModelHelpers
include ::Gitlab::Database::MigrationHelpers
include ::Gitlab::Database::Migrations::BackgroundMigrationHelpers
diff --git a/lib/gitlab/database/query_analyzers/base.rb b/lib/gitlab/database/query_analyzers/base.rb
index 0802d3c8013..5f321ece962 100644
--- a/lib/gitlab/database/query_analyzers/base.rb
+++ b/lib/gitlab/database/query_analyzers/base.rb
@@ -48,11 +48,15 @@ module Gitlab
end
def self.context_key
- "#{self.class.name}_context"
+ @context_key ||= "analyzer_#{self.analyzer_key}_context".to_sym
end
def self.suppress_key
- "#{self.class.name}_suppressed"
+ @suppress_key ||= "analyzer_#{self.analyzer_key}_suppressed".to_sym
+ end
+
+ def self.analyzer_key
+ @analyzer_key ||= self.name.demodulize.underscore.to_sym
end
end
end
diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
index 2e3db2a5c6e..a604f79dc41 100644
--- a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
+++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
@@ -56,6 +56,9 @@ module Gitlab
context[:transaction_depth_by_db][database] -= 1
if context[:transaction_depth_by_db][database] == 0
context[:modified_tables_by_db][database].clear
+
+ # Attempt to troubleshoot https://gitlab.com/gitlab-org/gitlab/-/issues/351531
+ ::CrossDatabaseModification::TransactionStackTrackRecord.log_gitlab_transactions_stack(action: :end_of_transaction)
elsif context[:transaction_depth_by_db][database] < 0
context[:transaction_depth_by_db][database] = 0
raise CrossDatabaseModificationAcrossUnsupportedTablesError, "Misaligned cross-DB transactions discovered at query #{sql}. This could be a bug in #{self.class} or a valid issue to investigate. Read more at https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions ."
@@ -87,6 +90,8 @@ module Gitlab
all_tables = context[:modified_tables_by_db].values.map(&:to_a).flatten
schemas = ::Gitlab::Database::GitlabSchema.table_schemas(all_tables)
+ schemas += ApplicationRecord.gitlab_transactions_stack
+
if schemas.many?
message = "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \
"a transaction modifying the '#{all_tables.to_a.join(", ")}' tables." \
diff --git a/lib/gitlab/database/schema_helpers.rb b/lib/gitlab/database/schema_helpers.rb
index 9ddc5391689..f96de13006f 100644
--- a/lib/gitlab/database/schema_helpers.rb
+++ b/lib/gitlab/database/schema_helpers.rb
@@ -73,6 +73,7 @@ module Gitlab
def with_lock_retries(&block)
Gitlab::Database::WithLockRetries.new(
+ connection: connection,
klass: self.class,
logger: Gitlab::BackgroundMigration::Logger
).run(&block)
diff --git a/lib/gitlab/database/shared_model.rb b/lib/gitlab/database/shared_model.rb
index 17d7886e8c8..563fab692ef 100644
--- a/lib/gitlab/database/shared_model.rb
+++ b/lib/gitlab/database/shared_model.rb
@@ -6,6 +6,10 @@ module Gitlab
class SharedModel < ActiveRecord::Base
self.abstract_class = true
+ # if shared model is used, this allows to limit connections
+ # on which this model is being shared
+ class_attribute :limit_connection_names, default: nil
+
class << self
def using_connection(connection)
previous_connection = self.overriding_connection
diff --git a/lib/gitlab/database/with_lock_retries.rb b/lib/gitlab/database/with_lock_retries.rb
index f9d467ae5cc..f2c5bb9088f 100644
--- a/lib/gitlab/database/with_lock_retries.rb
+++ b/lib/gitlab/database/with_lock_retries.rb
@@ -61,7 +61,7 @@ module Gitlab
[10.seconds, 10.minutes]
].freeze
- def initialize(logger: NULL_LOGGER, allow_savepoints: true, timing_configuration: DEFAULT_TIMING_CONFIGURATION, klass: nil, env: ENV, connection: ActiveRecord::Base.connection)
+ def initialize(logger: NULL_LOGGER, allow_savepoints: true, timing_configuration: DEFAULT_TIMING_CONFIGURATION, klass: nil, env: ENV, connection:)
@logger = logger
@klass = klass
@allow_savepoints = allow_savepoints
diff --git a/lib/gitlab/email/handler/create_note_handler.rb b/lib/gitlab/email/handler/create_note_handler.rb
index 4fa2fe1724e..b168efaac11 100644
--- a/lib/gitlab/email/handler/create_note_handler.rb
+++ b/lib/gitlab/email/handler/create_note_handler.rb
@@ -24,6 +24,8 @@ module Gitlab
validate_permission!(:create_note)
+ validate_from_address!
+
raise NoteableNotFoundError unless noteable
raise EmptyEmailError if note_message.blank?
@@ -56,6 +58,17 @@ module Gitlab
message_with_appended_reply
end
+
+ def from_address
+ mail.from&.first
+ end
+
+ def validate_from_address!
+ # Recipieint is always set to Support bot for ServiceDesk issues so we should exclude those.
+ return if author == User.support_bot
+
+ raise UserNotFoundError unless from_address && author.verified_email?(from_address)
+ end
end
end
end
diff --git a/lib/gitlab/event_store.rb b/lib/gitlab/event_store.rb
index 3d7b6b27eb0..e20ea1c7365 100644
--- a/lib/gitlab/event_store.rb
+++ b/lib/gitlab/event_store.rb
@@ -18,7 +18,7 @@ module Gitlab
end
def self.instance
- @instance ||= configure!
+ @instance ||= Store.new { |store| configure!(store) }
end
# Define all event subscriptions using:
@@ -29,14 +29,15 @@ module Gitlab
#
# store.subscribe(DomainA::SomeWorker, to: DomainB::SomeEvent), if: ->(event) { event.data == :some_value }
#
- def self.configure!
- Store.new do |store|
- ###
- # Add subscriptions here:
+ def self.configure!(store)
+ ###
+ # Add subscriptions here:
- store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, to: ::Ci::PipelineCreatedEvent
- end
+ store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, to: ::Ci::PipelineCreatedEvent
+ store.subscribe ::Namespaces::UpdateRootStatisticsWorker, to: ::Projects::ProjectDeletedEvent
end
private_class_method :configure!
end
end
+
+Gitlab::EventStore.prepend_mod_with('Gitlab::EventStore')
diff --git a/lib/gitlab/event_store/store.rb b/lib/gitlab/event_store/store.rb
index ecf3cd7e562..2e5e0215687 100644
--- a/lib/gitlab/event_store/store.rb
+++ b/lib/gitlab/event_store/store.rb
@@ -29,7 +29,7 @@ module Gitlab
raise InvalidEvent, "Event being published is not an instance of Gitlab::EventStore::Event: got #{event.inspect}"
end
- subscriptions[event.class].each do |subscription|
+ subscriptions.fetch(event.class, []).each do |subscription|
subscription.consume_event(event)
end
end
diff --git a/lib/gitlab/event_store/subscriber.rb b/lib/gitlab/event_store/subscriber.rb
index cf326d1f9e4..9f569059736 100644
--- a/lib/gitlab/event_store/subscriber.rb
+++ b/lib/gitlab/event_store/subscriber.rb
@@ -7,7 +7,6 @@
#
# @example:
# class SomeEventSubscriber
-# include ApplicationWorker
# include Gitlab::EventStore::Subscriber
#
# def handle_event(event)
@@ -18,6 +17,14 @@
module Gitlab
module EventStore
module Subscriber
+ extend ActiveSupport::Concern
+
+ included do
+ include ApplicationWorker
+
+ loggable_arguments 0, 1
+ end
+
def perform(event_type, data)
raise InvalidEvent, event_type unless self.class.const_defined?(event_type)
diff --git a/lib/gitlab/experiment/rollout/feature.rb b/lib/gitlab/experiment/rollout/feature.rb
new file mode 100644
index 00000000000..5a14e3c272e
--- /dev/null
+++ b/lib/gitlab/experiment/rollout/feature.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class Experiment
+ module Rollout
+ class Feature < Percent
+ # For this rollout strategy to consider an experiment as enabled, we
+ # must:
+ #
+ # - have a feature flag yaml file that declares it.
+ # - be in an environment that permits it.
+ # - not have rolled out the feature flag at all (no percent of actors,
+ # no inclusions, etc.)
+ def enabled?
+ return false if ::Feature::Definition.get(feature_flag_name).nil?
+ return false unless Gitlab.dev_env_or_com?
+
+ ::Feature.get(feature_flag_name).state != :off # rubocop:disable Gitlab/AvoidFeatureGet
+ end
+
+ # For assignment we first check to see if our feature flag is enabled
+ # for "self". This is done by calling `#flipper_id` (used behind the
+ # scenes by `Feature`). By default this is our `experiment.id` (or more
+ # specifically, the context key, which is an anonymous SHA generated
+ # using the details of an experiment.
+ #
+ # If the `Feature.enabled?` check is false, we return nil implicitly,
+ # which will assign the control. Otherwise we call super, which will
+ # assign a variant evenly, or based on our provided distribution rules.
+ def execute_assigment
+ super if ::Feature.enabled?(feature_flag_name, self, type: :experiment, default_enabled: :yaml)
+ end
+
+ # NOTE: There's a typo in the name of this method that we'll fix up.
+ alias_method :execute_assignment, :execute_assigment
+
+ # This is what's provided to the `Feature.enabled?` call that will be
+ # used to determine experiment inclusion. An experiment may provide an
+ # override for this method to make the experiment work on user, group,
+ # or projects.
+ #
+ # For example, when running an experiment on a project, you could make
+ # the experiment assignable by project (using chatops) by implementing
+ # a `flipper_id` method in the experiment:
+ #
+ # def flipper_id
+ # context.project.flipper_id
+ # end
+ #
+ # Or even cleaner, simply delegate it:
+ #
+ # delegate :flipper_id, to: -> { context.project }
+ def flipper_id
+ return experiment.flipper_id if experiment.respond_to?(:flipper_id)
+
+ "Experiment;#{id}"
+ end
+
+ private
+
+ def feature_flag_name
+ experiment.name.tr('/', '_')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/reference_update_error.rb b/lib/gitlab/git/reference_update_error.rb
new file mode 100644
index 00000000000..bc1452b74f0
--- /dev/null
+++ b/lib/gitlab/git/reference_update_error.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ # ReferenceUpdateError represents an error that happen when trying to
+ # update a Git reference.
+ class ReferenceUpdateError < StandardError
+ def initialize(message, reference, old_oid, new_oid)
+ @message = message
+ @reference = reference
+ @old_oid = old_oid
+ @new_oid = new_oid
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 240a701aba9..c3ee5b97379 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -972,18 +972,6 @@ module Gitlab
@praefect_info_client ||= Gitlab::GitalyClient::PraefectInfoService.new(self)
end
- def clean_stale_repository_files
- wrapped_gitaly_errors do
- gitaly_repository_client.cleanup if exists?
- end
- rescue Gitlab::Git::CommandError => e # Don't fail if we can't cleanup
- Gitlab::AppLogger.error("Unable to clean repository on storage #{storage} with relative path #{relative_path}: #{e.message}")
- Gitlab::Metrics.counter(
- :failed_repository_cleanup_total,
- 'Number of failed repository cleanup events'
- ).increment
- end
-
def branch_names_contains_sha(sha)
gitaly_ref_client.branch_names_contains_sha(sha)
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 759c6b93d9a..f98fb66ad21 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -328,11 +328,6 @@ module Gitlab
raise ForbiddenError, error_message(:push_code)
end
else
- # If there are worktrees with a HEAD pointing to a non-existent object,
- # calls to `git rev-list --all` will fail in git 2.15+. This should also
- # clear stale lock files.
- project.repository.clean_stale_repository_files if project.present?
-
check_access!
end
end
@@ -467,11 +462,6 @@ module Gitlab
def check_push_size!
return unless check_size_limit?
- # If there are worktrees with a HEAD pointing to a non-existent object,
- # calls to `git rev-list --all` will fail in git 2.15+. This should also
- # clear stale lock files.
- repository.clean_stale_repository_files
-
# Use #check_repository_disk_size to get correct push size whenever a lot of changes
# gets pushed at the same time containing the same blobs. This is only
# doable if GIT_OBJECT_DIRECTORY_RELATIVE env var is set and happens
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index c17934f12c3..adbf07de1b9 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -168,8 +168,12 @@ module Gitlab
raise unless decoded_error.present?
- raise decoded_error
+ # We simply ignore any reference update errors which are typically an
+ # indicator of multiple RPC calls trying to update the same reference
+ # at the same point in time.
+ return if decoded_error.is_a?(Gitlab::Git::ReferenceUpdateError)
+ raise decoded_error
ensure
request_enum.close
end
@@ -495,6 +499,12 @@ module Gitlab
access_check_error = detailed_error.access_check
# These messages were returned from internal/allowed API calls
Gitlab::Git::PreReceiveError.new(fallback_message: access_check_error.error_message)
+ when :reference_update
+ reference_update_error = detailed_error.reference_update
+ Gitlab::Git::ReferenceUpdateError.new(err.details,
+ reference_update_error.reference_name,
+ reference_update_error.old_oid,
+ reference_update_error.new_oid)
else
# We're handling access_check only for now, but we'll add more detailed error types
nil
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 7e7d543d0a5..73848dfff5d 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -21,11 +21,6 @@ module Gitlab
response.exists
end
- def cleanup
- request = Gitaly::CleanupRequest.new(repository: @gitaly_repo)
- GitalyClient.call(@storage, :repository_service, :cleanup, request, timeout: GitalyClient.fast_timeout)
- end
-
def garbage_collect(create_bitmap, prune:)
request = Gitaly::GarbageCollectRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap, prune: prune)
GitalyClient.call(@storage, :repository_service, :garbage_collect, request, timeout: GitalyClient.long_timeout)
diff --git a/lib/gitlab/github_import/importer/diff_note_importer.rb b/lib/gitlab/github_import/importer/diff_note_importer.rb
index 8a8d23401c1..02b582190b6 100644
--- a/lib/gitlab/github_import/importer/diff_note_importer.rb
+++ b/lib/gitlab/github_import/importer/diff_note_importer.rb
@@ -26,7 +26,7 @@ module Gitlab
# because it cannot use the BulkImporting strategy, which skips
# callbacks and validations. For this reason, notes that don't have
# suggestions are still imported with LegacyDiffNote
- if import_with_diff_note?
+ if note.contains_suggestion?
import_with_diff_note
else
import_with_legacy_diff_note
@@ -48,17 +48,6 @@ module Gitlab
attr_reader :note, :project, :client, :author_id, :author_found
- def import_with_diff_note?
- note.contains_suggestion? && use_diff_note_with_suggestions_enabled?
- end
-
- def use_diff_note_with_suggestions_enabled?
- Feature.enabled?(
- :github_importer_use_diff_note_with_suggestions,
- default_enabled: :yaml
- )
- end
-
def build_author_attributes
@author_id, @author_found = user_finder.author_id_for(note)
end
diff --git a/lib/gitlab/github_import/importer/pull_requests_importer.rb b/lib/gitlab/github_import/importer/pull_requests_importer.rb
index d7eaa5a470b..fc0c099b71c 100644
--- a/lib/gitlab/github_import/importer/pull_requests_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_importer.rb
@@ -38,7 +38,7 @@ module Gitlab
# deliberate. If we were to update this column after the fetch we may
# miss out on changes pushed during the fetch or between the fetch and
# updating the timestamp.
- project.update_column(:last_repository_updated_at, Time.zone.now)
+ project.touch(:last_repository_updated_at) # rubocop: disable Rails/SkipsModelValidations
project.repository.fetch_remote(project.import_url, refmap: Gitlab::GithubImport.refmap, forced: true)
diff --git a/lib/gitlab/github_import/importer/releases_importer.rb b/lib/gitlab/github_import/importer/releases_importer.rb
index c1fbd868800..64ec0251e54 100644
--- a/lib/gitlab/github_import/importer/releases_importer.rb
+++ b/lib/gitlab/github_import/importer/releases_importer.rb
@@ -21,10 +21,12 @@ module Gitlab
end
def already_imported?(release)
- existing_tags.include?(release.tag_name)
+ existing_tags.include?(release.tag_name) || release.tag_name.nil?
end
def build(release)
+ existing_tags.add(release.tag_name)
+
{
name: release.name,
tag: release.tag_name,
diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb
index 20068a33019..aba4729e9c8 100644
--- a/lib/gitlab/github_import/importer/repository_importer.rb
+++ b/lib/gitlab/github_import/importer/repository_importer.rb
@@ -80,7 +80,7 @@ module Gitlab
end
def update_clone_time
- project.update_column(:last_repository_updated_at, Time.zone.now)
+ project.touch(:last_repository_updated_at) # rubocop: disable Rails/SkipsModelValidations
end
private
diff --git a/lib/gitlab/github_import/object_counter.rb b/lib/gitlab/github_import/object_counter.rb
index 4c9a8da601f..7ce88280209 100644
--- a/lib/gitlab/github_import/object_counter.rb
+++ b/lib/gitlab/github_import/object_counter.rb
@@ -71,11 +71,7 @@ module Gitlab
add_counter_to_list(project, operation, counter_key)
- if Feature.disabled?(:import_redis_increment_by, default_enabled: :yaml)
- CACHING.increment(counter_key)
- else
- CACHING.increment_by(counter_key, value)
- end
+ CACHING.increment_by(counter_key, value)
end
def add_counter_to_list(project, operation, key)
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index 04f53accfeb..883abef9bdb 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -129,17 +129,7 @@ module Gitlab
def discussion_id
strong_memoize(:discussion_id) do
- if in_reply_to_id.present?
- current_discussion_id
- else
- Discussion.discussion_id(
- Struct
- .new(:noteable_id, :noteable_type)
- .new(merge_request.id, NOTEABLE_TYPE)
- ).tap do |discussion_id|
- cache_discussion_id(discussion_id)
- end
- end
+ (in_reply_to_id.present? && current_discussion_id) || generate_discussion_id
end
end
@@ -160,6 +150,16 @@ module Gitlab
side == 'RIGHT'
end
+ def generate_discussion_id
+ Discussion.discussion_id(
+ Struct
+ .new(:noteable_id, :noteable_type)
+ .new(merge_request.id, NOTEABLE_TYPE)
+ ).tap do |discussion_id|
+ cache_discussion_id(discussion_id)
+ end
+ end
+
def cache_discussion_id(discussion_id)
Gitlab::Cache::Import::Caching.write(discussion_id_cache_key(note_id), discussion_id)
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index ac3b4de0988..2bd59415771 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -27,6 +27,7 @@ module Gitlab
gon.revision = Gitlab.revision
gon.feature_category = Gitlab::ApplicationContext.current_context_attribute(:feature_category).presence
gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png')
+ gon.secure = Gitlab.config.gitlab.https
gon.sprite_icons = IconsHelper.sprite_icon_path
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
diff --git a/lib/gitlab/graphql/project/dast_profile_connection_extension.rb b/lib/gitlab/graphql/project/dast_profile_connection_extension.rb
new file mode 100644
index 00000000000..a3c3f2f2b7e
--- /dev/null
+++ b/lib/gitlab/graphql/project/dast_profile_connection_extension.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+module Gitlab
+ module Graphql
+ module Project
+ class DastProfileConnectionExtension < GraphQL::Schema::Field::ConnectionExtension
+ def after_resolve(value:, object:, context:, **rest)
+ preload_authorizations(context[:project_dast_profiles])
+ context[:project_dast_profiles] = nil
+ value
+ end
+
+ def preload_authorizations(dast_profiles)
+ return unless dast_profiles
+
+ projects = dast_profiles.map(&:project)
+ users = dast_profiles.filter_map { |dast_profile| dast_profile.dast_profile_schedule&.owner }
+ Preloaders::UsersMaxAccessLevelInProjectsPreloader.new(projects: projects, users: users).execute
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/hook_data/project_builder.rb b/lib/gitlab/hook_data/project_builder.rb
index 65c237f743f..ebd97d3ab1b 100644
--- a/lib/gitlab/hook_data/project_builder.rb
+++ b/lib/gitlab/hook_data/project_builder.rb
@@ -16,6 +16,7 @@ module Gitlab
# project_id: 1,
# owner_name: "John",
# owner_email: "user1@example.org",
+ # owners: [name: "John", email: "user1@example.org"],
# project_visibility: "internal",
# old_path_with_namespace: "old-path-with-namespace"
# }
@@ -32,19 +33,33 @@ module Gitlab
private
def project_data
- owner = project.owner
+ owners = project.owners.compact
+ # When this is removed, also remove the `deprecated_owner` method
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350603
+ owner = project.deprecated_owner
{
name: project.name,
path: project.path,
path_with_namespace: project.full_path,
project_id: project.id,
- owner_name: owner.name,
- owner_email: owner.respond_to?(:email) ? owner.email : "",
+ owner_name: owner.try(:name),
+ owner_email: user_email(owner),
+ owners: owners.map do |owner|
+ owner_data(owner)
+ end,
project_visibility: project.visibility.downcase
}
end
+ def owner_data(user)
+ { name: user.name, email: user_email(user) }
+ end
+
+ def user_email(user)
+ user.respond_to?(:email) ? user.email : ""
+ end
+
def event_specific_project_data(event)
return {} unless event == :rename || event == :transfer
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index d0918fc39bc..7bb16e071b0 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -9,6 +9,7 @@ module Gitlab
BlockedUrlError = Class.new(StandardError)
RedirectionTooDeep = Class.new(StandardError)
ReadTotalTimeout = Class.new(Net::ReadTimeout)
+ HeaderReadTimeout = Class.new(Net::ReadTimeout)
HTTP_TIMEOUT_ERRORS = [
Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout, Gitlab::HTTP::ReadTotalTimeout
@@ -24,7 +25,7 @@ module Gitlab
read_timeout: 20,
write_timeout: 30
}.freeze
- DEFAULT_READ_TOTAL_TIMEOUT = 20.seconds
+ DEFAULT_READ_TOTAL_TIMEOUT = 30.seconds
include HTTParty # rubocop:disable Gitlab/HTTParty
diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb
index f7a3da53fdb..dfecf3a669e 100644
--- a/lib/gitlab/http_connection_adapter.rb
+++ b/lib/gitlab/http_connection_adapter.rb
@@ -1,14 +1,23 @@
# frozen_string_literal: true
-# This class is part of the Gitlab::HTTP wrapper. Depending on the value
-# of the global setting allow_local_requests_from_web_hooks_and_services this adapter
-# will allow/block connection to internal IPs and/or urls.
+# This class is part of the Gitlab::HTTP wrapper. It handles local requests and header timeouts
#
-# This functionality can be overridden by providing the setting the option
-# allow_local_requests = true in the request. For example:
-# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
+# 1. Local requests
+# Depending on the value of the global setting allow_local_requests_from_web_hooks_and_services,
+# this adapter will allow/block connection to internal IPs and/or urls.
#
-# This option will take precedence over the global setting.
+# This functionality can be overridden by providing the setting the option
+# allow_local_requests = true in the request. For example:
+# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
+#
+# This option will take precedence over the global setting.
+#
+# 2. Header timeouts
+# When the use_read_total_timeout option is used, that means the receiver
+# of the HTTP request cannot be trusted. Gitlab::BufferedIo will be used,
+# to read header data. It is a modified version of Net::BufferedIO that
+# raises a timeout error if reading header data takes too much time.
+
module Gitlab
class HTTPConnectionAdapter < HTTParty::ConnectionAdapter
extend ::Gitlab::Utils::Override
@@ -17,9 +26,20 @@ module Gitlab
def connection
@uri, hostname = validate_url!(uri)
- super.tap do |http|
- http.hostname_override = hostname if hostname
+ http = super
+ http.hostname_override = hostname if hostname
+
+ if Feature.enabled?(:header_read_timeout_buffered_io)
+ gitlab_http = Gitlab::NetHttpAdapter.new(http.address, http.port)
+
+ http.instance_variables.each do |variable|
+ gitlab_http.instance_variable_set(variable, http.instance_variable_get(variable))
+ end
+
+ return gitlab_http
end
+
+ http
end
private
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index f056381b86a..584f7d4aeaf 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -43,29 +43,29 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 0,
'cs_CZ' => 0,
- 'da_DK' => 49,
+ 'da_DK' => 48,
'de' => 15,
'en' => 100,
'eo' => 0,
- 'es' => 38,
+ 'es' => 39,
'fil_PH' => 0,
'fr' => 11,
'gl_ES' => 0,
'id_ID' => 0,
'it' => 2,
- 'ja' => 36,
- 'ko' => 12,
- 'nb_NO' => 32,
+ 'ja' => 35,
+ 'ko' => 13,
+ 'nb_NO' => 31,
'nl_NL' => 0,
- 'pl_PL' => 5,
+ 'pl_PL' => 4,
'pt_BR' => 50,
'ro_RO' => 22,
- 'ru' => 26,
+ 'ru' => 32,
'tr_TR' => 14,
- 'uk' => 45,
- 'zh_CN' => 98,
+ 'uk' => 44,
+ 'zh_CN' => 96,
'zh_HK' => 2,
- 'zh_TW' => 3
+ 'zh_TW' => 2
}.freeze
private_constant :TRANSLATION_LEVELS
diff --git a/lib/gitlab/import_export/base/object_builder.rb b/lib/gitlab/import_export/base/object_builder.rb
index 5e9c8292c1e..7dee0f783cc 100644
--- a/lib/gitlab/import_export/base/object_builder.rb
+++ b/lib/gitlab/import_export/base/object_builder.rb
@@ -31,12 +31,18 @@ module Gitlab
def find
find_with_cache do
- find_object || klass.create(prepare_attributes)
+ find_object || create_object
end
end
protected
+ def create_object
+ klass.transaction do
+ klass.create(prepare_attributes)
+ end
+ end
+
def where_clauses
raise NotImplementedError
end
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 3da9083e743..e520cade517 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -81,20 +81,20 @@ module Gitlab
return true if status == 0
+ output = output&.strip
+ message = "command exited with error code #{status}"
+ message += ": #{output}" if output.present?
+
if @shared.respond_to?(:error)
- @shared.error(Gitlab::ImportExport::Error.new(output.to_s))
+ @shared.error(Gitlab::ImportExport::Error.new(message))
false
else
- raise Gitlab::ImportExport::Error, 'System call failed'
+ raise Gitlab::ImportExport::Error, message
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
- def git_bin_path
- Gitlab.config.git.bin_path
- end
-
def copy_files(source, destination)
# if we are copying files, create the destination folder
destination_folder = File.file?(source) ? File.dirname(destination) : destination
diff --git a/lib/gitlab/import_export/group/object_builder.rb b/lib/gitlab/import_export/group/object_builder.rb
index e171a31348e..43cc7a78a61 100644
--- a/lib/gitlab/import_export/group/object_builder.rb
+++ b/lib/gitlab/import_export/group/object_builder.rb
@@ -9,12 +9,6 @@ module Gitlab
# `Group::ObjectBuilder.build(Label, label_attributes)`
# finds or initializes a label with the given attributes.
class ObjectBuilder < Base::ObjectBuilder
- def self.build(*args)
- ::Group.transaction do
- super
- end
- end
-
def initialize(klass, attributes)
super
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index fb8d6e7d89b..d893c8dfaa3 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -6,15 +6,10 @@ module Gitlab
class StreamingSerializer
include Gitlab::ImportExport::CommandLineUtil
- BATCH_SIZE = 100
- SMALLER_BATCH_SIZE = 2
+ BATCH_SIZE = 2
def self.batch_size(exportable)
- if Feature.enabled?(:export_reduce_relation_batch_size, exportable)
- SMALLER_BATCH_SIZE
- else
- BATCH_SIZE
- end
+ BATCH_SIZE
end
class Raw < String
diff --git a/lib/gitlab/import_export/project/object_builder.rb b/lib/gitlab/import_export/project/object_builder.rb
index 64496d23402..bf60d115a25 100644
--- a/lib/gitlab/import_export/project/object_builder.rb
+++ b/lib/gitlab/import_export/project/object_builder.rb
@@ -13,12 +13,6 @@ module Gitlab
#
# It also adds some logic around Group Labels/Milestones for edge cases.
class ObjectBuilder < Base::ObjectBuilder
- def self.build(*args)
- ::Project.transaction do
- super
- end
- end
-
def initialize(klass, attributes)
super
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index bec709f4a36..07f4b333378 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -16,19 +16,20 @@ module Gitlab
def save
if compress_and_save
- Gitlab::Export::Logger.info(
- message: 'Export archive saved',
- exportable_class: @exportable.class.to_s,
- archive_file: archive_file
- )
+ log_export_results('Export archive saved')
save_upload
+
+ log_export_results('Export archive uploaded')
else
@shared.error(Gitlab::ImportExport::Error.new(error_message))
+
false
end
rescue StandardError => e
@shared.error(e)
+ log_export_results('Export archive saver failed')
+
false
ensure
remove_archive_tmp_dir
@@ -36,8 +37,16 @@ module Gitlab
private
+ attr_accessor :compress_duration_s, :assign_duration_s, :upload_duration_s, :upload_bytes
+
def compress_and_save
- tar_czf(archive: archive_file, dir: @shared.export_path)
+ result = nil
+
+ @compress_duration_s = Benchmark.realtime do
+ result = tar_czf(archive: archive_file, dir: @shared.export_path)
+ end
+
+ result
end
def remove_archive_tmp_dir
@@ -51,9 +60,14 @@ module Gitlab
def save_upload
upload = initialize_upload
- File.open(archive_file) { |file| upload.export_file = file }
+ @upload_bytes = File.size(archive_file)
+ @assign_duration_s = Benchmark.realtime do
+ File.open(archive_file) { |file| upload.export_file = file }
+ end
+
+ @upload_duration_s = Benchmark.realtime { upload.save! }
- upload.save!
+ true
end
def error_message
@@ -65,6 +79,23 @@ module Gitlab
ImportExportUpload.find_or_initialize_by(Hash[exportable_kind, @exportable])
end
+
+ def log_export_results(message)
+ Gitlab::Export::Logger.info(message: message, **log_data)
+ end
+
+ def log_data
+ ApplicationContext.current.merge(
+ {
+ exportable_class: @exportable.class.to_s,
+ archive_file: archive_file,
+ compress_duration_s: compress_duration_s&.round(6),
+ assign_duration_s: assign_duration_s&.round(6),
+ upload_duration_s: upload_duration_s&.round(6),
+ upload_bytes: upload_bytes
+ }
+ ).compact
+ end
end
end
end
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index f1370a40222..368b621bdfb 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -180,9 +180,6 @@ module Gitlab
class GrapeFormatter
# Convert an object to JSON.
#
- # This will default to the built-in Grape formatter if either :oj_json or :grape_gitlab_json
- # flags are disabled.
- #
# The `env` param is ignored because it's not needed in either our formatter or Grape's,
# but it is passed through for consistency.
#
@@ -194,11 +191,7 @@ module Gitlab
def self.call(object, env = nil)
return object.to_s if object.is_a?(PrecompiledJson)
- if Feature.enabled?(:grape_gitlab_json, default_enabled: true)
- Gitlab::Json.dump(object)
- else
- Grape::Formatter::Json.call(object, env)
- end
+ Gitlab::Json.dump(object)
end
end
@@ -248,8 +241,6 @@ module Gitlab
# @return [String]
# @raise [LimitExceeded] if the resulting json string is bigger than the specified limit
def self.encode(object, limit: 25.megabytes)
- return ::Gitlab::Json.dump(object) unless Feature.enabled?(:json_limited_encoder)
-
buffer = StringIO.new
buffer_size = 0
diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb
index a083ae60726..0fb7e376f5b 100644
--- a/lib/gitlab/legacy_github_import/release_formatter.rb
+++ b/lib/gitlab/legacy_github_import/release_formatter.rb
@@ -25,7 +25,7 @@ module Gitlab
end
def valid?
- !raw_data.draft
+ !raw_data.draft && raw_data.tag_name.present?
end
end
end
diff --git a/lib/gitlab/metrics/boot_time_tracker.rb b/lib/gitlab/metrics/boot_time_tracker.rb
new file mode 100644
index 00000000000..3e7026b8dea
--- /dev/null
+++ b/lib/gitlab/metrics/boot_time_tracker.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ class BootTimeTracker
+ include Singleton
+
+ SUPPORTED_RUNTIMES = [:puma, :sidekiq, :console].freeze
+
+ def startup_time
+ @startup_time || 0
+ end
+
+ def track_boot_time!(logger: Gitlab::AppJsonLogger)
+ return if @startup_time
+
+ runtime = Gitlab::Runtime.safe_identify
+ return unless SUPPORTED_RUNTIMES.include?(runtime)
+
+ @startup_time = Gitlab::Metrics::System.process_runtime_elapsed_seconds
+
+ Gitlab::Metrics.gauge(
+ :gitlab_rails_boot_time_seconds, 'Time elapsed for Rails primary process to finish startup'
+ ).set({}, @startup_time)
+
+ logger.info(message: 'Application boot finished', runtime: runtime.to_s, duration_s: @startup_time)
+ end
+
+ def reset!
+ @startup_time = nil
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/exporter/base_exporter.rb b/lib/gitlab/metrics/exporter/base_exporter.rb
index 190d3d3fd2f..2aea8d655fa 100644
--- a/lib/gitlab/metrics/exporter/base_exporter.rb
+++ b/lib/gitlab/metrics/exporter/base_exporter.rb
@@ -9,8 +9,10 @@ module Gitlab
class BaseExporter < Daemon
attr_reader :server
- attr_accessor :readiness_checks
-
+ # @param settings [Hash] SettingsLogic hash containing the `*_exporter` config
+ # @param log_enabled [Boolean] whether to log HTTP requests
+ # @param log_file [String] path to where the server log should be located
+ # @param gc_requests [Boolean] whether to run a major GC after each scraper request
def initialize(settings, log_enabled:, log_file:, gc_requests: false, **options)
super(**options)
@@ -85,7 +87,7 @@ module Gitlab
end
def readiness_probe
- ::Gitlab::HealthChecks::Probes::Collection.new(*readiness_checks)
+ ::Gitlab::HealthChecks::Probes::Collection.new
end
def liveness_probe
diff --git a/lib/gitlab/metrics/exporter/web_exporter.rb b/lib/gitlab/metrics/exporter/web_exporter.rb
index c05ad8ccf42..9a471c33770 100644
--- a/lib/gitlab/metrics/exporter/web_exporter.rb
+++ b/lib/gitlab/metrics/exporter/web_exporter.rb
@@ -4,64 +4,9 @@ module Gitlab
module Metrics
module Exporter
class WebExporter < BaseExporter
- ExporterCheck = Struct.new(:exporter) do
- def readiness
- Gitlab::HealthChecks::Result.new(
- 'web_exporter', exporter.running)
- end
-
- def available?
- true
- end
- end
-
- RailsMetricsInitializer = Struct.new(:app) do
- def call(env)
- Gitlab::Metrics::RailsSlis.initialize_request_slis_if_needed!
-
- app.call(env)
- end
- end
-
- attr_reader :running
-
# This exporter is always run on master process
def initialize(**options)
super(Settings.monitoring.web_exporter, log_enabled: true, log_file: 'web_exporter.log', **options)
-
- # DEPRECATED:
- # these `readiness_checks` are deprecated
- # as presenting no value in a way how we run
- # application: https://gitlab.com/gitlab-org/gitlab/issues/35343
- self.readiness_checks = [
- WebExporter::ExporterCheck.new(self),
- Gitlab::HealthChecks::PumaCheck
- ]
- end
-
- def mark_as_not_running!
- @running = false
- end
-
- private
-
- def rack_app
- app = super
-
- Rack::Builder.app do
- use RailsMetricsInitializer
- run app
- end
- end
-
- def start_working
- @running = true
- super
- end
-
- def stop_working
- mark_as_not_running!
- super
end
end
end
diff --git a/lib/gitlab/metrics/rails_slis.rb b/lib/gitlab/metrics/rails_slis.rb
index 8c40c0ad441..c4f305dbdc4 100644
--- a/lib/gitlab/metrics/rails_slis.rb
+++ b/lib/gitlab/metrics/rails_slis.rb
@@ -4,7 +4,7 @@ module Gitlab
module Metrics
module RailsSlis
class << self
- def initialize_request_slis_if_needed!
+ def initialize_request_slis!
Gitlab::Metrics::Sli.initialize_sli(:rails_request_apdex, possible_request_labels) unless Gitlab::Metrics::Sli.initialized?(:rails_request_apdex)
Gitlab::Metrics::Sli.initialize_sli(:graphql_query_apdex, possible_graphql_query_labels) unless Gitlab::Metrics::Sli.initialized?(:graphql_query_apdex)
end
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index c143a7f5a1b..d7fe983c553 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -62,6 +62,8 @@ module Gitlab
http_requests_total.get({ method: method, status: status, feature_category: feature_category })
end
end
+
+ Gitlab::Metrics::RailsSlis.initialize_request_slis!
end
def call(env)
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index d71ee671b8d..4a3ef3711a5 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -7,22 +7,20 @@ module Gitlab
DEFAULT_SAMPLING_INTERVAL_SECONDS = 60
GC_REPORT_BUCKETS = [0.01, 0.05, 0.1, 0.2, 0.3, 0.5, 1].freeze
- def initialize(...)
+ def initialize(prefix: nil, **options)
+ @prefix = prefix
+
GC::Profiler.clear
metrics[:process_start_time_seconds].set(labels, Time.now.to_i)
- super(...)
+ super(**options)
end
def metrics
@metrics ||= init_metrics
end
- def with_prefix(prefix, name)
- "ruby_#{prefix}_#{name}".to_sym
- end
-
def to_doc_string(name)
name.to_s.humanize
end
@@ -33,19 +31,19 @@ module Gitlab
def init_metrics
metrics = {
- file_descriptors: ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels),
- process_cpu_seconds_total: ::Gitlab::Metrics.gauge(with_prefix(:process, :cpu_seconds_total), 'Process CPU seconds total'),
- process_max_fds: ::Gitlab::Metrics.gauge(with_prefix(:process, :max_fds), 'Process max fds'),
- process_resident_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :resident_memory_bytes), 'Memory used (RSS)', labels),
- process_unique_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :unique_memory_bytes), 'Memory used (USS)', labels),
- process_proportional_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :proportional_memory_bytes), 'Memory used (PSS)', labels),
- process_start_time_seconds: ::Gitlab::Metrics.gauge(with_prefix(:process, :start_time_seconds), 'Process start time seconds'),
- sampler_duration: ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels),
- gc_duration_seconds: ::Gitlab::Metrics.histogram(with_prefix(:gc, :duration_seconds), 'GC time', labels, GC_REPORT_BUCKETS)
+ file_descriptors: ::Gitlab::Metrics.gauge(metric_name(:file, :descriptors), 'File descriptors used', labels),
+ process_cpu_seconds_total: ::Gitlab::Metrics.gauge(metric_name(:process, :cpu_seconds_total), 'Process CPU seconds total'),
+ process_max_fds: ::Gitlab::Metrics.gauge(metric_name(:process, :max_fds), 'Process max fds'),
+ process_resident_memory_bytes: ::Gitlab::Metrics.gauge(metric_name(:process, :resident_memory_bytes), 'Memory used (RSS)', labels),
+ process_unique_memory_bytes: ::Gitlab::Metrics.gauge(metric_name(:process, :unique_memory_bytes), 'Memory used (USS)', labels),
+ process_proportional_memory_bytes: ::Gitlab::Metrics.gauge(metric_name(:process, :proportional_memory_bytes), 'Memory used (PSS)', labels),
+ process_start_time_seconds: ::Gitlab::Metrics.gauge(metric_name(:process, :start_time_seconds), 'Process start time seconds'),
+ sampler_duration: ::Gitlab::Metrics.counter(metric_name(:sampler, :duration_seconds_total), 'Sampler time', labels),
+ gc_duration_seconds: ::Gitlab::Metrics.histogram(metric_name(:gc, :duration_seconds), 'GC time', labels, GC_REPORT_BUCKETS)
}
GC.stat.keys.each do |key|
- metrics[key] = ::Gitlab::Metrics.gauge(with_prefix(:gc_stat, key), to_doc_string(key), labels)
+ metrics[key] = ::Gitlab::Metrics.gauge(metric_name(:gc_stat, key), to_doc_string(key), labels)
end
metrics
@@ -65,6 +63,12 @@ module Gitlab
private
+ def metric_name(group, metric)
+ name = "ruby_#{group}_#{metric}"
+ name = "#{@prefix}_#{name}" if @prefix.present?
+ name.to_sym
+ end
+
def sample_gc
# Observe all GC samples
sample_gc_reports.each do |report|
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index 9bbcd1e056c..e646846face 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -7,6 +7,9 @@ module Gitlab
# This module relies on the /proc filesystem being available. If /proc is
# not available the methods of this module will be stubbed.
module System
+ extend self
+
+ PROC_STAT_PATH = '/proc/self/stat'
PROC_STATUS_PATH = '/proc/self/status'
PROC_SMAPS_ROLLUP_PATH = '/proc/self/smaps_rollup'
PROC_LIMITS_PATH = '/proc/self/limits'
@@ -17,7 +20,7 @@ module Gitlab
RSS_PATTERN = /VmRSS:\s+(?<value>\d+)/.freeze
MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/.freeze
- def self.summary
+ def summary
proportional_mem = memory_usage_uss_pss
{
version: RUBY_DESCRIPTION,
@@ -32,43 +35,43 @@ module Gitlab
end
# Returns the current process' RSS (resident set size) in bytes.
- def self.memory_usage_rss
+ def memory_usage_rss
sum_matches(PROC_STATUS_PATH, rss: RSS_PATTERN)[:rss].kilobytes
end
# Returns the current process' USS/PSS (unique/proportional set size) in bytes.
- def self.memory_usage_uss_pss
+ def memory_usage_uss_pss
sum_matches(PROC_SMAPS_ROLLUP_PATH, uss: PRIVATE_PAGES_PATTERN, pss: PSS_PATTERN)
.transform_values(&:kilobytes)
end
- def self.file_descriptor_count
+ def file_descriptor_count
Dir.glob(PROC_FD_GLOB).length
end
- def self.max_open_file_descriptors
+ def max_open_file_descriptors
sum_matches(PROC_LIMITS_PATH, max_fds: MAX_OPEN_FILES_PATTERN)[:max_fds]
end
- def self.cpu_time
+ def cpu_time
Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :float_second)
end
# Returns the current real time in a given precision.
#
# Returns the time as a Float for precision = :float_second.
- def self.real_time(precision = :float_second)
+ def real_time(precision = :float_second)
Process.clock_gettime(Process::CLOCK_REALTIME, precision)
end
# Returns the current monotonic clock time as seconds with microseconds precision.
#
# Returns the time as a Float.
- def self.monotonic_time
+ def monotonic_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
end
- def self.thread_cpu_time
+ def thread_cpu_time
# Not all OS kernels are supporting `Process::CLOCK_THREAD_CPUTIME_ID`
# Refer: https://gitlab.com/gitlab-org/gitlab/issues/30567#note_221765627
return unless defined?(Process::CLOCK_THREAD_CPUTIME_ID)
@@ -76,33 +79,67 @@ module Gitlab
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
end
- def self.thread_cpu_duration(start_time)
+ def thread_cpu_duration(start_time)
end_time = thread_cpu_time
return unless start_time && end_time
end_time - start_time
end
+ # Returns the total time the current process has been running in seconds.
+ def process_runtime_elapsed_seconds
+ # Entry 22 (1-indexed) contains the process `starttime`, see:
+ # https://man7.org/linux/man-pages/man5/proc.5.html
+ #
+ # This value is a fixed timestamp in clock ticks.
+ # To obtain an elapsed time in seconds, we divide by the number
+ # of ticks per second and subtract from the system uptime.
+ start_time_ticks = proc_stat_entries[21].to_f
+ clock_ticks_per_second = Etc.sysconf(Etc::SC_CLK_TCK)
+ uptime - (start_time_ticks / clock_ticks_per_second)
+ end
+
+ private
+
# Given a path to a file in /proc and a hash of (metric, pattern) pairs,
# sums up all values found for those patterns under the respective metric.
- def self.sum_matches(proc_file, **patterns)
+ def sum_matches(proc_file, **patterns)
results = patterns.transform_values { 0 }
- begin
- File.foreach(proc_file) do |line|
+ safe_yield_procfile(proc_file) do |io|
+ io.each_line do |line|
patterns.each do |metric, pattern|
match = line.match(pattern)
value = match&.named_captures&.fetch('value', 0)
results[metric] += value.to_i
end
end
- rescue Errno::ENOENT
- # This means the procfile we're reading from did not exist;
- # this is safe to ignore, since we initialize each metric to 0
end
results
end
+
+ def proc_stat_entries
+ safe_yield_procfile(PROC_STAT_PATH) do |io|
+ io.read.split(' ')
+ end || []
+ end
+
+ def safe_yield_procfile(path, &block)
+ File.open(path, &block)
+ rescue Errno::ENOENT
+ # This means the procfile we're reading from did not exist;
+ # most likely we're on Darwin.
+ end
+
+ # Equivalent to reading /proc/uptime on Linux 2.6+.
+ #
+ # Returns 0 if not supported, e.g. on Darwin.
+ def uptime
+ Process.clock_gettime(Process::CLOCK_BOOTTIME)
+ rescue NameError
+ 0
+ end
end
end
end
diff --git a/lib/gitlab/middleware/memory_report.rb b/lib/gitlab/middleware/memory_report.rb
new file mode 100644
index 00000000000..1c6c771009c
--- /dev/null
+++ b/lib/gitlab/middleware/memory_report.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Middleware
+ class MemoryReport
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = ActionDispatch::Request.new(env)
+
+ return @app.call(env) unless rendering_memory_profiler?(request)
+
+ begin
+ require 'memory_profiler'
+
+ report = MemoryProfiler.report do
+ @app.call(env)
+ end
+
+ report = report_to_string(report)
+ headers = { 'Content-Type' => 'text/plain' }
+
+ [200, headers, [report]]
+ rescue StandardError => e
+ ::Gitlab::ErrorTracking.track_exception(e)
+ [500, { 'Content-Type' => 'text/plain' }, ["Could not generate memory report: #{e}"]]
+ end
+ end
+
+ private
+
+ def rendering_memory_profiler?(request)
+ Rails.env.development? && request.params['performance_bar'] == 'memory'
+ end
+
+ def report_to_string(report)
+ io = StringIO.new
+ report.pretty_print(io, detailed_report: true, scale_bytes: true, normalize_paths: true)
+ io.string
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/net_http_adapter.rb b/lib/gitlab/net_http_adapter.rb
new file mode 100644
index 00000000000..2f7557f2bc3
--- /dev/null
+++ b/lib/gitlab/net_http_adapter.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # Webmock overwrites the Net::HTTP#request method with
+ # https://github.com/bblimke/webmock/blob/867f4b290fd133658aa9530cba4ba8b8c52c0d35/lib/webmock/http_lib_adapters/net_http.rb#L74
+ # Net::HTTP#request usually calls Net::HTTP#connect but the Webmock overwrite doesn't.
+ # This makes sure that, in a test environment, the superclass is the Webmock overwrite.
+ parent_class = if defined?(WebMock) && Rails.env.test?
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get('@webMockNetHTTP')
+ else
+ Net::HTTP
+ end
+
+ class NetHttpAdapter < parent_class
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ override :connect
+ def connect
+ result = super
+
+ @socket = Gitlab::BufferedIo.new(@socket.io,
+ read_timeout: @socket.read_timeout,
+ write_timeout: @socket.write_timeout,
+ continue_timeout: @socket.continue_timeout,
+ debug_output: @socket.debug_output)
+
+ result
+ end
+ end
+end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
index 3e14e1789bb..a9ff186c7cb 100644
--- a/lib/gitlab/omniauth_initializer.rb
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -28,6 +28,10 @@ module Gitlab
{ fail_with_empty_uid: true }
when 'google_oauth2'
{ client_options: { connection_opts: { request: { timeout: OAUTH2_TIMEOUT_SECONDS } } } }
+ when 'gitlab'
+ {
+ authorize_params: { gl_auth_type: 'login' }
+ }
else
{}
end
diff --git a/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb b/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb
index 95afd5a8595..58963779c69 100644
--- a/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb
+++ b/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb
@@ -12,6 +12,7 @@ module Gitlab
array_scope_table = Arel::Table.new(ARRAY_SCOPE_CTE_NAME)
@columns = columns.map do |column|
+ column = column.right if column.is_a?(Arel::Nodes::As)
ColumnData.new(column, "array_scope_#{column}", array_scope_table)
end
end
diff --git a/lib/gitlab/pipeline_scope_counts.rb b/lib/gitlab/pipeline_scope_counts.rb
new file mode 100644
index 00000000000..02f4ea33ddf
--- /dev/null
+++ b/lib/gitlab/pipeline_scope_counts.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class PipelineScopeCounts
+ attr_reader :project
+
+ PIPELINES_COUNT_LIMIT = 1000
+
+ def self.declarative_policy_class
+ 'Ci::ProjectPipelinesPolicy'
+ end
+
+ def initialize(current_user, project, params)
+ @current_user = current_user
+ @project = project
+ @params = params
+ end
+
+ def all
+ finder.execute.limit(PIPELINES_COUNT_LIMIT).count
+ end
+
+ def running
+ finder({ scope: "running" }).execute.limit(PIPELINES_COUNT_LIMIT).count
+ end
+
+ def finished
+ finder({ scope: "finished" }).execute.limit(PIPELINES_COUNT_LIMIT).count
+ end
+
+ def pending
+ finder({ scope: "pending" }).execute.limit(PIPELINES_COUNT_LIMIT).count
+ end
+
+ private
+
+ def finder(params = {})
+ ::Ci::PipelinesFinder.new(@project, @current_user, @params.merge(params))
+ end
+ end
+end
diff --git a/lib/gitlab/popen.rb b/lib/gitlab/popen.rb
index 7fa00d0c68c..586b271c4d0 100644
--- a/lib/gitlab/popen.rb
+++ b/lib/gitlab/popen.rb
@@ -10,10 +10,19 @@ module Gitlab
Result = Struct.new(:cmd, :stdout, :stderr, :status, :duration)
# Returns [stdout + stderr, status]
+ # status is either the exit code or the signal that killed the process
def popen(cmd, path = nil, vars = {}, &block)
result = popen_with_detail(cmd, path, vars, &block)
- ["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
+ # Process#waitpid returns Process::Status, which holds a 16-bit value.
+ # The higher-order 8 bits hold the exit() code (`exitstatus`).
+ # The lower-order bits holds whether the process was terminated.
+ # If the process didn't exit normally, `exitstatus` will be `nil`,
+ # but we still want a non-zero code, even if the value is
+ # platform-dependent.
+ status = result.status&.exitstatus || result.status.to_i
+
+ ["#{result.stdout}#{result.stderr}", status]
end
# Returns Result
diff --git a/lib/gitlab/process_memory_cache/helper.rb b/lib/gitlab/process_memory_cache/helper.rb
index ee4b81a9a19..8d436c14b48 100644
--- a/lib/gitlab/process_memory_cache/helper.rb
+++ b/lib/gitlab/process_memory_cache/helper.rb
@@ -35,7 +35,7 @@ module Gitlab
time = Time.current.to_f
cache_backend.write(key, data: data, cached_at: time)
- touch_cache_timestamp(key, time)
+ touch_cache_timestamp(key, time) unless shared_backend.read(key)
data
end
diff --git a/lib/gitlab/project_authorizations.rb b/lib/gitlab/project_authorizations.rb
index 23e380b3cf1..121626ced56 100644
--- a/lib/gitlab/project_authorizations.rb
+++ b/lib/gitlab/project_authorizations.rb
@@ -19,7 +19,7 @@ module Gitlab
relations = [
# The project a user has direct access to.
- user.projects.select_for_project_authorization,
+ user.projects_with_active_memberships.select_for_project_authorization,
# The personal projects of the user.
user.personal_projects.select_as_maintainer_for_project_authorization,
@@ -65,7 +65,7 @@ module Gitlab
group_group_links = GroupGroupLink.arel_table
# Namespaces the user is a member of.
- cte << user.groups
+ cte << user.groups_with_active_memberships
.select([namespaces[:id], members[:access_level]])
.except(:order)
@@ -99,6 +99,7 @@ module Gitlab
.and(members[:source_type].eq('Namespace'))
.and(members[:requested_at].eq(nil))
.and(members[:user_id].eq(user.id))
+ .and(members[:state].eq(::Member::STATE_ACTIVE))
.and(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
Arel::Nodes::OuterJoin.new(members, Arel::Nodes::On.new(cond))
@@ -120,6 +121,7 @@ module Gitlab
.and(members[:source_type].eq('Namespace'))
.and(members[:requested_at].eq(nil))
.and(members[:user_id].eq(user.id))
+ .and(members[:state].eq(::Member::STATE_ACTIVE))
.and(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
Arel::Nodes::InnerJoin.new(members, Arel::Nodes::On.new(cond))
end
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index d53b11fe98c..847f70693f3 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -51,7 +51,7 @@ module Gitlab
ProjectTemplate.new('dotnetcore', '.NET Core', _('A .NET Core console application template, customizable for any .NET Core project'), 'https://gitlab.com/gitlab-org/project-templates/dotnetcore', 'illustrations/logos/dotnet.svg'),
ProjectTemplate.new('android', 'Android', _('A ready-to-go template for use with Android apps'), 'https://gitlab.com/gitlab-org/project-templates/android', 'illustrations/logos/android.svg'),
ProjectTemplate.new('gomicro', 'Go Micro', _('Go Micro is a framework for micro service development'), 'https://gitlab.com/gitlab-org/project-templates/go-micro', 'illustrations/logos/gomicro.svg'),
- ProjectTemplate.new('gatsby', 'Pages/Gatsby', _('Everything you need to create a GitLab Pages site using Gatsby'), 'https://gitlab.com/pages/gatsby'),
+ ProjectTemplate.new('gatsby', 'Pages/Gatsby', _('Everything you need to create a GitLab Pages site using Gatsby'), 'https://gitlab.com/pages/gatsby', 'illustrations/third-party-logos/gatsby.svg'),
ProjectTemplate.new('hugo', 'Pages/Hugo', _('Everything you need to create a GitLab Pages site using Hugo'), 'https://gitlab.com/pages/hugo', 'illustrations/logos/hugo.svg'),
ProjectTemplate.new('jekyll', 'Pages/Jekyll', _('Everything you need to create a GitLab Pages site using Jekyll'), 'https://gitlab.com/pages/jekyll', 'illustrations/logos/jekyll.svg'),
ProjectTemplate.new('plainhtml', 'Pages/Plain HTML', _('Everything you need to create a GitLab Pages site using plain HTML'), 'https://gitlab.com/pages/plain-html'),
diff --git a/lib/gitlab/quick_actions/command_definition.rb b/lib/gitlab/quick_actions/command_definition.rb
index 8ce13db4c03..fcb7bc967ca 100644
--- a/lib/gitlab/quick_actions/command_definition.rb
+++ b/lib/gitlab/quick_actions/command_definition.rb
@@ -3,6 +3,8 @@
module Gitlab
module QuickActions
class CommandDefinition
+ ParseError = Class.new(StandardError)
+
attr_accessor :name, :aliases, :description, :explanation, :execution_message,
:params, :condition_block, :parse_params_block, :action_block, :warning, :icon, :types
@@ -41,7 +43,11 @@ module Gitlab
return unless available?(context)
message = if explanation.respond_to?(:call)
- execute_block(explanation, context, arg)
+ begin
+ execute_block(explanation, context, arg)
+ rescue ParseError => e
+ format(_('Problem with %{name} command: %{message}.'), name: name, message: e.message)
+ end
else
explanation
end
@@ -63,6 +69,8 @@ module Gitlab
return unless available?(context)
execute_block(action_block, context, arg)
+ rescue ParseError
+ # message propagation is handled in `execution_message`.
end
def execute_message(context, arg)
@@ -74,6 +82,8 @@ module Gitlab
else
execution_message
end
+ rescue ParseError => e
+ format _('Could not apply %{name} command. %{message}.'), name: name, message: e.message
end
def to_h(context)
diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb
index 5fd422db722..b44b47eca37 100644
--- a/lib/gitlab/quick_actions/issue_actions.rb
+++ b/lib/gitlab/quick_actions/issue_actions.rb
@@ -287,10 +287,11 @@ module Gitlab
desc _('Add customer relation contacts')
explanation _('Add customer relation contact(s).')
- params 'contact@example.com person@example.org'
+ params '[contact:contact@example.com] [contact:person@example.org]'
types Issue
condition do
- current_user.can?(:set_issue_crm_contacts, quick_action_target)
+ current_user.can?(:set_issue_crm_contacts, quick_action_target) &&
+ CustomerRelations::Contact.exists_for_group?(quick_action_target.project.group)
end
execution_message do
_('One or more contacts were successfully added.')
@@ -301,10 +302,11 @@ module Gitlab
desc _('Remove customer relation contacts')
explanation _('Remove customer relation contact(s).')
- params 'contact@example.com person@example.org'
+ params '[contact:contact@example.com] [contact:person@example.org]'
types Issue
condition do
- current_user.can?(:set_issue_crm_contacts, quick_action_target)
+ current_user.can?(:set_issue_crm_contacts, quick_action_target) &&
+ CustomerRelations::Contact.exists_for_group?(quick_action_target.project.group)
end
execution_message do
_('One or more contacts were successfully removed.')
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index cc2021e14e3..842d4ef482b 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -57,6 +57,11 @@ module Gitlab
access_check.can_push_to_branch?(merge_request.source_branch)
end
command :rebase do
+ unless quick_action_target.permits_force_push?
+ @execution_message[:rebase] = _('This merge request branch is protected from force push.')
+ next
+ end
+
if quick_action_target.cannot_be_merged?
@execution_message[:rebase] = _('This merge request cannot be rebased while there are conflicts.')
next
@@ -184,7 +189,7 @@ module Gitlab
execution_message do |users = nil|
reviewers = reviewers_to_add(users)
if reviewers.blank?
- _("Failed to assign a reviewer because no user was found.")
+ _("Failed to assign a reviewer because no user was specified.")
else
_('Assigned %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users),
reviewer_text: 'reviewer'.pluralize(reviewers.size) }
@@ -249,6 +254,76 @@ module Gitlab
@updates[:reviewer_ids] = []
end
end
+
+ desc do
+ if quick_action_target.allows_multiple_reviewers?
+ _('Request attention from assignee(s) or reviewer(s)')
+ else
+ _('Request attention from assignee or reviewer')
+ end
+ end
+ explanation do |users|
+ _('Request attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
+ end
+ execution_message do |users = nil|
+ if users.blank?
+ _("Failed to request attention because no user was found.")
+ else
+ _('Requested attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
+ end
+ end
+ params do
+ quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
+ end
+ types MergeRequest
+ condition do
+ Feature.enabled?(:mr_attention_requests, project, default_enabled: :yaml) &&
+ current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ end
+ parse_params do |attention_param|
+ extract_users(attention_param)
+ end
+ command :attention do |users|
+ next if users.empty?
+
+ users.each do |user|
+ ::MergeRequests::ToggleAttentionRequestedService.new(project: quick_action_target.project, merge_request: quick_action_target, current_user: current_user, user: user).execute
+ end
+ end
+
+ desc do
+ if quick_action_target.allows_multiple_reviewers?
+ _('Remove attention request(s)')
+ else
+ _('Remove attention request')
+ end
+ end
+ explanation do |users|
+ _('Removes attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
+ end
+ execution_message do |users = nil|
+ if users.blank?
+ _("Failed to remove attention because no user was found.")
+ else
+ _('Removed attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
+ end
+ end
+ params do
+ quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
+ end
+ types MergeRequest
+ condition do
+ Feature.enabled?(:mr_attention_requests, project, default_enabled: :yaml) &&
+ current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ end
+ parse_params do |attention_param|
+ extract_users(attention_param)
+ end
+ command :remove_attention do |users|
+ next if users.empty?
+
+ ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: quick_action_target.project, merge_request: quick_action_target, current_user: current_user, users: users).execute
+ end
end
def reviewer_users_sentence(users)
diff --git a/lib/gitlab/rack_attack/request.rb b/lib/gitlab/rack_attack/request.rb
index 94ae29af3d0..b24afd28dd7 100644
--- a/lib/gitlab/rack_attack/request.rb
+++ b/lib/gitlab/rack_attack/request.rb
@@ -3,6 +3,8 @@
module Gitlab
module RackAttack
module Request
+ include ::Gitlab::Utils::StrongMemoize
+
FILES_PATH_REGEX = %r{^/api/v\d+/projects/[^/]+/repository/files/.+}.freeze
GROUP_PATH_REGEX = %r{^/api/v\d+/groups/[^/]+/?$}.freeze
@@ -26,23 +28,31 @@ module Gitlab
end
def api_request?
- path.start_with?('/api')
+ logical_path.start_with?('/api')
+ end
+
+ def logical_path
+ @logical_path ||= path.delete_prefix(Gitlab.config.gitlab.relative_url_root)
+ end
+
+ def matches?(regex)
+ logical_path.match?(regex)
end
def api_internal_request?
- path =~ %r{^/api/v\d+/internal/}
+ matches?(%r{^/api/v\d+/internal/})
end
def health_check_request?
- path =~ %r{^/-/(health|liveness|readiness|metrics)}
+ matches?(%r{^/-/(health|liveness|readiness|metrics)})
end
def container_registry_event?
- path =~ %r{^/api/v\d+/container_registry_event/}
+ matches?(%r{^/api/v\d+/container_registry_event/})
end
def product_analytics_collector_request?
- path.start_with?('/-/collector/i')
+ logical_path.start_with?('/-/collector/i')
end
def should_be_skipped?
@@ -54,11 +64,7 @@ module Gitlab
end
def protected_path?
- !protected_path_regex.nil?
- end
-
- def protected_path_regex
- path =~ protected_paths_regex
+ matches?(protected_paths_regex)
end
def throttle?(throttle, authenticated:)
@@ -70,6 +76,7 @@ module Gitlab
def throttle_unauthenticated_api?
api_request? &&
!should_be_skipped? &&
+ !frontend_request? &&
!throttle_unauthenticated_packages_api? &&
!throttle_unauthenticated_files_api? &&
!throttle_unauthenticated_deprecated_api? &&
@@ -78,7 +85,7 @@ module Gitlab
end
def throttle_unauthenticated_web?
- web_request? &&
+ (web_request? || frontend_request?) &&
!should_be_skipped? &&
# TODO: Column will be renamed in https://gitlab.com/gitlab-org/gitlab/-/issues/340031
Gitlab::Throttle.settings.throttle_unauthenticated_enabled &&
@@ -87,6 +94,7 @@ module Gitlab
def throttle_authenticated_api?
api_request? &&
+ !frontend_request? &&
!throttle_authenticated_packages_api? &&
!throttle_authenticated_files_api? &&
!throttle_authenticated_deprecated_api? &&
@@ -94,7 +102,7 @@ module Gitlab
end
def throttle_authenticated_web?
- web_request? &&
+ (web_request? || frontend_request?) &&
!throttle_authenticated_git_lfs? &&
Gitlab::Throttle.settings.throttle_authenticated_web_enabled
end
@@ -178,15 +186,24 @@ module Gitlab
end
def packages_api_path?
- path =~ ::Gitlab::Regex::Packages::API_PATH_REGEX
+ matches?(::Gitlab::Regex::Packages::API_PATH_REGEX)
end
def git_lfs_path?
- path =~ Gitlab::PathRegex.repository_git_lfs_route_regex
+ matches?(::Gitlab::PathRegex.repository_git_lfs_route_regex)
end
def files_api_path?
- path =~ FILES_PATH_REGEX
+ matches?(FILES_PATH_REGEX)
+ end
+
+ def frontend_request?
+ strong_memoize(:frontend_request) do
+ next false unless env.include?('HTTP_X_CSRF_TOKEN') && session.include?(:_csrf_token)
+
+ # CSRF tokens are not verified for GET/HEAD requests, so we pretend that we always have a POST request.
+ Gitlab::RequestForgeryProtection.verified?(env.merge('REQUEST_METHOD' => 'POST'))
+ end
end
def deprecated_api_request?
@@ -195,7 +212,7 @@ module Gitlab
with_projects = params['with_projects']
with_projects = true if with_projects.blank?
- path =~ GROUP_PATH_REGEX && Gitlab::Utils.to_boolean(with_projects)
+ matches?(GROUP_PATH_REGEX) && Gitlab::Utils.to_boolean(with_projects)
end
end
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index b07b9c79858..a6491d23bf5 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -435,10 +435,6 @@ module Gitlab
@utc_date_regex ||= /\A[0-9]{4}-[0-9]{2}-[0-9]{2}\z/.freeze
end
- def merge_request_wip
- /(?i)(\[WIP\]\s*|WIP:\s*|\AWIP\z)/
- end
-
def merge_request_draft
/\A(?i)(\[draft\]|\(draft\)|draft:)/
end
diff --git a/lib/gitlab/runtime.rb b/lib/gitlab/runtime.rb
index 5fbbfd90be1..574e05658bc 100644
--- a/lib/gitlab/runtime.rb
+++ b/lib/gitlab/runtime.rb
@@ -31,6 +31,12 @@ module Gitlab
end
end
+ def safe_identify
+ identify
+ rescue UnknownProcessError, AmbiguousProcessError
+ nil
+ end
+
def puma?
!!defined?(::Puma)
end
diff --git a/lib/gitlab/saas.rb b/lib/gitlab/saas.rb
index 577e33fd700..0a4f2ba64a8 100644
--- a/lib/gitlab/saas.rb
+++ b/lib/gitlab/saas.rb
@@ -18,7 +18,7 @@ module Gitlab
end
def self.subdomain_regex
- %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}.freeze
+ %r{\Ahttps://[a-z0-9-]+\.gitlab\.com\z}.freeze
end
def self.dev_url
diff --git a/lib/gitlab/search/found_blob.rb b/lib/gitlab/search/found_blob.rb
index 183e582925d..60d3e360984 100644
--- a/lib/gitlab/search/found_blob.rb
+++ b/lib/gitlab/search/found_blob.rb
@@ -80,6 +80,10 @@ module Gitlab
super(presenter_class: BlobPresenter)
end
+ def binary?
+ false
+ end
+
def fetch_blob
path = [ref, blob_path]
missing_blob = { binary_path: blob_path }
diff --git a/lib/gitlab/security/scan_configuration.rb b/lib/gitlab/security/scan_configuration.rb
index eaccbb3be7e..381adda7991 100644
--- a/lib/gitlab/security/scan_configuration.rb
+++ b/lib/gitlab/security/scan_configuration.rb
@@ -18,27 +18,25 @@ module Gitlab
# SAST and Secret Detection are always available, but this isn't
# reflected by our license model yet.
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/333113
- %i[sast secret_detection].include?(type)
+ %i[sast sast_iac secret_detection].include?(type)
+ end
+
+ def can_enable_by_merge_request?
+ scans_configurable_in_merge_request.include?(type)
end
def configured?
configured
end
- def configuration_path
- configurable_scans[type]
- end
+ def configuration_path; end
private
attr_reader :project, :configured
- def configurable_scans
- strong_memoize(:configurable_scans) do
- {
- sast: project_security_configuration_sast_path(project)
- }
- end
+ def scans_configurable_in_merge_request
+ %i[sast sast_iac secret_detection]
end
end
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 3a31f651714..bc0071f6333 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -113,7 +113,7 @@ module Gitlab
# sidekiq jobs, and concurrency will be low anyway in test.
git: {
catfile_cache_size: 5,
- bin_path: File.expand_path(File.join(gitaly_dir, '_build', 'deps', 'git', 'install', 'bin', 'git'))
+ use_bundled_binaries: true
},
prometheus_listen_addr: prometheus_listen_addr
}.compact
@@ -130,7 +130,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] = File.join(gitaly_dir, '_build', 'bin') # binaries by default are in `_build/bin`
+ config[:bin_dir] = File.expand_path(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 }
diff --git a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
index 6186c9ad1f4..3de6c8df8aa 100644
--- a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
+++ b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
@@ -29,7 +29,7 @@ module Gitlab
# The worker classes aren't constants here, because that would force
# Application Settings to be loaded earlier causing failures loading
# the environment in rake tasks
- EXEMPT_WORKER_NAMES = ["BackgroundMigrationWorker", "Database::BatchedBackgroundMigrationWorker"].to_set
+ EXEMPT_WORKER_NAMES = %w[BackgroundMigrationWorker BackgroundMigration::CiDatabaseWorker Database::BatchedBackgroundMigrationWorker].to_set
JOB_STATUS_KEY = 'size_limiter'
class << self
diff --git a/lib/gitlab/sidekiq_queue.rb b/lib/gitlab/sidekiq_queue.rb
index 67a9d8120d8..e22f09b4976 100644
--- a/lib/gitlab/sidekiq_queue.rb
+++ b/lib/gitlab/sidekiq_queue.rb
@@ -8,7 +8,7 @@ module Gitlab
InvalidQueueError = Class.new(StandardError)
WORKER_KEY = 'worker_class'
- ALLOWED_KEYS = Gitlab::ApplicationContext::KNOWN_KEYS + [WORKER_KEY]
+ ALLOWED_KEYS = Gitlab::ApplicationContext.known_keys.map(&:to_s) + [WORKER_KEY]
attr_reader :queue_name
@@ -53,7 +53,7 @@ module Gitlab
private
def transform_key(key)
- if Gitlab::ApplicationContext::KNOWN_KEYS.include?(key)
+ if Gitlab::ApplicationContext.known_keys.include?(key.to_sym)
"meta.#{key}"
elsif key == WORKER_KEY
'class'
diff --git a/lib/gitlab/ssh_public_key.rb b/lib/gitlab/ssh_public_key.rb
index 314cc5e2db6..8a2f3bbe0ee 100644
--- a/lib/gitlab/ssh_public_key.rb
+++ b/lib/gitlab/ssh_public_key.rb
@@ -7,10 +7,12 @@ module Gitlab
# See https://man.openbsd.org/sshd#AUTHORIZED_KEYS_FILE_FORMAT for the list of
# supported algorithms.
TECHNOLOGIES = [
- Technology.new(:rsa, OpenSSL::PKey::RSA, [1024, 2048, 3072, 4096], %w(ssh-rsa)),
- Technology.new(:dsa, OpenSSL::PKey::DSA, [1024, 2048, 3072], %w(ssh-dss)),
- Technology.new(:ecdsa, OpenSSL::PKey::EC, [256, 384, 521], %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)),
- Technology.new(:ed25519, Net::SSH::Authentication::ED25519::PubKey, [256], %w(ssh-ed25519))
+ Technology.new(:rsa, SSHData::PublicKey::RSA, [1024, 2048, 3072, 4096], %w(ssh-rsa)),
+ Technology.new(:dsa, SSHData::PublicKey::DSA, [1024, 2048, 3072], %w(ssh-dss)),
+ Technology.new(:ecdsa, SSHData::PublicKey::ECDSA, [256, 384, 521], %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)),
+ Technology.new(:ed25519, SSHData::PublicKey::ED25519, [256], %w(ssh-ed25519)),
+ Technology.new(:ecdsa_sk, SSHData::PublicKey::SKECDSA, [256], %w(sk-ecdsa-sha2-nistp256@openssh.com)),
+ Technology.new(:ed25519_sk, SSHData::PublicKey::SKED25519, [256], %w(sk-ssh-ed25519@openssh.com))
].freeze
def self.technology(name)
@@ -18,7 +20,7 @@ module Gitlab
end
def self.technology_for_key(key)
- TECHNOLOGIES.find { |tech| key.is_a?(tech.key_class) }
+ TECHNOLOGIES.find { |tech| key.instance_of?(tech.key_class) }
end
def self.supported_types
@@ -45,7 +47,7 @@ module Gitlab
parts.each_with_object(+"#{ssh_type} ").with_index do |(part, content), index|
content << part
- if Gitlab::SSHPublicKey.new(content).valid?
+ if self.new(content).valid?
break [content, parts[index + 1]].compact.join(' ') # Add the comment part if present
elsif parts.size == index + 1 # return original content if we've reached the last element
break key_content
@@ -55,41 +57,53 @@ module Gitlab
attr_reader :key_text, :key
- # Unqualified MD5 fingerprint for compatibility
- delegate :fingerprint, to: :key, allow_nil: true
-
def initialize(key_text)
@key_text = key_text
+ # We need to strip options to parse key with options or in known_hosts
+ # format. See https://man.openbsd.org/sshd#AUTHORIZED_KEYS_FILE_FORMAT
+ # and https://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT
+ key_text_without_options = @key_text.to_s.match(/(\A|\s)(#{self.class.supported_algorithms.join('|')}).*/).to_s
+
@key =
begin
- Net::SSH::KeyFactory.load_data_public_key(key_text)
- rescue StandardError, NotImplementedError
+ SSHData::PublicKey.parse_openssh(key_text_without_options)
+ rescue SSHData::DecodeError
end
end
def valid?
- SSHKey.valid_ssh_public_key?(key_text)
+ key.present?
end
def type
- technology.name if key.present?
+ technology.name if valid?
+ end
+
+ def fingerprint
+ key.fingerprint(md5: true) if valid?
+ end
+
+ def fingerprint_sha256
+ 'SHA256:' + key.fingerprint(md5: false) if valid?
end
def bits
- return if key.blank?
+ return unless valid?
case type
when :rsa
- key.n&.num_bits
+ key.n.num_bits
when :dsa
- key.p&.num_bits
+ key.p.num_bits
when :ecdsa
- key.group.order&.num_bits
+ key.openssl.group.order.num_bits
when :ed25519
256
- else
- raise "Unsupported key type: #{type}"
+ when :ecdsa_sk
+ 256
+ when :ed25519_sk
+ 256
end
end
@@ -97,7 +111,11 @@ module Gitlab
def technology
@technology ||=
- self.class.technology_for_key(key) || raise("Unsupported key type: #{key.class}")
+ self.class.technology_for_key(key) || raise_unsupported_key_type_error
+ end
+
+ def raise_unsupported_key_type_error
+ raise("Unsupported key type: #{key.class}")
end
end
end
diff --git a/lib/gitlab/subscription_portal.rb b/lib/gitlab/subscription_portal.rb
index d987247fdc4..b8d124541f9 100644
--- a/lib/gitlab/subscription_portal.rb
+++ b/lib/gitlab/subscription_portal.rb
@@ -42,10 +42,6 @@ module Gitlab
"#{self.subscriptions_url}/subscriptions"
end
- def self.subscriptions_plans_url
- Gitlab::Saas.about_pricing_url
- end
-
def self.subscriptions_gitlab_plans_url
"#{self.subscriptions_url}/gitlab_plans"
end
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index 35f45c8809f..323f59d3373 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -5,9 +5,7 @@ module Gitlab
class GitlabCiYmlTemplate < BaseTemplate
BASE_EXCLUDED_PATTERNS = [%r{\.latest\.}].freeze
- TEMPLATES_WITH_LATEST_VERSION = {
- 'Jobs/Build' => true
- }.freeze
+ TEMPLATES_WITH_LATEST_VERSION = {}.freeze
def description
"# This file is a template, and might need editing before it works on your project."
diff --git a/lib/gitlab/untrusted_regexp/ruby_syntax.rb b/lib/gitlab/untrusted_regexp/ruby_syntax.rb
index 010214cf295..5176a6f6273 100644
--- a/lib/gitlab/untrusted_regexp/ruby_syntax.rb
+++ b/lib/gitlab/untrusted_regexp/ruby_syntax.rb
@@ -36,11 +36,11 @@ module Gitlab
create_untrusted_regexp(matches[:regexp], matches[:flags])
rescue RegexpError
raise unless fallback &&
- Feature.enabled?(:allow_unsafe_ruby_regexp, default_enabled: false)
+ Feature.enabled?(:allow_unsafe_ruby_regexp, default_enabled: :yaml)
if Feature.enabled?(:ci_unsafe_regexp_logger, type: :ops, default_enabled: :yaml)
Gitlab::AppJsonLogger.info(
- class: self.class.name,
+ class: self.name,
regexp: pattern.to_s,
fabricated: 'unsafe ruby regexp',
project_id: project&.id,
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
index d1a7bb65cc3..626bd3d4ad4 100644
--- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -7,7 +7,7 @@ module Gitlab
class Generator < ::Gitlab::UsageData
class << self
def generate(key_path)
- uncached_data.deep_stringify_keys.dig(*key_path.split('.'))
+ data.deep_stringify_keys.dig(*key_path.split('.'))
end
def add_metric(metric, time_frame: 'none', options: {})
diff --git a/lib/gitlab/usage/service_ping_report.rb b/lib/gitlab/usage/service_ping_report.rb
new file mode 100644
index 00000000000..d9e30c46498
--- /dev/null
+++ b/lib/gitlab/usage/service_ping_report.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ class ServicePingReport
+ class << self
+ def for(output:, cached: false)
+ case output.to_sym
+ when :all_metrics_values
+ all_metrics_values(cached)
+ when :metrics_queries
+ metrics_queries
+ when :non_sql_metrics_values
+ non_sql_metrics_values
+ end
+ end
+
+ private
+
+ def all_metrics_values(cached)
+ Rails.cache.fetch('usage_data', force: !cached, expires_in: 2.weeks) do
+ Gitlab::UsageData.data
+ end
+ end
+
+ def metrics_queries
+ Gitlab::UsageDataQueries.data
+ end
+
+ def non_sql_metrics_values
+ Gitlab::UsageDataNonSqlMetrics.data
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index adf920d8b52..e66a565246b 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -41,13 +41,7 @@ module Gitlab
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
- uncached_data
- end
- end
-
- def uncached_data
+ def data
clear_memoized
with_finished_at(:recording_ce_finished_at) do
@@ -55,10 +49,6 @@ module Gitlab
end
end
- def to_json(force_refresh: false)
- data(force_refresh: force_refresh).to_json
- end
-
def license_usage_data
{
recorded_at: recorded_at,
@@ -131,7 +121,6 @@ module Gitlab
issues_created_manually_from_alerts: issues_created_manually_from_alerts,
incident_issues: count(::Issue.incident, start: minimum_id(Issue), finish: maximum_id(Issue)),
alert_bot_incident_issues: count(::Issue.authored(::User.alert_bot), start: minimum_id(Issue), finish: maximum_id(Issue)),
- incident_labeled_issues: count(::Issue.with_label_attributes(::IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES), start: minimum_id(Issue), finish: maximum_id(Issue)),
keys: count(Key),
label_lists: count(List.label),
lfs_objects: count(LfsObject),
diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb
index 796cbfdb3d6..cecc24a38d5 100644
--- a/lib/gitlab/usage_data_counters.rb
+++ b/lib/gitlab/usage_data_counters.rb
@@ -39,3 +39,5 @@ module Gitlab
end
end
end
+
+Gitlab::UsageDataCounters.prepend_mod_with('Gitlab::UsageDataCounters')
diff --git a/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter.rb
new file mode 100644
index 00000000000..f3d5be5e28f
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module JetBrainsPluginActivityUniqueCounter
+ JETBRAINS_API_REQUEST_ACTION = 'i_code_review_user_jetbrains_api_request'
+ JETBRAINS_USER_AGENT_REGEX = /\Agitlab-jetbrains-plugin/.freeze
+
+ class << self
+ def track_api_request_when_trackable(user_agent:, user:)
+ user_agent&.match?(JETBRAINS_USER_AGENT_REGEX) && track_unique_action_by_user(JETBRAINS_API_REQUEST_ACTION, user)
+ end
+
+ private
+
+ def track_unique_action_by_user(action, user)
+ return unless user
+
+ track_unique_action(action, user.id)
+ end
+
+ def track_unique_action(action, value)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(action, value)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index 55ed9a42512..a39fa7aca4f 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -83,10 +83,6 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_security_sast_iac_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- name: p_ci_templates_security_dast_runner_validation
category: ci_templates
redis_slot: ci_templates
@@ -123,10 +119,6 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_security_dast_api_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- name: p_ci_templates_security_container_scanning
category: ci_templates
redis_slot: ci_templates
@@ -139,6 +131,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_dast_api_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_api_fuzzing
category: ci_templates
redis_slot: ci_templates
@@ -147,10 +143,18 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_cluster_image_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_qualys_iac_security
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_ios_fastlane
category: ci_templates
redis_slot: ci_templates
@@ -199,6 +203,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_kaniko
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_managed_cluster_applications
category: ci_templates
redis_slot: ci_templates
@@ -279,11 +287,11 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_jobs_sast_iac_latest
+- name: p_ci_templates_jobs_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_jobs_secret_detection
+- name: p_ci_templates_jobs_license_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -319,6 +327,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_jobs_dependency_scanning
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_jobs_deploy_latest
category: ci_templates
redis_slot: ci_templates
@@ -335,6 +347,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_jobs_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_terraform_latest
category: ci_templates
redis_slot: ci_templates
@@ -463,11 +479,11 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_sast_iac_latest
+- name: p_ci_templates_implicit_jobs_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_secret_detection
+- name: p_ci_templates_implicit_jobs_license_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -503,6 +519,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_jobs_dependency_scanning
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_jobs_deploy_latest
category: ci_templates
redis_slot: ci_templates
@@ -519,11 +539,11 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_sast
+- name: p_ci_templates_implicit_jobs_sast_iac_latest
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_sast_iac_latest
+- name: p_ci_templates_implicit_security_sast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -563,10 +583,6 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_api_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- name: p_ci_templates_implicit_security_container_scanning
category: ci_templates
redis_slot: ci_templates
@@ -579,6 +595,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_security_dast_api_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_security_api_fuzzing
category: ci_templates
redis_slot: ci_templates
@@ -587,11 +607,11 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_cluster_image_scanning
+- name: p_ci_templates_implicit_security_sast_iac_latest
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_kaniko
+- name: p_ci_templates_implicit_security_cluster_image_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
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 d4bc060abf9..42c51ec3921 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
@@ -127,6 +127,11 @@
redis_slot: code_review
category: code_review
aggregation: weekly
+- name: i_code_review_user_jetbrains_api_request
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_jetbrains_api_request
- name: i_code_review_user_create_mr_from_issue
redis_slot: code_review
category: code_review
@@ -236,7 +241,7 @@
redis_slot: code_review
category: code_review
aggregation: weekly
- feature_flag: diff_searching_usage_data
+ feature_flag: usage_data_diff_searches
- name: i_code_review_total_suggestions_applied
redis_slot: code_review
category: code_review
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index fc610f1e2d6..96755db8439 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -382,4 +382,8 @@
category: geo
redis_slot: geo
aggregation: daily
- feature_flag: track_geo_proxy_events
+# Growth
+- name: users_clicking_registration_features_offer
+ category: growth
+ redis_slot: users
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
index 44f6b42d584..49891080b03 100644
--- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml
+++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
@@ -295,3 +295,11 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
+- name: i_quickactions_attention
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+- name: i_quickactions_remove_attention
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/web_ide_counter.rb b/lib/gitlab/usage_data_counters/web_ide_counter.rb
index 9f2f4ac3971..f2753c8f215 100644
--- a/lib/gitlab/usage_data_counters/web_ide_counter.rb
+++ b/lib/gitlab/usage_data_counters/web_ide_counter.rb
@@ -3,7 +3,7 @@
module Gitlab
module UsageDataCounters
class WebIdeCounter < BaseCounter
- KNOWN_EVENTS = %w[commits views merge_requests previews terminals pipelines].freeze
+ KNOWN_EVENTS = %w[commits views merge_requests previews previews_success terminals pipelines].freeze
PREFIX = 'web_ide'
class << self
@@ -33,6 +33,12 @@ module Gitlab
count('previews')
end
+ def increment_previews_success_count
+ return unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
+
+ count('previews_success')
+ end
+
private
def redis_key(event)
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index 96cff024371..608545baf74 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -203,6 +203,13 @@ module Gitlab
rescue Addressable::URI::InvalidURIError, TypeError
end
+ def add_url_parameters(url, params)
+ uri = parse_url(url.to_s)
+ uri.query_values = uri.query_values.to_h.merge(params.to_h.stringify_keys)
+ uri.query_values = nil if uri.query_values.empty?
+ uri.to_s
+ end
+
def removes_sensitive_data_from_url(uri_string)
uri = parse_url(uri_string)
diff --git a/lib/gitlab/web_ide/config/entry/terminal.rb b/lib/gitlab/web_ide/config/entry/terminal.rb
index 3da2c3b2ced..b2f0e0285eb 100644
--- a/lib/gitlab/web_ide/config/entry/terminal.rb
+++ b/lib/gitlab/web_ide/config/entry/terminal.rb
@@ -28,7 +28,7 @@ module Gitlab
end
end
- entry :before_script, ::Gitlab::Ci::Config::Entry::Script,
+ entry :before_script, ::Gitlab::Ci::Config::Entry::Commands,
description: 'Global before script overridden in this job.'
entry :script, ::Gitlab::Ci::Config::Entry::Commands,
diff --git a/lib/gitlab_edition.rb b/lib/gitlab_edition.rb
index 6eb6b52c357..02006148a34 100644
--- a/lib/gitlab_edition.rb
+++ b/lib/gitlab_edition.rb
@@ -18,7 +18,11 @@ module GitlabEdition
end
def self.ee?
- @is_ee ||=
+ # To reduce dependencies in QA image we are not using
+ # `Gitlab::Utils::StrongMemoize` but reimplementing its functionality.
+ return @is_ee if defined?(@is_ee)
+
+ @is_ee =
# We use this method when the Rails environment is not loaded. This
# means that checking the presence of the License class could result in
# this method returning `false`, even for an EE installation.
@@ -34,7 +38,9 @@ module GitlabEdition
end
def self.jh?
- @is_jh ||=
+ return @is_jh if defined?(@is_jh)
+
+ @is_jh =
ee? &&
root.join('jh').exist? &&
!%w[true 1].include?(ENV['EE_ONLY'].to_s)
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index 9bd2309d2b7..43a2480d5b7 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -7,11 +7,12 @@ require 'google/apis/container_v1beta1'
require 'google/apis/cloudbilling_v1'
require 'google/apis/cloudresourcemanager_v1'
require 'google/apis/iam_v1'
+require 'google/apis/serviceusage_v1'
module GoogleApi
module CloudPlatform
class Client < GoogleApi::Auth
- SCOPE = 'https://www.googleapis.com/auth/cloud-platform'
+ SCOPE = 'https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/service.management'
LEAST_TOKEN_LIFE_TIME = 10.minutes
CLUSTER_MASTER_AUTH_USERNAME = 'admin'
CLUSTER_IPV4_CIDR_BLOCK = '/16'
@@ -20,6 +21,7 @@ module GoogleApi
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
].freeze
+ ROLES_LIST = %w[roles/iam.serviceAccountUser roles/artifactregistry.admin roles/cloudbuild.builds.builder roles/run.admin roles/storage.admin roles/cloudsql.admin roles/browser].freeze
class << self
def session_key_for_token
@@ -88,11 +90,8 @@ module GoogleApi
def list_projects
result = []
- service = Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService.new
- service.authorization = access_token
-
- response = service.fetch_all(items: :projects) do |token|
- service.list_projects
+ response = cloud_resource_manager_service.fetch_all(items: :projects) do |token|
+ cloud_resource_manager_service.list_projects
end
# Google API results are paged by default, so we need to iterate through
@@ -130,8 +129,32 @@ module GoogleApi
service.create_service_account_key(name, request_body)
end
+ def grant_service_account_roles(gcp_project_id, email)
+ body = policy_request_body(gcp_project_id, email)
+ cloud_resource_manager_service.set_project_iam_policy(gcp_project_id, body)
+ end
+
+ def enable_cloud_run(gcp_project_id)
+ enable_service(gcp_project_id, 'run.googleapis.com')
+ end
+
+ def enable_artifacts_registry(gcp_project_id)
+ enable_service(gcp_project_id, 'artifactregistry.googleapis.com')
+ end
+
+ def enable_cloud_build(gcp_project_id)
+ enable_service(gcp_project_id, 'cloudbuild.googleapis.com')
+ end
+
private
+ def enable_service(gcp_project_id, service_name)
+ name = "projects/#{gcp_project_id}/services/#{service_name}"
+ service = Google::Apis::ServiceusageV1::ServiceUsageService.new
+ service.authorization = access_token
+ service.enable_service(name)
+ end
+
def make_cluster_options(cluster_name, cluster_size, machine_type, legacy_abac, enable_addons)
{
cluster: {
@@ -173,6 +196,23 @@ module GoogleApi
options.header = { 'User-Agent': "GitLab/#{Gitlab::VERSION.match('(\d+\.\d+)').captures.first} (GPN:GitLab;)" }
end
end
+
+ def policy_request_body(gcp_project_id, email)
+ policy = cloud_resource_manager_service.get_project_iam_policy(gcp_project_id)
+ policy.bindings = policy.bindings + additional_policy_bindings("serviceAccount:#{email}")
+
+ Google::Apis::CloudresourcemanagerV1::SetIamPolicyRequest.new(policy: policy)
+ end
+
+ def additional_policy_bindings(member)
+ ROLES_LIST.map do |role|
+ Google::Apis::CloudresourcemanagerV1::Binding.new(role: role, members: [member])
+ end
+ end
+
+ def cloud_resource_manager_service
+ @gpc_service ||= Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService.new.tap { |s| s. authorization = access_token }
+ end
end
end
end
diff --git a/lib/learn_gitlab/project.rb b/lib/learn_gitlab/project.rb
index 599f9940e53..64f91dcf1a8 100644
--- a/lib/learn_gitlab/project.rb
+++ b/lib/learn_gitlab/project.rb
@@ -3,6 +3,7 @@
module LearnGitlab
class Project
PROJECT_NAME = 'Learn GitLab'
+ PROJECT_NAME_ULTIMATE_TRIAL = 'Learn GitLab - Ultimate trial'
BOARD_NAME = 'GitLab onboarding'
LABEL_NAME = 'Novice'
@@ -15,7 +16,7 @@ module LearnGitlab
end
def project
- @project ||= current_user.projects.find_by_name(PROJECT_NAME)
+ @project ||= current_user.projects.find_by_name([PROJECT_NAME, PROJECT_NAME_ULTIMATE_TRIAL])
end
def board
diff --git a/lib/security/ci_configuration/base_build_action.rb b/lib/security/ci_configuration/base_build_action.rb
index 880bfa6d61d..6012067fb53 100644
--- a/lib/security/ci_configuration/base_build_action.rb
+++ b/lib/security/ci_configuration/base_build_action.rb
@@ -42,6 +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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
YAML
diff --git a/lib/security/ci_configuration/container_scanning_build_action.rb b/lib/security/ci_configuration/container_scanning_build_action.rb
new file mode 100644
index 00000000000..82f9f7d0320
--- /dev/null
+++ b/lib/security/ci_configuration/container_scanning_build_action.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class ContainerScanningBuildAction < BaseBuildAction
+ private
+
+ def update_existing_content!
+ @existing_gitlab_ci_content['include'] = generate_includes
+ end
+
+ def template
+ return 'Auto-DevOps.gitlab-ci.yml' if @auto_devops_enabled
+
+ 'Security/Container-Scanning.gitlab-ci.yml'
+ end
+
+ def comment
+ <<~YAML
+ #{super}
+ # container_scanning:
+ # variables:
+ # DOCKER_IMAGE: ...
+ # DOCKER_USER: ...
+ # DOCKER_PASSWORD: ...
+ YAML
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/concerns/work_item_hierarchy.rb b/lib/sidebars/concerns/work_item_hierarchy.rb
new file mode 100644
index 00000000000..a4153bb5120
--- /dev/null
+++ b/lib/sidebars/concerns/work_item_hierarchy.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# This module has the necessary methods to render
+# work items hierarchy menu
+module Sidebars
+ module Concerns
+ module WorkItemHierarchy
+ def hierarchy_menu_item(container, url, path)
+ unless show_hierarachy_menu_item?(container)
+ return ::Sidebars::NilMenuItem.new(item_id: :hierarchy)
+ end
+
+ ::Sidebars::MenuItem.new(
+ title: _('Planning hierarchy'),
+ link: url,
+ active_routes: { path: path },
+ item_id: :hierarchy
+ )
+ end
+
+ def show_hierarachy_menu_item?(container)
+ can?(context.current_user, :read_planning_hierarchy, container)
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/projects/menus/ci_cd_menu.rb b/lib/sidebars/projects/menus/ci_cd_menu.rb
index 67e4209c382..5df99bb9d84 100644
--- a/lib/sidebars/projects/menus/ci_cd_menu.rb
+++ b/lib/sidebars/projects/menus/ci_cd_menu.rb
@@ -68,9 +68,13 @@ module Sidebars
return ::Sidebars::NilMenuItem.new(item_id: :pipelines_editor)
end
+ params = {
+ branch_name: context.current_ref || context.project.default_branch
+ }
+
::Sidebars::MenuItem.new(
title: s_('Pipelines|Editor'),
- link: project_ci_pipeline_editor_path(context.project),
+ link: project_ci_pipeline_editor_path(context.project, params),
active_routes: { path: 'projects/ci/pipeline_editor#show' },
item_id: :pipelines_editor
)
diff --git a/lib/sidebars/projects/menus/project_information_menu.rb b/lib/sidebars/projects/menus/project_information_menu.rb
index 44b94ee3522..4056d50d324 100644
--- a/lib/sidebars/projects/menus/project_information_menu.rb
+++ b/lib/sidebars/projects/menus/project_information_menu.rb
@@ -4,10 +4,13 @@ module Sidebars
module Projects
module Menus
class ProjectInformationMenu < ::Sidebars::Menu
+ include ::Sidebars::Concerns::WorkItemHierarchy
+
override :configure_menu_items
def configure_menu_items
add_item(activity_menu_item)
add_item(labels_menu_item)
+ add_item(hierarchy_menu_item(context.project, project_planning_hierarchy_path(context.project), 'projects#planning_hierarchy'))
add_item(members_menu_item)
true
diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb
deleted file mode 100644
index d0b64b8bfeb..00000000000
--- a/lib/system_check/app/git_config_check.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module SystemCheck
- module App
- class GitConfigCheck < SystemCheck::BaseCheck
- OPTIONS = {
- 'core.autocrlf' => 'input'
- }.freeze
-
- set_name 'Git configured correctly?'
-
- def check?
- correct_options = OPTIONS.map do |name, value|
- run_command(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value
- end
-
- correct_options.all?
- end
-
- # Tries to configure git itself
- #
- # Returns true if all subcommands were successful (according to their exit code)
- # Returns false if any or all subcommands failed.
- def repair!
- return false unless gitlab_user?
-
- command_success = OPTIONS.map do |name, value|
- system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
- end
-
- command_success.all?
- end
-
- def show_error
- try_fixing_it(
- sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{OPTIONS['core.autocrlf']}\"")
- )
- for_more_information(
- see_installation_guide_section('GitLab')
- )
- end
- end
- end
-end
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
deleted file mode 100644
index 6512b142969..00000000000
--- a/lib/system_check/app/git_version_check.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module SystemCheck
- module App
- class GitVersionCheck < SystemCheck::BaseCheck
- set_name -> { "Git version >= #{self.required_version} ?" }
- set_check_pass -> { "yes (#{self.current_version})" }
-
- def self.required_version
- @required_version ||= Gitlab::VersionInfo.parse('2.33.0')
- end
-
- def self.current_version
- @current_version ||= Gitlab::VersionInfo.parse(Gitlab::TaskHelpers.run_command(%W(#{Gitlab.config.git.bin_path} --version)))
- end
-
- def check?
- self.class.current_version.valid? && self.class.required_version <= self.class.current_version
- end
-
- def show_error
- $stdout.puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
-
- try_fixing_it(
- "Update your git to a version >= #{self.class.required_version} from #{self.class.current_version}"
- )
- fix_and_rerun
- end
- end
- end
-end
diff --git a/lib/system_check/orphans/repository_check.rb b/lib/system_check/orphans/repository_check.rb
index 33020417e95..8f15872de22 100644
--- a/lib/system_check/orphans/repository_check.rb
+++ b/lib/system_check/orphans/repository_check.rb
@@ -57,8 +57,8 @@ module SystemCheck
WHERE (p.repository_storage LIKE ?)
"
- query = ActiveRecord::Base.send(:sanitize_sql_array, [sql, storage_name]) # rubocop:disable GitlabSecurity/PublicSend
- ActiveRecord::Base.connection.select_all(query).rows.try(:flatten!) || []
+ query = ::Project.sanitize_sql_array([sql, storage_name])
+ ::Project.connection.select_all(query).rows.try(:flatten!) || []
end
def fetch_disk_namespaces(storage_path)
diff --git a/lib/system_check/rake_task/app_task.rb b/lib/system_check/rake_task/app_task.rb
index 892417d67ec..1eb7a35b40a 100644
--- a/lib/system_check/rake_task/app_task.rb
+++ b/lib/system_check/rake_task/app_task.rb
@@ -12,7 +12,6 @@ module SystemCheck
def self.checks
[
- SystemCheck::App::GitConfigCheck,
SystemCheck::App::DatabaseConfigExistsCheck,
SystemCheck::App::MigrationsAreUpCheck,
SystemCheck::App::OrphanedGroupMembersCheck,
@@ -28,7 +27,6 @@ module SystemCheck
SystemCheck::App::ProjectsHaveNamespaceCheck,
SystemCheck::App::RedisVersionCheck,
SystemCheck::App::RubyVersionCheck,
- SystemCheck::App::GitVersionCheck,
SystemCheck::App::GitUserDefaultSSHConfigCheck,
SystemCheck::App::ActiveUsersCheck,
SystemCheck::App::AuthorizedKeysPermissionCheck,
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index cbafed16852..0b70dba5c05 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -10,20 +10,20 @@ module Tasks
JH_ASSET_FOLDERS = %w[jh/app/assets].freeze
JS_ASSET_PATTERNS = %w[*.js config/**/*.js].freeze
JS_ASSET_FILES = %w[package.json yarn.lock].freeze
- MASTER_MD5_HASH_FILE = 'master-assets-hash.txt'
- HEAD_MD5_HASH_FILE = 'assets-hash.txt'
+ MASTER_SHA256_HASH_FILE = 'master-assets-hash.txt'
+ HEAD_SHA256_HASH_FILE = 'assets-hash.txt'
PUBLIC_ASSETS_WEBPACK_DIR = 'public/assets/webpack'
- def self.md5_of_assets_impacting_webpack_compilation
+ def self.sha256_of_assets_impacting_webpack_compilation
start_time = Time.now
asset_files = assets_impacting_webpack_compilation
- puts "Generating the MD5 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..."
+ puts "Generating the SHA256 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..."
- asset_file_md5s = asset_files.map do |asset_file|
- Digest::MD5.file(asset_file).hexdigest
+ asset_file_sha256s = asset_files.map do |asset_file|
+ Digest::SHA256.file(asset_file).hexdigest
end
- Digest::MD5.hexdigest(asset_file_md5s.join).tap { |md5| puts "=> MD5 generated in #{Time.now - start_time}: #{md5}" }
+ Digest::SHA256.hexdigest(asset_file_sha256s.join).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" }
end
def self.assets_impacting_webpack_compilation
@@ -63,25 +63,25 @@ namespace :gitlab do
desc 'GitLab | Assets | Compile all Webpack assets'
task :compile_webpack_if_needed do
- FileUtils.mv(Tasks::Gitlab::Assets::HEAD_MD5_HASH_FILE, Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE, force: true)
+ FileUtils.mv(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE, force: true)
- master_assets_md5 =
- if File.exist?(Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE)
- File.read(Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE)
+ master_assets_sha256 =
+ if File.exist?(Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE)
+ File.read(Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE)
else
'missing!'
end
- head_assets_md5 = Tasks::Gitlab::Assets.md5_of_assets_impacting_webpack_compilation.tap do |md5|
- File.write(Tasks::Gitlab::Assets::HEAD_MD5_HASH_FILE, md5)
+ head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_webpack_compilation.tap do |sha256|
+ File.write(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, sha256)
end
- puts "Webpack assets MD5 for `master`: #{master_assets_md5}"
- puts "Webpack assets MD5 for `HEAD`: #{head_assets_md5}"
+ puts "Webpack assets SHA256 for `master`: #{master_assets_sha256}"
+ puts "Webpack assets SHA256 for `HEAD`: #{head_assets_sha256}"
public_assets_webpack_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR)
- if head_assets_md5 != master_assets_md5 || !public_assets_webpack_dir_exists
+ if head_assets_sha256 != master_assets_sha256 || !public_assets_webpack_dir_exists
FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists
unless system('yarn webpack')
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 0bca63a64f5..78cb7d72d4f 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -9,26 +9,7 @@ namespace :gitlab do
task create: :gitlab_environment do
warn_user_is_not_gitlab
- %w(db repo uploads builds artifacts pages lfs terraform_state registry packages).each do |type|
- Rake::Task["gitlab:backup:#{type}:create"].invoke
- end
-
- backup = Backup::Manager.new(progress)
- backup.write_info
-
- if ENV['SKIP'] && ENV['SKIP'].include?('tar')
- backup.upload
- else
- backup.pack
- backup.upload
- backup.cleanup
- backup.remove_old
- end
-
- progress.puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
- "and are not included in this backup. You will need these files to restore a backup.\n" \
- "Please back them up manually.".color(:red)
- progress.puts "Backup task is done."
+ Backup::Manager.new(progress).create
end
# Restore backup of GitLab system
@@ -36,320 +17,109 @@ namespace :gitlab do
task restore: :gitlab_environment do
warn_user_is_not_gitlab
- backup = Backup::Manager.new(progress)
- cleanup_required = backup.unpack
- backup.verify_backup_version
-
- unless backup.skipped?('db')
- begin
- unless ENV['force'] == 'yes'
- warning = <<-MSG.strip_heredoc
- Be sure to stop Puma, Sidekiq, and any other process that
- connects to the database before proceeding. For Omnibus
- installs, see the following link for more information:
- https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
-
- Before restoring the database, we will remove all existing
- tables to avoid future upgrade problems. Be aware that if you have
- custom tables in the GitLab database these tables and all data will be
- removed.
- MSG
- puts warning.color(:red)
- ask_to_continue
- puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
- sleep(5)
- end
-
- # Drop all tables Load the schema to ensure we don't have any newer tables
- # hanging out from a failed upgrade
- puts_time 'Cleaning the database ... '.color(:blue)
- Rake::Task['gitlab:db:drop_tables'].invoke
- puts_time 'done'.color(:green)
- Rake::Task['gitlab:backup:db:restore'].invoke
- rescue Gitlab::TaskAbortedByUserError
- puts "Quitting...".color(:red)
- exit 1
- end
- end
-
- Rake::Task['gitlab:backup:repo:restore'].invoke unless backup.skipped?('repositories')
- Rake::Task['gitlab:backup:uploads:restore'].invoke unless backup.skipped?('uploads')
- Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds')
- Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts')
- Rake::Task['gitlab:backup:pages:restore'].invoke unless backup.skipped?('pages')
- Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs')
- Rake::Task['gitlab:backup:terraform_state:restore'].invoke unless backup.skipped?('terraform_state')
- Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry')
- Rake::Task['gitlab:backup:packages:restore'].invoke unless backup.skipped?('packages')
- Rake::Task['gitlab:shell:setup'].invoke
- Rake::Task['cache:clear'].invoke
-
- if cleanup_required
- backup.cleanup
- end
-
- backup.remove_tmp
-
- puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
- "and are not included in this backup. You will need to restore these files manually.".color(:red)
- puts "Restore task is done."
+ Backup::Manager.new(progress).restore
end
namespace :repo do
task create: :gitlab_environment do
- puts_time "Dumping repositories ...".color(:blue)
-
- max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i
- max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i
-
- if ENV["SKIP"] && ENV["SKIP"].include?("repositories")
- puts_time "[SKIPPED]".color(:cyan)
- elsif max_concurrency < 1 || max_storage_concurrency < 1
- 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, strategy: repository_backup_strategy).dump(
- max_concurrency: max_concurrency,
- max_storage_concurrency: max_storage_concurrency
- )
- puts_time "done".color(:green)
- end
+ Backup::Manager.new(progress).run_create_task('repositories')
end
task restore: :gitlab_environment do
- puts_time "Restoring repositories ...".color(:blue)
- Backup::Repositories.new(progress, strategy: repository_backup_strategy).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('repositories')
end
end
namespace :db do
task create: :gitlab_environment do
- puts_time "Dumping database ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("db")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Database.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::DatabaseBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('db')
end
task restore: :gitlab_environment do
- puts_time "Restoring database ... ".color(:blue)
- errors = Backup::Database.new(progress).restore
-
- if errors.present?
- warning = <<~MSG
- There were errors in restoring the schema. This may cause
- issues if this results in missing indexes, constraints, or
- columns. Please record the errors above and contact GitLab
- Support if you have questions:
- https://about.gitlab.com/support/
- MSG
-
- warn warning.color(:red)
- ask_to_continue
- end
-
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('db')
end
end
namespace :builds do
task create: :gitlab_environment do
- puts_time "Dumping builds ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("builds")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Builds.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('builds')
end
task restore: :gitlab_environment do
- puts_time "Restoring builds ... ".color(:blue)
- Backup::Builds.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('builds')
end
end
namespace :uploads do
task create: :gitlab_environment do
- puts_time "Dumping uploads ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("uploads")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Uploads.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('uploads')
end
task restore: :gitlab_environment do
- puts_time "Restoring uploads ... ".color(:blue)
- Backup::Uploads.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('uploads')
end
end
namespace :artifacts do
task create: :gitlab_environment do
- puts_time "Dumping artifacts ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("artifacts")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Artifacts.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('artifacts')
end
task restore: :gitlab_environment do
- puts_time "Restoring artifacts ... ".color(:blue)
- Backup::Artifacts.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('artifacts')
end
end
namespace :pages do
task create: :gitlab_environment do
- puts_time "Dumping pages ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("pages")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Pages.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('pages')
end
task restore: :gitlab_environment do
- puts_time "Restoring pages ... ".color(:blue)
- Backup::Pages.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('pages')
end
end
namespace :lfs do
task create: :gitlab_environment do
- puts_time "Dumping lfs objects ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("lfs")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Lfs.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
+ Backup::Manager.new(progress).run_create_task('lfs')
end
task restore: :gitlab_environment do
- puts_time "Restoring lfs objects ... ".color(:blue)
- Backup::Lfs.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('lfs')
end
end
namespace :terraform_state do
task create: :gitlab_environment do
- puts_time "Dumping terraform states ... ".color(:blue)
-
- if ENV["SKIP"] && ENV["SKIP"].include?("terraform_state")
- puts_time "[SKIPPED]".color(:cyan)
- else
- Backup::TerraformState.new(progress).dump
- puts_time "done".color(:green)
- end
+ Backup::Manager.new(progress).run_create_task('terraform_state')
end
task restore: :gitlab_environment do
- puts_time "Restoring terraform states ... ".color(:blue)
- Backup::TerraformState.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('terraform_state')
end
end
namespace :registry do
task create: :gitlab_environment do
- puts_time "Dumping container registry images ... ".color(:blue)
-
- if Gitlab.config.registry.enabled
- if ENV["SKIP"] && ENV["SKIP"].include?("registry")
- puts_time "[SKIPPED]".color(:cyan)
- else
- begin
- Backup::Registry.new(progress).dump
- puts_time "done".color(:green)
- rescue Backup::FileBackupError => e
- progress.puts "#{e.message}"
- end
- end
- else
- puts_time "[DISABLED]".color(:cyan)
- end
+ Backup::Manager.new(progress).run_create_task('registry')
end
task restore: :gitlab_environment do
- puts_time "Restoring container registry images ... ".color(:blue)
-
- if Gitlab.config.registry.enabled
- Backup::Registry.new(progress).restore
- puts_time "done".color(:green)
- else
- puts_time "[DISABLED]".color(:cyan)
- end
+ Backup::Manager.new(progress).run_restore_task('registry')
end
end
namespace :packages do
task create: :gitlab_environment do
- puts_time "Dumping packages ... ".color(:blue)
-
- if ENV['SKIP'] && ENV['SKIP'].include?('packages')
- puts_time "[SKIPPED]".color(:cyan)
- else
- Backup::Packages.new(progress).dump
- puts_time "done".color(:green)
- end
+ Backup::Manager.new(progress).run_create_task('packages')
end
task restore: :gitlab_environment do
- puts_time "Restoring packages ...".color(:blue)
- Backup::Packages.new(progress).restore
- puts_time "done".color(:green)
+ Backup::Manager.new(progress).run_restore_task('packages')
end
end
- def puts_time(msg)
- progress.puts "#{Time.now} -- #{msg}"
- Gitlab::BackupLogger.info(message: "#{Rainbow.uncolor(msg)}")
- end
-
def progress
if ENV['CRON']
# We need an object we can say 'puts' and 'print' to; let's use a
@@ -360,16 +130,6 @@ namespace :gitlab do
$stdout
end
end
-
- def repository_backup_strategy
- if Feature.enabled?(:gitaly_backup, default_enabled: :yaml)
- max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence
- max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence
- Backup::GitalyBackup.new(progress, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
- else
- Backup::GitalyRpcBackup.new(progress)
- end
- end
end
# namespace end: backup
end
diff --git a/lib/tasks/gitlab/banzai.rake b/lib/tasks/gitlab/banzai.rake
new file mode 100644
index 00000000000..b1c7e4ea519
--- /dev/null
+++ b/lib/tasks/gitlab/banzai.rake
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+namespace :gitlab do
+ namespace :banzai do
+ desc 'GitLab | Banzai | Render markdown using our FullPipeline (input will be requested)'
+ task render: :environment do |_t|
+ markdown = []
+
+ puts "\nEnter markdown below, Ctrl-D to end (if you need blank lines, paste in the full text):"
+ while buf = Readline.readline('', true)
+ markdown << buf
+ end
+
+ puts "Rendering using Gitlab's FullPipeline...\n\n"
+
+ html = MarkupHelper.markdown(markdown.join("\n"), { pipeline: :full, project: nil })
+ puts html.gsub('&#x000A;', "\n")
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index efb0e1ef1e1..6d4af9d166f 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -6,23 +6,32 @@ namespace :gitlab do
namespace :db do
desc 'GitLab | DB | Manually insert schema migration version'
task :mark_migration_complete, [:version] => :environment do |_, args|
- unless args[:version]
- puts "Must specify a migration version as an argument".color(:red)
- exit 1
+ mark_migration_complete(args[:version])
+ end
+
+ namespace :mark_migration_complete do
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
+ desc "Gitlab | DB | Manually insert schema migration version on #{name} database"
+ task name, [:version] => :environment do |_, args|
+ mark_migration_complete(args[:version], database: name)
+ end
end
+ end
- version = args[:version].to_i
- if version == 0
- puts "Version '#{args[:version]}' must be a non-zero integer".color(:red)
+ def mark_migration_complete(version, database: nil)
+ if version.to_i == 0
+ puts 'Must give a version argument that is a non-zero integer'.color(:red)
exit 1
end
- sql = "INSERT INTO schema_migrations (version) VALUES (#{version})"
- begin
- ActiveRecord::Base.connection.execute(sql)
- puts "Successfully marked '#{version}' as complete".color(:green)
+ Gitlab::Database.database_base_models.each do |name, model|
+ next if database && database.to_s != name
+
+ model.connection.execute("INSERT INTO schema_migrations (version) VALUES (#{model.connection.quote(version)})")
+
+ puts "Successfully marked '#{version}' as complete on database #{name}".color(:green)
rescue ActiveRecord::RecordNotUnique
- puts "Migration version '#{version}' is already marked complete".color(:yellow)
+ puts "Migration version '#{version}' is already marked complete on database #{name}".color(:yellow)
end
end
@@ -261,6 +270,19 @@ namespace :gitlab do
end
end
+ desc 'Run migration as gitlab non-superuser'
+ task :reset_as_non_superuser, [:username] => :environment do |_, args|
+ username = args.fetch(:username, 'gitlab')
+ puts "Migrate using username #{username}"
+ Rake::Task['db:drop'].invoke
+ Rake::Task['db:create'].invoke
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
+ ActiveRecord::Base.establish_connection(db_config.configuration_hash.merge(username: username)) # rubocop: disable Database/EstablishConnection
+ Gitlab::Database.check_for_non_superuser
+ Rake::Task['db:migrate'].invoke
+ end
+ end
+
# Only for development environments,
# we execute pending data migrations inline for convenience.
Rake::Task['db:migrate'].enhance do
diff --git a/lib/tasks/gitlab/dependency_proxy/migrate.rake b/lib/tasks/gitlab/dependency_proxy/migrate.rake
new file mode 100644
index 00000000000..fa35eacc59d
--- /dev/null
+++ b/lib/tasks/gitlab/dependency_proxy/migrate.rake
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+desc "GitLab | Dependency Proxy | Migrate dependency proxy files to remote storage"
+namespace :gitlab do
+ namespace :dependency_proxy do
+ task migrate: :environment do
+ logger = Logger.new($stdout)
+ logger.info('Starting transfer of dependency proxy files to object storage')
+
+ unless ::DependencyProxy::FileUploader.object_store_enabled?
+ raise 'Object store is disabled for dependency proxy feature'
+ end
+
+ ::DependencyProxy::Blob.with_files_stored_locally.find_each(batch_size: 10) do |blob_file|
+ blob_file.file.migrate!(::DependencyProxy::FileUploader::Store::REMOTE)
+
+ logger.info("Transferred dependency proxy blob file #{blob_file.id} of size #{blob_file.size.to_i.bytes} to object storage")
+ rescue StandardError => e
+ logger.error("Failed to transfer dependency proxy blob file #{blob_file.id} with error: #{e.message}")
+ end
+
+ ::DependencyProxy::Manifest.with_files_stored_locally.find_each(batch_size: 10) do |manifest_file|
+ manifest_file.file.migrate!(::DependencyProxy::FileUploader::Store::REMOTE)
+
+ logger.info("Transferred dependency proxy manifest file #{manifest_file.id} of size #{manifest_file.size.to_i.bytes} to object storage")
+ rescue StandardError => e
+ logger.error("Failed to transfer dependency proxy manifest file #{manifest_file.id} with error: #{e.message}")
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/docs/compile_deprecations.rake b/lib/tasks/gitlab/docs/compile_deprecations.rake
index 4ac68a9f850..f7821315f82 100644
--- a/lib/tasks/gitlab/docs/compile_deprecations.rake
+++ b/lib/tasks/gitlab/docs/compile_deprecations.rake
@@ -2,15 +2,19 @@
namespace :gitlab do
namespace :docs do
+ COLOR_CODE_RESET = "\e[0m"
+ COLOR_CODE_RED = "\e[31m"
+ COLOR_CODE_GREEN = "\e[32m"
+
desc "Generate deprecation list from individual files"
task :compile_deprecations do
require_relative '../../../../tooling/docs/deprecation_handling'
path = Rails.root.join("doc/update/deprecations.md")
File.write(path, Docs::DeprecationHandling.new('deprecation').render)
- puts "Deprecations compiled to #{path}"
+ puts "#{COLOR_CODE_GREEN}INFO: Deprecations compiled to #{path}.#{COLOR_CODE_RESET}"
end
- desc "Check that the deprecation doc is up to date"
+ desc "Check that the deprecation documentation is up to date"
task :check_deprecations do
require_relative '../../../../tooling/docs/deprecation_handling'
path = Rails.root.join("doc/update/deprecations.md")
@@ -19,9 +23,15 @@ namespace :gitlab do
doc = File.read(path)
if doc == contents
- puts "Deprecations doc is up to date."
+ puts "#{COLOR_CODE_GREEN}INFO: Deprecations documentation is up to date.#{COLOR_CODE_RESET}"
else
- format_output('Deprecations doc is outdated! You (or your technical writer) can update it by running `bin/rake gitlab:docs:compile_deprecations`.')
+ warn <<~EOS
+ #{COLOR_CODE_RED}ERROR: Deprecations documentation is outdated!#{COLOR_CODE_RESET}
+ To update the deprecations documentation, either:
+
+ - Run `bin/rake gitlab:docs:compile_deprecations` and commit the changes to this branch.
+ - Have a technical writer resolve the issue.
+ EOS
abort
end
end
@@ -31,10 +41,10 @@ namespace :gitlab do
require_relative '../../../../tooling/docs/deprecation_handling'
path = Rails.root.join("doc/update/removals.md")
File.write(path, Docs::DeprecationHandling.new('removal').render)
- puts "Removals compiled to #{path}"
+ puts "#{COLOR_CODE_GREEN}INFO: Removals compiled to #{path}.#{COLOR_CODE_RESET}"
end
- desc "Check that the removal doc is up to date"
+ desc "Check that the removal documentation is up to date"
task :check_removals do
require_relative '../../../../tooling/docs/deprecation_handling'
path = Rails.root.join("doc/update/removals.md")
@@ -42,9 +52,15 @@ namespace :gitlab do
doc = File.read(path)
if doc == contents
- puts "Removals doc is up to date."
+ puts "#{COLOR_CODE_GREEN}INFO: Removals documentation is up to date.#{COLOR_CODE_RESET}"
else
- format_output('Removals doc is outdated! You (or your technical writer) can update it by running `bin/rake gitlab:docs:compile_removals`.')
+ warn <<~EOS
+ #{COLOR_CODE_RED}ERROR: Removals documentation is outdated!#{COLOR_CODE_RESET}
+ To update the removals documentation, either:
+
+ - Run `bin/rake gitlab:docs:compile_removals` and commit the changes to this branch.
+ - Have a technical writer resolve the issue.
+ EOS
abort
end
end
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index 02764b5d46f..6f42bf8c946 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -22,8 +22,6 @@ namespace :gitlab do
proxies = Gitlab::Proxy.detect_proxy.map {|k, v| "#{k}: #{v}"}.join("\n\t\t")
end
- # check Git version
- git_version = run_and_match([Gitlab.config.git.bin_path, '--version'], /git version ([\d\.]+)/).to_a
# check Go version
go_version = run_and_match(%w(go version), /go version (.+)/).to_a
@@ -43,7 +41,6 @@ namespace :gitlab do
puts "Bundler Version:#{bunder_version || "unknown".color(:red)}"
puts "Rake Version:\t#{rake_version || "unknown".color(:red)}"
puts "Redis Version:\t#{redis_version[1] || "unknown".color(:red)}"
- puts "Git Version:\t#{git_version[1] || "unknown".color(:red)}"
puts "Sidekiq Version:#{Sidekiq::VERSION}"
puts "Go Version:\t#{go_version[1] || "unknown".color(:red)}"
@@ -95,7 +92,6 @@ namespace :gitlab do
end
end
puts "GitLab Shell path:\t\t#{Gitlab.config.gitlab_shell.path}"
- puts "Git:\t\t#{Gitlab.config.git.bin_path}"
end
end
end
diff --git a/lib/tasks/gitlab/tw/codeowners.rake b/lib/tasks/gitlab/tw/codeowners.rake
new file mode 100644
index 00000000000..43fd4f8685a
--- /dev/null
+++ b/lib/tasks/gitlab/tw/codeowners.rake
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'yaml'
+
+namespace :tw do
+ desc 'Generates a list of codeowners for documentation pages.'
+ task :codeowners do
+ CodeOwnerRule = Struct.new(:category, :writer)
+
+ CODE_OWNER_RULES = [
+ CodeOwnerRule.new('Activation', '@kpaizee'),
+ CodeOwnerRule.new("Adoption", '@kpaizee'),
+ CodeOwnerRule.new('Activation', '@kpaizee'),
+ CodeOwnerRule.new('Adoption', '@kpaizee'),
+ CodeOwnerRule.new('APM', '@ngaskill'),
+ CodeOwnerRule.new('Authentication & Authorization', '@eread'),
+ CodeOwnerRule.new('Certify', '@msedlakjakubowski'),
+ CodeOwnerRule.new('Code Review', '@aqualls'),
+ CodeOwnerRule.new('Compliance', '@eread'),
+ CodeOwnerRule.new('Composition Analysis', '@rdickenson'),
+ CodeOwnerRule.new('Configure', '@marcia'),
+ CodeOwnerRule.new('Container Security', '@ngaskill'),
+ CodeOwnerRule.new('Contributor Experience', '@eread'),
+ CodeOwnerRule.new('Conversion', '@kpaizee'),
+ CodeOwnerRule.new('Database', '@marcia'),
+ CodeOwnerRule.new('Development', '@marcia'),
+ CodeOwnerRule.new('Distribution', '@axil'),
+ CodeOwnerRule.new('Distribution (Charts)', '@axil'),
+ CodeOwnerRule.new('Distribution (Omnibus)', '@axil'),
+ CodeOwnerRule.new('Documentation Guidelines', '@cnorris'),
+ CodeOwnerRule.new('Dynamic Analysis', '@rdickenson'),
+ CodeOwnerRule.new('Ecosystem', '@kpaizee'),
+ CodeOwnerRule.new('Editor', '@aqualls'),
+ CodeOwnerRule.new('Expansion', '@kpaizee'),
+ CodeOwnerRule.new('Foundations', '@rdickenson'),
+ CodeOwnerRule.new('Fuzz Testing', '@rdickenson'),
+ CodeOwnerRule.new('Geo', '@axil'),
+ CodeOwnerRule.new('Gitaly', '@eread'),
+ CodeOwnerRule.new('Global Search', '@marcia'),
+ CodeOwnerRule.new('Health', '@ngaskill'),
+ CodeOwnerRule.new('Import', '@ngaskill'),
+ CodeOwnerRule.new('Infrastructure', '@marcia'),
+ CodeOwnerRule.new('Integrations', '@kpaizee'),
+ CodeOwnerRule.new('Knowledge', '@aqualls'),
+ CodeOwnerRule.new('License', '@sselhorn'),
+ CodeOwnerRule.new('Memory', '@marcia'),
+ CodeOwnerRule.new('Monitor', '@ngaskill'),
+ CodeOwnerRule.new('Optimize', '@fneill'),
+ CodeOwnerRule.new('Package', '@ngaskill'),
+ CodeOwnerRule.new('Pipeline Authoring', '@marcel.amirault'),
+ CodeOwnerRule.new('Pipeline Execution', '@marcel.amirault'),
+ CodeOwnerRule.new('Portfolio Management', '@msedlakjakubowski'),
+ CodeOwnerRule.new('Product Intelligence', '@fneill'),
+ CodeOwnerRule.new('Product Planning', '@msedlakjakubowski'),
+ CodeOwnerRule.new('Project Management', '@msedlakjakubowski'),
+ CodeOwnerRule.new('Provision', '@sselhorn'),
+ CodeOwnerRule.new('Purchase', '@sselhorn'),
+ CodeOwnerRule.new('Redirect', 'Redirect'),
+ CodeOwnerRule.new('Release', '@rdickenson'),
+ CodeOwnerRule.new('Runner', '@sselhorn'),
+ CodeOwnerRule.new('Sharding', '@marcia'),
+ CodeOwnerRule.new('Source Code', '@aqualls'),
+ CodeOwnerRule.new('Static Analysis', '@rdickenson'),
+ CodeOwnerRule.new('Static Site Editor', '@aqualls'),
+ CodeOwnerRule.new('Style Guide', '@sselhorn'),
+ CodeOwnerRule.new('Testing', '@eread'),
+ CodeOwnerRule.new('Threat Insights', '@fneill'),
+ CodeOwnerRule.new('Utilization', '@sselhorn'),
+ CodeOwnerRule.new('Vulnerability Research', '@fneill'),
+ CodeOwnerRule.new('Workspace', '@fneill')
+ ].freeze
+
+ Document = Struct.new(:group, :redirect) do
+ def has_a_valid_group?
+ group && !redirect
+ end
+
+ def missing_metadata?
+ !group && !redirect
+ end
+ end
+
+ def self.writer_for_group(category)
+ CODE_OWNER_RULES.find { |rule| rule.category == category }&.writer
+ end
+
+ errors = []
+
+ path = Rails.root.join("doc/**/*.md")
+ Dir.glob(path) do |file|
+ yaml_data = YAML.load_file(file)
+ document = Document.new(yaml_data['group'], yaml_data['redirect_to'])
+
+ if document.missing_metadata?
+ errors << file
+ next
+ end
+
+ writer = writer_for_group(document.group)
+ next unless writer
+
+ puts "#{file.gsub(Dir.pwd, ".")} #{writer}" if document.has_a_valid_group?
+ end
+
+ if errors.present?
+ puts "-----"
+ puts "ERRORS - the following files are missing the correct metadata:"
+ errors.map { |file| puts file.gsub(Dir.pwd, ".")}
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/usage_data.rake b/lib/tasks/gitlab/usage_data.rake
index 694c49240ed..9f064ef4c0c 100644
--- a/lib/tasks/gitlab/usage_data.rake
+++ b/lib/tasks/gitlab/usage_data.rake
@@ -4,17 +4,17 @@ namespace :gitlab do
namespace :usage_data do
desc 'GitLab | UsageData | Generate raw SQLs for usage ping in YAML'
task dump_sql_in_yaml: :environment do
- puts Gitlab::UsageDataQueries.uncached_data.to_yaml
+ puts Gitlab::Usage::ServicePingReport.for(output: :metrics_queries).to_yaml
end
desc 'GitLab | UsageData | Generate raw SQLs for usage ping in JSON'
task dump_sql_in_json: :environment do
- puts Gitlab::Json.pretty_generate(Gitlab::UsageDataQueries.uncached_data)
+ puts Gitlab::Json.pretty_generate(Gitlab::Usage::ServicePingReport.for(output: :metrics_queries))
end
desc 'GitLab | UsageData | Generate usage ping in JSON'
task generate: :environment do
- puts Gitlab::Json.pretty_generate(Gitlab::UsageData.uncached_data)
+ puts Gitlab::Json.pretty_generate(Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values))
end
desc 'GitLab | UsageData | Generate usage ping and send it to Versions Application'
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 9043877aba8..a96ae55e27c 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} በቡድን የሚተዳደሩ መለያዎችን ይጠቀማáˆá¢ በ%{group_name} የሚተዳደር አዲስ የGitLab መለያ መáጠር ይኖርቦታáˆá¢"
@@ -722,6 +751,9 @@ msgstr "%{level_name} በ%{group_level_name} ቡድን á‹áˆµáŒ¥ አይáˆá‰€á‹µ
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "የá•áˆ®áŒ€áŠ­á‰± fork áˆáŠ•áŒ­ á‹á‰…ተኛ እይታ ስላለዠ%{level_name} የተከለከለ áŠá‹á¢"
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 4ce7194d0fd..5ae1000ef86 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -148,6 +148,42 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -745,6 +781,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -934,6 +976,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -1030,6 +1075,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -1039,6 +1087,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -1153,9 +1204,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1192,6 +1240,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2296,21 +2347,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2335,9 +2377,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2443,9 +2482,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2455,7 +2491,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2470,6 +2506,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2536,6 +2575,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2653,9 +2695,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2953,6 +2992,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -3109,6 +3154,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -3145,7 +3193,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3271,6 +3319,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3334,6 +3385,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3436,7 +3490,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3997,22 +4051,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -4123,9 +4168,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4273,16 +4315,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4870,9 +4909,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4903,9 +4939,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4915,13 +4948,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4948,7 +4981,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4963,6 +4996,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4978,7 +5014,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4990,22 +5026,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -5119,6 +5161,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -5215,9 +5260,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5302,7 +5344,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5752,6 +5794,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5884,6 +5929,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5911,6 +5959,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5926,9 +5977,6 @@ 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 ""
@@ -5965,9 +6013,6 @@ 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 ""
@@ -6046,9 +6091,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -6127,6 +6178,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6451,18 +6505,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6478,9 +6526,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6529,15 +6574,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6556,9 +6592,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6754,6 +6787,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6823,9 +6865,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -7060,6 +7114,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7447,6 +7504,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7624,6 +7684,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7924,15 +7987,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -8029,6 +8083,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -8053,7 +8113,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -8098,7 +8158,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -8128,7 +8188,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -8185,13 +8245,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -8218,7 +8281,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -8245,6 +8308,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -8257,6 +8332,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8284,7 +8362,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8302,6 +8380,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -9256,6 +9337,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9505,6 +9589,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9535,6 +9622,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9580,12 +9673,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9613,12 +9709,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -10189,7 +10291,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10330,9 +10432,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10345,9 +10462,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10420,6 +10534,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10447,13 +10564,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10597,6 +10717,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10855,6 +10978,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -11089,6 +11215,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11329,6 +11458,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11338,10 +11470,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11431,12 +11563,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11449,9 +11575,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11464,9 +11587,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11539,9 +11659,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11569,9 +11686,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11581,12 +11695,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11599,9 +11707,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11623,9 +11728,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11899,9 +12001,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12352,6 +12451,9 @@ msgstr[5] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12367,6 +12469,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12583,9 +12688,39 @@ msgstr[5] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -13162,9 +13297,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -13234,7 +13366,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13429,7 +13561,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13675,6 +13807,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13819,9 +13954,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13891,6 +14026,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13969,9 +14110,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -14020,6 +14158,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -14299,6 +14440,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14326,6 +14470,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -15115,9 +15262,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -15127,15 +15271,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -15151,6 +15289,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -15235,10 +15421,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15682,18 +15865,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15781,12 +15952,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -16111,6 +16276,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -16186,6 +16354,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -16222,18 +16393,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -16270,6 +16444,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16324,6 +16501,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16399,12 +16579,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16420,6 +16594,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16453,16 +16630,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16474,9 +16654,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16525,6 +16702,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16561,10 +16744,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16642,6 +16825,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16765,9 +16951,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16792,6 +16975,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16972,6 +17158,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -17110,6 +17299,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -17278,6 +17470,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -17296,6 +17491,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17359,9 +17557,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17386,6 +17581,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17398,9 +17596,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17641,18 +17836,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17677,9 +17866,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17710,7 +17896,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17758,6 +17947,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17776,9 +17968,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17806,9 +17995,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17851,7 +18037,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17932,9 +18118,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17989,7 +18172,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -18226,6 +18409,33 @@ msgstr[5] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -18286,9 +18496,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18325,9 +18532,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18343,6 +18547,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18442,6 +18649,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18466,9 +18685,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -19081,6 +19297,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -19183,6 +19402,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -19258,6 +19480,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19684,9 +19909,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19699,9 +19921,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19771,6 +19990,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19789,9 +20011,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19828,6 +20047,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19837,6 +20059,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19897,7 +20122,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21721,6 +21946,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -22072,9 +22300,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -22090,6 +22315,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -22126,6 +22354,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22900,6 +23161,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22918,9 +23185,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23749,9 +24025,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23773,9 +24046,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23956,10 +24226,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -24064,9 +24334,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -24145,9 +24412,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -24166,9 +24430,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24688,6 +24949,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24715,6 +24979,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24781,7 +25048,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25714,7 +25981,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -26335,9 +26623,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26476,6 +26761,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26494,7 +26782,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26761,9 +27049,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26776,6 +27061,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26788,7 +27076,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26953,10 +27241,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -27139,6 +27445,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -27154,6 +27463,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27508,6 +27823,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27733,6 +28051,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27757,9 +28078,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27937,6 +28255,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27982,9 +28303,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28507,10 +28825,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28588,6 +28909,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28633,6 +28960,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28759,9 +29089,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28783,7 +29110,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28801,7 +29128,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29563,9 +29890,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29599,7 +29923,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29845,6 +30169,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29914,6 +30244,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29992,7 +30325,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30544,6 +30877,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30778,6 +31120,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30853,9 +31198,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30874,6 +31216,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -31009,9 +31354,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -31078,7 +31420,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -31186,13 +31528,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -31213,6 +31555,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -31300,6 +31645,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -31312,9 +31660,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -31333,6 +31687,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -31348,9 +31705,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31399,10 +31753,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31438,6 +31795,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31477,16 +31837,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31498,6 +31858,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31513,9 +31876,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31669,9 +32029,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31798,9 +32155,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -32146,7 +32500,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -32278,6 +32632,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -32332,6 +32689,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -32350,21 +32710,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -32374,12 +32743,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -32407,6 +32785,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32422,12 +32806,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32437,6 +32869,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32758,9 +33193,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -33148,7 +33580,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -33157,6 +33589,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -33166,18 +33601,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -33316,7 +33745,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33493,9 +33922,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33535,6 +33961,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33547,6 +33976,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33559,9 +33991,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33586,6 +34015,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33634,7 +34066,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33727,6 +34159,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33829,9 +34264,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -34138,9 +34597,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -34204,9 +34660,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34540,6 +34993,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34582,6 +35038,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34924,6 +35383,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34954,6 +35416,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -35032,9 +35515,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -35203,9 +35683,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -35230,6 +35707,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -35269,6 +35749,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -35323,6 +35806,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -35335,6 +35821,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35578,6 +36073,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35650,6 +36148,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35836,6 +36337,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -36016,9 +36520,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -36061,12 +36562,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -36076,9 +36571,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -36112,7 +36604,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -36283,6 +36775,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -36358,9 +36853,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -36376,9 +36868,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36748,7 +37237,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36799,7 +37288,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36883,9 +37372,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -37009,6 +37495,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -37048,9 +37537,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -37090,9 +37576,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -37312,6 +37804,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -37333,6 +37828,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -37372,6 +37870,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37600,9 +38101,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37858,9 +38356,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -38002,9 +38497,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -38020,9 +38512,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -38230,9 +38719,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -38347,6 +38833,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -38362,15 +38851,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38437,6 +38920,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38956,6 +39445,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38977,6 +39469,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -39412,6 +39907,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39943,6 +40441,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -40102,6 +40612,9 @@ msgstr[5] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -40327,6 +40840,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -40369,6 +40885,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -40387,6 +40906,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -40396,6 +40921,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -40408,6 +40936,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -40420,6 +40951,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40444,9 +40978,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40627,127 +41170,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40855,10 +41398,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -41170,7 +41713,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -41272,6 +41821,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -41305,6 +41857,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -41353,6 +41908,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -41398,6 +41956,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41533,6 +42094,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41629,6 +42193,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41668,7 +42235,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41683,6 +42250,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -42064,7 +42634,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -42073,9 +42643,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -42142,6 +42709,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -42280,6 +42850,15 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "approved by: "
msgstr ""
@@ -42367,6 +42946,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42751,6 +43333,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42778,12 +43363,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42919,6 +43498,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42973,6 +43555,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -43093,6 +43681,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -43189,9 +43780,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -43237,9 +43825,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -43366,7 +43951,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -43417,6 +44002,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -43471,6 +44059,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43516,6 +44107,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43525,9 +44119,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43564,9 +44155,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43867,9 +44455,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -44050,9 +44635,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index ceb49d0e7f6..3a0fbc6d102 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 82c56f0dc55..d84a094fa86 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index a39c3bf5ce9..6fbbcb217a2 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -645,6 +670,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1875,7 +1891,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 2ebca9f78af..f746f965631 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "от"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Подбиране на тази заÑвка за Ñливане"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "ВнедрÑваниÑ"
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "ОÑвежаването започна уÑпешно"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr "Схеми"
msgid "Pipelines charts"
msgstr "Графики за Ñхемите"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Изберете формата на архива"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Ðе можете да Ñъздавате повече проекти"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Вашето име"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 2b98bb85c85..ee0818fc56b 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 835bd013af1..620f7ee1485 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index 2572a05a0ab..7b26b894b62 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: 2022-01-06 17:25\n"
+"PO-Revision-Date: 2022-02-02 15:49\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -140,6 +140,38 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -674,6 +706,12 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -857,6 +895,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -953,6 +994,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -962,6 +1006,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -1075,9 +1122,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1113,6 +1157,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2180,21 +2227,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2219,9 +2257,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2327,9 +2362,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2339,7 +2371,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2354,6 +2386,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2420,6 +2455,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2537,9 +2575,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2837,6 +2872,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2993,6 +3034,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -3029,7 +3073,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3155,6 +3199,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3218,6 +3265,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3320,7 +3370,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3881,22 +3931,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -4007,9 +4048,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4157,16 +4195,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4746,9 +4781,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4779,9 +4811,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4791,13 +4820,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4824,7 +4853,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4839,6 +4868,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4854,7 +4886,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4866,22 +4898,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4995,6 +5033,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -5090,9 +5131,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5177,7 +5215,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5625,6 +5663,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5757,6 +5798,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5784,6 +5828,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5799,9 +5846,6 @@ 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 ""
@@ -5838,9 +5882,6 @@ 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 ""
@@ -5919,9 +5960,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -6000,6 +6047,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6321,18 +6371,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6348,9 +6392,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6399,15 +6440,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6426,9 +6458,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6624,6 +6653,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6692,9 +6730,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6929,6 +6979,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7314,6 +7367,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7491,6 +7547,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7791,15 +7850,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7896,6 +7946,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7920,7 +7976,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7965,7 +8021,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7995,7 +8051,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -8052,13 +8108,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -8085,7 +8144,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -8112,6 +8171,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -8124,6 +8195,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8150,7 +8224,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8168,6 +8242,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -9121,6 +9198,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9370,6 +9450,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9400,6 +9483,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9445,12 +9534,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9478,12 +9570,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -10051,7 +10149,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10192,9 +10290,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10207,9 +10320,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10282,6 +10392,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10309,13 +10422,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10459,6 +10575,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10717,6 +10836,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10951,6 +11073,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11189,6 +11314,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11198,10 +11326,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11291,12 +11419,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11309,9 +11431,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11324,9 +11443,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11399,9 +11515,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11429,9 +11542,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11441,12 +11551,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11459,9 +11563,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11483,9 +11584,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11758,9 +11856,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12205,6 +12300,9 @@ msgstr[4] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12220,6 +12318,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12435,9 +12536,39 @@ msgstr[4] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -13010,9 +13141,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -13081,7 +13209,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13276,7 +13404,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13522,6 +13650,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13666,9 +13797,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13711,6 +13839,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13738,6 +13869,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13816,9 +13953,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13867,6 +14001,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -14145,6 +14282,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14172,6 +14312,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14960,9 +15103,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14972,15 +15112,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14996,6 +15130,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -15079,10 +15261,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15525,17 +15704,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15623,12 +15791,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15953,6 +16115,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -16028,6 +16193,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -16064,18 +16232,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -16112,6 +16283,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16166,6 +16340,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16241,12 +16418,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16262,6 +16433,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16295,16 +16469,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16316,9 +16493,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16367,6 +16541,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16403,10 +16583,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16484,6 +16664,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16607,9 +16790,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16634,6 +16814,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16814,6 +16997,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16952,6 +17138,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -17120,6 +17309,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -17138,6 +17330,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17201,9 +17396,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17228,6 +17420,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17240,9 +17435,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17483,18 +17675,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17519,9 +17705,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17552,7 +17735,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17600,6 +17786,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17618,9 +17807,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17648,9 +17834,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17693,7 +17876,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17774,9 +17957,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17831,7 +18011,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -18066,6 +18246,33 @@ msgstr[4] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -18126,9 +18333,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18165,9 +18369,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18183,6 +18384,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18282,6 +18486,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18306,9 +18522,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18918,6 +19131,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -19020,6 +19236,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -19095,6 +19314,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19520,9 +19742,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19535,9 +19754,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19607,6 +19823,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19625,9 +19844,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19664,6 +19880,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19673,6 +19892,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19733,7 +19955,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21556,6 +21778,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21900,9 +22125,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21918,6 +22140,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21954,6 +22179,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22728,6 +22986,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22746,9 +23010,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23575,9 +23848,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23599,9 +23869,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23781,10 +24048,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23889,9 +24156,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23970,9 +24234,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23991,9 +24252,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24512,6 +24770,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24539,6 +24800,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24605,7 +24869,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25532,7 +25796,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -26152,9 +26437,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26293,6 +26575,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26311,7 +26596,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26578,9 +26863,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26593,6 +26875,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26605,7 +26890,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26770,10 +27055,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26956,6 +27259,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26971,6 +27277,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27325,6 +27637,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27550,6 +27865,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27574,9 +27892,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27754,6 +28069,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27799,9 +28117,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28324,10 +28639,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28405,6 +28723,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28450,6 +28774,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28576,9 +28903,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28600,7 +28924,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28618,7 +28942,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29380,9 +29704,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29416,7 +29737,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29662,6 +29983,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29731,6 +30058,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29808,7 +30138,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30357,6 +30687,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30589,6 +30927,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30664,9 +31005,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30685,6 +31023,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30818,9 +31159,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30887,7 +31225,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30993,13 +31331,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -31020,6 +31358,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -31107,6 +31448,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -31119,9 +31463,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -31140,6 +31490,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -31155,9 +31508,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31206,10 +31556,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31245,6 +31598,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31284,16 +31640,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31305,6 +31661,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31320,9 +31679,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31476,9 +31832,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31605,9 +31958,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31942,7 +32292,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -32074,6 +32424,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -32128,6 +32481,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -32146,21 +32502,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -32170,12 +32535,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -32203,6 +32577,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32218,12 +32598,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32233,6 +32661,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32554,9 +32985,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32944,7 +33372,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32953,6 +33381,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32962,18 +33393,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -33112,7 +33537,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33288,9 +33713,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33330,6 +33752,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33342,6 +33767,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33354,9 +33782,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33381,6 +33806,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33427,7 +33855,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33520,6 +33948,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33622,9 +34053,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33931,9 +34386,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33997,9 +34449,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34333,6 +34782,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34375,6 +34827,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34717,6 +35172,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34747,6 +35205,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34825,9 +35304,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34996,9 +35472,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -35023,6 +35496,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -35062,6 +35538,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -35116,6 +35595,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -35128,6 +35610,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35371,6 +35862,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35443,6 +35937,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35625,6 +36122,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35803,9 +36303,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35847,12 +36344,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35862,9 +36353,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35898,7 +36386,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -36068,6 +36556,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -36143,9 +36634,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -36161,9 +36649,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36533,7 +37018,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36584,7 +37069,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36668,9 +37153,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36794,6 +37276,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36833,9 +37318,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36875,9 +37357,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -37097,6 +37585,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -37118,6 +37609,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -37157,6 +37651,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37385,9 +37882,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37641,9 +38135,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37785,9 +38276,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37803,9 +38291,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -38013,9 +38498,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -38129,6 +38611,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -38144,15 +38629,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38219,6 +38698,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38738,6 +39223,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38759,6 +39247,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -39194,6 +39685,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39725,6 +40219,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39881,6 +40387,9 @@ msgstr[4] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -40106,6 +40615,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -40148,6 +40660,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -40166,6 +40681,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -40175,6 +40696,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -40187,6 +40711,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -40199,6 +40726,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40223,9 +40753,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40406,127 +40945,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40634,10 +41173,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40948,7 +41487,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -41050,6 +41595,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -41083,6 +41631,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -41131,6 +41682,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -41176,6 +41730,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41311,6 +41868,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41406,6 +41966,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41445,7 +42008,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41460,6 +42023,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41841,7 +42407,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41850,9 +42416,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41919,6 +42482,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -42055,6 +42621,14 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "approved by: "
msgstr ""
@@ -42141,6 +42715,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42522,6 +43099,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42549,12 +43129,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42688,6 +43262,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42740,6 +43317,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42859,6 +43442,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42955,9 +43541,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -43002,9 +43585,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -43130,7 +43710,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -43180,6 +43760,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -43234,6 +43817,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43279,6 +43865,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43288,9 +43877,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43327,9 +43913,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43625,9 +44208,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43808,9 +44388,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index dad23730748..a4c8c348b1c 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -124,6 +124,30 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d odobravatelj"
@@ -532,6 +556,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -703,6 +733,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -799,6 +832,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -808,6 +844,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -919,9 +958,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -955,6 +991,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1948,21 +1987,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1987,9 +2017,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2095,9 +2122,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2107,7 +2131,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2122,6 +2146,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2188,6 +2215,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2305,9 +2335,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2605,6 +2632,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2761,6 +2794,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2797,7 +2833,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2923,6 +2959,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3088,7 +3130,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3649,22 +3691,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3775,9 +3808,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3925,16 +3955,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4498,9 +4525,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4531,9 +4555,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4543,13 +4564,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4576,7 +4597,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4591,6 +4612,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4606,7 +4630,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4618,22 +4642,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4747,6 +4777,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4840,9 +4873,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4927,7 +4957,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5371,6 +5401,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr "Dnevni prosjek: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5503,6 +5536,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5530,6 +5566,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5545,9 +5584,6 @@ 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 ""
@@ -5584,9 +5620,6 @@ 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 ""
@@ -5665,9 +5698,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5746,6 +5785,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6061,18 +6103,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6088,9 +6124,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6139,15 +6172,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6166,9 +6190,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6364,6 +6385,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6430,9 +6460,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6667,6 +6709,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7048,6 +7093,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7225,6 +7273,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7525,15 +7576,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7630,6 +7672,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7654,7 +7702,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7699,7 +7747,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7729,7 +7777,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7786,13 +7834,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7819,7 +7870,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7846,6 +7897,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7858,6 +7921,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7882,7 +7948,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7900,6 +7966,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8851,6 +8920,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9100,6 +9172,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9130,6 +9205,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9175,12 +9256,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9208,12 +9292,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9775,7 +9865,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9916,9 +10006,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9931,9 +10036,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10006,6 +10108,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10033,13 +10138,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10183,6 +10291,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10441,6 +10552,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10675,6 +10789,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10909,6 +11026,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10918,10 +11038,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11011,12 +11131,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11029,9 +11143,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11044,9 +11155,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11119,9 +11227,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11149,9 +11254,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11161,12 +11263,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11179,9 +11275,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11203,9 +11296,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11476,9 +11566,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11911,6 +11998,9 @@ msgstr[2] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11926,6 +12016,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12139,9 +12232,39 @@ msgstr[2] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12706,9 +12829,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12775,7 +12895,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12970,7 +13090,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13216,6 +13336,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13360,9 +13483,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13405,6 +13525,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13432,6 +13555,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13510,9 +13639,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13561,6 +13687,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13837,6 +13966,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14650,9 +14785,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14662,15 +14794,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14686,6 +14812,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14767,10 +14941,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15211,15 +15382,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15307,12 +15469,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15637,6 +15793,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15712,6 +15871,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15748,18 +15910,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15796,6 +15961,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15850,6 +16018,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15925,12 +16096,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15946,6 +16111,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15979,16 +16147,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16000,9 +16171,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16051,6 +16219,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16087,10 +16261,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16168,6 +16342,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16291,9 +16468,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16318,6 +16492,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16498,6 +16675,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16636,6 +16816,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16804,6 +16987,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16822,6 +17008,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16885,9 +17074,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16912,6 +17098,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16924,9 +17113,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17167,18 +17353,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17203,9 +17383,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17236,7 +17413,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17284,6 +17464,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17302,9 +17485,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17332,9 +17512,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17377,7 +17554,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17458,9 +17635,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17515,7 +17689,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17746,6 +17920,33 @@ msgstr[2] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17806,9 +18007,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17845,9 +18043,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17863,6 +18058,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17962,6 +18160,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17986,9 +18196,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18592,6 +18799,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18694,6 +18904,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18769,6 +18982,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19192,9 +19408,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19207,9 +19420,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19279,6 +19489,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19297,9 +19510,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19336,6 +19546,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19345,6 +19558,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19405,7 +19621,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21226,6 +21442,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21556,9 +21775,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21574,6 +21790,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21610,6 +21829,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22384,6 +22636,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22402,9 +22660,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23227,9 +23494,6 @@ msgstr "Mjeseci"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23251,9 +23515,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23431,10 +23692,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23539,9 +23800,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23620,9 +23878,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23641,9 +23896,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24160,6 +24412,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24187,6 +24442,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24253,7 +24511,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25168,7 +25426,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25786,9 +26065,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25927,6 +26203,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25945,7 +26224,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26212,9 +26491,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26227,6 +26503,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26239,7 +26518,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26404,10 +26683,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26590,6 +26887,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26605,6 +26905,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26959,6 +27265,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27184,6 +27493,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27208,9 +27520,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27388,6 +27697,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27433,9 +27745,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27958,10 +28267,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28039,6 +28351,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28084,6 +28402,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28210,9 +28531,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28234,7 +28552,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28252,7 +28570,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29014,9 +29332,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29050,7 +29365,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29296,6 +29611,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29365,6 +29686,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29440,7 +29764,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29983,6 +30307,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30211,6 +30541,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30286,9 +30619,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30307,6 +30637,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30436,9 +30769,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30505,7 +30835,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30607,13 +30937,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30634,6 +30964,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30721,6 +31054,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30733,9 +31069,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30754,6 +31096,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30769,9 +31114,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30820,10 +31162,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30859,6 +31204,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30898,16 +31246,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30919,6 +31267,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30934,9 +31285,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31090,9 +31438,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31219,9 +31564,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31534,7 +31876,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31666,6 +32008,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31720,6 +32065,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31738,21 +32086,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31762,12 +32119,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,6 +32161,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31810,12 +32182,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31825,6 +32245,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32146,9 +32569,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32536,7 +32956,7 @@ msgstr "TehniÄka PodrÅ¡ka"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32545,6 +32965,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32554,18 +32977,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32704,7 +33121,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32878,9 +33295,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32920,6 +33334,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32932,6 +33349,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32944,9 +33364,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32971,6 +33388,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33013,7 +33433,7 @@ msgstr "Svi zadaci prikazani"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33106,6 +33526,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33208,9 +33631,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33517,9 +33964,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33583,9 +34027,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33919,6 +34360,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33961,6 +34405,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34303,6 +34750,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34333,6 +34783,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34411,9 +34882,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34582,9 +35050,6 @@ msgstr ""
msgid "Sunday"
msgstr "Nedjelja"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34609,6 +35074,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34648,6 +35116,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34702,6 +35173,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34714,6 +35188,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34957,6 +35440,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35029,6 +35515,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35203,6 +35692,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35377,9 +35869,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35419,12 +35908,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35434,9 +35917,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35470,7 +35950,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35638,6 +36118,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35713,9 +36196,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35731,9 +36211,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36103,7 +36580,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36154,7 +36631,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36238,9 +36715,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36364,6 +36838,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36403,9 +36880,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36445,9 +36919,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36667,6 +37147,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36688,6 +37171,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36727,6 +37213,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36955,9 +37444,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37207,9 +37693,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37351,9 +37834,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37369,9 +37849,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37579,9 +38056,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37693,6 +38167,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37708,15 +38185,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37783,6 +38254,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38302,6 +38779,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38323,6 +38803,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38758,6 +39241,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39289,6 +39775,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39439,6 +39937,9 @@ msgstr[2] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39664,6 +40165,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39706,6 +40210,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39724,6 +40231,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39733,6 +40246,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39745,6 +40261,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39757,6 +40276,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39781,9 +40303,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39964,127 +40495,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40192,10 +40723,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40504,7 +41035,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40606,6 +41143,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40639,6 +41179,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40687,6 +41230,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40732,6 +41278,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40867,6 +41416,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40960,6 +41512,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40999,7 +41554,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41014,6 +41569,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41395,7 +41953,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41404,9 +41962,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41473,6 +42028,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41605,6 +42163,12 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "approved by: "
msgstr ""
@@ -41689,6 +42253,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42064,6 +42631,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42091,12 +42661,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42226,6 +42790,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42274,6 +42841,12 @@ msgstr ""
msgid "group"
msgstr "grupa"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42391,6 +42964,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42487,9 +43063,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42532,9 +43105,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42658,7 +43228,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42706,6 +43276,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42760,6 +43333,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42805,6 +43381,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42814,9 +43393,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42853,9 +43429,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43141,9 +43714,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43324,9 +43894,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "korisniÄko ime"
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index baec3c96e96..817cd3af60c 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL escanejada"
msgstr[1] "%d URL escanejades"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprovador"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} no és un tema vàlid"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr "Branca nova"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr "Creat per mi"
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "feb."
@@ -15149,12 +15308,6 @@ msgstr "Filtra"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fallit"
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "Amaga els valors"
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr "Identitats"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "Mesos"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 44b010039f0..ce37c2d4bc5 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -132,6 +132,34 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -780,6 +814,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -876,6 +913,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2223,7 +2251,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2238,6 +2266,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2421,9 +2455,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4041,16 +4075,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr "Nová větev"
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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}."
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 635bb93c491..215a59b7225 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -148,6 +148,42 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -745,6 +781,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -934,6 +976,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -1030,6 +1075,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -1039,6 +1087,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -1153,9 +1204,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1192,6 +1240,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2296,21 +2347,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2335,9 +2377,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2443,9 +2482,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2455,7 +2491,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2470,6 +2506,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2536,6 +2575,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2653,9 +2695,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2953,6 +2992,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -3109,6 +3154,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -3145,7 +3193,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3271,6 +3319,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3334,6 +3385,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3436,7 +3490,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3997,22 +4051,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -4123,9 +4168,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4273,16 +4315,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4870,9 +4909,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4903,9 +4939,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4915,13 +4948,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4948,7 +4981,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4963,6 +4996,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4978,7 +5014,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4990,22 +5026,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -5119,6 +5161,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -5215,9 +5260,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5302,7 +5344,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5752,6 +5794,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5884,6 +5929,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5911,6 +5959,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5926,9 +5977,6 @@ 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 ""
@@ -5965,9 +6013,6 @@ 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 ""
@@ -6046,9 +6091,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -6127,6 +6178,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6451,18 +6505,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6478,9 +6526,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6529,15 +6574,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6556,9 +6592,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6754,6 +6787,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6823,9 +6865,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -7060,6 +7114,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7447,6 +7504,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7624,6 +7684,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7924,15 +7987,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -8029,6 +8083,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -8053,7 +8113,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -8098,7 +8158,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -8128,7 +8188,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -8185,13 +8245,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -8218,7 +8281,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -8245,6 +8308,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -8257,6 +8332,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8284,7 +8362,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8302,6 +8380,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -9256,6 +9337,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9505,6 +9589,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9535,6 +9622,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9580,12 +9673,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9613,12 +9709,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -10189,7 +10291,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10330,9 +10432,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10345,9 +10462,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10420,6 +10534,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10447,13 +10564,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10597,6 +10717,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10855,6 +10978,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -11089,6 +11215,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11329,6 +11458,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11338,10 +11470,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11431,12 +11563,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11449,9 +11575,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11464,9 +11587,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11539,9 +11659,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11569,9 +11686,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11581,12 +11695,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11599,9 +11707,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11623,9 +11728,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11899,9 +12001,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12352,6 +12451,9 @@ msgstr[5] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12367,6 +12469,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12583,9 +12688,39 @@ msgstr[5] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -13162,9 +13297,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -13234,7 +13366,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13429,7 +13561,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13675,6 +13807,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13819,9 +13954,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13891,6 +14026,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13969,9 +14110,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -14020,6 +14158,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -14299,6 +14440,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14326,6 +14470,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -15115,9 +15262,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -15127,15 +15271,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -15151,6 +15289,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -15235,10 +15421,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15682,18 +15865,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15781,12 +15952,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -16111,6 +16276,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -16186,6 +16354,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -16222,18 +16393,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -16270,6 +16444,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16324,6 +16501,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16399,12 +16579,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16420,6 +16594,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16453,16 +16630,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16474,9 +16654,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16525,6 +16702,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16561,10 +16744,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16642,6 +16825,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16765,9 +16951,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16792,6 +16975,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16972,6 +17158,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -17110,6 +17299,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -17278,6 +17470,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -17296,6 +17491,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17359,9 +17557,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17386,6 +17581,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17398,9 +17596,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17641,18 +17836,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17677,9 +17866,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17710,7 +17896,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17758,6 +17947,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17776,9 +17968,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17806,9 +17995,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17851,7 +18037,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17932,9 +18118,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17989,7 +18172,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -18226,6 +18409,33 @@ msgstr[5] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -18286,9 +18496,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18325,9 +18532,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18343,6 +18547,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18442,6 +18649,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18466,9 +18685,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -19081,6 +19297,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -19183,6 +19402,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -19258,6 +19480,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19684,9 +19909,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19699,9 +19921,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19771,6 +19990,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19789,9 +20011,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19828,6 +20047,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19837,6 +20059,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19897,7 +20122,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21721,6 +21946,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -22072,9 +22300,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -22090,6 +22315,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -22126,6 +22354,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22900,6 +23161,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22918,9 +23185,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23749,9 +24025,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23773,9 +24046,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23956,10 +24226,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -24064,9 +24334,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -24145,9 +24412,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -24166,9 +24430,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24688,6 +24949,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24715,6 +24979,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24781,7 +25048,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25714,7 +25981,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -26335,9 +26623,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26476,6 +26761,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26494,7 +26782,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26761,9 +27049,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26776,6 +27061,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26788,7 +27076,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26953,10 +27241,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -27139,6 +27445,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -27154,6 +27463,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27508,6 +27823,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27733,6 +28051,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27757,9 +28078,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27937,6 +28255,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27982,9 +28303,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28507,10 +28825,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28588,6 +28909,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28633,6 +28960,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28759,9 +29089,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28783,7 +29110,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28801,7 +29128,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29563,9 +29890,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29599,7 +29923,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29845,6 +30169,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29914,6 +30244,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29992,7 +30325,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30544,6 +30877,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30778,6 +31120,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30853,9 +31198,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30874,6 +31216,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -31009,9 +31354,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -31078,7 +31420,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -31186,13 +31528,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -31213,6 +31555,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -31300,6 +31645,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -31312,9 +31660,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -31333,6 +31687,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -31348,9 +31705,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31399,10 +31753,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31438,6 +31795,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31477,16 +31837,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31498,6 +31858,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31513,9 +31876,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31669,9 +32029,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31798,9 +32155,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -32146,7 +32500,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -32278,6 +32632,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -32332,6 +32689,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -32350,21 +32710,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -32374,12 +32743,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -32407,6 +32785,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32422,12 +32806,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32437,6 +32869,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32758,9 +33193,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -33148,7 +33580,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -33157,6 +33589,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -33166,18 +33601,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -33316,7 +33745,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33493,9 +33922,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33535,6 +33961,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33547,6 +33976,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33559,9 +33991,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33586,6 +34015,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33634,7 +34066,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33727,6 +34159,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33829,9 +34264,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -34138,9 +34597,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -34204,9 +34660,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34540,6 +34993,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34582,6 +35038,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34924,6 +35383,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34954,6 +35416,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -35032,9 +35515,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -35203,9 +35683,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -35230,6 +35707,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -35269,6 +35749,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -35323,6 +35806,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -35335,6 +35821,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35578,6 +36073,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35650,6 +36148,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35836,6 +36337,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -36016,9 +36520,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -36061,12 +36562,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -36076,9 +36571,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -36112,7 +36604,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -36283,6 +36775,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -36358,9 +36853,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -36376,9 +36868,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36748,7 +37237,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36799,7 +37288,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36883,9 +37372,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -37009,6 +37495,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -37048,9 +37537,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -37090,9 +37576,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -37312,6 +37804,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -37333,6 +37828,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -37372,6 +37870,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37600,9 +38101,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37858,9 +38356,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -38002,9 +38497,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -38020,9 +38512,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -38230,9 +38719,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -38347,6 +38833,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -38362,15 +38851,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38437,6 +38920,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38956,6 +39445,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38977,6 +39469,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -39412,6 +39907,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39943,6 +40441,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -40102,6 +40612,9 @@ msgstr[5] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -40327,6 +40840,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -40369,6 +40885,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -40387,6 +40906,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -40396,6 +40921,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -40408,6 +40936,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -40420,6 +40951,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40444,9 +40978,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40627,127 +41170,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40855,10 +41398,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -41170,7 +41713,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -41272,6 +41821,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -41305,6 +41857,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -41353,6 +41908,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -41398,6 +41956,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41533,6 +42094,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41629,6 +42193,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41668,7 +42235,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41683,6 +42250,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -42064,7 +42634,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -42073,9 +42643,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -42142,6 +42709,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -42280,6 +42850,15 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "approved by: "
msgstr ""
@@ -42367,6 +42946,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42751,6 +43333,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42778,12 +43363,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42919,6 +43498,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42973,6 +43555,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -43093,6 +43681,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -43189,9 +43780,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -43237,9 +43825,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -43366,7 +43951,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -43417,6 +44002,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -43471,6 +44059,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43516,6 +44107,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43525,9 +44119,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43564,9 +44155,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43867,9 +44455,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -44050,9 +44635,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index dbca2826517..7e06ad33c13 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL skannet"
msgstr[1] "%d URL'er skannet"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkender"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} åbnet sammenlægningsanmodning"
msgstr[1] "%{bold_start}%{count}%{bold_end} åbnede sammenlægningsanmodninger"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Maskeret:%{code_close} Skjult i joblogge. Skal matche maskeringskrav."
@@ -626,6 +652,9 @@ msgstr "aktivitet i %{group_name}"
msgid "%{group_name} group members"
msgstr "gruppemedlemmer i %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} bruger gruppehåndterede kontoer. Du skal oprette en ny GitLab-konto som håndteres af %{group_name}."
@@ -722,6 +751,9 @@ msgstr "%{level_name} er ikke tilladt i en %{group_level_name}-gruppe."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} er ikke tilladt eftersom forgreningskildeprojektet har lavere synlighed."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}Lær mere%{link_end} om roller."
@@ -731,6 +763,9 @@ msgstr "%{link_start}Fjern præfikset %{draft_snippet}%{link_end} fra titlen, nÃ
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Hvilke informationer indsamler GitLab Inc.?%{link_end}"
@@ -841,9 +876,6 @@ msgstr "%{placeholder} er ikke et gyldigt tema"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ msgstr "%{rotation} er blevet udregnet igen med de tilbageværende deltagere. Ko
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 "%{rotation} er blevet udregnet igen med de tilbageværende deltagere. Kontrollér venligst den nye opsætning for %{rotation}. Det anbefales at du tager kontakt til den nuværende vagtperson for at sikre kontinuitet i vagtdækning."
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} resultater for udtrykket '%{term}'"
@@ -1832,21 +1867,12 @@ msgstr "Den kan ikke bruges til at få adgang til andre data."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Hold adgangstokenen hemmelig. Alle der har den kan oprette problemstillinger som var de dig. Hvis det sker, så %{link_reset_it}."
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Hold adgangstokenen hemmelig. Alle der har den kan læse aktivitets- og problemstillings RSS-feeds eller din kalenderfeed som var de dig. Hvis det sker, så %{link_reset_it}."
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "Personlige adgangstokens"
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr "nulstil tokenen"
-
msgid "AccessibilityReport|Learn more"
msgstr "Lær mere"
@@ -1979,9 +2002,6 @@ msgstr "Tilføj CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Tilføj CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Tilføj GitLab til Slack"
-
msgid "Add Jaeger URL"
msgstr "Tilføj Jaeger-URL"
@@ -1991,8 +2011,8 @@ msgstr "Tilføj Kubernetes-klynge"
msgid "Add LICENSE"
msgstr "Tilføj LICENSE"
-msgid "Add New Node"
-msgstr "Tilføj nyt knudepunkt"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Tilføj README"
@@ -2006,6 +2026,9 @@ msgstr "Tilføj en %{type}"
msgid "Add a GPG key"
msgstr "Tilføj en GPG-nøgle"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Tilføj en Jaeger-URL for at erstatte siden med et link til din Jaeger-server. Du skal først %{link_start_tag}installere Jaeger%{link_end_tag}."
@@ -2072,6 +2095,9 @@ msgstr "Tilføj et gøremål"
msgid "Add an SSH key"
msgstr "Tilføj en SSH-nøgle"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Tilføj en eksisterende problemstilling"
@@ -2189,9 +2215,6 @@ msgstr "Tilføj systemhook"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "Tilføj tekst til indlogningssiden. Markdown er aktiveret."
-msgid "Add to Slack"
-msgstr "Tilføj til Slack"
-
msgid "Add to board"
msgstr "Tilføj til tavle"
@@ -2489,6 +2512,12 @@ msgstr "Du er ved at stoppe alle job. Det standser alle nuværende job som køre
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Fejl ved indlæsning af statistikken. Prøv venligst igen"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr "(deaktiveret)"
msgid "AdminUsers|(Internal)"
msgstr "(intern)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(afventer godkendelse)"
@@ -2681,7 +2713,7 @@ msgstr "Juster indstillingen brugerloft på din instans"
msgid "AdminUsers|Admin"
msgstr "Administrator"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr "Det er dig!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "Lær mere om %{link_start}udelukkede brugere%{link_end}."
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Log ind"
@@ -2870,6 +2905,9 @@ msgstr "Brugeren kan ikke tilgå git-depoter."
msgid "AdminUsers|The user can't log in."
msgstr "Brugeren kan ikke logge ind."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Brugeren logges ud"
@@ -2972,8 +3010,8 @@ msgstr "Du kan udelukke deres konto i fremtiden hvis det bliver nødvendigt."
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr "Du kan fjerne udelukkelse af deres konto i fremtiden. Deres data forbliver intakte."
-msgid "AdminUsers|You cannot remove your own admin rights."
-msgstr "Du kan ikke fjerne dine egne administratorrettigheder."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "Du skal overføre ejerskab eller slette de grupper som ejes af brugeren inden du kan slette dens konto"
@@ -3533,22 +3571,13 @@ msgstr "Tillad projekter i gruppen at bruge Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr "Tillad offentlig adgang til pipelines og jobdetaljer, herunder outputlogge og artefakter."
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Tillad anmodninger til det lokale netværk fra hooks og tjenester."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Tillad anmodninger til det lokale netværk fra systemhooks"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Tillad anmodninger til det lokale netværk fra webhooks og tjenester"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Tillad undergrupper at indstille deres egne regler for totrinsgodkendelse"
msgid "Allow this key to push to this repository"
msgstr "Tillad nøglen at bruge push til depotet"
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Der er opstået en fejl"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Der opstod en fejl ved tilføjelse af et udkast til tråden."
@@ -3809,18 +3835,15 @@ msgstr "Der opstod en fejl under hentning af jobbene."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Der opstod en fejl under hentning af den seneste pipeline."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Der opstod en fejl under hentning af udgivelserne. Prøv venligst igen."
msgid "An error occurred while fetching this tab."
msgstr "Der opstod en fejl under hentning af fanebladet."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Der opstod en fejl under generering af et brugernavn. Prøv venligst igen."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "Der opstod en fejl under hentning af autofuldførdata. Opdater venligst siden og prøv igen."
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "Der opstod en fejl under hentning af filer for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Tilføj godkendere"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr "Alle skannere"
@@ -4407,9 +4427,6 @@ msgstr "Godkendertype"
msgid "ApprovalRule|Approvers"
msgstr "Godkendere"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Eksempler: kvalitetssikring, sikkerhed."
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr "Sikkerhedsskannere"
msgid "ApprovalRule|Select All"
msgstr "Vælg alle"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Vælg skannere"
@@ -4482,7 +4502,7 @@ msgstr "Alvorlighedsniveauer"
msgid "ApprovalRule|Target branch"
msgstr "MÃ¥lgren"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,23 +4514,29 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Godkendelsesindstillinger for sammenlægningsanmodning er blevet opdateret."
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr "Forhindr godkendelse af forfatter."
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "Forhindr godkendelse af brugere som tilføjer commits."
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "Forhindr redigering af godkendelsesregler i sammenlægningsanmodninger."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Forhindr redigering af godkendelsesregler i projekter og sammenlægningsanmodninger."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "Fjern alle godkendelser når der tilføjes commits til kildegrenen."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
-msgstr "Kræv brugeradgangskode for at godkende."
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr "Der opstod en fejl under indlæsning af godkendelsesindstillinger for sammenlægningsanmodning."
@@ -4623,6 +4649,9 @@ msgstr "Er du sikker på, at du vil afarkivere projektet?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr "Er du sikker på, at du vil %{action} %{name}?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr "Er du sikker på, at du forsøge at sammenlægge?"
@@ -4715,9 +4744,6 @@ msgstr "Er du sikker på, at du vil fjerne identiteten?"
msgid "Are you sure you want to remove this list?"
msgstr "Er du sikker på, at du vil fjerne listen?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Er du sikker på, at du vil nulstille SCIM-tokenen? SCIM-provisionering vil stoppe med at virke indtil den nye token er opdateret."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Er du sikker på, at du vil nulstille tokenen til sundhedstjek?"
@@ -4802,7 +4828,7 @@ msgstr "Spørg igen senere"
msgid "Ask someone with write access to resolve it."
msgstr "Spørg nogen med skriveadgang om at løse den."
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "Avataren fjernes. Er du sikker?"
msgid "Average per day: %{average}"
msgstr "Gennemsnit pr. dag: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr "Belønning tilføjet"
@@ -5376,6 +5405,9 @@ msgstr "Brugeren med API-adgang til Bamboo-serveren."
msgid "Based on"
msgstr "Baseret på"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Nedenunder finder du alle de grupper, som er offentlige."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ msgstr "%{group_name} bruger i øjeblikket %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name}, du bruger i øjeblikket %{plan_name}."
-msgid "BillingPlans|Compare all plans"
-msgstr "Sammenlign alle planer"
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Tillykke, din gratis prøveperiode er aktiveret."
@@ -5457,9 +5489,6 @@ msgstr "Gruppen bruger den plan som er tilknyttet med dens forældergruppe."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Besøg opkrævningsafsnittet i vores %{parent_billing_page_link} for at håndtere planen til gruppen."
-msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
-msgstr "Opgrader til GitLab %{planNameForUpgrade}"
-
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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr "En e-mailadresse er kun synlig for brugere med offentlige e-mails."
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Bitbucket-import"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Blokér bruger"
@@ -5931,18 +5969,12 @@ msgstr "Slet sammenlagte grene"
msgid "Branches|Delete protected branch"
msgstr "Slet beskyttet gren"
-msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr "Slet beskyttet gren '%{branch_name}'?"
-
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
msgstr "Slet beskyttet gren. Er du HELT SIKKER?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
msgstr "Sletning af grenen %{strongStart}%{branchName}%{strongEnd} kan ikke fortrydes. Er du sikker?"
-msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "Sletning af grenen '%{branch_name}' kan ikke fortrydes. Er du sikker?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Sletning af de sammenlagte grene kan ikke fortrydes. Er du sikker?"
@@ -5958,9 +5990,6 @@ msgstr "Ny gren"
msgid "Branches|No branches to show"
msgstr "Ingen grene at vise"
-msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr "Når du bekræfter og trykker på %{delete_protected_branch}, så kan det ikke fortrydes eller gendannes."
-
msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
msgstr "Når du bekræfter og trykker på %{strongStart}%{buttonText}%{strongEnd}, så kan det ikke fortrydes eller gendannes."
@@ -6009,15 +6038,6 @@ 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 "Grenen er ikke blevet sammenlagt ind i %{default_branch}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Overvej at sammenlægge grenen inden den slettes for at forhindre tab af data."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-msgstr "Skriv %{branch_name_confirmation} for at bekræfte:"
-
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "For at forkaste de lokale ændringer og overskrive grenen med upstream-versionen skal du slette den her og vælge 'Opdater nu' ovenover."
@@ -6036,9 +6056,6 @@ msgstr "Du er ved at slette %{strongStart}%{branchName}%{strongEnd} parmanent."
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr "Du er ved at slette den beskyttede gren %{strongStart}%{branchName}%{strongEnd} permanent."
-msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "Du er ved at slette den beskyttede gren %{branch_name} permanent."
-
msgid "Branches|diverged from upstream"
msgstr "afviget fra upstream"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Som standard vil alle projekter og grupper bruge den globale underretningsindstilling."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "af"
@@ -6299,9 +6325,21 @@ msgstr "Udgivelsesstatistik"
msgid "CICDAnalytics|Releases"
msgstr "Udgivelser"
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr "Noget gik galt under hentning af udgivelsesstatistik"
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Kan ikke sammenlægges automatisk"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Kan ikke oprette misbrugsrapporten. Brugeren er blevet slettet."
@@ -6915,6 +6956,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Cherry-pick sammenlægningsanmodningen"
msgid "Child"
msgstr "Barn"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "Underepicen findes ikke."
@@ -7392,15 +7439,6 @@ msgstr "Klik for at skjule"
msgid "Click to reveal"
msgstr "Klik for at vise"
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr "Klientgodkendelsesnøgle"
-
-msgid "Client authentication key password"
-msgstr "Adgangskode til klientgodkendelsesnøgle"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr "Lukket: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Klynge"
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,8 +7610,8 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr "Der opstod en fejl under indlæsning af dine GitLab-agenter"
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr "Der opstod en fejl under indlæsning af din agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr "Aldrig"
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr "Registreringsagent"
msgid "ClusterAgents|Registration token"
msgstr "Registreringstoken"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr "Agenten har ingen tokens"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr "Commit (ved redigering af commit-meddelelse)"
msgid "Commit Message"
msgstr "Commit-meddelelse"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr "Commit ændringer"
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Komponent"
@@ -8995,6 +9066,12 @@ msgstr "Konfigurer %{repository_checks_link_start}depottjek%{link_end} og %{hous
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr "Konfigurer afhængighedsskanning i `.gitlab-ci.yml` med den GitLab-håndterede skabelon. Du kan [tilføje variabeltilsidesættelser](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) for at tilpasse indstillinger for afhængighedsskanning."
@@ -9040,12 +9117,15 @@ msgstr "Konfigurer tracing"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Konfigurer en %{codeStart}.gitlab-webide.yml%{codeEnd}-fil i mappen %{codeStart}.gitlab%{codeEnd} for at komme i gang med webterminal. %{helpStart}Lær mere%{helpEnd}."
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr "Konfigurer avancerede tilladelser, Large File Storage og totrinsgodkendelsesindstillinger."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
+msgstr ""
msgid "Configure existing installation"
msgstr "Konfigurer eksisterende installation"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Konfigurer måden en bruger opretter en ny konto."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Bekræft"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Bekræft ny adgangskode"
@@ -9637,8 +9723,8 @@ msgstr "Styr e-mails som er linket til din konto"
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
-msgstr "Styr om der vises tilbud fra tredjepart i GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
msgstr ""
@@ -9778,9 +9864,24 @@ msgstr "Handlinger"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr "Korpusnavn"
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr "Sidste job:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr "Ny upload"
@@ -9868,6 +9966,9 @@ msgstr "Kunne ikke tegne linjerne for jobrelationer"
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr "Kunne ikke hente regelsæt fordi eksisterende regelsæt-YAML er ugyldig"
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "Kunne ikke finde design."
@@ -9895,13 +9996,16 @@ msgstr "Kunne ikke fjerne udløseren."
msgid "Could not restore the group"
msgstr "Kunne ikke gendanne gruppen"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "Kunne ikke tilbagekalde efterligningstokenen %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "Kunne ikke tilbagekalde den personlige adgangstoken %{personal_access_token_name}."
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr "Opret problemstilling for at løse alle tråde"
msgid "Create iteration"
msgstr "Opret gennemløb"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "Opret liste"
@@ -10303,6 +10410,9 @@ msgstr "Oprettet af mig"
msgid "Created by:"
msgstr "Oprettet af:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "Oprettelsesdato"
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Dato"
@@ -10778,10 +10894,10 @@ msgstr "Dage fra sammenlægning til udsendelse"
msgid "DORA4Metrics|Deployment frequency"
msgstr "Udsendelseshyppighed"
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr "Kunne ikke oprette skannerprofilen. Prøv venligst igen."
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr "Kunne ikke oprette webstedsprofilen. Prøv venligst igen."
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr "Kunne ikke slette gemt skanning. Opdater venligst siden eller prøv igen senere."
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr "Kunne ikke slette gemte skanninger:"
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr "Kunne ikke slette skannerprofil. Opdater venligst siden eller prøv igen senere."
@@ -10889,9 +10999,6 @@ msgstr "Kunne ikke slette webstedsprofil. Opdater venligst siden eller prøv ige
msgid "DastProfiles|Could not delete site profiles:"
msgstr "Kunne ikke slette webstedsprofiler:"
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr "Kunne ikke hente gemte skanninger. Opdater venligst siden eller prøv igen senere."
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "Kunne ikke hente skannerprofiler. Opdater venligst siden eller prøv igen senere."
@@ -10904,9 +11011,6 @@ msgstr "Kunne ikke opdatere skannerprofilen. Prøv venligst igen."
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "Kunne ikke opdatere webstedsprofilen. Prøv venligst igen."
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr "Fejlfindingsmeddelelser"
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr "Kør skanning"
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr "Gem profil"
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr "Skan"
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr "Skannerprofiler"
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr "Planlæg"
-
msgid "DastProfiles|Select branch"
msgstr "Vælg gren"
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr "MÃ¥l"
-
msgid "DastProfiles|Target URL"
msgstr "MÃ¥l-URL"
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Udsendelser"
msgid "Deploy Keys"
msgstr "Udsendelsesnøgler"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr "Udsendelsesfrysninger"
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Udsend til ..."
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "annulleret"
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Start en gratis prøveperiode"
@@ -12622,7 +12738,7 @@ msgstr "Vis kilde"
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr "Rediger kommentar"
msgid "Edit Deploy Key"
msgstr "Rediger udsendelsesnøgle"
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr "Vi kunne ikke finde ud af hvilken bruger der tilhører e-mailen. Opret v
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "Vi kunne ikke finde projektet. Tjek venligst om der er nogle stavefejl."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Du har ikke tilladelse til at udføre handlingen. Hvis du mener det er en fejl, så kontakt en medarbejder."
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr "Aktivér automatisk depothusarbejde"
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Aktivér vedligeholdelsestilstand"
@@ -13279,6 +13398,12 @@ msgstr "Aktivér reCAPTCHA for indlogning."
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr "Slutter"
msgid "Ends: %{endsAt}"
msgstr "Slutter: %{endsAt}"
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr "Indtast din Bitbucket-server-URL og personlige adgangstoken nedenunder"
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "Indtast URL'en til din Phabricator-server og personlige adgangstoken nedenunder"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Indtast sammenlægningsanmodnings-URL'er"
@@ -13683,6 +13808,9 @@ msgstr "Stop miljø"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "Der opstod en fejl ved hentning af loggene. Prøv venligst igen."
@@ -13710,6 +13838,9 @@ msgstr "af %{avatar}"
msgid "Environments|protected"
msgstr "beskyttet"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Epic"
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr "Eksporterede krav"
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr "Eksternt id"
@@ -14507,15 +14635,9 @@ msgstr "Ekstern URL"
msgid "External User:"
msgstr "Ekstern bruger:"
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr "URL for eksternt lager"
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,11 +14781,8 @@ msgstr "Kunne ikke oprette framework"
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr "Kunne ikke oprette sammenlægningsanmodning. Prøv venligst igen."
-
-msgid "Failed to create new project access token: %{token_response_message}"
-msgstr "Kunne ikke oprette ny projektadgangstoken: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
+msgstr ""
msgid "Failed to create repository"
msgstr "Kunne ikke oprette depot"
@@ -15054,14 +15221,6 @@ msgstr "Bruger-id'er"
msgid "FeatureFlag|User List"
msgstr "Brugerliste"
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Feb."
@@ -15149,12 +15308,6 @@ msgstr "Filtrér"
msgid "Filter by"
msgstr "Filtrér efter"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrér efter %{issuable_type} som i øjeblikket er lukket."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr "Filtrér efter %{issuable_type} som i øjeblikket er åbne."
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr "Filtrér efter %{page_context_word} som i øjeblikket er åbne."
@@ -15479,6 +15632,9 @@ msgstr "Fandt fejl i din %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Fandt fejl i din .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr "Framework slettet"
@@ -15554,6 +15710,9 @@ msgstr "Generelle indstillinger"
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Generer nøgle"
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo-knudepunkter"
-
msgid "Geo Replication"
msgstr "Geo-replikation"
msgid "Geo Settings"
msgstr "Geoindstillinger"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr "Geo-websteder"
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr "Tilføj websted"
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr "Alle %{replicable_name}"
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr "Matcher ikke den primære lagerkonfiguration"
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr "Ingen tilgængelige replikationspladser"
-msgid "Geo|Node name can't be blank"
-msgstr "Knudepunktsnavn må ikke være tomt"
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr "Knudepunktsnavn skal være fra 1 til 255 tegn"
-
msgid "Geo|Not synced yet"
msgstr "Ikke synkroniseret endnu"
@@ -15788,6 +15950,9 @@ msgstr "Intet at verificere"
msgid "Geo|Offline"
msgstr "Offline"
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Afventende synkronisering"
@@ -15821,17 +15986,20 @@ msgstr "Download igen"
msgid "Geo|Remove"
msgstr "Fjern"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
-msgstr "Fjern knudepunkt"
+msgid "Geo|Remove site"
+msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
-msgstr "Fjernelse af et Geo-knudepunkt stopper synkroniseringen til og fra knudepunktet. Er du sikker?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
+msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
msgstr ""
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr "Replikationsdetaljer"
-msgid "Geo|Replication details"
-msgstr "Replikationsdetaljer"
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr "Sekundært websted"
msgid "Geo|Selective (%{syncLabel})"
msgstr "Selektiv (%{syncLabel})"
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,11 +16100,11 @@ msgstr "Webstedet er i øjeblikket %{minutes_behind} bagefter det primære webst
msgid "Geo|There are no %{replicable_type} to show"
msgstr "Der er ingen %{replicable_type} at vise"
-msgid "Geo|There was an error deleting the Geo Node"
-msgstr "Der opstod en fejl under sletning af Geo-knudepunktet"
+msgid "Geo|There was an error deleting the Geo Site"
+msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
-msgstr "Der opstod en fejl under hentning af Geo-knudepunkterne"
+msgid "Geo|There was an error fetching the Geo Sites"
+msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "Det vil synkronisere alle %{replicableType} igen. Det kan tage noget tid af fuldføre. Er du sikker på, at du vil fortsætte?"
@@ -16010,6 +16181,9 @@ msgstr "sekundær"
msgid "Get a free instance review"
msgstr "FÃ¥ en gratis instanskontrol"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr "FÃ¥ et abonnement med support"
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr "GitLab-eksport"
-msgid "GitLab for Slack"
-msgstr "GitLab for Slack"
-
msgid "GitLab group: %{source_link}"
msgstr "GitLab-gruppe: %{source_link}"
@@ -16160,6 +16331,9 @@ msgstr "GitLab er open source-software til at samarbejde om kode."
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "GitLab-medlem eller e-mailadresse"
@@ -16340,6 +16514,9 @@ msgstr "Gitpod-URL"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr "Gå til forælder"
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr "GÃ¥ til forrige side"
@@ -16646,6 +16826,9 @@ msgstr "Gruppen %{group_name} blev planlagt til sletning."
msgid "Group %{group_name} was successfully created."
msgstr "Gruppen %{group_name} blev oprettet."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr "Gruppe-URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr "Gruppeprogram: %{name}"
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr "Gruppér job efter"
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr "Gruppemedlemmer"
@@ -16754,6 +16937,9 @@ msgstr "Gruppenavigation"
msgid "Group overview content"
msgstr "Indhold for gruppeoversigt"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr "Gruppeprojekter"
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr "SCIM-token"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Din SCIM-token"
-
msgid "GroupSAML|as %{access_level}"
msgstr "som %{access_level}"
@@ -17078,7 +17252,10 @@ msgstr "Søg efter grupper"
msgid "GroupSelect|Select a group"
msgstr "Vælg en gruppe"
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr "Deaktivér e-mail-underretninger"
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr "Aktivér forsinket sletning af projekt"
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "Pipelineindstillinger blev opdateret for gruppen"
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Indstillingen anvendes på %{ancestor_group}. Du kan tilsidesætte indst
msgid "GroupSettings|Transfer group"
msgstr "Overfør gruppe"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr "Udfyld venligst din personlige adgangstoken."
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "Skjul værdier"
msgid "Hide values"
msgstr "Skjul værdier"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr "Husarbejde"
msgid "Housekeeping successfully started"
msgstr "Husarbejde startet"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "Husarbejde, eksport, sti, overfør, fjern, arkivér."
-
msgid "How do I configure Akismet?"
msgstr "Hvordan konfigurerer jeg Akismet?"
@@ -17685,9 +17880,6 @@ msgstr "Hvordan bruger jeg er webterminal?"
msgid "How do I use file templates?"
msgstr "Hvordan bruger jeg filskabeloner?"
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "Jeg accepterer %{terms_link}"
msgid "I forgot my password"
msgstr "Jeg har glemt min adgangskode"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr "Jeg vil udforske GitLab for at se om det er værd at skifte til"
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr "Identiteter"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr "Meget svært"
msgid "InProductMarketing|Very easy"
msgstr "Meget nemt"
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr "Hændelse"
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr "Tilføj en integrering"
msgid "Integrations|Add namespace"
msgstr "Tilføj navnerum"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Alle detaljer"
@@ -19043,9 +19253,6 @@ msgstr "Der opstod en fejl under indlæsning af projekter med tilpassede indstil
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr "Browserbegrænsninger"
-
msgid "Integrations|Comment detail:"
msgstr "Kommentardetalje:"
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr "Hold dine PHP-afhængigheder opdateret på Packagist."
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr "Link navnerum"
@@ -19133,9 +19343,6 @@ msgstr "Ingen tilgængelige navnerum."
msgid "Integrations|No linked namespaces"
msgstr "Ingen linkede navnerum"
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr "Bemærk: integreringen virker kun med kontoer på GitLab.com (SaaS)."
-
msgid "Integrations|Projects using custom settings"
msgstr "Projekter som bruger tilpassede indstillinger"
@@ -19172,6 +19379,9 @@ msgstr "Send underretninger om projektbegivenheder til Unify Circuit."
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr "Log ind og tilføj navnerum"
@@ -19181,6 +19391,9 @@ msgstr "Standard"
msgid "Integrations|There are no projects using custom settings"
msgstr "Der er ingen projekter som bruger tilpassede indstillinger"
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr "Integreringen og nedarvede projekter blev nulstillet."
@@ -19241,7 +19454,7 @@ msgstr "Interne - projektet kan tilgås af brugere som er logget ind, undtagen e
msgid "Internal URL (optional)"
msgstr "Intern URL (valgfrit)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr "Licensfil"
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr "Licensoversigt"
@@ -21384,9 +21600,6 @@ msgstr "Indlæser ..."
msgid "Loading…"
msgstr "Indlæser …"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Lokalisering"
@@ -21402,6 +21615,9 @@ msgstr "LÃ¥s"
msgid "Lock %{issuableDisplayName}"
msgstr "LÃ¥s %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr "Låse gør det muligt at låse en bestemte fil eller mappe."
msgid "Locks the discussion."
msgstr "LÃ¥ser debatten."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "Sammenlæg når pipeline lykkes"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "Commit til kildegren"
@@ -23053,9 +23317,6 @@ msgstr "MÃ¥neder"
msgid "More Information"
msgstr "Mere information"
-msgid "More Slack commands"
-msgstr "Flere Slack-kommandoer"
-
msgid "More actions"
msgstr "Flere handlinger"
@@ -23077,9 +23338,6 @@ msgstr "Der findes mere information|her"
msgid "More information."
msgstr "Mere information."
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr "%{strongOpen}alle%{strongClose} pods"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ".yaml"
-
msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml-tilstand"
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr "Regel"
-
msgid "NetworkPolicies|Rule mode"
msgstr "Regeltilstand"
@@ -23466,9 +23718,6 @@ msgstr "Noget gik galt. Kunne ikke hente regelsæt"
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr "Trafik som ikke matcher nogen regel vil blive blokeret."
-
msgid "NetworkPolicies|all DNS names"
msgstr "Alle DNS-navne"
@@ -23984,6 +24233,9 @@ msgstr "Ingen milepæl"
msgid "No milestones to show"
msgstr "Ingen milepæle at vise"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr "Ingen profiler fundet"
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr "Ingen projekter fundet"
@@ -24077,8 +24332,8 @@ msgstr "Ingen sårbarheder tilstede"
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
-msgstr "Ingen webhooks fundet, tilføj en i formularen ovenover."
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr "Vores team er blevet underrettet. Prøv venligst igen."
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr "Indsæt projektsti (f.eks. gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr "Indsæt din offentlige SSH-nøgle som typisk findes i filen '~/.ssh/id_ed25519.pub' eller '~/.ssh/id_rsa.pub' og begynder med 'ssh-ed25519' eller 'ssh-rsa'. Indsæt ikke din private SSH-nøgle da det kan kompromittere din identitet."
-
msgid "Patch to apply"
msgstr "Patch som skal anvendes"
@@ -25744,6 +26017,9 @@ msgstr "objekt"
msgid "PerformanceBar|wall"
msgstr "væg"
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr "Periode i sekunder"
@@ -25762,7 +26038,7 @@ msgstr "Tilladelser"
msgid "Permissions Help"
msgstr "Hjælp for tilladelser"
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Pipelinediagrammer"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr "Tilføj et kodekvalitetsjob"
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "Er du sikker på, at du vil køre pipelinen?"
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Byg med selvtillid"
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,11 +26497,29 @@ msgstr "Vis sammenlagt YAML"
msgid "Pipelines|Visualize"
msgstr "Visualiser"
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr "ugyldig"
-msgid "Pipelines|parent"
-msgstr "forælder"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "Handlinger"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr "Plan:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26422,6 +26719,12 @@ msgstr "Afspil alle manuelt"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Venligst %{link_to_register} eller %{link_to_sign_in} for at kommentere"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr "Præferencer for tid"
msgid "Preferences|Use relative times"
msgstr "Brug relative tidspunkter"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Forrige"
@@ -27001,6 +27307,9 @@ msgstr "Beskæring af avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Avataren fjernes. Er du sikker?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr "By, land"
msgid "Profiles|Clear status"
msgstr "Ryd status"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Klik på et ikon for at aktivere indlogning med en af følgende tjenester"
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr "Private SSH-nøgler som er synlige offentligt kan kompromittere dit syst
msgid "Profiles|Remove avatar"
msgstr "Fjern avatar"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Indstil nyt profilbillede"
@@ -27250,9 +27559,6 @@ msgstr "Totrinsgodkendelse"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Skriv din %{confirmationValue} for at bekræfte:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Begynder typisk med \"ssh-ed25519 …\" eller \"ssh-rsa …\""
-
msgid "Profiles|Update profile settings"
msgstr "Opdater profilindstillinger"
@@ -27775,10 +28081,13 @@ msgstr "Afkrydsningsboksen er som standard synlig og tilvalgt."
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr "Afkrydsningsboksen er som standard synlig og fravalgt."
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr "Globalt"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Internt"
@@ -27901,6 +28216,9 @@ msgstr "Sammenlægningsanmodninger"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr "Overfør projekt"
@@ -28051,7 +28366,7 @@ msgstr "Brugere kan anmode om adgang"
msgid "ProjectSettings|View and edit files in this project."
msgstr "Vis og rediger filer i projektet."
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr "Hvad er badges?"
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr "Offentlige pipelines"
@@ -28867,7 +29179,7 @@ msgstr "Køb flere minutter"
msgid "Purchase more storage"
msgstr "Køb mere lager"
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr "Rebase kildegren"
msgid "Rebase source branch on the target branch."
msgstr "Rebase kildegren på målgrenen."
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr "Recaptcha verificeret?"
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "Reducer projektets synlighed"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "Reducer projektets synlighed?"
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr "Anmodninger pr. periode"
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr "Anmodninger til domænerne/adresserne på det lokale netværk vil blive tilladt når lokale anmodninger fra hooks og tjenester ikke er tilladt. IP-områder såsom 1:0:0:0:0:0:0:0/124 eller 127.0.0.0/28 understøttes. Jokertegn for domæner understøttes ikke i øjeblikket. Brug komma, semikolon eller linjeskift til at adskille flere indslag. Tilladelseslisten kan højst indeholde 1000 indslag. Domæner skal bruge IDNA-kodning. F.eks.: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr "Kræves i projektet."
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Kravet %{reference} er blevet tilføjet"
@@ -30245,9 +30574,6 @@ msgstr "Løst af"
msgid "Resolved by %{name}"
msgstr "Løst af %{name}"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr "Svar"
@@ -30314,7 +30640,7 @@ msgstr "Genoptag"
msgid "Resync"
msgstr "Synkroniser igen"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,15 +30740,15 @@ msgstr "Tilbagekald"
msgid "Revoked"
msgstr "Tilbagekaldt"
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "Tilbagekaldt efterligningstoken %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr "Tilbagekaldte projektadgangstokenen %{project_access_token_name}!"
-
msgid "RightSidebar|Copy email address"
msgstr "Kopiér e-mailadresse"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Vejkort"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Rolle"
@@ -30528,6 +30857,9 @@ msgstr "Der er opstået en fejl under hentning af instruktioner"
msgid "Runners|Architecture"
msgstr "Arkitektur"
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr "Udsend GitLab Runner i AWS"
msgid "Runners|Description"
msgstr "Beskrivelse"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr "Download og installer programfil"
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr "IP-adresse"
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr "Offline"
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr "Online"
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revision"
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Runnere"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
-msgstr "Runnere i gruppen: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
+msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr "Noget fik galt under hentning af mærkatforslagene"
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr "Runneren er tilknyttet et eller flere projekter."
-
msgid "Runners|This runner is associated with specific projects."
msgstr "Runneren er tilknyttet med bestemte projekter."
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr "SVG-illustration"
-
msgid "Satisfied"
msgstr "Opfyldt"
@@ -31026,9 +31367,6 @@ msgstr "Søg"
msgid "Search GitLab"
msgstr "Søg på GitLab"
-msgid "Search Jira issues"
-msgstr "Søg efter Jira-problemstillinger"
-
msgid "Search a group"
msgstr "Søg efter en gruppe"
@@ -31330,7 +31668,7 @@ msgstr "Lær mere om sårbarhedstjek"
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr "%{branches} %{plural}"
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr "Seneste skanning"
@@ -31534,21 +31878,30 @@ msgstr "Kun ejere kan opdatere sikkerhedsregelsætprojekt"
msgid "SecurityOrchestration|Policies"
msgstr "Regelsæt"
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr "Regelsætbeskrivelse"
msgid "SecurityOrchestration|Policy editor"
msgstr "Regelsæteditor"
-msgid "SecurityOrchestration|Policy preview"
-msgstr ""
-
msgid "SecurityOrchestration|Policy status"
msgstr "Regelsætstatus"
+msgid "SecurityOrchestration|Policy summary"
+msgstr ""
+
msgid "SecurityOrchestration|Policy type"
msgstr "Regelsættype"
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr "Regel"
@@ -31558,12 +31911,21 @@ msgstr "Regler"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr "Beklager, dit filter gav ingen resultater."
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr "vis resultater"
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr "+%{count} mere"
@@ -31621,6 +32037,9 @@ msgstr "Miljøer"
msgid "SecurityPolicies|Policy type"
msgstr "Regelsættype"
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} og %{secondProject}"
@@ -31942,9 +32361,6 @@ msgstr "Vælg arkivformat"
msgid "Select Git revision"
msgstr "Vælg Git-revision"
-msgid "Select GitLab project to link with your Slack team"
-msgstr "Vælg GitLab-projekt som skal linkes med dit Slack-team"
-
msgid "Select Page"
msgstr "Vælg side"
@@ -32332,8 +32748,8 @@ msgstr "Serviceskranke"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr "Serviceskranke giver personer mulighed for at oprette problemstillinger i din GitLab-instans uden deres egen brugerkonto. Det giver en unik e-mailadressen til slutbrugeren som kan bruges til at oprette problemstillinger i et projekt. Svar kan enten sendes gennem GitLab-grænsefladen eller med e-mail. Kun slutbrugere ser tråde via e-mail."
-msgid "Service URL"
-msgstr "Tjeneste-URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr "Aktivér serviceskranke"
@@ -32350,18 +32769,12 @@ msgstr "Kontakt venligst en administrator for at få hjælp med at opsætning se
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "Problemstillinger som er oprettet med e-mails fra serviceskranken vises her. Hver kommentar bliver en del af e-mail-samtalen."
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr "Serviceskranke er aktiveret men endnu ikke aktiv"
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr "Serviceskranke er ikke aktiveret"
msgid "ServiceDesk|Service Desk is not supported"
msgstr "Serviceskranke understøttes ikke"
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr "For at aktivere serviceskranke i instansen skal en instansadministrator først opsætte indgående e-mail."
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr "For at aktivere serviceskranke i instansen skal en instansadministrator først opsætte indgående e-mail."
@@ -32500,8 +32913,8 @@ msgstr "Opsæt CI/CD"
msgid "Set up Jira Integration"
msgstr "Opsæt Jira-integrering"
-msgid "Set up a %{type} Runner for a project"
-msgstr "Opsæt en %{type}-runner til et projekt"
+msgid "Set up a %{type} runner for a project"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr "Vis al aktivitet"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr "Vis alle problemstillinger."
@@ -32727,6 +33140,9 @@ msgstr "Vis arkiverede projekter"
msgid "Show archived projects only"
msgstr "Vis kun arkiverede projekter"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Vis kommando"
@@ -32739,9 +33155,6 @@ msgstr "Vis kommentarer til filen"
msgid "Show comments only"
msgstr "Vis kun kommentarer"
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr "Vis liste"
msgid "Show one file at a time"
msgstr "Vis én fil ad gangen"
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr "Vis listen lukket"
@@ -32806,7 +33222,7 @@ msgstr "Viser alle problemstillinger"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr "Log ud og tilmeld"
msgid "Sign up"
msgstr "Tilmeld"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "Tilmeldingen lykkedes! Bekræft venligst din e-mail for at logge ind."
@@ -33001,9 +33420,33 @@ msgstr "Slack-program"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr "Sender underretninger om projektbegivenheder til Slack-kanaler."
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Noget gik galt. Prøv venligst igen."
msgid "Something went wrong. Try again later."
msgstr "Noget gik galt. Prøv igen senere."
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr "Beklager, ingen projekter matchede din søgning"
@@ -33376,9 +33816,6 @@ msgstr "Sidste kontakt"
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr "Sidst opdateret"
-
msgid "SortOptions|Least popular"
msgstr "Mindst populær"
@@ -33712,6 +34149,9 @@ msgstr "Start sammenlægningstog"
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Start søgning"
@@ -33754,6 +34194,9 @@ msgstr "Starter: %{startsAt}"
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "Abonneret"
msgid "Subscribed to this %{quick_action_target}."
msgstr "Abonneret til denne %{quick_action_target}."
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr "Abonnerer til denne %{quick_action_target}."
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr "Tilføj sæder"
@@ -34204,9 +34671,6 @@ msgstr "Slutdato for prøveperiode"
msgid "SubscriptionTable|Trial start date"
msgstr "Startdato for prøveperiode"
-msgid "SubscriptionTable|Upgrade"
-msgstr "Opgrader"
-
msgid "SubscriptionTable|Usage"
msgstr "Forbrug"
@@ -34375,9 +34839,6 @@ msgstr "Opsummering/bemærkning"
msgid "Sunday"
msgstr "Søndag"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr "Aktivér abonnement"
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr "Start gratis prøveperiode"
msgid "SuperSonics|Subscription details"
msgstr "Abonnementsdetaljer"
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Support"
@@ -34750,6 +35229,9 @@ msgstr "MÃ¥lgren"
msgid "Target-Branch"
msgstr "MÃ¥lgren"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr "Opgave-id: %{elastic_task}"
@@ -34822,6 +35304,9 @@ msgstr "vilkår for tjeneste-aftale og privatlivspolitik"
msgid "Terms of Service and Privacy Policy"
msgstr "Vilkår for tjeneste og privatlivspolitik"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr "Terraform"
@@ -34992,6 +35477,9 @@ msgstr "Test"
msgid "Test Cases"
msgstr "Testsager"
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr "Det var det, godt gået!"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
-msgstr "Funktionen %{featureName} er del af din GitLab Ultimate-prøveperiode."
-
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr "URL'en skal begynde med http:// eller https://"
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr "Den seneste pipeline for sammenlægningsanmodnigen mislykkedes."
@@ -35498,9 +35977,6 @@ msgstr "Siden kunne ikke vises fordi den fik timeout."
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr "Forælderepicen er fortrolig og kan kun indeholde fortrolige epics og problemstillinger"
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr "Adgangskoden til Jenkins-serveren."
@@ -35516,9 +35992,6 @@ msgstr "Pipelinen blev ikke slettet"
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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr "Projektet kan tilgås af alle brugere som er logget ind undtagen eksterne brugere."
@@ -35888,8 +36361,8 @@ msgstr "Der opstod en fejl ved hentning af %{replicableType}"
msgid "There was an error fetching the Geo Settings"
msgstr "Der opstod en fejl ved hentning af Geo-indstillingerne"
-msgid "There was an error fetching the Node's Groups"
-msgstr "Der var en fejl ved hentning af knudepunktets grupper"
+msgid "There was an error fetching the Sites's Groups"
+msgstr ""
msgid "There was an error fetching the deploy freezes."
msgstr "Der opstod en fejl under hentning af udsendelsesfrysningerne."
@@ -35939,8 +36412,8 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr "Der opstod en fejl ved indhentning af Jira-brugerne."
-msgid "There was an error saving this Geo Node."
-msgstr "Der opstod en fejl under gemning af Geo-knudepunktet."
+msgid "There was an error saving this Geo Site"
+msgstr ""
msgid "There was an error saving your changes."
msgstr "Der opstod en fejl ved gemning af dine ændringer."
@@ -36023,9 +36496,6 @@ msgstr "De sendes til %{email} i en vedhæftning når det er færdigt."
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr "Tilbud fra tredjepart"
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "%{issuableDisplayName} er låst. Kun projektmedlemmer kan kommentere."
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Epicen findes ikke eller du har ikke tilstrækkelig tilladelse."
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr "Funktionen er en del af din GitLab Ultimate-prøveperiode."
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr "Gruppen er blevet planlagt til permanent sletning %{date}"
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr "Gruppen er linket til et abonnement"
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr "Pipelinen blev udløst af en planlægning."
msgid "This project"
msgstr "Projektet"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr "Projektet er arkiveret og kan ikke kommenteres på."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Projektet er licenseret under %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr "Projektet håndterer sine afhængigheder med %{strong_start}%{manager_name}%{strong_end}"
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Indstillingen kan tilsidesættes i hvert projekt."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "Abonnementet er til"
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr "Tid i sekunder"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Tid i sekunder som GitLab vil vente på svar fra den eksterne tjeneste. Når tjenesten ikke svarer i tide vil adgangen blive nægtet."
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "For at tilføje en SSH-nøgle skal du %{generate_link_start}generere en%{link_end} eller bruge en %{existing_link_start}eksisterende nøgle%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr "Indsæt venligst følgende link i din browser for at fjerne abonnering f
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr "Gøremålsliste"
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "Spor tid med hurtighandlinger"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr "Virksomhedsnavn"
@@ -37490,15 +37963,9 @@ msgstr "Land"
msgid "Trial|Dismiss"
msgstr "Afskedig"
-msgid "Trial|First name"
-msgstr "Fornavn"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr "GitLab Ultimate-prøveperiode (valgfrit)"
-msgid "Trial|Last name"
-msgstr "Efternavn"
-
msgid "Trial|Number of employees"
msgstr "Antal ansatte"
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr "Udløsere"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "Fejlsøg og overvåg dit program med tracing"
@@ -38084,6 +38557,9 @@ msgstr "Opdateret"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Opdateret %{updated_at} af %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "Opdateringer"
@@ -38105,6 +38581,9 @@ msgstr "Opgrader din plan"
msgid "Upload"
msgstr "Upload"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Upload CSV-fil"
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr "Version %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
msgstr "Version %{versionNumber} (seneste)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "Vis dokumentation"
@@ -39218,6 +39712,9 @@ msgstr[1] "Vis offentlige GPG-nøgler"
msgid "View replaced file @ "
msgstr "Vis erstattet fil @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr "Vis indstilling"
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "Yderligere information"
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr "Download"
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr "Billede"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Links"
@@ -39524,6 +40036,9 @@ msgstr "Navnerum"
msgid "Vulnerability|Project"
msgstr "Projekt"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Værktøj"
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "ADVARSEL:"
@@ -39743,6 +40270,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr "Hjælp for webhooks"
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "Kommentarer"
@@ -39785,6 +40354,9 @@ msgstr "Hændelser for pipeline"
msgid "Webhooks|Push events"
msgstr "Hændelser for push"
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr "Hændelser for udgivelser"
@@ -39815,55 +40387,10 @@ msgstr "Udløser"
msgid "Webhooks|URL"
msgstr "URL"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr "URL'en udløses når en fortrolig problemstilling oprettes, opdateres, lukkes eller genåbnes"
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr "URL'en udløses når et funktionsflag slås til eller fra"
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr "URL'en udløses når et gruppemedlem oprettes, opdateres eller fjernes"
-
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr "URL'en udløses når en sammenlægningsanmodning oprettes, opdateres eller sammenlægges"
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr "URL'en udløses når en udgivelse oprettes eller opdateres"
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr "URL'en udløses når en undergruppe oprettes eller fjernes"
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr "URL'en udløses når en wikiside oprettes eller opdateres"
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr "URL'en udløses når en problemstilling oprettes, opdateres, lukkes eller genåbnes"
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr "URL'en udløses når nogen tilføjer en kommentar"
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr "URL'en udløses når nogen tilføjer en kommentar til en fortrolig problemstilling"
-
-msgid "Webhooks|URL is triggered when the job status changes"
-msgstr "URL'en udløses når jobstatussen ændres"
-
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr "URL'en udløses når pipelinestatussen ændres"
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr "URL'en skal være procentkodet hvis det er nødvendigt."
-
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr "Igangværende arbejde (åbne og tildelte)"
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr "Du er ved at fjerne %{group_name}. Det sletter også alle dens undergrup
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "Du er ved at fjerne forgreningsrelationen fra %{project_full_name}. Er du HELT sikker?"
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr "Du er ved at overføre %{project_full_name} til et andet navnerum. Er du HELT SIKKER?"
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr "Du kan også teste din %{gitlab_ci_yml} i %{lint_link_start}CI Lint%{lin
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Du kan også uploade eksisterende filer fra din computer ved at bruge instruktionerne nedenunder."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Du kan let bidrage til dem ved at anmode om at deltage i grupperne."
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Du har ikke tilladelse til at forlade denne %{namespaceType}."
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "Du har ikke tilladelse til at køre webterminalen. Kontakt venligst en projektadministrator."
@@ -40737,6 +41285,9 @@ msgstr "Du har ikke tilstrækkelige tilladelser til at oprette en HTTP-integreri
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr "Du har ikke tilstrækkelige tilladelser til at oprette en vagtplan for projektet"
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr "Du har ikke tilstrækkelige tilladelser til at fjerne en vagtplansrotation fra projektet"
@@ -40776,7 +41327,7 @@ msgstr "Du har nået din projektgrænse"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr "Du har opsat 2FA til din konto! Hvis du mister adgang til din 2FA-enhed, så kan du bruge dine gendannelseskoder til at få adgang til din konto. Ellers kan du, hvis du uploader en SSH-nøgle, %{anchorOpen}bruge nøglen til at generere yderligere gendannelseskoder%{anchorClose}."
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr "Du forlod \"%{membershipable_human_name}\" %{source_type}."
msgid "You may close the milestone now."
msgstr "Du kan nu lukke milepælen."
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,8 +41726,8 @@ msgstr "Dit navn"
msgid "Your new %{type}"
msgstr "Din nye %{type}"
-msgid "Your new SCIM token"
-msgstr "Din nye SCIM-token"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr "Din nye kommentar"
@@ -41181,9 +41735,6 @@ msgstr "Din nye kommentar"
msgid "Your new personal access token has been created."
msgstr "Din nye personlige adgangstoken er blevet oprettet."
-msgid "Your new project access token has been created."
-msgstr "Din nye projektadgangstoken er blevet oprettet."
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "Dit abonnement udløb!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr "godkendt af: "
@@ -41463,6 +42022,9 @@ msgstr "kan ikke ændres hvis et personligt projekt har beholderregistermærkate
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr "kan ikke aktiveres fordi forældergruppe ikke tillader det"
@@ -41835,6 +42397,9 @@ msgstr "committed"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr "oprettet %{issuable_created} af %{author}"
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "oprettet %{timeAgoString} af %{email} via %{user}"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "oprettet %{timeAgoString} af %{user}"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "oprettet %{timeAgoString} af %{user} i Jira"
-
msgid "created %{timeAgo}"
msgstr "oprettet %{timeAgo}"
@@ -41995,6 +42554,9 @@ msgstr "mislykket"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr "frontmatter"
msgid "group"
msgstr "gruppe"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "gruppemedlemmer"
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr "er ikke tilladt eftersom gruppen ikke er topniveaugruppe."
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr "indlæser"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "låst af %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "log ind"
-
msgid "manual"
msgstr "manuelt"
@@ -42297,9 +42865,6 @@ msgstr "Sammenlægningsanmodningen indeholder ingen ændringer."
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr " Gendan den venligst eller brug en anden %{missingBranchName}-gren"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,8 +42987,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr "Skjul %{widget}-detaljer"
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr "Hvis grenen %{missingBranchName} findes i dit lokale depot, så kan du sammenlægge sammenlægningsanmodningen manuelt med kommandolinjen"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr "Hvis den sidste pipeline kørte i forgreningsprojektet, så kan den være upræcis. Inden sammenlægning anbefaler vi at køre en pipeline i projektet."
@@ -42469,6 +43034,9 @@ msgstr "Sammenlægning blokeret: pipeline skal lykkes. Den venter på en manuel
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Sammenlægning mislykkedes."
@@ -42523,6 +43091,9 @@ msgstr "Ã…bn i web-IDE"
msgid "mrWidget|Plain diff"
msgstr "Ren diff"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Klar til at blive sammenlagt automatisk. Spørg nogen med skriveadgang til depotet om at sammenlægge anmodningen"
@@ -42568,6 +43139,9 @@ msgstr "Indstillet af %{merge_author} til at starte et sammenlægningstog når p
msgid "mrWidget|Show %{widget} details"
msgstr "Vis %{widget}-detaljer"
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Ændringerne blev sammenlagt i"
@@ -42577,9 +43151,6 @@ msgstr "Ændringerne blev ikke sammenlagt i"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Kildegrenen er blevet slettet"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Din adgangskode"
-msgid "mrWidget|branch does not exist."
-msgstr "Grenen findes ikke."
-
msgid "mrWidget|into"
msgstr "i"
@@ -42899,9 +43467,6 @@ msgstr "depot:"
msgid "required"
msgstr "kræves"
-msgid "reset it."
-msgstr "nulstil den."
-
msgid "satisfied"
msgstr "opfyldt"
@@ -43082,9 +43647,6 @@ msgstr "brugeravatar"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "brugerpræferencer"
-
msgid "username"
msgstr "brugernavn"
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index ccd4eff4bf3..ba82faa9a92 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -68,7 +68,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" existiert nicht auf \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "\"%{repository_name}\" (%{repository_size}) überschreitet das Limit von %{limit}."
msgid "#%{issueIid} (closed)"
msgstr "#%{issueIid} (geschlossen)"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL gescannt"
msgstr[1] "%d URLs gescannt"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d Genehmigende(r)"
@@ -435,7 +455,7 @@ msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} hat %{original_issue} zu %{new_issue} geklont."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
-msgstr ""
+msgstr "%{author_link} hat %{original_issue} geklont. Du hast keinen Zugriff auf das neue Projekt."
msgid "%{author_link} wrote:"
msgstr "%{author_link} schrieb:"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} offener Merge Request"
msgstr[1] "%{bold_start}%{count}%{bold_end} offene Merge Requests"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Maskiert:%{code_close} In Job-Logs versteckt. Muss Maskier-Bedingungen erfüllen."
@@ -570,7 +596,7 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}Erweiterte Suche%{doc_link_end} ist aktiviert."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Erfahre mehr über Sichtbarkeitsstufen.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
msgstr "%{docs_link_start}Was ist \"Large File Storage\"?%{docs_link_end}"
@@ -626,6 +652,9 @@ msgstr "%{group_name} Aktivität"
msgid "%{group_name} group members"
msgstr "%{group_name} Gruppenmitglieder"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} nutzt Accounts, die von einer Gruppe verwaltet werden. Du musst dir einen neuen GitLab-Account erstellen, welcher von %{group_name} verwaltet wird."
@@ -722,6 +751,9 @@ msgstr "%{level_name} ist in einer %{group_level_name} -Gruppe nicht erlaubt."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} ist nicht zulässig, da das Fork-Quellprojekt eine geringere Sichtbarkeit hat."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}Erfahre mehr%{link_end} über Rollenberechtigungen."
@@ -731,6 +763,9 @@ msgstr "%{link_start}Entferne das %{draft_snippet} Präfix%{link_end} aus dem Ti
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Welche Informationen sammelt GitLab Inc.?%{link_end}"
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -868,7 +900,7 @@ msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr "%{reportType} hat %{totalStart} keine %{totalEnd} Sicherheitslücken erkannt."
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
-msgstr ""
+msgstr "%{retryButtonStart}Versuche es erneut%{retryButtonEnd} oder %{newFileButtonStart}füge eine neue Datei hinzu%{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 "%{rotation} wurde mit den verbliebenen Beteiligten neu errechnet. Bitte den neuen Stand von %{rotation_link} überprüfen. Wir empfehlen, sich mit den aktuellen Bereitschaftsverantwortlichen in Verbindung zu setzen, um eine kontinuierliche Anrufbereitschaft sicherzustellen."
@@ -876,6 +908,9 @@ msgstr "%{rotation} wurde mit den verbliebenen Beteiligten neu errechnet. Bitte
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 "%{rotation} wurde mit den verbliebenen Beteiligten neu errechnet. Bitte die neue Einrichtung für %{rotation} überprüfen. Wir empfehlen, sich mit den aktuellen Bereitschaftsverantwortlichen in Verbindung zu setzen, um eine kontinuierliche Anrufbereitschaft sicherzustellen."
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} Ergebnisse für Suchwort '%{term}'"
@@ -1449,7 +1484,7 @@ msgid ":%{startLine} to %{endLine}"
msgstr ":%{startLine} bis %{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
-msgstr ""
+msgstr "Ein %{incident_docs_start}modifiziertes Ticket%{incident_docs_end}, um Störfälle zu beenden."
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Eine .NET Core-Konsolenanwendungsvorlage, anpassbar für jedes .NET Core-Projekt"
@@ -1509,7 +1544,7 @@ msgid "A group is a collection of several projects"
msgstr "Eine Gruppe ist eine Ansammlung mehrerer Projekte"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
-msgstr ""
+msgstr "Eine Gruppe repräsentiert deine Organisation in GitLab. Mithilfe von Gruppen kannst du Benutzer(innen) verwalten und über mehrere Projekte hinweg zusammenarbeiten."
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
@@ -1572,7 +1607,7 @@ msgid "A rebase is already in progress."
msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
-msgstr ""
+msgstr "Eine Anmeldung in dein Konto ging von der folgenden IP-Adresse aus: %{ip}"
msgid "A title is required"
msgstr ""
@@ -1581,7 +1616,7 @@ msgid "A user with write access to the source branch selected this option"
msgstr "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Option ausgewählt"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
-msgstr ""
+msgstr "AKTION NÖTIG: Beim Abrufen des Let's Encrypt-Zertifikats für die GitLab Pages-Domain '%{domain}' trat ein Fehler auf."
msgid "API"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "Es kann nicht für den Zugriff auf andere Daten verwendet werden."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "Persönliches Zugangs-Token"
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr "CHANGELOG hinzufügen"
msgid "Add CONTRIBUTING"
msgstr "CONTRIBUTING hinzufügen"
-msgid "Add GitLab to Slack"
-msgstr "GitLab zu Slack hinzufügen"
-
msgid "Add Jaeger URL"
msgstr "Jaeger URL hinzufügen"
@@ -1991,7 +2011,7 @@ msgstr "Kubernetes-Cluster hinzufügen"
msgid "Add LICENSE"
msgstr "LIZENZ hinzufügen"
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "GPG-Schlüssel hinzufügen"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "SSH-Schlüssel hinzufügen"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr "System-Hook hinzufügen"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Zu Slack hinzufügen"
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Fehler beim Laden der Statistik. Bitte versuche es erneut"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr "Das bist du!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Benutzer(in) wird abgemeldet"
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3393,7 +3431,7 @@ msgid "AlertsIntegrations|No integrations have been added yet."
msgstr ""
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
-msgstr ""
+msgstr "Die aktuelle Integration konnte nicht aktualisiert werden. Bitte versuche es erneut."
msgid "AlertsIntegrations|The integration could not be added. Please try again."
msgstr ""
@@ -3533,22 +3571,13 @@ msgstr "Erlaube es Projekten in dieser Gruppe Git LFS zu verwenden"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Erlaube Anfragen an das lokale Netzwerk von Hooks und Diensten."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Anfragen an das lokale Netzwerk von System-Hooks erlauben"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Anfragen an das lokale Netzwerk von Web-Hooks und Diensten erlauben"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3615,7 +3644,7 @@ msgid "Alternate support URL for Help page and Help dropdown."
msgstr ""
msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
-msgstr ""
+msgstr "Alternativ kannst du dein Konto in ein verwaltetes Konto der Gruppe %{group_name} konvertieren."
msgid "Amazon EKS"
msgstr "Amazon EKS"
@@ -3659,9 +3688,6 @@ msgstr "Es ist ein Fehler aufgetreten"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Beim Hinzufügen eines Entwurfs zur Diskussion ist ein Fehler aufgetreten."
@@ -3809,18 +3835,15 @@ msgstr "Beim Abrufen der Jobs ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Beim Abrufen der Releases ist ein Fehler aufgetreten. Bitte versuche es erneut."
msgid "An error occurred while fetching this tab."
msgstr "Beim Abrufen des Tabs ist ein Fehler aufgetreten."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Beim Erzeugen des Benutzernames trat ein Fehler auf. Bitte versuche es erneut."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr ""
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Genehmigungsberechtigte(r)"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr "Möchtest du wirklich dieses Projekt aus dem Archiv zurückholen?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "Bist du sicher, dass du diese Identität entfernen willst?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Möchtest du wirklich das SCIM-Token zurücksetzen? Die SCIM-Bereitstellung funktioniert nicht mehr, bis das neue Token aktualisiert ist."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Bist du sicher, dass du den Health-Check-Token zurücksetzen willst?"
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "Avatar wird entfernt. Bist du sicher?"
msgid "Average per day: %{average}"
msgstr "Durchschnitt pro Tag: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Vorsicht. Änderungen am Projektnamensraum können unbeabsichtigte Nebenwirkungen haben."
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Unten findest du alle Gruppen, die öffentlich sind."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Bitbucket-Import"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Zusammengeführte Branches löschen"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Löschen der zusammengeführten Branches kann nicht rückgängig gemacht werden. Bist du sicher?"
@@ -5958,9 +5990,6 @@ msgstr "Neuer Branch"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Um Datenverlust zu vermeiden, überlege diesen Branch zu mergen, bevor du ihn löschst."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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\"."
@@ -6036,9 +6056,6 @@ 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."
-
msgid "Branches|diverged from upstream"
msgstr "weicht vom Upstream ab"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Standardmäßig verwenden alle Projekte und Gruppen die globalen Einstellungen für Benachrichtigungen."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "von"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Kann nicht automatisch zusammengeführt werden"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Der Missbrauchsbericht kann nicht erstellt werden. Der/Die Benutzer(in) wurde gelöscht."
@@ -6915,6 +6956,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Diesen Merge-Request cherry picken"
msgid "Child"
msgstr "Untergeordnet"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "Untergeordnetes Epic existiert nicht."
@@ -7138,7 +7185,7 @@ msgid "Choose visibility level, enable/disable project features and their permis
msgstr ""
msgid "Choose what content you want to see on a group’s overview page."
-msgstr ""
+msgstr "Inhalte auswählen, die du auf Gruppenübersichtsseiten sehen willst."
msgid "Choose which Git strategy to use when fetching the project."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "Client-Authentifizierungszertifikat"
-
-msgid "Client authentication key"
-msgstr "Client-Authentifizierungsschlüssel"
-
-msgid "Client authentication key password"
-msgstr "Kennwort für den Client-Authentifizierungsschlüssel"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Schließt dieses %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr "Commit (beim Bearbeiten der Commit-Nachricht)"
msgid "Commit Message"
msgstr "Commit-Nachricht"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr "Tracing konfigurieren"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "Vorhandene Installation konfigurieren"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Konfiguriere, wie ein(e) Benutzer(in) ein neues Konto erstellt."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Bestätigen"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr "Von mir erstellt"
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "Standardklassifikationslabel"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Bereitstellungen"
msgid "Deploy Keys"
msgstr "Bereitstellungsschlüssel"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Bereitstellen auf..."
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr "Kommentar bearbeiten"
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "Aktiviere die Klassifizierungskontrolle mithilfe eines externen Service"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr "Gib unten deine Bitbucket-Server-URL und deinen persönlichen Zugriffsto
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr "Umgebung stoppen"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr "geschützt"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Epic"
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "Externe Autorisierung der Klassifikationsrichtlinie"
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "Externe Authentifizierung"
-
msgid "External authorization denied access to this project"
msgstr "Externe Autorisierung verbietet den Zugriff auf dieses Projekt"
-msgid "External authorization request timeout"
-msgstr "Zeitüberschreitung für externe Autorisierungsanfrage"
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr "Klassifizierungslabel"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Wenn kein Klassifizierungslabel gesetzt ist, wird das Standardlabel `%{default_label}` benutzt."
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Feb"
@@ -15149,12 +15308,6 @@ msgstr "Filter"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtern nach %{issuable_type}, die derzeit geschlossen sind."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Generiere einen Standardsatz von Labels"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo-Knoten"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fehlgeschlagen"
@@ -15767,12 +15935,6 @@ msgstr "Nächste Synchronisierung geplant um"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Noch nicht synchronisiert"
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Ausstehende Synchronisation"
@@ -15821,16 +15986,19 @@ msgstr "Erneuter Download"
msgid "Geo|Remove"
msgstr "Entfernen"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr "Tracking-Datenbankeintrag entfernen"
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr "sekundär"
msgid "Get a free instance review"
msgstr "Erhalte eine kostenlose Instanzprüfung"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Gruppen-Git-LFS-Status:"
@@ -16664,6 +16847,9 @@ msgstr "Gruppen-SAML muss zum Testen aktiviert sein"
msgid "Group URL"
msgstr "Gruppen-URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Gruppenbetreuer können Gruppen-Runner unter %{link} registrieren"
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr "Die Pipeline-Minuten der Gruppe wurden erfolgreich zurückgesetzt."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr "Gruppe benötigt ein separates Konto"
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "Pipeline-Einstellungen wurden für die Gruppe aktualisiert"
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Diese Einstellung wird auf %{ancestor_group} angewendet. Du kannst die E
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff au
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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "Werte ausblenden"
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "Bereinigung erfolgreich gestartet"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "Ich akzeptiere die %{terms_link}"
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr "Identitäten"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "Wenn diese Option aktiviert ist, wird der Zugriff auf Projekte mit einem externen Service anhand ihrer Klassifizierungslabels überprüft."
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18044,7 +18248,7 @@ msgid "Import tasks from Phabricator into issues"
msgstr "Importieren Sie Aufgaben aus Phabricator in Tickets"
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
-msgstr ""
+msgstr "Zeitüberschreitung beim Import: Dauerte länger als %{import_jobs_expiration} Sekunden"
msgid "ImportAProjectModal|Import from a project"
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18844,7 +19057,7 @@ msgid "Indicates whether this runner can pick jobs without tags"
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 ""
+msgstr "Informiere Benutzer:innen ohne SSH-Schlüssel, dass einer hinzugefügt werden muss, um pushen über SSH zu ermöglichen."
msgid "Infrastructure"
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr "Lade..."
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Lokalisierung"
@@ -21402,6 +21615,9 @@ msgstr "Sperren"
msgid "Lock %{issuableDisplayName}"
msgstr "Sperre %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr "Sperrungen bieten die Möglichkeit, bestimmte Dateien oder Ordner zu spe
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Mit Smartcard einloggen"
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22746,7 +23010,7 @@ msgid "Metrics|You can save a copy of this dashboard to your repository so it ca
msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
-msgstr ""
+msgstr "Du wirst diese Metrik dauerhaft zu löschen. Dies kann nicht rückgängig gemacht werden."
msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "Monate"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr "Weitere Aktionen"
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Keine anderen Tags mit einem solchen Namen oder einer solchen Beschreibung"
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,8 +25241,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Ausgehende Anfragen"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,8 +26038,8 @@ msgstr "Zugriffsberechtigungen"
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
-msgstr "Berechtigungen, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Persönlicher Zugangs-Token"
@@ -26029,9 +26305,6 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Pipelinediagramme"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Baue mit Vertrauen"
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26687,7 +26990,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
-msgstr ""
+msgstr "Wähle aus, welche Inhalte du auf der Projektübersichtsseite sehen möchtest."
msgid "Preferences|Choose what content you want to see on your homepage."
msgstr ""
@@ -26765,7 +27068,7 @@ msgid "Preferences|This feature is experimental and translations are not complet
msgstr "Dieses Feature ist experimentell und die Ãœbersetzungen sind noch nicht abgeschlossen"
msgid "Preferences|This setting allows you to customize the appearance of the syntax."
-msgstr ""
+msgstr "Diese Einstellung erlaubt es dir, das Aussehen der Syntax anzupassen."
msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr "Avatar zuschneiden"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Avatar wird entfernt. Bist du sicher?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr "Status löschen"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Avatar entfernen"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Neues Profilbild festlegen"
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Gib deinen %{confirmationValue} zur Bestätigung ein:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr "Profileinstellungen aktualisieren"
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr "Diese Einstellung wird auf Serverebene angewendet, wurde aber für diese
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Diese Einstellung wird auf alle Projekte angewendet, sofern sie nicht von einem Admin überschrieben wird."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr "Öffentliche Pipelines"
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "Projekt-Sichtbarkeit verringern"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "Sichtbarkeit dieses Projekts verringern?"
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr "Das Repository muss mindestens eine Datei enthalten."
msgid "Repository size is above the limit."
msgstr "Die Repository-Größe liegt über dem Limit."
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Repository-Speicher"
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr "Fortsetzen"
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr "Zurücknehmen"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Roadmap"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr "Suche"
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Archivierungsformat auswählen"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,8 +32748,8 @@ msgstr "Service-Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "Service-URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr "CI/CD einrichten"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr "Pipeline-Minuten zurücksetzen"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Verwendete Pipeline-Minuten zurücksetzen"
-msgid "Sherlock Transactions"
-msgstr "Sherlock-Transaktionen"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr "Archivierte Projekte anzeigen"
msgid "Show archived projects only"
msgstr "Nur archivierte Projekte anzeigen"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Befehl anzeigen"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr "Zeige komplettes Rohprotokoll"
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr "Slack-Anwendung"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "Die Slack-Integration ermöglicht es dir, mit GitLab über Slash-Befehle im Chat-Fenster zu interagieren."
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Etwas ist schief gelaufen. Bitte versuche es erneut."
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Entschuldigung, keine Epics stimmten mit deiner Suche überein"
-
msgid "Sorry, no projects matched your search"
msgstr "Entschuldigung, keine Projekte stimmten mit deiner Suche überein"
@@ -33376,9 +33816,6 @@ msgstr "Zuletzt gesehen"
msgid "SortOptions|Last created"
msgstr "Zuletzt erstellt"
-msgid "SortOptions|Last updated"
-msgstr "Zuletzt aktualisiert"
-
msgid "SortOptions|Least popular"
msgstr "Am unbeliebtesten"
@@ -33578,7 +34015,7 @@ msgid "SourcegraphPreferences|This feature is experimental and currently limited
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
-msgstr ""
+msgstr "Diese Funktion ist experimentell und beschränkt auf öffentliche Projekte."
msgid "SourcegraphPreferences|This feature is experimental."
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Suche starten"
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Gib deine Nachricht an, um sie zu aktivieren"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "Abonniert"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr "Sonntag"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr "Zielbranch"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr "Nutzungsbedingungen und Datenschutzerklärung"
msgid "Terms of Service and Privacy Policy"
msgstr "Nutzungsbedingungen und Datenschutzerklärung"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr "Test"
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Testabdeckung analysieren"
@@ -35144,7 +35632,7 @@ msgid "Thank you for your feedback!"
msgstr ""
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
-msgstr ""
+msgstr "Vielen Dank für deine Meldung. Ein:e GitLab-Admin wird sich der Sache in Kürze widmen."
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Das zu verwendende X.509-Zertifikat, wenn über MTLS mit dem externen Autorisierungsdienst kommunizieren muss. Wenn dieses Feld leer gelassen wird, wird das Serverzertifikat beim Zugriff über HTTPS weiterhin überprüft."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "Das Kennwort, das zum Entschlüsseln des privaten Schlüssels erforderlich ist. Dies ist optional und der Wert wird im Ruhezustand verschlüsselt."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ msgstr "Die Pipeline wurde gelöscht"
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 "Die Pipelinezeitplan startet in Zukunft wiederholt Pipelines für bestimmte Branches oder Tags. Diese geplanten Pipelines haben denselben begrenzten Zugriff auf das Projekt, wie der zugeordnete Nutzer."
-msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "Der private Schlüssel, der verwendet werden soll, wenn ein Clientzertifikat bereitgestellt wird. Dieser Wert wird im Ruhezustand verschlüsselt."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr "Dieses Projekt"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr "Dieses Projekt ist archiviert und kann nicht kommentiert werden."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Diese Einstellung kann in jedem Projekt überschrieben werden."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Zeit in Sekunden die GitLab auf die Antwort des externen Dienstes warten wird. Wenn der Dienst nicht rechtzeitig antwortet, wird der Zugriff verweigert."
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Um einen SSH-Schlüssel hinzuzufügen, musst du %{generate_link_start}einen generieren%{link_end} oder einen %{existing_link_start}vorhandenen Schlüssel%{link_end} verwenden."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "Um deine Suche zu erweitern, verändere oder entferne Filter."
-
msgid "To-Do List"
msgstr "To-Do-Liste"
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "Verfolge die Zeit mit Kurzbefehlen"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr "Aktualisiert"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Aktualisiert %{updated_at} von %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr "Zeige ersetzte Datei @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "Bezeichner"
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Links"
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projekt"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,11 +40498,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhin angegeben werden, ohne projektübergreifende Eigenschaften auszuschalten oder einen externen Autorisierungscheck durchzuführen."
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40367,7 +40900,7 @@ msgid "You are an admin, which means granting access to %{client_name} will allo
msgstr ""
msgid "You are attempting to delete a file that has been previously updated."
-msgstr ""
+msgstr "Du versuchst eine Datei zu löschen, die zuvor aktualisiert wurde."
msgid "You are attempting to update a file that has changed since you started editing it."
msgstr ""
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Du kannst einfach dazu beitragen, indem du um Aufnahme in diesen Gruppen
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Du hast die Projektbegrenzung erreicht"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40864,7 +41418,7 @@ msgid "You will first need to set up Jira Integration to use this feature."
msgstr ""
msgid "You will lose all changes you've made to this file. This action cannot be undone."
-msgstr ""
+msgstr "Alle deine Änderungen an dieser Datei gehen verloren. Dies kann nicht rückgängig gemacht werden."
msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
msgstr ""
@@ -41095,7 +41649,7 @@ msgid "Your comment could not be submitted! Please check your network connection
msgstr ""
msgid "Your comment could not be updated! Please check your network connection and try again."
-msgstr ""
+msgstr "Dein Kommentar konnte nicht aktualisiert werden! Bitte überprüfe deine Netzwerkverbindung und versuche es erneut."
msgid "Your comment will be discarded."
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Dein Name"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr "Gruppe"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "gesperrt durch %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "einloggen"
-
msgid "manual"
msgstr "manuell"
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Bitte stelle es wieder her, oder verwende einen anderen Branch %{missingBranchName}"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,8 +42987,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fehlgeschlagen."
@@ -42523,6 +43091,9 @@ msgstr "In Web-IDE öffnen"
msgid "mrWidget|Plain diff"
msgstr "Unformatiertes Diff"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Bereit zum automatischen Mergen. Bitte jemanden mit Schreibrechten zu diesem Repository diesen Merge-Request zu mergen"
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Die Änderungen wurden gemerged nach"
@@ -42577,9 +43151,6 @@ msgstr "Die Änderungen wurden nicht gemerged nach"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Der Quellbranch wurde gelöscht"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Dein Password"
-msgid "mrWidget|branch does not exist."
-msgstr "Branch existiert nicht."
-
msgid "mrWidget|into"
msgstr "in"
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr "Zurücksetzen."
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr "Benutzeravatar"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "Benutzername"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 5b12b90aa40..8eabb110e70 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 8b08938d39c..0f026fc1f2a 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "de"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Precize elekti ĉi tiun peton pri kunfando"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Disponigadoj"
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "La refreÅigo komenciÄis sukcese"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr "Ĉenstabloj"
msgid "Pipelines charts"
msgstr "Ĉenstablaj diagramoj"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Elektu formaton de arkivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Vi ne povas krei pliajn projektojn"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Via nomo"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 5bb9c3f1ba4..6e4a6a19c43 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -38,7 +38,7 @@ msgid " Type"
msgstr " Tipo"
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr "Necesita hacer esto antes de %{grace_period_deadline}."
msgid " and "
msgstr " y "
@@ -113,8 +113,28 @@ msgstr[1] "%d URLs analizadas"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
-msgstr[0] "%d URL escaneada"
-msgstr[1] "%d URLs escaneadas"
+msgstr[0] "%d URL analizada"
+msgstr[1] "%d URLs analizadas"
+
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
msgid "%d approver"
msgid_plural "%d approvers"
@@ -198,8 +218,8 @@ msgstr[1] "%d días"
msgid "%d epic"
msgid_plural "%d epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d épica"
+msgstr[1] "%d épicas"
msgid "%d error"
msgid_plural "%d errors"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr "Actividad de %{group_name}"
msgid "%{group_name} group members"
msgstr "miembros del grupo %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} utiliza cuentas administradas de grupo. Debe crear una nueva cuenta de GitLab que será administrada por %{group_name}."
@@ -722,6 +751,9 @@ msgstr "%{level_name} no está permitido en un grupo de %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} no está permitido debido a que el fork del proyecto origen tiene menor visibilidad."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}Obtener más información%{link_end} sobre los roles."
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} no es un tema válido"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,11 +908,14 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} resultados para el término '%{term}'"
msgid "%{search} %{description} %{scope}"
-msgstr ""
+msgstr "%{search}%{description}%{scope}"
msgid "%{seconds}s"
msgstr "%{seconds} s"
@@ -1027,7 +1062,7 @@ msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advertencias encontradas: mostrando la primera %{warningsDisplayed}"
msgid "%{type} only supports %{name} name"
-msgstr ""
+msgstr "%{type} solo admite %{name} nombre"
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1081,7 +1116,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar notificaciones a aplicaciones web en respuesta a eventos en un grupo o proyecto. Recomendamos utilizar una %{integrations_link_start}integración%{link_end} en lugar de un webhook."
msgid "%{widget} options"
-msgstr ""
+msgstr "%{widget} opciones"
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 ""
@@ -1161,7 +1196,7 @@ msgid "(max size 15 MB)"
msgstr "(tamaño máximo 15 MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(opcional)"
msgid "(removed)"
msgstr "(eliminado)"
@@ -1659,10 +1694,10 @@ msgid "APIFuzzing|Predefined profiles"
msgstr "Perfiles predefinidos"
msgid "APIFuzzing|Scan mode"
-msgstr "Modo de escaneo"
+msgstr "Modo de análisis"
msgid "APIFuzzing|Scan profile"
-msgstr "Perfil de escaneo"
+msgstr "Perfil de análisis"
msgid "APIFuzzing|Show code snippet for the profile"
msgstr "Mostrar fragmento de código para el perfil"
@@ -1671,7 +1706,7 @@ msgid "APIFuzzing|Target URL"
msgstr "URL de destino"
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr "Hay tres maneras de realizar escaneos."
+msgstr "Hay tres maneras de realizar los análisis."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "No se puede utilizar para acceder a ningún otro dato."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Mantenga este token en secreto. Cualquiera que lo tenga puede acceder a los objetos estáticos del repositorio como si fuera usted. Si eso sucede alguna vez, %{reset_link_start}reinice este token%{reset_link_end}."
-
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Mantenga este token en secreto. Cualquiera que lo tenga puede crear incidencias como si fuera usted. Si eso sucede, %{link_reset_it}."
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Mantenga este token en secreto. Cualquiera que lo tenga puede leer la actividad o crear anuncios RSS o anuncios en su calendario como si fuera usted. Si eso sucede, %{link_reset_it}."
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "Tokens de acceso personal"
@@ -1871,9 +1897,6 @@ msgstr "Su token de correo electrónico entrante lo autentica cuando crea una nu
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 this token"
-msgstr "reiniciar este token"
-
msgid "AccessibilityReport|Learn more"
msgstr "Obtener más información"
@@ -1914,7 +1937,7 @@ msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, y
msgstr ""
msgid "AccountValidation|Learn more."
-msgstr ""
+msgstr "Más información."
msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
msgstr ""
@@ -1926,7 +1949,7 @@ msgid "AccountValidation|Verification is required to discourage and reduce the a
msgstr ""
msgid "AccountValidation|unsubscribe"
-msgstr ""
+msgstr "Cancelar suscripción"
msgid "AccountValidation|you may %{unsubscribe_link} at any time."
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr "Añadir CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Añadir CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Añadir GitLab a Slack"
-
msgid "Add Jaeger URL"
msgstr "Añadir URL de Jaeger"
@@ -1991,8 +2011,8 @@ msgstr "Añadir clúster de Kubernetes"
msgid "Add LICENSE"
msgstr "Añadir LICENSE"
-msgid "Add New Node"
-msgstr "Añadir un nuevo nodo"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Añadir README"
@@ -2006,6 +2026,9 @@ msgstr "Añadir un %{type}"
msgid "Add a GPG key"
msgstr "Añadir una clave GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2064,7 +2087,7 @@ msgid "Add a task list"
msgstr "Añadir una lista de tareas"
msgid "Add a title..."
-msgstr ""
+msgstr "Añadir un título..."
msgid "Add a to do"
msgstr "Añadir a tareas pendientes"
@@ -2072,6 +2095,9 @@ msgstr "Añadir a tareas pendientes"
msgid "Add an SSH key"
msgstr "Añadir una clave SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Añadir una incidencia existente"
@@ -2189,9 +2215,6 @@ msgstr "Añadir hook del sistema"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Añadir a Slack"
-
msgid "Add to board"
msgstr "Agregar al tablero"
@@ -2316,7 +2339,7 @@ msgid "Adds %{labels} %{label_text}."
msgstr "Agrega %{labels} %{label_text}."
msgid "Adds a Zoom meeting."
-msgstr ""
+msgstr "Añadir una reunión de Zoom."
msgid "Adds a to do."
msgstr "Añade una tarea pendiente."
@@ -2325,7 +2348,7 @@ msgid "Adds an issue to an epic."
msgstr "Agregar una incidencia a una tarea épica."
msgid "Adds email participant(s)."
-msgstr ""
+msgstr "Añadir las direcciones de correo electrónico de los participantes"
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr "Ajusta la frecuencia con la que la interfaz de usuario de GitLab busca actualizaciones."
@@ -2421,7 +2444,7 @@ msgid "AdminArea|Maintainer"
msgstr "Mantenedor"
msgid "AdminArea|Minimal access"
-msgstr ""
+msgstr "Acceso mínimo"
msgid "AdminArea|New group"
msgstr "Nuevo grupo"
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Se ha producido un error al cargar las estadísticas. Por favor, inténtalo de nuevo"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr "(Desactivado)"
msgid "AdminUsers|(Internal)"
msgstr "(Interno)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Pendiente de aprobación)"
@@ -2681,7 +2713,7 @@ msgstr "Ajuste la configuración del límite de usuarios en tu instancia"
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2697,7 +2729,7 @@ msgid "AdminUsers|Approved users can:"
msgstr "Los usuarios aprobados pueden:"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "Auditor"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
msgstr ""
@@ -2807,6 +2839,9 @@ msgstr "¡Es usted!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Iniciar sesión"
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr "El usuario no puede iniciar sesión."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "El usuario será desconectado"
@@ -2972,8 +3010,8 @@ 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 "No puede eliminar sus propios derechos de administración."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "Debe transferir la propiedad o eliminar los grupos que son propiedad de este usuario antes de poder eliminar su cuenta"
@@ -3066,7 +3104,7 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr ""
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
msgstr "Clave de API de Akismet"
@@ -3192,7 +3230,7 @@ msgid "AlertManagement|There was an error displaying the alerts. Confirm your en
msgstr ""
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
-msgstr ""
+msgstr "Se ha producido un error mientras se actualizaba la lista de asignados. Por favor, inténtelo de nuevo."
msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
msgstr ""
@@ -3533,22 +3571,13 @@ msgstr "Permitir que los proyectos dentro de este grupo usen Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Permitir peticiones a la red local desde los hooks y los servicios."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Permitir solicitudes a la red local desde hooks de sistema"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Permitir solicitudes a la red local desde web hooks y servicios"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Permitir que los subgrupos configuren sus propias reglas de autenticación de dos factores"
msgid "Allow this key to push to this repository"
msgstr "Permitir a esta clave hacer push a este repositorio"
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Se ha producido un error"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Se ha producido un error al agregar un borrador a la discusión."
@@ -3809,18 +3835,15 @@ msgstr "Se ha producido un error al obtener los trabajos."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Se ha producido un error al obtener el último pipeline."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Se ha producido un error al obtener las versiones. Por favor, inténtelo de nuevo."
msgid "An error occurred while fetching this tab."
msgstr "Se ha producido un error al obtener esta pestaña."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Se ha producido un error al generar un nombre de usuario. Por favor, inténtelo de nuevo."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "Se ha producido un error al obtener datos de autocompletado. Por favor, actualice la página e inténtelo de nuevo."
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "Se ha producido un error al obtener los archivos de - %{branchId}"
@@ -4374,11 +4397,8 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Añadir aprobadores"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
-msgstr "Todos los escáneres"
+msgstr "Todos los análisis"
msgid "ApprovalRule|All severity levels"
msgstr "Todos los niveles de gravedad"
@@ -4407,9 +4427,6 @@ msgstr "Tipo de aprobador"
msgid "ApprovalRule|Approvers"
msgstr "Aprobadores"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Ejemplos: QA, Seguridad."
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4441,7 +4458,7 @@ msgid "ApprovalRule|Please enter a number equal or greater than zero"
msgstr "Por favor, introduzca un número igual o superior a cero"
msgid "ApprovalRule|Please select at least one security scanner"
-msgstr "Por favor, seleccione al menos un escáner de seguridad"
+msgstr "Por favor, seleccione al menos un análisis de seguridad"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "Por favor seleccione al menos un nivel de gravedad"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4462,11 +4479,14 @@ msgid "ApprovalRule|Rule name"
msgstr "Nombre de la regla"
msgid "ApprovalRule|Security scanners"
-msgstr "Escáneres de seguridad"
+msgstr "Análisis de seguridad"
msgid "ApprovalRule|Select All"
msgstr "Seleccionar todo"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Seleccionar escáneres"
@@ -4482,7 +4502,7 @@ msgstr "Niveles de gravedad"
msgid "ApprovalRule|Target branch"
msgstr "Branch de destino"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr "¿Está seguro de que desea desarchivar este proyecto?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr "¿Está seguro que desea %{action} %{name}?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "¿Está seguro de que desea eliminar esta identidad?"
msgid "Are you sure you want to remove this list?"
msgstr "¿Está seguro de que desea eliminar esta lista?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "¿Está seguro de que desea restablecer el token SCIM? La provisión de SCIM dejará de funcionar hasta que se actualice el nuevo token."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "¿Está seguro que desea restablecer el token de verificación de estado?"
@@ -4802,7 +4828,7 @@ msgstr "Pregunta de nuevo más tarde"
msgid "Ask someone with write access to resolve it."
msgstr "Pedir a alguien con acceso de escritura que lo resuelva."
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4839,7 +4865,7 @@ msgid "Assign reviewer(s)"
msgstr "Asignar revisores"
msgid "Assign severity"
-msgstr ""
+msgstr "Asignar gravedad"
msgid "Assign some issues to this milestone."
msgstr "Asignar algunas incidencias a este hito."
@@ -4848,10 +4874,10 @@ msgid "Assign to"
msgstr "Asignar a"
msgid "Assign to commenting user"
-msgstr ""
+msgstr "Asignar al usuario que comenta"
msgid "Assign to me"
-msgstr ""
+msgstr "Asignar a mí"
msgid "Assign yourself to these issues"
msgstr "Asignarse estas incidencias"
@@ -4863,7 +4889,7 @@ msgid "Assigned %{assignee_users_sentence}."
msgstr "Asignado a %{assignee_users_sentence}."
msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "Asignado %{reviewer_users_sentence} como %{reviewer_text}."
msgid "Assigned Issues"
msgstr "Incidencias asignadas"
@@ -4978,7 +5004,7 @@ msgid "AuditLogs|IP Address"
msgstr "Dirección IP"
msgid "AuditLogs|Member Events"
-msgstr ""
+msgstr "Eventos de miembros"
msgid "AuditLogs|No matching %{type} found."
msgstr "No se encontraron %{type} coincidentes."
@@ -5244,6 +5270,9 @@ msgstr "El avatar será eliminado. ¿Está seguro?"
msgid "Average per day: %{average}"
msgstr "Promedio por día: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr "Premio añadido"
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr "Basado en"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tenga cuidado. Cambiar el espacio de nombres del proyecto puede tener efectos secundarios no deseados."
@@ -5403,6 +5435,9 @@ msgstr "A continuación se muestran los ajustes relativos a %{link_to_gitlab_pag
msgid "Below you will find all the groups that are public."
msgstr "A continuación encontrará todos los grupos públicos."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Cobertura de código quincenal"
@@ -5418,9 +5453,6 @@ msgstr "%{group_name} está actualmente usando el %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name} está utilizando el %{plan_name}."
-msgid "BillingPlans|Compare all plans"
-msgstr "Comparar todos los planes"
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Enhorabuena, su plan de prueba está activado."
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5515,7 +5544,7 @@ msgid "Billings|Reactivate trial"
msgstr "Reactivar el periodo de prueba"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr ""
+msgstr "No se pueden habilitar los ejecutores compartidos hasta que se registre una tarjeta de crédito válida."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -5536,11 +5565,17 @@ msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on sh
msgstr ""
msgid "Billings|Your account has been validated"
+msgstr "Su cuenta ha sido validada"
+
+msgid "Billing|%{user} was successfully approved"
msgstr ""
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Importar desde Bitbucket"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Bloquear usuario"
@@ -5652,19 +5690,19 @@ msgid "Board scope affects which issues are displayed for anyone who visits this
msgstr "El alcance del panel de control afecta qué problemas se muestran para cualquiera persona que visite este panel"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Grupos"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Cargando grupos"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "No hay resultados coincidentes"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Buscar grupos"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Seleccionar un grupo"
msgid "BoardNewIssue|No matching results"
msgstr "No hay resultados coincidentes"
@@ -5679,7 +5717,7 @@ msgid "BoardNewIssue|Select a project"
msgstr "Seleccionar un proyecto"
msgid "BoardScope|An error occurred while getting milestones, please try again."
-msgstr ""
+msgstr "Se ha producido un error al obtener los hitos, por favor inténtelo de nuevo."
msgid "BoardScope|An error occurred while searching for labels, please try again."
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Borrar ramas fusionadas"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "El borrado de las ramas fusionadas no podrá deshacerse. ¿Está usted seguro?"
@@ -5958,9 +5990,6 @@ msgstr "Nueva rama"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Para evitar pérdida de datos, considere hacer un merge request de esta rama antes de borrarla."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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."
@@ -6036,9 +6056,6 @@ 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}."
-
msgid "Branches|diverged from upstream"
msgstr "Divergido desde el servidor"
@@ -6100,7 +6117,7 @@ msgid "Bulk request concurrency"
msgstr ""
msgid "Bulk update"
-msgstr ""
+msgstr "Actualización masiva"
msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Por defecto, todos los proyectos y grupos utilizarán la configuración de notificaciones global."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6462,7 +6500,7 @@ msgid "Can't load mermaid module: %{err}"
msgstr "No se puede cargar el módulo de Mermaid: %{err}"
msgid "Can't scan the code?"
-msgstr "¿No puede escanear el código?"
+msgstr "¿No puede analizar el código?"
msgid "Can't update snippet: %{err}"
msgstr "No se puede actualizar el fragmento de código: %{err}"
@@ -6495,7 +6533,7 @@ msgid "CanaryIngress|Doing so will set a deployment change in progress. This tem
msgstr ""
msgid "CanaryIngress|Stable"
-msgstr ""
+msgstr "Estable"
msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "No se puede hacer merge automáticamente"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "No se puede crear el informe de abuso. El usuario ha sido eliminado."
@@ -6576,7 +6617,7 @@ msgid "Cannot promote issue because it does not belong to a group."
msgstr "No se puede promocionar la incidencia porque no pertenece a un grupo."
msgid "Cannot promote issue due to insufficient permissions."
-msgstr ""
+msgstr "No se puede promocionar la incidencia debido a la falta de permisos."
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
@@ -6687,7 +6728,7 @@ msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
msgstr "Revisor cambiado de %{old} a %{new}"
msgid "ChangeReviewer|Reviewer changed to %{new}"
-msgstr ""
+msgstr "Revisor cambiado a %{new}"
msgid "ChangeReviewer|Unassigned"
msgstr "Sin asignar"
@@ -6864,7 +6905,7 @@ msgid "Checkout"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
-msgstr ""
+msgstr "$%{selectedPlanPrice} por cada 10 GB de almacenamiento por año"
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Dirección de facturación"
@@ -7092,6 +7136,9 @@ msgstr "Escoger esta solicitud de fusión"
msgid "Child"
msgstr "Hijo"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "La subtarea épica no existe."
@@ -7392,15 +7439,6 @@ msgstr "Clic para ocultar"
msgid "Click to reveal"
msgstr "Haga clic para revelar"
-msgid "Client authentication certificate"
-msgstr "Certificado de autenticación del cliente"
-
-msgid "Client authentication key"
-msgstr "Clave de autenticación del cliente"
-
-msgid "Client authentication key password"
-msgstr "Contraseña de clave de autenticación del cliente"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr "Cerrado: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Cierra este %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Clúster"
@@ -7521,23 +7565,23 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr "%{number} de %{total} agentes"
+msgid "ClusterAgents|%{number} of %{total} Agents"
+msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
msgstr "%{number} de %{total} clústeres conectados a través de certificados de cluster"
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon} Conectado"
msgid "ClusterAgents|%{titleIcon}Not connected"
-msgstr ""
+msgstr "ClusterAgents|%{titleIcon} No conectado"
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} creado"
msgid "ClusterAgents|%{tokenName} revoked"
-msgstr ""
+msgstr "%{tokenName} revocado"
msgid "ClusterAgents|Access tokens"
msgstr "Tokens de acceso"
@@ -7549,13 +7593,13 @@ msgid "ClusterAgents|Advanced installation methods"
msgstr "Métodos de instalación avanzados"
msgid "ClusterAgents|Agent"
-msgstr ""
+msgstr "Agente"
msgid "ClusterAgents|Agent %{strongStart}connected%{strongEnd}"
-msgstr ""
+msgstr "Agente %{strongStart}conectado%{strongEnd}"
msgid "ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}"
-msgstr ""
+msgstr "Agente %{strongStart}desconectado%{strongEnd}"
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr "Es posible que el agente no esté conectado a GitLab"
@@ -7564,43 +7608,43 @@ msgid "ClusterAgents|Agent never connected to GitLab"
msgstr "El agente nunca se ha conectado a GitLab"
msgid "ClusterAgents|All"
-msgstr ""
+msgstr "Todos"
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr "Se ha producido un error al cargar sus agentes de GitLab"
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr "Se ha producido un error al cargar su agente"
msgid "ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again."
-msgstr ""
+msgstr "Se ha producido un error al recuperar la actividad del agente de GitLab. Recargue la página para volver a intentarlo."
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "Se ha producido un error desconocido. Por favor, inténtelo de nuevo."
msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
-msgstr ""
+msgstr "¿Está seguro de que desea eliminar este agente? Esta acción no se puede deshacer."
msgid "ClusterAgents|Certificate"
-msgstr ""
+msgstr "Certificado"
msgid "ClusterAgents|Configuration"
msgstr "Configuración"
msgid "ClusterAgents|Connect a cluster through the Agent"
-msgstr ""
+msgstr "Conectar a un clúster mediante el agente"
msgid "ClusterAgents|Connect existing cluster"
-msgstr ""
+msgstr "Conectar a un clúster existente"
msgid "ClusterAgents|Connect with a certificate"
-msgstr ""
+msgstr "Conectar con un certificado"
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
-msgstr ""
+msgstr "Conectar con el agente de GitLab"
msgid "ClusterAgents|Connect your cluster through the Agent"
msgstr ""
@@ -7615,7 +7659,7 @@ msgid "ClusterAgents|Copy token"
msgstr "Copiar token"
msgid "ClusterAgents|Create a new cluster"
-msgstr ""
+msgstr "Crear un nuevo clúster"
msgid "ClusterAgents|Created by"
msgstr "Creado por"
@@ -7627,13 +7671,13 @@ msgid "ClusterAgents|Date created"
msgstr "Fecha de creación"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "Eliminar"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "Eliminar agente"
msgid "ClusterAgents|Deprecated"
-msgstr ""
+msgstr "Obsoleto"
msgid "ClusterAgents|Description"
msgstr "Descripción"
@@ -7642,25 +7686,28 @@ msgid "ClusterAgents|Event occurred"
msgstr ""
msgid "ClusterAgents|Failed to register an agent"
-msgstr ""
+msgstr "Se ha producido un error al registrar un agente"
msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
msgid "ClusterAgents|GitLab Agent"
-msgstr ""
+msgstr "Agente de GitLab"
msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr "Agente de GitLab para Kubernetes"
+
+msgid "ClusterAgents|Give feedback"
msgstr ""
msgid "ClusterAgents|Go to the repository files"
-msgstr ""
+msgstr "Ir a los archivos del repositorio"
msgid "ClusterAgents|How to register an agent?"
-msgstr ""
+msgstr "¿Cómo registrar un agente?"
-msgid "ClusterAgents|Install a new agent"
-msgstr "Instalar un nuevo agente"
+msgid "ClusterAgents|Install new Agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Última conexión %{timeAgo}"
@@ -7675,7 +7722,7 @@ msgid "ClusterAgents|Learn how to troubleshoot"
msgstr "Aprende a solucionar problemas"
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "Asegúrese de estar utilizando un token válido"
msgid "ClusterAgents|Name"
msgstr "Nombre"
@@ -7686,7 +7733,7 @@ msgstr "Nunca"
msgid "ClusterAgents|Never connected"
msgstr "Nunca se ha conectado"
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7696,16 +7743,16 @@ msgid "ClusterAgents|Not connected"
msgstr "No está conectado"
msgid "ClusterAgents|Recommended"
-msgstr ""
+msgstr "Recomendado"
msgid "ClusterAgents|Recommended installation method"
msgstr "Método de instalación recomendado"
msgid "ClusterAgents|Register"
-msgstr ""
+msgstr "Registrar"
msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
-msgstr ""
+msgstr "Registre un agente para generar un token que se utilizará para instalar el agente en su clúster en el siguiente paso."
msgid "ClusterAgents|Registering Agent"
msgstr "Registrando agente"
@@ -7713,16 +7760,31 @@ msgstr "Registrando agente"
msgid "ClusterAgents|Registration token"
msgstr "Token de registro"
-msgid "ClusterAgents|Security"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
+msgid "ClusterAgents|Security"
+msgstr "Seguridad"
+
msgid "ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected."
msgstr ""
msgid "ClusterAgents|Select an agent"
-msgstr ""
+msgstr "Seleccione un agente"
msgid "ClusterAgents|Select an agent to register with GitLab"
+msgstr "Seleccione un agente para registrar en GitLab"
+
+msgid "ClusterAgents|Tell us what you think"
msgstr ""
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
@@ -7746,9 +7808,9 @@ msgid "ClusterAgents|This agent has no tokens"
msgstr "Este agente no tiene tokens"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
-msgstr ""
+msgstr "Para eliminar el agente, escriba %{name} para confirmar:"
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7761,9 +7823,12 @@ msgid "ClusterAgents|Unknown user"
msgstr "Usuario desconocido"
msgid "ClusterAgents|View all %{number} agents"
-msgstr ""
+msgstr "Ver todos los agentes %{number}"
msgid "ClusterAgents|View all %{number} clusters"
+msgstr "Ver todos los %{number} clústeres"
+
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
msgstr ""
msgid "ClusterAgents|What is GitLab Agent activity?"
@@ -7809,7 +7874,7 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Añadir cluster de Kubernetes"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "Añadir integración con clúster de Kubernetes"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Agregar un cluster Kubernetes a su grupo compartirá automáticamente el cluster en todos sus proyectos. Utilice las aplicaciones de revisión, implemente sus aplicaciones y ejecute fácilmente los pipelines para todos los proyectos que utilizan el mismo clúster."
@@ -8716,6 +8781,9 @@ msgstr "Commit (al editar el mensaje de confirmación)"
msgid "Commit Message"
msgstr "Mensaje del commit"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8789,7 +8857,7 @@ msgid "Company"
msgstr "Empresa"
msgid "Company Name"
-msgstr ""
+msgstr "Nombre de la empresa"
msgid "Compare"
msgstr "Comparar"
@@ -8957,7 +9025,7 @@ msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "ComplianceReport|Approved by author"
-msgstr ""
+msgstr "Aprobado por el autor"
msgid "ComplianceReport|Approved by committer"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Componente"
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,17 +9117,20 @@ msgstr "Configurar seguimiento"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "Configurar la instalación existente"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "Configurar las réplicas del repositorio."
msgid "Configure repository storage."
-msgstr ""
+msgstr "Configurar el almacenamiento del repositorio."
msgid "Configure settings for Advanced Search with Elasticsearch."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configure la forma en la que un usuario crea una cuenta nueva."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Confirmar"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Confirmar nueva contraseña"
@@ -9194,7 +9280,7 @@ msgid "Container Registry"
msgstr "Registro de contenedores"
msgid "Container Scanning"
-msgstr "Escaneo de contenedores"
+msgstr "Análisis de contenedores"
msgid "Container does not exist"
msgstr "El contenedor no existe"
@@ -9255,7 +9341,7 @@ msgid "ContainerRegistry|Cleanup in progress"
msgstr ""
msgid "ContainerRegistry|Cleanup incomplete"
-msgstr ""
+msgstr "Limpieza incompleta"
msgid "ContainerRegistry|Cleanup is currently removing tags"
msgstr ""
@@ -9264,10 +9350,10 @@ msgid "ContainerRegistry|Cleanup is disabled for this project"
msgstr ""
msgid "ContainerRegistry|Cleanup is ongoing"
-msgstr ""
+msgstr "El proceso de limpieza está en curso"
msgid "ContainerRegistry|Cleanup pending"
-msgstr ""
+msgstr "Limpieza pendiente"
msgid "ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr "Controle los correos electrónicos vinculados a su cuenta"
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9722,7 +9808,7 @@ msgid "Copy file path"
msgstr "Copiar la ruta del archivo"
msgid "Copy issue URL to clipboard"
-msgstr ""
+msgstr "Copiar la URL de la incidencia al portapapeles"
msgid "Copy key"
msgstr "Copiar clave"
@@ -9778,9 +9864,24 @@ msgstr "Acciones"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr "Los corpus se utilizan en las pruebas de tipo fuzz como fuente de mutación para mejorar futuras pruebas."
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr "Nombre del corpus"
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr "Administración de corpus de prueba de Fuzz"
@@ -9793,9 +9894,6 @@ msgstr "Último uso"
msgid "CorpusManagement|Latest Job:"
msgstr "Último trabajo:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr "Nueva subida"
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "No se pudo encontrar el diseño."
@@ -9895,14 +9996,17 @@ msgstr "No es posible eliminar el disparador."
msgid "Could not restore the group"
msgstr "Se ha producido un error al restaurar el grupo"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "No se puede revocar el token de suplantación %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "No se pudo revocar el token de acceso personal %{personal_access_token_name}."
-msgid "Could not revoke project access token %{project_access_token_name}."
-msgstr "No se pudo revocar el token de acceso al proyecto %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
msgid "Could not save group ID"
msgstr "Se ha producido un error al guardar el ID del grupo"
@@ -9926,7 +10030,7 @@ msgid "Couldn't assign policy to project"
msgstr ""
msgid "Country"
-msgstr ""
+msgstr "País"
msgid "Coverage"
msgstr "Cobertura"
@@ -9947,10 +10051,10 @@ msgid "Create %{type}"
msgstr "Crear %{type}"
msgid "Create %{workspace} label"
-msgstr ""
+msgstr "Crear etiqueta de %{workspace}"
msgid "Create Google Cloud project"
-msgstr ""
+msgstr "Crear proyecto de Google Cloud"
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
@@ -9980,7 +10084,7 @@ msgid "Create a new issue"
msgstr "Crear una nueva incidencia"
msgid "Create a new project"
-msgstr ""
+msgstr "Crear un nuevo proyecto"
msgid "Create a new repository"
msgstr "Crear un nuevo repositorio"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr "Crear iteración"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "Crear lista"
@@ -10232,7 +10339,7 @@ msgid "CreateValueStreamForm|Recover hidden stage"
msgstr ""
msgid "CreateValueStreamForm|Restore defaults"
-msgstr ""
+msgstr "Restaurar valores predeterminados"
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
@@ -10241,13 +10348,13 @@ msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "Seleccionar evento final"
msgid "CreateValueStreamForm|Select start event"
-msgstr ""
+msgstr "Seleccionar evento inicial"
msgid "CreateValueStreamForm|Stage %{index}"
-msgstr ""
+msgstr "Etapa %{index}"
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr "Creado por mí"
msgid "Created by:"
msgstr "Creado por:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "Fecha de creación"
@@ -10367,16 +10477,16 @@ msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
msgid "Crm|Contact has been added"
-msgstr ""
+msgstr "Se ha añadido el contacto"
msgid "Crm|Contact has been updated"
-msgstr ""
+msgstr "El contacto se ha actualizado"
msgid "Crm|Create new contact"
msgstr "Crear nuevo contacto"
msgid "Crm|Create organization"
-msgstr ""
+msgstr "Crear organización"
msgid "Crm|Customer Relations Contacts"
msgstr ""
@@ -10394,25 +10504,25 @@ msgid "Crm|Edit contact"
msgstr ""
msgid "Crm|Email"
-msgstr ""
+msgstr "Correo electrónico"
msgid "Crm|First name"
-msgstr ""
+msgstr "Nombre"
msgid "Crm|Last name"
-msgstr ""
+msgstr "Apellido"
msgid "Crm|New Organization"
-msgstr ""
+msgstr "Nueva Organización"
msgid "Crm|New contact"
-msgstr ""
+msgstr "Nuevo contacto"
msgid "Crm|New organization"
-msgstr ""
+msgstr "Nueva organización"
msgid "Crm|No contacts found"
-msgstr ""
+msgstr "No se han encontrado contactos"
msgid "Crm|No organizations found"
msgstr "No se encontraron organizaciones"
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10755,10 +10868,10 @@ msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
msgid "DAST Configuration"
-msgstr ""
+msgstr "Configuración DAST"
msgid "DAST Scans"
-msgstr ""
+msgstr "Análisis DAST"
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Fecha"
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10803,7 +10919,7 @@ msgid "DORA4Metrics|The chart displays the median time between a merge request b
msgstr ""
msgid "DSN"
-msgstr ""
+msgstr "DSN"
msgid "Dashboard"
msgstr "Panel de control"
@@ -10839,7 +10955,7 @@ msgid "DastConfig|Generate code snippet"
msgstr "Generar fragmento de código"
msgid "DastConfig|Scan Configuration"
-msgstr "Configuración de escaneo"
+msgstr "Configuración del análisis"
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 ""
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr "Escaner DAST"
-
msgid "DastProfiles|Debug messages"
msgstr "Mensajes de depuración"
@@ -10914,7 +11018,7 @@ msgid "DastProfiles|Delete profile"
msgstr "Eliminar perfil"
msgid "DastProfiles|Do you want to discard this scanner profile?"
-msgstr "¿Desea descartar este perfil de escáner?"
+msgstr "¿Desea descartar este perfil de análisis?"
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr "¿Desea descartar este perfil del sitio?"
@@ -10926,7 +11030,7 @@ msgid "DastProfiles|Edit profile"
msgstr "Editar perfil"
msgid "DastProfiles|Edit scanner profile"
-msgstr "Editar perfil de escáner"
+msgstr "Editar perfil del análisis"
msgid "DastProfiles|Edit site profile"
msgstr "Editar perfil del sitio"
@@ -10971,7 +11075,7 @@ msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr "Mínimo = 1 segundo, Máximo = 3600 segundos"
msgid "DastProfiles|New scanner profile"
-msgstr "Nuevo perfil de escaneo"
+msgstr "Nuevo perfil de análisis"
msgid "DastProfiles|New site profile"
msgstr "Nuevo perfil del sitio"
@@ -10979,9 +11083,6 @@ msgstr "Nuevo perfil del sitio"
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,14 +11119,8 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr "Escanear"
-
msgid "DastProfiles|Scan mode"
-msgstr "Modo de escaneo"
+msgstr "Modo de análisis"
msgid "DastProfiles|Scanner Profile"
msgstr "Perfil de escaneo"
@@ -11037,10 +11129,7 @@ msgid "DastProfiles|Scanner Profiles"
msgstr "Perfiles de escaneo"
msgid "DastProfiles|Scanner name"
-msgstr "Nombre del escáner"
-
-msgid "DastProfiles|Schedule"
-msgstr ""
+msgstr "Nombre del análisis"
msgid "DastProfiles|Select branch"
msgstr "Seleccionar branch"
@@ -11063,9 +11152,6 @@ msgstr "Tipo de sitio"
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr "Destino"
-
msgid "DastProfiles|Target URL"
msgstr "URL de destino"
@@ -11335,9 +11421,6 @@ msgstr "Ramas por defecto y ramas protegidas"
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "Etiqueta de clasificación por defecto"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11567,7 +11650,7 @@ msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value S
msgstr ""
msgid "DeleteValueStream|Delete %{name}"
-msgstr ""
+msgstr "Eliminar %{name}"
msgid "Deleted"
msgstr "Eliminado"
@@ -11705,7 +11788,7 @@ msgid "Dependency list"
msgstr ""
msgid "DependencyProxy|Cached %{time}"
-msgstr ""
+msgstr "En caché %{time}"
msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Despliegues"
msgid "Deploy Keys"
msgstr "Claves de despliegue"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Desplegar en..."
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "Este despliegue se creó utilizando el API"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "cancelado"
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Iniciar una prueba gratuita"
@@ -12622,7 +12738,7 @@ msgstr "Mostrar fuente"
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,8 +12933,8 @@ msgstr "Editar comentario"
msgid "Edit Deploy Key"
msgstr "Editar la clave de despliegue"
-msgid "Edit Geo Node"
-msgstr "Editar nodo de Geo"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr "Editar hook del grupo"
@@ -12947,7 +13063,7 @@ msgid "Editing"
msgstr "Editando"
msgid "Elapsed time"
-msgstr ""
+msgstr "Tiempo transcurrido"
msgid "Elasticsearch AWS IAM credentials"
msgstr "Credenciales IAM de AWS Elasticsearch"
@@ -13063,6 +13179,9 @@ msgstr "No es posible averiguar a qué usuario corresponde al correo electrónic
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "No es posible encontrar el proyecto. Por favor, compruebe si hay algún error tipográfico."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "No se le permite realizar esta acción. Si cree que esto se debe a un error, por favor, póngase en contacto con un miembro del personal."
@@ -13207,9 +13326,6 @@ msgstr "Habilitar la autenticación"
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "Habilitar control de clasificación utilizando un servicio externo"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Habilitar el modo de mantenimiento"
@@ -13279,6 +13398,12 @@ msgstr "Habilitar reCAPTCHA para iniciar sesión."
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr "Reforzar la protección de ataques a DNS"
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13367,7 +13489,7 @@ msgid "Enforce personal access token expiration"
msgstr ""
msgid "Enforce two-factor authentication"
-msgstr ""
+msgstr "Forzar la autenticación de doble factor"
msgid "Enforce two-factor authentication for all user sign-ins."
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr "Introduzca a continuación, la URL de su servidor de Bitbucket y su toke
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "Introduzca la URL de su servidor Phabricator y su token de acceso"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Introduzca las URL de la solicitud de fusión"
@@ -13421,10 +13546,10 @@ msgid "Enter one or more user ID separated by commas"
msgstr "Introduzca uno o más ID de usuario separados por comas"
msgid "Enter the %{name} description"
-msgstr ""
+msgstr "Introduzca la descripción de %{name}"
msgid "Enter the %{name} title"
-msgstr ""
+msgstr "Introduzca el título de %{name}"
msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
msgstr ""
@@ -13576,7 +13701,7 @@ msgid "Environments|Delete"
msgstr "Eliminar"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "¿Eliminar '%{environmentName}'?"
msgid "Environments|Delete environment"
msgstr "Eliminar entorno"
@@ -13591,7 +13716,7 @@ msgid "Environments|Deployment"
msgstr "Despliegue"
msgid "Environments|Deployment %{status}"
-msgstr ""
+msgstr "Despliegue %{status}"
msgid "Environments|Enable review app"
msgstr ""
@@ -13621,7 +13746,7 @@ msgid "Environments|Logs from %{start} to %{end}."
msgstr "Logs desde %{start} hasta %{end}."
msgid "Environments|More information"
-msgstr ""
+msgstr "Más información"
msgid "Environments|New environment"
msgstr "Nuevo entorno"
@@ -13681,6 +13806,9 @@ msgid "Environments|Stop environment"
msgstr "Detener entorno"
msgid "Environments|Stopping %{environmentName}"
+msgstr "Deteniendo %{environmentName}"
+
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
msgstr ""
msgid "Environments|There was an error fetching the logs. Please try again."
@@ -13705,11 +13833,14 @@ msgid "Environments|You don't have any environments right now"
msgstr "No tiene ningún entorno ahora mismo"
msgid "Environments|by %{avatar}"
-msgstr ""
+msgstr "por %{avatar}"
msgid "Environments|protected"
msgstr "protegido"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Épica"
@@ -13783,10 +13914,10 @@ msgid "Epics|Remove issue"
msgstr "Eliminar la incidencia"
msgid "Epics|Search epics"
-msgstr ""
+msgstr "Buscar tareas épicas"
msgid "Epics|Select epic"
-msgstr ""
+msgstr "Seleccionar épica"
msgid "Epics|Show more"
msgstr "Mostrar más"
@@ -13798,7 +13929,7 @@ msgid "Epics|Something went wrong while creating child epics."
msgstr "Se ha producido un error al crear las tareas épicas hijas."
msgid "Epics|Something went wrong while creating issue."
-msgstr ""
+msgstr "Se ha producido un error al crear la incidencia."
msgid "Epics|Something went wrong while fetching child epics."
msgstr "Se ha producido un error al obtener las tareas épicas hijas."
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "Política de autorización de clasificación externa"
-
msgid "External ID"
msgstr "ID externo"
@@ -14507,15 +14635,9 @@ msgstr "URL externa"
msgid "External User:"
msgstr "Usuario externo"
-msgid "External authentication"
-msgstr "Autenticación externa"
-
msgid "External authorization denied access to this project"
msgstr "Se ha denegado la autorización externa para el acceso a este proyecto"
-msgid "External authorization request timeout"
-msgstr "Tiempo de espera agotado para la solicitud de acceso"
-
msgid "External storage URL"
msgstr "URL de almacenamiento externo"
@@ -14531,6 +14653,54 @@ msgstr "Etiqueta de clasificación"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Cuando no existe ninguna etiqueta de clasificación se utilizará la etiqueta predeterminada `%{default_label}'."
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14875,10 +15042,10 @@ msgid "FeatureFlags|Add strategy"
msgstr "Añadir una estrategia"
msgid "FeatureFlags|All Environments"
-msgstr ""
+msgstr "Todos los entornos"
msgid "FeatureFlags|All Users"
-msgstr ""
+msgstr "Todos los usuarios"
msgid "FeatureFlags|All users"
msgstr "Todos los usuarios"
@@ -15054,14 +15221,6 @@ msgstr "Ids de usuario"
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Feb"
@@ -15078,7 +15237,7 @@ msgid "File"
msgstr "Archivo"
msgid "File %{current} of %{total}"
-msgstr ""
+msgstr "Archivo %{current} de %{total}"
msgid "File Hooks"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr "Filtro"
msgid "Filter by"
msgstr "Filtrar por"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrar por %{issuable_type} que actualmente estén cerrados."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15198,7 +15351,7 @@ msgid "Filter parameters are not valid. Make sure that the end date is after the
msgstr ""
msgid "Filter pipelines"
-msgstr ""
+msgstr "Filtrar pipelines"
msgid "Filter results"
msgstr "Filtrar resultados"
@@ -15213,10 +15366,10 @@ msgid "Filter results..."
msgstr "Filtrar resultados..."
msgid "Filter users"
-msgstr ""
+msgstr "Filtrar usuarios"
msgid "Filter your repositories by name"
-msgstr ""
+msgstr "Filtrar sus repositorios por nombre"
msgid "Filter..."
msgstr "Filtrar..."
@@ -15390,7 +15543,7 @@ msgid "Fork project"
msgstr "Realizar un fork del proyecto"
msgid "Fork project?"
-msgstr ""
+msgstr "¿Desea realizar un fork del proyecto?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
@@ -15399,10 +15552,10 @@ msgid "ForkProject|An error occurred while forking the project. Please try again
msgstr ""
msgid "ForkProject|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "ForkProject|Create a group"
-msgstr ""
+msgstr "Crear un grupo"
msgid "ForkProject|Fork project"
msgstr ""
@@ -15411,13 +15564,13 @@ msgid "ForkProject|Forking a repository allows you to make changes without affec
msgstr ""
msgid "ForkProject|Internal"
-msgstr ""
+msgstr "Interno"
msgid "ForkProject|Please select a namespace"
-msgstr ""
+msgstr "Por favor, seleccione un espacio de nombres"
msgid "ForkProject|Please select a visibility level"
-msgstr ""
+msgstr "Por favor, seleccione el nivel de visibilidad"
msgid "ForkProject|Private"
msgstr "Privado"
@@ -15426,10 +15579,10 @@ msgid "ForkProject|Project access must be granted explicitly to each user. If th
msgstr ""
msgid "ForkProject|Public"
-msgstr ""
+msgstr "Público"
msgid "ForkProject|Select a namespace"
-msgstr ""
+msgstr "Seleccione un espacio de nombres"
msgid "ForkProject|Select a namespace to fork the project"
msgstr ""
@@ -15441,13 +15594,13 @@ msgid "ForkProject|The project can be accessed without any authentication."
msgstr ""
msgid "ForkProject|Visibility level"
-msgstr ""
+msgstr "Nivel de visibilidad"
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
msgid "ForkSuggestion|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "ForkSuggestion|Fork"
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr "Se han encontrado errores en su archivo %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Se han encontrado errores en su fichero .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15549,11 +15705,14 @@ msgid "General pipelines"
msgstr "Pipelines"
msgid "General settings"
-msgstr ""
+msgstr "Configuración general"
msgid "Generate a default set of labels"
msgstr "Generar un conjunto predeterminado de etiquetas"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Generar clave"
@@ -15561,7 +15720,7 @@ msgid "Generate new export"
msgstr "Generar nueva exportación"
msgid "Generate new token"
-msgstr ""
+msgstr "Generar un nuevo token"
msgid "Generate project access tokens scoped to this project for your applications that need access to the GitLab API."
msgstr ""
@@ -15579,10 +15738,10 @@ msgid "Generic package file size in bytes"
msgstr ""
msgid "GenericReport|After"
-msgstr ""
+msgstr "Después"
msgid "GenericReport|Before"
-msgstr ""
+msgstr "Antes"
msgid "GenericReport|Diff"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo Nodos"
-
msgid "Geo Replication"
msgstr "Replicación de Geo"
msgid "Geo Settings"
msgstr "Configuración de Geo"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr "Todo %{replicable_name}"
@@ -15681,22 +15846,25 @@ msgid "Geo|Data replication lag"
msgstr ""
msgid "Geo|Data type"
-msgstr ""
+msgstr "Tipo de datos"
msgid "Geo|Disabled"
-msgstr ""
+msgstr "Deshabilitado"
msgid "Geo|Discover GitLab Geo"
-msgstr ""
+msgstr "Descubra GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
+msgstr "No coincide con la configuración de almacenamiento primaria"
+
+msgid "Geo|Edit %{nodeType} site"
msgstr ""
msgid "Geo|Failed"
msgstr "Fallido"
msgid "Geo|Filter by name"
-msgstr ""
+msgstr "Filtrar por nombre"
msgid "Geo|Filter by status"
msgstr "Filtrar por estado"
@@ -15717,7 +15885,7 @@ msgid "Geo|Go to the primary site"
msgstr ""
msgid "Geo|Healthy"
-msgstr ""
+msgstr "Saludable"
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -15729,7 +15897,7 @@ msgid "Geo|In sync"
msgstr "Sincronizado"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "Geo|Last event ID from primary"
msgstr ""
@@ -15767,12 +15935,6 @@ 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"
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr "El nombre del nodo debe tener entre 1 y 255 caracteres"
-
msgid "Geo|Not synced yet"
msgstr "Sin sincronizar aún"
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Sincronización pendiente"
@@ -15795,10 +15960,10 @@ msgid "Geo|Pending verification"
msgstr "Pendiente de verificación"
msgid "Geo|Primary node"
-msgstr ""
+msgstr "Nodo principal"
msgid "Geo|Primary site"
-msgstr ""
+msgstr "Sitio principal"
msgid "Geo|Project"
msgstr "Proyecto"
@@ -15813,7 +15978,7 @@ msgid "Geo|Projects in certain storage shards"
msgstr "Proyectos en determinados grupos de almacenamiento"
msgid "Geo|Queued"
-msgstr ""
+msgstr "En cola"
msgid "Geo|Redownload"
msgstr "Volver a descargar"
@@ -15821,16 +15986,19 @@ msgstr "Volver a descargar"
msgid "Geo|Remove"
msgstr "Eliminar"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr "Eliminar entrada"
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr "Eliminar entrada de la base de datos de seguimiento"
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15840,10 +16008,7 @@ msgid "Geo|Replicated data is verified with the secondary site(s) using checksum
msgstr ""
msgid "Geo|Replication Details"
-msgstr ""
-
-msgid "Geo|Replication details"
-msgstr ""
+msgstr "Detalles de replicación"
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15852,10 +16017,10 @@ msgid "Geo|Replication slots"
msgstr ""
msgid "Geo|Replication status"
-msgstr ""
+msgstr "Estado de replicación"
msgid "Geo|Replication summary"
-msgstr ""
+msgstr "Resumen de replicación"
msgid "Geo|Resync"
msgstr "Resincronizar"
@@ -15864,10 +16029,10 @@ msgid "Geo|Resync all"
msgstr "Volver a sincronizar todo"
msgid "Geo|Resync all %{replicableType}"
-msgstr ""
+msgstr "Volver a sincronizar todo %{replicableType}"
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "Volver a sincronizar todos los proyectos"
msgid "Geo|Retry count"
msgstr "Contador de reintentos"
@@ -15879,18 +16044,24 @@ msgid "Geo|Reverify all"
msgstr "Volver a comprobar todo"
msgid "Geo|Reverify all projects"
-msgstr ""
+msgstr "Volver a comprobar todos los proyectos"
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary site."
msgstr ""
msgid "Geo|Secondary node"
-msgstr ""
+msgstr "Nodo secundario"
msgid "Geo|Secondary site"
-msgstr ""
+msgstr "Sitio secundario"
msgid "Geo|Selective (%{syncLabel})"
+msgstr "Selectivo (%{syncLabel})"
+
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
msgstr ""
msgid "Geo|Site's status was updated %{timeAgo}."
@@ -15900,7 +16071,7 @@ msgid "Geo|Status"
msgstr "Estado"
msgid "Geo|Storage config"
-msgstr ""
+msgstr "Configuración del almacenamiento"
msgid "Geo|Synced"
msgstr "Sincronizado"
@@ -15909,16 +16080,16 @@ msgid "Geo|Synced at"
msgstr "Sincronizado en"
msgid "Geo|Synchronization"
-msgstr ""
+msgstr "Sincronización"
msgid "Geo|Synchronization failed - %{error}"
msgstr "Se ha producido un error durante la sincronización - %{error}"
msgid "Geo|Synchronization settings"
-msgstr ""
+msgstr "Configuración de sincronización"
msgid "Geo|Synchronization status"
-msgstr ""
+msgstr "Estado de la sincronización"
msgid "Geo|The database is currently %{db_lag} behind the primary site."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr "No hay %{replicable_type} para mostrar"
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15957,13 +16128,13 @@ msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
msgstr "La URL debe ser una URL válida (ej: https://gitlab.com)"
msgid "Geo|Undefined"
-msgstr ""
+msgstr "Indefinido"
msgid "Geo|Unhealthy"
-msgstr ""
+msgstr "No saludable"
msgid "Geo|Unknown"
-msgstr ""
+msgstr "Desconocido"
msgid "Geo|Unknown state"
msgstr "Estado desconocido"
@@ -16010,6 +16181,9 @@ msgstr "secundario"
msgid "Get a free instance review"
msgstr "Obtenga una revisión de instancia gratuita"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16017,7 +16191,7 @@ msgid "Get started"
msgstr "Empezar"
msgid "Get started with GitLab"
-msgstr ""
+msgstr "Primeros pasos con Gitlab"
msgid "Get started with error tracking"
msgstr "Comenzar con el control de errores"
@@ -16047,7 +16221,7 @@ msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for th
msgstr ""
msgid "Git LFS status:"
-msgstr ""
+msgstr "Estado de Git LFS:"
msgid "Git global setup"
msgstr "Configuración global de Git"
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr "GitLab para Slack"
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "Miembro de GitLab o dirección de correo electrónico"
@@ -16317,7 +16491,7 @@ msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
msgid "GithubIntegration|Repository URL"
-msgstr ""
+msgstr "URL del repositorio"
msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
msgstr ""
@@ -16335,16 +16509,19 @@ msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "URL de Gitpod"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
+msgstr "https://gitpod.example.com"
msgid "Given access %{time_ago}"
msgstr "Acceso concedido %{time_ago}"
@@ -16383,10 +16560,10 @@ msgid "GlobalSearch|Results updated. %{count} results available. Use the up and
msgstr ""
msgid "GlobalSearch|Search GitLab"
-msgstr ""
+msgstr "Buscar en GitLab"
msgid "GlobalSearch|Search results are loading"
-msgstr ""
+msgstr "Se están cargando los resultados de la búsqueda"
msgid "GlobalSearch|Type and press the enter key to submit search."
msgstr ""
@@ -16395,13 +16572,13 @@ msgid "GlobalSearch|Type for new suggestions to appear below."
msgstr ""
msgid "GlobalSearch|in all GitLab"
-msgstr ""
+msgstr "en todo GitLab"
msgid "GlobalSearch|in group"
-msgstr ""
+msgstr "en el grupo"
msgid "GlobalSearch|in project"
-msgstr ""
+msgstr "en el proyecto"
msgid "Go Back"
msgstr "Volver"
@@ -16422,7 +16599,7 @@ msgid "Go full screen"
msgstr "Ir a pantalla completa"
msgid "Go to %{source_name}"
-msgstr ""
+msgstr "Ir a %{source_name}"
msgid "Go to commits"
msgstr "Ir a commits"
@@ -16434,7 +16611,7 @@ msgid "Go to environments"
msgstr "Ir a los entornos"
msgid "Go to epic"
-msgstr ""
+msgstr "Ir a la épica"
msgid "Go to file"
msgstr "Ir al archivo"
@@ -16473,16 +16650,19 @@ msgid "Go to next page"
msgstr "Ir a la página siguiente"
msgid "Go to page %{page}"
-msgstr ""
+msgstr "Ir a la página %{page}"
msgid "Go to parent"
msgstr "Ir al principal"
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr "Ir a la página anterior"
msgid "Go to primary site"
-msgstr ""
+msgstr "Ir al sitio principal"
msgid "Go to project"
msgstr "Ir al proyecto"
@@ -16623,7 +16803,7 @@ msgid "GraphViewType|Stage"
msgstr ""
msgid "Graphs"
-msgstr ""
+msgstr "Gráficos"
msgid "Gravatar"
msgstr "Gravatar"
@@ -16646,6 +16826,9 @@ msgstr "Se ha programado el grupo %{group_name} para su eliminación."
msgid "Group %{group_name} was successfully created."
msgstr "El grupo %{group_name} se actualizó correctamente."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Estado del grupo GIT LFS:"
@@ -16664,6 +16847,9 @@ msgstr "El grupo SAML debe estar habilitado para poder probar"
msgid "Group URL"
msgstr "URL del grupo"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16725,10 +16911,7 @@ msgid "Group is required when cluster_type is :group"
msgstr ""
msgid "Group jobs by"
-msgstr ""
-
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Los mantenedores de grupo pueden registrar grupos de ejecutores en el %{link}"
+msgstr "Agrupar trabajos por"
msgid "Group members"
msgstr "Miembros del grupo"
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr "Resumen del contenido del grupo"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr "La cuota de minutos del pipeline fue restablecida con éxito."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16854,7 +17037,7 @@ msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
-msgstr ""
+msgstr " Se ha producido un error al obtener las tareas épicas"
msgid "GroupRoadmap|Something went wrong while fetching milestones"
msgstr ""
@@ -16866,10 +17049,10 @@ msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timelin
msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
msgid "GroupRoadmap|This quarter"
-msgstr ""
+msgstr "Este trimestre"
msgid "GroupRoadmap|This year"
-msgstr ""
+msgstr "Este año"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
msgstr ""
@@ -16884,7 +17067,7 @@ msgid "GroupRoadmap|To widen your search, change or remove filters; from %{start
msgstr "Para ampliar su búsqueda, cambie o elimine los filtros; desde %{startDate} a %{endDate}."
msgid "GroupRoadmap|Within 3 years"
-msgstr ""
+msgstr "Dentro de 3 años"
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr "Opciones de configuración de SAML Single Sign On"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "URL del endpoint de SCIM API"
-
msgid "GroupSAML|SCIM Token"
msgstr "Token SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "La huella digital SHA1 del certificado de firma de tokens SAML. Puede obtener esta información de su proveedor de identidad, donde también se puede llamar \"Huella digital\"."
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "El token SCIM está oculto. Para ver el valor del token de nuevo, necesita "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr "Respuesta SAML válida"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Tu token SCIM"
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17073,12 +17247,15 @@ msgid "GroupSelect|No matching results"
msgstr ""
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "Buscar grupos"
msgid "GroupSelect|Select a group"
+msgstr "Seleccione un grupo"
+
+msgid "GroupSettings|Allow project and group access token creation"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17100,7 +17277,7 @@ msgid "GroupSettings|Cannot update the path because there are projects under thi
msgstr "No se puede actualizar la ruta porque hay proyectos en este grupo que contienen imágenes de Docker en su registro de contenedores. Elimine primero las imágenes de sus proyectos e inténtelo de nuevo."
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "Cambiar la URL del grupo"
msgid "GroupSettings|Changing a group's URL can have unintended side effects."
msgstr ""
@@ -17126,6 +17303,9 @@ msgstr "Desactivar las notificaciones por correo electrónico"
msgid "GroupSettings|Disable group mentions"
msgstr "Desactivar las menciones de grupo"
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr "¡Se ha generado el token de registro para los nuevos ejecutores!"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "La configuración del pipeline se actualizó para el grupo"
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17184,7 +17358,7 @@ msgid "GroupSettings|Select a subgroup to use as the source for custom project t
msgstr ""
msgid "GroupSettings|Select parent group"
-msgstr ""
+msgstr "Seleccionar grupo principal"
msgid "GroupSettings|Select the project that contains your custom Insights file."
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Esta configuración se aplica en %{ancestor_group}. Puede sobrescribir l
msgid "GroupSettings|Transfer group"
msgstr "Transferir grupo"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,23 +17474,20 @@ msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a c
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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
msgid "GroupsNew|Connect instance"
-msgstr ""
+msgstr "Conectar instancia"
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
-msgstr ""
+msgstr "Contacte con un administrador para habilitar las opciones para importar su grupo."
msgid "GroupsNew|Create group"
msgstr "Crear grupo"
msgid "GroupsNew|Create new group"
-msgstr ""
+msgstr "Crear nuevo grupo"
msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17433,10 +17604,10 @@ msgid "Header message"
msgstr "Encabezado del mensaje"
msgid "HeaderAction|incident"
-msgstr ""
+msgstr "incidente"
msgid "HeaderAction|issue"
-msgstr ""
+msgstr "incidencia"
msgid "Headers"
msgstr ""
@@ -17586,6 +17757,33 @@ msgstr[1] "Ocultar valores"
msgid "Hide values"
msgstr "Ocultar valores"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr "Hay vulnerabilidades altas o desconocidas presentes"
@@ -17646,9 +17844,6 @@ msgstr "Mantenimiento"
msgid "Housekeeping successfully started"
msgstr "Servicio de limpieza iniciado con éxito"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "Tareas de mantenimiento, exportación, ruta, transferencia, eliminación, archivo."
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "Cómo funciona"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "Aceptar los %{terms_link}"
msgid "I forgot my password"
msgstr "He olvidado mi contraseña"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17782,13 +17977,13 @@ msgid "IP Address"
msgstr "Direccion IP"
msgid "IP address expiration time"
-msgstr ""
+msgstr "Tiempo de caducidad de la dirección IP"
msgid "IP address restrictions"
-msgstr ""
+msgstr "Restricciones de la dirección IP"
msgid "IP addresses per user"
-msgstr ""
+msgstr "Direcciones IP por usuario"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr "La restricción de la subred IP solo está permitida en grupos de nivel superior"
@@ -17802,6 +17997,18 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "Si está habilitado, el acceso a los proyectos se validará en un servicio externo utilizando su etiqueta de clasificación."
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18124,7 +18328,7 @@ msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improves Git cloning performance."
-msgstr ""
+msgstr "Mejora el rendimiento de clonado de Git."
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
@@ -18175,7 +18379,7 @@ msgid "InProductMarketing|And finally %{deploy_link} a Python application."
msgstr ""
msgid "InProductMarketing|Are your runners ready?"
-msgstr ""
+msgstr "¿Sus ejecutores están preparados?"
msgid "InProductMarketing|Automated security scans directly within GitLab"
msgstr ""
@@ -18208,10 +18412,10 @@ msgid "InProductMarketing|Create a custom runner"
msgstr ""
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
-msgstr ""
+msgstr "Cree un proyecto en GitLab en 5 minutos"
msgid "InProductMarketing|Create your first project!"
-msgstr ""
+msgstr "¡Cree su primer proyecto!"
msgid "InProductMarketing|Deliver Better Products Faster"
msgstr ""
@@ -18226,22 +18430,22 @@ msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
msgid "InProductMarketing|Do you have a minute?"
-msgstr ""
+msgstr "¿Tiene un minuto?"
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
-msgstr ""
+msgstr "¿Tiene un compañero que sería perfecto para esta tarea?"
msgid "InProductMarketing|Easy"
msgstr ""
msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
-msgstr ""
+msgstr "Amplíe su viaje de DevOps con una prueba gratuita de GitLab"
msgid "InProductMarketing|Explore GitLab CI/CD"
-msgstr ""
+msgstr "Explore GitLab CI/CD"
msgid "InProductMarketing|Explore the options"
-msgstr ""
+msgstr "Explore las opciones"
msgid "InProductMarketing|Explore the power of GitLab CI/CD"
msgstr ""
@@ -18259,10 +18463,10 @@ msgid "InProductMarketing|Find out how your teams are really doing"
msgstr ""
msgid "InProductMarketing|Follow our steps"
-msgstr ""
+msgstr "Siga nuestros pasos"
msgid "InProductMarketing|Free 30-day trial"
-msgstr ""
+msgstr "Prueba gratuita de 30 días"
msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy."
msgstr ""
@@ -18286,7 +18490,7 @@ msgid "InProductMarketing|Get your team set up on GitLab"
msgstr ""
msgid "InProductMarketing|Git basics"
-msgstr ""
+msgstr "Conceptos básicos de Git"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr "Muy difícil"
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr "Incidente"
msgid "Incident Management Limits"
msgstr "Límites de gestión de incidentes"
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr "Plantilla de incidente (opcional)."
@@ -18664,7 +18877,7 @@ msgid "IncidentManagement|Missed SLA"
msgstr "SLA omitido"
msgid "IncidentManagement|No incidents to display."
-msgstr ""
+msgstr "No hay incidentes que mostrar."
msgid "IncidentManagement|Open"
msgstr "Abierto"
@@ -18694,7 +18907,7 @@ msgid "IncidentManagement|Unknown"
msgstr "Desconocido"
msgid "IncidentManagement|Unpublished"
-msgstr ""
+msgstr "Sin publicar"
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
msgstr ""
@@ -18703,7 +18916,7 @@ msgid "IncidentSettings|Fine-tune incident settings and set up integrations with
msgstr ""
msgid "IncidentSettings|Grafana integration"
-msgstr ""
+msgstr "Integración de Grafana"
msgid "IncidentSettings|Incident settings"
msgstr ""
@@ -18715,7 +18928,7 @@ msgid "IncidentSettings|Introduce a countdown timer in incident issues to better
msgstr ""
msgid "IncidentSettings|PagerDuty integration"
-msgstr ""
+msgstr "Integración con PagerDuty"
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -18724,10 +18937,10 @@ msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
msgstr ""
msgid "IncidentSettings|Time limit must be a valid number."
-msgstr ""
+msgstr "El límite de tiempo debe ser un número válido."
msgid "IncidentSettings|Time limit must be greater than 0."
-msgstr ""
+msgstr "El límite de tiempo debe ser mayor que 0."
msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
msgstr ""
@@ -18742,7 +18955,7 @@ msgid "Incidents"
msgstr "Incidentes"
msgid "Incidents|Add a URL"
-msgstr ""
+msgstr "Añadir una URL"
msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
msgstr ""
@@ -18763,19 +18976,19 @@ msgid "Incidents|You can optionally add a URL to link users to the original grap
msgstr ""
msgid "Incident|Alert details"
-msgstr ""
+msgstr "Detalles de la alerta"
msgid "Incident|Are you sure you wish to delete this image?"
-msgstr ""
+msgstr "¿Está seguro que desea eliminar esta imagen?"
msgid "Incident|Deleting %{filename}"
-msgstr ""
+msgstr "Eliminando %{filename}"
msgid "Incident|Metrics"
-msgstr ""
+msgstr "Métricas"
msgid "Incident|Summary"
-msgstr ""
+msgstr "Resumen"
msgid "Incident|There was an issue loading alert data. Please try again."
msgstr ""
@@ -18874,7 +19087,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 ""
@@ -19028,9 +19241,6 @@ msgstr "Añadir una integración"
msgid "Integrations|Add namespace"
msgstr "Añadir espacio de nombres"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Todos los detalles"
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr "Limitaciones del navegador"
-
msgid "Integrations|Comment detail:"
msgstr "Detalles del comentario:"
@@ -19071,7 +19278,7 @@ msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
msgid "Integrations|Edit project alias"
-msgstr ""
+msgstr "Editar el alias del proyecto"
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
@@ -19080,7 +19287,7 @@ msgid "Integrations|Enable comments"
msgstr "Habilitar comentarios"
msgid "Integrations|Enter your alias"
-msgstr ""
+msgstr "Introduzca su alias"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr "No hay espacios de nombres disponibles."
msgid "Integrations|No linked namespaces"
msgstr "No hay espacios de nombres vinculados"
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19161,10 +19368,10 @@ msgid "Integrations|Saving will update the default settings for all projects tha
msgstr ""
msgid "Integrations|Search Jira issues"
-msgstr ""
+msgstr "Buscar incidencias de Jira"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "Buscar incidencias de ZenTao"
msgid "Integrations|Send notifications about project events to Unify Circuit."
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr "Estándar"
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "URL interna (opcional)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -19269,7 +19482,7 @@ msgid "Invalid URL"
msgstr "URL no válida"
msgid "Invalid URL: %{url}"
-msgstr ""
+msgstr "URL no válida: %{url}"
msgid "Invalid container_name"
msgstr "Nombre del contenedor no válido"
@@ -19398,13 +19611,13 @@ msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_o
msgstr ""
msgid "InviteEmail|%{project_or_group} details"
-msgstr ""
+msgstr "detalles de %{project_or_group}"
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
msgstr ""
msgid "InviteEmail|Join now"
-msgstr ""
+msgstr "Únase ahora"
msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
msgstr ""
@@ -19473,28 +19686,28 @@ msgid "InviteMembersModal|Invite"
msgstr "Invitar"
msgid "InviteMembersModal|Invite a group"
-msgstr ""
+msgstr "Invitar a un grupo"
msgid "InviteMembersModal|Invite members"
-msgstr ""
+msgstr "Invitar miembros"
msgid "InviteMembersModal|Members were successfully added"
-msgstr ""
+msgstr "Los miembros se han añadido correctamente"
msgid "InviteMembersModal|Search for a group to invite"
-msgstr ""
+msgstr "Buscar un grupo para invitar"
msgid "InviteMembersModal|Select a group to invite"
-msgstr ""
+msgstr "Seleccione un grupo para invitar"
msgid "InviteMembersModal|Select a role"
-msgstr ""
+msgstr "Seleccione un rol"
msgid "InviteMembersModal|Select members or type email addresses"
-msgstr ""
+msgstr "Seleccione miembros o escriba las direcciones de correo electrónico"
msgid "InviteMembersModal|Something went wrong"
-msgstr ""
+msgstr "Algo salió mal"
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
@@ -19692,7 +19905,7 @@ msgid "Issue published on status page."
msgstr ""
msgid "Issue types"
-msgstr ""
+msgstr "Tipos de incidencias"
msgid "Issue update failed"
msgstr "Se ha producido un error al actualizar incidencia"
@@ -19704,7 +19917,7 @@ msgid "Issue weight"
msgstr "Peso de la incidencia"
msgid "Issue(s) already assigned"
-msgstr ""
+msgstr "Incidencia(s) ya asignadas"
msgid "IssueAnalytics|Age"
msgstr "Edad"
@@ -19755,13 +19968,13 @@ msgid "IssueBoards|Switch board"
msgstr "Cambiar tablero"
msgid "IssueList|created %{timeAgoString} by %{user}"
-msgstr ""
+msgstr "creado %{timeAgoString} por %{user}"
msgid "IssueTracker|Custom issue tracker"
msgstr "Gestor de incidencias personalizado"
msgid "IssueTracker|Issue URL"
-msgstr ""
+msgstr "URL de la incidencia"
msgid "IssueTracker|New issue URL"
msgstr ""
@@ -19911,31 +20124,31 @@ msgid "Iteration removed"
msgstr "Iteración eliminada"
msgid "Iteration updated"
-msgstr ""
+msgstr "Iteración actualizada"
msgid "Iterations"
msgstr "Iteraciones"
msgid "Iterations|Add iteration"
-msgstr ""
+msgstr "Añadir iteración"
msgid "Iterations|Automated scheduling"
-msgstr ""
+msgstr "Programación automática"
msgid "Iterations|Cadence configuration is invalid."
-msgstr ""
+msgstr "La configuración de la cadencia no es válida."
msgid "Iterations|Cadence name"
-msgstr ""
+msgstr "Nombre de la cadencia"
msgid "Iterations|Couldn't find iteration cadence"
msgstr ""
msgid "Iterations|Create cadence"
-msgstr ""
+msgstr "Crear cadencia"
msgid "Iterations|Create cadence and start iteration"
-msgstr ""
+msgstr "Crear cadencia e iniciar iteración"
msgid "Iterations|Create iteration"
msgstr ""
@@ -20145,13 +20358,13 @@ msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{proj
msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
-msgstr ""
+msgstr "Se ha producido un error al obtener la lista de incidencias"
msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
msgstr ""
msgid "JiraService|Base URL of the Jira instance."
-msgstr ""
+msgstr "URL base de la instancia de Jira."
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -20160,13 +20373,13 @@ msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functio
msgstr ""
msgid "JiraService|Enable Jira issues"
-msgstr ""
+msgstr "Habilitar incidencias de Jira"
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
msgid "JiraService|Enable Jira transitions"
-msgstr ""
+msgstr "Habilitar transiciones de Jira"
msgid "JiraService|Enter new password or API token"
msgstr ""
@@ -20181,10 +20394,10 @@ msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
msgid "JiraService|For example, 12, 24"
-msgstr ""
+msgstr "Por ejemplo, 12, 24"
msgid "JiraService|For example, AB"
-msgstr ""
+msgstr "Por ejemplo, AB"
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
@@ -20211,19 +20424,19 @@ msgid "JiraService|Jira issue type"
msgstr ""
msgid "JiraService|Jira issues"
-msgstr ""
+msgstr "Incidencias de Jira"
msgid "JiraService|Jira project key"
-msgstr ""
+msgstr "Clave del proyecto Jira"
msgid "JiraService|Leave blank to use your current password or API token."
-msgstr ""
+msgstr "Déjelo en blanco para usar su contraseña o token del API actual."
msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Open Jira"
-msgstr ""
+msgstr "Abrir Jira"
msgid "JiraService|Password or API token"
msgstr "Contraseña o token del API"
@@ -20235,7 +20448,7 @@ msgid "JiraService|Project key is required to generate issue types"
msgstr ""
msgid "JiraService|Select issue type"
-msgstr ""
+msgstr "Seleccione el tipo de incidencia"
msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
@@ -20247,10 +20460,10 @@ msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|This is a Premium feature"
-msgstr ""
+msgstr "Esta es una característica Premium"
msgid "JiraService|This is an Ultimate feature"
-msgstr ""
+msgstr "Esta es una característica Ultimate"
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20277,7 +20490,7 @@ msgid "JiraService|Using Jira for issue tracking?"
msgstr ""
msgid "JiraService|View Jira issues in GitLab"
-msgstr ""
+msgstr "Ver las incidencias de Jira en GitLab"
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below."
msgstr ""
@@ -20304,10 +20517,10 @@ msgid "Job ID"
msgstr "Id del trabajo"
msgid "Job artifact"
-msgstr ""
+msgstr "Artefacto del trabajo"
msgid "Job artifacts"
-msgstr ""
+msgstr "Artefactos del trabajo"
msgid "Job has been erased"
msgstr "El trabajo ha sido eliminado"
@@ -20439,10 +20652,10 @@ msgid "Job|into"
msgstr "en"
msgid "Job|manual"
-msgstr ""
+msgstr "manual"
msgid "Job|triggered"
-msgstr ""
+msgstr "activado"
msgid "Job|with"
msgstr "con"
@@ -20451,19 +20664,19 @@ msgid "Join Zoom meeting"
msgstr "Unirse a la reunión de Zoom"
msgid "Join a project"
-msgstr ""
+msgstr "Unirse a un proyecto"
msgid "Join your team on GitLab and contribute to an existing project"
msgstr ""
msgid "Joined %{time_ago}"
-msgstr ""
+msgstr "Se unió el %{time_ago}"
msgid "Joined %{user_created_time}"
-msgstr ""
+msgstr "Se unió el %{user_created_time}"
msgid "Joined projects (%{projects_count})"
-msgstr ""
+msgstr "Se unió a los proyectos (%{projects_count})"
msgid "Jul"
msgstr "Jul"
@@ -20499,7 +20712,7 @@ msgid "Keep divergent refs"
msgstr ""
msgid "Keep editing"
-msgstr ""
+msgstr "Seguir editando"
msgid "Keeping all SAST analyzers enabled future-proofs the project in case new languages are added later on. Determining which analyzers apply is a process that consumes minimal resources and adds minimal time to the pipeline. Leaving all SAST analyzers enabled ensures maximum coverage."
msgstr ""
@@ -20520,22 +20733,22 @@ msgid "Keyboard shortcuts"
msgstr "Atajos de teclado"
msgid "KeyboardKey|Alt"
-msgstr ""
+msgstr "Alt"
msgid "KeyboardKey|Ctrl"
-msgstr ""
+msgstr "Ctrl"
msgid "KeyboardKey|Ctrl+"
-msgstr ""
+msgstr "Ctrl+"
msgid "KeyboardKey|Enter"
-msgstr ""
+msgstr "Intro"
msgid "KeyboardKey|Esc"
-msgstr ""
+msgstr "Esc"
msgid "KeyboardKey|Shift"
-msgstr ""
+msgstr "Mayúsculas"
msgid "KeyboardShortcuts|No shortcuts matched your search"
msgstr ""
@@ -20550,7 +20763,7 @@ msgid "Ki"
msgstr ""
msgid "Kontra"
-msgstr ""
+msgstr "Kontra"
msgid "Kroki"
msgstr "Kroki"
@@ -20583,7 +20796,7 @@ msgid "Kubernetes cluster was successfully updated."
msgstr "El clúster de Kubernetes se actualizó correctamente."
msgid "Kubernetes clusters"
-msgstr ""
+msgstr "Clústeres de Kubernetes"
msgid "Kubernetes deployment not found"
msgstr "Despliegue de Kubernetes no encontrado"
@@ -20595,10 +20808,10 @@ msgid "LDAP"
msgstr "LDAP"
msgid "LDAP Synchronization"
-msgstr ""
+msgstr "Sincronización LDAP"
msgid "LDAP group settings"
-msgstr ""
+msgstr "Configuración del grupo LDAP"
msgid "LDAP settings"
msgstr "Configuración LDAP"
@@ -20610,10 +20823,10 @@ msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to
msgstr "Sincronización LDAP en curso. Esto podría tardar unos minutos. Por favor, actualice la página para ver los cambios."
msgid "LDAP synchronizations"
-msgstr ""
+msgstr "Sincronizaciones LDAP"
msgid "LDAP uid:"
-msgstr ""
+msgstr "uid de LDAP:"
msgid "LFS"
msgstr "LFS"
@@ -20637,7 +20850,7 @@ msgid "Label actions dropdown"
msgstr "Desplegable de acciones de las etiquetaa"
msgid "Label priority"
-msgstr ""
+msgstr "Prioridad de etiqueta"
msgid "Label was created"
msgstr "Etiqueta creada"
@@ -20670,7 +20883,7 @@ msgid "Labels can be applied to issues and merge requests."
msgstr "Las etiquetas se pueden aplicar a las incidencias y a los merge requests."
msgid "Labels with no issues in this iteration:"
-msgstr ""
+msgstr "Etiquetas sin incidencias en esta iteración:"
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
@@ -20930,10 +21143,10 @@ msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLa
msgstr ""
msgid "LearnGitLab|Create an issue"
-msgstr ""
+msgstr "Crear una incidencia"
msgid "LearnGitLab|Create or import a repository"
-msgstr ""
+msgstr "Crear o importar un repositorio"
msgid "LearnGitLab|Create or import your first repository into your new project."
msgstr ""
@@ -20942,7 +21155,7 @@ msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and pl
msgstr ""
msgid "LearnGitLab|Deploy"
-msgstr ""
+msgstr "Desplegar"
msgid "LearnGitLab|Enable require merge approvals"
msgstr ""
@@ -20954,7 +21167,7 @@ msgid "LearnGitLab|Invite your colleagues"
msgstr ""
msgid "LearnGitLab|Learn GitLab"
-msgstr ""
+msgstr "Aprender GitLab"
msgid "LearnGitLab|Plan and execute"
msgstr ""
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21349,16 +21565,16 @@ msgid "Live preview"
msgstr "Vista previa"
msgid "Load more"
-msgstr ""
+msgstr "Cargar más"
msgid "Load more users"
-msgstr ""
+msgstr "Cargar más usuarios"
msgid "Loading"
msgstr "Cargando"
msgid "Loading %{name}"
-msgstr ""
+msgstr "Cargando %{name}"
msgid "Loading contribution stats for group members"
msgstr "Cargando las estadísticas de las colaboraciones de los miembros del grupo"
@@ -21370,7 +21586,7 @@ msgid "Loading functions timed out. Please reload the page to try again."
msgstr "Se agotó el tiempo de espera al cargar las funciones. Por favor, vuelva a cargar la página e inténtelo de nuevo."
msgid "Loading more"
-msgstr ""
+msgstr "Cargar más"
msgid "Loading snippet"
msgstr "Cargando fragmento de código"
@@ -21384,9 +21600,6 @@ msgstr "Cargando..."
msgid "Loading…"
msgstr "Cargando…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Localización"
@@ -21402,6 +21615,9 @@ msgstr "Bloquear"
msgid "Lock %{issuableDisplayName}"
msgstr "Bloquear %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr "Bloquear membresías a la sincronización LDAP"
@@ -21438,6 +21654,39 @@ msgstr "Los bloqueos brindan la capacidad de bloquear archivos o carpetas especÃ
msgid "Locks the discussion."
msgstr "Bloquea la discusión."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Iniciar sesión con una tarjeta inteligente"
@@ -21568,7 +21817,7 @@ msgid "Manage project labels"
msgstr "Administrar etiquetas de proyectos"
msgid "Manage projects."
-msgstr ""
+msgstr "Administrar proyectos"
msgid "Manage two-factor authentication"
msgstr "Administrar autenticación de dos factores"
@@ -21700,13 +21949,13 @@ msgid "Match not found; try refining your search query."
msgstr "No se encontró la coincidencia; por favor refine la consulta de su búsqueda."
msgid "Mattermost"
-msgstr ""
+msgstr "Mattermost"
msgid "Mattermost URL:"
-msgstr ""
+msgstr "URL de Mattermost:"
msgid "Mattermost notifications"
-msgstr ""
+msgstr "Notificaciones de Mattermost"
msgid "MattermostService|Add to Mattermost"
msgstr "Agregar a Mattermost"
@@ -21739,13 +21988,13 @@ msgid "MattermostService|Use this service to perform common tasks in your projec
msgstr ""
msgid "Max 100,000 events"
-msgstr ""
+msgstr "Máx. 100.000 eventos"
msgid "Max authenticated Git LFS requests per period per user"
msgstr ""
msgid "Max file size is 200 KB."
-msgstr ""
+msgstr "El tamaño máximo del archivo es de 200 KB."
msgid "Max role"
msgstr ""
@@ -21754,7 +22003,7 @@ msgid "Max session time"
msgstr ""
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "Máximo 20 caracteres"
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -22060,13 +22309,13 @@ msgid "Members|Direct"
msgstr ""
msgid "Members|Disabled"
-msgstr ""
+msgstr "Deshabilitado"
msgid "Members|Edit permissions"
msgstr ""
msgid "Members|Enabled"
-msgstr ""
+msgstr "Habilitado"
msgid "Members|Expiration date removed successfully."
msgstr ""
@@ -22075,7 +22324,7 @@ msgid "Members|Expiration date updated successfully."
msgstr ""
msgid "Members|Filter members"
-msgstr ""
+msgstr "Filtrar miembros"
msgid "Members|Inherited"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "Ejecutar merge cuando el pipeline se ejecute con éxito"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "Commit a la rama origen"
@@ -22501,7 +22765,7 @@ msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
-msgstr ""
+msgstr "UTC (hora universal coordinada)"
msgid "MetricsSettings|User's local timezone"
msgstr ""
@@ -22522,28 +22786,28 @@ msgid "Metrics|Add metric"
msgstr "Añadir métrica"
msgid "Metrics|Add panel"
-msgstr ""
+msgstr "Añadir panel"
msgid "Metrics|Avg"
msgstr "Avg"
msgid "Metrics|Back to dashboard"
-msgstr ""
+msgstr "Volver al panel de control"
msgid "Metrics|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consulte la documentación de CI/CD sobre la implementación en un entorno"
msgid "Metrics|Collapse panel"
-msgstr ""
+msgstr "Contraer panel"
msgid "Metrics|Collapse panel (Esc)"
-msgstr ""
+msgstr "Contraer panel (Esc)"
msgid "Metrics|Copy YAML"
-msgstr ""
+msgstr "Copiar YAML"
msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
msgstr ""
@@ -22629,10 +22893,10 @@ msgid "Metrics|Metrics Settings"
msgstr ""
msgid "Metrics|Min"
-msgstr ""
+msgstr "Min"
msgid "Metrics|More actions"
-msgstr ""
+msgstr "Más acciones"
msgid "Metrics|Must be a valid PromQL query."
msgstr "Debe ser una consulta PromQL válida."
@@ -22641,10 +22905,10 @@ msgid "Metrics|New metric"
msgstr "Nueva métrica"
msgid "Metrics|Open repository"
-msgstr ""
+msgstr "Abrir repositorio"
msgid "Metrics|Panel YAML"
-msgstr ""
+msgstr "Panel YAML"
msgid "Metrics|Panel YAML copied"
msgstr ""
@@ -22976,7 +23240,7 @@ msgid "Mirroring will only be available if the feature is included in the plan o
msgstr ""
msgid "Miscellaneous"
-msgstr ""
+msgstr "Miscelánea"
msgid "Missing"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "Meses"
msgid "More Information"
msgstr "Más información"
-msgid "More Slack commands"
-msgstr "Más comandos de Slack"
-
msgid "More actions"
msgstr "Más acciones"
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "Más de %{number_commits_distance} commits diferente con %{default_branch}"
@@ -23153,7 +23411,7 @@ msgid "MrDeploymentActions|Stop environment"
msgstr "Detener entorno"
msgid "Multi-project"
-msgstr ""
+msgstr "Multi-proyecto"
msgid "Multi-project Runners cannot be removed"
msgstr ""
@@ -23204,7 +23462,7 @@ msgid "Name"
msgstr "Nombre"
msgid "Name can't be blank"
-msgstr ""
+msgstr "El nombre no puede estar en blanco"
msgid "Name has already been taken"
msgstr "El nombre ya está en uso"
@@ -23219,16 +23477,16 @@ msgid "Name:"
msgstr "Nombre:"
msgid "Namespace"
-msgstr ""
+msgstr "Espacio de nombres"
msgid "Namespace ID:"
-msgstr ""
+msgstr "ID del namespace :"
msgid "Namespace is empty"
msgstr "Espacio de nombres está vacía"
msgid "Namespace:"
-msgstr ""
+msgstr "Espacio de nombres:"
msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
@@ -23256,17 +23514,17 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
msgstr ""
msgid "Namespaces"
-msgstr ""
+msgstr "Espacios de nombres"
msgid "Namespaces to index"
msgstr "Espacios de nombres a indexar"
@@ -23281,40 +23539,40 @@ msgid "Navigate to the project to close the milestone."
msgstr "Desplácese hasta el proyecto para cerrar el hito."
msgid "Navigation bar"
-msgstr ""
+msgstr "Barra de navegación"
msgid "NavigationTheme|Blue"
-msgstr ""
+msgstr "Azul"
msgid "NavigationTheme|Dark"
-msgstr ""
+msgstr "Oscuro"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "Modo oscuro (alfa)"
msgid "NavigationTheme|Green"
-msgstr ""
+msgstr "Verde"
msgid "NavigationTheme|Indigo"
-msgstr ""
+msgstr "Ãndigo"
msgid "NavigationTheme|Light"
-msgstr ""
+msgstr "Claro"
msgid "NavigationTheme|Light Blue"
-msgstr ""
+msgstr "Azul claro"
msgid "NavigationTheme|Light Green"
-msgstr ""
+msgstr "Verde claro"
msgid "NavigationTheme|Light Indigo"
-msgstr ""
+msgstr "Ãndigo claro"
msgid "NavigationTheme|Light Red"
-msgstr ""
+msgstr "Rojo claro"
msgid "NavigationTheme|Red"
-msgstr ""
+msgstr "Rojo"
msgid "Nav|Help"
msgstr "Ayuda"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23392,28 +23647,28 @@ msgid "NetworkPolicies|Are you sure you want to delete this policy? This action
msgstr ""
msgid "NetworkPolicies|Create policy"
-msgstr ""
+msgstr "Crear política"
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
-msgstr ""
+msgstr "Definir la ubicación, las condiciones y las acciones de esta política."
msgid "NetworkPolicies|Delete policy"
-msgstr ""
+msgstr "Eliminar política"
msgid "NetworkPolicies|Delete policy: %{policy}"
-msgstr ""
+msgstr "Eliminar política: %{policy}"
msgid "NetworkPolicies|Deny all traffic"
-msgstr ""
+msgstr "Denegar todo el tráfico"
msgid "NetworkPolicies|Edit policy"
msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
-msgstr ""
+msgstr "El entorno no tiene plataforma de despliegue"
msgid "NetworkPolicies|IP/subnet"
-msgstr ""
+msgstr "IP/subred"
msgid "NetworkPolicies|Invalid or empty policy"
msgstr "Política no válida o vacía"
@@ -23434,10 +23689,10 @@ msgid "NetworkPolicies|Network policy can be created after the environment is lo
msgstr ""
msgid "NetworkPolicies|Network traffic"
-msgstr ""
+msgstr "Tráfico de red"
msgid "NetworkPolicies|None selected"
-msgstr ""
+msgstr "Ninguna seleccionada"
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23445,17 +23700,14 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr "Definición de la política"
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
-msgstr ""
+msgstr "Modo de la regla"
msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
msgstr ""
msgid "NetworkPolicies|Save changes"
-msgstr ""
+msgstr "Guardar cambios"
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr "Algo salió mal, se ha producido un error al actualizar la política"
@@ -23466,23 +23718,20 @@ msgstr "Algo salió mal, se ha producido un error al obtener las políticas"
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
-msgstr ""
+msgstr "Todos los nombres de DNS"
msgid "NetworkPolicies|all IP addresses"
msgstr ""
msgid "NetworkPolicies|any pod"
-msgstr ""
+msgstr "cualquier pod"
msgid "NetworkPolicies|any port"
msgstr ""
msgid "NetworkPolicies|domain name"
-msgstr ""
+msgstr "nombre de dominio"
msgid "NetworkPolicies|entity"
msgstr ""
@@ -23586,19 +23835,19 @@ msgid "New Project"
msgstr "Nuevo proyecto"
msgid "New Requirement"
-msgstr ""
+msgstr "Nuevo requisito"
msgid "New Snippet"
msgstr "Nuevo fragmento de código"
msgid "New Test Case"
-msgstr ""
+msgstr "Nuevo caso de prueba"
msgid "New User"
msgstr "Nuevo usuario"
msgid "New application"
-msgstr ""
+msgstr "Nueva aplicación"
msgid "New branch"
msgstr "Nueva rama"
@@ -23619,7 +23868,7 @@ msgid "New directory"
msgstr "Nuevo directorio"
msgid "New discussion"
-msgstr ""
+msgstr "Nueva discusión"
msgid "New environment"
msgstr "Nuevo entorno"
@@ -23637,10 +23886,10 @@ msgid "New group"
msgstr "Nuevo grupo"
msgid "New group URL"
-msgstr ""
+msgstr "Nueva URL de grupo"
msgid "New group name"
-msgstr ""
+msgstr "Nuevo nombre de grupo"
msgid "New health check access token has been generated!"
msgstr "¡Se ha generado un nuevo token de acceso para la verificación de estado!"
@@ -23685,10 +23934,10 @@ msgid "New project"
msgstr "Nuevo proyecto"
msgid "New project page"
-msgstr ""
+msgstr "Nueva página de proyecto"
msgid "New project pages"
-msgstr ""
+msgstr "Nuevas páginas de proyecto"
msgid "New project/repository"
msgstr "Nuevo proyecto/repositorio"
@@ -23808,7 +24057,7 @@ msgid "No artifacts found"
msgstr ""
msgid "No assignee"
-msgstr ""
+msgstr "Sin asignar"
msgid "No authentication methods configured."
msgstr "No hay métodos de autenticación configurados."
@@ -23984,11 +24233,14 @@ msgstr "Sin hito"
msgid "No milestones to show"
msgstr "No hay hitos para mostrar"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "No hay otras etiquetas con ese nombre o descripción"
msgid "No panels matching properties %{opts}"
-msgstr ""
+msgstr "No hay paneles que coincidan con las propiedades %{opts}"
msgid "No parent group"
msgstr "Ningún grupo padre"
@@ -24011,17 +24263,20 @@ msgstr "No hay etiquetas priorizadas con dicho nombre o descripción"
msgid "No profiles found"
msgstr "No se encontraron perfiles"
-msgid "No projects found"
+msgid "No project subscribes to the pipelines in this project."
msgstr ""
+msgid "No projects found"
+msgstr "No se encontraron proyectos"
+
msgid "No public deploy keys"
-msgstr ""
+msgstr "No hay claves públicas de despliegue"
msgid "No public groups"
msgstr "No hay grupos públicos"
msgid "No ref selected"
-msgstr ""
+msgstr "Ningún ref seleccionado"
msgid "No related merge requests found."
msgstr ""
@@ -24039,7 +24294,7 @@ msgid "No schedules"
msgstr "No hay programaciones"
msgid "No service accounts"
-msgstr ""
+msgstr "Sin cuentas de servicio"
msgid "No severity matches the provided parameter"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr "No se han encontrado vulnerabilidades"
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24391,7 +24646,7 @@ msgid "Number of files touched"
msgstr "Número de archivos tocados"
msgid "Number of replicas"
-msgstr ""
+msgstr "Número de réplicas"
msgid "Number of shards"
msgstr ""
@@ -24448,10 +24703,10 @@ msgid "OnCallScheduless|Any escalation rules that are using this schedule will a
msgstr ""
msgid "OnCallSchedules|1 day"
-msgstr ""
+msgstr "1 día"
msgid "OnCallSchedules|2 weeks"
-msgstr ""
+msgstr "2 semanas"
msgid "OnCallSchedules|Add a rotation"
msgstr ""
@@ -24460,7 +24715,7 @@ msgid "OnCallSchedules|Add a schedule"
msgstr ""
msgid "OnCallSchedules|Add an additional schedule to your project"
-msgstr ""
+msgstr "Añada un horario adicional a su proyecto"
msgid "OnCallSchedules|Add rotation"
msgstr ""
@@ -24475,7 +24730,7 @@ msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\"
msgstr ""
msgid "OnCallSchedules|Collapse schedule"
-msgstr ""
+msgstr "Colapsar horario"
msgid "OnCallSchedules|Create on-call schedules in GitLab"
msgstr ""
@@ -24499,7 +24754,7 @@ msgid "OnCallSchedules|Enable end date"
msgstr ""
msgid "OnCallSchedules|Expand schedule"
-msgstr ""
+msgstr "Expandir horario"
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -24625,7 +24880,7 @@ msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Delete profile"
-msgstr ""
+msgstr "Eliminar perfil"
msgid "OnDemandScans|Description (optional)"
msgstr ""
@@ -24634,7 +24889,7 @@ msgid "OnDemandScans|Edit on-demand DAST scan"
msgstr ""
msgid "OnDemandScans|Edit profile"
-msgstr ""
+msgstr "Editar perfil"
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
@@ -24676,10 +24931,10 @@ msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulne
msgstr ""
msgid "OnDemandScans|Repeats"
-msgstr ""
+msgstr "Repetir"
msgid "OnDemandScans|Run scan"
-msgstr ""
+msgstr "Ejecutar análisis"
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -24694,7 +24949,7 @@ msgid "OnDemandScans|Scan name"
msgstr ""
msgid "OnDemandScans|Scan type"
-msgstr ""
+msgstr "Tipo de análisis"
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24703,7 +24958,7 @@ msgid "OnDemandScans|Schedule scan"
msgstr ""
msgid "OnDemandScans|Select one of the existing profiles"
-msgstr ""
+msgstr "Seleccione uno de los perfiles existentes"
msgid "OnDemandScans|Site profile"
msgstr ""
@@ -24715,22 +24970,22 @@ msgid "OnDemandScans|Target"
msgstr ""
msgid "OnDemandScans|The scan could not be canceled."
-msgstr ""
+msgstr "No se pudo cancelar el análisis."
msgid "OnDemandScans|The scan could not be retried."
-msgstr ""
+msgstr "No se ha podido volver a intentar el análisis."
msgid "OnDemandScans|There are no finished scans."
-msgstr ""
+msgstr "No hay ningún análisis finalizado."
msgid "OnDemandScans|There are no running scans."
-msgstr ""
+msgstr "No hay ningún análisis en ejecución."
msgid "OnDemandScans|There are no saved scans."
-msgstr ""
+msgstr "No hay ningún análisis guardado."
msgid "OnDemandScans|There are no scheduled scans."
-msgstr ""
+msgstr "No hay ningún análisis programado."
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24939,7 +25194,7 @@ msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=valu
msgstr ""
msgid "Optional."
-msgstr ""
+msgstr "Opcional."
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Opcionalmente, puede %{link_to_customize} cómo se importan en Gitlab las direcciones de correo y los nombres de usuario de FogBugz."
@@ -24951,7 +25206,7 @@ msgid "Or you can choose one of the suggested colors below"
msgstr "O puede seleccionar alguno de los colores sugeridos a continuación"
msgid "Organizations"
-msgstr ""
+msgstr "Organización"
msgid "Orphaned member"
msgstr ""
@@ -24960,7 +25215,7 @@ msgid "Other Labels"
msgstr "Otras etiquetas"
msgid "Other available runners"
-msgstr ""
+msgstr "Otros ejecutores disponibles"
msgid "Other information"
msgstr "Otra información"
@@ -24969,16 +25224,16 @@ msgid "Other merge requests block this MR"
msgstr "Otras merge request bloquean este MR"
msgid "Other versions"
-msgstr ""
+msgstr "Otras versiones"
msgid "Other visibility settings have been disabled by the administrator."
msgstr "Otros ajustes de visibilidad han sido desactivados por el administrador."
msgid "Otherwise, click the link below to complete the process."
-msgstr ""
+msgstr "De lo contrario, haga clic en el siguiente enlace para completar el proceso."
msgid "Otherwise, click the link below to complete the process:"
-msgstr ""
+msgstr "De lo contrario, haga clic en el siguiente enlace para completar el proceso:"
msgid "Our team has been notified. Please try again."
msgstr ""
@@ -24986,8 +25241,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Peticiones salientes"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25017,7 +25293,7 @@ msgid "Owned by me"
msgstr "De mi propiedad"
msgid "Owned by:"
-msgstr ""
+msgstr "Propiedad de:"
msgid "Owner"
msgstr "Propietario"
@@ -25029,13 +25305,13 @@ msgid "PQL|By providing my contact information, I agree GitLab may contact me vi
msgstr ""
msgid "PQL|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "PQL|Contact our Sales team"
msgstr ""
msgid "PQL|Contact sales"
-msgstr ""
+msgstr "Contactar con ventas"
msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
msgstr ""
@@ -25044,13 +25320,13 @@ msgid "PQL|Message for the Sales team (optional)"
msgstr ""
msgid "PQL|Please select a city or state"
-msgstr ""
+msgstr "Por favor seleccione una ciudad o estado"
msgid "PQL|Submit information"
-msgstr ""
+msgstr "Enviar información"
msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
-msgstr ""
+msgstr "¡Gracias por contactarnos! Nuestro equipo de ventas se pondrá en contacto con usted muy pronto."
msgid "Package Registry"
msgstr "Registro de paquetes"
@@ -25092,7 +25368,7 @@ msgid "Package type must be Maven"
msgstr "El tipo de paquete debe ser Maven"
msgid "Package type must be NPM"
-msgstr ""
+msgstr "El tipo de paquete debe ser NPM"
msgid "Package type must be NuGet"
msgstr "El tipo de paquete debe ser NuGet"
@@ -25101,7 +25377,7 @@ msgid "Package type must be PyPi"
msgstr "El tipo de paquete debe ser PyPi"
msgid "Package type must be RubyGems"
-msgstr ""
+msgstr "El tipo de paquete debe ser RubyGems"
msgid "PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Accept packages with the same name and version."
msgstr ""
@@ -25287,7 +25563,7 @@ msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your
msgstr "Aprenda a %{noPackagesLinkStart}publicar y compartir sus paquetes%{noPackagesLinkEnd} con GitLab."
msgid "PackageRegistry|License information located at %{link}"
-msgstr ""
+msgstr "La información de licencia se encuentra en %{link}"
msgid "PackageRegistry|Manually Published"
msgstr "Publicado manualmente"
@@ -25311,15 +25587,15 @@ msgid "PackageRegistry|Package Registry"
msgstr ""
msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
+msgstr "Paquete eliminado correctamente"
msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
msgid "PackageRegistry|Package has %{updatesCount} archived update"
msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "El paquete tiene %{updatesCount} actualizacion archivada"
+msgstr[1] "El paquete tiene %{updatesCount} actualizaciones archivadas"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -25343,10 +25619,10 @@ msgid "PackageRegistry|PyPI"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
-msgstr ""
+msgstr "Receta: %{recipe}"
msgid "PackageRegistry|Registry setup"
-msgstr ""
+msgstr "Configuración del registro"
msgid "PackageRegistry|Remove package"
msgstr "Eliminar paquete"
@@ -25355,31 +25631,31 @@ msgid "PackageRegistry|Required Python: %{pythonVersion}"
msgstr ""
msgid "PackageRegistry|RubyGems"
-msgstr ""
+msgstr "RubyGems"
msgid "PackageRegistry|Settings for Generic packages"
msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
-msgstr ""
+msgstr "Configuración para paquetes de Maven"
msgid "PackageRegistry|Show Composer commands"
-msgstr ""
+msgstr "Mostrar comandos de Composer"
msgid "PackageRegistry|Show Conan commands"
-msgstr ""
+msgstr "Mostrar comandos de Conan"
msgid "PackageRegistry|Show NPM commands"
-msgstr ""
+msgstr "Mostrar comandos de NPM"
msgid "PackageRegistry|Show Nuget commands"
-msgstr ""
+msgstr "Mostrar comandos de Nuget"
msgid "PackageRegistry|Show PyPi commands"
-msgstr ""
+msgstr "Mostrar comandos de PyPi"
msgid "PackageRegistry|Show Yarn commands"
-msgstr ""
+msgstr "Mostrar comandos de Yarn"
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -25412,10 +25688,10 @@ msgid "PackageRegistry|To widen your search, change or remove the filters above.
msgstr ""
msgid "PackageRegistry|Type"
-msgstr ""
+msgstr "Tipo"
msgid "PackageRegistry|Unable to fetch package version information."
-msgstr ""
+msgstr "No se ha podido obtener la información de la versión del paquete."
msgid "PackageRegistry|Unable to load package"
msgstr "Se ha producido un error al cargar el paquete"
@@ -25427,16 +25703,16 @@ msgid "PackageRegistry|You are about to delete %{filename}. This is a destructiv
msgstr ""
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr ""
+msgstr "Está a punto de eliminar %{name}, esta operación es irreversible, ¿está seguro?"
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
-msgstr ""
+msgstr "Está a punto de eliminar la versión %{version} de %{name}. ¿Está seguro?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
-msgstr ""
+msgstr "Puede que también necesite configurar la autenticación utilizando un token de autentificación. %{linkStart} Vea la documentación%{linkEnd} para obtener más información."
msgid "PackageRegistry|npm"
-msgstr ""
+msgstr "npm"
msgid "PackageRegistry|published by %{author}"
msgstr "publicado por %{author}"
@@ -25451,16 +25727,16 @@ msgid "Page settings"
msgstr ""
msgid "PagerDutySettings|Active"
-msgstr ""
+msgstr "Activo"
msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
msgstr ""
msgid "PagerDutySettings|Failed to update Webhook URL"
-msgstr ""
+msgstr "Se ha producido un error al actualizar la URL del webhook"
msgid "PagerDutySettings|Reset webhook URL"
-msgstr ""
+msgstr "Restablecer la URL del webhook"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr "Parche a aplicar"
@@ -25727,13 +26000,13 @@ msgid "PerformanceBar|Sort chronologically"
msgstr ""
msgid "PerformanceBar|Stats"
-msgstr ""
+msgstr "Estadísticas"
msgid "PerformanceBar|Total duration"
-msgstr ""
+msgstr "Duración total"
msgid "PerformanceBar|Trace"
-msgstr ""
+msgstr "Traza"
msgid "PerformanceBar|cpu"
msgstr ""
@@ -25744,11 +26017,14 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
msgid "Permalink"
-msgstr ""
+msgstr "Enlace permanente"
msgid "Permanently delete project"
msgstr ""
@@ -25760,10 +26036,10 @@ msgid "Permissions"
msgstr "Permisos"
msgid "Permissions Help"
-msgstr ""
+msgstr "Ayuda de permisos"
-msgid "Permissions, LFS, 2FA"
-msgstr "Permisos, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Token de acceso personal"
@@ -25778,10 +26054,10 @@ msgid "Personal project creation is not allowed. Please contact your administrat
msgstr "No se permite la creación de proyectos personales. Por favor, póngase en contacto con su administrador con preguntas"
msgid "Personal projects"
-msgstr ""
+msgstr "Proyectos personales"
msgid "Personal projects limit:"
-msgstr ""
+msgstr "Límite de los proyectos personales:"
msgid "Phabricator Server Import"
msgstr "Importar servidor Phabricator"
@@ -25808,7 +26084,7 @@ msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Pipeline %{label} para \"%{dataTitle}\""
msgid "Pipeline Editor"
-msgstr ""
+msgstr "Editor de pipelines"
msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
msgstr ""
@@ -26029,9 +26305,6 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Gráficos de los pipelines"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "La configuración de los pipelines para '%{project_name}' se actualizó correctamente."
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Construir con confianza"
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26123,7 +26399,7 @@ msgid "Pipelines|Merged YAML is view only"
msgstr ""
msgid "Pipelines|More Information"
-msgstr ""
+msgstr "Más información"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -26221,11 +26497,29 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr "no válido"
-msgid "Pipelines|parent"
-msgstr "padre"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "Acciones"
@@ -26270,10 +26564,10 @@ msgid "Pipeline|Failed"
msgstr "Fallido"
msgid "Pipeline|In progress"
-msgstr ""
+msgstr "En progreso"
msgid "Pipeline|Manual"
-msgstr ""
+msgstr "Manual"
msgid "Pipeline|Merge train pipeline"
msgstr ""
@@ -26309,13 +26603,13 @@ msgid "Pipeline|Run for branch name or tag"
msgstr ""
msgid "Pipeline|Run pipeline"
-msgstr ""
+msgstr "Ejecutar pipeline"
msgid "Pipeline|Running"
-msgstr ""
+msgstr "En ejecución"
msgid "Pipeline|Skipped"
-msgstr ""
+msgstr "Omitido"
msgid "Pipeline|Source"
msgstr ""
@@ -26402,16 +26696,19 @@ msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
msgid "Plan"
-msgstr ""
+msgstr "Plan"
msgid "Plan:"
msgstr "Plan:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
msgid "PlantUML URL"
-msgstr ""
+msgstr "URL de PlantUML"
msgid "Play"
msgstr "Ejecutar"
@@ -26422,6 +26719,12 @@ msgstr "Ejecutar todo manualmente"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Por favor %{link_to_register} o %{link_to_sign_in} para comentar"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "Por favor, %{startTagRegister}regístrese%{endRegisterTag} o %{startTagSignIn}inicie sesión%{endSignInTag} para contestar"
@@ -26447,7 +26750,7 @@ msgid "Please check your email (%{email}) to verify that you own this address an
msgstr "Por favor revise su correo electrónico (%{email}) para verificar que es el propietario de esta dirección y desbloquear la potencia de CI/CD. ¿No lo ha recibido? %{resend_link}. ¿Ha utilizado una dirección de correo electrónico incorrecta? %{update_link}."
msgid "Please choose a file"
-msgstr ""
+msgstr "Por favor, elija un archivo"
msgid "Please complete your profile with email address"
msgstr "Por favor, complete su perfil con una dirección de correo electrónico"
@@ -26465,7 +26768,7 @@ msgid "Please contact your administrator with any questions."
msgstr ""
msgid "Please contact your administrator."
-msgstr ""
+msgstr "Por favor, póngase en contacto con su administrador."
msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
msgstr ""
@@ -26663,7 +26966,7 @@ msgid "Port"
msgstr "Puerto"
msgid "Postman collection"
-msgstr ""
+msgstr "Colección de Postman"
msgid "Postman collection file path or URL"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr "Preferencias de hora"
msgid "Preferences|Use relative times"
msgstr "Utilizar tiempos relativos"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Previo"
@@ -26945,7 +27251,7 @@ msgid "Profile Settings"
msgstr "Configuración del perfil"
msgid "Profile failed to delete"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el perfil"
msgid "Profile image guideline"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr "Redimensionador de avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "El avatar será eliminado, ¿está seguro?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "Bio"
@@ -27025,9 +27334,6 @@ msgstr "Ciudad, país"
msgid "Profiles|Clear status"
msgstr "Borrar estado"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Haga clic en el icono para activar el inicio de sesión con uno de los siguientes servicios"
-
msgid "Profiles|Commit email"
msgstr "Dirección de correo electrónico para los commits"
@@ -27191,7 +27497,7 @@ msgid "Profiles|Pronouns"
msgstr ""
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "Pronunciación"
msgid "Profiles|Public avatar"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Eliminar avatar"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Establecer una nueva imagen de perfil"
@@ -27250,9 +27559,6 @@ msgstr "Autenticación de dos factores"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escribe tu %{confirmationValue} para confirmar:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Normalmente comienza con \"ssh-ed25519 …\" o \"ssh-rsa …\""
-
msgid "Profiles|Update profile settings"
msgstr "Actualizar la configuración del perfil"
@@ -27482,7 +27788,7 @@ msgid "Project name"
msgstr "Nombre del proyecto"
msgid "Project navigation"
-msgstr ""
+msgstr "Navegación del proyecto"
msgid "Project order will not be saved as local storage is not available."
msgstr "El orden del proyecto no se guardará ya que el almacenamiento local no está disponible."
@@ -27569,7 +27875,7 @@ msgid "ProjectOverview|You must sign in to star a project"
msgstr "Debe iniciar sesión para marcar como favorito un proyecto"
msgid "ProjectPage|Copy project ID"
-msgstr ""
+msgstr "Copiar ID del proyecto"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID de proyecto: %{project_id}"
@@ -27578,10 +27884,10 @@ msgid "ProjectQualitySummary|An error occurred while trying to fetch project qua
msgstr ""
msgid "ProjectQualitySummary|Coverage"
-msgstr ""
+msgstr "Cobertura"
msgid "ProjectQualitySummary|Failure"
-msgstr ""
+msgstr "Error"
msgid "ProjectQualitySummary|Latest pipeline results"
msgstr ""
@@ -27596,16 +27902,16 @@ msgid "ProjectQualitySummary|Measure of how much of your code is covered by test
msgstr ""
msgid "ProjectQualitySummary|See full report"
-msgstr ""
+msgstr "Ver informe completo"
msgid "ProjectQualitySummary|See project Code Coverage Statistics"
-msgstr ""
+msgstr "Ver las estadísticas de cobertura del código del proyecto"
msgid "ProjectQualitySummary|Skipped"
-msgstr ""
+msgstr "Omitido"
msgid "ProjectQualitySummary|Success"
-msgstr ""
+msgstr "Éxito"
msgid "ProjectQualitySummary|Test coverage"
msgstr ""
@@ -27644,13 +27950,13 @@ msgid "ProjectService|Enter new password"
msgstr ""
msgid "ProjectService|Enter new password."
-msgstr ""
+msgstr "Introducir una nueva contraseña."
msgid "ProjectService|Enter new token"
-msgstr ""
+msgstr "Introducir un nuevo token"
msgid "ProjectService|Issue URL"
-msgstr ""
+msgstr "URL de la incidencia"
msgid "ProjectService|Jenkins server URL"
msgstr ""
@@ -27677,16 +27983,16 @@ msgid "ProjectService|Perform common operations on GitLab project: %{project_nam
msgstr "Realice operaciones comunes en el proyecto GitLab: %{project_name}"
msgid "ProjectService|Run CI/CD pipelines with Buildkite."
-msgstr ""
+msgstr "Ejecute pipelines CI/CD con Buildkite."
msgid "ProjectService|Run CI/CD pipelines with Drone."
-msgstr ""
+msgstr "Ejecute pipelines CI/CD con Drone."
msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
-msgstr ""
+msgstr "Ejecute pipelines de CI/CD con JetBrains TeamCity."
msgid "ProjectService|TeamCity server URL"
-msgstr ""
+msgstr "URL del servidor de TeamCity"
msgid "ProjectService|The build configuration ID of the TeamCity project."
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27851,11 +28160,17 @@ msgid "ProjectSettings|Git Large File Storage (LFS)"
msgstr ""
msgid "ProjectSettings|Global"
-msgstr ""
+msgstr "Global"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Interno"
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28016,7 +28334,7 @@ msgid "ProjectSettings|These checks must pass before merge requests can be merge
msgstr ""
msgid "ProjectSettings|This project"
-msgstr ""
+msgstr "Este proyecto"
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Esta configuración se aplica a nivel del servidor y se puede sobreescribir por un administrador."
@@ -28027,11 +28345,8 @@ msgstr "Esta configuración se aplica a nivel del servidor pero se ha sobreescri
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Esta configuración se aplicará a todos los proyectos a menos que sea sobreescrita por un administrador."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
-msgstr ""
+msgstr "Transferir proyecto"
msgid "ProjectSettings|Upstream project"
msgstr ""
@@ -28049,9 +28364,9 @@ msgid "ProjectSettings|Users can request access"
msgstr ""
msgid "ProjectSettings|View and edit files in this project."
-msgstr ""
+msgstr "Ver y editar archivos en este proyecto."
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28721,13 +29036,13 @@ msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
msgid "ProtectedBranch|Unprotect"
-msgstr ""
+msgstr "Desproteger"
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
msgid "ProtectedBranch|default"
-msgstr ""
+msgstr "Por defecto"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} podrá modificarse por los desarrolladores. ¿Estás seguro de que desea continuar?"
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "Claves de despliegue público (%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "Pipelines públicos"
@@ -28867,7 +29179,7 @@ msgstr "Comprar más minutos"
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "Reduce la visibilidad del proyecto"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "¿Reducir la visibilidad de este proyecto?"
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr "El repositorio debe contener al menos 1 archivo."
msgid "Repository size is above the limit."
msgstr "El tamaño del repositorio está por encima del límite."
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Almacenamiento del repositorio"
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Se ha añadido el requisito %{reference}"
@@ -30245,9 +30574,6 @@ msgstr "Resuelto por"
msgid "Resolved by %{name}"
msgstr "Resuelto por %{name}"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr "Resuelve las direcciones IP una vez y las utiliza para enviar peticiones"
-
msgid "Response"
msgstr "Respuesta"
@@ -30314,7 +30640,7 @@ msgstr "Reanudar"
msgid "Resync"
msgstr "Resincronizar"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,15 +30740,15 @@ msgstr "Revocar"
msgid "Revoked"
msgstr "Revocado"
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "¡Token de suplantación revocado %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Se ha revocado el token de acceso personal %{personal_access_token_name}!"
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr "¡Token de acceso al proyecto revocado %{project_access_token_name}!"
-
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Hoja de ruta"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Rol"
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr "Verificación SSL:"
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr "Buscar"
msgid "Search GitLab"
msgstr "Buscar en GitLab"
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} y %{secondProject}"
@@ -31942,9 +32361,6 @@ msgstr "Seleccionar formato de archivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr "Seleccione el proyecto GitLab para vincular con su equipo de Slack"
-
msgid "Select Page"
msgstr "Seleccionar página"
@@ -32332,8 +32748,8 @@ msgstr "Service Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "URL del servicio"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr "Configurar CI/CD"
msgid "Set up Jira Integration"
msgstr "Configurar la integración con Jira"
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr "Restablecer minutos de los 'pipelines'"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Restablecer los minutos utilizados de los 'pipelines'"
-msgid "Sherlock Transactions"
-msgstr "Transacciones de Sherlock"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr "Mostrar toda la actividad"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr "Mostrar todas las incidencias."
@@ -32727,6 +33140,9 @@ msgstr "Mostrar proyectos archivados"
msgid "Show archived projects only"
msgstr "Mostrar solo proyectos archivados"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Mostrar comando"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr "Mostrar solo los comentarios"
-msgid "Show commit description"
-msgstr "Mostrar la descripción del commit"
-
msgid "Show complete raw log"
msgstr "Mostrar el registro completo sin procesar"
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr "Mostrar todas las incidencias"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr "Cerrar la sesión y regístrarse"
msgid "Sign up"
msgstr "Regístrese"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "¡Registro creado correctamente! Por favor, confirme su dirección de correo electrónico para iniciar sesión."
@@ -33001,9 +33420,33 @@ msgstr "Aplicación Slack"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "La integración con Slack le permite interactuar con GitLab mediante comandos slash en una ventana de chat."
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Algo salió mal. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong. Try again later."
msgstr "Se ha producido un error. Por favor, inténtelo más tarde."
-msgid "Sorry, no epics matched your search"
-msgstr "Lo sentimos, no hay tareas épicas que coincidan con su búsqueda"
-
msgid "Sorry, no projects matched your search"
msgstr "Lo sentimos, no hay proyectos que coincidan con su búsqueda"
@@ -33376,9 +33816,6 @@ msgstr "Último Contacto"
msgid "SortOptions|Last created"
msgstr "Fecha de creación"
-msgid "SortOptions|Last updated"
-msgstr "Fecha de actualización"
-
msgid "SortOptions|Least popular"
msgstr "Menos popular"
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Iniciar una búsqueda"
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Indique su mensaje para activar"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "Suscrito"
msgid "Subscribed to this %{quick_action_target}."
msgstr "Suscrito a este %{quick_action_target}."
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr "Se suscribe a este %{quick_action_target}."
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr "Fecha de finalización del periodo de prueba"
msgid "SubscriptionTable|Trial start date"
msgstr "Fecha de inicio de la versión de prueba"
-msgid "SubscriptionTable|Upgrade"
-msgstr "Actualizar"
-
msgid "SubscriptionTable|Usage"
msgstr "Uso"
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr "Domingo"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Soporte"
@@ -34750,6 +35229,9 @@ msgstr "Rama de destino"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr "Términos del acuerdo de servicio y de la política de privacidad"
msgid "Terms of Service and Privacy Policy"
msgstr "Términos del servicio y política de privacidad"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr "Probar"
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Análisis de cobertura de las pruebas"
@@ -35164,9 +35652,6 @@ 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 %{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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Un certificado X.509 se utiliza cuando se require una comunicación TLS con un servicio de autorización externo. Si se deja en blanco, el certificado utilizado desde el servidor es validado cuando se accedes a través del protocolo HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La conexión terminará después de %{timeout}. Para los repositorios que tarden más tiempo, utilice una combinación de git clone y git push."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "La contraseña requerida para descifrar la clave privada. Esto es opcional y su valor está encriptado."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ msgstr "Se ha eliminado el pipeline"
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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "La clave privada que se utiliza cuando se proporciona un certificado cliente. Este valor está encriptado."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr "Se ha producido un error al obtener el %{replicableType}"
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr "Se ha producido un error al restablecer los minutos de ejecución de los
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Este %{issuableDisplayName} está bloqueado. Solo los miembros del proyecto pueden comentar."
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Esta tarea épica no existe o no tiene permisos suficientes."
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr "Esta característica requiere que el almacenamiento local esté activado"
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr "Este proyecto"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr "Este proyecto está archivado y no se puede comentar en el."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Esta configuración se puede reemplazar en cada proyecto."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "Esta suscripción es para"
@@ -36740,9 +37225,6 @@ msgstr "Tiempo desde el último commit al merge"
msgid "Time in seconds"
msgstr "Tiempo en segundos"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Tiempo en segundos que GitLab esperará hasta obtener una respuesta de un servicio externo. Cuando el servicio no responda a tiempo, se denegará el acceso."
-
msgid "Time of import: %{importTime}"
msgstr "Tiempo de importación: %{importTime}"
@@ -36990,9 +37472,6 @@ msgstr "Para acceder a este dominio, cree un nuevo registro DNS"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Para agregar una clave SSH necesita %{generate_link_start}generar una%{link_end} o utilizar una clave existente %{existing_link_start}%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Para agregar la entrada manualmente, proporcione los siguientes detalles a la aplicación en su teléfono."
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr "Para ampliar la búsqueda, cambie o elimine filtros"
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "Para ampliar la búsqueda, cambie o elimine filtros."
-
msgid "To-Do List"
msgstr "Lista de tareas pendientes"
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "Seguimiento del tiempo con acciones rápidas"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr "Haga el seguimiento de sus proyectos de GitLab con GitLab para Slack."
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr "Su prueba termina el %{boldStart}%{trialEndDate}%{boldEnd}. Esperamos que estés disfrutando de las características de GitLab %{planName}. Para mantener esas funciones después de que termine tu prueba, tendrás que comprar una suscripción. (También puedes elegir GitLab Premium si se ajusta a tus necesidades)"
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr "Nombre de la empresa"
@@ -37490,15 +37963,9 @@ msgstr "País"
msgid "Trial|Dismiss"
msgstr "Descartar"
-msgid "Trial|First name"
-msgstr "Primer nombre"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr "GitLab Ultimate (opcional)"
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr "Número de empleados"
@@ -37565,6 +38032,12 @@ msgstr "El disparador se actualizó correctamente."
msgid "Triggerer"
msgstr "Disparador"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "Solucione problemas y supervise su aplicación con el seguimiento"
@@ -38084,6 +38557,9 @@ msgstr "Actualizado"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Actualizado %{updated_at} por %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "Actualizaciones"
@@ -38105,6 +38581,9 @@ msgstr "Actualice su plan"
msgid "Upload"
msgstr "Subir"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Subir fichero CSV"
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr "Versión %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
msgstr "Versión %{versionNumber} (última)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "Ver documentación"
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr "Ver archivo reemplazado @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr "Ver configuración"
@@ -39443,6 +39940,9 @@ msgstr "Respuesta"
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr "La respuesta recibida es la que se recibió cuando se detectó este fallo"
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "Información adicional"
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr "Descargar"
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Evidencia"
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr "Identificador"
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "Identificadores"
@@ -39512,6 +40021,9 @@ msgstr "Imagen"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Enlaces"
@@ -39524,6 +40036,9 @@ msgstr "Espacio de nombres"
msgid "Vulnerability|Project"
msgstr "Proyecto"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39534,7 +40049,10 @@ msgid "Vulnerability|Request/Response"
msgstr "Solicitud/Respuesta"
msgid "Vulnerability|Scanner Provider"
-msgstr "Proveedor del escáner"
+msgstr "Proveedor para el análisis"
+
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39597,7 +40124,7 @@ msgid "We are currently unable to fetch data for this graph."
msgstr "Actualmente no podemos obtener datos para este gráfico."
msgid "We are currently unable to fetch data for this pipeline."
-msgstr ""
+msgstr "Actualmente no podemos obtener datos para este pipeline."
msgid "We could not determine the path to remove the epic"
msgstr "No es posible determinar la ruta para eliminar esta tarea épica"
@@ -39743,6 +40270,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr "Ayuda de Webhooks"
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "Comentarios"
@@ -39785,6 +40354,9 @@ msgstr "Eventos de pipelines"
msgid "Webhooks|Push events"
msgstr ""
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr ""
@@ -39792,7 +40364,7 @@ msgid "Webhooks|SSL verification"
msgstr "Verificación SSL"
msgid "Webhooks|Secret token"
-msgstr ""
+msgstr "Token secreto"
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -39815,55 +40387,10 @@ msgstr "Disparador"
msgid "Webhooks|URL"
msgstr "URL"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr ""
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr ""
-
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,11 +40498,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Al dejar la URL en blanco, aún se pueden especificar las etiquetas de clasificación sin deshabilitar las funciones de proyectos cruzados ni realizar comprobaciones de autorización externas."
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40282,7 +40809,13 @@ msgstr "Trabajo en curso (abierto y sin asignar)"
msgid "Work in progress Limit"
msgstr "Límite de trabajo en progreso"
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "No tiene permiso para realizar esta acción"
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr "También puede validar su fichero %{gitlab_ci_yml} en %{lint_link_start}
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "También puede subir archivos existentes desde su ordenador utilizando las instrucciones que se muestran a continuación."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Puede contribuir fácilmente pidiendo unirse a estos grupos."
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "No tiene permiso para dejar este %{namespaceType}."
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "No tiene permiso para ejecutar el terminal web. Por favor, póngase en contacto con un administrador del proyecto."
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Has alcanzado el límite de tu proyecto"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr "Dejó el \"%{membershipable_human_name}\" %{source_type}."
msgid "You may close the milestone now."
msgstr "Puede cerrar el hito ahora."
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr "Debe estar conectado para buscar en todo GitLab"
@@ -41172,8 +41726,8 @@ msgstr "Tu nombre"
msgid "Your new %{type}"
msgstr "Su nuevo %{type}"
-msgid "Your new SCIM token"
-msgstr "Su nuevo token SCIM"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr ""
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr "Se ha creado su nuevo token de acceso personal."
-msgid "Your new project access token has been created."
-msgstr "Se ha creado un nuevo token de acceso al proyecto."
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "Su contraseña no es necesaria para ver esta página. Si se le solicita una contraseña o cualquier otro dato personal, póngase en contacto con su administrador para denunciar el abuso."
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "¡Su suscripción ha caducado!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr "no se puede modificar si un proyecto personal ya contiene etiquetas de r
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "creado %{timeAgoString} por %{email} través de %{user}"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "creado %{timeAgoString} por %{user}"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "creado %{timeAgoString} por %{user} en Jira"
-
msgid "created %{timeAgo}"
msgstr "creado el %{timeAgo}"
@@ -41995,6 +42554,9 @@ msgstr "fallido"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr "no se puede descartar el hallazgo asociado (id =%{finding_id}): %{message}"
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr "grupo"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr "cargando"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "iniciar sesión"
-
msgid "manual"
msgstr "manual"
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Restaure o use una rama diferente %{missingBranchName}"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,8 +42987,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fallido."
@@ -42523,6 +43091,9 @@ msgstr "Abrir en Web IDE"
msgid "mrWidget|Plain diff"
msgstr "Diff normal"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "listo para fusionarse automáticamente. Pídale a alguien que tenga acceso de escritura a este repositorio que fusione esta solicitud"
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Los cambios se fusionaron en"
@@ -42577,9 +43151,6 @@ msgstr "Los cambios no se fusionaron en"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Se ha eliminado el branch de origen"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Su contraseña"
-msgid "mrWidget|branch does not exist."
-msgstr "la rama no existe."
-
msgid "mrWidget|into"
msgstr "en"
@@ -42899,9 +43467,6 @@ msgstr "repositorio:"
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr "restablecer."
-
msgid "satisfied"
msgstr "satisfecho"
@@ -43082,9 +43647,6 @@ msgstr "avatar del usuario"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "preferencias de usuario"
-
msgid "username"
msgstr "usuario"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 7365b99ef0b..04a99950930 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 8d461c0c997..b45e2ca7ff3 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index dcf6c4f31c6..3f9d5a25419 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 721b7c66fde..494b17b465a 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: 2022-01-06 17:25\n"
+"PO-Revision-Date: 2022-02-02 15:49\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 93f73123226..92352666ac3 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr " %{start} à %{end}"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d approbateur"
@@ -293,8 +313,8 @@ msgstr[1] "%d demandes de fusion auxquelles vous n'avez pas accès."
msgid "%d merge requests"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d demande de fusion"
+msgstr[1] "%d demandes de fusion"
msgid "%d metric"
msgid_plural "%d metrics"
@@ -363,8 +383,8 @@ msgstr[1] "%d fragments sélectionnés"
msgid "%d star"
msgid_plural "%d stars"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d étoile"
+msgstr[1] "%d étoiles"
msgid "%d tag"
msgid_plural "%d tags"
@@ -420,10 +440,10 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} et %{openOrClose} %{noteable}"
msgid "%{actionText} & close %{noteable}"
-msgstr ""
+msgstr "%{actionText} et fermer %{noteable}"
msgid "%{actionText} & reopen %{noteable}"
-msgstr ""
+msgstr "%{actionText} et réouvrir %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} est une plage d'adresses IP non valide"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} demande de fusion ouverte"
msgstr[1] "%{bold_start}%{count}%{bold_end} demandes de fusion ouvertes"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Masqué :%{code_close} Masqué dans les journaux des logs. Doit correspondre aux exigences de masquage."
@@ -503,8 +529,8 @@ msgstr "%{count} approbations de %{name}"
msgid "%{count} contact"
msgid_plural "%{count} contacts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} contact"
+msgstr[1] "%{count} contacts"
msgid "%{count} files touched"
msgstr "%{count} fichiers modifiés"
@@ -549,55 +575,55 @@ msgid "%{count} total weight"
msgstr "%{count} poids total"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical} Critique%{criticalEnd} %{highStart}%{high} Haut%{highEnd} et %{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
-msgstr ""
+msgstr "%{dashboard_path} est introuvable."
msgid "%{days} days until tags are automatically removed"
-msgstr ""
+msgstr "%{days} jours jusqu'à ce que les étiquettes soient automatiquement retirées"
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}Utiliser un template à déployer sur ECS%{deployLinkEnd}, ou utiliser une image docker pour %{commandsLinkStart}exécuter les commandes AWS dans GitLab CI/CD%{commandsLinkEnd}."
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
-msgstr ""
+msgstr "%{description}- Événement Sentry : %{errorUrl}- Vu pour la première fois : %{firstSeen}- Vu pour la dernière fois : %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
-msgstr ""
+msgstr "La %{doc_link_start}recherche avancée%{doc_link_end} est désactivée car %{ref_elem} n'est pas la branche par défaut. %{docs_link}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}La recherche avancée%{doc_link_end} est activée."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}En savoir plus sur les niveaux de visibilité.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Qu'est-ce que le stockage de fichiers volumineux ?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Qu'est-ce que l'authentification à deux facteurs ?%{docs_link_end}"
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (Échéance)"
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} Essayez de picorer à nouveau ce commit."
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Réessayez de créer un nouveau répertoire."
msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Essayez de défaire (`revert`) ce commit à nouveau."
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Réessayez de téléverser un fichier."
msgid "%{emailPrefix}@company.com"
-msgstr ""
+msgstr "%{emailPrefix}@societe.fr"
msgid "%{extra} more downstream pipelines"
msgstr ""
@@ -618,43 +644,46 @@ 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 ""
+msgstr "%{global_id} n'est pas un identifiant valide pour %{expected_types}."
msgid "%{group_name} activity"
-msgstr ""
+msgstr "Activité du groupe %{group_name}"
msgid "%{group_name} group members"
+msgstr "Membres du groupe %{group_name}"
+
+msgid "%{group_name} is approaching the limit of available seats"
msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
-msgstr ""
+msgstr "%{group_name} utilise les comptes gérés du groupe. Vous devez créer un nouveau compte GitLab qui sera géré par %{group_name}."
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}&%{epic_iid} &middot; créée %{epic_created} par %{author}"
msgid "%{hook_type} was deleted"
-msgstr ""
+msgstr "%{hook_type} a été supprimé"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type} était programmé pour la suppression"
msgid "%{host} sign-in from new location"
-msgstr ""
+msgstr "%{host} connexion depuis un nouvel emplacement"
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 "Les %{integrations_link_start}Intégrations%{link_end} vous permettent d'inclure des applications tierces à votre flux de travail GitLab. Si les intégrations disponibles ne répondent pas à vos besoins, envisagez l'utilisation de %{webhooks_link_start}webhooks%{link_end}."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sera supprimé ! Êtesâ€vous sûr ?"
msgid "%{issueType} actions"
-msgstr ""
+msgstr "%{issueType} actions"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{issuesSize} avec une limite de %{maxIssueCount}"
msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
-msgstr ""
+msgstr "Les %{italic_start}Nouveautés%{italic_end} ne sont pas actives et ne peuvent pas être affichées."
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgstr "%{itemsCount} tickets avec une limite de %{maxIssueCount}"
@@ -675,7 +704,7 @@ msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}État du plantage :%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}Preuve :%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
msgstr "%{labelStart}Fichier :%{labelEnd} %{file}"
@@ -722,6 +751,9 @@ msgstr "%{level_name} n'est pas autorisé dans un groupe %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} n'est pas autorisé car le projet divergent a une visibilité inférieure."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}En savoir plus%{link_end} sur les rôles."
@@ -729,6 +761,9 @@ msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title
msgstr "%{link_start}Supprimez le %{draft_snippet} préfixe%{link_end} du titre pour permettre la fusion lorsque cette demande de fusion sera prête."
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr "%{link_start}Débutez le titre avec %{draft_snippet}%{link_end} pour empêcher un brouillon de demande de fusion d'être fusionné avant qu'il ne soit prêt."
+
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -765,10 +800,10 @@ msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, ce ticket sera fermé automatiquement."
msgid "%{name_with_link} namespace has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "L'espace de noms %{name_with_link} dispose de %{percent} ou moins de minutes restantes d'Exécuteur de Pipeline Partagé. Une fois qu’elles seront épuisées, aucune nouvelle tâche ni pipeline de ses projets ne sera lancé."
msgid "%{name_with_link} namespace has run out of Shared Runner Pipeline minutes. No new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "L'espace de noms %{name_with_link} a épuisé ses minutes d'Exécuteur de Pipeline Partagé. Aucune nouvelle tâche ni pipeline dans ses projets ne sera lancé."
msgid "%{name} (Busy)"
msgstr "%{name} (Occupé)"
@@ -783,7 +818,7 @@ msgid "%{name} is already being used for another emoji"
msgstr "%{name} est déjà utilisé pour un autre emoji"
msgid "%{name} is reserved for %{type} report type"
-msgstr ""
+msgstr "%{name} est réservé pour le type de rapport %{type}"
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} est prévu pour %{action}"
@@ -824,25 +859,22 @@ msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} ouverts, %{closedIssues} fermés"
msgid "%{percentage}%% weight completed"
-msgstr ""
+msgstr "%{percentage}%% du poids completé"
msgid "%{percent}%% complete"
msgstr "%{percent} %% effectués"
msgid "%{percent}%{percentSymbol} complete"
-msgstr ""
+msgstr "%{percent}%{percentSymbol} completé"
msgid "%{placeholder} is not a valid color scheme"
-msgstr ""
+msgstr "%{placeholder} n'est pas un jeu de couleurs valide"
msgid "%{placeholder} is not a valid theme"
-msgstr ""
+msgstr "%{placeholder} n'est pas un thème valide"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
-msgstr ""
-
-msgid "%{primary} (%{secondary})"
-msgstr ""
+msgstr "%{policy_link} (notifiant après %{elapsed_time} minutes à moins de %{status})"
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr "Ajouter un CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Ajouter un CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr "Ajouter une URL Jaeger"
@@ -1991,7 +2011,7 @@ msgstr "Ajouter une grappe de serveurs Kubernetes"
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erreur lors du chargement des statistiques. Veuillez réessayer"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr "Autoriser les projets de ce groupe à utiliser le stockage Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Autoriser les requêtes sur le réseau local à partir de hooks et de services."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Une erreur est survenue"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr "Une erreur est survenue pendant la récupération des tâches."
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette identité ?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton de bilan de santé ?"
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
msgid "Average per day: %{average}"
msgstr "Moyenne par jour : %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Vous trouverez ciâ€dessous tous les groupes publics."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Importation de Bitbucket"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Supprimer les branches fusionnées"
msgid "Branches|Delete protected branch"
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) ?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "La suppression des branches fusionnées ne peut être annulée. Êtesâ€vous sûr(e) ?"
@@ -5958,9 +5990,6 @@ msgstr "Nouvelle branche"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Afin d’éviter de perdre des données, il est conseillé de fusionner cette branche avant de la supprimer."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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."
@@ -6036,9 +6056,6 @@ 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} »."
-
msgid "Branches|diverged from upstream"
msgstr "en divergence du dépôt en amont"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "par"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Ne peut être fusionnée automatiquement"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Picorer cette demande de fusion"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "Certificat d’authentification du client"
-
-msgid "Client authentication key"
-msgstr "Clef d’authentification du client"
-
-msgid "Client authentication key password"
-msgstr "Mot de passe de la clef d’authentification client"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr "Message du commit"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr "Configurer le traçage"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configurez la manière dont une personne crée un nouveau compte."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr "Créé par moi"
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "Étiquette de classement par défaut"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Déploiements"
msgid "Deploy Keys"
msgstr "Clefs de déploiement"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "Activer le contrôle de classification à l’aide d’un service externe"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr "Entrez l’URL de votre serveur Bitbucket et votre jeton d’accès pers
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr "Arrêter l’environnement"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr "protégé"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Épopée"
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "Autorisation de politique de classification externe"
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "Authentification externe"
-
msgid "External authorization denied access to this project"
msgstr "L’autorisation externe a refusé l’accès à ce projet"
-msgid "External authorization request timeout"
-msgstr "Expiration du délai d’attente de la demande d’autorisation externe"
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr "Étiquette de classification"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Lorsqu’aucune étiquette de classification n’est définie, l’étiquette par défaut « %{default_label} » sera utilisée."
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "févr."
@@ -15149,12 +15308,6 @@ msgstr "Filtrer"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement fermés."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Générer un jeu d’étiquettes par défaut"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "NÅ“uds Geo"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "En échec"
@@ -15767,12 +15935,6 @@ msgstr "Prochaine synchro programmée à"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Pas encore synchronisé"
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "En attente de synchronisation"
@@ -15821,16 +15986,19 @@ msgstr "Reâ€télécharger"
msgid "Geo|Remove"
msgstr "Supprimer"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr "secondaire"
msgid "Get a free instance review"
msgstr "Obtenez une revue d’instance gratuite"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Statut du stockage LFS Git du groupe :"
@@ -16664,6 +16847,9 @@ msgstr "Le SAML de groupe doit être activé afin de pouvoir tester"
msgid "Group URL"
msgstr "URL du groupe"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Les responsables de groupe peuvent créer des exécuteurs de groupe via %{link}"
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Ce paramètre s’applique au groupe %{ancestor_group}. Vous pouvez écr
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accÃ
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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "Masquer les valeurs"
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "Maintenance démarrée avec succès"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "J’accepte les %{terms_link}"
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr "Identités"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "Si activé, l’accès aux projets sera validé sur un service externe en se basant sur leurs étiquettes de classification respectives."
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr "Chargement…"
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr "Verrouiller"
msgid "Lock %{issuableDisplayName}"
msgstr "Verrouiller %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr "Les verrous permettent de verrouiller un fichier ou un dossier spécifiq
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Se connecter avec une carte à puce"
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "Mois"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr "Autres actions"
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Aucune autre étiquette avec un tel nom ou une telle description"
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24688,7 +24943,7 @@ msgid "OnDemandScans|Save scan"
msgstr ""
msgid "OnDemandScans|Scan library"
-msgstr ""
+msgstr "Bibliothèque de numérisation"
msgid "OnDemandScans|Scan name"
msgstr ""
@@ -24986,8 +25241,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Requêtes sortantes"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,8 +26038,8 @@ msgstr "Droits d’accès"
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
-msgstr "Autorisations, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Jeton d’accès personnel"
@@ -26029,9 +26305,6 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Graphiques des pipelines"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Construire en toute confiance"
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr "Rogneur d’avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr "Effacer le statut"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Supprimer l’avatar"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Définir une nouvelle photo de profil"
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr "Mettre à jour les paramètres du profil"
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr "Ce paramètre s’applique au niveau du serveur, mais il a été outrepa
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Ce paramètre s’appliquera à tous les projets à moins qu’un administrateur ou une administratrice ne l’outrepasse sur certains projets."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr "Pipelines publics"
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Stockage du dépôt"
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr "Reprendre"
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr "Révoquer"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Feuille de route"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr "Rechercher"
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Sélectionnez le format de l’archive"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,8 +32748,8 @@ msgstr "Service d’assistance"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "URL du service"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr "Configuration CI/CD"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr "Réinitialiser le compteur de minutes du pipeline"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Réinitialiser les minutes du pipeline utilisées"
-msgid "Sherlock Transactions"
-msgstr "Transactions Sherlock"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Afficher la commande"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr "Afficher le journal brut complet"
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr "Application Slack"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "L’intégration de Slack permet d’interagir avec GitLab via des commandes slash dans une fenêtre de messagerie instantanée."
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Quelque chose s’est mal passé. Veuillez réessayer."
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Désolé, aucune épopée ne correspond à votre recherche"
-
msgid "Sorry, no projects matched your search"
msgstr "Désolé, aucun projet ne correspond à votre recherche"
@@ -33376,9 +33816,6 @@ msgstr "Contact le plus récent"
msgid "SortOptions|Last created"
msgstr "Créé récemment"
-msgid "SortOptions|Last updated"
-msgstr "Date de mise à jour décroissante"
-
msgid "SortOptions|Least popular"
msgstr "Popularité croissante"
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Énoncez votre message à activer"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "Abonné"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr "Branche cible"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr "Conditions générales d’utilisation et politique de confidentialité"
msgid "Terms of Service and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Analyse de la couverture des tests"
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Le certificat X.509 à utiliser lorsque l’authentification TLS mutuelle est requise pour communiquer avec le service d’autorisation externe. Si ce champ est vide, le certificat du serveur est tout de même validé lors de l’accès via HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessitent plus de temps, utilisez une combinaison de clone et push."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "La phrase de passe permettant de déchiffrer la clef privée. Ceci est facultatif et la valeur est chiffrée au repos."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 "La planification des pipelines permet l’exécution de pipelines programmés, de manière récurrente, pour des branches ou des étiquettes spécifiques. Ces pipelines programmés hériteront d’un accès limité aux projets en fonction de l’utilisateur qui leur est associé."
-msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "La clef privée à utiliser lorsqu’un certificat client est fourni. Cette valeur est chiffrée au repos."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr "Ce projet"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Ce paramètre peut être outrepassé pour chacun des projets."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Délai d’attente, en secondes, d’une réponse du service externe. Lorsque le service ne répond pas à temps, l’accès sera refusé."
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Afin d’ajouter une clef SSH, vous devez soit %{generate_link_start}en génèrer une%{link_end}, soit utiliser une %{existing_link_start}clef existante%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres."
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "Suivre le temps estimé/passé avec les actions rapides"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "Dépanner et surveiller votre application grâce au traçage"
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr "Voir le fichier remplacé @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "Identifiants"
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Liens"
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projet"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,11 +40498,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peuvent toujours être spécifiées sans désactiver les fonctionnalités interâ€projets ni effectuer de vérifications d’autorisation externes."
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Vous pouvez facilement y contribuer en demandant à rejoindre ces groupe
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Vous avez atteint votre limite de projet"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Votre nom"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Veuillez la restaurer ou utiliser une autre branche %{missingBranchName}"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,8 +42987,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
@@ -42523,6 +43091,9 @@ msgstr "Ouvrir dans l’EDI Web"
msgid "mrWidget|Plain diff"
msgstr "Diff simple"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Prête à être fusionnée automatiquement. Demandez à quelqu’un ayant un accès en écriture à ce dépôt d’effectuer cette fusion"
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Les modifications ont été fusionnées dans"
@@ -42577,9 +43151,6 @@ msgstr "Les modifications n’ont pas été fusionnées dans"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr "la branche n’existe pas."
-
msgid "mrWidget|into"
msgstr "dans"
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "nom d’utilisateur"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 150f6214e95..37f8a3fd7b4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -126,6 +146,11 @@ msgid_plural "%d approvers (you've approved)"
msgstr[0] ""
msgstr[1] ""
+msgid "%d assigned issue"
+msgid_plural "%d assigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -401,8 +426,23 @@ msgid_plural "%d vulnerabilities dismissed"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability updated"
-msgid_plural "%d vulnerabilities updated"
+msgid "%d vulnerability set to confirmed"
+msgid_plural "%d vulnerabilities set to confirmed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to dismissed"
+msgid_plural "%d vulnerabilities set to dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to needs triage"
+msgid_plural "%d vulnerabilities set to needs triage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to resolved"
+msgid_plural "%d vulnerabilities set to resolved"
msgstr[0] ""
msgstr[1] ""
@@ -461,6 +501,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -484,6 +530,12 @@ msgstr[1] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
+msgid "%{completed} of %{total} issues closed"
+msgstr ""
+
+msgid "%{completed} of %{total} weight completed"
+msgstr ""
+
msgid "%{cores} cores"
msgstr ""
@@ -626,6 +678,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -829,6 +884,9 @@ msgstr ""
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr ""
+msgid "%{percentage}%% issues closed"
+msgstr ""
+
msgid "%{percentage}%% weight completed"
msgstr ""
@@ -1258,6 +1316,9 @@ msgid_plural "- Users"
msgstr[0] ""
msgstr[1] ""
+msgid "- of - issues closed"
+msgstr ""
+
msgid "- of - weight completed"
msgstr ""
@@ -2045,6 +2106,9 @@ msgstr ""
msgid "Add a numbered list"
msgstr ""
+msgid "Add a related epic"
+msgstr ""
+
msgid "Add a related issue"
msgstr ""
@@ -2159,6 +2223,9 @@ msgstr ""
msgid "Add or subtract spent time"
msgstr ""
+msgid "Add people"
+msgstr ""
+
msgid "Add previously merged commits"
msgstr ""
@@ -2225,6 +2292,9 @@ msgstr ""
msgid "Add webhook"
msgstr ""
+msgid "Add your team members and others to GitLab."
+msgstr ""
+
msgid "Add/remove"
msgstr ""
@@ -2684,7 +2754,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2810,6 +2880,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2873,6 +2946,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2975,7 +3051,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3041,12 +3117,6 @@ msgstr ""
msgid "AdvancedSearch|Reindex required"
msgstr ""
-msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
-msgstr ""
-
-msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
-msgstr ""
-
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3542,7 +3612,7 @@ msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3653,9 +3723,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3803,16 +3870,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4194,12 +4258,15 @@ msgstr ""
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
-msgid "ApplicationSettings|By making this change, you will automatically approve %d user with the pending approval status."
-msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
+msgid "ApplicationSettings|Approve users who are pending approval?"
+msgstr ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve %d user who is pending approval."
+msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users who are pending approval."
msgstr[0] ""
msgstr[1] ""
-msgid "ApplicationSettings|By making this change, you will automatically approve all users in pending approval status."
+msgid "ApplicationSettings|By making this change, you will automatically approve all users who are pending approval."
msgstr ""
msgid "ApplicationSettings|Denied domains for sign-ups"
@@ -4368,9 +4435,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4401,9 +4465,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4413,13 +4474,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4446,7 +4507,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4461,6 +4522,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4476,7 +4540,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4488,22 +4552,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4602,10 +4672,10 @@ 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}"
msgstr ""
-msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
+msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
msgstr ""
-msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
+msgid "Are you absolutely sure?"
msgstr ""
msgid "Are you sure that you want to archive this project?"
@@ -4641,12 +4711,18 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this comment?"
+msgstr ""
+
msgid "Are you sure you want to delete this deploy key?"
msgstr ""
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
+msgid "Are you sure you want to delete this label?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -4730,6 +4806,9 @@ msgstr ""
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
msgstr ""
+msgid "Are you sure you want to revoke this project access token? This action cannot be undone."
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -4874,9 +4953,6 @@ msgstr ""
msgid "Assigned to %{assignee_name}"
msgstr ""
-msgid "Assigned to %{name}"
-msgstr ""
-
msgid "Assigned to me"
msgstr ""
@@ -4941,6 +5017,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attention"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5103,6 +5182,12 @@ msgstr ""
msgid "Authorized applications (%{size})"
msgstr ""
+msgid "AuthorizedApplication|Are you sure you want to revoke this application?"
+msgstr ""
+
+msgid "AuthorizedApplication|Revoke application"
+msgstr ""
+
msgid "Authors: %{authors}"
msgstr ""
@@ -5238,6 +5323,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5418,9 +5506,6 @@ 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 ""
@@ -5457,9 +5542,6 @@ 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 ""
@@ -5625,6 +5707,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6219,6 +6304,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6287,6 +6381,9 @@ msgstr ""
msgid "CICDAnalytics|Shared Runners Usage"
msgstr ""
+msgid "CICDAnalytics|Shared runner pipeline minute duration by month"
+msgstr ""
+
msgid "CICDAnalytics|Shared runner usage"
msgstr ""
@@ -6428,6 +6525,9 @@ msgstr ""
msgid "Can create groups:"
msgstr ""
+msgid "Can not delete primary training"
+msgstr ""
+
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -6533,6 +6633,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6758,9 +6861,6 @@ msgstr ""
msgid "Changing any setting here requires an application restart"
msgstr ""
-msgid "Changing group URL can have unintended side effects."
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -6848,9 +6948,6 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
-msgid "Checking group URL availability..."
-msgstr ""
-
msgid "Checking group path availability..."
msgstr ""
@@ -7092,6 +7189,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7341,6 +7441,9 @@ msgstr ""
msgid "Clear recent searches"
msgstr ""
+msgid "Clear repository checks"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -7518,7 +7621,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7560,10 +7663,19 @@ msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
+msgid "ClusterAgents|Agent version mismatch"
+msgstr ""
+
+msgid "ClusterAgents|Agent version mismatch and update"
+msgstr ""
+
+msgid "ClusterAgents|Agent version update required"
+msgstr ""
+
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7590,10 +7702,10 @@ msgstr ""
msgid "ClusterAgents|Connect existing cluster"
msgstr ""
-msgid "ClusterAgents|Connect with a certificate"
+msgid "ClusterAgents|Connect with Agent"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with a certificate"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7650,13 +7762,19 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|How to update the Agent?"
+msgstr ""
+
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7683,7 +7801,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7710,6 +7828,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7722,6 +7852,12 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
+msgid "ClusterAgents|The Agent version do not match each other across your cluster's pods. This can happen when a new Agent version was just deployed and Kubernetes is shutting down the old pods."
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7763,6 +7899,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -7772,6 +7911,9 @@ msgstr ""
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your Agent version is out of sync with your GitLab version (v%{version}), which might cause compatibility problems. Update the Agent installed on your cluster to the most recent version."
+msgstr ""
+
msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
msgstr ""
@@ -8648,9 +8790,6 @@ msgstr ""
msgid "Comma-separated list of email addresses."
msgstr ""
-msgid "Comma-separated list of users allowed to exceed the rate limit."
-msgstr ""
-
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr ""
@@ -8713,6 +8852,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8995,12 +9137,21 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure GitLab"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -9784,7 +9935,13 @@ msgstr ""
msgid "CorpusManagement|Actions"
msgstr ""
-msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files are used in coverage-guided fuzz testing as seed inputs to improve testing."
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
msgstr ""
msgid "CorpusManagement|Corpus name"
@@ -9793,6 +9950,12 @@ msgstr ""
msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
msgstr ""
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9805,9 +9968,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9832,6 +9992,9 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
+msgid "Could not apply %{name} command. %{message}."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9982,6 +10145,9 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
+msgid "Create a group"
+msgstr ""
+
msgid "Create a merge request"
msgstr ""
@@ -10006,6 +10172,9 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Create a project"
+msgstr ""
+
msgid "Create an account using:"
msgstr ""
@@ -10324,6 +10493,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10366,6 +10538,9 @@ msgstr ""
msgid "Creation date"
msgstr ""
+msgid "Creator"
+msgstr ""
+
msgid "Credentials"
msgstr ""
@@ -10378,9 +10553,15 @@ msgstr ""
msgid "CredentialsInventory|Personal Access Tokens"
msgstr ""
+msgid "CredentialsInventory|Project Access Tokens"
+msgstr ""
+
msgid "CredentialsInventory|SSH Keys"
msgstr ""
+msgid "Credit card required to be on file in order to create a pipeline"
+msgstr ""
+
msgid "Credit card:"
msgstr ""
@@ -10564,9 +10745,6 @@ msgstr ""
msgid "Customer relations"
msgstr ""
-msgid "Customizable by an administrator."
-msgstr ""
-
msgid "Customizable by owners."
msgstr ""
@@ -10793,6 +10971,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10802,10 +10983,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,10 +11052,16 @@ msgstr ""
msgid "DastProfiles|AJAX spider"
msgstr ""
+msgid "DastProfiles|API"
+msgstr ""
+
+msgid "DastProfiles|API endpoint URL"
+msgstr ""
+
msgid "DastProfiles|Active"
msgstr ""
-msgid "DastProfiles|Additional request headers (Optional)"
+msgid "DastProfiles|Additional request headers (optional)"
msgstr ""
msgid "DastProfiles|Are you sure you want to delete this profile?"
@@ -10958,7 +11145,13 @@ msgstr ""
msgid "DastProfiles|Excluded URLs"
msgstr ""
-msgid "DastProfiles|Excluded URLs (Optional)"
+msgid "DastProfiles|Excluded URLs (optional)"
+msgstr ""
+
+msgid "DastProfiles|Excluded paths"
+msgstr ""
+
+msgid "DastProfiles|Excluded paths (optional)"
msgstr ""
msgid "DastProfiles|Hide debug messages"
@@ -11015,9 +11208,6 @@ msgstr ""
msgid "DastProfiles|Request headers"
msgstr ""
-msgid "DastProfiles|Rest API"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11218,6 +11408,9 @@ msgstr ""
msgid "DatadogIntegration|API URL"
msgstr ""
+msgid "DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}"
+msgstr ""
+
msgid "DatadogIntegration|Environment"
msgstr ""
@@ -11236,12 +11429,18 @@ msgstr ""
msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments."
msgstr ""
+msgid "DatadogIntegration|Tags"
+msgstr ""
+
msgid "DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}."
msgstr ""
msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
msgstr ""
+msgid "DatadogIntegration|have an invalid format"
+msgstr ""
+
msgid "Datasource name not found"
msgstr ""
@@ -11251,9 +11450,6 @@ msgstr ""
msgid "Date merged"
msgstr ""
-msgid "Date picker"
-msgstr ""
-
msgid "Date range"
msgstr ""
@@ -11407,9 +11603,6 @@ msgstr ""
msgid "Definition"
msgstr ""
-msgid "Delayed Project Deletion (%{adjourned_deletion})"
-msgstr ""
-
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
msgstr ""
@@ -11488,10 +11681,10 @@ msgstr ""
msgid "Delete pipeline"
msgstr ""
-msgid "Delete project"
+msgid "Delete pipeline schedule"
msgstr ""
-msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgid "Delete project"
msgstr ""
msgid "Delete row"
@@ -11521,6 +11714,9 @@ msgstr ""
msgid "Delete this epic and all descendants?"
msgstr ""
+msgid "Delete this project"
+msgstr ""
+
msgid "Delete user list"
msgstr ""
@@ -11779,6 +11975,12 @@ msgstr ""
msgid "Deploy to..."
msgstr ""
+msgid "DeployBoards|To see deployment progress for your environments, make sure you are deploying to %{codeStart}$KUBE_NAMESPACE%{codeEnd} and annotating with %{codeStart}app.gitlab.com/app=$CI_PROJECT_PATH_SLUG%{codeEnd} and %{codeStart}app.gitlab.com/env=$CI_ENVIRONMENT_SLUG%{codeEnd}."
+msgstr ""
+
+msgid "DeployBoard|Kubernetes Pods"
+msgstr ""
+
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
@@ -11863,9 +12065,6 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
-msgid "DeployTokens|Allows read and write access to registry images."
-msgstr ""
-
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -11878,6 +12077,9 @@ msgstr ""
msgid "DeployTokens|Allows read-only access to the repository."
msgstr ""
+msgid "DeployTokens|Allows write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Copy deploy token"
msgstr ""
@@ -11974,9 +12176,51 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "Deployment Target|Project deployment target (optional)"
+msgstr ""
+
+msgid "Deployment Target|Select the deployment target"
+msgstr ""
+
msgid "Deployment frequency"
msgstr ""
+msgid "DeploymentTarget|GitLab Pages"
+msgstr ""
+
+msgid "DeploymentTarget|Heroku"
+msgstr ""
+
+msgid "DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)"
+msgstr ""
+
+msgid "DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)"
+msgstr ""
+
+msgid "DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)"
+msgstr ""
+
+msgid "DeploymentTarget|Mobile app store"
+msgstr ""
+
+msgid "DeploymentTarget|No deployment planned"
+msgstr ""
+
+msgid "DeploymentTarget|Other hosting service"
+msgstr ""
+
+msgid "DeploymentTarget|Registry (package or container)"
+msgstr ""
+
+msgid "DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)"
+msgstr ""
+
+msgid "DeploymentTarget|Serverless backend (Lambda, Cloud functions)"
+msgstr ""
+
+msgid "DeploymentTarget|Virtual machine (for example, EC2)"
+msgstr ""
+
msgid "Deployments"
msgstr ""
@@ -11994,9 +12238,15 @@ msgstr ""
msgid "Deployment|Created"
msgstr ""
+msgid "Deployment|Deployment ID"
+msgstr ""
+
msgid "Deployment|Failed"
msgstr ""
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
msgid "Deployment|Running"
msgstr ""
@@ -12009,6 +12259,9 @@ msgstr ""
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Triggerer"
+msgstr ""
+
msgid "Deployment|Waiting"
msgstr ""
@@ -12036,6 +12289,18 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
+msgid "Deprecations|Feature deprecation and removal"
+msgstr ""
+
+msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
+msgstr ""
+
+msgid "Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
+msgstr ""
+
+msgid "Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -12281,10 +12546,10 @@ msgstr ""
msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least one issue opened"
+msgid "DevopsAdoption|At least one issue created"
msgstr ""
-msgid "DevopsAdoption|At least one merge request opened"
+msgid "DevopsAdoption|At least one merge request created"
msgstr ""
msgid "DevopsAdoption|At least one pipeline successfully run"
@@ -12601,6 +12866,9 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
+msgid "Dismiss Alert"
+msgstr ""
+
msgid "Dismiss merge request promotion"
msgstr ""
@@ -12628,9 +12896,15 @@ msgstr ""
msgid "Display alerts from all configured monitoring tools."
msgstr ""
+msgid "Display milestones"
+msgstr ""
+
msgid "Display name"
msgstr ""
+msgid "Display progress of child issues"
+msgstr ""
+
msgid "Display rendered file"
msgstr ""
@@ -12736,6 +13010,9 @@ msgstr ""
msgid "Download image"
msgstr ""
+msgid "Download payload"
+msgstr ""
+
msgid "Download raw data (.csv)"
msgstr ""
@@ -13396,6 +13673,9 @@ msgstr ""
msgid "Enforce two-factor authentication for all user sign-ins."
msgstr ""
+msgid "Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
+msgstr ""
+
msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
msgstr ""
@@ -13456,6 +13736,9 @@ msgstr ""
msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
msgstr ""
+msgid "Enter the following to confirm:"
+msgstr ""
+
msgid "Enter the name of your application, and we'll return a unique %{type}."
msgstr ""
@@ -13710,6 +13993,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13737,6 +14023,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -13980,9 +14269,6 @@ msgstr ""
msgid "Error occurred while updating the issue status"
msgstr ""
-msgid "Error occurred while updating the issue weight"
-msgstr ""
-
msgid "Error occurred. A blocked user cannot be deactivated"
msgstr ""
@@ -14130,6 +14416,9 @@ msgstr ""
msgid "Escalation policies must have at least one rule"
msgstr ""
+msgid "Escalation policy"
+msgstr ""
+
msgid "Escalation policy:"
msgstr ""
@@ -14477,6 +14766,9 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore public projects"
+msgstr ""
+
msgid "Explore snippets"
msgstr ""
@@ -14638,7 +14930,7 @@ msgid_plural "Failed to archive designs. Please try again."
msgstr[0] ""
msgstr[1] ""
-msgid "Failed to assign a reviewer because no user was found."
+msgid "Failed to assign a reviewer because no user was specified."
msgstr ""
msgid "Failed to assign a user because no user was found."
@@ -14677,9 +14969,6 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
@@ -14707,6 +14996,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to find users for %{missing}"
+msgstr ""
+
msgid "Failed to generate export, please try again later."
msgstr ""
@@ -14809,6 +15101,9 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
+msgid "Failed to remove attention because no user was found."
+msgstr ""
+
msgid "Failed to remove mirror."
msgstr ""
@@ -14821,6 +15116,9 @@ msgstr ""
msgid "Failed to remove user key."
msgstr ""
+msgid "Failed to request attention because no user was found."
+msgstr ""
+
msgid "Failed to reset key. Please try again."
msgstr ""
@@ -14902,6 +15200,9 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature deprecation and removal"
+msgstr ""
+
msgid "Feature flag status"
msgstr ""
@@ -15120,14 +15421,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15215,12 +15508,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15545,6 +15832,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15671,6 +15961,9 @@ msgstr ""
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15707,6 +16000,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15767,6 +16063,9 @@ msgstr ""
msgid "Geo|Failed"
msgstr ""
+msgid "Geo|Filter Geo sites"
+msgstr ""
+
msgid "Geo|Filter by name"
msgstr ""
@@ -15839,12 +16138,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15860,6 +16153,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15899,13 +16195,13 @@ msgstr ""
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15917,9 +16213,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15968,6 +16261,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16004,10 +16303,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16178,6 +16477,9 @@ msgstr ""
msgid "GitLab Issue"
msgstr ""
+msgid "GitLab KAS"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -16226,6 +16528,9 @@ msgstr ""
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
+msgid "GitLab is free to use. Many features for larger teams are part of our %{link_start}paid products%{link_end}. You can try Ultimate for free without any obligation or payment details."
+msgstr ""
+
msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
msgstr ""
@@ -16559,6 +16864,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16736,9 +17044,6 @@ msgstr ""
msgid "Group Hooks"
msgstr ""
-msgid "Group ID"
-msgstr ""
-
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
@@ -16766,9 +17071,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -16883,7 +17185,7 @@ msgstr ""
msgid "Group: %{name}"
msgstr ""
-msgid "GroupActivityMetrics|Issues opened"
+msgid "GroupActivityMetrics|Issues created"
msgstr ""
msgid "GroupActivityMetrics|Last 90 days"
@@ -16892,7 +17194,7 @@ msgstr ""
msgid "GroupActivityMetrics|Members added"
msgstr ""
-msgid "GroupActivityMetrics|Merge Requests opened"
+msgid "GroupActivityMetrics|Merge Requests created"
msgstr ""
msgid "GroupActivityMetrics|Recent activity"
@@ -17183,6 +17485,9 @@ msgstr ""
msgid "GroupSettings|Changing a group's URL can have unintended side effects."
msgstr ""
+msgid "GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores."
+msgstr ""
+
msgid "GroupSettings|Compliance frameworks"
msgstr ""
@@ -17216,7 +17521,7 @@ msgstr ""
msgid "GroupSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
-msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
+msgid "GroupSettings|If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
msgstr ""
msgid "GroupSettings|New runners registration token has been generated!"
@@ -17225,9 +17530,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17255,9 +17557,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17342,6 +17641,12 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
+msgid "Groups are a great way to organize projects and people."
+msgstr ""
+
+msgid "Groups are the best way to manage projects and members."
+msgstr ""
+
msgid "Groups to synchronize"
msgstr ""
@@ -17381,9 +17686,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17438,7 +17740,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17453,13 +17755,16 @@ msgstr ""
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
msgstr ""
-msgid "GroupsTree|Edit group"
+msgid "GroupsTree|Delete"
+msgstr ""
+
+msgid "GroupsTree|Edit"
msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Leave this group"
+msgid "GroupsTree|Leave group"
msgstr ""
msgid "GroupsTree|Loading groups"
@@ -17471,9 +17776,57 @@ msgstr ""
msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
+msgid "GroupsTree|Options"
+msgstr ""
+
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "Groups|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Groups|Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "Groups|Checking group URL availability..."
+msgstr ""
+
+msgid "Groups|Enter a descriptive name for your group."
+msgstr ""
+
+msgid "Groups|Group ID"
+msgstr ""
+
+msgid "Groups|Group URL"
+msgstr ""
+
+msgid "Groups|Group avatar"
+msgstr ""
+
+msgid "Groups|Group description (optional)"
+msgstr ""
+
+msgid "Groups|Group name"
+msgstr ""
+
+msgid "Groups|Group path is available."
+msgstr ""
+
+msgid "Groups|Group path is unavailable. Path has been replaced with a suggested available path."
+msgstr ""
+
+msgid "Groups|Learn more"
+msgstr ""
+
+msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
+msgstr ""
+
+msgid "Groups|Remove avatar"
+msgstr ""
+
+msgid "Groups|Save changes"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -17667,6 +18020,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17727,9 +18107,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17781,6 +18158,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17856,6 +18236,9 @@ msgstr ""
msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
msgstr ""
+msgid "IP"
+msgstr ""
+
msgid "IP Address"
msgstr ""
@@ -17883,7 +18266,7 @@ msgstr ""
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
-msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method."
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Create a project"
@@ -17949,6 +18332,9 @@ msgstr ""
msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
msgstr ""
+msgid "If you are added to a project, it will be displayed here."
+msgstr ""
+
msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
msgstr ""
@@ -18255,12 +18641,24 @@ msgstr ""
msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|A single application eliminates complex integrations, data chokepoints, and toolchain maintenance, resulting in greater productivity and lower cost."
+msgstr ""
+
+msgid "InProductMarketing|Access advanced features, build more efficiently, strengthen security and compliance."
+msgstr ""
+
+msgid "InProductMarketing|Access advanced features."
+msgstr ""
+
msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
msgstr ""
msgid "InProductMarketing|And finally %{deploy_link} a Python application."
msgstr ""
+msgid "InProductMarketing|And many more..."
+msgstr ""
+
msgid "InProductMarketing|Are your runners ready?"
msgstr ""
@@ -18279,15 +18677,33 @@ msgstr ""
msgid "InProductMarketing|Blog"
msgstr ""
+msgid "InProductMarketing|Break down silos to coordinate seamlessly across development, operations, and security with a consistent experience across the development lifecycle."
+msgstr ""
+
+msgid "InProductMarketing|Burn up/down charts"
+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"
+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 ""
+msgid "InProductMarketing|Code review analytics"
+msgstr ""
+
+msgid "InProductMarketing|Collaboration across stages in GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Collaboration made easy"
+msgstr ""
+
msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
msgstr ""
@@ -18297,12 +18713,21 @@ msgstr ""
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
msgstr ""
+msgid "InProductMarketing|Create well-defined workflows by using scoped labels on issues, merge requests, and epics. Labels with the same scope cannot be used together, which prevents conflicts."
+msgstr ""
+
msgid "InProductMarketing|Create your first project!"
msgstr ""
+msgid "InProductMarketing|Define who owns specific files or directories, so the right reviewers are suggested when a merge request introduces changes to those files."
+msgstr ""
+
msgid "InProductMarketing|Deliver Better Products Faster"
msgstr ""
+msgid "InProductMarketing|Dependency scanning"
+msgstr ""
+
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
@@ -18312,15 +18737,27 @@ msgstr ""
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Discover Premium & Ultimate"
+msgstr ""
+
+msgid "InProductMarketing|Discover Premium & Ultimate."
+msgstr ""
+
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr ""
+msgid "InProductMarketing|Dynamic application security testing"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
+msgid "InProductMarketing|Epics"
+msgstr ""
+
msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
msgstr ""
@@ -18342,9 +18779,15 @@ msgstr ""
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
+msgid "InProductMarketing|Find and fix bottlenecks in your code review process by understanding how long open merge requests have been in review."
+msgstr ""
+
msgid "InProductMarketing|Find out how your teams are really doing"
msgstr ""
+msgid "InProductMarketing|Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
+msgstr ""
+
msgid "InProductMarketing|Follow our steps"
msgstr ""
@@ -18381,6 +18824,9 @@ msgstr ""
msgid "InProductMarketing|GitLab is better with teammates to help out!"
msgstr ""
+msgid "InProductMarketing|GitLab is infrastructure agnostic (supporting GCP, AWS, Azure, OpenShift, VMWare, On Prem, Bare Metal, and more), offering a consistent workflow experience – irrespective of the environment."
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -18471,21 +18917,36 @@ msgstr ""
msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
msgstr ""
+msgid "InProductMarketing|Keep your code quality high by defining who should approve merge requests and how many approvals are required."
+msgstr ""
+
msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
msgstr ""
+msgid "InProductMarketing|Lower cost of development"
+msgstr ""
+
+msgid "InProductMarketing|Make it easier to collaborate on high-level ideas by grouping related issues in an epic."
+msgstr ""
+
msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
msgstr ""
msgid "InProductMarketing|Master the art of importing!"
msgstr ""
+msgid "InProductMarketing|Merge request approval rule"
+msgstr ""
+
msgid "InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}"
msgstr ""
msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"
msgstr ""
+msgid "InProductMarketing|Multiple required approvers"
+msgstr ""
+
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
@@ -18498,18 +18959,33 @@ msgstr ""
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
+msgid "InProductMarketing|Protect your web application by using DAST to examine for vulnerabilities in deployed environments."
+msgstr ""
+
msgid "InProductMarketing|Rapid development, simplified"
msgstr ""
msgid "InProductMarketing|Reduce Security & Compliance Risk"
msgstr ""
+msgid "InProductMarketing|Require multiple approvers on a merge request, so you know it's in good shape before it's merged."
+msgstr ""
+
+msgid "InProductMarketing|Roadmaps"
+msgstr ""
+
+msgid "InProductMarketing|Scoped labels"
+msgstr ""
+
msgid "InProductMarketing|Security that's integrated into your development lifecycle"
msgstr ""
msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
msgstr ""
+msgid "InProductMarketing|Speed. Efficiency. Trust."
+msgstr ""
+
msgid "InProductMarketing|Spin up an autoscaling runner in GitLab"
msgstr ""
@@ -18519,6 +18995,9 @@ msgstr ""
msgid "InProductMarketing|Start a Self-Managed trial"
msgstr ""
+msgid "InProductMarketing|Start a free trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18585,6 +19064,9 @@ msgstr ""
msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
msgstr ""
+msgid "InProductMarketing|Track completed issues in a chart, so you can see how a milestone is progressing at a glance."
+msgstr ""
+
msgid "InProductMarketing|Try GitLab Ultimate for free"
msgstr ""
@@ -18621,6 +19103,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
+msgstr ""
+
msgid "InProductMarketing|Want to host GitLab on your servers?"
msgstr ""
@@ -18642,6 +19127,9 @@ msgstr ""
msgid "InProductMarketing|YouTube"
msgstr ""
+msgid "InProductMarketing|Your software, deployed your way"
+msgstr ""
+
msgid "InProductMarketing|Your teams can be more efficient"
msgstr ""
@@ -18765,6 +19253,12 @@ msgstr ""
msgid "IncidentManagement|Open"
msgstr ""
+msgid "IncidentManagement|Page your team with escalation policies"
+msgstr ""
+
+msgid "IncidentManagement|Paged"
+msgstr ""
+
msgid "IncidentManagement|Published"
msgstr ""
@@ -18792,6 +19286,9 @@ msgstr ""
msgid "IncidentManagement|Unpublished"
msgstr ""
+msgid "IncidentManagement|Use escalation policies to automatically page your team when incidents are created."
+msgstr ""
+
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
msgstr ""
@@ -18837,7 +19334,10 @@ msgstr ""
msgid "Incidents"
msgstr ""
-msgid "Incidents|Add a URL"
+msgid "Incidents|Add image details"
+msgstr ""
+
+msgid "Incidents|Add text or a link to display with your image. If you don't add either, the file name displays instead."
msgstr ""
msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
@@ -18852,10 +19352,10 @@ msgstr ""
msgid "Incidents|There was an issue loading metric images."
msgstr ""
-msgid "Incidents|There was an issue uploading your image."
+msgid "Incidents|There was an issue updating your image."
msgstr ""
-msgid "Incidents|You can optionally add a URL to link users to the original graph."
+msgid "Incidents|There was an issue uploading your image."
msgstr ""
msgid "Incident|Alert details"
@@ -18864,9 +19364,18 @@ msgstr ""
msgid "Incident|Are you sure you wish to delete this image?"
msgstr ""
+msgid "Incident|Delete image"
+msgstr ""
+
msgid "Incident|Deleting %{filename}"
msgstr ""
+msgid "Incident|Edit image text or link"
+msgstr ""
+
+msgid "Incident|Editing %{filename}"
+msgstr ""
+
msgid "Incident|Metrics"
msgstr ""
@@ -19124,9 +19633,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19139,9 +19645,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Clear if using a self-signed certificate."
msgstr ""
@@ -19217,6 +19720,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19235,9 +19741,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19277,6 +19780,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19286,6 +19792,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19325,9 +19834,6 @@ msgstr ""
msgid "Integrations|can't exceed %{recipients_limit}"
msgstr ""
-msgid "Interactive developer security education."
-msgstr ""
-
msgid "Interactive mode"
msgstr ""
@@ -19346,7 +19852,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -19817,6 +20323,9 @@ msgstr ""
msgid "IssueAnalytics|Assignees"
msgstr ""
+msgid "IssueAnalytics|Created by"
+msgstr ""
+
msgid "IssueAnalytics|Due date"
msgstr ""
@@ -19829,9 +20338,6 @@ msgstr ""
msgid "IssueAnalytics|Milestone"
msgstr ""
-msgid "IssueAnalytics|Opened by"
-msgstr ""
-
msgid "IssueAnalytics|Status"
msgstr ""
@@ -19955,10 +20461,10 @@ msgstr ""
msgid "IssuesAnalytics|Avg/Month:"
msgstr ""
-msgid "IssuesAnalytics|Issues opened"
+msgid "IssuesAnalytics|Issues created"
msgstr ""
-msgid "IssuesAnalytics|Issues opened per month"
+msgid "IssuesAnalytics|Issues created per month"
msgstr ""
msgid "IssuesAnalytics|Last 12 months"
@@ -19985,6 +20491,9 @@ msgstr ""
msgid "It looks like you have some draft commits in this branch."
msgstr ""
+msgid "It looks like you're attempting to activate your subscription. Use %{a_start}the Subscription page%{a_end} instead."
+msgstr ""
+
msgid "It may be several days before you see feature usage data."
msgstr ""
@@ -20213,6 +20722,9 @@ msgstr ""
msgid "JiraConnect|You can now close this window and return to Jira."
msgstr ""
+msgid "JiraConnect|You don't have permission to create branches for this project. Select a different project or contact the project owner for access. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "JiraRequest|A connection error occurred while connecting to Jira. Try your request again."
msgstr ""
@@ -20486,6 +20998,9 @@ msgstr ""
msgid "Job|Erase job log and artifacts"
msgstr ""
+msgid "Job|Finished at"
+msgstr ""
+
msgid "Job|Job artifacts"
msgstr ""
@@ -20510,6 +21025,9 @@ msgstr ""
msgid "Job|Show complete raw"
msgstr ""
+msgid "Job|Status"
+msgstr ""
+
msgid "Job|The artifacts were removed"
msgstr ""
@@ -20654,9 +21172,6 @@ msgstr ""
msgid "Ki"
msgstr ""
-msgid "Kontra"
-msgstr ""
-
msgid "Kroki"
msgstr ""
@@ -20980,6 +21495,9 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
+msgid "Learn more about GitLab"
+msgstr ""
+
msgid "Learn more about Needs relationships"
msgstr ""
@@ -21307,9 +21825,18 @@ msgstr ""
msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
msgstr ""
+msgid "Licenses|Drag your license file here or %{linkStart}click to upload%{linkEnd}."
+msgstr ""
+
+msgid "Licenses|Drop your license file to start the upload."
+msgstr ""
+
msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
msgstr ""
+msgid "Licenses|Error: You are trying to upload something other than a file"
+msgstr ""
+
msgid "Licenses|License Compliance"
msgstr ""
@@ -21328,6 +21855,9 @@ msgstr ""
msgid "Licenses|Specified policies in this project"
msgstr ""
+msgid "Licenses|The file could not be uploaded."
+msgstr ""
+
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
@@ -21375,6 +21905,9 @@ msgstr ""
msgid "Link"
msgstr ""
+msgid "Link (optional)"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -21411,6 +21944,9 @@ msgstr ""
msgid "Linked emails (%{email_count})"
msgstr ""
+msgid "Linked epics"
+msgstr ""
+
msgid "Linked issues"
msgstr ""
@@ -21438,6 +21974,9 @@ msgstr ""
msgid "List of all merge commits"
msgstr ""
+msgid "List of users allowed to exceed the rate limit."
+msgstr ""
+
msgid "List options"
msgstr ""
@@ -21657,6 +22196,9 @@ msgstr ""
msgid "Maintenance mode"
msgstr ""
+msgid "Make adjustments to how your GitLab instance is set up."
+msgstr ""
+
msgid "Make and review changes in the browser with the Web IDE"
msgstr ""
@@ -22062,6 +22604,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum requests per 10 minutes per user"
+msgstr ""
+
msgid "Maximum requests per minute"
msgstr ""
@@ -22152,6 +22697,19 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
+msgid "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seat in use and will be billed for the overage."
+msgid_plural "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seats in use and will be billed for the overage."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "MembersOverage|You are about to incur additional charges"
+msgstr ""
+
+msgid "MembersOverage|Your subscription includes %d seat."
+msgid_plural "MembersOverage|Your subscription includes %d seats."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Membership"
msgstr ""
@@ -22353,6 +22911,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22371,9 +22935,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22440,13 +23013,13 @@ msgstr ""
msgid "MergeRequests|Create issue to resolve thread"
msgstr ""
-msgid "MergeRequests|Failed to squash. Should be done manually."
+msgid "MergeRequests|Saving the comment failed"
msgstr ""
-msgid "MergeRequests|Saving the comment failed"
+msgid "MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch."
msgstr ""
-msgid "MergeRequests|This project does not allow squashing commits when merge requests are accepted."
+msgid "MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging."
msgstr ""
msgid "MergeRequests|Thread stays resolved"
@@ -23215,9 +23788,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23290,6 +23860,18 @@ msgstr ""
msgid "MrDeploymentActions|Stop environment"
msgstr ""
+msgid "MrList|Assigned to %{name}, go to their profile."
+msgstr ""
+
+msgid "MrList|Attention requested from assignee %{name}, go to their profile."
+msgstr ""
+
+msgid "MrList|Attention requested from reviewer %{name}, go to their profile."
+msgstr ""
+
+msgid "MrList|Review requested from %{name}, go to their profile."
+msgstr ""
+
msgid "Multi-project"
msgstr ""
@@ -23323,7 +23905,7 @@ msgstr ""
msgid "Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "My Awesome Group"
+msgid "My awesome group"
msgstr ""
msgid "My company or team"
@@ -23502,9 +24084,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23583,9 +24162,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -24119,6 +24695,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -25031,7 +25610,7 @@ msgstr ""
msgid "Opened issues"
msgstr ""
-msgid "OpenedNDaysAgo|Opened"
+msgid "OpenedNDaysAgo|Created"
msgstr ""
msgid "Opens in a new window"
@@ -25076,9 +25655,6 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
-msgid "Optional."
-msgstr ""
-
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -25867,6 +26443,9 @@ msgstr ""
msgid "PerformanceBar|Memory"
msgstr ""
+msgid "PerformanceBar|Memory report"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -25909,9 +26488,6 @@ msgstr ""
msgid "Permalink"
msgstr ""
-msgid "Permanently delete project"
-msgstr ""
-
msgid "Permanently remove group"
msgstr ""
@@ -26182,13 +26758,46 @@ msgstr ""
msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
msgstr ""
-msgid "Pipelines"
+msgid "PipelineWizardDefaultCommitMessage|Add %{filename}"
msgstr ""
-msgid "Pipelines charts"
+msgid "PipelineWizardDefaultCommitMessage|Update %{filename}"
+msgstr ""
+
+msgid "PipelineWizardInputValidation|This field is required"
+msgstr ""
+
+msgid "PipelineWizardInputValidation|This value is not valid"
+msgstr ""
+
+msgid "PipelineWizard|Commit"
+msgstr ""
+
+msgid "PipelineWizard|Commit Message"
+msgstr ""
+
+msgid "PipelineWizard|Commit changes to your file"
+msgstr ""
+
+msgid "PipelineWizard|Commit file to Branch"
+msgstr ""
+
+msgid "PipelineWizard|Commit your new file"
+msgstr ""
+
+msgid "PipelineWizard|The file has been committed."
+msgstr ""
+
+msgid "PipelineWizard|There was a problem committing the changes."
+msgstr ""
+
+msgid "PipelineWizard|There was a problem while checking whether your file already exists in the specified branch."
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
msgstr ""
msgid "Pipelines settings for '%{project_name}' were successfully updated."
@@ -26383,6 +26992,9 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
msgid "Pipelines|detached"
msgstr ""
@@ -26584,6 +27196,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26689,9 +27304,6 @@ msgstr ""
msgid "Please enter a valid time interval"
msgstr ""
-msgid "Please enter or upload a valid license."
-msgstr ""
-
msgid "Please enter your current password."
msgstr ""
@@ -26800,9 +27412,6 @@ msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
-msgid "Please type the following to confirm:"
-msgstr ""
-
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -26836,6 +27445,18 @@ msgstr ""
msgid "Policy project doesn't exist"
msgstr ""
+msgid "PolicyRuleMultiSelect|%{firstLabel} +%{numberOfAdditionalLabels} more"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|All %{itemTypeName}"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|Select %{itemTypeName}"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|Select all"
+msgstr ""
+
msgid "Polling interval multiplier"
msgstr ""
@@ -27064,6 +27685,9 @@ msgstr ""
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Problem with %{name} command: %{message}."
+msgstr ""
+
msgid "Proceed"
msgstr ""
@@ -27214,9 +27838,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27394,6 +28015,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27538,6 +28162,9 @@ msgstr ""
msgid "Progress"
msgstr ""
+msgid "Progress tracking"
+msgstr ""
+
msgid "Project"
msgstr ""
@@ -27961,10 +28588,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28042,6 +28672,9 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
msgstr ""
@@ -28057,13 +28690,19 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Learn about commit history."
+msgstr ""
+
+msgid "ProjectSettings|Leave empty to use default template."
+msgstr ""
+
msgid "ProjectSettings|Manage who can see the project in the public access directory."
msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
-msgid "ProjectSettings|Maximum 500 characters."
+msgid "ProjectSettings|Maximum %{maxLength} characters."
msgstr ""
msgid "ProjectSettings|Merge checks"
@@ -28090,6 +28729,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28201,6 +28843,9 @@ msgstr ""
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
+msgid "ProjectSettings|The default template will be applied on save."
+msgstr ""
+
msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
@@ -28216,9 +28861,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28240,7 +28882,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28258,7 +28900,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|What are merge trains?"
+msgstr ""
+
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28375,6 +29020,9 @@ msgstr ""
msgid "Projects are organized into groups"
msgstr ""
+msgid "Projects are where you store your code, access issues, wiki and other features of GitLab."
+msgstr ""
+
msgid "Projects contributed to"
msgstr ""
@@ -28390,12 +29038,6 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
-msgstr ""
-
-msgid "Projects will be permanently deleted immediately."
-msgstr ""
-
msgid "Projects with critical vulnerabilities"
msgstr ""
@@ -28912,6 +29554,9 @@ msgstr ""
msgid "ProtectedBranch|Unprotect"
msgstr ""
+msgid "ProtectedBranch|Unprotect branch"
+msgstr ""
+
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
@@ -28939,6 +29584,9 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Required approvals"
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -28960,10 +29608,13 @@ msgstr ""
msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr ""
+msgid "ProtectedTags|Unprotect tag"
+msgstr ""
+
msgid "ProtectedTags|default"
msgstr ""
-msgid "ProtectedTag|By default, protected branches restrict who can modify the tag."
+msgid "ProtectedTag|By default, protected tags restrict who can modify the tag."
msgstr ""
msgid "ProtectedTag|Learn more."
@@ -29026,6 +29677,9 @@ msgstr ""
msgid "Public projects Minutes cost factor"
msgstr ""
+msgid "Public projects are an easy way to allow everyone to have read-only access."
+msgstr ""
+
msgid "Publish to status page"
msgstr ""
@@ -29053,7 +29707,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29269,6 +29923,9 @@ msgstr ""
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
msgstr ""
+msgid "Read more about related epics"
+msgstr ""
+
msgid "Read more about related issues"
msgstr ""
@@ -29353,9 +30010,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recovering projects"
-msgstr ""
-
msgid "Recovery Codes"
msgstr ""
@@ -29451,7 +30105,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29645,9 +30299,6 @@ msgstr ""
msgid "Remove all or specific reviewer(s)"
msgstr ""
-msgid "Remove approver"
-msgstr ""
-
msgid "Remove approvers"
msgstr ""
@@ -29663,6 +30314,9 @@ msgstr ""
msgid "Remove attention request"
msgstr ""
+msgid "Remove attention request(s)"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -29801,6 +30455,9 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
+msgid "Removed attention from %{users_sentence}."
+msgstr ""
+
msgid "Removed attention request from @%{username}"
msgstr ""
@@ -29852,6 +30509,9 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
+msgid "Removes attention from %{users_sentence}."
+msgstr ""
+
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -29991,6 +30651,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30217,6 +30882,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30244,6 +30912,15 @@ msgstr ""
msgid "Request attention"
msgstr ""
+msgid "Request attention from %{users_sentence}."
+msgstr ""
+
+msgid "Request attention from assignee or reviewer"
+msgstr ""
+
+msgid "Request attention from assignee(s) or reviewer(s)"
+msgstr ""
+
msgid "Request attention to review"
msgstr ""
@@ -30268,6 +30945,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from %{users_sentence}."
+msgstr ""
+
msgid "Requested attention from @%{username}"
msgstr ""
@@ -30310,6 +30990,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30479,6 +31162,9 @@ msgstr ""
msgid "Restore project"
msgstr ""
+msgid "Restoring projects"
+msgstr ""
+
msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
msgstr ""
@@ -30509,6 +31195,9 @@ msgstr ""
msgid "Retry"
msgstr ""
+msgid "Retry failed jobs"
+msgstr ""
+
msgid "Retry job"
msgstr ""
@@ -30556,9 +31245,6 @@ msgstr ""
msgid "Review changes"
msgstr ""
-msgid "Review requested from %{name}"
-msgstr ""
-
msgid "Review requests for you"
msgstr ""
@@ -30630,6 +31316,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30717,6 +31406,12 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
+msgid "Runners|Assigned Projects (%{projectCount})"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30735,6 +31430,9 @@ msgstr ""
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30753,6 +31451,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30768,9 +31469,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30783,6 +31481,9 @@ msgstr ""
msgid "Runners|Instance"
msgstr ""
+msgid "Runners|Jobs"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -30861,6 +31562,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30873,9 +31577,6 @@ msgstr ""
msgid "Runners|Runner %{name} was deleted"
msgstr ""
-msgid "Runners|Runner ID"
-msgstr ""
-
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30900,16 +31601,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31023,6 +31724,9 @@ msgstr ""
msgid "Runners|stale"
msgstr ""
+msgid "Runner|This runner has not run any jobs."
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -31092,9 +31796,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31140,6 +31841,12 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval from %{approvalsRequired} of the following approvers: %{approvers}"
+msgstr ""
+
+msgid "ScanResultPolicy|add an approver"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -31468,9 +32175,6 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
-msgid "SecureCodeWarrior"
-msgstr ""
-
msgid "Security"
msgstr ""
@@ -31495,9 +32199,6 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "Security training with guide and learning pathways."
-msgstr ""
-
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -31522,7 +32223,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31600,7 +32301,7 @@ msgstr ""
msgid "SecurityConfiguration|Manage corpus"
msgstr ""
-msgid "SecurityConfiguration|Manage corpus files used as mutation sources in coverage fuzzing."
+msgid "SecurityConfiguration|Manage corpus files used as seed inputs with coverage-guided fuzzing."
msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
@@ -31675,6 +32376,9 @@ msgstr ""
msgid "SecurityOrchestration|Add rule"
msgstr ""
+msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again."
+msgstr ""
+
msgid "SecurityOrchestration|All policies"
msgstr ""
@@ -31690,7 +32394,7 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
-msgid "SecurityOrchestration|Disabled"
+msgid "SecurityOrchestration|Don't show the alert anymore"
msgstr ""
msgid "SecurityOrchestration|Edit policy"
@@ -31711,9 +32415,15 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
+msgid "SecurityOrchestration|Latest scan run against %{agent}"
+msgstr ""
+
msgid "SecurityOrchestration|Network"
msgstr ""
@@ -31723,12 +32433,21 @@ msgstr ""
msgid "SecurityOrchestration|No rules defined - policy will not run."
msgstr ""
+msgid "SecurityOrchestration|Not enabled"
+msgstr ""
+
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
@@ -31768,6 +32487,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan result"
msgstr ""
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,7 +32517,10 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
-msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting the %{branches}."
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
msgid "SecurityOrchestration|There was a problem creating the new security policy"
@@ -31804,6 +32529,9 @@ msgstr ""
msgid "SecurityOrchestration|This project does not contain any security policies."
msgstr ""
+msgid "SecurityOrchestration|This view only shows scan results for the agent %{agent}. You can view scan results for all agents in the %{linkStart}Operational Vulnerabilities tab of the vulnerability report%{linkEnd}."
+msgstr ""
+
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
@@ -31813,12 +32541,15 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
msgstr ""
msgid "SecurityOrchestration|a"
msgstr ""
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
msgid "SecurityOrchestration|an"
msgstr ""
@@ -31846,6 +32577,9 @@ msgstr ""
msgid "SecurityOrchestration|scanners find"
msgstr ""
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
msgid "SecurityOrchestration|user with id"
msgstr ""
@@ -32524,22 +33258,19 @@ msgstr ""
msgid "Serverless|Getting started with serverless"
msgstr ""
-msgid "Serverless|Help shape the future of Serverless at GitLab"
-msgstr ""
-
msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
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|Learn more about Serverless"
msgstr ""
msgid "Serverless|No functions available"
msgstr ""
-msgid "Serverless|Sign up for First Look"
+msgid "Serverless|Serverless was %{linkStart}deprecated%{linkEnd} in GitLab 14.3."
+msgstr ""
+
+msgid "Serverless|Serverless was %{postLinkStart}deprecated%{postLinkEnd}. But if you opt to use it, you must install Knative in your Kubernetes cluster first. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "Serverless|The deploy job has not finished."
@@ -32551,9 +33282,6 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
-msgid "Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly."
-msgstr ""
-
msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
msgstr ""
@@ -32569,9 +33297,6 @@ msgstr ""
msgid "Service Account Key"
msgstr ""
-msgid "Service Accounts"
-msgstr ""
-
msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
@@ -32584,9 +33309,15 @@ msgstr ""
msgid "Service account generated successfully"
msgstr ""
+msgid "Service accounts"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32722,6 +33453,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the per-user rate limit for getting a user by ID via the API."
+msgstr ""
+
msgid "Set the per-user rate limit for notes created by web or API requests."
msgstr ""
@@ -32740,7 +33474,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32901,6 +33635,9 @@ msgstr ""
msgid "Shared runners details"
msgstr ""
+msgid "Shared runners enabled cannot be enabled until a valid credit card is on file"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -32952,9 +33689,15 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
+msgid "Show all milestones"
+msgstr ""
+
msgid "Show all test cases."
msgstr ""
@@ -32964,6 +33707,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32976,9 +33722,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32991,6 +33734,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show group milestones"
+msgstr ""
+
msgid "Show labels"
msgstr ""
@@ -33003,6 +33749,15 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
+msgid "Show project milestones"
+msgstr ""
+
+msgid "Show sub-group milestones"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33043,7 +33798,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33076,12 +33831,6 @@ msgstr ""
msgid "Sidebar|None"
msgstr ""
-msgid "Sidebar|Only numeral characters allowed"
-msgstr ""
-
-msgid "Sidebar|Weight"
-msgstr ""
-
msgid "Sidekiq job compression threshold (bytes)"
msgstr ""
@@ -33244,12 +33993,21 @@ msgstr ""
msgid "Slack logo"
msgstr ""
+msgid "SlackIntegration|Are you sure you want to remove this project from the Slack application?"
+msgstr ""
+
msgid "SlackIntegration|GitLab for Slack"
msgstr ""
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
msgid "SlackIntegration|Project alias"
msgstr ""
+msgid "SlackIntegration|Remove project"
+msgstr ""
+
msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
msgstr ""
@@ -33262,6 +34020,9 @@ msgstr ""
msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
msgstr ""
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33391,9 +34152,6 @@ msgstr ""
msgid "Something went wrong trying to load issue contacts."
msgstr ""
-msgid "Something went wrong when creating a work item. Please try again"
-msgstr ""
-
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -33487,9 +34245,6 @@ msgstr ""
msgid "Something went wrong while inserting your image. Please try again."
msgstr ""
-msgid "Something went wrong while merging this merge request. Please try again."
-msgstr ""
-
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
msgstr ""
@@ -33568,9 +34323,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33961,12 +34713,18 @@ msgstr ""
msgid "Start date"
msgstr ""
+msgid "Start free trial"
+msgstr ""
+
msgid "Start merge train"
msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34009,6 +34767,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34384,6 +35145,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34471,6 +35253,21 @@ msgstr ""
msgid "Subscriptions"
msgstr ""
+msgid "Subscriptions|Chat with sales"
+msgstr ""
+
+msgid "Subscriptions|Close"
+msgstr ""
+
+msgid "Subscriptions|Not ready to buy yet?"
+msgstr ""
+
+msgid "Subscriptions|Start a free trial"
+msgstr ""
+
+msgid "Subscriptions|We understand. Maybe you have some questions for our sales team, or maybe you'd like to try some of the paid features first. What would you like to do?"
+msgstr ""
+
msgid "Subscription|Your subscription for %{strong}%{namespace_name}%{strong_close} has expired and you are now on %{pricing_link_start}the GitLab Free tier%{pricing_link_end}. Don't worry, your data is safe. Get in touch with our support team (%{support_email}). They'll gladly help with your subscription renewal."
msgstr ""
@@ -34630,9 +35427,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34657,6 +35451,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34696,6 +35493,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34750,6 +35550,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34762,6 +35565,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34993,6 +35805,9 @@ msgstr ""
msgid "TagsPage|protected"
msgstr ""
+msgid "Take a look at the documentation to discover all of GitLab’s capabilities."
+msgstr ""
+
msgid "Target Branch"
msgstr ""
@@ -35005,6 +35820,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35250,6 +36068,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35389,6 +36210,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text (optional)"
+msgstr ""
+
msgid "Text added to the body of all email messages. %{character_limit} character limit"
msgstr ""
@@ -35422,9 +36246,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35517,6 +36338,9 @@ msgstr ""
msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
msgstr ""
+msgid "The current epic"
+msgstr ""
+
msgid "The current issue"
msgstr ""
@@ -35672,9 +36496,15 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
+msgid "The license key is invalid."
+msgstr ""
+
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -35690,6 +36520,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The license you uploaded is invalid. If the issue persists, contact support at %{link}."
+msgstr ""
+
msgid "The list creation wizard is already open"
msgstr ""
@@ -36131,7 +36964,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36182,7 +37015,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36311,10 +37144,10 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues and merge requests."
+msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} and everything this project contains. %{strongOpen}There is no going back%{strongClose}"
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues and merge requests."
+msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains."
msgstr ""
msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}immediately%{strongClose}."
@@ -36389,6 +37222,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36428,9 +37264,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36443,9 +37276,6 @@ msgstr ""
msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
msgstr ""
-msgid "This forked project has the following:"
-msgstr ""
-
msgid "This form is disabled in preview"
msgstr ""
@@ -36476,6 +37306,9 @@ msgstr ""
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36524,6 +37357,12 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue cannot be assigned to a confidential epic because it is public."
+msgstr ""
+
+msgid "This issue cannot be made public because it belongs to a confidential epic."
+msgstr ""
+
msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
msgstr ""
@@ -36641,6 +37480,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
+msgid "This merge request branch is protected from force push."
+msgstr ""
+
msgid "This merge request cannot be rebased while there are conflicts."
msgstr ""
@@ -36692,9 +37534,15 @@ msgstr ""
msgid "This pipeline was triggered by a schedule."
msgstr ""
+msgid "This process deletes the project repository and all related resources."
+msgstr ""
+
msgid "This project"
msgstr ""
+msgid "This project can be restored until %{date}."
+msgstr ""
+
msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
msgstr ""
@@ -36713,6 +37561,9 @@ msgstr ""
msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources."
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -37395,9 +38246,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37407,6 +38255,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Todos count"
+msgstr ""
+
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
msgstr ""
@@ -37802,6 +38653,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38153,6 +39010,9 @@ msgstr ""
msgid "Unlock account"
msgstr ""
+msgid "Unlock more features with GitLab Ultimate"
+msgstr ""
+
msgid "Unlock the discussion"
msgstr ""
@@ -38216,6 +39076,9 @@ msgstr ""
msgid "Unsubscribes from this %{quick_action_target}."
msgstr ""
+msgid "Unsupported sort value."
+msgstr ""
+
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
@@ -38444,6 +39307,9 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
+msgid "UsageQuota|From %{storage_enforcement_date} storage limits will apply to this namespace. View and manage your usage in %{strong_start}Group Settings &gt; Usage quotas%{strong_end}."
+msgstr ""
+
msgid "UsageQuota|Git repository."
msgstr ""
@@ -38699,6 +39565,12 @@ msgstr ""
msgid "Use hashed storage paths for newly created and renamed repositories. Always enabled since 13.0."
msgstr ""
+msgid "Use issue count"
+msgstr ""
+
+msgid "Use issue weight"
+msgstr ""
+
msgid "Use one line per URI"
msgstr ""
@@ -39080,6 +39952,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users API rate limit"
+msgstr ""
+
msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
msgstr ""
@@ -39405,6 +40280,9 @@ msgstr ""
msgid "View group labels"
msgstr ""
+msgid "View group pipeline usage quota"
+msgstr ""
+
msgid "View incident details at"
msgstr ""
@@ -39476,6 +40354,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39605,6 +40486,9 @@ msgstr ""
msgid "VulnerabilityManagement|An unverified non-confirmed finding"
msgstr ""
+msgid "VulnerabilityManagement|At least one identifier is required"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -39614,12 +40498,24 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
+msgid "VulnerabilityManagement|Enter a name"
+msgstr ""
+
+msgid "VulnerabilityManagement|Enter the CVE or CWE code"
+msgstr ""
+
+msgid "VulnerabilityManagement|Enter the CVE or CWE identifier URL"
+msgstr ""
+
msgid "VulnerabilityManagement|Fetching linked Jira issues"
msgstr ""
msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
+msgid "VulnerabilityManagement|Name is a required field"
+msgstr ""
+
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -39635,6 +40531,18 @@ msgstr ""
msgid "VulnerabilityManagement|Select a method"
msgstr ""
+msgid "VulnerabilityManagement|Select a severity level"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Severity is a required field"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while creating vulnerability"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -39659,6 +40567,12 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Status is a required field"
+msgstr ""
+
+msgid "VulnerabilityManagement|Submit vulnerability"
+msgstr ""
+
msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
msgstr ""
@@ -39812,6 +40726,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39845,6 +40762,9 @@ msgstr ""
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40067,6 +40987,15 @@ msgstr ""
msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
+msgid "Webhooks|Are you sure you want to delete this group hook?"
+msgstr ""
+
+msgid "Webhooks|Are you sure you want to delete this project hook?"
+msgstr ""
+
+msgid "Webhooks|Are you sure you want to delete this webhook?"
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr ""
@@ -40076,6 +41005,9 @@ msgstr ""
msgid "Webhooks|Confidential issues events"
msgstr ""
+msgid "Webhooks|Delete webhook"
+msgstr ""
+
msgid "Webhooks|Deployment events"
msgstr ""
@@ -40564,6 +41496,24 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
+msgstr ""
+
+msgid "WorkItem|Something went wrong when creating a work item. Please try again"
+msgstr ""
+
+msgid "WorkItem|Something went wrong when fetching work item types. Please try again"
+msgstr ""
+
+msgid "WorkItem|Type"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -40630,7 +41580,10 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to permanently delete this project"
+msgid "You are about to delete this forked project containing:"
+msgstr ""
+
+msgid "You are about to delete this project containing:"
msgstr ""
msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
@@ -40651,6 +41604,9 @@ msgstr ""
msgid "You are attempting to update a file that has changed since you started editing it."
msgstr ""
+msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
+msgstr ""
+
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
@@ -40663,6 +41619,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40696,6 +41655,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40855,9 +41817,6 @@ msgstr ""
msgid "You can only upload one design when dropping onto an existing design."
msgstr ""
-msgid "You can recover this project until %{date}"
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -40906,9 +41865,6 @@ 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 can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
@@ -40930,6 +41886,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41079,6 +42038,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41535,6 +42497,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41679,6 +42644,9 @@ msgstr ""
msgid "archived:"
msgstr ""
+msgid "artifacts"
+msgstr ""
+
msgid "assign yourself"
msgstr ""
@@ -41708,6 +42676,9 @@ msgstr[1] ""
msgid "branch name"
msgstr ""
+msgid "builds"
+msgstr ""
+
msgid "by"
msgstr ""
@@ -42131,6 +43102,9 @@ msgstr ""
msgid "contact with same email already exists in group hierarchy"
msgstr ""
+msgid "container registry images"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42170,6 +43144,9 @@ msgstr ""
msgid "data"
msgstr ""
+msgid "database"
+msgstr ""
+
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -42543,6 +43520,9 @@ msgstr ""
msgid "level: %{level}"
msgstr ""
+msgid "lfs objects"
+msgstr ""
+
msgid "limit of %{project_limit} reached"
msgstr ""
@@ -42596,9 +43576,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42721,7 +43698,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42765,6 +43742,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
+msgstr ""
+
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
@@ -42825,6 +43805,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42870,13 +43853,13 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
-msgid "mrWidget|The changes were merged into"
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were not merged into"
+msgid "mrWidget|The changes were merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
+msgid "mrWidget|The changes were not merged into"
msgstr ""
msgid "mrWidget|The source branch has been deleted"
@@ -42915,9 +43898,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43029,9 +44009,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgo}"
-msgstr ""
-
msgid "or"
msgstr ""
@@ -43043,6 +44020,12 @@ msgid_plural "out of %d total tests"
msgstr[0] ""
msgstr[1] ""
+msgid "packages"
+msgstr ""
+
+msgid "pages"
+msgstr ""
+
msgid "parent"
msgid_plural "parents"
msgstr[0] ""
@@ -43192,6 +44175,9 @@ msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "repositories"
+msgstr ""
+
msgid "repository:"
msgstr ""
@@ -43312,12 +44298,18 @@ msgstr ""
msgid "tag name"
msgstr ""
+msgid "terraform states"
+msgstr ""
+
msgid "the correct format."
msgstr ""
msgid "the file"
msgstr ""
+msgid "the following epic(s)"
+msgstr ""
+
msgid "the following issue(s)"
msgstr ""
@@ -43330,12 +44322,6 @@ msgstr ""
msgid "this document"
msgstr ""
-msgid "this issue cannot be assigned to a confidential epic since it is public"
-msgstr ""
-
-msgid "this issue cannot be made public since it belongs to a confidential epic"
-msgstr ""
-
msgid "time summary"
msgstr ""
@@ -43472,3 +44458,6 @@ msgstr ""
msgid "{project}"
msgstr ""
+
+msgid "✔"
+msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 3c6e7a33c91..4a23d97d8e4 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr " %{start} a %{end}"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 791ca7c801e..26cb7e7c4a6 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -132,6 +132,34 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -780,6 +814,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -876,6 +913,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr "הוספת CONTRIBUTING (הדרכה למתנדבי×)"
-msgid "Add GitLab to Slack"
-msgstr "הוספת GitLab ל־Slack"
-
msgid "Add Jaeger URL"
msgstr "הוספת כתובת Jaeger"
@@ -2223,7 +2251,7 @@ msgstr "הוספת מקבץ Kubernetes"
msgid "Add LICENSE"
msgstr "הוספת LICENSE (רישיון)"
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2238,6 +2266,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "הוספת מפתח GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "הוספת מפתח SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2421,9 +2455,6 @@ msgstr "הוספת התליית מערכת"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "הוספת טקסט לעמוד הכניסה. ×פשר Markdown."
-msgid "Add to Slack"
-msgstr "הוספה ל־Slack"
-
msgid "Add to board"
msgstr "הוספה ללוח"
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4041,16 +4075,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 31fcea58b1f..f0c42e611c1 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 186561fdfda..a32857f1e13 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -124,6 +124,30 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -532,6 +556,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -703,6 +733,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -799,6 +832,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -808,6 +844,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -919,9 +958,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -955,6 +991,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1948,21 +1987,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1987,9 +2017,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2095,9 +2122,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2107,7 +2131,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2122,6 +2146,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2188,6 +2215,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2305,9 +2335,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2605,6 +2632,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2761,6 +2794,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2797,7 +2833,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2923,6 +2959,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3088,7 +3130,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3649,22 +3691,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3775,9 +3808,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3925,16 +3955,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4498,9 +4525,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4531,9 +4555,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4543,13 +4564,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4576,7 +4597,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4591,6 +4612,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4606,7 +4630,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4618,22 +4642,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4747,6 +4777,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4840,9 +4873,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4927,7 +4957,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5371,6 +5401,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5503,6 +5536,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5530,6 +5566,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5545,9 +5584,6 @@ 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 ""
@@ -5584,9 +5620,6 @@ 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 ""
@@ -5665,9 +5698,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5746,6 +5785,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6061,18 +6103,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6088,9 +6124,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6139,15 +6172,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6166,9 +6190,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6364,6 +6385,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6430,9 +6460,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6667,6 +6709,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7048,6 +7093,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7225,6 +7273,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7525,15 +7576,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7630,6 +7672,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7654,7 +7702,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7699,7 +7747,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7729,7 +7777,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7786,13 +7834,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7819,7 +7870,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7846,6 +7897,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7858,6 +7921,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7882,7 +7948,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7900,6 +7966,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8851,6 +8920,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9100,6 +9172,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9130,6 +9205,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9175,12 +9256,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9208,12 +9292,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9775,7 +9865,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9916,9 +10006,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9931,9 +10036,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10006,6 +10108,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10033,13 +10138,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10183,6 +10291,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10441,6 +10552,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10675,6 +10789,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10909,6 +11026,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10918,10 +11038,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11011,12 +11131,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11029,9 +11143,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11044,9 +11155,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11119,9 +11227,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11149,9 +11254,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11161,12 +11263,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11179,9 +11275,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11203,9 +11296,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11476,9 +11566,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11911,6 +11998,9 @@ msgstr[2] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11926,6 +12016,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12139,9 +12232,39 @@ msgstr[2] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12706,9 +12829,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12775,7 +12895,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12970,7 +13090,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13216,6 +13336,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13360,9 +13483,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13405,6 +13525,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13432,6 +13555,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13510,9 +13639,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13561,6 +13687,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13837,6 +13966,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14650,9 +14785,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14662,15 +14794,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14686,6 +14812,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14767,10 +14941,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15211,15 +15382,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15307,12 +15469,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15637,6 +15793,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15712,6 +15871,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15748,18 +15910,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15796,6 +15961,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15850,6 +16018,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15925,12 +16096,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15946,6 +16111,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15979,16 +16147,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16000,9 +16171,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16051,6 +16219,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16087,10 +16261,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16168,6 +16342,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16291,9 +16468,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16318,6 +16492,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16498,6 +16675,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16636,6 +16816,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16804,6 +16987,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16822,6 +17008,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16885,9 +17074,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16912,6 +17098,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16924,9 +17113,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17167,18 +17353,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17203,9 +17383,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17236,7 +17413,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17284,6 +17464,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17302,9 +17485,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17332,9 +17512,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17377,7 +17554,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17458,9 +17635,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17515,7 +17689,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17746,6 +17920,33 @@ msgstr[2] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17806,9 +18007,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17845,9 +18043,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17863,6 +18058,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17962,6 +18160,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17986,9 +18196,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18592,6 +18799,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18694,6 +18904,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18769,6 +18982,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19192,9 +19408,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19207,9 +19420,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19279,6 +19489,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19297,9 +19510,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19336,6 +19546,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19345,6 +19558,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19405,7 +19621,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21226,6 +21442,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21556,9 +21775,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21574,6 +21790,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21610,6 +21829,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22384,6 +22636,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22402,9 +22660,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23227,9 +23494,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23251,9 +23515,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23431,10 +23692,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23539,9 +23800,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23620,9 +23878,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23641,9 +23896,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24160,6 +24412,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24187,6 +24442,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24253,7 +24511,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25168,7 +25426,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25786,9 +26065,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25927,6 +26203,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25945,7 +26224,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26212,9 +26491,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26227,6 +26503,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26239,7 +26518,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26404,10 +26683,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26590,6 +26887,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26605,6 +26905,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26959,6 +27265,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27184,6 +27493,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27208,9 +27520,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27388,6 +27697,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27433,9 +27745,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27958,10 +28267,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28039,6 +28351,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28084,6 +28402,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28210,9 +28531,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28234,7 +28552,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28252,7 +28570,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29014,9 +29332,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29050,7 +29365,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29296,6 +29611,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29365,6 +29686,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29440,7 +29764,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29983,6 +30307,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30211,6 +30541,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30286,9 +30619,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30307,6 +30637,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30436,9 +30769,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30505,7 +30835,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30607,13 +30937,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30634,6 +30964,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30721,6 +31054,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30733,9 +31069,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30754,6 +31096,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30769,9 +31114,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30820,10 +31162,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30859,6 +31204,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30898,16 +31246,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30919,6 +31267,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30934,9 +31285,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31090,9 +31438,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31219,9 +31564,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31534,7 +31876,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31666,6 +32008,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31720,6 +32065,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31738,21 +32086,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31762,12 +32119,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,6 +32161,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31810,12 +32182,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31825,6 +32245,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32146,9 +32569,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32536,7 +32956,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32545,6 +32965,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32554,18 +32977,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32704,7 +33121,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32878,9 +33295,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32920,6 +33334,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32932,6 +33349,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32944,9 +33364,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32971,6 +33388,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33013,7 +33433,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33106,6 +33526,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33208,9 +33631,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33517,9 +33964,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33583,9 +34027,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33919,6 +34360,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33961,6 +34405,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34303,6 +34750,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34333,6 +34783,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34411,9 +34882,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34582,9 +35050,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34609,6 +35074,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34648,6 +35116,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34702,6 +35173,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34714,6 +35188,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34957,6 +35440,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35029,6 +35515,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35203,6 +35692,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35377,9 +35869,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35419,12 +35908,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35434,9 +35917,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35470,7 +35950,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35638,6 +36118,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35713,9 +36196,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35731,9 +36211,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36103,7 +36580,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36154,7 +36631,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36238,9 +36715,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36364,6 +36838,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36403,9 +36880,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36445,9 +36919,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36667,6 +37147,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36688,6 +37171,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36727,6 +37213,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36955,9 +37444,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37207,9 +37693,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37351,9 +37834,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37369,9 +37849,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37579,9 +38056,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37693,6 +38167,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37708,15 +38185,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37783,6 +38254,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38302,6 +38779,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38323,6 +38803,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38758,6 +39241,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39289,6 +39775,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39439,6 +39937,9 @@ msgstr[2] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39664,6 +40165,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39706,6 +40210,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39724,6 +40231,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39733,6 +40246,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39745,6 +40261,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39757,6 +40276,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39781,9 +40303,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39964,127 +40495,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40192,10 +40723,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40504,7 +41035,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40606,6 +41143,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40639,6 +41179,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40687,6 +41230,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40732,6 +41278,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40867,6 +41416,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40960,6 +41512,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40999,7 +41554,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41014,6 +41569,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41395,7 +41953,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41404,9 +41962,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41473,6 +42028,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41605,6 +42163,12 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "approved by: "
msgstr ""
@@ -41689,6 +42253,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42064,6 +42631,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42091,12 +42661,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42226,6 +42790,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42274,6 +42841,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42391,6 +42964,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42487,9 +43063,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42532,9 +43105,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42658,7 +43228,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42706,6 +43276,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42760,6 +43333,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42805,6 +43381,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42814,9 +43393,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42853,9 +43429,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43141,9 +43714,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43324,9 +43894,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index bd16729ea98..c100c167bbd 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index 513a87dd770..0e66f44665a 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index c2a7fae7a62..ac7ab4845ba 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -645,6 +670,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1875,7 +1891,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 0b15beddbea..119c3833bc0 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -645,6 +670,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1875,7 +1891,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 0d340987b24..6efb1cc76b9 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index d02eafd53c6..d3847f8a6ec 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr "%{level_name} non è consentito in un gruppo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Confermi di voler resettare il token di controllo di stato?"
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Elimina branch mergiate"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Eliminare le branch mergiate è un'operazione irreversibile. Sicuro di voler procedere?"
@@ -5958,9 +5990,6 @@ msgstr "Nuova branch"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Per evitare perdita di dati considera di mergiare questa branch prima di eliminarla."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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."
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "per"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Cherry-pick questa richiesta di merge"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr "Messaggio di commit"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Rilasci"
msgid "Deploy Keys"
msgstr "Chiavi di Deploy (rilascio)"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Feb"
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Questa impostazione è stata applicata a %{ancestor_group}. Puoi eseguir
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "Housekeeping iniziato con successo"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr "Pipeline"
msgid "Pipelines charts"
msgstr "Grafici pipeline"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Inserisci il tuo %{confirmationValue} per confermare:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Seleziona formato d'archivio"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Hai raggiunto il tuo limite di progetto"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Il tuo nome"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 8738f0e82b4..ab14b7fb064 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: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} ã¾ã§"
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] "%d 件ã®ã‚¹ã‚­ãƒ£ãƒ³ã•ã‚ŒãŸ URL"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d 人ã®æ‰¿èªè€…"
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} 件ã®ã‚ªãƒ¼ãƒ—ンã—ã¦ã„るマージリクエスト"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}マスク:%{code_close} ジョブログã§éžè¡¨ç¤ºã«ã—ã¾ã™ã€‚マスキングã®è¦ä»¶ã‚’満ãŸã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -549,6 +571,9 @@ msgstr "%{group_name} アクティビティー"
msgid "%{group_name} group members"
msgstr "%{group_name} グループã®ãƒ¡ãƒ³ãƒãƒ¼"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} ã¯ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¾ã™ã€‚ %{group_name} ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã‚‹æ–°ã—ã„GitLabアカウントを作æˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -645,6 +670,9 @@ msgstr "%{level_name} 㯠%{group_level_name} グループã«å«ã‚られã¾ã›ã
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。フォークã—ãŸã‚½ãƒ¼ã‚¹ãƒ—ロジェクトã¯ã‚ˆã‚Šå¯è¦–性ãŒä½Žã„ã‹ã‚‰ã§ã™ã€‚"
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "ロールã«ã¤ã„ã¦%{link_start}ã‚‚ã£ã¨è©³ã—ã%{link_end}。"
@@ -654,6 +682,9 @@ msgstr "タイトルã‹ã‚‰ %{link_start} %{draft_snippet} ã®ãƒ—レフィックã
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr "タイトルã®å…ˆé ­ã« %{link_start} %{draft_snippet} %{link_end} を書ã„ã¦ã€ä½œæ¥­ä¸­ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒæº–å‚™ãŒã§ãã‚‹ã¾ã§ãƒžãƒ¼ã‚¸ã•ã‚Œãªã„よã†ã«ã—ã¾ã™ã€‚"
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}GitLab Inc.ã¯ã©ã®ã‚ˆã†ãªæƒ…報をåŽé›†ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ%{link_end}"
@@ -763,9 +794,6 @@ msgstr "%{placeholder} 㯠有効ãªãƒ†ãƒ¼ãƒžã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr "%{project_path} ã¯ã€GitLab プロファイルã«READMEを追加ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚開始ã™ã‚‹ã«ã¯ã€ãƒ‘ブリックプロジェクトを作æˆã—ã€README ãŒå«ã¾ã‚ŒãŸçŠ¶æ…‹ã§ãƒªãƒã‚¸ãƒˆãƒªã‚’åˆæœŸåŒ–ã—ã¾ã™ã€‚ %{help_link_start}詳細ã¯ã“ã¡ã‚‰%{help_link_end}"
@@ -797,6 +825,9 @@ msgstr "残りã®å‚加者ã‹ã‚‰ %{rotation} ã‚’å†è¨ˆç®—ã—ã¾ã—ãŸã€‚ %{rotat
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 "残りã®å‚加者ã‹ã‚‰ %{rotation} ã‚’å†è¨ˆç®—ã—ã¾ã—ãŸã€‚ %{rotation}ã®æ–°ã—ã„設定を確èªã—ã¦ãã ã•ã„。 オンコールã®ã‚«ãƒãƒ¬ãƒƒã‚¸ã‚’確èªã™ã‚‹ãŸã‚ã«ã€ç¾åœ¨ã®ã‚ªãƒ³ã‚³ãƒ¼ãƒ«ã®å¯¾å¿œè€…ã«é€£çµ¡ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚"
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr "ä»–ã®ãƒ‡ãƒ¼ã‚¿ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã«ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れをæŒã£ã¦ã„る人ã¯èª°ã§ã‚‚ã‚ãªãŸã«ãªã‚Šã™ã¾ã—ã¦ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¹ã‚¿ãƒ†ã‚£ãƒƒã‚¯ã‚ªãƒ–ジェクトã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ã‚‚ã—ã‚‚æ¼æ´©ã—ãŸå ´åˆã€ %{reset_link_start} ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセット %{reset_link_end}ã™ã¹ãã§ã™ã€‚"
-
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã¯ç§˜å¯†ã«ã—ã¦ãŠã„ã¦ãã ã•ã„。ã“れをæŒã£ã¦ã„る人ã¯èª°ã§ã‚‚ã‚ãªãŸã¨åŒã˜ã‚ˆã†ã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã§ãã¾ã™ã€‚ã‚‚ã—æ¼æ´©ã—ãŸå ´åˆã€ %{link_reset_it}。"
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れをæŒã£ã¦ã„る人ã¯èª°ã§ã‚‚ã‚ãªãŸã®ã‚ˆã†ã«ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを読ã‚ã€ã‚ãªãŸã¨ã—ã¦RSSフィードやカレンダーã®ãƒ•ã‚£ãƒ¼ãƒ‰ã‚’発行ã§ãã¾ã™ã€‚æ¼æ´©ã—ãŸå ´åˆã¯ã€%{link_reset_it} ã™ã¹ãã§ã™ã€‚"
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "パーソナルアクセストークン"
@@ -1755,9 +1777,6 @@ msgstr "ã‚ãªãŸãŒãƒ¡ãƒ¼ãƒ«ã§æ–°ã—ã„イシューを作æˆã™ã‚‹ã¨ãã€ã‚
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 this token"
-msgstr "トークンをリセット"
-
msgid "AccessibilityReport|Learn more"
msgstr "詳細を表示"
@@ -1863,9 +1882,6 @@ msgstr "変更履歴を追加"
msgid "Add CONTRIBUTING"
msgstr "CONTRIBUTINGを追加"
-msgid "Add GitLab to Slack"
-msgstr "GitLabã‚’Slackã«è¿½åŠ ã™ã‚‹"
-
msgid "Add Jaeger URL"
msgstr "Jaeger URL を追加"
@@ -1875,8 +1891,8 @@ msgstr "Kubernetes クラスターを追加"
msgid "Add LICENSE"
msgstr "ライセンスã®è¿½åŠ "
-msgid "Add New Node"
-msgstr "æ–°ã—ã„ノードを追加"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "README を追加"
@@ -1890,6 +1906,9 @@ msgstr "%{type} を追加"
msgid "Add a GPG key"
msgstr "GPGキーを追加"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Jaeger URL を追加ã—ã¦ã€ã“ã®ãƒšãƒ¼ã‚¸ã‚’ Jaeger サーãƒãƒ¼ã¸ã®ãƒªãƒ³ã‚¯ã«ç½®ãæ›ãˆã¾ã™ã€‚ã¾ãš %{link_start_tag}Jaeger をインストール%{link_end_tag}ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -1956,6 +1975,9 @@ msgstr "Todoを追加"
msgid "Add an SSH key"
msgstr "SSH éµã‚’追加"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "既存ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追加"
@@ -2073,9 +2095,6 @@ msgstr "システムフックã®è¿½åŠ "
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "サインインページã«ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ マークダウンãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚"
-msgid "Add to Slack"
-msgstr "Slackã«è¿½åŠ "
-
msgid "Add to board"
msgstr "ボードã«è¿½åŠ "
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "統計ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr "(éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–)"
msgid "AdminUsers|(Internal)"
msgstr "(内部)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(承èªå¾…ã¡)"
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†è€…"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr "ã‚ãªãŸã§ã™ï¼"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "ログイン"
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "ユーザーã¯ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™"
@@ -2856,8 +2890,8 @@ 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 "ã‚ãªãŸã¯è‡ªèº«ã®ç®¡ç†è€…権é™ã‚’削除ã§ãã¾ã›ã‚“。"
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr ""
@@ -3417,23 +3451,14 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®ãƒ—ロジェクト㫠Git LFS を使用ã§ãã‚‹
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "フックãŠã‚ˆã³ã‚µãƒ¼ãƒ“スã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "システムフックã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "web フックãŠã‚ˆã³ã‚µãƒ¼ãƒ“スã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
-msgstr "ã“ã®ã‚»ã‚«ãƒ³ãƒ€ãƒªãƒŽãƒ¼ãƒ‰ãŒã‚ªãƒ–ジェクトストレージ上ã«ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を複製ã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™"
+msgid "Allow this secondary site to replicate content on Object Storage"
+msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
@@ -3543,9 +3568,6 @@ msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã«ä¸‹æ›¸ãを追加ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3693,18 +3715,15 @@ msgstr "ジョブã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching the latest pipeline."
msgstr "最新ã®ãƒ‘イプラインã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "リリースã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "An error occurred while fetching this tab."
msgstr "ã“ã®ã‚¿ãƒ–ã®ãƒ•ã‚§ãƒƒãƒä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while generating a username. Please try again."
-msgstr "ユーザーåã®ç”Ÿæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "%{branchId} ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "承èªè€…を追加"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "承èªè€…"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr "ターゲットブランãƒ"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr "ã“ã®ãƒ—ロジェクトã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–を解除ã—ã¦ã‚ˆã‚ã—ã„ã§
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr "ã“ã® ID を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "本当ã«SCIMトークンをリセットã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿæ–°ã—ã„トークンを更新ã™ã‚‹ã¾ã§SCIMプロビジョニングã¯æ©Ÿèƒ½ã—ãªããªã‚Šã¾ã™ã€‚"
-
msgid "Are you sure you want to reset the health check token?"
msgstr "本当ã«ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Average per day: %{average}"
msgstr "1æ—¥ã‚ãŸã‚Šã®å¹³å‡: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®åå‰ç©ºé–“を変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "以下ã«å…¬é–‹ã•ã‚Œã¦ã„る全グループを表示ã—ã¾ã™ã€‚"
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr "Bitbucket インãƒãƒ¼ãƒˆ"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr "マージã•ã‚ŒãŸãƒ–ランãƒã‚’削除"
msgid "Branches|Delete protected branch"
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}' ブランãƒã‚’削除ã—ãŸã‚‰å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“。よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "マージã•ã‚ŒãŸãƒ–ランãƒã‚’削除ã™ã‚‹ã¨å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“。よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -5828,9 +5856,6 @@ msgstr "æ–°è¦ãƒ–ランãƒ"
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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} ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "データã®æ¶ˆå¤±ã‚’é¿ã‘ã‚‹ãŸã‚ã€å‰Šé™¤ã™ã‚‹å‰ã«ã“ã®ãƒ–ランãƒã‚’マージã™ã‚‹ã“ã¨ã‚’オススメã—ã¾ã™ã€‚"
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 "ローカルã®å¤‰æ›´å†…容を破棄ã—ã¦ã€ã‚¢ãƒƒãƒ—ストリームã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ãƒ–ランãƒã‚’上書ãã™ã‚‹ã«ã¯ã€ã“ã“ã§ãれらを削除ã—ã€ä¸Šã®ã€Œä»Šã™ãæ›´æ–°ã€ã‚’クリックã—ã¦ãã ã•ã„。"
@@ -5906,9 +5922,6 @@ 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} を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
-
msgid "Branches|diverged from upstream"
msgstr "アップストリームã‹ã‚‰åˆ†å²"
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "デフォルトã§ã¯ã€ã™ã¹ã¦ã®ãƒ—ロジェクトã¨ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«é€šçŸ¥è¨­å®šã‚’使用ã—ã¾ã™ã€‚"
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者"
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "自動的ã«ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "ä¸æ­£åˆ©ç”¨ãƒ¬ãƒãƒ¼ãƒˆã¯ä½œæˆã§ãã¾ã›ã‚“。ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -6782,6 +6819,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "請求先ä½æ‰€"
@@ -6959,6 +6999,9 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ック"
msgid "Child"
msgstr "å­"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "å­ã‚¨ãƒ”ックã¯å­˜åœ¨ã—ã¾ã›ã‚“。"
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "クライアントèªè¨¼è¨¼æ˜Žæ›¸"
-
-msgid "Client authentication key"
-msgstr "クライアントèªè¨¼ã‚­ãƒ¼"
-
-msgid "Client authentication key password"
-msgstr "クライアントèªè¨¼ã‚­ãƒ¼ã®ãƒ‘スワード"
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} ã‚’é–‰ã˜ã‚‹ã€‚"
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "クラスター"
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr "コミット(コミットメッセージã®ç·¨é›†æ™‚)"
msgid "Commit Message"
msgstr "コミットメッセージ"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr "トレーシングã®è¨­å®š"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "既存ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’設定ã™ã‚‹"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "リãƒã‚¸ãƒˆãƒªã®ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã‚’設定ã—ã¾ã™ã€‚"
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "ユーザーãŒæ–°ã—ã„アカウントを作æˆã™ã‚‹æ–¹æ³•ã‚’設定ã—ã¾ã™ã€‚"
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "確èª"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr "アカウントã«ç´ã¥ãメールã®ç®¡ç†"
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,14 +9854,17 @@ msgstr "トリガーを除去ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Could not restore the group"
msgstr "グループをリストアã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "代ç†ãƒˆãƒ¼ã‚¯ãƒ³ %{token_name} を無効ã«ã§ãã¾ã›ã‚“。"
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ %{personal_access_token_name} を無効ã«ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "Could not revoke project access token %{project_access_token_name}."
-msgstr "プロジェクトアクセストークン %{project_access_token_name} を無効ã«ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
msgid "Could not save group ID"
msgstr "グループIDã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr "イテレーションã®ä½œæˆ"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr "自分ãŒä½œæˆ"
msgid "Created by:"
msgstr "作æˆè€…:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr "ターゲットサイトãŠã‚ˆã³ã‚¹ã‚­ãƒ£ãƒ³ä»•æ§˜ã§ä¸€èˆ¬çš„ã«ä½¿ç”¨
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr "デフォルトブランãƒã¨ä¿è­·ãƒ–ランãƒ"
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "デフォルト分類ラベル"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] "デプロイ"
msgid "Deploy Keys"
msgstr "デプロイキー"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr "デプロイã®é€²è¡ŒçŠ¶æ³ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 ãƒãƒƒãƒ‰ã‚’表示ã™ã‚‹ã«ã¯ã€ã”使用ã®ç’°å¢ƒãŒ%{linkStart}デプロイボードã®åŸºæº–%{linkEnd}ã¨ä¸€è‡´ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "デプロイ先..."
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "ã“ã®ãƒ‡ãƒ—ロイã¯APIを使用ã—ã¦ä½œæˆã•ã‚Œã¾ã—ãŸ"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "キャンセルã•ã‚Œã¾ã—ãŸã€‚"
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "無料トライアルを始ã‚ã‚‹"
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,8 +12776,8 @@ msgstr "コメントを編集"
msgid "Edit Deploy Key"
msgstr "デプロイキーã®ç·¨é›†"
-msgid "Edit Geo Node"
-msgstr "ジオノードを編集"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr "グループフックを編集"
@@ -12910,6 +13022,9 @@ msgstr "ã©ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ¡ãƒ¼ãƒ«ã«å¯¾å¿œã—ã¦ã„ã‚‹ã®ã‹æŠŠæ¡ã§ãã¾
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "プロジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚入力ミスãŒãªã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。"
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "ã“ã®æ“作ã®å®Ÿè¡Œã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ã“ã‚ŒãŒèª¤ã£ã¦ã„ã‚‹ã¨æ€ã‚れる場åˆã¯ã€ã‚¹ã‚¿ãƒƒãƒ•ãƒ¡ãƒ³ãƒãƒ¼ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "外部サービスを使用ã—ã¦ã€åˆ†é¡žåˆ¶å¾¡ã‚’有効ã«ã™ã‚‹ã€‚"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "メンテナンスモードを有効ã«ã™ã‚‹"
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr "DNSå†ãƒã‚¤ãƒ³ãƒ‰æ”»æ’ƒã«å¯¾ã™ã‚‹ä¿è­·ã‚’強化ã™ã‚‹"
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr "ã‚ãªãŸã® Bitbucket Server ã® URL ã¨ä»¥ä¸‹ã®å€‹äººã‚¢ã‚¯ã‚»ã‚¹ãƒˆã
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "ã‚ãªãŸã® Phabricator サーãƒãƒ¼ã®URLã¨ãƒ‘ーソナルアクセストークンを入力ã—ã¦ãã ã•ã„"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "マージリクエストã®URLを入力"
@@ -13529,6 +13650,9 @@ msgstr "環境ã®åœæ­¢"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr "ä¿è­·"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "エピック"
@@ -14340,9 +14467,6 @@ msgstr "ä¿è­·ãƒ–ランãƒã‚„ä¿è­·ã‚¿ã‚°ä¸Šã§å®Ÿè¡Œã•ã‚Œã¦ã„るパイプラ
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "外部分類èªè¨¼ãƒãƒªã‚·ãƒ¼"
-
msgid "External ID"
msgstr "外部ID"
@@ -14352,15 +14476,9 @@ msgstr "外部 URL"
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "外部èªè¨¼"
-
msgid "External authorization denied access to this project"
msgstr "ã“ã®ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’æ‹’å¦ã™ã‚‹å¤–部èªè¨¼"
-msgid "External authorization request timeout"
-msgstr "外部èªè¨¼å‡¦ç†ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ"
-
msgid "External storage URL"
msgstr "外部ストレージã®URL"
@@ -14376,6 +14494,54 @@ msgstr "分類ラベル"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "ラベルãŒåˆ†é¡žã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€`%{default_label}` ãŒæ—¢å®šã®ãƒ©ãƒ™ãƒ«ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "2月"
@@ -14991,12 +15147,6 @@ msgstr "フィルター"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‰ã˜ãŸ %{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr "%{gitlab_ci_yml} ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ".gitlab-ci.yml ã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "åˆæœŸè¨­å®šãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆã‚’生æˆã™ã‚‹"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "éµã‚’生æˆ"
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo ノード"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr "Geo設定"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失敗"
@@ -15609,12 +15774,6 @@ msgstr "次回ã®åŒæœŸäºˆå®šæ—¥æ™‚"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "ã¾ã åŒæœŸã—ã¦ã„ã¾ã›ã‚“。"
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "åŒæœŸã®ãƒšãƒ³ãƒ‡ã‚£ãƒ³ã‚°"
@@ -15663,16 +15825,19 @@ msgstr "å†ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
msgid "Geo|Remove"
msgstr "削除"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr "セカンダリー"
msgid "Get a free instance review"
msgstr "ç„¡æ–™ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãƒ¬ãƒ“ューã®å–å¾—"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr "GitLab for Slack"
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "GitLabメンãƒãƒ¼ã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹"
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr "親ã«ç§»å‹•"
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr "グループ %{group_name} ã¯å‰Šé™¤äºˆå®šã—ã¾ã—ãŸã€‚"
msgid "Group %{group_name} was successfully created."
msgstr "'%{group_name}' グループã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "グループ Git LFS ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹:"
@@ -16506,6 +16686,9 @@ msgstr "グループ SAML を有効ã«ã—ã¦ãƒ†ã‚¹ãƒˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™
msgid "Group URL"
msgstr "グループ URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "グループ Maintainer 㯠%{link} ã§ã‚°ãƒ«ãƒ¼ãƒ— Runner を登録ã§ãã¾ã™ã€‚"
-
msgid "Group members"
msgstr "グループã®ãƒ¡ãƒ³ãƒãƒ¼"
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr "グループ概è¦ã‚³ãƒ³ãƒ†ãƒ³ãƒ„"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr "グループã®ãƒ‘イプライン時間ãŒæ­£å¸¸ã«ãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr "グループã«ã¯åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¿…è¦ã§ã™"
@@ -16851,18 +17031,12 @@ msgstr "SAML シングル サインオンã®è¨­å®š"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "SCIM APIエンドãƒã‚¤ãƒ³ãƒˆã®URL"
-
msgid "GroupSAML|SCIM Token"
msgstr "SCIMトークン"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML トークン㮠SHA1 フィンガープリントã§è¨¼æ˜Žæ›¸ã«ç½²åã—ã¾ã™ã€‚ã“ã‚Œã¯ã‚µãƒ ãƒ—リントã¨å‘¼ã°ã‚Œã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚"
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "SCIMトークンã¯éžè¡¨ç¤ºã«ãªã£ã¦ã„ã¾ã™ã€‚トークンã®å€¤ã‚’ã‚‚ã†ä¸€åº¦ç¢ºèªã™ã‚‹ã«ã¯ã€æ¬¡ã®æ‰‹é †ã‚’実行ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr "妥当ãªSAMLレスãƒãƒ³ã‚¹"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "SCIMトークン"
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr "メール通知を無効ã«ã™ã‚‹"
msgid "GroupSettings|Disable group mentions"
msgstr "グループã®ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã‚’無効ã«ã™ã‚‹"
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr "æ–°ã—ã„ランナー登録トークンを生æˆã—ã¾ã—ãŸï¼"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "グループã®ãƒ‘イプライン設定ãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸ"
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr "ã“ã®è¨­å®šã¯ %{ancestor_group} ã«é©ç”¨ã•ã‚Œã¾ã™ã€‚設定を上æ›
msgid "GroupSettings|Transfer group"
msgstr "グループã®è»¢é€"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] "éžè¡¨ç¤º"
msgid "Hide values"
msgstr "éžè¡¨ç¤º"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ング"
msgid "Housekeeping successfully started"
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤ã€ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–。"
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "仕組ã¿"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr "%{terms_link} ã«åŒæ„ã™ã‚‹"
msgid "I forgot my password"
msgstr "パスワードを忘れã¾ã—ãŸ"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr "識別å­"
msgid "Identities"
msgstr "ID"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "有効ã«è¨­å®šã—ãŸå ´åˆã€å¤–部サービスã‹ã‚‰ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒåˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’使用ã—ã¦åˆ¶å¾¡ã•ã‚Œã¾ã™ã€‚"
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr "インシデント管ç†åˆ¶é™"
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "内部URL(オプション)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr "読ã¿è¾¼ã¿ä¸­..."
msgid "Loading…"
msgstr "読ã¿è¾¼ã¿ä¸­â€¦"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "ローカライズ"
@@ -21230,6 +21440,9 @@ msgstr "ロック"
msgid "Lock %{issuableDisplayName}"
msgstr "%{issuableDisplayName} をロック"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr "メンãƒãƒ¼ã‚·ãƒƒãƒ—ã‚’LDAPåŒæœŸã«é™å®š"
@@ -21266,6 +21479,39 @@ msgstr "ロックã¯ã€ç‰¹å®šã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚„フォルダをロックã™ã‚‹æ©Ÿ
msgid "Locks the discussion."
msgstr " ディスカッションをロックã™ã‚‹."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "スマートカードã§ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹"
@@ -22040,6 +22286,12 @@ msgstr "マージリクエストã®ä¾å­˜é–¢ä¿‚"
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "ソースブランãƒã¸ã®ã‚³ãƒŸãƒƒãƒˆ"
@@ -22879,9 +23140,6 @@ msgstr "月"
msgid "More Information"
msgstr "詳細"
-msgid "More Slack commands"
-msgstr "ãã®ä»–ã®Slackコマンド"
-
msgid "More actions"
msgstr "ãã®ä»–ã®æ“作"
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "%{default_branch} ã‹ã‚‰%{number_commits_distance} コミット以上異ãªã£ã¦ã„ã¾ã™ã€‚"
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr "マイルストーンãªã—"
msgid "No milestones to show"
msgstr "表示ã™ã‚‹ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "ãã®ä»–ã«ã€ãã®åå‰ã¾ãŸã¯èª¬æ˜Žã®ãƒ©ãƒ™ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -23835,6 +24084,9 @@ msgstr "ãã®åå‰ã¾ãŸã¯ãã®èª¬æ˜Žã‚’ã‚‚ã£ãŸã€å„ªå…ˆãƒ©ãƒ™ãƒ«ã¯ã‚ã‚Š
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,8 +24153,8 @@ msgstr "脆弱性ã¯ç™ºè¦‹ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
-msgstr "ウェブフックãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚上記ã®ãƒ•ã‚©ãƒ¼ãƒ ã«ã‚¦ã‚§ãƒ–フックを追加ã—ã¦ãã ã•ã„。"
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -24804,8 +25056,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "アウトãƒã‚¦ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,8 +25852,8 @@ msgstr "権é™"
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
-msgstr "パーミッションã€LFSã€2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
@@ -25846,9 +26119,6 @@ msgstr "パイプライン"
msgid "Pipelines charts"
msgstr "パイプラインãƒãƒ£ãƒ¼ãƒˆ"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr "マージリクエストã®ãƒ‘イプラインãŒæ§‹æˆã•ã‚Œã¾ã—ãŸã€‚デタッãƒã•ã‚ŒãŸãƒ‘イプラインã¯ã€ãƒžãƒ¼ã‚¸çµæžœã«å¯¾ã—ã¦ã§ã¯ãªãã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã§å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯ã€ãƒžãƒ¼ã‚¸çµæžœã®ãƒ‘イプラインã®æ–‡æ›¸ã‚’ã”覧ãã ã•ã„。"
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "%{project_name} ã®ãƒ‘イプライン設定を正常ã«æ›´æ–°ã—ã¾ã—ãŸã€‚"
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "ä¿¡é ¼ã®ã‚るビルド"
@@ -25873,8 +26146,8 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
-msgstr "å­ãƒ‘イプライン"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
msgid "Pipelines|Clear runner caches"
msgstr ""
@@ -26038,11 +26311,29 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
-msgstr "親"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr ""
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr "プラン:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26239,6 +26533,12 @@ msgstr "ã™ã¹ã¦ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚¸ãƒ§ãƒ–を実行"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "コメントã™ã‚‹ã«ã¯ %{link_to_register} ã¾ãŸã¯ %{link_to_sign_in} ã‚’ã—ã¦ãã ã•ã„"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "返信ã™ã‚‹ã«ã¯ %{startTagRegister}登録%{endRegisterTag} ã¾ãŸã¯ %{startTagSignIn}サインイン%{endSignInTag} ã—ã¦ãã ã•ã„"
@@ -26593,6 +26893,9 @@ msgstr "時間設定"
msgid "Preferences|Use relative times"
msgstr "相対時間を使用"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚¯ãƒ­ãƒƒãƒ‘ー"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "BIO"
@@ -26842,9 +27148,6 @@ msgstr "国ã€éƒ½é“府県"
msgid "Profiles|Clear status"
msgstr "ステータスをクリア"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "次ã®ã‚µãƒ¼ãƒ“スã®ä¸­ã‹ã‚‰ä¸€ã¤ã‚’é¸ã‚“ã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã‚’開始ã—ã¦ãã ã•ã„"
-
msgid "Profiles|Commit email"
msgstr "コミットメール"
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "æ–°ã—ã„プロフィール画åƒã‚’設定ã™ã‚‹"
@@ -27067,9 +27373,6 @@ msgstr "2è¦ç´ èªè¨¼"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "確èªã®ãŸã‚ %{confirmationValue} を入力ã—ã¦ãã ã•ã„:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "典型的ã«ã¯ \"ssh-ed25519 …\"ã¾ãŸã¯ \"ssh-rsa …\"ã§å§‹ã¾ã‚Šã¾ã™"
-
msgid "Profiles|Update profile settings"
msgstr "プロファイル設定を更新"
@@ -27592,11 +27895,14 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "マージã®æ–¹æ³•ã€ãƒžãƒ¼ã‚¸ã‚ªãƒ—ションã€ãƒžãƒ¼ã‚¸ãƒã‚§ãƒƒã‚¯ãŠã‚ˆã³ãƒžãƒ¼ã‚¸æ案をé¸æŠžã—ã¾ã™ã€‚"
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
-msgstr "マージ方法ã€ãƒžãƒ¼ã‚¸ã‚ªãƒ—ションã€ãƒžãƒ¼ã‚¸ãƒã‚§ãƒƒã‚¯ãŠã‚ˆã³ãƒžãƒ¼ã‚¸æ案をé¸æŠžã—ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レートを設定ã—ã¾ã™ã€‚"
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -27718,6 +28030,9 @@ msgstr "マージリクエスト"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "マージæ案"
@@ -27844,9 +28159,6 @@ msgstr "ã“ã®è¨­å®šã¯ã‚µãƒ¼ãƒãƒ¼ãƒ¬ãƒ™ãƒ«ã§é©ç”¨ã•ã‚Œã¦ã„ã¾ã™ãŒã€ã“
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "ã“ã®è¨­å®šã¯ã€ç®¡ç†è€…ãŒä¸Šæ›¸ãã—ãªã„å ´åˆã€ã™ã¹ã¦ã®ãƒ—ロジェクトã«é©ç”¨ã•ã‚Œã¾ã™ã€‚"
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "公開デプロイキー (%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "公開パイプライン"
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "プロジェクトã®å…¬é–‹ç¯„囲を狭ã‚ã‚‹"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "ã“ã®ãƒ—ロジェクトã®å…¬é–‹ç¯„囲を狭ã‚ã¾ã™ã‹?"
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "リãƒã‚¸ãƒˆãƒªã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸"
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "è¦ä»¶ã® %{reference} ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸ"
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr "%{name} ã«ã‚ˆã£ã¦è§£æ±º"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr "IPアドレスを一度解決ã—ã¦ã€ãれを使ã£ã¦ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡ã—ã¾ã™"
-
msgid "Response"
msgstr "レスãƒãƒ³ã‚¹"
@@ -30123,7 +30445,7 @@ msgstr "å†é–‹"
msgid "Resync"
msgstr "å†åŒæœŸ"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,15 +30543,15 @@ msgstr "失効"
msgid "Revoked"
msgstr ""
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "代ç†ãƒˆãƒ¼ã‚¯ãƒ³ %{token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "パーソナルアクセストークン㮠%{personal_access_token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr "プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ %{project_access_token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
-
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr "ロードマップ"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "役割"
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr "説明"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr "SSL ã®æ¤œè¨¼:"
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr "検索"
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr "グループã®æ¤œç´¢"
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} 㨠%{secondProject}"
@@ -31738,9 +32153,6 @@ msgstr "アーカイブã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’é¸æŠž"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr "Slackãƒãƒ¼ãƒ ã¨ãƒªãƒ³ã‚¯ã™ã‚‹ GitLab ã®ãƒ—ロジェクトをé¸æŠžã—ã¾ã™"
-
msgid "Select Page"
msgstr "ページを変更"
@@ -32128,8 +32540,8 @@ msgstr "サービスデスク"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "サービス URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr "CI/CD を設定"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr "パイプライン実行時間をリセット"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "使用済ã¿ã®ãƒ‘イプライン実行時間をリセットã™ã‚‹"
-msgid "Sherlock Transactions"
-msgstr "シャーロックトランザクション"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr "ã™ã¹ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを表示"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr "アーカイブã—ãŸãƒ—ロジェクトを表示"
msgid "Show archived projects only"
msgstr "アーカイブã—ãŸãƒ—ロジェクトã®ã¿ã‚’表示"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "コマンドを表示"
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr "コメントã®ã¿è¡¨ç¤º"
-msgid "Show commit description"
-msgstr "コミットã®èª¬æ˜Žã‚’表示"
-
msgid "Show complete raw log"
msgstr "完全ãªç”Ÿãƒ­ã‚°ã‚’表示ã™ã‚‹"
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr "ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr "ログアウト&登録"
msgid "Sign up"
msgstr "サインアップ"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "登録ã¯æˆåŠŸã—ã¾ã—ãŸï¼ メールアドレスを確èªã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
@@ -32794,9 +33209,33 @@ msgstr "Slack アプリケーション"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "Slackçµ±åˆã§ã¯ã€Slackã®ãƒãƒ£ãƒƒãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‹ã‚‰ slash コマンドを介ã—㦠GitLab ã¨ã‚„ã‚Šã¨ã‚Šã§ãã¾ã™ã€‚"
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã—ã¦ãã ã•ã„。"
msgid "Something went wrong. Try again later."
msgstr "ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚ã¨ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
-msgid "Sorry, no epics matched your search"
-msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾ã›ã‚“"
-
msgid "Sorry, no projects matched your search"
msgstr "検索æ¡ä»¶ã«ä¸€è‡´ã™ã‚‹ãƒ—ロジェクトã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -33169,9 +33605,6 @@ msgstr "最後ã«å‚加ã—ãŸé †"
msgid "SortOptions|Last created"
msgstr "最新作æˆé †"
-msgid "SortOptions|Last updated"
-msgstr "最終更新日時"
-
msgid "SortOptions|Least popular"
msgstr "人気順"
@@ -33505,6 +33938,9 @@ msgstr "マージトレインを開始"
msgid "Start merge train when pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã‚’開始"
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "検索開始"
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "メッセージを有効ã«ã™ã‚‹"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr "購読中"
msgid "Subscribed to this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} を購読ã—ã¾ã—ãŸã€‚"
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} を購読ã—ã¾ã™ã€‚"
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr "試用終了日"
msgid "SubscriptionTable|Trial start date"
msgstr "試用開始日"
-msgid "SubscriptionTable|Upgrade"
-msgstr "アップグレード"
-
msgid "SubscriptionTable|Usage"
msgstr "使用方法"
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr "日曜日"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "サãƒãƒ¼ãƒˆ"
@@ -34543,6 +35018,9 @@ msgstr "ターゲットブランãƒ"
msgid "Target-Branch"
msgstr "ターゲットブランãƒ"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
msgid "Terms of Service and Privacy Policy"
msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr "テスト"
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "ã“ã® %{group_path} グループã§ã€ã‚ãªãŸã¯ã‚·ãƒ³ã‚°ãƒ«ã‚µã‚¤ãƒ³ã‚ªãƒ³ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã§ãã¾ã™ã€‚"
-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 ""
@@ -34991,12 +35472,6 @@ msgstr "Prometheusサーãƒãƒ¼ã¯ã€Œæ‚ªã„リクエストã€ã¨å¿œç­”ã—ã¾ã—ã
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "外部èªè¨¼ã‚µãƒ¼ãƒ“スã¨ã®é€šä¿¡ã«ç›¸äº’ TLS ãŒå¿…è¦ãªå ´åˆã«ä½¿ç”¨ã™ã‚‹ X509 証明書。空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€HTTPS 経由ã§ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ãã«ã‚µãƒ¼ãƒè¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãŒè¡Œã‚ã‚Œã¾ã™ã€‚"
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr "クライアントシークレットをéžå…¬é–‹ã«ã§ãる場所ã§ã‚¢ãƒ—リケーションを使用ã—ã¾ã™ã€‚ãƒã‚¤ãƒ†ã‚£ãƒ–モãƒã‚¤ãƒ«ã‚¢ãƒ—リã¨ã‚·ãƒ³ã‚°ãƒ«ãƒšãƒ¼ã‚¸ã‚¢ãƒ—リã¯éžå…¬é–‹ã¨ã¯ã¿ãªã—ã¾ã›ã‚“。"
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイムアウトã™ã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ã¯ã€clone/push を組ã¿åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。"
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr "親エピックã¯éžå…¬é–‹ã§ã€éžå…¬é–‹ã®ã‚¨ãƒ”ックã¨ã‚¤ã‚·ãƒ¥ãƒ¼ã ã‘ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™"
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "秘密éµã®å¾©å·ã«å¿…è¦ã¨ãªã‚‹ãƒ‘スフレーズ。ã“ã‚Œã¯ã‚ªãƒ—ションã§ã€å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "クライアント証明書ãŒæä¾›ã•ã‚Œã‚‹ã¨ãã«ä½¿ç”¨ã™ã‚‹ç§˜å¯†éµã€‚ã“ã®å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr "ユーザーã®ãƒ‘イプライン時間ã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒ
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "ã“ã® %{issuableDisplayName} ã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚プロジェクトメンãƒãƒ¼ ã ã‘ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚"
@@ -35934,6 +36400,9 @@ msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã¯%{strong_open}検証ã•ã‚Œã¦ã„ãªã„%{strong_clos
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr "ã“ã®å†…容ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ç†ç”±ã¯ %{reason} ã§ã™ã€‚代ã‚ã‚Šã« %{options} ãŒä½¿ç”¨ã§ãã¾ã™ã€‚"
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr "ã“ã®ã‚¨ãƒ”ックã«ã¯ã€æ—¢ã«æœ€å¤§æ•°ã®å­ã‚¨ãƒ”ックãŒã‚ã‚Šã¾
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "ã“ã®ã‚¨ãƒ”ックã¯å­˜åœ¨ã—ãªã„ã‹ã€ã‚ãªãŸã«å分ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr "プロジェクト"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ãŠã‚Šã€ã‚³ãƒ¡ãƒ³ãƒˆ
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "ã“ã®è¨­å®šã¯ã€å„プロジェクトã§ä¸Šæ›¸ãã§ãã¾ã™ã€‚"
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "ã“ã®ã‚µãƒ–スクリプションã¯"
@@ -36525,9 +37006,6 @@ msgstr "ç›´å‰ã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ãƒžãƒ¼ã‚¸ã¾ã§ã®æ™‚é–“"
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "外部サービスã‹ã‚‰ã®å¿œç­”時間(秒å˜ä½ï¼‰ã‚’設定ã—ã¾ã™ã€‚設定時間内ã«å¿œç­”ãŒç„¡ã„å ´åˆã€ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã™ã€‚"
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr "ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€æ–°ã—ã„DNSレコード
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "SSH キーを追加ã™ã‚‹ã«ã¯ã€%{generate_link_start}キーを生æˆã™ã‚‹%{link_end} ã¾ãŸã¯%{existing_link_start}既存ã®ã‚­ãƒ¼ã‚’使用ã™ã‚‹%{link_end}ã®ã©ã¡ã‚‰ã‹ãŒå¿…è¦ã§ã™ã€‚"
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "エントリーを手動ã§è¿½åŠ ã™ã‚‹ã«ã¯ã€ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã®ã‚¢ãƒ—リケーションã«æ¬¡ã®è©³ç´°ã‚’入力ã—ã¦ãã ã•ã„"
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ä¸Šã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
-
msgid "To-Do List"
msgstr "To-Do リスト"
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr "トリガーã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Triggerer"
msgstr "トリガー"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "トレーシングã§ã‚¢ãƒ—リケーションをトラブルシューティングãŠã‚ˆã³ç›£è¦–ã™ã‚‹"
@@ -37866,6 +38335,9 @@ msgstr "æ›´æ–°ã—ã¾ã—ãŸ"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "%{updated_by} ã«ã‚ˆã£ã¦%{updated_at} ã«æ›´æ–°"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "CSVファイルã®ã‚¢ãƒƒãƒ—ロード"
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "文書ã®è¡¨ç¤º"
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr "変更後ファイルを表示 @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "識別å­"
@@ -39291,6 +39796,9 @@ msgstr "イメージ"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "リンク"
@@ -39303,6 +39811,9 @@ msgstr "åå‰ç©ºé–“"
msgid "Vulnerability|Project"
msgstr "プロジェクト"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr "スキャナープロãƒã‚¤ãƒ€ãƒ¼"
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,6 +40045,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr ""
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "コメント"
@@ -39564,6 +40129,9 @@ msgstr "パイプラインイベント"
msgid "Webhooks|Push events"
msgstr "プッシュイベント"
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr ""
@@ -39594,55 +40162,10 @@ msgstr "トリガー"
msgid "Webhooks|URL"
msgstr "URL"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when the job status changes"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr ""
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr ""
-
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,11 +40273,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "URL を空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクト間ã®æ©Ÿèƒ½ã‚’無効ã«ã—ãŸã‚Šã€å¤–部èªè¨¼ãƒã‚§ãƒƒã‚¯ã‚’実行ã—ãŸã‚Šã›ãšã«åˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40060,7 +40583,13 @@ msgstr "作業中(オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦ï¼‰"
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} プロジェクトã¨ã®ãƒ•ã‚©ãƒ¼ã‚¯ã®é–¢ä¿‚を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "ã“ã®æ“作を実行ã™ã‚‹æ¨©é™ã‚’ã‚‚ã£ã¦ã„ã¾ã›ã‚“。"
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr "%{lint_link_start}CI Lint%{lint_link_end}㧠%{gitlab_ci_yml} をテスã
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "以下ã®æ‰‹é †ã«ãã£ã¦ã€ã‚ãªãŸã®ã‚³ãƒ³ãƒ”ューター上ã®æ—¢å­˜ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロードã§ãã¾ã™ã€‚"
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr "ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®å‚加をリクエストã™ã‚‹ã“ã¨ã§ã€
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "ã‚ãªãŸã¯ã“ã® %{namespaceType} を離れる許å¯ã‚’å¾—ã¦ã„ã¾ã›ã‚“。"
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "Web ターミナルを実行ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。プロジェクト管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr "プロジェクト数ã®ä¸Šé™ã«é”ã—ã¦ã„ã¾ã™"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr "ã‚ãªãŸã¯ \"%{membershipable_human_name}\"%{source_type} を残ã—ã¾
msgid "You may close the milestone now."
msgstr "マイルストーンを終了ã§ãã¾ã™ã€‚"
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,8 +41499,8 @@ msgstr "åå‰"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
-msgstr "æ–°ã—ã„ SCIM トークン"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr ""
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr "æ–°ã—ã„パーソナルアクセストークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Your new project access token has been created."
-msgstr "æ–°ã—ã„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã«ã¯ãƒ‘スワードã¯å¿…è¦ã‚ã‚Šã¾ã›ã‚“。パスワードやãã®ä»–ã®å€‹äººæƒ…報をè¦æ±‚ã•ã‚ŒãŸå ´åˆã¯ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ä¸æ­£åˆ©ç”¨ã‚’報告ã—ã¦ãã ã•ã„。"
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "サブスクリプションã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸï¼"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr "マージリクエストã®æ‰¿èªè€…ã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™"
msgid "any-approver for the project already exists"
msgstr "プロジェクトã®æ‰¿èªè€…ã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™"
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr "個人用プロジェクトã«ã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚¿ã‚°ãŒã‚ã‚‹
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr "コミット済ã¿"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr "失敗ã—ã¾ã—ãŸ"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr "関連付ã‘られãŸæ¤œå‡ºçµæžœã‚’破棄ã§ãã¾ã›ã‚“ã§ã—ãŸ(id =%{finding_id}): %{message}"
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr "グループ"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ç¾åœ¨ã€ãƒ—ロジェクトレベルã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。"
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "%{path_lock_user_name} ã«ã‚ˆã£ã¦ %{created_at} ã«ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "log in"
-msgstr "ログイン"
-
msgid "manual"
msgstr "マニュアル"
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "ブランãƒã‚’復元ã™ã‚‹ã‹ã€åˆ¥ã® %{missingBranchName} ブランãƒã‚’使用ã—ã¦ãã ã•ã„"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,8 +42746,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’使用ã—ã¦ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -42286,6 +42849,9 @@ msgstr "Web IDE ã§é–‹ã"
msgid "mrWidget|Plain diff"
msgstr "テキスト差分"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "自動マージã®æº–å‚™ãŒã§ãã¾ã—ãŸã€‚ã“ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’マージã™ã‚‹ã«ã¯ã€ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã¸ã®æ›¸ãè¾¼ã¿æ¨©é™ã‚’æŒã¤äººã«ä¾é ¼ã—ã¾ã™"
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã—ãŸ"
@@ -42340,9 +42909,6 @@ msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "パスワード"
-msgid "mrWidget|branch does not exist."
-msgstr "ブランãƒãŒå­˜åœ¨ã—ã¾ã›ã‚“。"
-
msgid "mrWidget|into"
msgstr "→"
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr "リセットã—ã¾ã™ã€‚"
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr "ユーザーã®ã‚¢ãƒã‚¿ãƒ¼"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "ユーザーå"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index df58416397a..cd051bceb14 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index f650053d008..0916e772d41 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: 2022-01-06 17:25\n"
+"PO-Revision-Date: 2022-02-02 15:49\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 0e77ef6cc52..cf64ff655a3 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -82,7 +82,7 @@ msgstr[0] "%dê±´ì˜ ê²½ê³ "
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
+msgstr[0] "%dê±´ì˜ ê²½ê³ :"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] "%dê°œì˜ URL 검사ë¨"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%dëª…ì˜ ìŠ¹ì¸ìž"
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -440,7 +462,7 @@ msgid_plural "%{count} items"
msgstr[0] "%{count}ê°œì˜ í•­ëª©"
msgid "%{count} items per page"
-msgstr ""
+msgstr "페ì´ì§€ 당 %{count}ê°œì˜ ì•„ì´í…œ"
msgid "%{count} more"
msgstr "%{count} ê°œ ë”보기"
@@ -549,6 +571,9 @@ msgstr "%{group_name} 활ë™"
msgid "%{group_name} group members"
msgstr "%{group_name} 그룹 회ì›"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name}ì€ ê·¸ë£¹ 관리 ê³„ì •ì„ ì‚¬ìš© 합니다. %{group_name}를 관리 í•  새 GitLab ê³„ì •ì„ ë§Œë“¤ì–´ì•¼ 합니다."
@@ -645,6 +670,9 @@ msgstr "%{group_level_name} 그룹ì—는 %{level_name} ì´ í—ˆìš©ë˜ì§€ 않습ë‹
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "Forkí•œ ì›ë³¸ 프로ì íŠ¸ê°€ ë” ë‚®ì€ ê³µê°œ 수준으로 설정ë˜ì–´ 있으므로 %{level_name} ìˆ˜ì¤€ì´ í—ˆìš©ë˜ì§€ 않습니다."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "ì—­í• ì— ëŒ€í•´ %{link_start}ìžì„¸ížˆ 알아보기%{link_end}."
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -676,13 +707,13 @@ msgid "%{message} showing first %{warnings_displayed}"
msgstr "%{message} 첫 번째 %{warnings_displayed} 보기"
msgid "%{milestone} (expired)"
-msgstr ""
+msgstr "%{milestone} (만료ë¨)"
msgid "%{milliseconds}ms"
msgstr ""
msgid "%{model_name} not found"
-msgstr ""
+msgstr "%{model_name} ì°¾ì„ ìˆ˜ ì—†ìŒ"
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, ì´ ì´ìŠˆëŠ” ìžë™ìœ¼ë¡œ í´ë¡œì¦ˆ ë©ë‹ˆë‹¤."
@@ -731,10 +762,10 @@ msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commi
msgstr "%{default_branch} 로부터 %{number_commits_behind} commits behind, %{number_commits_ahead} commits ahead"
msgid "%{oneMonthAgo} - %{today}"
-msgstr ""
+msgstr "%{oneMonthAgo} - %{today}"
msgid "%{oneWeekAgo} - %{today}"
-msgstr ""
+msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr ""
@@ -758,14 +789,11 @@ msgid "%{placeholder} is not a valid color scheme"
msgstr ""
msgid "%{placeholder} is not a valid theme"
-msgstr ""
+msgstr "%{placeholder}(ì€)는 유효한 테마가 아닙니다."
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary}(%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -777,7 +805,7 @@ msgid_plural "%{releases} releases"
msgstr[0] "%{releases} 릴리즈"
msgid "%{remaining_approvals} left"
-msgstr ""
+msgstr "%{remaining_approvals} 남ìŒ"
msgid "%{reportType} %{status}"
msgstr "%{reportType} %{status}"
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -993,7 +1024,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}ì„ ì‚¬ìš©í•˜ë©´ 그룹 ë˜ëŠ” 프로ì íŠ¸ì˜ ì´ë²¤íŠ¸ì— 대한 ì‘답으로 웹 애플리케ì´ì…˜ì— ì•Œë¦¼ì„ ë³´ë‚¼ 수 있습니다. Webhook보다 %{integrations_link_start}통합%{link_end}ì„ ì‚¬ìš©í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
msgid "%{widget} options"
-msgstr ""
+msgstr "%{widget} 옵션"
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 "%{code_tag_start}v*%{code_tag_end}나, %{code_tag_start}*-릴리스%{code_tag_end}ê°™ì€ %{wildcards_link_start}와ì¼ë“œì¹´ë“œ%{wildcards_link_end}는 지ì›ë©ë‹ˆë‹¤."
@@ -1048,13 +1079,13 @@ msgid "(+%{count}&nbsp;rules)"
msgstr "(+%{count}&nbsp;규칙)"
msgid "(Group Managed Account)"
-msgstr ""
+msgstr "(그룹 관리 계정)"
msgid "(No changes)"
msgstr "(변경사항 ì—†ìŒ)"
msgid "(UTC %{offset}) %{timezone}"
-msgstr ""
+msgstr "(UTC %{offset}) %{timezone}"
msgid "(check progress)"
msgstr "(진행 ìƒí™© 확ì¸)"
@@ -1085,13 +1116,13 @@ msgid_plural "(squashes %d commits)"
msgstr[0] ""
msgid "(this user)"
-msgstr ""
+msgstr "(ì´ ì‚¬ìš©ìž)"
msgid "(we need your current password to confirm your changes)"
msgstr ""
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* 지정하지 않으면 모든 ì‹œê°„ì€ UTC 기준입니다"
msgid "*Required"
msgstr "*필수"
@@ -1119,7 +1150,7 @@ msgid "+%{extra} more"
msgstr ""
msgid "+%{more_assignees_count}"
-msgstr ""
+msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
msgstr ""
@@ -1153,7 +1184,7 @@ msgid "- Not available to run jobs."
msgstr ""
msgid "- Select -"
-msgstr ""
+msgstr "- ì„ íƒ -"
msgid "- User"
msgid_plural "- Users"
@@ -1166,10 +1197,10 @@ msgid "- show less"
msgstr "-ëœ ë³´ê¸°"
msgid "."
-msgstr ""
+msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr ""
@@ -1203,7 +1234,7 @@ msgstr[0] "%dì¼ ë‚¨ìŒ"
msgid "1 day selected"
msgid_plural "%d days selected"
-msgstr[0] ""
+msgstr[0] "%dì¼ ì„ íƒë¨"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
@@ -1211,7 +1242,7 @@ msgstr[0] ""
msgid "1 follower"
msgid_plural "%{count} followers"
-msgstr[0] ""
+msgstr[0] "팔로워 %{count}명"
msgid "1 group"
msgid_plural "%d groups"
@@ -1223,11 +1254,11 @@ msgstr[0] "%d시간"
msgid "1 issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
+msgstr[0] "%dê°œ ì´ìŠˆ ì„ íƒë¨"
msgid "1 merge request selected"
msgid_plural "%d merge requests selected"
-msgstr[0] ""
+msgstr[0] "%dê°œì˜ ë¨¸ì§€ 리퀘스트가 ì„ íƒë¨"
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
@@ -1345,7 +1376,7 @@ msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still w
msgstr ""
msgid "A Gitpod configured Webapplication in Spring and Java"
-msgstr ""
+msgstr "Spring ë° Java 웹애플리케ì´ì…˜ì—ì„œ Gitpodì´ êµ¬ì„±ë˜ì—ˆìŒ"
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -1378,7 +1409,7 @@ msgid "A deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
msgid "A different reason"
-msgstr ""
+msgstr "다른 ì´ìœ "
msgid "A file has been changed."
msgstr "파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -1441,25 +1472,25 @@ msgid "A project containing issues for each audit inquiry in the HIPAA Audit Pro
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 ""
+msgstr "프로ì íŠ¸ì˜ 저장소 ì´ë¦„ì€ URL(브ë¼ìš°ì €ë¥¼ 통해 프로ì íŠ¸ì— 액세스하는 ë° ì‚¬ìš©í•˜ëŠ” ì´ë¦„)ê³¼ GitLabì´ ì„¤ì¹˜ëœ íŒŒì¼ ë””ìŠ¤í¬ì˜ 위치를 ì •ì˜í•©ë‹ˆë‹¤. %{link_start}ë” ì•Œì•„ë³´ê¸°%{link_end}"
msgid "A quarterly reconciliation is due on %{date}"
msgstr ""
msgid "A ready-to-go template for use with Android apps"
-msgstr ""
+msgstr "안드로ì´ë“œ ì•±ì— ë°”ë¡œ 사용할 수 있는 템플릿입니다"
msgid "A ready-to-go template for use with iOS Swift apps"
-msgstr ""
+msgstr "iOS 스위프트 ì•±ì— ë°”ë¡œ 사용할 수 있는 템플릿입니다"
msgid "A rebase is already in progress."
-msgstr ""
+msgstr "리베ì´ìŠ¤ëŠ” ì´ë¯¸ 진행 중입니다."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "ë‹¤ìŒ IP 주소ì—ì„œ ê³„ì •ì— ë¡œê·¸ì¸í–ˆìŠµë‹ˆë‹¤ : %{ip}"
msgid "A title is required"
-msgstr ""
+msgstr "ì œëª©ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "A user with write access to the source branch selected this option"
msgstr "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì…˜ì„ ì„ íƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -1471,13 +1502,13 @@ msgid "API"
msgstr "API"
msgid "API Fuzzing"
-msgstr ""
+msgstr "API í¼ì§•"
msgid "API Fuzzing Configuration"
-msgstr ""
+msgstr "API í¼ì§• 설정"
msgid "API Help"
-msgstr ""
+msgstr "API ë„움ë§"
msgid "API Token"
msgstr "API 토í°"
@@ -1495,16 +1526,16 @@ msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
msgstr ""
msgid "APIFuzzing|API Fuzzing Configuration"
-msgstr ""
+msgstr "API í¼ì§• 설정"
msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
-msgstr ""
+msgstr "방법 ì„ íƒ"
msgid "APIFuzzing|Choose a profile"
-msgstr ""
+msgstr "프로필 ì„ íƒ"
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1513,7 +1544,7 @@ msgid "APIFuzzing|Customize your project's API fuzzing configuration options and
msgstr ""
msgid "APIFuzzing|Enable authentication"
-msgstr ""
+msgstr "ì¸ì¦ 활성화"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
msgstr ""
@@ -1540,7 +1571,7 @@ msgid "APIFuzzing|Password for basic authentication"
msgstr "기본 ì¸ì¦ì„ 위한 비밀번호"
msgid "APIFuzzing|Predefined profiles"
-msgstr ""
+msgstr "사전 ì •ì˜ëœ 프로필"
msgid "APIFuzzing|Scan mode"
msgstr "모드 스캔"
@@ -1549,13 +1580,13 @@ msgid "APIFuzzing|Scan profile"
msgstr "프로필 스캔"
msgid "APIFuzzing|Show code snippet for the profile"
-msgstr ""
+msgstr "í”„ë¡œí•„ì— ëŒ€í•œ 코드 스니펫 표시"
msgid "APIFuzzing|Target URL"
msgstr "타겟 URL"
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr ""
+msgstr "ìŠ¤ìº”ì„ ìˆ˜í–‰í•˜ëŠ” 세 가지 ë°©ë²•ì´ ìžˆìŠµë‹ˆë‹¤."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr "다른 ë°ì´í„°ì— 액세스하는 ë° ì‚¬ìš©í•  수 없습니다."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°"
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
@@ -1863,9 +1882,6 @@ msgstr "ë³€ê²½ëœ ë¡œê·¸ 추가"
msgid "Add CONTRIBUTING"
msgstr "컨트리뷰팅 추가"
-msgid "Add GitLab to Slack"
-msgstr "ìŠ¬ëž™ì— GitLab 추가"
-
msgid "Add Jaeger URL"
msgstr "Jaeger URL 추가"
@@ -1875,8 +1891,8 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
msgid "Add LICENSE"
msgstr "LICENSE 추가"
-msgid "Add New Node"
-msgstr "새 노드 추가"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "README 추가"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "GPG 키 추가"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "ì´ íŽ˜ì´ì§€ë¥¼ Jaeger ì„œë²„ì— ëŒ€í•œ ë§í¬ë¡œ 바꾸려면 Jaeger URLì„ ì¶”ê°€í•˜ì‹­ì‹œì˜¤. 먼저 %{link_start_tag}Jaeger를 설치%{link_end_tag}해야 합니다."
@@ -1930,13 +1949,13 @@ msgid "Add a link to Grafana"
msgstr ""
msgid "Add a new issue"
-msgstr ""
+msgstr "ì´ìŠˆ 추가"
msgid "Add a numbered list"
msgstr "번호 매기기 ëª©ë¡ ì¶”ê°€"
msgid "Add a related issue"
-msgstr ""
+msgstr "관련 ì´ìŠˆ 추가"
msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "SSH 키 추가"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "기존 ì´ìŠˆ 추가"
@@ -2047,7 +2069,7 @@ msgid "Add or subtract spent time"
msgstr ""
msgid "Add previously merged commits"
-msgstr ""
+msgstr "ì´ì „ì— ë¨¸ì§€ëœ ì»¤ë°‹ 추가"
msgid "Add project"
msgstr "프로ì íŠ¸ 추가"
@@ -2073,9 +2095,6 @@ msgstr "시스템 í›„í¬ ì¶”ê°€"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "ìŠ¬ëž™ì— ì¶”ê°€"
-
msgid "Add to board"
msgstr "ë³´ë“œì— ì¶”ê°€"
@@ -2152,7 +2171,7 @@ msgid "Added %{label_references} %{label_text}."
msgstr ""
msgid "Added a to do."
-msgstr ""
+msgstr "í• ì¼ì— 추가ë¨."
msgid "Added an issue to an epic."
msgstr "ì´ìŠˆë¥¼ ì—í”½ì— ì¶”ê°€í–ˆìŠµë‹ˆë‹¤."
@@ -2167,7 +2186,7 @@ msgid "Adding new applications is disabled in your GitLab instance. Please conta
msgstr "GitLab ì¸ìŠ¤í„´ìŠ¤ì— 새 애플리케ì´ì…˜ì„ 추가 í•  수 없습니다. ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
msgid "Additional Metadata"
-msgstr ""
+msgstr "추가 메타ë°ì´í„°"
msgid "Additional minutes"
msgstr "추가 시간(분)"
@@ -2179,16 +2198,16 @@ msgid "Additional text"
msgstr "추가 í…스트"
msgid "Additional text for the sign-in and Help page."
-msgstr ""
+msgstr "ë¡œê·¸ì¸ ë° ë„ì›€ë§ íŽ˜ì´ì§€ì— 대한 추가 í…스트"
msgid "Additional text to show on the Help page"
-msgstr ""
+msgstr "ë„ì›€ë§ íŽ˜ì´ì§€ì— 표시할 추가 í…스트"
msgid "Additional text to show on the sign-in page"
msgstr ""
msgid "Address"
-msgstr ""
+msgstr "주소"
msgid "Adds"
msgstr "추가하기"
@@ -2206,7 +2225,7 @@ msgid "Adds a to do."
msgstr ""
msgid "Adds an issue to an epic."
-msgstr ""
+msgstr "ì´ìŠˆë¥¼ ì—í”½ì— ì¶”ê°€í•©ë‹ˆë‹¤."
msgid "Adds email participant(s)."
msgstr ""
@@ -2218,25 +2237,25 @@ msgid "Adjust your filters/search criteria above. If you believe this may be an
msgstr ""
msgid "Admin"
-msgstr ""
+msgstr "관리ìž"
msgid "Admin Area"
msgstr "ê´€ë¦¬ìž ì˜ì—­"
msgid "Admin Mode"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ëª¨ë“œ"
msgid "Admin Note"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ë…¸íŠ¸"
msgid "Admin Notifications"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ì•Œë¦¼"
msgid "Admin Overview"
msgstr "ê´€ë¦¬ìž ê°œìš”"
msgid "Admin Section"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ì˜ì—­"
msgid "Admin mode already enabled"
msgstr ""
@@ -2272,7 +2291,7 @@ msgid "AdminArea|Bots"
msgstr "ë´‡"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "ì»´í¬ë„ŒíŠ¸"
msgid "AdminArea|Developer"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2428,7 +2453,7 @@ msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Ter
msgstr ""
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
-msgstr ""
+msgstr "그룹 ë˜ëŠ” ì¸ìŠ¤í„´ìŠ¤ 수준ì—ì„œ 지정ë˜ì§€ ì•Šì€ ê²½ìš° ê¸°ë³¸ê°’ì€ %{default_initial_branch_name}입니다. 기존 ì €ìž¥ì†Œì— ì˜í–¥ì„ 주지 않습니다."
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2515,10 +2540,10 @@ msgid "AdminStatistics|Snippets"
msgstr "스니펫"
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "(관리ìž)"
msgid "AdminUsers|(Banned)"
-msgstr ""
+msgstr "(차단ë¨)"
msgid "AdminUsers|(Blocked)"
msgstr "(차단ë¨)"
@@ -2529,6 +2554,9 @@ msgstr "(비활성화ë¨)"
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,14 +2593,14 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "관리ìž"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
msgstr "관리ìžë“¤"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "승ì¸"
msgid "AdminUsers|Approve user %{username}?"
msgstr ""
@@ -2614,7 +2642,7 @@ msgid "AdminUsers|Blocked"
msgstr "차단ë¨"
msgid "AdminUsers|Blocking user has the following effects:"
-msgstr ""
+msgstr "사용ìžë¥¼ 차단하면 다ìŒê³¼ ê°™ì€ íš¨ê³¼ê°€ 있습니다."
msgid "AdminUsers|Cannot sign in or access instance information"
msgstr ""
@@ -2644,7 +2672,7 @@ msgid "AdminUsers|Deactivated"
msgstr "비활성화ë¨"
msgid "AdminUsers|Deactivating a user has the following effects:"
-msgstr ""
+msgstr "사용ìžë¥¼ 비활성화하면 다ìŒê³¼ ê°™ì€ íš¨ê³¼ê°€ 있습니다."
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -2691,6 +2719,9 @@ msgstr "ì´ê²ƒì€ 나!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "로그ì¸"
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2776,7 +2810,7 @@ msgid "AdminUsers|To confirm, type %{username}"
msgstr "확ì¸ì„ 위해 %{username} ì„ ìž…ë ¥í•˜ì„¸ìš”"
msgid "AdminUsers|Unban user"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì°¨ë‹¨ í•´ì œ"
msgid "AdminUsers|Unban user %{username}?"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -2878,7 +2912,7 @@ msgid "AdminUsers|user cap"
msgstr ""
msgid "Administration"
-msgstr ""
+msgstr "관리"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
@@ -3313,7 +3347,7 @@ msgid "All (default)"
msgstr ""
msgid "All GitLab"
-msgstr ""
+msgstr "모든 GitLab"
msgid "All Members"
msgstr "모든 맵버"
@@ -3358,7 +3392,7 @@ msgid "All projects"
msgstr "모든 프로ì íŠ¸"
msgid "All projects selected"
-msgstr ""
+msgstr "모든 프로ì íŠ¸ê°€ ì„ íƒë¨"
msgid "All threads resolved"
msgstr "모든 스레드가 í•´ê²°ë¨"
@@ -3417,22 +3451,13 @@ msgstr "ì´ ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ë“¤ì´ Git LFS를 사용하ë„ë¡ í—ˆìš©"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "후í¬ì™€ 서비스ì—ì„œ 로컬 네트워í¬ì— 대한 ìš”ì²­ì„ í—ˆìš©í•©ë‹ˆë‹¤."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "하위 ê·¸ë£¹ì´ ìžì²´ 2단계 ì¸ì¦ ê·œì¹™ì„ ì„¤ì •í•˜ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3508,7 +3533,7 @@ msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
msgstr ""
msgid "Amazon Web Services Logo"
-msgstr ""
+msgstr "아마존 웹 서비스 로고"
msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr ""
@@ -3543,9 +3568,6 @@ msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr "ìž‘ì—…ì„ ê°€ì ¸ 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the latest pipeline."
msgstr "가장 ìµœê·¼ì˜ íŒŒì´í”„ ë¼ì¸ì„ 가져오는 ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr "ì •ë§ë¡œ 해당 í•­ëª©ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
msgid "Average per day: %{average}"
msgstr "하루 í‰ê· : %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "공개 ëœ ëª¨ë“  ê·¸ë£¹ì„ ì•„ëž˜ì—ì„œ ì°¾ì„ ìˆ˜ 있습니다."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name}ë‹˜ì€ í˜„ìž¬ %{plan_name} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니다."
-msgid "BillingPlans|Compare all plans"
-msgstr ""
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr "Bitbucketì—ì„œ 가져오기"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr "ë¨¸ì§€ëœ ë¸Œëžœì¹˜ 지우기"
msgid "Branches|Delete protected branch"
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}' 브랜치를 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮습니까?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "ë¨¸ì§€ëœ ë¸Œëžœì¹˜ë¥¼ 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮ì„까요?"
@@ -5828,9 +5856,6 @@ msgstr "새 브랜치"
msgid "Branches|No branches to show"
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 ""
@@ -5841,7 +5866,7 @@ msgid "Branches|Overview"
msgstr "개요"
msgid "Branches|Please type the following to confirm:"
-msgstr ""
+msgstr "다ìŒì— 있는 ë‚´ìš©ì„ ìž…ë ¥í•˜ì—¬ 확ì¸í•˜ì„¸ìš”."
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ëŠ” %{project_settings_link} ì—ì„œ 관리할 수 있습니다."
@@ -5879,15 +5904,6 @@ 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} ë¡œ 머지ë˜ì§€ 않았습니다."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "ë°ì´í„° ì†ì‹¤ì„ 방지 하려면 삭제하기 ì „ì— ì´ ë¸Œëžœì¹˜ë¥¼ 머지하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 "로컬 ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí•˜ê³  업스트림 버전으로 브랜치를 ë®ì–´ì“°ë ¤ë©´ 여기서 삭제하고 '지금 ì—…ë°ì´íŠ¸'를 ì„ íƒí•˜ì„¸ìš”."
@@ -5906,9 +5922,6 @@ 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} 브랜치를 삭제하려고 합니다."
-
msgid "Branches|diverged from upstream"
msgstr "업스트림ì—ì„œ 분기ë¨"
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "작성ìž"
@@ -6117,7 +6139,7 @@ msgid "CI configuration validated, including all configuration added with the %{
msgstr ""
msgid "CI settings"
-msgstr ""
+msgstr "CI 설정"
msgid "CI variables"
msgstr ""
@@ -6132,13 +6154,13 @@ msgid "CI/CD Analytics"
msgstr ""
msgid "CI/CD Settings"
-msgstr ""
+msgstr "CI/CD 설정"
msgid "CI/CD configuration"
msgstr "CI/CD 구성"
msgid "CI/CD configuration file"
-msgstr ""
+msgstr "CI/CD 설정 파ì¼"
msgid "CI/CD|No projects have been added to the scope"
msgstr ""
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6331,7 +6365,7 @@ msgid "Can't load mermaid module: %{err}"
msgstr ""
msgid "Can't scan the code?"
-msgstr ""
+msgstr "코드를 스캔할 수 없습니까?"
msgid "Can't update snippet: %{err}"
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "ìžë™ìœ¼ë¡œ 머지할 수 없습니다."
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6520,7 +6557,7 @@ msgid "Change made by"
msgstr ""
msgid "Change milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 변경"
msgid "Change path"
msgstr "경로 변경"
@@ -6771,7 +6808,7 @@ msgid "Checkout|%{selectedPlanText} plan"
msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 Cherry-pick"
msgid "Child"
msgstr "하위"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "하위 ì—í”½ì´ ì¡´ìž¬í•˜ì§€ 않습니다."
@@ -7254,19 +7297,10 @@ msgid "Click to expand text"
msgstr "í…스트를 í´ë¦­í•˜ì—¬ 확장하세요."
msgid "Click to hide"
-msgstr ""
+msgstr "숨기려면 í´ë¦­"
msgid "Click to reveal"
-msgstr ""
-
-msgid "Client authentication certificate"
-msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ì„œ"
-
-msgid "Client authentication key"
-msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ 키"
-
-msgid "Client authentication key password"
-msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ 키 비밀번호"
+msgstr "í´ë¦­í•˜ì—¬ 공개"
msgid "Client request timeout"
msgstr "í´ë¼ì´ì–¸íŠ¸ 요청 시간 초과"
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8398,7 +8459,7 @@ msgid "ClusterIntegration|meets the requirements"
msgstr "요구 ì‚¬í•­ì„ ì¶©ì¡±"
msgid "ClusterIntegration|sign up"
-msgstr ""
+msgstr "가입"
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr "커밋 메시지"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,9 +8894,12 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
-msgid "Component"
+msgid "ComplianceReport|No violations found"
msgstr ""
+msgid "Component"
+msgstr "ì»´í¬ë„ŒíŠ¸"
+
msgid "Confidence"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr "ì¶”ì  êµ¬ì„±"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "사용ìžê°€ 새로운 ê³„ì •ì„ ë§Œë“œëŠ” ë°©ë²•ì„ ì„¤ì •í•©ë‹ˆë‹¤."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "확ì¸"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9026,7 +9108,7 @@ msgid "Connected"
msgstr "ì—°ê²°ë¨"
msgid "Connecting"
-msgstr ""
+msgstr "연결 중"
msgid "Connecting to terminal sync service"
msgstr "í„°ë¯¸ë„ ë™ê¸°í™” ì„œë¹„ìŠ¤ì— ì—°ê²°ì¤‘"
@@ -9041,7 +9123,7 @@ msgid "Connection failure"
msgstr "연결 실패"
msgid "Connection timed out"
-msgstr ""
+msgstr "ì—°ê²° ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Connection timeout"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -9953,7 +10056,7 @@ msgid "Create new label"
msgstr "새 ë¼ë²¨ 만들기"
msgid "Create new project"
-msgstr ""
+msgstr "새 프로ì íŠ¸ 만들기"
msgid "Create or import your first project"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr "ë‚˜ì— ì˜í•´ ìƒì„±ë¨"
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11186,7 +11268,7 @@ msgid "Default artifacts expiration"
msgstr ""
msgid "Default branch"
-msgstr ""
+msgstr "기본 브랜치"
msgid "Default branch and protected branches"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "기본 분류 ë¼ë²¨"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11300,7 +11379,7 @@ msgid "DelayedJobs|delayed"
msgstr "지연ë¨"
msgid "Delete"
-msgstr ""
+msgstr "삭제 "
msgid "Delete %{issuableType}"
msgstr ""
@@ -11312,7 +11391,7 @@ msgid "Delete Comment"
msgstr "댓글 삭제"
msgid "Delete Key"
-msgstr ""
+msgstr "키 삭제"
msgid "Delete Selected"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] "ë°°í¬"
msgid "Deploy Keys"
msgstr "ë°°í¬ í‚¤"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,8 +12776,8 @@ msgstr "댓글 편집"
msgid "Edit Deploy Key"
msgstr "ë°°í¬ í‚¤ 편집"
-msgid "Edit Geo Node"
-msgstr "ì´ ë…¸ë“œ 편집"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr ""
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "외부 서비스로 분류 제어 사용"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13064,7 +13176,7 @@ msgid "Enable delayed project deletion by default for newly-created groups."
msgstr ""
msgid "Enable email notification"
-msgstr ""
+msgstr "ì´ë©”ì¼ ì•Œë¦¼ 활성화"
msgid "Enable error tracking"
msgstr "오류 ì¶”ì  ì‚¬ìš©"
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr "아래 Bitbucket Server URL ë° ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 입력하십ì
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13305,7 +13426,7 @@ msgstr ""
msgid "Environment"
msgid_plural "Environments"
-msgstr[0] ""
+msgstr[0] "환경"
msgid "Environment does not have deployments"
msgstr ""
@@ -13344,7 +13465,7 @@ msgid "Environments"
msgstr "환경"
msgid "Environments Dashboard"
-msgstr ""
+msgstr "환경 대시보드"
msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
msgstr ""
@@ -13356,10 +13477,10 @@ msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Deta
msgstr ""
msgid "EnvironmentsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "ëŒ€ì‹œë³´ë“œì— í”„ë¡œì íŠ¸ 추가"
msgid "EnvironmentsDashboard|Add projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 추가"
msgid "EnvironmentsDashboard|Environments Dashboard"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr "중지 환경"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,11 +13680,14 @@ msgstr ""
msgid "Environments|protected"
msgstr "보호ë¨"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "ì—픽"
msgid "Epic Boards"
-msgstr ""
+msgstr "ì—픽 ë³´ë“œ"
msgid "Epic cannot be found."
msgstr ""
@@ -13590,10 +13717,10 @@ msgid "Epics, issues, and merge requests"
msgstr ""
msgid "Epics|%{startDate} – %{dueDate}"
-msgstr ""
+msgstr "%{startDate} – %{dueDate}"
msgid "Epics|%{startDate} – No due date"
-msgstr ""
+msgstr "%{startDate} – 마ê°ì¼ ì—†ìŒ"
msgid "Epics|Add a new epic"
msgstr ""
@@ -13620,7 +13747,7 @@ msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
msgid "Epics|No start date – %{dueDate}"
-msgstr ""
+msgstr "ì‹œìž‘ì¼ ì—†ìŒ â€“ %{dueDate}"
msgid "Epics|Remove epic"
msgstr ""
@@ -13701,7 +13828,7 @@ msgid "Error creating label."
msgstr ""
msgid "Error creating new directory. Please try again."
-msgstr ""
+msgstr "새 디렉토리를 만드는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
msgid "Error creating new iteration"
msgstr ""
@@ -14097,7 +14224,7 @@ msgid "Every 6 months on the %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every day"
-msgstr ""
+msgstr "매ì¼"
msgid "Every day (at %{time})"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "외부 분류 ì •ì±… ì¸ì¦"
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr "외부 URL"
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "외부 ì¸ì¦"
-
msgid "External authorization denied access to this project"
msgstr "외부 ì¸ì¦ì´ ì´ í”„ë¡œì íŠ¸ì— 대한 액세스를 거부했습니다."
-msgid "External authorization request timeout"
-msgstr "외부 ì¸ì¦ 요청 시간 초과"
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14669,7 +14832,7 @@ msgid "Faster releases. Better code. Less pain."
msgstr ""
msgid "Favicon"
-msgstr ""
+msgstr "파비콘"
msgid "Favicon was successfully removed."
msgstr ""
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "2ì›”"
@@ -14965,7 +15121,7 @@ msgid "File upload error."
msgstr "íŒŒì¼ ì—…ë¡œë“œ 오류"
msgid "Filename"
-msgstr ""
+msgstr "파ì¼ëª…"
msgid "Files"
msgstr "파ì¼"
@@ -14991,12 +15147,6 @@ msgstr "í•„í„°"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15160,13 +15310,13 @@ msgid "Folder/%{name}"
msgstr ""
msgid "Follow"
-msgstr ""
+msgstr "팔로우"
msgid "Followed Users' Activity"
-msgstr ""
+msgstr "팔로우한 사용ìžì˜ 활ë™"
msgid "Followed users"
-msgstr ""
+msgstr "팔로우한 사용ìž"
msgid "Font Color"
msgstr "글꼴 색"
@@ -15321,11 +15471,14 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
msgid "Free"
-msgstr ""
+msgstr "무료"
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "키 ìƒì„±"
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo 노드"
-
msgid "Geo Replication"
msgstr "Geo 레플리케ì´ì…˜"
msgid "Geo Settings"
msgstr "Geo 설정"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr "Geo 사ì´íŠ¸"
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr "사ì´íŠ¸ 추가"
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr "GitLab Geo 알아보기"
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "실패"
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr "다시 다운로드"
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr "사ì´íŠ¸ì˜ ìƒíƒœê°€ %{timeAgo} ì „ ì—…ë°ì´íŠ¸ ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -15745,7 +15913,7 @@ msgid "Geo|Storage config"
msgstr ""
msgid "Geo|Synced"
-msgstr ""
+msgstr "ë™ê¸°í™” ë¨"
msgid "Geo|Synced at"
msgstr ""
@@ -15754,7 +15922,7 @@ msgid "Geo|Synchronization"
msgstr ""
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "ë™ê¸°í™” 실패 - %{error}"
msgid "Geo|Synchronization settings"
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15859,7 +16030,7 @@ msgid "Get started"
msgstr ""
msgid "Get started with GitLab"
-msgstr ""
+msgstr "GitLab 시작하기"
msgid "Get started with error tracking"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr "Gitpod URL"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16276,16 +16450,16 @@ msgid "Go to environments"
msgstr ""
msgid "Go to epic"
-msgstr ""
+msgstr "ì—픽으로 ì´ë™"
msgid "Go to file"
-msgstr ""
+msgstr "파ì¼ë¡œ ì´ë™"
msgid "Go to file permalink (while viewing a file)"
msgstr ""
msgid "Go to files"
-msgstr ""
+msgstr "파ì¼ë¡œ ì´ë™"
msgid "Go to find file"
msgstr ""
@@ -16297,7 +16471,7 @@ msgid "Go to issue boards"
msgstr ""
msgid "Go to issues"
-msgstr ""
+msgstr "ì´ìŠˆë¡œ ì´ë™"
msgid "Go to jobs"
msgstr ""
@@ -16312,7 +16486,7 @@ msgid "Go to metrics"
msgstr ""
msgid "Go to next page"
-msgstr ""
+msgstr "ë‹¤ìŒ íŽ˜ì´ì§€ë¡œ ì´ë™"
msgid "Go to page %{page}"
msgstr ""
@@ -16320,9 +16494,12 @@ msgstr ""
msgid "Go to parent"
msgstr ""
-msgid "Go to previous page"
+msgid "Go to parent directory"
msgstr ""
+msgid "Go to previous page"
+msgstr "ì´ì „ 페ì´ì§€ë¡œ ì´ë™"
+
msgid "Go to primary site"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "그룹 Git LFS ìƒíƒœ:"
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr "그룹 URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "그룹 관리ìžëŠ” grouo runners를 여기서 ë“±ë¡ í•  수 있습니다: %{link}"
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16690,7 +16870,7 @@ msgid "GroupRoadmap|Loading epics"
msgstr ""
msgid "GroupRoadmap|No start and end date"
-msgstr ""
+msgstr "ì‹œìž‘ì¼ ë° ë§ˆê°ì¼ ì—†ìŒ"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr "ì´ ì„¤ì •ì€ %{ancestor_group} ì— ì ìš©ë©ë‹ˆë‹¤. ì„¤ì •ì„ ìž¬ì •ì˜
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17236,7 +17404,7 @@ msgid "GroupsTree|Search by name"
msgstr "ì´ë¦„으로 검색"
msgid "Guideline"
-msgstr ""
+msgstr "ê°€ì´ë“œë¼ì¸"
msgid "HAR (HTTP Archive)"
msgstr ""
@@ -17281,7 +17449,7 @@ msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
-msgstr ""
+msgstr "í—¤ë”"
msgid "Heading 1"
msgstr ""
@@ -17426,6 +17594,33 @@ msgstr[0] "값 숨기기"
msgid "Hide values"
msgstr "값 숨기기"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17457,7 +17652,7 @@ msgid "Home page URL"
msgstr ""
msgid "Homepage"
-msgstr ""
+msgstr "홈페ì´ì§€"
msgid "Hook execution failed. Ensure the group has a project with commits."
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr "정리"
msgid "Housekeeping successfully started"
msgstr "정리가 성공ì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "정리, 내보내기, 경로, 전송, 삭제, 보관"
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
msgid "I forgot my password"
msgstr "비밀번호를 잊었습니다."
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17637,11 +17829,23 @@ msgid "Identifier"
msgstr "ì‹ë³„ìž"
msgid "Identifiers"
-msgstr ""
+msgstr "ì‹ë³„ìž"
msgid "Identities"
msgstr "ID"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -17745,7 +17946,7 @@ msgid "Ignored"
msgstr ""
msgid "Image URL"
-msgstr ""
+msgstr "ì´ë¯¸ì§€ URL"
msgid "Image details"
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18321,7 +18525,7 @@ msgid "InProductMarketing|This is email %{current_series} of %{total_series} in
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
-msgstr ""
+msgstr "Ticketmaster는 CI 구축 ì‹œê°„ì„ 15ë°° 단축했습니다."
msgid "InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}."
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18693,7 +18903,7 @@ msgid "Infrastructure as Code (IaC) Scanning"
msgstr ""
msgid "InfrastructureRegistry|Copy Terraform Command"
-msgstr ""
+msgstr "Terraform 커맨드 복사"
msgid "InfrastructureRegistry|Copy Terraform Setup Command"
msgstr ""
@@ -18711,7 +18921,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 ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -19300,7 +19510,7 @@ msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
msgid "InviteMembersModal|GitLab member or email address"
-msgstr ""
+msgstr "GitLab íšŒì› ë˜ëŠ” ì´ë©”ì¼ ì£¼ì†Œ"
msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
@@ -19321,7 +19531,7 @@ msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
msgid "InviteMembersModal|Select a group to invite"
-msgstr ""
+msgstr "초대할 그룹 ì„ íƒ"
msgid "InviteMembersModal|Select a role"
msgstr "ì—­í•  ì„ íƒ"
@@ -19537,7 +19747,7 @@ msgid "Issue was closed by %{name} %{reason}"
msgstr ""
msgid "Issue weight"
-msgstr ""
+msgstr "ì´ìŠˆ 가중치"
msgid "Issue(s) already assigned"
msgstr ""
@@ -20323,7 +20533,7 @@ msgid "K8s pod health"
msgstr ""
msgid "KEY"
-msgstr ""
+msgstr "키"
msgid "Keep"
msgstr ""
@@ -20353,7 +20563,7 @@ msgid "Key: %{key}"
msgstr ""
msgid "Keyboard shortcuts"
-msgstr ""
+msgstr "키보드 단축키"
msgid "KeyboardKey|Alt"
msgstr ""
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21144,7 +21357,7 @@ msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
msgid "Links"
-msgstr ""
+msgstr "ë§í¬"
msgid "List"
msgstr "목ë¡"
@@ -21177,7 +21390,7 @@ msgid "Live preview"
msgstr "실시간 미리보기"
msgid "Load more"
-msgstr ""
+msgstr "ë” ë³´ê¸°"
msgid "Load more users"
msgstr ""
@@ -21198,7 +21411,7 @@ msgid "Loading functions timed out. Please reload the page to try again."
msgstr ""
msgid "Loading more"
-msgstr ""
+msgstr "ë” ë¶ˆëŸ¬ì˜¤ê¸°"
msgid "Loading snippet"
msgstr ""
@@ -21212,14 +21425,11 @@ msgstr "불러오는 중…"
msgid "Loading…"
msgstr "로딩 중…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "현지화"
msgid "Location"
-msgstr ""
+msgstr "위치"
msgid "Location:"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr "잠금"
msgid "Lock %{issuableDisplayName}"
msgstr "%{issuableDisplayName} 잠금"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "스마트 카드로 로그ì¸"
@@ -21438,13 +21684,13 @@ msgid "March"
msgstr "3ì›”"
msgid "Mark as done"
-msgstr ""
+msgstr "완료로 표시"
msgid "Mark as draft"
msgstr ""
msgid "Mark as ready"
-msgstr ""
+msgstr "준비ë¨ìœ¼ë¡œ 표시"
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -21951,10 +22197,10 @@ msgid "Memory Usage"
msgstr ""
msgid "Menu"
-msgstr ""
+msgstr "메뉴"
msgid "Merge"
-msgstr ""
+msgstr "머지"
msgid "Merge Conflicts"
msgstr ""
@@ -22017,7 +22263,7 @@ msgid "Merge locally"
msgstr ""
msgid "Merge options"
-msgstr ""
+msgstr "머지 옵션"
msgid "Merge request"
msgstr "머지 리퀘스트(MR)"
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22613,10 +22874,10 @@ msgstr ""
msgid "Milestone"
msgid_plural "Milestones"
-msgstr[0] ""
+msgstr[0] "마ì¼ìŠ¤í†¤"
msgid "Milestone due date"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼"
msgid "Milestone lists not available with your current license"
msgstr "현재 ë¼ì´ì„¼ìŠ¤ì—서는 마ì¼ìŠ¤í†¤ 목ë¡ì„ 사용할 수 없습니다."
@@ -22808,7 +23069,7 @@ msgid "Missing"
msgstr ""
msgid "Missing OAuth configuration for GitHub."
-msgstr ""
+msgstr "GitHubì— ëŒ€í•œ OAuth ì„¤ì •ì´ ëˆ„ë½ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Missing OS"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr "달"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr "추가 작업"
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23048,13 +23303,13 @@ msgid "Namespace"
msgstr ""
msgid "Namespace ID:"
-msgstr ""
+msgstr "네임스페ì´ìŠ¤ ID:"
msgid "Namespace is empty"
-msgstr ""
+msgstr "네임스페ì´ìŠ¤ê°€ 비어 있습니다."
msgid "Namespace:"
-msgstr ""
+msgstr "네임스페ì´ìŠ¤:"
msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23361,7 +23607,7 @@ msgid "New Application"
msgstr "새로운 애플리케ì´ì…˜"
msgid "New Branch"
-msgstr ""
+msgstr "새 브랜치"
msgid "New Deploy Key"
msgstr ""
@@ -23373,7 +23619,7 @@ msgid "New Epic"
msgstr ""
msgid "New File"
-msgstr ""
+msgstr "새 파ì¼"
msgid "New Group"
msgstr "새 그룹"
@@ -23545,13 +23791,13 @@ msgid "New subgroup"
msgstr "새 서브그룹"
msgid "New tag"
-msgstr ""
+msgstr "새 태그"
msgid "New test case"
msgstr ""
msgid "New topic"
-msgstr ""
+msgstr "새 주제"
msgid "New users set to external"
msgstr ""
@@ -23563,7 +23809,7 @@ msgid "New..."
msgstr "새로 만들기..."
msgid "Newest first"
-msgstr ""
+msgstr "최신순"
msgid "Newly-registered users are external by default"
msgstr ""
@@ -23572,10 +23818,10 @@ msgid "Next"
msgstr "다ìŒ"
msgid "Next commit"
-msgstr ""
+msgstr "ë‹¤ìŒ ì»¤ë°‹"
msgid "Next design"
-msgstr ""
+msgstr "ë‹¤ìŒ ë””ìžì¸"
msgid "Next file in diff"
msgstr ""
@@ -23587,7 +23833,7 @@ msgid "Next unresolved discussion"
msgstr ""
msgid "Nickname"
-msgstr ""
+msgstr "닉네임"
msgid "No"
msgstr "아니오"
@@ -23602,7 +23848,7 @@ msgid "No CSV data to display."
msgstr ""
msgid "No Epic"
-msgstr ""
+msgstr "ì—픽 ì—†ìŒ"
msgid "No Matching Results"
msgstr ""
@@ -23614,7 +23860,7 @@ msgid "No Scopes"
msgstr ""
msgid "No Tag"
-msgstr ""
+msgstr "태그 ì—†ìŒ"
msgid "No active admin user found"
msgstr ""
@@ -23680,7 +23926,7 @@ msgid "No containers available"
msgstr ""
msgid "No contributions"
-msgstr ""
+msgstr "기여 ì—†ìŒ"
msgid "No contributions were found"
msgstr "기여를 ì°¾ì„ ìˆ˜ 없습니다."
@@ -23806,6 +24052,9 @@ msgid "No milestone"
msgstr ""
msgid "No milestones to show"
+msgstr "표시할 마ì¼ìŠ¤í†¤ì´ 없습니다."
+
+msgid "No namespace"
msgstr ""
msgid "No other labels with such name or description"
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23878,7 +24130,7 @@ msgid "No starrers matched your search"
msgstr ""
msgid "No start date"
-msgstr ""
+msgstr "ì‹œìž‘ì¼ ì—†ìŒ"
msgid "No tag selected"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,8 +25056,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "외부로 가는 요청"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25265,7 +25538,7 @@ msgid "Page not found"
msgstr ""
msgid "Page settings"
-msgstr ""
+msgstr "페ì´ì§€ 설정"
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr "권한"
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25613,7 +25886,7 @@ msgid "Pick a name"
msgstr ""
msgid "Pin code"
-msgstr ""
+msgstr "Pin 코드"
msgid "Pipeline"
msgstr "파ì´í”„ë¼ì¸"
@@ -25826,7 +26099,7 @@ msgid "PipelineSource|Schedule"
msgstr ""
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "트리거"
msgid "PipelineSource|Web"
msgstr ""
@@ -25846,9 +26119,6 @@ msgstr "파ì´í”„ë¼ì¸"
msgid "Pipelines charts"
msgstr "파ì´í”„ë¼ì¸ 차트"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "ìžì‹ ìžˆê²Œ 빌드하세요"
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26312,7 +26612,7 @@ msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
msgid "Please enter a valid URL format, ex: http://www.example.com/home"
-msgstr ""
+msgstr "유효한 URL 형ì‹ì„ 입력하세요. 예 : http://www.example.com/home"
msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
msgstr ""
@@ -26435,7 +26735,7 @@ msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
msgid "Please type the following to confirm:"
-msgstr ""
+msgstr "다ìŒì— 있는 ë‚´ìš©ì„ ìž…ë ¥í•˜ì—¬ 확ì¸í•˜ì„¸ìš”."
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr "시간 설정"
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr "아바타 ìžë¥´ê¸°"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr "ë„ì‹œ, êµ­ê°€"
msgid "Profiles|Clear status"
msgstr "ìƒíƒœ 지우기"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "ì•„ì´ì½˜ì„ í´ë¦­í•˜ì—¬ 아래 서비스를 ì´ìš©í•œ 로그ì¸ì„ 활성화하세요."
-
msgid "Profiles|Commit email"
msgstr "커밋 ì´ë©”ì¼"
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "아바타 제거"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "새 프로필 사진 설정"
@@ -27067,9 +27373,6 @@ msgstr "ì´ì¤‘ ì¸ì¤‘"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "확ì¸ì„ 위해 %{confirmationValue} 를 입력하세요."
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "ì¼ë°˜ì ìœ¼ë¡œ \"ssh-ed25519 …\" ë˜ëŠ” \"ssh-rsa ...\"으로 시작합니다."
-
msgid "Profiles|Update profile settings"
msgstr "프로필 설정 ì—…ë°ì´íŠ¸"
@@ -27083,7 +27386,7 @@ msgid "Profiles|Use a private email - %{email}"
msgstr "ê°œì¸ ì´ë©”ì¼ ì‚¬ìš© - %{email}"
msgid "Profiles|User ID"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ID"
msgid "Profiles|Username change failed - %{message}"
msgstr "ì‚¬ìš©ìž ì´ë¦„ 바꾸기 실패 - %{message}"
@@ -27209,13 +27512,13 @@ msgid "Project Badges"
msgstr "프로ì íŠ¸ 배지"
msgid "Project Files"
-msgstr ""
+msgstr "프로ì íŠ¸ 파ì¼"
msgid "Project ID"
-msgstr ""
+msgstr "프로ì íŠ¸ ID"
msgid "Project Templates"
-msgstr ""
+msgstr "프로ì íŠ¸ 템플릿"
msgid "Project URL"
msgstr "프로ì íŠ¸ URL"
@@ -27281,7 +27584,7 @@ msgid "Project import requests"
msgstr ""
msgid "Project info:"
-msgstr ""
+msgstr "프로ì íŠ¸ ì •ë³´:"
msgid "Project information"
msgstr "프로ì íŠ¸ ì •ë³´"
@@ -27293,7 +27596,7 @@ msgid "Project members"
msgstr ""
msgid "Project milestone"
-msgstr ""
+msgstr "프로ì íŠ¸ 마ì¼ìŠ¤í†¤"
msgid "Project name"
msgstr "프로ì íŠ¸ ì´ë¦„"
@@ -27305,13 +27608,13 @@ msgid "Project order will not be saved as local storage is not available."
msgstr ""
msgid "Project path"
-msgstr ""
+msgstr "프로ì íŠ¸ 경로"
msgid "Project security status"
-msgstr ""
+msgstr "프로ì íŠ¸ 보안 ìƒíƒœ"
msgid "Project security status help page"
-msgstr ""
+msgstr "프로ì íŠ¸ 보안 ìƒíƒœ ë„ì›€ë§ íŽ˜ì´ì§€"
msgid "Project slug"
msgstr "프로ì íŠ¸ 슬러그"
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27833,7 +28148,7 @@ msgid "ProjectSettings|These checks must pass before merge requests can be merge
msgstr ""
msgid "ProjectSettings|This project"
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸"
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 관리ìžì— ì˜í•´ ë³€ê²½ë  ìˆ˜ 있습니다."
@@ -27844,9 +28159,6 @@ msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 프로ì íŠ¸ì— ì
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "관리ìžì— 변경ë˜ì§€ 않는 í•œ, ì´ ì„¤ì •ì€ ëª¨ë“  프로ì íŠ¸ì— ì ìš©ë©ë‹ˆë‹¤."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr "공용 파ì´í”„ ë¼ì¸"
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29320,7 +29638,7 @@ msgid "Remove from batch"
msgstr ""
msgid "Remove from epic"
-msgstr ""
+msgstr "ì—픽ì—ì„œ 제거"
msgid "Remove group"
msgstr "그룹 제거"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "ì €ìž¥ì†Œì˜ ì €ìž¥ê³µê°„"
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr "재개"
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr "í기"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr "로드맵"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30702,10 +31042,7 @@ msgid "SSL Verification:"
msgstr ""
msgid "SSL verification"
-msgstr ""
-
-msgid "SVG illustration"
-msgstr ""
+msgstr "SSL ê²€ì¦"
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr "검색"
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -31760,13 +32172,13 @@ msgid "Select a label"
msgstr "ë¼ë²¨ ì„ íƒ"
msgid "Select a milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ ì„ íƒ"
msgid "Select a new namespace"
msgstr ""
msgid "Select a project"
-msgstr ""
+msgstr "프로ì íŠ¸ ì„ íƒ"
msgid "Select a reason"
msgstr ""
@@ -31859,7 +32271,7 @@ msgid "Select project to create %{type}"
msgstr ""
msgid "Select project to create issue"
-msgstr ""
+msgstr "ì´ìŠˆë¥¼ ìƒì„±í•  프로ì íŠ¸ ì„ íƒ"
msgid "Select projects"
msgstr "프로ì íŠ¸ ì„ íƒ"
@@ -32128,8 +32540,8 @@ msgstr "서비스 ë°ìŠ¤í¬"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "서비스 URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr "CI/CD 설정"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr "ì…œë¡ íŠ¸ëžœì ì…˜"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "명령 보기"
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr "완료 로그 표시"
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr "Slack 어플리케ì´ì…˜"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„해주세요."
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "죄송합니다. 검색과 ì¼ì¹˜í•˜ëŠ” ì—í”½ì´ ì—†ìŠµë‹ˆë‹¤."
-
msgid "Sorry, no projects matched your search"
msgstr "죄송합니다. 검색 결과와 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ê°€ 없습니다."
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr "ìµœê·¼ì— ìƒì„±ëœ"
-msgid "SortOptions|Last updated"
-msgstr "ìµœê·¼ì— ì—…ë°ì´íŠ¸ ëœ"
-
msgid "SortOptions|Least popular"
msgstr "ëœ ì¸ê¸°ìžˆëŠ”"
@@ -33191,7 +33624,7 @@ msgid "SortOptions|Merged recently"
msgstr ""
msgid "SortOptions|Milestone due date"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼"
msgid "SortOptions|Milestone due later"
msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼ì´ 먼"
@@ -33293,10 +33726,10 @@ msgid "Source Branch"
msgstr ""
msgid "Source IP"
-msgstr ""
+msgstr "소스 IP"
msgid "Source branch"
-msgstr ""
+msgstr "소스 브랜치"
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr ""
@@ -33428,7 +33861,7 @@ msgid "Stage"
msgstr "스테ì´ì§€"
msgid "Standard"
-msgstr ""
+msgstr "표준"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
@@ -33464,7 +33897,7 @@ msgid "Stars"
msgstr ""
msgid "Start Date"
-msgstr ""
+msgstr "시작 날짜"
msgid "Start Time"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr "구ë…ë¨"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34025,10 +34485,10 @@ msgid "Successful purchase image"
msgstr ""
msgid "Successfully activated"
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ 활성화ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Successfully approved"
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ 승ì¸ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Successfully banned"
msgstr ""
@@ -34037,19 +34497,19 @@ msgid "Successfully blocked"
msgstr ""
msgid "Successfully confirmed"
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Successfully deactivated"
msgstr "비활성화했습니다."
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ U2F 장치를 제거했습니다."
msgid "Successfully deleted WebAuthn device."
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ WebAuthn 장치를 제거했습니다."
msgid "Successfully removed email."
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ ì´ë©”ì¼ì„ 제거했습니다."
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
@@ -34070,7 +34530,7 @@ msgid "Successfully updated %{last_updated_timeago}."
msgstr "성공ì ìœ¼ë¡œ %{last_updated_timeago}ì— ì—…ë°ì´íŠ¸í–ˆìŠµë‹ˆë‹¤."
msgid "Successfully updated the environment."
-msgstr ""
+msgstr "성공ì ìœ¼ë¡œ í™˜ê²½ì„ ì—…ë°ì´íŠ¸í–ˆìŠµë‹ˆë‹¤."
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34412,22 +34887,22 @@ msgid "System output"
msgstr ""
msgid "Table of Contents"
-msgstr ""
+msgstr "목차"
msgid "Table of contents"
-msgstr ""
+msgstr "목차"
msgid "Tag"
msgstr "태그"
msgid "Tag list:"
-msgstr ""
+msgstr "태그 목ë¡:"
msgid "Tag name"
-msgstr ""
+msgstr "태그 ì´ë¦„"
msgid "Tag name is required"
-msgstr ""
+msgstr "태그 ì´ë¦„ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "Tag push events"
msgstr ""
@@ -34436,7 +34911,7 @@ msgid "Tag this commit."
msgstr ""
msgid "Tag:"
-msgstr ""
+msgstr "태그:"
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr "서비스 약관 계약 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
msgid "Terms of Service and Privacy Policy"
msgstr "서비스 약관 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34770,15 +35251,18 @@ msgid "Terraform|Unlocking state"
msgstr ""
msgid "Terraform|You are about to remove the state file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously will remain intact, and only the state file with all its versions will be removed. This action cannot be undone."
-msgstr ""
+msgstr "ìƒíƒœ íŒŒì¼ %{name}ì„(를) 제거하려고 합니다. ì´ë ‡ê²Œ 하면 모든 ìƒíƒœ 버전과 기ë¡ì´ ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œë©ë‹ˆë‹¤. ì´ì „ì— í”„ë¡œë¹„ì €ë‹ëœ ì¸í”„ë¼ëŠ” 그대로 유지ë˜ë©°, 모든 ë²„ì „ì´ í¬í•¨ëœ ìƒíƒœ 파ì¼ë§Œ 제거ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ì·¨ì†Œí•  수 없습니다."
msgid "Terraform|You cannot remove the State file because it's locked. Unlock the State file first before removing it."
msgstr ""
msgid "Test"
-msgstr ""
+msgstr "테스트"
msgid "Test Cases"
+msgstr "테스트 ì¼€ì´ìŠ¤"
+
+msgid "Test case"
msgstr ""
msgid "Test coverage parsing"
@@ -34793,7 +35277,7 @@ msgid_plural "Test coverage: %d hits"
msgstr[0] ""
msgid "Test settings"
-msgstr ""
+msgstr "테스트 설정"
msgid "TestCases|Move test case"
msgstr ""
@@ -34943,7 +35427,7 @@ msgid "Thanks for your purchase!"
msgstr ""
msgid "That's OK, I don't want to renew"
-msgstr ""
+msgstr "괜찮습니다, 갱신하지 않겠습니다."
msgid "That's it, well done!"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34962,7 +35443,7 @@ msgstr ""
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
-msgstr[0] ""
+msgstr[0] "%{type} ì—는 다ìŒê³¼ ê°™ì€ ì˜¤ë¥˜ê°€ 있습니다."
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35055,7 +35527,7 @@ msgid "The contents of this group, its subgroups and projects will be permanentl
msgstr ""
msgid "The current issue"
-msgstr ""
+msgstr "현재 ì´ìŠˆ"
msgid "The current user is not authorized to access the job log."
msgstr ""
@@ -35124,7 +35596,7 @@ msgid "The following Personal Access Token was revoked by an administrator, %{us
msgstr ""
msgid "The following SSH key was deleted by an administrator, %{username}."
-msgstr ""
+msgstr "%{username}님, ë‹¤ìŒ SSH 키는 관리ìžì— ì˜í•´ ì‚­ì œ ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "The following items will NOT be exported:"
msgstr ""
@@ -35140,7 +35612,7 @@ msgid "The fork relationship has been removed."
msgstr "í¬í¬ 관계가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "The form contains the following errors:"
-msgstr ""
+msgstr "ì–‘ì‹ì— 다ìŒê³¼ ê°™ì€ ì˜¤ë¥˜ê°€ 있습니다."
msgid "The form contains the following warning:"
msgstr ""
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35515,13 +35984,13 @@ msgid "There are no open test cases"
msgstr ""
msgid "There are no packages yet"
-msgstr ""
+msgstr "ì•„ì§ íŒ¨í‚¤ì§€ê°€ 없습니다"
msgid "There are no projects shared with this group yet"
msgstr ""
msgid "There are no topics to show."
-msgstr ""
+msgstr "표시할 주제가 없습니다."
msgid "There are no variables yet."
msgstr ""
@@ -35545,16 +36014,16 @@ msgid "There is already a to-do item for this design."
msgstr ""
msgid "There is no chart data available."
-msgstr ""
+msgstr "사용 가능한 차트 ë°ì´í„°ê°€ 없습니다."
msgid "There is no data available."
-msgstr ""
+msgstr "사용 가능한 ë°ì´í„°ê°€ 없습니다."
msgid "There is no data available. Please change your selection."
msgstr ""
msgid "There is no table data available."
-msgstr ""
+msgstr "사용 가능한 í…Œì´ë¸” ë°ì´í„°ê°€ 없습니다."
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -35569,7 +36038,7 @@ msgid "There was a problem fetching emojis."
msgstr ""
msgid "There was a problem fetching epics."
-msgstr ""
+msgstr "ì—í”½ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "There was a problem fetching groups."
msgstr "ê·¸ë£¹ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35689,7 +36158,7 @@ msgid "There was an error fetching the top labels for the selected group"
msgstr ""
msgid "There was an error fetching the variables."
-msgstr ""
+msgstr "변수를 가져오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "There was an error fetching value stream analytics stages."
msgstr ""
@@ -35724,11 +36193,11 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
-msgstr ""
+msgstr "변경 ì‚¬í•­ì„ ì €ìž¥í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "There was an error subscribing to this label."
msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36172,7 +36644,7 @@ msgid "This job will automatically run after its timer finishes. Often they are
msgstr ""
msgid "This license has already expired."
-msgstr ""
+msgstr "ì´ ë¼ì´ì„ ìŠ¤ëŠ” ì´ë¯¸ 만료ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "This link points to external content"
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr "ì´ í”„ë¡œì íŠ¸"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36319,7 +36800,7 @@ msgid "This user has no identities"
msgstr "ì´ ì‚¬ìš©ìžëŠ” ì‹ ì›ì´ 없습니다."
msgid "This user has no personal projects."
-msgstr ""
+msgstr "ì´ ì‚¬ìš©ìžëŠ” ê°œì¸ í”„ë¡œì íŠ¸ê°€ 없습니다."
msgid "This user has previously committed to the %{name} project."
msgstr ""
@@ -36493,7 +36974,7 @@ msgid "Time (in hours) that users are allowed to skip forced configuration of tw
msgstr ""
msgid "Time Spent"
-msgstr ""
+msgstr "소요 시간"
msgid "Time based: Yes"
msgstr ""
@@ -36511,7 +36992,7 @@ msgid "Time between merge request creation and merge/close"
msgstr "머지 리퀘스트(MR) ìƒì„±ê³¼ 머지 / 닫기 사ì´ì˜ 시간"
msgid "Time estimate"
-msgstr ""
+msgstr "ì˜ˆìƒ ì‹œê°„"
msgid "Time from first comment to last commit"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36718,7 +37196,7 @@ msgid "Timeout for the fastest Gitaly operations (in seconds)."
msgstr ""
msgid "Timezone"
-msgstr ""
+msgstr "시간대"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -36744,7 +37222,7 @@ msgid "Title:"
msgstr "제목:"
msgid "Titles and Descriptions"
-msgstr ""
+msgstr "제목 ë° ì„¤ëª…"
msgid "To"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36828,7 +37303,7 @@ msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal
msgstr ""
msgid "To get started, use the link below to confirm your account."
-msgstr ""
+msgstr "시작하려면 아래 ë§í¬ë¥¼ 사용하여 ê³„ì •ì„ í™•ì¸í•˜ì„¸ìš”."
msgid "To help improve GitLab and its user experience, GitLab periodically collects usage information."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr "í•  ì¼ ëª©ë¡"
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "퀵 ì•¡ì…˜ 시간 추ì "
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37161,7 +37627,7 @@ msgid "Transfer ownership"
msgstr ""
msgid "Transfer project"
-msgstr ""
+msgstr "프로ì íŠ¸ ì´ì „"
msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37357,7 +37826,7 @@ msgid "Try again"
msgstr "다시 ì‹œë„하십시오"
msgid "Try again?"
-msgstr ""
+msgstr "다시 ì‹œë„í•´ 보세요."
msgid "Try all GitLab has to offer for 30 days."
msgstr "GitLabì´ ì œê³µí•˜ëŠ” 모든 ê¸°ëŠ¥ì„ 30ë™ì•ˆ 사용해 보세요."
@@ -37405,7 +37874,7 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Twitter:"
-msgstr ""
+msgstr "트위터:"
msgid "Two-Factor Authentication"
msgstr ""
@@ -37447,7 +37916,7 @@ msgid "Type"
msgstr ""
msgid "Type/State"
-msgstr ""
+msgstr "유형/ìƒíƒœ"
msgid "U2F Devices (%{length})"
msgstr ""
@@ -37462,10 +37931,10 @@ msgid "URL cannot be blank"
msgstr ""
msgid "URL is invalid"
-msgstr ""
+msgstr "URLì´ ìž˜ëª»ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "URL is required"
-msgstr ""
+msgstr "URLì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "URL is triggered for each branch updated to the repository"
msgstr ""
@@ -37474,13 +37943,13 @@ msgid "URL is triggered when a merge request is created, updated, or merged"
msgstr ""
msgid "URL is triggered when a new tag is pushed to the repository"
-msgstr ""
+msgstr "새 태그가 ì €ìž¥ì†Œì— í‘¸ì‰¬ë˜ë©´ URLì´ íŠ¸ë¦¬ê±°ë©ë‹ˆë‹¤."
msgid "URL is triggered when repository is updated"
msgstr ""
msgid "URL must be percent-encoded if neccessary."
-msgstr ""
+msgstr "필요한 경우 URLì„ í¼ì„¼íŠ¸ ì¸ì½”ë”©ì„ í•´ì•¼í•©ë‹ˆë‹¤."
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
msgstr ""
@@ -37495,7 +37964,7 @@ msgid "URL of the external storage to serve the repository static objects."
msgstr ""
msgid "URL or request ID"
-msgstr ""
+msgstr "URL ë˜ëŠ” 요청 ID"
msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
msgstr ""
@@ -37645,7 +38114,7 @@ msgid "Unexpected error"
msgstr ""
msgid "Unfollow"
-msgstr ""
+msgstr "팔로우 취소"
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
@@ -37822,7 +38291,7 @@ msgid "Update iteration"
msgstr ""
msgid "Update milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ ì—…ë°ì´íŠ¸"
msgid "Update now"
msgstr "지금 ì—…ë°ì´íŠ¸"
@@ -37831,7 +38300,7 @@ msgid "Update username"
msgstr ""
msgid "Update variable"
-msgstr ""
+msgstr "변수 ì—…ë°ì´íŠ¸"
msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr "업로드"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "CSV íŒŒì¼ ì—…ë¡œë“œ"
@@ -38245,7 +38720,7 @@ msgid "Use primary email (%{email})"
msgstr ""
msgid "Use shortcuts"
-msgstr ""
+msgstr "단축키 사용"
msgid "Use slash commands."
msgstr ""
@@ -38296,7 +38771,7 @@ msgid "Used to help configure your identity provider"
msgstr ""
msgid "User"
-msgstr ""
+msgstr "사용ìž"
msgid "User %{current_user_username} has started impersonating %{username}"
msgstr ""
@@ -38308,7 +38783,7 @@ msgid "User %{user} was removed from %{group}."
msgstr ""
msgid "User ID"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ID"
msgid "User OAuth applications"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38341,7 +38819,7 @@ msgid "User is not allowed to resolve thread"
msgstr ""
msgid "User key"
-msgstr ""
+msgstr "ì‚¬ìš©ìž í‚¤"
msgid "User key was successfully removed."
msgstr ""
@@ -38479,7 +38957,7 @@ msgid "UserProfile|Bot activity"
msgstr ""
msgid "UserProfile|Contributed projects"
-msgstr "기여한 프로ì íŠ¸ë“¤"
+msgstr "기여한 프로ì íŠ¸"
msgid "UserProfile|Edit profile"
msgstr "프로필 수정"
@@ -38488,10 +38966,10 @@ msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
msgid "UserProfile|Followers"
-msgstr ""
+msgstr "팔로워"
msgid "UserProfile|Following"
-msgstr ""
+msgstr "팔로잉"
msgid "UserProfile|Groups"
msgstr "그룹"
@@ -38539,7 +39017,7 @@ msgid "UserProfile|Subscribe"
msgstr "구ë…"
msgid "UserProfile|This user doesn't have any followers."
-msgstr ""
+msgstr "ì´ ì‚¬ìš©ìžëŠ” 팔로워가 없습니다."
msgid "UserProfile|This user doesn't have any personal projects"
msgstr ""
@@ -38557,7 +39035,7 @@ msgid "UserProfile|This user is blocked"
msgstr ""
msgid "UserProfile|This user isn't following other users."
-msgstr ""
+msgstr "ì´ ì‚¬ìš©ìžëŠ” 다른 사용ìžë¥¼ 팔로우하고 있지 않습니다."
msgid "UserProfile|Unconfirmed user"
msgstr ""
@@ -38569,13 +39047,13 @@ msgid "UserProfile|View user in admin area"
msgstr "ê´€ë¦¬ìž ì˜ì—­ì—ì„œ ì‚¬ìš©ìž ë³´ê¸°"
msgid "UserProfile|You are not following other users."
-msgstr ""
+msgstr "ë‹¹ì‹ ì€ ë‹¤ë¥¸ 사용ìžë¥¼ 팔로우하고 있지 않습니다."
msgid "UserProfile|You can create a group for several dependent projects."
msgstr ""
msgid "UserProfile|You do not have any followers."
-msgstr ""
+msgstr "ì•„ì§ íŒ”ë¡œì›Œê°€ 없습니다."
msgid "UserProfile|You haven't created any personal projects."
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38937,10 +39427,10 @@ msgid "View incident issues."
msgstr ""
msgid "View issue"
-msgstr ""
+msgstr "ì´ìŠˆ 보기"
msgid "View issues"
-msgstr ""
+msgstr "ì´ìŠˆ 보기"
msgid "View it on GitLab"
msgstr "GitLabì—ì„œ 보기"
@@ -38961,7 +39451,7 @@ msgid "View log"
msgstr "로그 보기"
msgid "View logs"
-msgstr ""
+msgstr "로그 보기"
msgid "View merge request"
msgstr ""
@@ -38982,7 +39472,7 @@ msgid "View performance dashboard."
msgstr ""
msgid "View project"
-msgstr ""
+msgstr "프로ì íŠ¸ 보기"
msgid "View project in admin area"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr "êµì²´ëœ íŒŒì¼ ë³´ê¸° @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39211,10 +39704,10 @@ msgid "VulnerabilityStatusTypes|Resolved"
msgstr ""
msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
-msgstr ""
+msgstr "%{scannerName} (버전 %{scannerVersion})"
msgid "Vulnerability|Activity"
-msgstr ""
+msgstr "활ë™"
msgid "Vulnerability|Actual Response"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39274,7 +39773,7 @@ msgid "Vulnerability|False positive detected"
msgstr ""
msgid "Vulnerability|File"
-msgstr ""
+msgstr "파ì¼"
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -39282,15 +39781,24 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
msgid "Vulnerability|Image"
-msgstr ""
+msgstr "ì´ë¯¸ì§€"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39298,9 +39806,12 @@ msgid "Vulnerability|Method"
msgstr ""
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "네임스페ì´ìŠ¤"
msgid "Vulnerability|Project"
+msgstr "프로ì íŠ¸"
+
+msgid "Vulnerability|Remove identifier row"
msgstr ""
msgid "Vulnerability|Reproduction Assets"
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39325,10 +39839,10 @@ msgid "Vulnerability|Set the status of the vulnerability finding based on the in
msgstr ""
msgid "Vulnerability|Severity"
-msgstr ""
+msgstr "심ê°ë„"
msgid "Vulnerability|Status"
-msgstr ""
+msgstr "ìƒíƒœ"
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
msgstr ""
@@ -39339,12 +39853,21 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
-msgid "WARNING:"
+msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr "경고:"
+
msgid "Wait for the file to load to copy its contents"
msgstr ""
@@ -39358,10 +39881,10 @@ msgid "Want to see the data? Please ask an administrator for access."
msgstr "ì´ ë°ì´í„°ë¥¼ ë³´ê³  싶ì€ê°€ìš”? 관리ìžì—게 액세스 ê¶Œí•œì„ ìš”ì²­í•˜ì„¸ìš”."
msgid "Warning"
-msgstr ""
+msgstr "경고"
msgid "Warning:"
-msgstr ""
+msgstr "경고:"
msgid "Warning: Displaying this diagram might cause performance issues on this page."
msgstr ""
@@ -39502,147 +40025,147 @@ msgid "WebexTeamsService|Webex Teams"
msgstr ""
msgid "Webhook"
-msgstr ""
+msgstr "웹훅"
msgid "Webhook Logs"
-msgstr ""
+msgstr "웹훅 로그"
msgid "Webhook Settings"
-msgstr ""
+msgstr "웹훅 설정"
msgid "Webhook events will be displayed here."
msgstr ""
msgid "Webhook:"
-msgstr ""
+msgstr "웹훅"
msgid "Webhooks"
-msgstr ""
+msgstr "웹훅"
msgid "Webhooks Help"
-msgstr ""
+msgstr "웹훅 ë„움ë§"
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr "기밀 ì´ìŠˆê°€ ìƒì„±, ì—…ë°ì´íŠ¸, 종료 ë˜ëŠ” 다시 열릴 ë•Œ URLì´ íŠ¸ë¦¬ê±°ë©ë‹ˆë‹¤."
+msgid "Webhooks|Merge request events"
+msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr "ì´ìŠˆê°€ ìƒì„±, ì—…ë°ì´íŠ¸, 종료 ë˜ëŠ” 다시 열릴 ë•Œ URLì´ íŠ¸ë¦¬ê±°ë©ë‹ˆë‹¤."
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -39917,7 +40440,7 @@ msgid "WikiPage|Are you sure you want to switch back to the classic editor?"
msgstr ""
msgid "WikiPage|Cancel"
-msgstr ""
+msgstr "취소"
msgid "WikiPage|Commit message"
msgstr ""
@@ -39953,7 +40476,7 @@ msgid "WikiPage|Page title"
msgstr ""
msgid "WikiPage|Retry"
-msgstr ""
+msgstr "재시ë„"
msgid "WikiPage|Save changes"
msgstr ""
@@ -39977,7 +40500,7 @@ msgid "WikiPage|Tip: You can specify the full path for the new file. We will aut
msgstr "íŒ: 새 파ì¼ì˜ ì „ì²´ 경로를 지정할 수 있습니다. 누ë½ëœ 디렉토리는 ìžë™ìœ¼ë¡œ ìƒì„±ë©ë‹ˆë‹¤."
msgid "WikiPage|Title"
-msgstr ""
+msgstr "제목"
msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
@@ -39998,7 +40521,7 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr "ì—¬ê¸°ì— ë‚´ìš©ì„ ìž‘ì„±í•˜ê±°ë‚˜ 파ì¼ì„ 드래그하세요…"
msgid "Wikis"
-msgstr ""
+msgstr "위키"
msgid "Wiki|Create New Page"
msgstr ""
@@ -40025,7 +40548,7 @@ msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
msgstr ""
msgid "Wiki|Title"
-msgstr ""
+msgstr "제목"
msgid "Wiki|View All Pages"
msgstr ""
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40115,7 +40644,7 @@ msgid "Yes, close issue"
msgstr ""
msgid "Yes, delete project"
-msgstr ""
+msgstr "예, 프로ì íŠ¸ë¥¼ 삭제합니다."
msgid "Yesterday"
msgstr "어제"
@@ -40162,6 +40691,9 @@ msgstr "%{group_name}ì„ ì œê±°í•©ë‹ˆë‹¤. ì´ì— ë”°ë¼ ëª¨ë“  하위 그룹과
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40175,7 +40707,7 @@ msgid "You are not allowed to %{action} a user"
msgstr ""
msgid "You are not allowed to approve a user"
-msgstr ""
+msgstr "사용ìžë¥¼ 승ì¸í•  ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "You are not allowed to log in using password"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,14 +40778,17 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "You can always change your URL later"
-msgstr ""
+msgstr "ë‚˜ì¤‘ì— ì–¸ì œë“ ì§€ URLì„ ë³€ê²½í•  수 있습니다."
msgid "You can always edit this later"
-msgstr ""
+msgstr "ë‚˜ì¤‘ì— ì–¸ì œë“ ì§€ 수정할 수 있습니다."
msgid "You can create a new %{link}."
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40304,7 +40845,7 @@ msgid "You can group test cases using labels. To learn about the future directio
msgstr ""
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "%{project_name} ì— ìƒˆ 회ì›ì„ 초대하거나 다른 ê·¸ë£¹ì„ ì´ˆëŒ€í•  수 있습니다."
msgid "You can invite a new member to %{project_name}."
msgstr "%{project_name} ì— ìƒˆ 회ì›ì„ 초대할 수 있습니다."
@@ -40313,7 +40854,7 @@ msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}.
msgstr "%{strong_start}%{group_name}%{strong_end} ì— ìƒˆ 회ì›ì„ 초대할 수 있습니다."
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "%{project_name} ì— ë‹¤ë¥¸ ê·¸ë£¹ì„ ì´ˆëŒ€í•  수 있습니다.."
msgid "You can move around the graph by using the arrow keys."
msgstr "화살표 키를 사용하여 그래프를 움ì§ì¼ 수 있습니다."
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "웹 터미ë„ì„ ì‹¤í–‰í•  수 있는 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤. 프로ì íŠ¸ 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr "프로ì íŠ¸ ìˆ«ìž í•œë„ì— ë„달했습니다."
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40887,7 +41437,7 @@ msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here
msgstr ""
msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
-msgstr ""
+msgstr "대시보드가 ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤. %{web_ide_link_start}여기서 수정%{web_ide_link_end}하실 수 있습니다."
msgid "Your default notification email is used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr "ê·€í•˜ì˜ ì´ë¦„"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr "ì´ë¯¸ 프로ì íŠ¸ 승ì¸ìžê°€ 존재합니다."
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41187,7 +41741,7 @@ msgstr ""
msgid "branch"
msgid_plural "branches"
-msgstr[0] ""
+msgstr[0] "브랜치"
msgid "branch name"
msgstr "브랜치 ì´ë¦„"
@@ -41196,7 +41750,7 @@ msgid "by"
msgstr "by"
msgid "cURL:"
-msgstr ""
+msgstr "cURL:"
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41601,11 +42158,14 @@ msgid "commit %{commit_id}"
msgstr ""
msgid "committed"
-msgstr ""
+msgstr "커밋ë¨"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr "%{timeAgo} ì „ ìƒì„±ë¨"
@@ -41662,7 +42216,7 @@ msgid "days"
msgstr ""
msgid "default branch"
-msgstr ""
+msgstr "기본 브랜치"
msgid "deleted"
msgstr ""
@@ -41671,7 +42225,7 @@ msgid "deploy"
msgstr ""
msgid "design"
-msgstr ""
+msgstr "ë””ìžì¸"
msgid "detached"
msgstr ""
@@ -41680,7 +42234,7 @@ msgid "disabled"
msgstr "사용 안 함"
msgid "does not exist"
-msgstr ""
+msgstr "존재하지 않습니다"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
@@ -41732,7 +42286,7 @@ msgid "environment_id parameter is required when type is container_policy"
msgstr ""
msgid "epic"
-msgstr ""
+msgstr "ì—픽"
msgid "error"
msgstr ""
@@ -41741,7 +42295,7 @@ msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
msgstr ""
msgid "example.com"
-msgstr ""
+msgstr "example.com"
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -41764,12 +42318,15 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
msgid "file"
msgid_plural "files"
-msgstr[0] ""
+msgstr[0] "파ì¼"
msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
@@ -41793,7 +42350,7 @@ msgid "for this project"
msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해"
msgid "fork"
-msgstr ""
+msgstr "í¬í¬"
msgid "from"
msgstr ""
@@ -41806,6 +42363,12 @@ msgid "frontmatter"
msgstr ""
msgid "group"
+msgstr "그룹"
+
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
msgstr ""
msgid "group members"
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -41954,7 +42520,7 @@ msgid "is too long (maximum is 1000 entries)"
msgstr ""
msgid "issue"
-msgstr ""
+msgstr "ì´ìŠˆ"
msgid "issues at risk"
msgstr ""
@@ -41987,7 +42553,7 @@ msgid "kuromoji custom analyzer"
msgstr ""
msgid "last commit:"
-msgstr ""
+msgstr "마지막 커밋:"
msgid "latest"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "브랜치를 ë³µì›í•˜ê±°ë‚˜ 다른 %{missingBranchName} 브랜치를 사용해주세요."
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42157,7 +42717,7 @@ msgid "mrWidget|Create issue to resolve all threads"
msgstr ""
msgid "mrWidget|Delete source branch"
-msgstr ""
+msgstr "소스 브랜치 삭제"
msgid "mrWidget|Deletes the source branch"
msgstr ""
@@ -42186,8 +42746,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "머지 실패."
@@ -42251,10 +42814,10 @@ msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
msgid "mrWidget|Merging! Changes will land soon…"
-msgstr ""
+msgstr "머지 중! 변경 ì‚¬í•­ì´ ê³§ ì ìš©ë©ë‹ˆë‹¤â€¦"
msgid "mrWidget|Merging! Drum roll, please…"
-msgstr ""
+msgstr "머지 중! ë‘구ë‘구ë‘구…"
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
@@ -42272,7 +42835,7 @@ msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
msgid "mrWidget|Merging! We're almost there…"
-msgstr ""
+msgstr "머지 중! ê±°ì˜ ë‹¤ ë습니다…"
msgid "mrWidget|More information"
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr "Web IDEì—ì„œ 열기"
msgid "mrWidget|Plain diff"
msgstr "Plain diff"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "ìžë™ìœ¼ë¡œ 머지할 준비가 ë˜ì—ˆìŠµë‹ˆë‹¤. ì´ ì €ìž¥ì†Œì˜ ì“°ê¸° ê¶Œí•œì´ ìžˆëŠ” ì‚¬ëžŒì´ ë¨¸ì§€í•  수 있ë„ë¡ ìš”ì²­í•˜ì„¸ìš”."
@@ -42299,7 +42865,7 @@ msgid "mrWidget|Refreshing now"
msgstr "지금 새로고침 중"
msgid "mrWidget|Remove from merge train"
-msgstr ""
+msgstr "머지 트레ì¸ì—ì„œ 제거"
msgid "mrWidget|Request to merge"
msgstr "머지 리퀘스트(MR)"
@@ -42314,7 +42880,7 @@ msgid "mrWidget|Revert this merge request in a new merge request"
msgstr "새로운 머지 리퀘스트(MR)ì—ì„œ ì´ ë¨¸ì§€ 리퀘스트(MR)ë¡œ ë˜ëŒë¦¬ê¸°"
msgid "mrWidget|Revoke approval"
-msgstr ""
+msgstr "ìŠ¹ì¸ ì·¨ì†Œ"
msgid "mrWidget|SAST and Secret Detection is not enabled."
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr "파ì´í”„ë¼ì¸ì´ 성공할 ë•Œ 머지 트레ì¸ì„ 시작하ë„ë¡ %{m
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -42340,11 +42909,8 @@ msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì§€ 않았습니다."
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr "ì´ ë¨¸ì§€ ë¦¬í€˜ìŠ¤íŠ¸ì— ëŒ€í•œ 파ì´í”„ë¼ì¸ì´ 완료ë˜ì§€ 않았습니다. 새 ì»¤ë°‹ì„ í‘¸ì‹œí•˜ì—¬ 오류를 수정하거나 %{linkStart}문제 í•´ê²° 문서%{linkEnd}를 확ì¸í•˜ì—¬ 가능한 다른 ìž‘ì—…ì„ í™•ì¸í•˜ì„¸ìš”."
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr "ì´ ë¨¸ì§€ ë¦¬í€˜ìŠ¤íŠ¸ì— ëŒ€í•œ 파ì´í”„ë¼ì¸ì´ 완료ë˜ì§€ 않았습니다. 새 ì»¤ë°‹ì„ í‘¸ì‰¬í•˜ì—¬ 오류를 수정하세요."
-
msgid "mrWidget|The source branch has been deleted"
-msgstr ""
+msgstr "소스 브랜치가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
@@ -42379,14 +42945,11 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr "브랜치가 존재하지 않습니다."
-
msgid "mrWidget|into"
msgstr "로"
msgid "must be a Debian package"
-msgstr ""
+msgstr "Debian 패키지여야 합니다"
msgid "must be a boolean value"
msgstr ""
@@ -42529,7 +43092,7 @@ msgid "personal access tokens"
msgstr ""
msgid "pipeline"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸"
msgid "pipeline schedules documentation"
msgstr ""
@@ -42591,13 +43154,13 @@ msgid "project members"
msgstr ""
msgid "project name"
-msgstr ""
+msgstr "프로ì íŠ¸ ì´ë¦„"
msgid "project namespace cannot be the parent of another namespace"
msgstr ""
msgid "projects"
-msgstr ""
+msgstr "프로ì íŠ¸"
msgid "quick actions"
msgstr ""
@@ -42609,10 +43172,10 @@ msgid "reCAPTCHA helps prevent credential stuffing."
msgstr ""
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "reCAPTCHA ê°œì¸ í‚¤"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "reCAPTCHA 사ì´íŠ¸ 키"
msgid "recent activity"
msgstr ""
@@ -42645,21 +43208,18 @@ msgid "removed a Zoom call from this issue"
msgstr ""
msgid "rendered diff"
-msgstr ""
+msgstr "ë Œë”ë§ëœ diff"
msgid "reply"
msgid_plural "replies"
msgstr[0] "답변"
msgid "repository:"
-msgstr ""
+msgstr "저장소:"
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42712,13 +43272,13 @@ msgid "show %{count} more"
msgstr ""
msgid "show fewer"
-msgstr ""
+msgstr "ë” ì ê²Œ 표시"
msgid "show less"
-msgstr ""
+msgstr "간략히 보기"
msgid "sign in"
-msgstr ""
+msgstr "로그ì¸"
msgid "smartcn custom analyzer"
msgstr ""
@@ -42727,7 +43287,7 @@ msgid "source"
msgstr "소스"
msgid "source diff"
-msgstr ""
+msgstr "소스 diff"
msgid "specified top is not part of the tree"
msgstr ""
@@ -42742,10 +43302,10 @@ msgid "started a discussion on %{design_link}"
msgstr ""
msgid "started on %{timebox_start_date}"
-msgstr ""
+msgstr "%{timebox_start_date}ì— ì‹œìž‘ë¨"
msgid "starts on %{timebox_start_date}"
-msgstr ""
+msgstr "%{timebox_start_date}ì— ì‹œìž‘"
msgid "structure is too large"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr "ì‚¬ìš©ìž ì•„ë°”íƒ€"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "ì‚¬ìš©ìž ì„¤ì •"
-
msgid "username"
msgstr "사용ìžëª…"
@@ -42853,13 +43410,13 @@ msgid "value for '%{storage}' must be an integer"
msgstr ""
msgid "value for '%{storage}' must be between 0 and 100"
-msgstr ""
+msgstr "'%{storage}'ì˜ ê°’ì€ 0ì—ì„œ 100 사ì´ì—¬ì•¼ 합니다."
msgid "verify ownership"
msgstr ""
msgid "version %{versionIndex}"
-msgstr ""
+msgstr "버전 %{versionIndex}"
msgid "via %{closed_via}"
msgstr ""
@@ -42871,10 +43428,10 @@ msgid "view it on GitLab"
msgstr "GitLabì—ì„œ 보기"
msgid "view the blob"
-msgstr ""
+msgstr "blob 보기"
msgid "view the source"
-msgstr ""
+msgstr "소스 보기"
msgid "visibility"
msgstr ""
@@ -42884,13 +43441,13 @@ msgid_plural "vulnerabilities"
msgstr[0] ""
msgid "vulnerability|Add a comment"
-msgstr ""
+msgstr "댓글 추가"
msgid "vulnerability|Add a comment or reason for dismissal"
msgstr ""
msgid "vulnerability|Add comment"
-msgstr ""
+msgstr "댓글 추가"
msgid "vulnerability|Add comment & dismiss"
msgstr ""
@@ -42902,7 +43459,7 @@ msgid "vulnerability|Dismiss vulnerability"
msgstr ""
msgid "vulnerability|Save comment"
-msgstr ""
+msgstr "댓글 저장"
msgid "vulnerability|Undo dismiss"
msgstr ""
@@ -42911,29 +43468,29 @@ msgid "vulnerability|dismissed"
msgstr ""
msgid "was scheduled to merge after pipeline succeeds by"
-msgstr ""
+msgstr "ë‹¤ìŒ íŒŒì´í”„ë¼ì¸ì´ 성공한 ë’¤ 머지ë˜ë„ë¡ ì˜ˆì•½ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "wiki page"
-msgstr ""
+msgstr "위키 페ì´ì§€"
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} ê°œì˜ ì¶”ê°€, %{deletions} ê°œì˜ ì‚­ì œê°€ 있습니다."
msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
-msgstr ""
+msgstr "만료가 %{old_expiry}ì—ì„œ %{new_expiry}(으)ë¡œ 변경ë¨"
msgid "with expiry remaining unchanged at %{old_expiry}"
msgstr ""
msgid "yaml invalid"
-msgstr ""
+msgstr "유효하지 ì•Šì€ yaml"
msgid "your settings"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ ì„¤ì •"
msgid "{group}"
-msgstr ""
+msgstr "{그룹}"
msgid "{project}"
-msgstr ""
+msgstr "{프로ì íŠ¸}"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 369003ca62e..037e73633d7 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index 4230c6d6bf3..e7520f63696 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 49a136f8582..472482312a1 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -132,6 +132,34 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -780,6 +814,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -876,6 +913,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2223,7 +2251,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2238,6 +2266,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2421,9 +2455,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4041,16 +4075,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 43a30dde9c1..1c43fe1fd20 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 4f3ea7851de..ec1d1e69b95 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index c2a65db27ba..fd0a4e25ba1 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL skannet"
msgstr[1] "%d URLer skannet"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkjenner"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} åpnet fletteforespørsel"
msgstr[1] "%{bold_start}%{count}%{bold_end} åpnede fletteforespørsler"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Maskert:%{code_close} Skjult i jobblogger. MÃ¥ oppfylle kravene til maskering."
@@ -626,6 +652,9 @@ msgstr "%{group_name}-aktivitet"
msgid "%{group_name} group members"
msgstr "%{group_name} gruppemedlemmer"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} bruker gruppeadministrerte kontoer. Du må opprette en ny GitLab-konto som vil bli administreres av %{group_name}."
@@ -722,6 +751,9 @@ msgstr "%{level_name} er ikke tillatt i en %{group_level_name}-gruppe."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} er ikke tillatt siden utgreiningskildeprosjektet har lavere synlighet."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} er ikke et gyldig tema"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "Den kan ikke brukes til å få tilgang til noen andre data."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "Sjetonger for personlig tilgang"
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr "Lær mer"
@@ -1979,9 +2002,6 @@ msgstr "Legg til CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Legg til CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Legg til GitLab til Slack"
-
msgid "Add Jaeger URL"
msgstr "Legg til Jaeger-URL"
@@ -1991,8 +2011,8 @@ msgstr "Legg til Kubernetes-klynge"
msgid "Add LICENSE"
msgstr "Legg til LICENSE"
-msgid "Add New Node"
-msgstr "Legg til ny node"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Legg til README"
@@ -2006,6 +2026,9 @@ msgstr "Legg til en %{type}"
msgid "Add a GPG key"
msgstr "Legg til en GPG-nøkkel"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr "Legg til en oppgave"
msgid "Add an SSH key"
msgstr "Legg til en SSH-nøkkel"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Legg til en eksisterende sak"
@@ -2189,9 +2215,6 @@ msgstr "Legg til systemkrok"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Legg til i Slack"
-
msgid "Add to board"
msgstr "Legg til på bord"
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Feil under innlasting av statistikken. Vennligst prøv igjen"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr "(Deaktivert)"
msgid "AdminUsers|(Internal)"
msgstr "(Intern)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Venter på godkjenning)"
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr "Det er deg!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Logg på"
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr "Brukeren kan ikke logge på."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Brukeren vil bli logget av"
@@ -2972,8 +3010,8 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr ""
@@ -3533,22 +3571,13 @@ msgstr "Tillat prosjekter innenfor denne gruppen å bruke Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Tillat forespørsler til det lokale nettverket fra kroker og tjenester."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Tillat forespørsler til det lokale nettverket fra systemkroker"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Tillat forespørsler til det lokale nettverket fra Webhooks og tjenester"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "En feil har oppstått"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "En feil oppstod under tillegging av et utkast til tråden."
@@ -3809,18 +3835,15 @@ msgstr "En feil oppstod under innhenting av jobbene."
msgid "An error occurred while fetching the latest pipeline."
msgstr "En feil oppstod under innhenting av den nyeste rørledningen."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "En feil oppstod under innhenting av lanseringene. Vennligst prøv igjen."
msgid "An error occurred while fetching this tab."
msgstr "En feil oppstod under innhenting av denne fanen."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "En feil oppstod under generering av brukernavn. Vennligst prøv igjen."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "En feil oppstod under henting av filer for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Legg til godkjennere"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr "Alle skannere"
@@ -4407,9 +4427,6 @@ msgstr "Godkjennertype"
msgid "ApprovalRule|Approvers"
msgstr "Godkjennere"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr "Velg alle"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Velg skannere"
@@ -4482,7 +4502,7 @@ msgstr "Alvorlighetsgrader"
msgid "ApprovalRule|Target branch"
msgstr "MÃ¥lgren"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr "Er du sikker på at du vil oppheve arkiveringen av dette prosjektet?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr "Er du sikker på at du vil %{action} %{name}?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "Er du sikker på at du vil fjerne denne identiteten?"
msgid "Are you sure you want to remove this list?"
msgstr "Er du sikker på at du vil fjerne denne listen?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Er du sikker du vil tilbakestille helsesjekksjetongen?"
@@ -4802,7 +4828,7 @@ msgstr "Spør igjen senere"
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "Avataren vil bli fjernet. Er du sikker?"
msgid "Average per day: %{average}"
msgstr "Gjennomsnitt per dag: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr "Basert på"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Nedenfor vil du finne alle de gruppene som er offentlige."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "%{user_name}, du bruker for øyeblikket %{plan_name}-planen."
-msgid "BillingPlans|Compare all plans"
-msgstr ""
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5457,9 +5489,6 @@ 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 "Oppgrader til GitLab %{planNameForUpgrade}"
-
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 "Mens GitLab avslutter tilgjengeligheten til BronSe-planen, kan du fortsatt fornye Bronse-abonnementet én siste gang før %{eoa_bronze_plan_end_date}. Vi tilbyr også en gratis oppgradering til Premium-abonnementet vårt i en kort tidsperiode (opptil 25 brukere)! Lær mer om endringene og tilbudene i vår %{announcement_link}."
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Bitbucket-import"
msgid "Blame"
msgstr "Ã…rsaksliste"
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Blokker bruker"
@@ -5931,18 +5969,12 @@ msgstr "Slett grener som er flettet sammen"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Å slette de flettede grenene kan ikke angres på. Er du sikker?"
@@ -5958,9 +5990,6 @@ msgstr "Ny gren"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Vurder å slå sammen denne grenen for å hindre tap av data."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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}."
-
msgid "Branches|diverged from upstream"
msgstr "avveket fra oppstrøm"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "av"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr "Utgivelser"
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Kan ikke flettes automatisk"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Kan ikke opprette misbruksrapporten. Brukeren har blitt slettet."
@@ -6915,6 +6956,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Faktureringsadresse"
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr "Etterkommer"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr "Klikk for å skjule"
msgid "Click to reveal"
msgstr "Klikk for å vise"
-msgid "Client authentication certificate"
-msgstr "Klientautentiseringssertifikat"
-
-msgid "Client authentication key"
-msgstr "Klientautentiseringsnøkkel"
-
-msgid "Client authentication key password"
-msgstr "Klientautentiseringsnøkkel-passord"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr "Lukket: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Klynge"
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr "Aldri"
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr "Commit (under redigering av commit-meldingen)"
msgid "Commit Message"
msgstr "Commit-beskjed"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr "Commit endringer"
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Komponent"
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr "Konfigurer sporing"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Konfigurer en %{codeStart}.gitlab-webide.yml%{codeEnd}-fil i %{codeStart}.gitlab%{codeEnd}-mappen for å begynne å bruke netterminalen. %{helpStart}Lær mer.%{helpEnd}"
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "Sett opp eksisterende installasjon"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "Sett opp kodelagerspeiling."
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "Konfigurer hvilke lister som skal vises for alle som besøker dette bordet"
msgid "Confirm"
msgstr "Bekreft"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Bekreft nytt passord"
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr "Handlinger"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr "Nyligst brukt"
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr "Ny opplasting"
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "Klarte ikke å finne designet."
@@ -9895,13 +9996,16 @@ msgstr "Klarte ikke å fjerne trigger."
msgid "Could not restore the group"
msgstr "Klarte ikke å gjenopprette gruppen"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr "Opprett iterasjon"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "Opprett liste"
@@ -10303,6 +10410,9 @@ msgstr "Opprettet av meg"
msgid "Created by:"
msgstr "Laget av:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "Opprettelsesdato"
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Dato"
@@ -10778,11 +10894,11 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
-msgstr "Median-ledetid"
+msgid "DORA4Metrics|Median (last %{days}d)"
+msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
msgstr ""
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr "Klarte ikke å opprette nettstedsprofilen. Vennligst prøv igjen."
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr "Klarte ikke å slette skannerprofilen. Vennligst oppfrisk siden, eller prøv igjen senere."
@@ -10889,9 +10999,6 @@ msgstr "Klarte ikke å slette nettstedsprofilen. Vennligst oppfrisk siden, eller
msgid "DastProfiles|Could not delete site profiles:"
msgstr "Klarte ikke å slette nettstedsprofiler:"
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "Klarte ikke å oppdatere nettstedsprofilen. Vennligst prøv igjen."
-msgid "DastProfiles|DAST Scan"
-msgstr "DAST-skanning"
-
msgid "DastProfiles|Debug messages"
msgstr "Avlusingsmeldinger"
@@ -10979,9 +11083,6 @@ msgstr "Ny nettstedsprofil"
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr "Kjør skanning"
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr "Lagre profil"
-msgid "DastProfiles|Saved Scans"
-msgstr "Lagrede skanninger"
-
-msgid "DastProfiles|Scan"
-msgstr "Skann"
-
msgid "DastProfiles|Scan mode"
msgstr "Skannemodus"
@@ -11039,9 +11131,6 @@ msgstr "Skanner-profiler"
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr "Velg gren"
@@ -11063,9 +11152,6 @@ msgstr "Nettstedstype"
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr "MÃ¥l"
-
msgid "DastProfiles|Target URL"
msgstr "MÃ¥l-URL"
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Distribueringer"
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Distribuer til …"
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "avbrutt"
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Begynn en gratis prøveperiode"
@@ -12622,7 +12738,7 @@ msgstr "Vis kilden"
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr "Rediger kommentar"
msgid "Edit Deploy Key"
msgstr "Rediger distribusjonsnøkkel"
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr "Skru på autentisering"
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Skru på vedlikeholdsmodus"
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr "Slutter den"
msgid "Ends: %{endsAt}"
msgstr "Slutter: %{endsAt}"
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Skriv inn fletteforespørsels-URL-er"
@@ -13683,6 +13808,9 @@ msgstr "Stopp miljø"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "Det oppstod en feil under innhenting av loggfilene. Vennligst prøv igjen."
@@ -13710,6 +13838,9 @@ msgstr "av %{avatar}"
msgid "Environments|protected"
msgstr "beskyttet"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Epos"
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr "Eksporterte krav"
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr "Ekstern ID"
@@ -14507,15 +14635,9 @@ msgstr "Ekstern URL"
msgid "External User:"
msgstr "Ekstern bruker:"
-msgid "External authentication"
-msgstr "Ekstern autentisering"
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr "Bruker-ID-er"
msgid "FeatureFlag|User List"
msgstr "Brukerliste"
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Feb"
@@ -15149,12 +15308,6 @@ msgstr "Filter"
msgid "Filter by"
msgstr "Filtrer etter"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrer etter %{issuable_type} som for øyeblikket er stengt."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr "Fant feil i din %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Fant feil i din .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Generer et standardsett med stempler"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Generer nøkkel"
@@ -15590,18 +15749,21 @@ msgstr "Forskjeller"
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo-noder"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr "Geo-innstillinger"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr "Legg til nettsted"
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr "Alle %{replicable_name}"
@@ -15692,6 +15857,9 @@ msgstr "Oppdag GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -15767,12 +15935,6 @@ 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"
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Ikke synkronisert enda"
@@ -15788,6 +15950,9 @@ msgstr "Ingenting å verifisere"
msgid "Geo|Offline"
msgstr "Frakoblet"
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Avventer synkronisering"
@@ -15821,16 +15986,19 @@ msgstr "Laste ned på nytt"
msgid "Geo|Remove"
msgstr "Fjern"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr "Fjern oppføring"
-msgid "Geo|Remove node"
-msgstr "Fjern node"
+msgid "Geo|Remove site"
+msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr "Sekundært nettsted"
msgid "Geo|Selective (%{syncLabel})"
msgstr "Selektiv (%{syncLabel})"
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr "Det er ingen %{replicable_type} å vise"
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr "sekundær"
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr "GitLab-eksport"
-msgid "GitLab for Slack"
-msgstr "GitLab for Slack"
-
msgid "GitLab group: %{source_link}"
msgstr "GitLab-gruppe: %{source_link}"
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr "Gitpod-URL"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr "GÃ¥ til forrige side"
@@ -16646,6 +16826,9 @@ msgstr "Gruppen %{group_name} ble planlagt for sletting."
msgid "Group %{group_name} was successfully created."
msgstr "Gruppen %{group_name} ble vellykket opprettet."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Gruppe-Git-LFS-status:"
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr "Gruppe-URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr "Gruppeprogram: %{name}"
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr "Gruppér jobber etter"
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr "Gruppemedlemmer"
@@ -16754,6 +16937,9 @@ msgstr "Gruppenavigasjon"
msgid "Group overview content"
msgstr "Gruppeoversikts-innhold"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr "Gruppeprosjekter"
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr "SCIM-sjetong"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr "Gyldig SAML-respons"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Din SCIM-sjetong"
-
msgid "GroupSAML|as %{access_level}"
msgstr "som %{access_level}"
@@ -17078,7 +17252,10 @@ msgstr "Søk i grupper"
msgid "GroupSelect|Select a group"
msgstr "Velg en gruppe"
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr "Skru av e-postvarsler"
msgid "GroupSettings|Disable group mentions"
msgstr "Skru av gruppenevninger"
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr "Denne innstillingen brukes på %{ancestor_group}. Du kan overstyre innst
msgid "GroupSettings|Transfer group"
msgstr "Overfør gruppe"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "Skjul verdiene"
msgid "Hide values"
msgstr "Skjul verdier"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr "Renhold"
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "Hvordan det virker"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "Jeg aksepterer %{terms_link}"
msgid "I forgot my password"
msgstr "Jeg glemte passordet mitt"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr "Identifikasjoner"
msgid "Identities"
msgstr "Identiteter"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr "Veldig vanskelig"
msgid "InProductMarketing|Very easy"
msgstr "Veldig enkelt"
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr "Hendelse"
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr "Legg til en integrasjon"
msgid "Integrations|Add namespace"
msgstr "Legg til et navneområde"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Alle detaljer"
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr "Nettleserbegrensninger"
-
msgid "Integrations|Comment detail:"
msgstr "Kommentardetalj:"
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr "Ingen tilgjengelige navneområder."
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr "Standard"
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "Intern URL (valgfritt)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr "Lisensfil"
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr "Lisensoversikt"
@@ -21384,9 +21600,6 @@ msgstr "Laster..."
msgid "Loading…"
msgstr "Laster …"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Lokalisering"
@@ -21402,6 +21615,9 @@ msgstr "LÃ¥s"
msgid "Lock %{issuableDisplayName}"
msgstr "LÃ¥s %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr "LÃ¥ser diskusjonen."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Logg på med et smartkort"
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr "Fletteforespørselshendelser"
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "MÃ¥neder"
msgid "More Information"
msgstr "Mer informasjon"
-msgid "More Slack commands"
-msgstr "Mere Slack-kommandoer"
-
msgid "More actions"
msgstr "Flere handlinger"
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr "Mere informasjon."
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "Mer enn %{number_commits_distance} commiter er annerledes fra %{default_branch}"
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr "%{strongOpen}alle%{strongClose} podder"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr "%{strongOpen}enhver%{strongClose} port"
-msgid "NetworkPolicies|.yaml"
-msgstr ".yaml"
-
msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml-modus"
@@ -23445,9 +23700,6 @@ msgstr "%{policyName}-retningslinjen ble vellykket endret"
msgid "NetworkPolicies|Policy definition"
msgstr "Retningslinjedefinisjon"
-msgid "NetworkPolicies|Rule"
-msgstr "Regel"
-
msgid "NetworkPolicies|Rule mode"
msgstr "Regelmodus"
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr "alle DNS-navn"
@@ -23984,6 +24233,9 @@ msgstr "Ingen milepæl"
msgid "No milestones to show"
msgstr "Ingen milepæler å vise"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Ingen andre stempler med sådan navn eller beskrivelse"
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr "Ingen profiler ble funnet"
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr "Ingen prosjekter ble funnet"
@@ -24077,7 +24332,7 @@ msgstr "Ingen sårbarheter er til stede"
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,8 +25241,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Utgående forespørsler"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr "Periode i sekunder"
@@ -25762,8 +26038,8 @@ msgstr "Tillatelser"
msgid "Permissions Help"
msgstr "Hjelp for tillatelser"
-msgid "Permissions, LFS, 2FA"
-msgstr "Tillatelser, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Personlig tilgangsnøkkel"
@@ -26029,9 +26305,6 @@ msgstr "Rørledninger"
msgid "Pipelines charts"
msgstr "Rørledningsdiagrammer"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr "Rørledninger for fletteforespørsler er konfigurert. En frakoblet rørledning kjører i sammenheng med fletteforespørselen, og ikke mot det innflettede resultatet. Lær mer i dokumentasjonen for rørledninger for innflettede resultater."
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,11 +26497,29 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr "ugyldig"
-msgid "Pipelines|parent"
-msgstr "underkategori av"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "Handlinger"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr "Plan:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Vennligst %{link_to_register} eller %{link_to_sign_in} for å kommentere"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr "Tidspreferanser"
msgid "Preferences|Use relative times"
msgstr "Bruk relative tidspunkter"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Forrige"
@@ -27001,6 +27307,9 @@ msgstr "Avatarbeskjærer"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Avataren vil blir fjernet. Er du sikker?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "Profil"
@@ -27025,9 +27334,6 @@ msgstr "By, land"
msgid "Profiles|Clear status"
msgstr "Tøm status"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Klikk på ikonene for å aktivere pålogging med en av følgende tjenester"
-
msgid "Profiles|Commit email"
msgstr "Commit-E-post"
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Fjern avatar"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Velg nytt profilbilde"
@@ -27250,9 +27559,6 @@ msgstr "2-trinnsautentisering"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Skriv inn din %{confirmationValue} for å bekrefte:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr "Oppdater profilinnstillinger"
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr "Universelt"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Internt"
@@ -27901,6 +28216,9 @@ msgstr "Fletteforespørsler"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "Fletteforslag"
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr "Overfør prosjekt"
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr "Offentlige rørledninger"
@@ -28867,7 +29179,7 @@ msgstr "Kjøp flere minutter"
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Kodelager-lagring"
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr "Forespørsler til disse domenene/adressene i det lokale nettverket vil være tillatt når lokale forespørsler fra kroker og tjenester ikke er tillatt. IP-områder som 1:0:0:0:0:0:0:0/124 eller 127.0.0.0/28 støttes. Domene-jokertegn støttes ikke for øyeblikket. Bruk komma, semikolon eller ny linje for å skille flere oppføringer. Tillatelseslisten kan inneholde maksimalt 1000 oppføringer. Domener bør bruke IDNA-koding. F.eks.: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr "PÃ¥krevd i dette prosjektet."
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Kravet %{reference} er lagt til"
@@ -30245,9 +30574,6 @@ msgstr "Løst av"
msgid "Resolved by %{name}"
msgstr "Løst av %{name}"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr "Svar"
@@ -30314,7 +30640,7 @@ msgstr "Fortsett"
msgid "Resync"
msgstr "Re-synk"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr "Tilbakekall"
msgid "Revoked"
msgstr "Tilbakekalt"
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Veikart"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Rolle"
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr "Arkitektur"
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr "Beskrivelse"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr "IP-adresse"
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr "Frakoblet"
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr "PÃ¥ nett"
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revisjon"
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Løpere"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr "SSL-verifisering:"
msgid "SSL verification"
msgstr "SSL-verifisering"
-msgid "SVG illustration"
-msgstr "SVG-illustrasjon"
-
msgid "Satisfied"
msgstr "Fornøyd"
@@ -31026,9 +31367,6 @@ msgstr "Søk"
msgid "Search GitLab"
msgstr "Søk på GitLab"
-msgid "Search Jira issues"
-msgstr "Søk blant Jira-saker"
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr "Lisenssjekk"
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr "%{branches} %{plural}"
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr "Hvis du bruker Auto DevOps, vil ikke din %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd}-filen bli oppdatert hvis du endrer en retningslinje i denne delen. Auto DevOps-brukere bør gjøre endringer ved å følge dokumentasjonen for %{linkStart}Container-nettverksretningslinjer%{linkEnd}."
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr "Seneste skanning"
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr "Regel"
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr "vis resultater"
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr "+%{count} til"
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr "Retningslinjetype"
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} og %{secondProject}"
@@ -31942,9 +32361,6 @@ msgstr "Velg arkivformat"
msgid "Select Git revision"
msgstr "Velg Git-revisjon"
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr "Velg side"
@@ -32332,8 +32748,8 @@ msgstr "Tjenestedesk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr "Tjenestedesken lar folk opprette saksrapporter i din GitLab-forekomst uten å ha sin egen brukerkonto. Det sørger for en unik e-postadresse for sluttbrukere til å opprette saksrapporter i et prosjekt. Svar kan sendes enten via GitLab-grensesnittet eller via e-post. Sluttbrukere ser kun tråden via e-post."
-msgid "Service URL"
-msgstr "Tjeneste-URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr "Sett opp CI/CD"
msgid "Set up Jira Integration"
msgstr "Sett opp Jira-integrering"
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr "Vis all aktivitet"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr "Vis alle saker."
@@ -32727,6 +33140,9 @@ msgstr "Vis arkiverte prosjekter"
msgid "Show archived projects only"
msgstr "Vis kun arkiverte prosjekter"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Vis kommando"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr "Vis bare kommentarer"
-msgid "Show commit description"
-msgstr "Vis commit-beskrivelse"
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr "Vis liste"
msgid "Show one file at a time"
msgstr "Vis én fil om gangen"
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr "Vis «Lukket»-listen"
@@ -32806,7 +33222,7 @@ msgstr "Viser alle saker"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr "Logg av og registrer"
msgid "Sign up"
msgstr "Registrer deg"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr "Slack-applikasjon"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Noe gikk galt. Vennligst prøv igjen."
msgid "Something went wrong. Try again later."
msgstr "Noe gikk galt. Prøv igjen senere."
-msgid "Sorry, no epics matched your search"
-msgstr "Beklager, ingen eposer samsvarer med søket ditt"
-
msgid "Sorry, no projects matched your search"
msgstr "Beklager, ingen prosjekter samsvarer med søket ditt"
@@ -33376,9 +33816,6 @@ msgstr "Siste kontakt"
msgid "SortOptions|Last created"
msgstr "Sist opprettet"
-msgid "SortOptions|Last updated"
-msgstr "Senest oppdatert"
-
msgid "SortOptions|Least popular"
msgstr "Minst populær"
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Start søk"
@@ -33754,6 +34194,9 @@ msgstr "Starter: %{startsAt}"
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "PÃ¥meldt"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr "Legg til seter"
@@ -34204,9 +34671,6 @@ msgstr "Prøveperiodens sluttdato"
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr "Oppgrader"
-
msgid "SubscriptionTable|Usage"
msgstr "Benyttelse"
@@ -34375,9 +34839,6 @@ msgstr "Oppsummering / Notat"
msgid "Sunday"
msgstr "Søndag"
-msgid "SuperSonics|Activate cloud license"
-msgstr "Aktiver skylisens"
-
msgid "SuperSonics|Activate subscription"
msgstr "Aktiver abonnement"
@@ -34402,6 +34863,9 @@ msgstr "Skylisensiering"
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr "Begynn gratis prøveperiode"
msgid "SuperSonics|Subscription details"
msgstr "Abonnementsdetaljer"
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr "Synkroniser abonnementsdetaljer"
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Støtte"
@@ -34750,6 +35229,9 @@ msgstr "MÃ¥lgren"
msgid "Target-Branch"
msgstr "MÃ¥lgren"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr "Oppgave-ID: %{elastic_task}"
@@ -34822,6 +35304,9 @@ msgstr "Vilkår for serviceavtale og personvernregler"
msgid "Terms of Service and Privacy Policy"
msgstr "Bruksvilkår og personvern"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr "Terraform"
@@ -34992,6 +35477,9 @@ msgstr "Test"
msgid "Test Cases"
msgstr "Testtilfeller"
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr "Det var det, bra jobbet!"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr "Snowplow-infokapseldomenet."
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr "URL-en til Jenkins-tjeneren."
@@ -35220,9 +35699,6 @@ msgstr "URL-en burde starte med http:// eller https://"
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "X.509-sertifikatet som skal brukes når det kreves gjensidig TLS for å kommunisere med den eksterne autorisasjonstjenesten. Hvis det er tomt, blir tjenersertifikatet fortsatt validert når du besøker den gjennom HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr "Programmet vil bli brukt der klienthemmeligheten kan holdes konfidensiell. Apper designet for mobiler, og enkeltsideapper, blir ansett som ikke-konfidensielle."
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr "Passordet til Jenkins-tjeneren."
@@ -35516,9 +35992,6 @@ msgstr "Rørledningen har blitt slettet"
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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr "En feil oppstod under innhenting av %{replicableType}"
msgid "There was an error fetching the Geo Settings"
msgstr "Det oppstod en feil under innhenting av Geo-innstillingene"
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,8 +36412,8 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
-msgstr "En feil oppstod under lagring av denne geo-noden."
+msgid "There was an error saving this Geo Site"
+msgstr ""
msgid "There was an error saving your changes."
msgstr "En feil oppstod under lagring av endringene dine."
@@ -36023,9 +36496,6 @@ msgstr "Disse vil bli sendt til %{email} som et vedlegg når de er ferdige."
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr "Tredjepartstilbud"
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Denne %{issuableDisplayName} er låst. Kun prosjektmedlemmer kan kommentere."
@@ -36149,6 +36619,9 @@ msgstr "Denne commiten ble signert med en %{strong_open}uverifisert%{strong_clos
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr "Denne gruppen er knyttet til et abonnement"
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr "Dette prosjektet"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Dette prosjektet er lisensiert som %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Denne innstillingen kan overstyres i hvert prosjekt."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "Dette abonnementet er for"
@@ -36740,9 +37225,6 @@ msgstr "Tid fra siste commit til innfletting"
msgid "Time in seconds"
msgstr "Tid i sekunder"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr "Importeringstid: %{importTime}"
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "For å legge til en SSH-nøkkel må du %{generate_link_start}generere en%{link_end}, eller bruke en %{existing_link_start}eksisterende nøkkel%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr "For å oppdatere utdrag med flere filer, må du bruke `files`-parameteren"
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr "For å utvide søket, endre eller fjerne filtrene ovenfor"
msgid "To widen your search, change or remove filters above."
msgstr "For å utvide søket, endre eller fjerne filtrene ovenfor."
-msgid "To widen your search, change or remove filters."
-msgstr "For å utvide søket, endre eller fjerne filtre."
-
msgid "To-Do List"
msgstr "Gjøremålsliste"
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr "Firmanavn"
@@ -37490,15 +37963,9 @@ msgstr "Land"
msgid "Trial|Dismiss"
msgstr "Avvis"
-msgid "Trial|First name"
-msgstr "Fornavn"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr "Etternavn"
-
msgid "Trial|Number of employees"
msgstr "Antall ansatte"
@@ -37565,6 +38032,12 @@ msgstr "Triggeren ble vellykket oppdatert."
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr "Oppdatert"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Oppdatert %{updated_at} av %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "Oppdateringer"
@@ -38105,6 +38581,9 @@ msgstr "Oppgrader planen din"
msgid "Upload"
msgstr "Last opp"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Last opp CSV-fil"
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr "Versjon %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
msgstr "Versjon %{versionNumber} (nyeste)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "Vis dokumentasjon"
@@ -39218,6 +39712,9 @@ msgstr[1] "Vis offentlige GPG-nøkler"
msgid "View replaced file @ "
msgstr "Vis erstattet fil @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr "Vis innstilling"
@@ -39443,6 +39940,9 @@ msgstr "Faktisk respons"
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "Ytterligere info"
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr "Last ned"
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Bevis"
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr "Identifikator"
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "identifikatorer"
@@ -39512,6 +40021,9 @@ msgstr "Bilde"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Lenker"
@@ -39524,6 +40036,9 @@ msgstr "Navnefelt"
msgid "Vulnerability|Project"
msgstr "Prosjekt"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr "Skannerleverandør"
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Verktøy"
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "ADVARSEL:"
@@ -39743,6 +40270,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr "Webhook-hjelp"
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "Kommentarer"
@@ -39785,6 +40354,9 @@ msgstr "Rørledningshendelser"
msgid "Webhooks|Push events"
msgstr "Pushhendelser"
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr ""
@@ -39815,55 +40387,10 @@ msgstr "Trigger"
msgid "Webhooks|URL"
msgstr "URL"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr ""
-
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr ""
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr ""
-
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr "Du kan også teste din %{gitlab_ci_yml} i %{lint_link_start}CI Lint%{lin
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Du kan også laste opp eksisterende filer fra datamaskinen din ved å følge instruksjonene nedenfor."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Du har ikke tillatelse til å forlate denne %{namespaceType}."
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Du har nådd prosjektgrensen"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr "Du forlot «%{membershipable_human_name}»-%{source_type}."
msgid "You may close the milestone now."
msgstr "Du kan lukke milepælen nå."
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,8 +41726,8 @@ msgstr "Navnet ditt"
msgid "Your new %{type}"
msgstr "Din nye %{type}"
-msgid "Your new SCIM token"
-msgstr "Din nye SCIM-sjetong"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr "Din nye kommentar"
@@ -41181,9 +41735,6 @@ msgstr "Din nye kommentar"
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "Abonnementet ditt har utløpt!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr "godkjent av: "
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr "forpliktet"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr "opprettet %{timeAgo}"
@@ -41995,6 +42554,9 @@ msgstr "mislyktes"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr "gruppe"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "gruppemedlemmer"
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr "laster"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "låst av %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "logg inn"
-
msgid "manual"
msgstr "manual"
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Vennligst gjenopprett den eller bruk en annen %{missingBranchName}-fane"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Fletting mislyktes."
@@ -42523,6 +43091,9 @@ msgstr "Ã…pne i nett-IDE"
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Endringene ble flettet inn i"
@@ -42577,9 +43151,6 @@ msgstr "Endringene ble ikke flettet inn i"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Kildegrenen har blitt slettet"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Passordet ditt"
-msgid "mrWidget|branch does not exist."
-msgstr "grenen eksisterer ikke."
-
msgid "mrWidget|into"
msgstr "inni"
@@ -42899,9 +43467,6 @@ msgstr "kodelager:"
msgid "required"
msgstr "påkrevd"
-msgid "reset it."
-msgstr "tilbakestille den."
-
msgid "satisfied"
msgstr "tilfredsstilt"
@@ -43082,9 +43647,6 @@ msgstr "brukerens profilbilde"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "brukerinnstillinger"
-
msgid "username"
msgstr "brukernavn"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 4057a8d0ea8..928cebf3594 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "door"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/or_IN/gitlab.po b/locale/or_IN/gitlab.po
new file mode 100644
index 00000000000..8690b4dbf35
--- /dev/null
+++ b/locale/or_IN/gitlab.po
@@ -0,0 +1,43744 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Odia\n"
+"Language: or_IN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Project-ID: 288872\n"
+"X-Crowdin-Language: or\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 6\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
+
+msgid " %{start} to %{end}"
+msgstr ""
+
+msgid " (from %{timeoutSource})"
+msgstr ""
+
+msgid " Collected %{time}"
+msgstr ""
+
+msgid " Please sign in."
+msgstr ""
+
+msgid " Target Path"
+msgstr ""
+
+msgid " Try to %{action} this file again."
+msgstr ""
+
+msgid " Type"
+msgstr ""
+
+msgid " You need to do this before %{grace_period_deadline}."
+msgstr ""
+
+msgid " and "
+msgstr ""
+
+msgid " and %{sliced}"
+msgstr ""
+
+msgid " or "
+msgstr ""
+
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
+
+msgid " or references (e.g. path/to/project!merge_request_id)"
+msgstr ""
+
+msgid " reacted with :%{name}:"
+msgstr ""
+
+msgid "\"%{path}\" did not exist on \"%{ref}\""
+msgstr ""
+
+msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
+msgstr ""
+
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
+msgid "#general, #development"
+msgstr ""
+
+msgid "%d Alert"
+msgid_plural "%d Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Alert:"
+msgid_plural "%d Alerts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Approval"
+msgid_plural "%d Approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Module"
+msgid_plural "%d Modules"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Other"
+msgid_plural "%d Others"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Package"
+msgid_plural "%d Packages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Scanned URL"
+msgid_plural "%d Scanned URLs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d URL scanned"
+msgid_plural "%d URLs scanned"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver"
+msgid_plural "%d approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver (you've approved)"
+msgid_plural "%d approvers (you've approved)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d child epic"
+msgid_plural "%d child epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d code quality issue"
+msgid_plural "%d code quality issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment on this commit"
+msgid_plural "%d comments on this commit"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commenter"
+msgid_plural "%d commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit author"
+msgid_plural "%d commit authors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit,"
+msgid_plural "%d commits,"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d completed issue"
+msgid_plural "%d completed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d epic"
+msgid_plural "%d epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error"
+msgid_plural "%d errors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error found:"
+msgid_plural "%d errors found:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed"
+msgid_plural "%d failed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d inaccessible merge request"
+msgid_plural "%d inaccessible merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue in this group"
+msgid_plural "%d issues in this group"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue successfully imported with the label"
+msgid_plural "%d issues successfully imported with the label"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+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] ""
+
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d milestone"
+msgid_plural "%d milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d pending comment"
+msgid_plural "%d pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+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] ""
+
+msgid "%d previously merged commit"
+msgid_plural "%d previously merged commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project"
+msgid_plural "%d projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project selected"
+msgid_plural "%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d request with warnings"
+msgid_plural "%d requests with warnings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d shard selected"
+msgid_plural "%d shards selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag"
+msgid_plural "%d tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag per image name"
+msgid_plural "%d tags per image name"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d token has expired"
+msgid_plural "%d tokens have expired"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unassigned issue"
+msgid_plural "%d unassigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unresolved thread"
+msgid_plural "%d unresolved threads"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability"
+msgid_plural "%d vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability dismissed"
+msgid_plural "%d vulnerabilities dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability updated"
+msgid_plural "%d vulnerabilities updated"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d warning found:"
+msgid_plural "%d warnings found:"
+msgstr[0] ""
+msgstr[1] ""
+
+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] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
+msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
+msgstr ""
+
+msgid "%{author_link} wrote:"
+msgstr ""
+
+msgid "%{authorsName}'s thread"
+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 "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
+msgstr ""
+
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_authored_timeago}"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
+msgstr ""
+
+msgid "%{completedCount} completed weight"
+msgstr ""
+
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{completedWeight} of %{totalWeight} weight completed"
+msgstr ""
+
+msgid "%{cores} cores"
+msgstr ""
+
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
+msgid "%{count} LOC/commit"
+msgstr ""
+
+msgid "%{count} approval required from %{name}"
+msgid_plural "%{count} approvals required from %{name}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} files touched"
+msgstr ""
+
+msgid "%{count} item"
+msgid_plural "%{count} items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} items per page"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} more release"
+msgid_plural "%{count} more releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} of %{required} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} of %{total}"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} related %{pluralized_subject}: %{links}"
+msgstr ""
+
+msgid "%{count} selected"
+msgstr ""
+
+msgid "%{count} total weight"
+msgstr ""
+
+msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
+msgstr ""
+
+msgid "%{dashboard_path} could not be found."
+msgstr ""
+
+msgid "%{days} days until tags are automatically removed"
+msgstr ""
+
+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 ""
+
+msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
+msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
+msgstr ""
+
+msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
+msgstr ""
+
+msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
+msgstr ""
+
+msgid "%{due_date} (Past due)"
+msgstr ""
+
+msgid "%{duration}ms"
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to upload a file again."
+msgstr ""
+
+msgid "%{emailPrefix}@company.com"
+msgstr ""
+
+msgid "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
+msgstr ""
+
+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_name} activity"
+msgstr ""
+
+msgid "%{group_name} group members"
+msgstr ""
+
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
+msgstr ""
+
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
+msgid "%{host} sign-in from new location"
+msgstr ""
+
+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 ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{issueType} actions"
+msgstr ""
+
+msgid "%{issuesSize} with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
+msgstr ""
+
+msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
+msgstr ""
+
+msgid "%{labelStart}Class:%{labelEnd} %{class}"
+msgstr ""
+
+msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
+msgstr ""
+
+msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
+msgstr ""
+
+msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
+msgstr ""
+
+msgid "%{labelStart}File:%{labelEnd} %{file}"
+msgstr ""
+
+msgid "%{labelStart}Image:%{labelEnd} %{image}"
+msgstr ""
+
+msgid "%{labelStart}Method:%{labelEnd} %{method}"
+msgstr ""
+
+msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+msgstr ""
+
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr ""
+
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgstr ""
+
+msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
+msgstr ""
+
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{label_for_message} unavailable"
+msgstr ""
+
+msgid "%{learn_more_link}."
+msgstr ""
+
+msgid "%{lessThan} 1 hour"
+msgstr ""
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "%{link_start}Learn more%{link_end} about roles."
+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."
+msgstr ""
+
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
+
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
+msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
+msgstr ""
+
+msgid "%{listToShow}, and %{awardsListLength} more"
+msgstr ""
+
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
+msgstr ""
+
+msgid "%{mergeLength}/%{usersLength} can merge"
+msgstr ""
+
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
+msgid "%{model_name} not found"
+msgstr ""
+
+msgid "%{mrText}, this issue will be closed automatically."
+msgstr ""
+
+msgid "%{name_with_link} namespace 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_with_link} namespace has run out of Shared Runner Pipeline minutes. No new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name} (Busy)"
+msgstr ""
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
+msgid "%{name} is already being used for another emoji"
+msgstr ""
+
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
+msgid "%{name} is scheduled for %{action}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{name}(%{url}) namespace has %{percent} or less Shared Runner Pipeline minutes remaining. After it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name}(%{url}) namespace has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name}, confirm your email address now!"
+msgstr ""
+
+msgid "%{no_of_days} day"
+msgid_plural "%{no_of_days} days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{oneMonthAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneWeekAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneYearAgo} - %{today}"
+msgstr ""
+
+msgid "%{openedEpics} open, %{closedEpics} closed"
+msgstr ""
+
+msgid "%{openedIssues} open, %{closedIssues} closed"
+msgstr ""
+
+msgid "%{percentage}%% weight completed"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{percent}%{percentSymbol} complete"
+msgstr ""
+
+msgid "%{placeholder} is not a valid color scheme"
+msgstr ""
+
+msgid "%{placeholder} is not a valid theme"
+msgstr ""
+
+msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
+msgid "%{ref} cannot be added: %{error}"
+msgstr ""
+
+msgid "%{releases} release"
+msgid_plural "%{releases} releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{remaining_approvals} left"
+msgstr ""
+
+msgid "%{reportType} %{status}"
+msgstr ""
+
+msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
+msgstr ""
+
+msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
+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 "%{runner} created %{timeago}"
+msgstr ""
+
+msgid "%{scope} results for term '%{term}'"
+msgstr ""
+
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
+msgid "%{seconds}s"
+msgstr ""
+
+msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{securityScanner} result is not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}"
+msgstr ""
+
+msgid "%{size} %{unit}"
+msgstr ""
+
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
+msgstr ""
+
+msgid "%{spanStart}in%{spanEnd} %{errorFn}"
+msgstr ""
+
+msgid "%{start} to %{end}"
+msgstr ""
+
+msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
+msgstr ""
+
+msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} approval rule%{strong_end} requires eligible members to approve before merging."
+msgid_plural "%{strong_start}%{count} approval rules%{strong_end} require eligible members to approve before merging."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} eligible member%{strong_end} must approve to merge."
+msgid_plural "%{strong_start}%{count} eligible members%{strong_end} must approve to merge."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Storage"
+msgstr ""
+
+msgid "%{strong_start}%{release_count}%{strong_end} Release"
+msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{tabname} changed"
+msgstr ""
+
+msgid "%{tags} tag per image name"
+msgstr ""
+
+msgid "%{tags} tags per image name"
+msgstr ""
+
+msgid "%{tag}-%{evidence}-%{filename}"
+msgstr ""
+
+msgid "%{template_project_id} is unknown or invalid"
+msgstr ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{timebox_name} should belong either to a project or a group."
+msgstr ""
+
+msgid "%{timebox_type} does not support burnup charts"
+msgstr ""
+
+msgid "%{timebox_type} must have a start and due date"
+msgstr ""
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalWeight} total weight"
+msgstr ""
+
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
+msgid "%{total} open issue weight"
+msgstr ""
+
+msgid "%{total} warnings found: showing first %{warningsDisplayed}"
+msgstr ""
+
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+msgstr ""
+
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
+msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project_link}: "
+msgstr ""
+
+msgid "%{user_name} (%{user_username}) was removed from the following escalation policies 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 ""
+
+msgid "%{username}'s avatar"
+msgstr ""
+
+msgid "%{user} created a merge request: %{mr_link}"
+msgstr ""
+
+msgid "%{user} created an epic: %{epic_link}"
+msgstr ""
+
+msgid "%{user} created an issue: %{issue_link}"
+msgstr ""
+
+msgid "%{value} is not included in the list"
+msgstr ""
+
+msgid "%{value} s"
+msgstr ""
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+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 ""
+
+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 ""
+
+msgid "%{widget} options"
+msgstr ""
+
+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 ""
+
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{name}' Value Stream created"
+msgstr ""
+
+msgid "'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "'%{template_name}' is unknown or invalid"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
+msgid "(%{value}) has already been taken"
+msgstr ""
+
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
+msgid "(Group Managed Account)"
+msgstr ""
+
+msgid "(No changes)"
+msgstr ""
+
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(expired)"
+msgstr ""
+
+msgid "(leave blank if you don't want to change it)"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(optional)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(this user)"
+msgstr ""
+
+msgid "(we need your current password to confirm your changes)"
+msgstr ""
+
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
+msgid "*Required"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{approvers} more approvers"
+msgstr ""
+
+msgid "+%{extra} more"
+msgstr ""
+
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
+msgid "+%{tags} more"
+msgstr ""
+
+msgid ", and "
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
+msgid "- Available to run jobs."
+msgstr ""
+
+msgid "- Event"
+msgid_plural "- Events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- Not available to run jobs."
+msgstr ""
+
+msgid "- Select -"
+msgstr ""
+
+msgid "- User"
+msgid_plural "- Users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- of - weight completed"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "."
+msgstr ""
+
+msgid "/"
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "0t1DgySidms"
+msgstr ""
+
+msgid "1 Day"
+msgid_plural "%d Days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Issue"
+msgid_plural "%d Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day selected"
+msgid_plural "%d days selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 deploy key"
+msgid_plural "%d deploy keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 follower"
+msgid_plural "%{count} followers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%{num} users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
+msgid "1000+"
+msgstr ""
+
+msgid "192.168.0.0/24"
+msgstr ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "20-29 contributions"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FADevice|Registered On"
+msgstr ""
+
+msgid "3 days"
+msgstr ""
+
+msgid "3 hours"
+msgstr ""
+
+msgid "30 days"
+msgstr ""
+
+msgid "30 minutes"
+msgstr ""
+
+msgid "30+ contributions"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "7 days"
+msgstr ""
+
+msgid "8 hours"
+msgstr ""
+
+msgid ":%{startLine} to %{endLine}"
+msgstr ""
+
+msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
+msgstr ""
+
+msgid "A .NET Core console application template, customizable for any .NET Core project"
+msgstr ""
+
+msgid "A CI/CD pipeline must run and be successful before merge."
+msgstr ""
+
+msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Gitpod configured Webapplication in Spring and Java"
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
+msgstr ""
+
+msgid "A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
+msgstr ""
+
+msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
+msgstr ""
+
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
+msgid "A complete DevOps platform"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A different reason"
+msgstr ""
+
+msgid "A file has been changed."
+msgstr ""
+
+msgid "A file was not found."
+msgstr ""
+
+msgid "A file with '%{file_name}' already exists in %{branch} branch"
+msgstr ""
+
+msgid "A group is a collection of several projects"
+msgstr ""
+
+msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
+msgstr ""
+
+msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
+msgstr ""
+
+msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
+msgstr ""
+
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
+msgstr ""
+
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A merge request hasn't yet been merged"
+msgstr ""
+
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
+msgstr ""
+
+msgid "A new impersonation token has been created."
+msgstr ""
+
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
+msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A platform value can be web, mob or app."
+msgstr ""
+
+msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
+msgstr ""
+
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+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’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 ""
+
+msgid "A quarterly reconciliation is due on %{date}"
+msgstr ""
+
+msgid "A ready-to-go template for use with Android apps"
+msgstr ""
+
+msgid "A ready-to-go template for use with iOS Swift apps"
+msgstr ""
+
+msgid "A rebase is already in progress."
+msgstr ""
+
+msgid "A sign-in to your account has been made from the following IP address: %{ip}"
+msgstr ""
+
+msgid "A title is required"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
+msgstr ""
+
+msgid "API"
+msgstr ""
+
+msgid "API Fuzzing"
+msgstr ""
+
+msgid "API Fuzzing Configuration"
+msgstr ""
+
+msgid "API Help"
+msgstr ""
+
+msgid "API Token"
+msgstr ""
+
+msgid "API key"
+msgstr ""
+
+msgid "API?"
+msgstr ""
+
+msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
+msgstr ""
+
+msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
+msgstr ""
+
+msgid "APIFuzzing|Choose a method"
+msgstr ""
+
+msgid "APIFuzzing|Choose a profile"
+msgstr ""
+
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Customize your project's API fuzzing configuration options and copy the code snippet to your .gitlab-ci.yml file to apply any changes. Note that this tool does not reflect or update your .gitlab-ci.yml file automatically. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Enable authentication"
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
+msgstr ""
+
+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|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
+msgstr ""
+
+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|Make sure your credentials are secured"
+msgstr ""
+
+msgid "APIFuzzing|Password for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|Predefined profiles"
+msgstr ""
+
+msgid "APIFuzzing|Scan mode"
+msgstr ""
+
+msgid "APIFuzzing|Scan profile"
+msgstr ""
+
+msgid "APIFuzzing|Show code snippet for the profile"
+msgstr ""
+
+msgid "APIFuzzing|Target URL"
+msgstr ""
+
+msgid "APIFuzzing|There are three ways to perform scans."
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all stages"
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
+msgstr ""
+
+msgid "APIFuzzing|Username for basic authentication"
+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 ""
+
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS Secret Access Key"
+msgstr ""
+
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
+
+msgid "Abort"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Abuse reports notification email"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Acceptable for use in this project"
+msgstr ""
+
+msgid "Access Git repositories or the API."
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied for your LDAP account."
+msgstr ""
+
+msgid "Access denied: %{error}"
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access expires"
+msgstr ""
+
+msgid "Access forbidden. Check your access level."
+msgstr ""
+
+msgid "Access granted"
+msgstr ""
+
+msgid "Access key ID"
+msgstr ""
+
+msgid "Access requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
+msgstr ""
+
+msgid "AccessDropdown|Deploy Keys"
+msgstr ""
+
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "AccessTokens|Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Are you sure?"
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Copy feed token"
+msgstr ""
+
+msgid "AccessTokens|Copy incoming email token"
+msgstr ""
+
+msgid "AccessTokens|Copy static object token"
+msgstr ""
+
+msgid "AccessTokens|Created"
+msgstr ""
+
+msgid "AccessTokens|Feed token"
+msgstr ""
+
+msgid "AccessTokens|Incoming email token"
+msgstr ""
+
+msgid "AccessTokens|It cannot be used to access any other data."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
+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, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
+msgid "AccessTokens|Personal Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Static object token"
+msgstr ""
+
+msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
+msgstr ""
+
+msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
+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 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 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 authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
+msgstr ""
+
+msgid "AccessibilityReport|Learn more"
+msgstr ""
+
+msgid "AccessibilityReport|Message: %{message}"
+msgstr ""
+
+msgid "AccessibilityReport|New"
+msgstr ""
+
+msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account ID"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Account:"
+msgstr ""
+
+msgid "Account: %{account}"
+msgstr ""
+
+msgid "AccountValidation|Fix your pipelines by validating your account"
+msgstr ""
+
+msgid "AccountValidation|I'll bring my own runners"
+msgstr ""
+
+msgid "AccountValidation|If you no longer wish to receive marketing emails from us,"
+msgstr ""
+
+msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, you'll need to validate your account using one of our verification options. If you prefer not to, you can run pipelines by bringing your own runners and disabling shared runners for your project."
+msgstr ""
+
+msgid "AccountValidation|Learn more."
+msgstr ""
+
+msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
+msgstr ""
+
+msgid "AccountValidation|Validate your account"
+msgstr ""
+
+msgid "AccountValidation|Verification is required to discourage and reduce the abuse on GitLab infrastructure. If you verify with a credit or debit card, %{strong_start}GitLab will not charge your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
+msgstr ""
+
+msgid "AccountValidation|unsubscribe"
+msgstr ""
+
+msgid "AccountValidation|you may %{unsubscribe_link} at any time."
+msgstr ""
+
+msgid "Action"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activated on"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Active chat names (%{count})"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Activity|An error occured while retrieving activity. Reload the page to try again."
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add LICENSE"
+msgstr ""
+
+msgid "Add New Site"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add Zoom meeting"
+msgstr ""
+
+msgid "Add a %{type}"
+msgstr ""
+
+msgid "Add a GPG key"
+msgstr ""
+
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
+msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
+msgstr ""
+
+msgid "Add a bullet list"
+msgstr ""
+
+msgid "Add a collapsible section"
+msgstr ""
+
+msgid "Add a comment to this line"
+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 ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a horizontal rule"
+msgstr ""
+
+msgid "Add a line"
+msgstr ""
+
+msgid "Add a link"
+msgstr ""
+
+msgid "Add a link to Grafana"
+msgstr ""
+
+msgid "Add a new issue"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
+msgid "Add a related issue"
+msgstr ""
+
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add a task list"
+msgstr ""
+
+msgid "Add a title..."
+msgstr ""
+
+msgid "Add a to do"
+msgstr ""
+
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
+msgid "Add an existing issue"
+msgstr ""
+
+msgid "Add an impersonation token"
+msgstr ""
+
+msgid "Add another link"
+msgstr ""
+
+msgid "Add approval rule"
+msgstr ""
+
+msgid "Add approvers"
+msgstr ""
+
+msgid "Add bold text"
+msgstr ""
+
+msgid "Add broadcast message"
+msgstr ""
+
+msgid "Add child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
+msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
+msgstr ""
+
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
+msgid "Add deploy freeze"
+msgstr ""
+
+msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
+msgid "Add email participant(s)"
+msgstr ""
+
+msgid "Add environment"
+msgstr ""
+
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add italic text"
+msgstr ""
+
+msgid "Add key"
+msgstr ""
+
+msgid "Add label(s)"
+msgstr ""
+
+msgid "Add list"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add or remove previously merged commits"
+msgstr ""
+
+msgid "Add or subtract spent time"
+msgstr ""
+
+msgid "Add previously merged commits"
+msgstr ""
+
+msgid "Add project"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add request manually"
+msgstr ""
+
+msgid "Add strikethrough text"
+msgstr ""
+
+msgid "Add suggestion to batch"
+msgstr ""
+
+msgid "Add system hook"
+msgstr ""
+
+msgid "Add text to the sign-in page. Markdown enabled."
+msgstr ""
+
+msgid "Add to board"
+msgstr ""
+
+msgid "Add to epic"
+msgstr ""
+
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add to tree"
+msgstr ""
+
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
+msgid "Add trigger"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Add variable"
+msgstr ""
+
+msgid "Add vulnerability finding"
+msgstr ""
+
+msgid "Add webhook"
+msgstr ""
+
+msgid "Add/remove"
+msgstr ""
+
+msgid "AddContextCommits|Add previously merged commits"
+msgstr ""
+
+msgid "AddContextCommits|Add/remove"
+msgstr ""
+
+msgid "AddMember|Emails cannot be blank"
+msgstr ""
+
+msgid "AddMember|Invite email is invalid"
+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 ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
+msgid "Added"
+msgstr ""
+
+msgid "Added %{epic_ref} as a child epic."
+msgstr ""
+
+msgid "Added %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Added a to do."
+msgstr ""
+
+msgid "Added an issue to an epic."
+msgstr ""
+
+msgid "Added for this merge request"
+msgstr ""
+
+msgid "Added in this version"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional Metadata"
+msgstr ""
+
+msgid "Additional minutes"
+msgstr ""
+
+msgid "Additional minutes:"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Additional text for the sign-in and Help page."
+msgstr ""
+
+msgid "Additional text to show on the Help page"
+msgstr ""
+
+msgid "Additional text to show on the sign-in page"
+msgstr ""
+
+msgid "Address"
+msgstr ""
+
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds %{labels} %{label_text}."
+msgstr ""
+
+msgid "Adds a Zoom meeting."
+msgstr ""
+
+msgid "Adds a to do."
+msgstr ""
+
+msgid "Adds an issue to an epic."
+msgstr ""
+
+msgid "Adds email participant(s)."
+msgstr ""
+
+msgid "Adjust how frequently the GitLab UI polls for updates."
+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 ""
+
+msgid "Admin Mode"
+msgstr ""
+
+msgid "Admin Note"
+msgstr ""
+
+msgid "Admin Notifications"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin Section"
+msgstr ""
+
+msgid "Admin mode already enabled"
+msgstr ""
+
+msgid "Admin mode disabled"
+msgstr ""
+
+msgid "Admin mode enabled"
+msgstr ""
+
+msgid "Admin navigation"
+msgstr ""
+
+msgid "Admin notes"
+msgstr ""
+
+msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
+msgstr ""
+
+msgid "AdminArea|Active users"
+msgstr ""
+
+msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
+msgstr ""
+
+msgid "AdminArea|Billable users"
+msgstr ""
+
+msgid "AdminArea|Blocked users"
+msgstr ""
+
+msgid "AdminArea|Bots"
+msgstr ""
+
+msgid "AdminArea|Components"
+msgstr ""
+
+msgid "AdminArea|Developer"
+msgstr ""
+
+msgid "AdminArea|Features"
+msgstr ""
+
+msgid "AdminArea|Get security updates from GitLab and stay up to date"
+msgstr ""
+
+msgid "AdminArea|Groups"
+msgstr ""
+
+msgid "AdminArea|Guest"
+msgstr ""
+
+msgid "AdminArea|Included Free in license"
+msgstr ""
+
+msgid "AdminArea|Latest groups"
+msgstr ""
+
+msgid "AdminArea|Latest projects"
+msgstr ""
+
+msgid "AdminArea|Latest users"
+msgstr ""
+
+msgid "AdminArea|Maintainer"
+msgstr ""
+
+msgid "AdminArea|Minimal access"
+msgstr ""
+
+msgid "AdminArea|New group"
+msgstr ""
+
+msgid "AdminArea|New project"
+msgstr ""
+
+msgid "AdminArea|New user"
+msgstr ""
+
+msgid "AdminArea|Owner"
+msgstr ""
+
+msgid "AdminArea|Projects"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+msgstr ""
+
+msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
+msgstr ""
+
+msgid "AdminArea|Sign up for the GitLab newsletter"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|Total users"
+msgstr ""
+
+msgid "AdminArea|Users"
+msgstr ""
+
+msgid "AdminArea|Users statistics"
+msgstr ""
+
+msgid "AdminArea|Users with highest role"
+msgstr ""
+
+msgid "AdminArea|Users without a Group and Project"
+msgstr ""
+
+msgid "AdminArea|View latest groups"
+msgstr ""
+
+msgid "AdminArea|View latest projects"
+msgstr ""
+
+msgid "AdminArea|View latest users"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminDashboard|Error loading the statistics. Please try again"
+msgstr ""
+
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
+msgid "AdminLabels|Define your default set of project labels"
+msgstr ""
+
+msgid "AdminLabels|Labels created here will be automatically added to new projects."
+msgstr ""
+
+msgid "AdminLabels|They can be used to categorize issues and merge requests."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminSettings|A Let's Encrypt account will be configured for this GitLab instance using this email address. You will receive emails to warn of expiring certificates. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|All new projects can use the instance's shared runners by default."
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Configure Let's Encrypt"
+msgstr ""
+
+msgid "AdminSettings|Disable feed token"
+msgstr ""
+
+msgid "AdminSettings|Disable public access to Pages sites"
+msgstr ""
+
+msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
+msgstr ""
+
+msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Enable pipeline suggestion banner"
+msgstr ""
+
+msgid "AdminSettings|Enable shared runners for new projects"
+msgstr ""
+
+msgid "AdminSettings|Feed token"
+msgstr ""
+
+msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
+msgstr ""
+
+msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
+msgstr ""
+
+msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
+msgstr ""
+
+msgid "AdminSettings|Let's Encrypt email"
+msgstr ""
+
+msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
+msgstr ""
+
+msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
+msgstr ""
+
+msgid "AdminSettings|No required pipeline"
+msgstr ""
+
+msgid "AdminSettings|Protect CI/CD variables by default"
+msgstr ""
+
+msgid "AdminSettings|Require users to prove ownership of custom domains"
+msgstr ""
+
+msgid "AdminSettings|Required pipeline configuration"
+msgstr ""
+
+msgid "AdminSettings|Select a CI/CD template"
+msgstr ""
+
+msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
+msgstr ""
+
+msgid "AdminSettings|Select to disable public access for Pages sites, which requires users to sign in for access to the Pages sites in your instance. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
+msgstr ""
+
+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|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Size and domain settings for Pages static sites."
+msgstr ""
+
+msgid "AdminSettings|The default domain to use for Auto Review Apps and Auto Deploy stages in all projects."
+msgstr ""
+
+msgid "AdminSettings|The default name for the initial branch of new repositories created in the instance."
+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 projects in this group can be selected as templates for new projects created on the instance. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
+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 "AdminStatistics|Active Users"
+msgstr ""
+
+msgid "AdminStatistics|Forks"
+msgstr ""
+
+msgid "AdminStatistics|Issues"
+msgstr ""
+
+msgid "AdminStatistics|Merge requests"
+msgstr ""
+
+msgid "AdminStatistics|Milestones"
+msgstr ""
+
+msgid "AdminStatistics|Notes"
+msgstr ""
+
+msgid "AdminStatistics|SSH Keys"
+msgstr ""
+
+msgid "AdminStatistics|Snippets"
+msgstr ""
+
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+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 ""
+
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
+msgid "AdminUsers|Activate"
+msgstr ""
+
+msgid "AdminUsers|Activate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Adjust the user cap setting on your instance"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Administrator"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Block user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Blocking user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Cannot sign in or access instance information"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
+msgid "AdminUsers|Confirm user"
+msgstr ""
+
+msgid "AdminUsers|Confirm user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "AdminUsers|Deactivate"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Deactivated"
+msgstr ""
+
+msgid "AdminUsers|Deactivating a user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
+msgstr ""
+
+msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
+msgstr ""
+
+msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
+msgstr ""
+
+msgid "AdminUsers|Important information about usage on your GitLab instance"
+msgstr ""
+
+msgid "AdminUsers|Is using seat"
+msgstr ""
+
+msgid "AdminUsers|Issues authored by this user are hidden from other users."
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
+msgid "AdminUsers|Locked"
+msgstr ""
+
+msgid "AdminUsers|Log in"
+msgstr ""
+
+msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Owned groups will be left"
+msgstr ""
+
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
+msgid "AdminUsers|Personal projects will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects, group and user history will be left intact"
+msgstr ""
+
+msgid "AdminUsers|Reactivating a user will:"
+msgstr ""
+
+msgid "AdminUsers|Regular"
+msgstr ""
+
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
+
+msgid "AdminUsers|Reject"
+msgstr ""
+
+msgid "AdminUsers|Reject user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Rejected users:"
+msgstr ""
+
+msgid "AdminUsers|Restore user access to the account, including web, Git and API."
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|The user can't access git repositories."
+msgstr ""
+
+msgid "AdminUsers|The user can't log in."
+msgstr ""
+
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
+msgid "AdminUsers|The user will be logged out"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access the API"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to use slash commands"
+msgstr ""
+
+msgid "AdminUsers|The user will not receive any notifications"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
+msgid "AdminUsers|Unban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unblock"
+msgstr ""
+
+msgid "AdminUsers|Unblock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unlock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|User administration"
+msgstr ""
+
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to login"
+msgstr ""
+
+msgid "AdminUsers|Users"
+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 ""
+
+msgid "AdminUsers|What can I do?"
+msgstr ""
+
+msgid "AdminUsers|What does this mean?"
+msgstr ""
+
+msgid "AdminUsers|When banned:"
+msgstr ""
+
+msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
+msgstr ""
+
+msgid "AdminUsers|Will be deleted"
+msgstr ""
+
+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 ""
+
+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 can always block their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always deactivate their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You can ban their account in the future if necessary."
+msgstr ""
+
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
+
+msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
+msgstr ""
+
+msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
+msgstr ""
+
+msgid "AdminUsers|approve them"
+msgstr ""
+
+msgid "AdminUsers|contact our support team"
+msgstr ""
+
+msgid "AdminUsers|docs"
+msgstr ""
+
+msgid "AdminUsers|user cap"
+msgstr ""
+
+msgid "Administration"
+msgstr ""
+
+msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
+msgstr ""
+
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Learn more about quarterly reconciliation"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
+msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
+msgstr ""
+
+msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
+msgstr ""
+
+msgid "Admin|The number of max users in your instance exceeds the number of users in your license. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
+msgstr ""
+
+msgid "Admin|View pending user approvals"
+msgstr ""
+
+msgid "Admin|Your instance has reached its user cap"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced export options"
+msgstr ""
+
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
+msgid "After a successful password update you will be redirected to login screen."
+msgstr ""
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
+msgstr ""
+
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
+msgstr ""
+
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
+msgstr ""
+
+msgid "After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance."
+msgstr ""
+
+msgid "After you've reviewed these contribution guidelines, you'll be all set to"
+msgstr ""
+
+msgid "Akismet"
+msgstr ""
+
+msgid "Akismet API Key"
+msgstr ""
+
+msgid "Akismet helps prevent the creation of spam issues in public projects."
+msgstr ""
+
+msgid "AlertManagement|Acknowledged"
+msgstr ""
+
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
+msgid "AlertManagement|Alert"
+msgstr ""
+
+msgid "AlertManagement|Alert assignee(s): %{assignees}"
+msgstr ""
+
+msgid "AlertManagement|Alert detail"
+msgstr ""
+
+msgid "AlertManagement|Alert details"
+msgstr ""
+
+msgid "AlertManagement|Alert status: %{status}"
+msgstr ""
+
+msgid "AlertManagement|Alerts"
+msgstr ""
+
+msgid "AlertManagement|All alerts"
+msgstr ""
+
+msgid "AlertManagement|Assign status"
+msgstr ""
+
+msgid "AlertManagement|Assignees"
+msgstr ""
+
+msgid "AlertManagement|Authorize external service"
+msgstr ""
+
+msgid "AlertManagement|Create incident"
+msgstr ""
+
+msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
+msgstr ""
+
+msgid "AlertManagement|Edit"
+msgstr ""
+
+msgid "AlertManagement|Environment"
+msgstr ""
+
+msgid "AlertManagement|Events"
+msgstr ""
+
+msgid "AlertManagement|Incident"
+msgstr ""
+
+msgid "AlertManagement|Key"
+msgstr ""
+
+msgid "AlertManagement|Metrics"
+msgstr ""
+
+msgid "AlertManagement|Metrics weren't available in the alerts payload."
+msgstr ""
+
+msgid "AlertManagement|More information"
+msgstr ""
+
+msgid "AlertManagement|No alert data to display."
+msgstr ""
+
+msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "AlertManagement|No alerts to display."
+msgstr ""
+
+msgid "AlertManagement|None"
+msgstr ""
+
+msgid "AlertManagement|Open"
+msgstr ""
+
+msgid "AlertManagement|Please try again."
+msgstr ""
+
+msgid "AlertManagement|Reported %{when}"
+msgstr ""
+
+msgid "AlertManagement|Reported %{when} by %{tool}"
+msgstr ""
+
+msgid "AlertManagement|Resolved"
+msgstr ""
+
+msgid "AlertManagement|Runbook"
+msgstr ""
+
+msgid "AlertManagement|Service"
+msgstr ""
+
+msgid "AlertManagement|Severity"
+msgstr ""
+
+msgid "AlertManagement|Start time"
+msgstr ""
+
+msgid "AlertManagement|Status"
+msgstr ""
+
+msgid "AlertManagement|Surface alerts in GitLab"
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the status of the alert."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the to-do item of the alert."
+msgstr ""
+
+msgid "AlertManagement|This assignee cannot be assigned to this alert."
+msgstr ""
+
+msgid "AlertManagement|Tool"
+msgstr ""
+
+msgid "AlertManagement|Triggered"
+msgstr ""
+
+msgid "AlertManagement|Value"
+msgstr ""
+
+msgid "AlertManagement|View incident"
+msgstr ""
+
+msgid "AlertMappingBuilder|Define fallback"
+msgstr ""
+
+msgid "AlertMappingBuilder|GitLab alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Make selection"
+msgstr ""
+
+msgid "AlertMappingBuilder|Payload alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Select key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key is generated for the integration. After you save the integration, both are visible under the “View credentials†tab."
+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 ""
+
+msgid "AlertSettings|Delete integration"
+msgstr ""
+
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
+msgid "AlertSettings|Edit payload"
+msgstr ""
+
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
+msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
+msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
+msgstr ""
+
+msgid "AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
+msgstr ""
+
+msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
+msgstr ""
+
+msgid "AlertSettings|Integration successfully saved"
+msgstr ""
+
+msgid "AlertSettings|Name integration"
+msgstr ""
+
+msgid "AlertSettings|Parse payload fields"
+msgstr ""
+
+msgid "AlertSettings|Proceed with editing"
+msgstr ""
+
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
+msgid "AlertSettings|Prometheus API base URL"
+msgstr ""
+
+msgid "AlertSettings|Reset Key"
+msgstr ""
+
+msgid "AlertSettings|Reset the mapping"
+msgstr ""
+
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgstr ""
+
+msgid "AlertSettings|Save & create test alert"
+msgstr ""
+
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Save integration & send"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
+msgid "AlertSettings|Send test alert"
+msgstr ""
+
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
+msgid "AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the \"Parse payload fields\" button to continue."
+msgstr ""
+
+msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
+msgstr ""
+
+msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|View URL and authorization key"
+msgstr ""
+
+msgid "AlertSettings|View credentials"
+msgstr ""
+
+msgid "AlertSettings|Webhook URL"
+msgstr ""
+
+msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
+msgstr ""
+
+msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
+msgstr ""
+
+msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration payload is invalid."
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet."
+msgstr ""
+
+msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be added. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is deleted."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
+msgstr ""
+
+msgid "Algorithm"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All %{replicableType} are being scheduled for %{action}"
+msgstr ""
+
+msgid "All (default)"
+msgstr ""
+
+msgid "All GitLab"
+msgstr ""
+
+msgid "All Members"
+msgstr ""
+
+msgid "All branches"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
+msgid "All environments"
+msgstr ""
+
+msgid "All epics"
+msgstr ""
+
+msgid "All groups and projects"
+msgstr ""
+
+msgid "All issues"
+msgstr ""
+
+msgid "All issues for this milestone are closed."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All merge conflicts were resolved. The merge request can now be merged."
+msgstr ""
+
+msgid "All merge request dependencies have been merged"
+msgstr ""
+
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
+
+msgid "All projects"
+msgstr ""
+
+msgid "All projects selected"
+msgstr ""
+
+msgid "All threads resolved"
+msgstr ""
+
+msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
+msgstr ""
+
+msgid "All users must have a name."
+msgstr ""
+
+msgid "All users with matching cards"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow access to members of the following group"
+msgstr ""
+
+msgid "Allow access to the following IP addresses"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow group owners to manage LDAP-related settings"
+msgstr ""
+
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
+
+msgid "Allow only the selected protocols to be used for Git access."
+msgstr ""
+
+msgid "Allow owners to manage default branch protection per group"
+msgstr ""
+
+msgid "Allow owners to manually add users outside of LDAP"
+msgstr ""
+
+msgid "Allow password authentication for Git over HTTP(S)"
+msgstr ""
+
+msgid "Allow password authentication for the web interface"
+msgstr ""
+
+msgid "Allow project maintainers to configure repository mirroring"
+msgstr ""
+
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
+
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
+msgid "Allow this key to push to this repository"
+msgstr ""
+
+msgid "Allow this secondary site to replicate content on Object Storage"
+msgstr ""
+
+msgid "Allow use of licensed EE features"
+msgstr ""
+
+msgid "Allow users to dismiss the broadcast message"
+msgstr ""
+
+msgid "Allow users to register any application to use GitLab as an OAuth provider"
+msgstr ""
+
+msgid "Allow users to request access (if visibility is public or internal)"
+msgstr ""
+
+msgid "Allowed"
+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 ""
+
+msgid "Allowed to create:"
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Almost there"
+msgstr ""
+
+msgid "Almost there..."
+msgstr ""
+
+msgid "Already blocked"
+msgstr ""
+
+msgid "Already have login and password?"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
+msgid "Also unassign this user from related issues and merge requests"
+msgstr ""
+
+msgid "Alternate support URL for Help page and Help dropdown."
+msgstr ""
+
+msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
+msgstr ""
+
+msgid "Amazon EKS"
+msgstr ""
+
+msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
+msgstr ""
+
+msgid "Amazon Web Services Logo"
+msgstr ""
+
+msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr ""
+
+msgid "An Enterprise User GitLab account has been created for you by your organization:"
+msgstr ""
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An alert has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
+msgid "An error occurred adding a draft to the thread."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred fetching the approval rules."
+msgstr ""
+
+msgid "An error occurred fetching the approvers for the new rule."
+msgstr ""
+
+msgid "An error occurred fetching the dropdown data."
+msgstr ""
+
+msgid "An error occurred fetching the project authors."
+msgstr ""
+
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when updating the title"
+msgstr ""
+
+msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while adding approvers"
+msgstr ""
+
+msgid "An error occurred while adding formatted title for epic"
+msgstr ""
+
+msgid "An error occurred while authorizing your role"
+msgstr ""
+
+msgid "An error occurred while checking group path. Please refresh and try again."
+msgstr ""
+
+msgid "An error occurred while decoding the file."
+msgstr ""
+
+msgid "An error occurred while deleting the approvers group"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while deleting the pipeline."
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while disabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while drawing job relationship links."
+msgstr ""
+
+msgid "An error occurred while enabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while fetching Markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching ancestors"
+msgstr ""
+
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching codequality mr diff reports."
+msgstr ""
+
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching coverage reports."
+msgstr ""
+
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching exposed artifacts."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching issues."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
+msgid "An error occurred while fetching participants"
+msgstr ""
+
+msgid "An error occurred while fetching participants."
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
+msgid "An error occurred while fetching reference"
+msgstr ""
+
+msgid "An error occurred while fetching tags. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching terraform reports."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job logs."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
+msgid "An error occurred while getting files for - %{branchId}"
+msgstr ""
+
+msgid "An error occurred while getting issue counts"
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading a section of this page."
+msgstr ""
+
+msgid "An error occurred while loading all the files."
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading code owners."
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading designs. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading group members."
+msgstr ""
+
+msgid "An error occurred while loading issues"
+msgstr ""
+
+msgid "An error occurred while loading merge requests."
+msgstr ""
+
+msgid "An error occurred while loading projects."
+msgstr ""
+
+msgid "An error occurred while loading the Jobs tab."
+msgstr ""
+
+msgid "An error occurred while loading the Needs tab."
+msgstr ""
+
+msgid "An error occurred while loading the Test Reports tab."
+msgstr ""
+
+msgid "An error occurred while loading the access tokens form, please try again."
+msgstr ""
+
+msgid "An error occurred while loading the blob controls."
+msgstr ""
+
+msgid "An error occurred while loading the data. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the file content."
+msgstr ""
+
+msgid "An error occurred while loading the file."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again later."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred while loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred while loading the merge request."
+msgstr ""
+
+msgid "An error occurred while loading the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the pipeline."
+msgstr ""
+
+msgid "An error occurred while loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while loading your content. Please try again."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
+
+msgid "An error occurred while parsing the file."
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while rendering the editor"
+msgstr ""
+
+msgid "An error occurred while reordering issues."
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
+msgid "An error occurred while saving changes: %{error}"
+msgstr ""
+
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while triggering the job."
+msgstr ""
+
+msgid "An error occurred while trying to generate the report. Please try again later."
+msgstr ""
+
+msgid "An error occurred while trying to run a new pipeline for this merge request."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating approvers"
+msgstr ""
+
+msgid "An error occurred while updating assignees."
+msgstr ""
+
+msgid "An error occurred while updating configuration."
+msgstr ""
+
+msgid "An error occurred while updating labels."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
+msgid "An error occurred while updating the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while uploading the file. Please try again."
+msgstr ""
+
+msgid "An error occurred while uploading the image. Please try again."
+msgstr ""
+
+msgid "An error occurred while validating group path"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An example project for managing Kubernetes clusters integrated with GitLab"
+msgstr ""
+
+msgid "An example project that shows off the best practices for setting up GitLab for your own organization, including sample issues, merge requests, and milestones"
+msgstr ""
+
+msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr ""
+
+msgid "An incident has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An incident has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An integer value is required for seconds"
+msgstr ""
+
+msgid "An issue already exists"
+msgstr ""
+
+msgid "An unauthenticated user"
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while loading the code quality diff."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "An unknown error occurred while loading this graph."
+msgstr ""
+
+msgid "An unknown error occurred."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Analyze a review version of your web application."
+msgstr ""
+
+msgid "Analyze your dependencies for known vulnerabilities."
+msgstr ""
+
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
+msgid "Analyze your source code and git history for secrets."
+msgstr ""
+
+msgid "Analyze your source code for known vulnerabilities."
+msgstr ""
+
+msgid "Analyzing file…"
+msgstr ""
+
+msgid "Ancestors"
+msgstr ""
+
+msgid "And this registration token:"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Another action is currently in progress"
+msgstr ""
+
+msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any %{header}"
+msgstr ""
+
+msgid "Any Author"
+msgstr ""
+
+msgid "Any Milestone"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any label"
+msgstr ""
+
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
+
+msgid "Any milestone"
+msgstr ""
+
+msgid "Any namespace"
+msgstr ""
+
+msgid "App ID"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Appearance was successfully created."
+msgstr ""
+
+msgid "Appearance was successfully updated."
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
+msgid "Append the comment with %{tableflip}"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application limits saved successfully"
+msgstr ""
+
+msgid "Application settings saved successfully"
+msgstr ""
+
+msgid "Application settings update failed"
+msgstr ""
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
+msgid "Application was successfully destroyed."
+msgstr ""
+
+msgid "Application was successfully updated."
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "ApplicationSettings|After sign up text"
+msgstr ""
+
+msgid "ApplicationSettings|Allowed domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Approve %d user"
+msgid_plural "ApplicationSettings|Approve %d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
+msgid "ApplicationSettings|Approve users in the pending approval status?"
+msgstr ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve %d user with the pending approval status."
+msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve all users in pending approval status."
+msgstr ""
+
+msgid "ApplicationSettings|Denied domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|Domain denylist"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable domain denylist for sign ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable email restrictions for sign ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enter denylist manually"
+msgstr ""
+
+msgid "ApplicationSettings|Markdown enabled"
+msgstr ""
+
+msgid "ApplicationSettings|Minimum password length (number of characters)"
+msgstr ""
+
+msgid "ApplicationSettings|ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
+msgid "ApplicationSettings|Require admin approval for new sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. See the %{linkStart}supported syntax%{linkEnd} for more information."
+msgstr ""
+
+msgid "ApplicationSettings|Save changes"
+msgstr ""
+
+msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}"
+msgstr ""
+
+msgid "ApplicationSettings|Send confirmation email on sign-up"
+msgstr ""
+
+msgid "ApplicationSettings|Sign-up enabled"
+msgstr ""
+
+msgid "ApplicationSettings|Upload denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|User cap"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "ApplicationSettings|domain.com"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply %d suggestion"
+msgid_plural "Apply %d suggestions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to all branches or a specific protected branch."
+msgstr ""
+
+msgid "Applying"
+msgstr ""
+
+msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
+msgstr ""
+
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion..."
+msgstr ""
+
+msgid "Applying suggestions..."
+msgstr ""
+
+msgid "Approval Status"
+msgstr ""
+
+msgid "Approval rules"
+msgstr ""
+
+msgid "Approval rules reset to project defaults"
+msgstr ""
+
+msgid "Approval settings"
+msgstr ""
+
+msgid "ApprovalRuleRemove|%d member"
+msgid_plural "ApprovalRuleRemove|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} member%{strongEnd}. Approvals from this member are not revoked."
+msgid_plural "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} members%{strongEnd}. Approvals from these members are not revoked."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%d member"
+msgid_plural "ApprovalRuleSummary|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
+msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRule|%{firstLabel} +%{numberOfAdditionalLabels} more"
+msgstr ""
+
+msgid "ApprovalRule|A merge request author collaborating with a merge request approver"
+msgstr ""
+
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
+msgid "ApprovalRule|All scanners"
+msgstr ""
+
+msgid "ApprovalRule|All severity levels"
+msgstr ""
+
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
+msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
+msgstr ""
+
+msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
+msgstr ""
+
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
+msgid "ApprovalRule|Approval rules"
+msgstr ""
+
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
+msgid "ApprovalRule|Approver Type"
+msgstr ""
+
+msgid "ApprovalRule|Approvers"
+msgstr ""
+
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
+msgstr ""
+
+msgid "ApprovalRule|Increase quality and maintain standards."
+msgstr ""
+
+msgid "ApprovalRule|Learn more about merge request approval rules."
+msgstr ""
+
+msgid "ApprovalRule|Name"
+msgstr ""
+
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
+msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
+msgstr ""
+
+msgid "ApprovalRule|Please enter a number equal or greater than zero"
+msgstr ""
+
+msgid "ApprovalRule|Please select at least one security scanner"
+msgstr ""
+
+msgid "ApprovalRule|Please select at least one severity level"
+msgstr ""
+
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Reduce your time to merge."
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
+msgid "ApprovalRule|Rule name"
+msgstr ""
+
+msgid "ApprovalRule|Security scanners"
+msgstr ""
+
+msgid "ApprovalRule|Select All"
+msgstr ""
+
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
+msgid "ApprovalRule|Select scanners"
+msgstr ""
+
+msgid "ApprovalRule|Select severity levels"
+msgstr ""
+
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
+msgid "ApprovalRule|Severity levels"
+msgstr ""
+
+msgid "ApprovalRule|Target branch"
+msgstr ""
+
+msgid "ApprovalRule|Try for free"
+msgstr ""
+
+msgid "ApprovalRule|Vulnerabilities allowed"
+msgstr ""
+
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
+msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approval by author."
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgstr ""
+
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
+msgstr ""
+
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
+
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
+
+msgid "ApprovalSettings|There was an error loading merge request approval settings."
+msgstr ""
+
+msgid "ApprovalSettings|There was an error updating merge request approval settings."
+msgstr ""
+
+msgid "ApprovalSettings|This setting is configured at the instance level and can only be changed by an administrator."
+msgstr ""
+
+msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed in the group settings by an administrator or group owner."
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Adheres to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|At least one rule does not adhere to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
+msgstr ""
+
+msgid "Approvals are optional."
+msgstr ""
+
+msgid "Approvals|Section: %section"
+msgstr ""
+
+msgid "Approve"
+msgstr ""
+
+msgid "Approve a merge request"
+msgstr ""
+
+msgid "Approve the current merge request."
+msgstr ""
+
+msgid "Approved"
+msgstr ""
+
+msgid "Approved MRs"
+msgstr ""
+
+msgid "Approved the current merge request."
+msgstr ""
+
+msgid "Approved-By"
+msgstr ""
+
+msgid "Approver"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Architecture not found for OS"
+msgstr ""
+
+msgid "Archive"
+msgstr ""
+
+msgid "Archive jobs"
+msgstr ""
+
+msgid "Archive project"
+msgstr ""
+
+msgid "Archive test case"
+msgstr ""
+
+msgid "Archived"
+msgstr ""
+
+msgid "Archived (%{movedToStart}moved%{movedToEnd})"
+msgstr ""
+
+msgid "Archived in this version"
+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}"
+msgstr ""
+
+msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
+msgstr ""
+
+msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
+msgstr ""
+
+msgid "Are you sure that you want to archive this project?"
+msgstr ""
+
+msgid "Are you sure that you want to unarchive this project?"
+msgstr ""
+
+msgid "Are you sure you want to %{action} %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
+msgid "Are you sure you want to attempt to merge?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to close this blocked issue?"
+msgstr ""
+
+msgid "Are you sure you want to delete %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to delete these artifacts?"
+msgstr ""
+
+msgid "Are you sure you want to delete this %{typeOfComment}?"
+msgstr ""
+
+msgid "Are you sure you want to delete this SSH key?"
+msgstr ""
+
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to discard this comment?"
+msgstr ""
+
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to import %d repository?"
+msgid_plural "Are you sure you want to import %d repositories?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to merge immediately?"
+msgstr ""
+
+msgid "Are you sure you want to re-deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to reindex?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{email}?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove the license?"
+msgstr ""
+
+msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to remove this list?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the registration token?"
+msgstr ""
+
+msgid "Are you sure you want to retry this migration?"
+msgstr ""
+
+msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
+msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
+
+msgid "Arrange charts"
+msgstr ""
+
+msgid "Artifact"
+msgstr ""
+
+msgid "Artifact could not be deleted."
+msgstr ""
+
+msgid "Artifact was successfully deleted."
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Add commit messages as comments to Asana tasks."
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask again later"
+msgstr ""
+
+msgid "Ask someone with write access to resolve it."
+msgstr ""
+
+msgid "Ask your group owner to set up a group runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assets:"
+msgstr ""
+
+msgid "Assign"
+msgstr ""
+
+msgid "Assign Iteration"
+msgstr ""
+
+msgid "Assign To"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
+msgid "Assign severity"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assign to commenting user"
+msgstr ""
+
+msgid "Assign to me"
+msgstr ""
+
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
+msgid "Assigned %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned merge requests"
+msgstr ""
+
+msgid "Assigned projects"
+msgstr ""
+
+msgid "Assigned to %{assigneeName}"
+msgstr ""
+
+msgid "Assigned to %{assignee_name}"
+msgstr ""
+
+msgid "Assigned to %{name}"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assigned to you"
+msgstr ""
+
+msgid "Assignee"
+msgid_plural "%d Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Assignee has no permissions"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Assignees"
+msgstr ""
+
+msgid "Assigns %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
+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 field of %{one_of_required_fields} must be present"
+msgstr ""
+
+msgid "At least one of group_id or project_id must be specified"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens is expired, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens will expire soon, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At risk"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Attaching File - %{progress}"
+msgstr ""
+
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Audit events"
+msgstr ""
+
+msgid "AuditLogs|(removed)"
+msgstr ""
+
+msgid "AuditLogs|Action"
+msgstr ""
+
+msgid "AuditLogs|Author"
+msgstr ""
+
+msgid "AuditLogs|Date"
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please try again."
+msgstr ""
+
+msgid "AuditLogs|Group Events"
+msgstr ""
+
+msgid "AuditLogs|IP Address"
+msgstr ""
+
+msgid "AuditLogs|Member Events"
+msgstr ""
+
+msgid "AuditLogs|No matching %{type} found."
+msgstr ""
+
+msgid "AuditLogs|Object"
+msgstr ""
+
+msgid "AuditLogs|Project Events"
+msgstr ""
+
+msgid "AuditLogs|Target"
+msgstr ""
+
+msgid "AuditLogs|This month"
+msgstr ""
+
+msgid "AuditLogs|User Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authenticate"
+msgstr ""
+
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
+msgid "Authenticate with GitHub"
+msgstr ""
+
+msgid "Authenticated API rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated API requests"
+msgstr ""
+
+msgid "Authenticated Git LFS rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated Git LFS request rate limit"
+msgstr ""
+
+msgid "Authenticated Git LFS requests"
+msgstr ""
+
+msgid "Authenticated web rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated web requests"
+msgstr ""
+
+msgid "Authenticating"
+msgstr ""
+
+msgid "Authentication"
+msgstr ""
+
+msgid "Authentication Failure"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication failed: %{error_message}"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Authentication method updated"
+msgstr ""
+
+msgid "Authentication via U2F device failed."
+msgstr ""
+
+msgid "Authentication via WebAuthn device failed."
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Author: %{author_name}"
+msgstr ""
+
+msgid "Authored %{timeago}"
+msgstr ""
+
+msgid "Authored %{timeago} by %{author}"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization required"
+msgstr ""
+
+msgid "Authorization token duration (minutes)"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorize %{user} to use your account?"
+msgstr ""
+
+msgid "Authorized %{new_chat_name}"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto stop successfully canceled."
+msgstr ""
+
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
+
+msgid "Auto-close referenced issues on default branch"
+msgstr ""
+
+msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Dismiss Auto DevOps box"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
+msgstr ""
+
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
+
+msgid "Autocomplete"
+msgstr ""
+
+msgid "Autocomplete description"
+msgstr ""
+
+msgid "Autocomplete hint"
+msgstr ""
+
+msgid "Autocomplete usage hint"
+msgstr ""
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
+msgid "Automatic event tracking provides a traceable history for audits."
+msgstr ""
+
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available ID"
+msgstr ""
+
+msgid "Available group runners: %{runners}"
+msgstr ""
+
+msgid "Available runners: %{runners}"
+msgstr ""
+
+msgid "Available shared runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Awaiting user signup"
+msgstr ""
+
+msgid "Award added"
+msgstr ""
+
+msgid "Award removed"
+msgstr ""
+
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
+msgid "Back"
+msgstr ""
+
+msgid "Back to page %{number}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background Migrations"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Badge saved."
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|Name"
+msgstr ""
+
+msgid "Badges|New badge added."
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo"
+msgstr ""
+
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key."
+msgstr ""
+
+msgid "BambooService|Bamboo service root URL."
+msgstr ""
+
+msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
+msgstr ""
+
+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 ""
+
+msgid "BambooService|The user with API access to the Bamboo server."
+msgstr ""
+
+msgid "Based on"
+msgstr ""
+
+msgid "Basic information"
+msgstr ""
+
+msgid "Be careful. Changing the project's namespace can have unintended side effects."
+msgstr ""
+
+msgid "Be careful. Renaming a project's repository can have unintended side effects."
+msgstr ""
+
+msgid "Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}"
+msgstr ""
+
+msgid "Before inserting code, be sure to read the comment that separated each code group."
+msgstr ""
+
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are the fingerprints for the current instance SSH host keys."
+msgstr ""
+
+msgid "Below are the settings for %{link_to_gitlab_pages}."
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Beta"
+msgstr ""
+
+msgid "Bi-weekly code coverage"
+msgstr ""
+
+msgid "Billable Users"
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
+
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
+
+msgid "BillingPlans|Congratulations, your free trial is activated."
+msgstr ""
+
+msgid "BillingPlans|End of availability for the Bronze Plan"
+msgstr ""
+
+msgid "BillingPlans|Free upgrade!"
+msgstr ""
+
+msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
+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 ""
+
+msgid "BillingPlans|Pricing page"
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+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 ""
+
+msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|billed annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|group"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "BillingPlan|Upgrade"
+msgstr ""
+
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
+msgid "Billings|%{planName} plan"
+msgstr ""
+
+msgid "Billings|An error occurred while extending your trial."
+msgstr ""
+
+msgid "Billings|An error occurred while reactivating your trial."
+msgstr ""
+
+msgid "Billings|By extending your trial, you will receive an additional 30 days of %{planName}. Your trial can be only extended once."
+msgstr ""
+
+msgid "Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once."
+msgstr ""
+
+msgid "Billings|Extend trial"
+msgstr ""
+
+msgid "Billings|Reactivate trial"
+msgstr ""
+
+msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
+msgstr ""
+
+msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
+msgstr ""
+
+msgid "Billings|Your account has been validated"
+msgstr ""
+
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
+msgid "Billing|An email address is only visible for users with public emails."
+msgstr ""
+
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
+msgid "Billing|An error occurred while getting a billable member details"
+msgstr ""
+
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|An error occurred while loading pending members list"
+msgstr ""
+
+msgid "Billing|An error occurred while removing a billable member"
+msgstr ""
+
+msgid "Billing|Awaiting member signup"
+msgstr ""
+
+msgid "Billing|Cannot remove user"
+msgstr ""
+
+msgid "Billing|Direct memberships"
+msgstr ""
+
+msgid "Billing|Enter at least three characters to search."
+msgstr ""
+
+msgid "Billing|Export list"
+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 ""
+
+msgid "Billing|Project invite"
+msgstr ""
+
+msgid "Billing|Remove user %{username} from your subscription"
+msgstr ""
+
+msgid "Billing|Toggle seat details"
+msgstr ""
+
+msgid "Billing|Type %{username} to confirm"
+msgstr ""
+
+msgid "Billing|User was successfully removed"
+msgstr ""
+
+msgid "Billing|Users occupying seats in"
+msgstr ""
+
+msgid "Billing|View pending approvals"
+msgstr ""
+
+msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+msgstr ""
+
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
+msgid "Block user"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blocked by %d issue"
+msgid_plural "Blocked by %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked issue"
+msgstr ""
+
+msgid "Blocking"
+msgstr ""
+
+msgid "Blocking issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewEpic|Groups"
+msgstr ""
+
+msgid "BoardNewEpic|Loading groups"
+msgstr ""
+
+msgid "BoardNewEpic|No matching results"
+msgstr ""
+
+msgid "BoardNewEpic|Search groups"
+msgstr ""
+
+msgid "BoardNewEpic|Select a group"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
+msgid "BoardScope|An error occurred while getting milestones, please try again."
+msgstr ""
+
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
+msgid "BoardScope|An error occurred while searching for users, please try again."
+msgstr ""
+
+msgid "BoardScope|Any Milestone"
+msgstr ""
+
+msgid "BoardScope|Any assignee"
+msgstr ""
+
+msgid "BoardScope|Any label"
+msgstr ""
+
+msgid "BoardScope|Assignee"
+msgstr ""
+
+msgid "BoardScope|Choose labels"
+msgstr ""
+
+msgid "BoardScope|Edit"
+msgstr ""
+
+msgid "BoardScope|Labels"
+msgstr ""
+
+msgid "BoardScope|Milestone"
+msgstr ""
+
+msgid "BoardScope|No milestone"
+msgstr ""
+
+msgid "BoardScope|Search milestones"
+msgstr ""
+
+msgid "BoardScope|Select assignee"
+msgstr ""
+
+msgid "BoardScope|Select labels"
+msgstr ""
+
+msgid "BoardScope|Select milestone"
+msgstr ""
+
+msgid "BoardScope|Select weight"
+msgstr ""
+
+msgid "BoardScope|Started"
+msgstr ""
+
+msgid "BoardScope|Upcoming"
+msgstr ""
+
+msgid "BoardScope|Weight"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and board lists"
+msgstr ""
+
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|An error occurred while creating the epic. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching child groups. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching group projects. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while removing the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while updating the board list. Please try again."
+msgstr ""
+
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|New board"
+msgstr ""
+
+msgid "Boards|New epic"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
+msgid "Board|Are you sure you want to delete this board?"
+msgstr ""
+
+msgid "Board|Board scope"
+msgstr ""
+
+msgid "Board|Create board"
+msgstr ""
+
+msgid "Board|Create new board"
+msgstr ""
+
+msgid "Board|Delete board"
+msgstr ""
+
+msgid "Board|Edit board"
+msgstr ""
+
+msgid "Board|Enter board name"
+msgstr ""
+
+msgid "Board|Failed to delete board. Please try again."
+msgstr ""
+
+msgid "Board|Load more epics"
+msgstr ""
+
+msgid "Board|Load more issues"
+msgstr ""
+
+msgid "Board|Loading epics"
+msgstr ""
+
+msgid "Bold text"
+msgstr ""
+
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
+msgid "Branch"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch already exists"
+msgstr ""
+
+msgid "Branch changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+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 merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+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 ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+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|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|Unable to load branches"
+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|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Breadcrumbs"
+msgstr ""
+
+msgid "Brief title about the change"
+msgstr ""
+
+msgid "Broadcast Message was successfully created."
+msgstr ""
+
+msgid "Broadcast Message was successfully updated."
+msgstr ""
+
+msgid "Broadcast Messages"
+msgstr ""
+
+msgid "Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more."
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Browse templates"
+msgstr ""
+
+msgid "BuildArtifacts|An error occurred while fetching the artifacts"
+msgstr ""
+
+msgid "BuildArtifacts|Loading artifacts"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Bulk request concurrency"
+msgstr ""
+
+msgid "Bulk update"
+msgstr ""
+
+msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
+msgstr ""
+
+msgid "BulkImport|%{feature} (require v%{version})"
+msgstr ""
+
+msgid "BulkImport|Existing groups"
+msgstr ""
+
+msgid "BulkImport|Filter by source group"
+msgstr ""
+
+msgid "BulkImport|Following data will not be migrated: %{bullets} Contact system administrator of %{host} to upgrade GitLab if you need this data in your migration"
+msgstr ""
+
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Group import history"
+msgstr ""
+
+msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
+msgid "BulkImport|Import selected"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed."
+msgstr ""
+
+msgid "BulkImport|Last imported to %{link}"
+msgstr ""
+
+msgid "BulkImport|Name already exists."
+msgstr ""
+
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
+msgid "BulkImport|New group"
+msgstr ""
+
+msgid "BulkImport|No history is available"
+msgstr ""
+
+msgid "BulkImport|No parent"
+msgstr ""
+
+msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total}"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} from %{link}"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter}\" from %{link}"
+msgstr ""
+
+msgid "BulkImport|Source group"
+msgstr ""
+
+msgid "BulkImport|To new group"
+msgstr ""
+
+msgid "BulkImport|Update of import statuses with realtime changes failed"
+msgstr ""
+
+msgid "BulkImport|You have no groups to import"
+msgstr ""
+
+msgid "BulkImport|Your imported groups will appear here."
+msgstr ""
+
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
+msgid "Burndown chart"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "Burnup chart"
+msgstr ""
+
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "Busy"
+msgstr ""
+
+msgid "Buy CI Minutes"
+msgstr ""
+
+msgid "Buy Storage"
+msgstr ""
+
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
+msgid "By %{user_name}"
+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 default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
+msgstr ""
+
+msgid "CI settings"
+msgstr ""
+
+msgid "CI variables"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD configuration file"
+msgstr ""
+
+msgid "CI/CD|No projects have been added to the scope"
+msgstr ""
+
+msgid "CICDAnalytics|%{percent}%{percentSymbol}"
+msgstr ""
+
+msgid "CICDAnalytics|All time"
+msgstr ""
+
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
+msgid "CICDAnalytics|Lead time"
+msgstr ""
+
+msgid "CICDAnalytics|Projects with releases"
+msgstr ""
+
+msgid "CICDAnalytics|Release"
+msgid_plural "CICDAnalytics|Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
+msgid "CICDAnalytics|Releases"
+msgstr ""
+
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
+msgid "CICDAnalytics|Something went wrong while fetching release statistics"
+msgstr ""
+
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
+msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
+msgstr ""
+
+msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
+msgstr ""
+
+msgid "CICD|Add an existing project to the scope"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline for all projects"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Limit CI_JOB_TOKEN access"
+msgstr ""
+
+msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgstr ""
+
+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 runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|group enabled"
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CLOSED"
+msgstr ""
+
+msgid "CLOSED (MOVED)"
+msgstr ""
+
+msgid "CODEOWNERS rule violation"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "CPU"
+msgstr ""
+
+msgid "CSV is being generated and will be emailed to you upon completion."
+msgstr ""
+
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
+msgid "Cadence is not automated"
+msgstr ""
+
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Campfire room ID (optional)"
+msgstr ""
+
+msgid "Campfire subdomain (optional)"
+msgstr ""
+
+msgid "Campfire token"
+msgstr ""
+
+msgid "CampfireService|API authentication token from Campfire."
+msgstr ""
+
+msgid "CampfireService|From the end of the room URL."
+msgstr ""
+
+msgid "CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}"
+msgstr ""
+
+msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
+msgstr ""
+
+msgid "Can be manually deployed to"
+msgstr ""
+
+msgid "Can be overridden in each project."
+msgstr ""
+
+msgid "Can create groups:"
+msgstr ""
+
+msgid "Can't apply as the source branch was deleted."
+msgstr ""
+
+msgid "Can't apply as these lines were changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply as this line was changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply this suggestion."
+msgstr ""
+
+msgid "Can't be empty"
+msgstr ""
+
+msgid "Can't create snippet: %{err}"
+msgstr ""
+
+msgid "Can't fetch content for the blob: %{err}"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't load mermaid module: %{err}"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
+msgid "Can't update snippet: %{err}"
+msgstr ""
+
+msgid "Canary"
+msgstr ""
+
+msgid "Canary Ingress does not exist in the environment."
+msgstr ""
+
+msgid "Canary weight must be specified and valid range (0..100)."
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}"
+msgstr ""
+
+msgid "CanaryIngress|Canary"
+msgstr ""
+
+msgid "CanaryIngress|Change ratio"
+msgstr ""
+
+msgid "CanaryIngress|Change the ratio of canary deployments?"
+msgstr ""
+
+msgid "CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished."
+msgstr ""
+
+msgid "CanaryIngress|Stable"
+msgstr ""
+
+msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel and close"
+msgstr ""
+
+msgid "Cancel index deletion"
+msgstr ""
+
+msgid "Cancel running"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cancel your account"
+msgstr ""
+
+msgid "Cancel, keep project"
+msgstr ""
+
+msgid "Canceled deployment to"
+msgstr ""
+
+msgid "Cancelled"
+msgstr ""
+
+msgid "Cancelling Preview"
+msgstr ""
+
+msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
+msgid "Cannot create the abuse report. The user has been deleted."
+msgstr ""
+
+msgid "Cannot create the abuse report. This user has been blocked."
+msgstr ""
+
+msgid "Cannot delete %{profile_name} referenced in security policy"
+msgstr ""
+
+msgid "Cannot have multiple Jira imports running at the same time"
+msgstr ""
+
+msgid "Cannot have multiple unresolved alerts"
+msgstr ""
+
+msgid "Cannot import because issues are not available in this project."
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
+
+msgid "Cannot merge"
+msgstr ""
+
+msgid "Cannot modify %{profile_name} referenced in security policy"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Cannot modify provider during creation"
+msgstr ""
+
+msgid "Cannot promote issue because it does not belong to a group."
+msgstr ""
+
+msgid "Cannot promote issue due to insufficient permissions."
+msgstr ""
+
+msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgstr ""
+
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
+msgid "Cannot skip two factor authentication setup"
+msgstr ""
+
+msgid "Capacity threshold"
+msgstr ""
+
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
+msgid "CascadingSettings|Enforce for all subgroups"
+msgstr ""
+
+msgid "CascadingSettings|Setting enforced"
+msgstr ""
+
+msgid "CascadingSettings|Subgroups cannot change this setting."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an instance admin."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
+msgstr ""
+
+msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
+msgstr ""
+
+msgid "CascadingSettings|cannot be nil when locking the attribute"
+msgstr ""
+
+msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate Issuer"
+msgstr ""
+
+msgid "Certificate Subject"
+msgstr ""
+
+msgid "Change assignee"
+msgstr ""
+
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
+msgid "Change branches"
+msgstr ""
+
+msgid "Change label"
+msgstr ""
+
+msgid "Change made by"
+msgstr ""
+
+msgid "Change milestone"
+msgstr ""
+
+msgid "Change path"
+msgstr ""
+
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
+msgid "Change role"
+msgstr ""
+
+msgid "Change status"
+msgstr ""
+
+msgid "Change subscription"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Unassigned"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Search branches"
+msgstr ""
+
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
+msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
+msgid "Changed assignee(s)."
+msgstr ""
+
+msgid "Changed reviewer(s)."
+msgstr ""
+
+msgid "Changed the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes"
+msgstr ""
+
+msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
+msgstr ""
+
+msgid "Changes saved."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes to the title have not been saved"
+msgstr ""
+
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
+msgid "Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Branch"
+msgstr ""
+
+msgid "ChatMessage|Commit"
+msgstr ""
+
+msgid "ChatMessage|Failed job"
+msgstr ""
+
+msgid "ChatMessage|Failed stage"
+msgstr ""
+
+msgid "ChatMessage|Invalid CI config YAML file"
+msgstr ""
+
+msgid "ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}"
+msgstr ""
+
+msgid "ChatMessage|Tag"
+msgstr ""
+
+msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
+msgstr ""
+
+msgid "ChatMessage|has failed"
+msgstr ""
+
+msgid "ChatMessage|has passed"
+msgstr ""
+
+msgid "ChatMessage|has passed with warnings"
+msgstr ""
+
+msgid "ChatMessage|in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|in %{project_link}"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "Check feature availability on namespace plan"
+msgstr ""
+
+msgid "Check out, review, and merge locally"
+msgstr ""
+
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
+msgstr ""
+
+msgid "Check the current instance configuration "
+msgstr ""
+
+msgid "Check with your administrator."
+msgstr ""
+
+msgid "Check your Docker images for known vulnerabilities."
+msgstr ""
+
+msgid "Check your Kubernetes cluster images for known vulnerabilities."
+msgstr ""
+
+msgid "Check your source instance permissions."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Checking group URL availability..."
+msgstr ""
+
+msgid "Checking group path availability..."
+msgstr ""
+
+msgid "Checking username availability..."
+msgstr ""
+
+msgid "Checkout"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per user per year"
+msgstr ""
+
+msgid "Checkout|%d CI minute pack"
+msgid_plural "Checkout|%d CI minute packs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
+msgstr ""
+
+msgid "Checkout|%{name}'s CI minutes"
+msgstr ""
+
+msgid "Checkout|%{name}'s GitLab subscription"
+msgstr ""
+
+msgid "Checkout|%{name}'s storage subscription"
+msgstr ""
+
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
+msgid "Checkout|%{quantity} GB of storage"
+msgstr ""
+
+msgid "Checkout|%{quantity} storage pack"
+msgid_plural "Checkout|%{quantity} storage packs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Checkout|%{selectedPlanText} plan"
+msgstr ""
+
+msgid "Checkout|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
+msgstr ""
+
+msgid "Checkout|(x%{numberOfUsers})"
+msgstr ""
+
+msgid "Checkout|(x%{quantity})"
+msgstr ""
+
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
+msgid "Checkout|Billing address"
+msgstr ""
+
+msgid "Checkout|CI minute pack"
+msgstr ""
+
+msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
+msgstr ""
+
+msgid "Checkout|CI minutes"
+msgstr ""
+
+msgid "Checkout|Checkout"
+msgstr ""
+
+msgid "Checkout|City"
+msgstr ""
+
+msgid "Checkout|Confirm purchase"
+msgstr ""
+
+msgid "Checkout|Confirming..."
+msgstr ""
+
+msgid "Checkout|Continue to billing"
+msgstr ""
+
+msgid "Checkout|Continue to payment"
+msgstr ""
+
+msgid "Checkout|Country"
+msgstr ""
+
+msgid "Checkout|Create a new group"
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load. Please try again."
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load: %{message}"
+msgstr ""
+
+msgid "Checkout|Edit"
+msgstr ""
+
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
+msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order! Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load countries. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load states. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load the payment form. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to register credit card. Please try again."
+msgstr ""
+
+msgid "Checkout|GB"
+msgstr ""
+
+msgid "Checkout|GitLab group"
+msgstr ""
+
+msgid "Checkout|GitLab plan"
+msgstr ""
+
+msgid "Checkout|Group"
+msgstr ""
+
+msgid "Checkout|Name of company or organization using GitLab"
+msgstr ""
+
+msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
+msgstr ""
+
+msgid "Checkout|Number of users"
+msgstr ""
+
+msgid "Checkout|Payment method"
+msgstr ""
+
+msgid "Checkout|Please select a country"
+msgstr ""
+
+msgid "Checkout|Please select a state"
+msgstr ""
+
+msgid "Checkout|Purchase details"
+msgstr ""
+
+msgid "Checkout|Select"
+msgstr ""
+
+msgid "Checkout|State"
+msgstr ""
+
+msgid "Checkout|Storage packs"
+msgstr ""
+
+msgid "Checkout|Street address"
+msgstr ""
+
+msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
+msgstr ""
+
+msgid "Checkout|Subscription details"
+msgstr ""
+
+msgid "Checkout|Subtotal"
+msgstr ""
+
+msgid "Checkout|Tax"
+msgstr ""
+
+msgid "Checkout|Total"
+msgstr ""
+
+msgid "Checkout|Total minutes: %{quantity}"
+msgstr ""
+
+msgid "Checkout|Total storage: %{quantity} GB"
+msgstr ""
+
+msgid "Checkout|Users"
+msgstr ""
+
+msgid "Checkout|You'll create your new group after checkout"
+msgstr ""
+
+msgid "Checkout|Your organization"
+msgstr ""
+
+msgid "Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly."
+msgstr ""
+
+msgid "Checkout|Your subscription will be applied to this group"
+msgstr ""
+
+msgid "Checkout|Zip code"
+msgstr ""
+
+msgid "Checkout|a storage subscription"
+msgstr ""
+
+msgid "Checkout|company or team"
+msgstr ""
+
+msgid "Checkout|minutes"
+msgstr ""
+
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
+msgid "Checkout|x %{quantity} %{units} per pack ="
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Child"
+msgstr ""
+
+msgid "Child epic"
+msgstr ""
+
+msgid "Child epic does not exist."
+msgstr ""
+
+msgid "Child epic doesn't exist."
+msgstr ""
+
+msgid "Chinese language support using"
+msgstr ""
+
+msgid "Choose File..."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a group"
+msgstr ""
+
+msgid "Choose a template"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose file…"
+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 ""
+
+msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
+
+msgid "Choose which Git strategy to use when fetching the project."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose your framework"
+msgstr ""
+
+msgid "CiCdAnalytics|Date range: %{range}"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|preparing"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for resource"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|preparing"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatusText|waiting"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
+msgid "CiVariables|Environments"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
+msgid "CiVariables|Protected"
+msgstr ""
+
+msgid "CiVariables|Remove variable"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
+msgid "CiVariables|Variables"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Masked"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle masked"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "Classification Label (optional)"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clean up after running %{link_start}git filter-repo%{link_end} on the repository."
+msgstr ""
+
+msgid "Clean up image tags"
+msgstr ""
+
+msgid "Cleanup policies are executed by background workers. This setting defines the maximum number of workers that can run concurrently. Set it to 0 to remove all workers and not execute the cleanup policies."
+msgstr ""
+
+msgid "Cleanup policy maximum number of tags to be deleted"
+msgstr ""
+
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
+msgid "Cleanup policy maximum workers running concurrently"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear all repository checks"
+msgstr ""
+
+msgid "Clear chart filters"
+msgstr ""
+
+msgid "Clear due date"
+msgstr ""
+
+msgid "Clear health status"
+msgstr ""
+
+msgid "Clear recent searches"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Clear start date"
+msgstr ""
+
+msgid "Clear templates search input"
+msgstr ""
+
+msgid "Clear weight"
+msgstr ""
+
+msgid "Cleared health status."
+msgstr ""
+
+msgid "Cleared weight."
+msgstr ""
+
+msgid "Clears health status."
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
+msgid "Click %{link_start}here%{link_end} to view the request."
+msgstr ""
+
+msgid "Click %{link_to} to view the request."
+msgstr ""
+
+msgid "Click the link below to confirm your email address (%{email})"
+msgstr ""
+
+msgid "Click the link below to confirm your email address."
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Click to hide"
+msgstr ""
+
+msgid "Click to reveal"
+msgstr ""
+
+msgid "Client request timeout"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clientside DSN"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone this issue"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with %{protocol}"
+msgstr ""
+
+msgid "Clone with KRB5"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
+msgstr ""
+
+msgid "Cloned this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Clones this issue, without comments, to %{project}."
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close %{issueType}"
+msgstr ""
+
+msgid "Close %{noteable}"
+msgstr ""
+
+msgid "Close %{tabname}"
+msgstr ""
+
+msgid "Close design"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Close sidebar"
+msgstr ""
+
+msgid "Close this %{quick_action_target}"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Closed MRs"
+msgstr ""
+
+msgid "Closed epics"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "Closed this %{quick_action_target}."
+msgstr ""
+
+msgid "Closed: %{closed}"
+msgstr ""
+
+msgid "Closes this %{quick_action_target}."
+msgstr ""
+
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
+msgid "Cluster"
+msgstr ""
+
+msgid "Cluster Health"
+msgstr ""
+
+msgid "Cluster cache cleared."
+msgstr ""
+
+msgid "Cluster does not exist"
+msgstr ""
+
+msgid "Cluster is required for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "Cluster level"
+msgstr ""
+
+msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "ClusterAgents|%{name} successfully deleted"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} Agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
+msgid "ClusterAgents|%{titleIcon}Connected"
+msgstr ""
+
+msgid "ClusterAgents|%{titleIcon}Not connected"
+msgstr ""
+
+msgid "ClusterAgents|%{tokenName} created"
+msgstr ""
+
+msgid "ClusterAgents|%{tokenName} revoked"
+msgstr ""
+
+msgid "ClusterAgents|Access tokens"
+msgstr ""
+
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
+msgid "ClusterAgents|Agent %{strongStart}connected%{strongEnd}"
+msgstr ""
+
+msgid "ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}"
+msgstr ""
+
+msgid "ClusterAgents|Agent might not be connected to GitLab"
+msgstr ""
+
+msgid "ClusterAgents|Agent never connected to GitLab"
+msgstr ""
+
+msgid "ClusterAgents|All"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your agent"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again."
+msgstr ""
+
+msgid "ClusterAgents|An unknown error occurred. Please try again."
+msgstr ""
+
+msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
+msgstr ""
+
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
+msgid "ClusterAgents|Configuration"
+msgstr ""
+
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connected"
+msgstr ""
+
+msgid "ClusterAgents|Connection status"
+msgstr ""
+
+msgid "ClusterAgents|Copy token"
+msgstr ""
+
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
+msgid "ClusterAgents|Created by"
+msgstr ""
+
+msgid "ClusterAgents|Created by %{name} %{time}"
+msgstr ""
+
+msgid "ClusterAgents|Date created"
+msgstr ""
+
+msgid "ClusterAgents|Delete"
+msgstr ""
+
+msgid "ClusterAgents|Delete agent"
+msgstr ""
+
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
+msgid "ClusterAgents|Description"
+msgstr ""
+
+msgid "ClusterAgents|Event occurred"
+msgstr ""
+
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
+
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
+
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
+
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
+
+msgid "ClusterAgents|Install new Agent"
+msgstr ""
+
+msgid "ClusterAgents|Last connected %{timeAgo}."
+msgstr ""
+
+msgid "ClusterAgents|Last contact"
+msgstr ""
+
+msgid "ClusterAgents|Learn how to create an agent access token"
+msgstr ""
+
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
+msgid "ClusterAgents|Make sure you are using a valid token."
+msgstr ""
+
+msgid "ClusterAgents|Name"
+msgstr ""
+
+msgid "ClusterAgents|Never"
+msgstr ""
+
+msgid "ClusterAgents|Never connected"
+msgstr ""
+
+msgid "ClusterAgents|No Agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
+msgid "ClusterAgents|Not connected"
+msgstr ""
+
+msgid "ClusterAgents|Recommended"
+msgstr ""
+
+msgid "ClusterAgents|Recommended installation method"
+msgstr ""
+
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
+msgid "ClusterAgents|Registering Agent"
+msgstr ""
+
+msgid "ClusterAgents|Registration token"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
+msgid "ClusterAgents|Security"
+msgstr ""
+
+msgid "ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected."
+msgstr ""
+
+msgid "ClusterAgents|Select an agent"
+msgstr ""
+
+msgid "ClusterAgents|Select an agent to register with GitLab"
+msgstr ""
+
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgstr ""
+
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
+msgstr ""
+
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|There's no activity from the past day"
+msgid_plural "ClusterAgents|There's no activity from the past %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ClusterAgents|This agent has no tokens"
+msgstr ""
+
+msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
+msgstr ""
+
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|Token created by %{userName}"
+msgstr ""
+
+msgid "ClusterAgents|Token revoked by %{userName}"
+msgstr ""
+
+msgid "ClusterAgents|Unknown user"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
+msgid "ClusterAgents|What is GitLab Agent activity?"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
+msgid "ClusterAgents|You will need to create a token to connect to your agent"
+msgstr ""
+
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
+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|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|API URL should be a valid http/https url."
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
+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|Amazon EKS"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
+msgstr ""
+
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with AWS"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with Amazon Web Services"
+msgstr ""
+
+msgid "ClusterIntegration|Authentication Error"
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Check your CA certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Check your cluster status"
+msgstr ""
+
+msgid "ClusterIntegration|Check your token"
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the worker node %{linkStart}instance type%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clear cluster cache"
+msgstr ""
+
+msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster management project"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster name is required."
+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 ""
+
+msgid "ClusterIntegration|Connect cluster with certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Connection Error"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load IAM roles"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load VPCs for the selected region"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load networks"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load security groups for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnets for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create cluster on"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on EKS"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Creating Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Kubernetes Service"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Cloud Run for Anthos"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Prometheus integration"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter new Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope is required."
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to authenticate."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to connect to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|HTTP Error"
+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 ""
+
+msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
+msgstr ""
+
+msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
+msgstr ""
+
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Integration disabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integration enabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
+msgstr ""
+
+msgid "ClusterIntegration|Key pair name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version not found"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Loading IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Loading Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Loading networks"
+msgstr ""
+
+msgid "ClusterIntegration|Loading security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your API endpoint is correct"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
+msgstr ""
+
+msgid "ClusterIntegration|Namespace per environment"
+msgstr ""
+
+msgid "ClusterIntegration|No IAM Roles found"
+msgstr ""
+
+msgid "ClusterIntegration|No Key Pairs found"
+msgstr ""
+
+msgid "ClusterIntegration|No VPCs found"
+msgstr ""
+
+msgid "ClusterIntegration|No instance type found"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No networks found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No security group found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnet found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnetworks found"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes must be a numerical value."
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Provider details"
+msgstr ""
+
+msgid "ClusterIntegration|Provision Role ARN"
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{linkStart}help page%{linkEnd} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Removes cluster from project but keeps associated resources"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Search Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Search VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Search instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search networks"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|Security group"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select a network to choose a subnetwork"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a Key Pair"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
+msgid "ClusterIntegration|Select a zone to choose a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
+msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Service role"
+msgstr ""
+
+msgid "ClusterIntegration|Service token is required."
+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|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
+
+msgid "ClusterIntegration|Subnets"
+msgstr ""
+
+msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provisioned role, first create one on %{awsLinkStart}Amazon Web Services %{awsLinkEnd} using the above account and external IDs. %{moreInfoStart}More information%{moreInfoEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
+msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
+msgstr ""
+
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Troubleshooting tips:"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Authenticate"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Connect"
+msgstr ""
+
+msgid "ClusterIntegration|Unknown Error"
+msgstr ""
+
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
+msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
+msgstr ""
+
+msgid "ClusterIntegration|You should select at least two subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
+msgid "ClusterIntegration|Your service role is distinct from the provision role used when authenticating. It will allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Clusters|An error occurred while loading clusters"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
+msgstr ""
+
+msgid "Code Coverage| Empty code coverage data"
+msgstr ""
+
+msgid "Code Coverage|Couldn't fetch the code coverage data"
+msgstr ""
+
+msgid "Code Owner"
+msgstr ""
+
+msgid "Code Owners"
+msgstr ""
+
+msgid "Code Quality"
+msgstr ""
+
+msgid "Code Review"
+msgstr ""
+
+msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
+msgstr ""
+
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
+msgstr ""
+
+msgid "Code owner approval is required"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Code review"
+msgstr ""
+
+msgid "Code snippet"
+msgstr ""
+
+msgid "Code snippet copied. Insert it in the correct location in the YAML file."
+msgstr ""
+
+msgid "CodeIntelligence|This is the definition"
+msgstr ""
+
+msgid "CodeNavigation|No references found"
+msgstr ""
+
+msgid "CodeOwner|Pattern"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations on this line"
+msgstr ""
+
+msgid "Cohorts|Inactive users"
+msgstr ""
+
+msgid "Cohorts|Month %{month_index}"
+msgstr ""
+
+msgid "Cohorts|New users"
+msgstr ""
+
+msgid "Cohorts|Registration month"
+msgstr ""
+
+msgid "Cohorts|Returning users"
+msgstr ""
+
+msgid "Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately."
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse all threads"
+msgstr ""
+
+msgid "Collapse approvers"
+msgstr ""
+
+msgid "Collapse issues"
+msgstr ""
+
+msgid "Collapse milestones"
+msgstr ""
+
+msgid "Collapse replies"
+msgstr ""
+
+msgid "Collapse settings section"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
+msgid "Collector hostname"
+msgstr ""
+
+msgid "Colorize messages"
+msgstr ""
+
+msgid "ComboSearch is not defined"
+msgstr ""
+
+msgid "Comma-separated list of email addresses."
+msgstr ""
+
+msgid "Comma-separated list of users allowed to exceed the rate limit."
+msgstr ""
+
+msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Commands applied"
+msgstr ""
+
+msgid "Commands did not apply"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve thread"
+msgstr ""
+
+msgid "Comment & unresolve thread"
+msgstr ""
+
+msgid "Comment '%{label}' position"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comment is being updated"
+msgstr ""
+
+msgid "Comment on lines %{startLine} to %{endLine}"
+msgstr ""
+
+msgid "Comment/Reply (quoting selected text)"
+msgstr ""
+
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit (when editing commit message)"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit SHA"
+msgstr ""
+
+msgid "Commit changes"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit message (optional)"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits to"
+msgstr ""
+
+msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Community forum"
+msgstr ""
+
+msgid "Company"
+msgstr ""
+
+msgid "Company Name"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare %{oldCommitId}...%{newCommitId}"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare GitLab editions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "Compare submodule commit revisions"
+msgstr ""
+
+msgid "Compare with previous version"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "CompareRevisions|Branches"
+msgstr ""
+
+msgid "CompareRevisions|Compare"
+msgstr ""
+
+msgid "CompareRevisions|Create merge request"
+msgstr ""
+
+msgid "CompareRevisions|Filter by Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select branch/tag"
+msgstr ""
+
+msgid "CompareRevisions|Select target project"
+msgstr ""
+
+msgid "CompareRevisions|Swap revisions"
+msgstr ""
+
+msgid "CompareRevisions|Tags"
+msgstr ""
+
+msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|View open merge request"
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
+
+msgid "Compliance framework"
+msgstr ""
+
+msgid "Compliance report"
+msgstr ""
+
+msgid "ComplianceDashboard|created by:"
+msgstr ""
+
+msgid "ComplianceFrameworks|Add framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance framework deleted successfully"
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
+msgid "ComplianceFrameworks|Edit framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error deleting the compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Invalid format"
+msgstr ""
+
+msgid "ComplianceFrameworks|Name"
+msgstr ""
+
+msgid "ComplianceFrameworks|Name is required"
+msgstr ""
+
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
+msgstr ""
+
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgstr ""
+
+msgid "ComplianceFramework|Edit compliance framework"
+msgstr ""
+
+msgid "ComplianceFramework|New compliance framework"
+msgstr ""
+
+msgid "ComplianceReport|Approved by author"
+msgstr ""
+
+msgid "ComplianceReport|Approved by committer"
+msgstr ""
+
+msgid "ComplianceReport|Less than 2 approvers"
+msgstr ""
+
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
+msgid "Component"
+msgstr ""
+
+msgid "Confidence"
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Configuration help"
+msgstr ""
+
+msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
+msgstr ""
+
+msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and %{housekeeping_link_start}housekeeping%{link_end} on repositories."
+msgstr ""
+
+msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
+msgstr ""
+
+msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Integrations"
+msgstr ""
+
+msgid "Configure Prometheus"
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure SAST in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
+msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure Secret Detection in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) to customize Secret Detection settings."
+msgstr ""
+
+msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
+msgstr ""
+
+msgid "Configure existing installation"
+msgstr ""
+
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
+msgid "Configure repository mirroring."
+msgstr ""
+
+msgid "Configure repository storage."
+msgstr ""
+
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
+msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure specific limits for deprecated API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the default first day of the week and time tracking units."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Configure via Merge Request"
+msgstr ""
+
+msgid "Configure which lists are shown for anyone who visits this board"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "Confirm approval"
+msgstr ""
+
+msgid "Confirm new password"
+msgstr ""
+
+msgid "Confirm user"
+msgstr ""
+
+msgid "Confirm your account"
+msgstr ""
+
+msgid "Confirm your email address"
+msgstr ""
+
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
+msgid "Confirmation required"
+msgstr ""
+
+msgid "Confirmed at:"
+msgstr ""
+
+msgid "Confirmed:"
+msgstr ""
+
+msgid "Conflict: This file was added both in the source and target branches, but with different contents."
+msgstr ""
+
+msgid "Conflict: This file was modified in both the source and target branches."
+msgstr ""
+
+msgid "Conflict: This file was modified in the source branch, but removed in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was removed in the source branch, but modified in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was removed in the source branch, but renamed in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was renamed differently in the source and target branches."
+msgstr ""
+
+msgid "Conflict: This file was renamed in the source branch, but removed in the target branch."
+msgstr ""
+
+msgid "Confluence"
+msgstr ""
+
+msgid "Confluence Cloud Workspace URL"
+msgstr ""
+
+msgid "ConfluenceService|Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
+msgstr ""
+
+msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the \"Wiki\" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL."
+msgstr ""
+
+msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
+msgstr ""
+
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connected"
+msgstr ""
+
+msgid "Connecting"
+msgstr ""
+
+msgid "Connecting to terminal sync service"
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Connection failed"
+msgstr ""
+
+msgid "Connection failure"
+msgstr ""
+
+msgid "Connection timed out"
+msgstr ""
+
+msgid "Connection timeout"
+msgstr ""
+
+msgid "Consistency guarantee method"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Contacts"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container does not exist"
+msgstr ""
+
+msgid "Container must be a project or a group."
+msgstr ""
+
+msgid "Container registry images"
+msgstr ""
+
+msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
+msgstr ""
+
+msgid "Container repositories"
+msgstr ""
+
+msgid "Container repositories synchronization concurrency limit"
+msgstr ""
+
+msgid "Container repository"
+msgstr ""
+
+msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
+msgstr ""
+
+msgid "ContainerRegistry|%{count} Image repository"
+msgid_plural "ContainerRegistry|%{count} Image repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{count} Tag"
+msgid_plural "ContainerRegistry|%{count} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
+msgstr ""
+
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
+msgid "ContainerRegistry|Build an image"
+msgstr ""
+
+msgid "ContainerRegistry|CLI Commands"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup in progress"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup incomplete"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is currently removing tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is disabled for this project"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is ongoing"
+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 ""
+
+msgid "ContainerRegistry|Cleanup policy successfully saved."
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup timed out"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run soon"
+msgstr ""
+
+msgid "ContainerRegistry|Configuration digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Copy build command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy login command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy push command"
+msgstr ""
+
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
+msgid "ContainerRegistry|Delete selected tags"
+msgstr ""
+
+msgid "ContainerRegistry|Delete tag"
+msgstr ""
+
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgstr ""
+
+msgid "ContainerRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "ContainerRegistry|Docker connection error"
+msgstr ""
+
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy will run in %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|If you are not already logged in, you need to authenticate to the Container Registry by using your GitLab username and password. If you have %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd} instead of a password."
+msgstr ""
+
+msgid "ContainerRegistry|Image repository deletion failed"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository not found"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository will be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
+msgid "ContainerRegistry|Image tags"
+msgstr ""
+
+msgid "ContainerRegistry|Invalid tag: missing manifest digest"
+msgstr ""
+
+msgid "ContainerRegistry|Keep tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep the most recent:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Login"
+msgstr ""
+
+msgid "ContainerRegistry|Manifest digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Next cleanup scheduled to run on:"
+msgstr ""
+
+msgid "ContainerRegistry|Not yet scheduled"
+msgstr ""
+
+msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
+msgstr ""
+
+msgid "ContainerRegistry|Please try different search criteria"
+msgstr ""
+
+msgid "ContainerRegistry|Published %{timeInfo}"
+msgstr ""
+
+msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
+msgstr ""
+
+msgid "ContainerRegistry|Push an image"
+msgstr ""
+
+msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgid_plural "ContainerRegistry|Remove tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|Remove tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tags older than:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
+msgid "ContainerRegistry|Run cleanup:"
+msgstr ""
+
+msgid "ContainerRegistry|Some tags were not deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the image details."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the repository list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the tags list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "ContainerRegistry|Tag successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The filter returned no results"
+msgstr ""
+
+msgid "ContainerRegistry|The image repository could not be found."
+msgstr ""
+
+msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
+msgstr ""
+
+msgid "ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
+msgstr ""
+
+msgid "ContainerRegistry|The value of this input should be less than 256 characters"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images available in this group"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images stored for this project"
+msgstr ""
+
+msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
+msgstr ""
+
+msgid "ContainerRegistry|This image has no active tags"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository has failed to be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository is scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
+msgstr ""
+
+msgid "ContainerRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the GitLab Container Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
+msgstr ""
+
+msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
+msgstr ""
+
+msgid "Content parsed with %{link}."
+msgstr ""
+
+msgid "ContentEditor|Table of Contents"
+msgstr ""
+
+msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "ContextCommits|Failed to create context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to create/remove context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to delete context commits. Please try again."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Analytics"
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
+msgstr ""
+
+msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
+msgstr ""
+
+msgid "ContributionAnalytics|Issues"
+msgstr ""
+
+msgid "ContributionAnalytics|Last 3 months"
+msgstr ""
+
+msgid "ContributionAnalytics|Last month"
+msgstr ""
+
+msgid "ContributionAnalytics|Last week"
+msgstr ""
+
+msgid "ContributionAnalytics|Merge requests"
+msgstr ""
+
+msgid "ContributionAnalytics|No issues for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No merge requests for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No pushes for the selected time period."
+msgstr ""
+
+msgid "Contributions for %{calendar_date}"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributor"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Control emails linked to your account"
+msgstr ""
+
+msgid "Control how the GitLab Package Registry functions."
+msgstr ""
+
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgstr ""
+
+msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
+msgstr ""
+
+msgid "Cookie domain"
+msgstr ""
+
+msgid "Copied"
+msgstr ""
+
+msgid "Copied labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{name}"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{type}"
+msgstr ""
+
+msgid "Copy Account ID to clipboard"
+msgstr ""
+
+msgid "Copy External ID to clipboard"
+msgstr ""
+
+msgid "Copy ID"
+msgstr ""
+
+msgid "Copy IP Address"
+msgstr ""
+
+msgid "Copy KRB5 clone URL"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy URL"
+msgstr ""
+
+msgid "Copy branch name"
+msgstr ""
+
+msgid "Copy codes"
+msgstr ""
+
+msgid "Copy command"
+msgstr ""
+
+msgid "Copy commands"
+msgstr ""
+
+msgid "Copy commit SHA"
+msgstr ""
+
+msgid "Copy environment"
+msgstr ""
+
+msgid "Copy evidence SHA"
+msgstr ""
+
+msgid "Copy failed. Please manually copy the value."
+msgstr ""
+
+msgid "Copy file contents"
+msgstr ""
+
+msgid "Copy file path"
+msgstr ""
+
+msgid "Copy issue URL to clipboard"
+msgstr ""
+
+msgid "Copy key"
+msgstr ""
+
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy link to chart"
+msgstr ""
+
+msgid "Copy reference"
+msgstr ""
+
+msgid "Copy secret"
+msgstr ""
+
+msgid "Copy source branch name"
+msgstr ""
+
+msgid "Copy the code below to implement tracking in your application:"
+msgstr ""
+
+msgid "Copy this registration token."
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token"
+msgstr ""
+
+msgid "Copy trigger token"
+msgstr ""
+
+msgid "Copy value"
+msgstr ""
+
+msgid "Corpus Management"
+msgstr ""
+
+msgid "Corpus Management|Are you sure you want to delete the corpus?"
+msgstr ""
+
+msgid "CorpusManagement|Actions"
+msgstr ""
+
+msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
+msgstr ""
+
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Corpus name"
+msgstr ""
+
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
+msgid "CorpusManagement|Last updated"
+msgstr ""
+
+msgid "CorpusManagement|Last used"
+msgstr ""
+
+msgid "CorpusManagement|Latest Job:"
+msgstr ""
+
+msgid "CorpusManagement|New upload"
+msgstr ""
+
+msgid "CorpusManagement|Not Set"
+msgstr ""
+
+msgid "CorpusManagement|Target"
+msgstr ""
+
+msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
+msgid "CorpusMnagement|New corpus"
+msgstr ""
+
+msgid "Could not add admins as members"
+msgstr ""
+
+msgid "Could not apply %{name} command."
+msgstr ""
+
+msgid "Could not authorize chat nickname. Try again!"
+msgstr ""
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
+msgid "Could not commit. An unexpected error occurred."
+msgstr ""
+
+msgid "Could not connect to FogBugz, check your URL"
+msgstr ""
+
+msgid "Could not connect to Sentry. Refresh the page to try again."
+msgstr ""
+
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
+msgid "Could not create Wiki Repository at this time. Please try again later."
+msgstr ""
+
+msgid "Could not create environment"
+msgstr ""
+
+msgid "Could not create group"
+msgstr ""
+
+msgid "Could not create issue"
+msgstr ""
+
+msgid "Could not create project"
+msgstr ""
+
+msgid "Could not create wiki page"
+msgstr ""
+
+msgid "Could not delete chat nickname %{chat_name}."
+msgstr ""
+
+msgid "Could not delete wiki page"
+msgstr ""
+
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
+msgid "Could not fetch policy because existing policy YAML is invalid"
+msgstr ""
+
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "Could not find design."
+msgstr ""
+
+msgid "Could not find iteration"
+msgstr ""
+
+msgid "Could not get the data properly"
+msgstr ""
+
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not load usage counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+msgstr ""
+
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
+msgid "Could not revoke impersonation token %{token_name}."
+msgstr ""
+
+msgid "Could not revoke personal access token %{personal_access_token_name}."
+msgstr ""
+
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "Could not save group ID"
+msgstr ""
+
+msgid "Could not save project ID"
+msgstr ""
+
+msgid "Could not save prometheus manual configuration"
+msgstr ""
+
+msgid "Could not update the LDAP settings"
+msgstr ""
+
+msgid "Could not update wiki page"
+msgstr ""
+
+msgid "Could not upload your designs as one or more files uploaded are not supported."
+msgstr ""
+
+msgid "Couldn't assign policy to project"
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create %{workspace} label"
+msgstr ""
+
+msgid "Create Google Cloud project"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr ""
+
+msgid "Create a Mattermost team for this group"
+msgstr ""
+
+msgid "Create a merge request"
+msgstr ""
+
+msgid "Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new project"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+msgid "Create an incident. Incidents are created for each alert triggered."
+msgstr ""
+
+msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create common files more quickly, and standardize their format."
+msgstr ""
+
+msgid "Create confidential merge request"
+msgstr ""
+
+msgid "Create confidential merge request and branch"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create from"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create incident"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create issue to resolve all threads"
+msgstr ""
+
+msgid "Create iteration"
+msgstr ""
+
+msgid "Create label"
+msgstr ""
+
+msgid "Create list"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new"
+msgstr ""
+
+msgid "Create new %{name} by email"
+msgstr ""
+
+msgid "Create new CI/CD pipeline"
+msgstr ""
+
+msgid "Create new Value Stream"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new project"
+msgstr ""
+
+msgid "Create or import your first project"
+msgstr ""
+
+msgid "Create project"
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create release"
+msgstr ""
+
+msgid "Create requirement"
+msgstr ""
+
+msgid "Create service account"
+msgstr ""
+
+msgid "Create snippet"
+msgstr ""
+
+msgid "Create tag %{tagName}"
+msgstr ""
+
+msgid "Create topic"
+msgstr ""
+
+msgid "Create user"
+msgstr ""
+
+msgid "Create via merge request"
+msgstr ""
+
+msgid "Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "Create your group"
+msgstr ""
+
+msgid "Create/import your first project"
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr ""
+
+msgid "CreateValueStreamForm|Code stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create new Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
+msgstr ""
+
+msgid "CreateValueStreamForm|Edit value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Editing stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter value stream name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Issue stage end"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Plan stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select an end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore defaults"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Save value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage %{index}"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name already exists"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Update stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Created %{timestamp}"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created On"
+msgstr ""
+
+msgid "Created a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created by %{job}"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created by:"
+msgstr ""
+
+msgid "Created compliance violations if any were found"
+msgstr ""
+
+msgid "Created date"
+msgstr ""
+
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on %{created_at}"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creates a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creating"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
+msgstr ""
+
+msgid "Creation date"
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "CredentialsInventory|GPG Keys"
+msgstr ""
+
+msgid "CredentialsInventory|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Credit card:"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Crm|Contact has been added"
+msgstr ""
+
+msgid "Crm|Contact has been updated"
+msgstr ""
+
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Create organization"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Customer Relations Organizations"
+msgstr ""
+
+msgid "Crm|Default rate (optional)"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Edit contact"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New Organization"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|New organization"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Organization has been added"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crowd"
+msgstr ""
+
+msgid "CsvParser|Failed to render the CSV file for the following reasons:"
+msgstr ""
+
+msgid "CsvParser|Quoted field unterminated"
+msgstr ""
+
+msgid "CsvParser|Too few fields"
+msgstr ""
+
+msgid "CsvParser|Too many fields"
+msgstr ""
+
+msgid "CsvParser|Trailing quote on quoted field is malformed"
+msgstr ""
+
+msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
+msgstr ""
+
+msgid "Current"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current Project"
+msgstr ""
+
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
+msgid "Current node must be the primary node or you will be locking yourself out"
+msgstr ""
+
+msgid "Current password"
+msgstr ""
+
+msgid "Current sign-in IP:"
+msgstr ""
+
+msgid "Current sign-in at:"
+msgstr ""
+
+msgid "Current sign-in ip"
+msgstr ""
+
+msgid "Current vulnerabilities count"
+msgstr ""
+
+msgid "CurrentUser|Buy Pipeline minutes"
+msgstr ""
+
+msgid "CurrentUser|Edit profile"
+msgstr ""
+
+msgid "CurrentUser|One of your groups is running out"
+msgstr ""
+
+msgid "CurrentUser|Preferences"
+msgstr ""
+
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
+
+msgid "CurrentUser|Upgrade"
+msgstr ""
+
+msgid "Custom Attributes"
+msgstr ""
+
+msgid "Custom Git clone URL for HTTP(S)"
+msgstr ""
+
+msgid "Custom analyzers: language support"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom metrics"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Custom range"
+msgstr ""
+
+msgid "Custom range (UTC)"
+msgstr ""
+
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
+msgid "Customizable by an administrator."
+msgstr ""
+
+msgid "Customizable by owners."
+msgstr ""
+
+msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize icon"
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize name"
+msgstr ""
+
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
+
+msgid "Customize your pipeline configuration."
+msgstr ""
+
+msgid "Cycle Time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first commit time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first deployed to production"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build finish time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build start time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request merged"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Total"
+msgstr ""
+
+msgid "CycleAnalyticsStage|is not available for the selected group"
+msgstr ""
+
+msgid "CycleAnalyticsStage|should be under a group"
+msgstr ""
+
+msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
+msgstr ""
+
+msgid "CycleAnalytics|%{stageCount} stages selected"
+msgstr ""
+
+msgid "CycleAnalytics|All stages"
+msgstr ""
+
+msgid "CycleAnalytics|Average days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Date"
+msgstr ""
+
+msgid "CycleAnalytics|Days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Display chart filters"
+msgstr ""
+
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
+msgid "CycleAnalytics|No stages selected"
+msgstr ""
+
+msgid "CycleAnalytics|Number of tasks"
+msgstr ""
+
+msgid "CycleAnalytics|Only %{maxLabels} labels can be selected at this time"
+msgstr ""
+
+msgid "CycleAnalytics|Project selected"
+msgid_plural "CycleAnalytics|%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CycleAnalytics|Select labels"
+msgstr ""
+
+msgid "CycleAnalytics|Show"
+msgstr ""
+
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "CycleAnalytics|Stages"
+msgstr ""
+
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
+msgid "CycleAnalytics|The average time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
+msgid "CycleAnalytics|The given date range is larger than 180 days"
+msgstr ""
+
+msgid "CycleAnalytics|Type of work"
+msgstr ""
+
+msgid "CycleAnalytics|group dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|not allowed for the given start event"
+msgstr ""
+
+msgid "CycleAnalytics|project dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|stage dropdown"
+msgstr ""
+
+msgid "DAG visualization requires at least 3 dependent jobs."
+msgstr ""
+
+msgid "DAST Configuration"
+msgstr ""
+
+msgid "DAST Scans"
+msgstr ""
+
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "DORA4Metrics|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
+msgid "DORA4Metrics|Date"
+msgstr ""
+
+msgid "DORA4Metrics|Days from merge to deploy"
+msgstr ""
+
+msgid "DORA4Metrics|Deployment frequency"
+msgstr ""
+
+msgid "DORA4Metrics|Lead time for changes"
+msgstr ""
+
+msgid "DORA4Metrics|Median (last %{days}d)"
+msgstr ""
+
+msgid "DORA4Metrics|No merge requests were deployed during this period"
+msgstr ""
+
+msgid "DORA4Metrics|Number of deployments"
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting lead time data."
+msgstr ""
+
+msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
+msgstr ""
+
+msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
+msgstr ""
+
+msgid "DSN"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "Dashboard uid not found"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "DashboardProjects|Trending"
+msgstr ""
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+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 ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Authentication"
+msgstr ""
+
+msgid "DastProfiles|Authentication URL"
+msgstr ""
+
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not create the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not update the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not update the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this site profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard your changes?"
+msgstr ""
+
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
+msgid "DastProfiles|Edit scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Edit site profile"
+msgstr ""
+
+msgid "DastProfiles|Enable Authentication"
+msgstr ""
+
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Error Details"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
+msgid "DastProfiles|Manage DAST scans"
+msgstr ""
+
+msgid "DastProfiles|Manage profiles"
+msgstr ""
+
+msgid "DastProfiles|Manage site profiles"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
+msgstr ""
+
+msgid "DastProfiles|New site profile"
+msgstr ""
+
+msgid "DastProfiles|No scanner profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|No site profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|Not Validated"
+msgstr ""
+
+msgid "DastProfiles|Passive"
+msgstr ""
+
+msgid "DastProfiles|Password"
+msgstr ""
+
+msgid "DastProfiles|Password form field"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
+msgid "DastProfiles|Request headers"
+msgstr ""
+
+msgid "DastProfiles|Rest API"
+msgstr ""
+
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
+msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
+msgstr ""
+
+msgid "DastProfiles|Save profile"
+msgstr ""
+
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
+msgid "DastProfiles|Select branch"
+msgstr ""
+
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
+msgid "DastProfiles|Site Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site name"
+msgstr ""
+
+msgid "DastProfiles|Site type"
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Target URL"
+msgstr ""
+
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|URL"
+msgstr ""
+
+msgid "DastProfiles|URLs to skip during the authenticated scan."
+msgstr ""
+
+msgid "DastProfiles|Username"
+msgstr ""
+
+msgid "DastProfiles|Username form field"
+msgstr ""
+
+msgid "DastProfiles|Validated"
+msgstr ""
+
+msgid "DastProfiles|Validation status"
+msgstr ""
+
+msgid "DastProfiles|Website"
+msgstr ""
+
+msgid "DastProfiles|You can either choose a passive scan or validate the target site from the site profile management page. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
+msgstr ""
+
+msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
+msgstr ""
+
+msgid "DastSiteValidation|Copy HTTP header to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Copy Meta tag to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Could not create validation token. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Could not revoke validation. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Download validation text file"
+msgstr ""
+
+msgid "DastSiteValidation|Header validation"
+msgstr ""
+
+msgid "DastSiteValidation|Meta tag validation"
+msgstr ""
+
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
+msgid "DastSiteValidation|Revoke validation"
+msgstr ""
+
+msgid "DastSiteValidation|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add following HTTP header to your site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add following meta tag to your site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm header location and validate"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm meta tag location and validate"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm text file location and validate"
+msgstr ""
+
+msgid "DastSiteValidation|Text file validation"
+msgstr ""
+
+msgid "DastSiteValidation|The validation has failed. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|The validation is in progress. Please wait..."
+msgstr ""
+
+msgid "DastSiteValidation|This will affect %d other profile targeting the same URL."
+msgid_plural "DastSiteValidation|This will affect %d other profiles targeting the same URL."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "DastSiteValidation|To run an active scan, validate your target site. All site profiles that share the same base URL share the same validation status."
+msgstr ""
+
+msgid "DastSiteValidation|Validate"
+msgstr ""
+
+msgid "DastSiteValidation|Validate target site"
+msgstr ""
+
+msgid "DastSiteValidation|Validated"
+msgstr ""
+
+msgid "DastSiteValidation|Validating..."
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed"
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
+msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
+msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Data type"
+msgstr ""
+
+msgid "Database update failed"
+msgstr ""
+
+msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
+msgstr ""
+
+msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
+msgstr ""
+
+msgid "DatadogIntegration|API URL"
+msgstr ""
+
+msgid "DatadogIntegration|Environment"
+msgstr ""
+
+msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}"
+msgstr ""
+
+msgid "DatadogIntegration|How do I set up this integration?"
+msgstr ""
+
+msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues. %{docs_link}"
+msgstr ""
+
+msgid "DatadogIntegration|Service"
+msgstr ""
+
+msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments."
+msgstr ""
+
+msgid "DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}."
+msgstr ""
+
+msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
+msgstr ""
+
+msgid "Datasource name not found"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Date merged"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Date range"
+msgstr ""
+
+msgid "Date range limited to %{number} days"
+msgstr ""
+
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
+msgid "Day of month"
+msgstr ""
+
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
+msgid "Days"
+msgstr ""
+
+msgid "Days to merge"
+msgstr ""
+
+msgid "Deactivate dormant users after 90 days of inactivity"
+msgstr ""
+
+msgid "Dear Administrator,"
+msgstr ""
+
+msgid "Debian package already exists in Distribution"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Decompressed archive size validation failed."
+msgstr ""
+
+msgid "Decrease"
+msgstr ""
+
+msgid "Default CI/CD configuration file"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default branch protection"
+msgstr ""
+
+msgid "Default delayed project deletion"
+msgstr ""
+
+msgid "Default deletion delay"
+msgstr ""
+
+msgid "Default description template for issues"
+msgstr ""
+
+msgid "Default description template for merge requests"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default initial branch name"
+msgstr ""
+
+msgid "Default project deletion protection"
+msgstr ""
+
+msgid "Default projects limit"
+msgstr ""
+
+msgid "Default timeout"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "DefaultBranchLabel|default"
+msgstr ""
+
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define custom rules for what constitutes spam, independent of Akismet"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
+msgstr ""
+
+msgid "Define how approval rules are applied to merge requests."
+msgstr ""
+
+msgid "Definition"
+msgstr ""
+
+msgid "Delayed Project Deletion (%{adjourned_deletion})"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Run the delayed job now?"
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete %{issuableType}"
+msgstr ""
+
+msgid "Delete %{name}"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete Key"
+msgstr ""
+
+msgid "Delete Selected"
+msgstr ""
+
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete badge"
+msgstr ""
+
+msgid "Delete column"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete corpus"
+msgstr ""
+
+msgid "Delete deploy key"
+msgstr ""
+
+msgid "Delete file"
+msgstr ""
+
+msgid "Delete image repository"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{labelName}"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Delete row"
+msgstr ""
+
+msgid "Delete self monitoring project"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete subscription"
+msgstr ""
+
+msgid "Delete table"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete this epic and all descendants?"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+msgstr ""
+
+msgid "DeleteProject|Failed to remove events. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove webhooks. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteValueStream|'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
+msgstr ""
+
+msgid "DeleteValueStream|Delete %{name}"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deleted chat nickname: %{chat_name}!"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
+
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
+msgid "Deleting"
+msgstr ""
+
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "Deleting the project will delete its repository and all related resources, including issues and merge requests."
+msgstr ""
+
+msgid "Deletion pending. This project will be deleted on %{date}. Repository and other project resources are read-only."
+msgstr ""
+
+msgid "Denied"
+msgstr ""
+
+msgid "Denied authorization of chat nickname %{user_name}."
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny access request"
+msgstr ""
+
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies help page link"
+msgstr ""
+
+msgid "Dependencies|%d additional vulnerability not shown"
+msgid_plural "Dependencies|%d additional vulnerabilities not shown"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d vulnerability detected"
+msgid_plural "Dependencies|%d vulnerabilities detected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%{remainingLicensesCount} more"
+msgstr ""
+
+msgid "Dependencies|(top level)"
+msgstr ""
+
+msgid "Dependencies|All"
+msgstr ""
+
+msgid "Dependencies|Based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Dependency path"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
+msgid "Dependencies|License"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
+msgid "Dependencies|Toggle vulnerability list"
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Vulnerable components"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency List has no entries"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency Scanning"
+msgstr ""
+
+msgid "Dependency list"
+msgstr ""
+
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
+
+msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
+msgstr ""
+
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
+
+msgid "DependencyProxy|Copy prefix"
+msgstr ""
+
+msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|Storage settings"
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
+msgstr ""
+
+msgid "DependencyProxy|When enabled, images older than 90 days will be removed from the cache."
+msgstr ""
+
+msgid "Depends on %d merge request being merged"
+msgid_plural "Depends on %d merge requests being merged"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
+msgid "Deploy freezes"
+msgstr ""
+
+msgid "Deploy key was successfully updated."
+msgstr ""
+
+msgid "Deploy keys"
+msgstr ""
+
+msgid "Deploy keys grant read/write access to all repositories in your instance"
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
+msgstr ""
+
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Delete"
+msgstr ""
+
+msgid "DeployFreeze|Delete deploy freeze?"
+msgstr ""
+
+msgid "DeployFreeze|Delete freeze period"
+msgstr ""
+
+msgid "DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Grant write permissions to this key"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows read and write access to the package registry."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the package registry."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository."
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+msgid "DeployTokens|Copy username"
+msgstr ""
+
+msgid "DeployTokens|Create a new deploy token for all projects in this group. %{link_start}What are deploy tokens?%{link_end}"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+msgstr ""
+
+msgid "DeployTokens|Enter a unique name for your deploy token."
+msgstr ""
+
+msgid "DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}."
+msgstr ""
+
+msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|New deploy token"
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|Your new Deploy Token username"
+msgstr ""
+
+msgid "DeployTokens|Your new group deploy token has been created."
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deploying to AWS is easy with GitLab"
+msgstr ""
+
+msgid "Deployment Frequency"
+msgstr ""
+
+msgid "Deployment frequency"
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
+msgid "Deployments|%{deployments} environment impacted."
+msgid_plural "Deployments|%{deployments} environments impacted."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deployment|API"
+msgstr ""
+
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
+msgid "Deployment|This deployment was created using the API"
+msgstr ""
+
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
+msgid "Deployment|canceled"
+msgstr ""
+
+msgid "Deployment|created"
+msgstr ""
+
+msgid "Deployment|failed"
+msgstr ""
+
+msgid "Deployment|running"
+msgstr ""
+
+msgid "Deployment|skipped"
+msgstr ""
+
+msgid "Deployment|success"
+msgstr ""
+
+msgid "Deprecated API rate limits"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Describe the goal of the changes and what reviewers should be aware of."
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description (optional)"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
+msgid "Description template"
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Design Management files and data"
+msgstr ""
+
+msgid "Design repositories"
+msgstr ""
+
+msgid "Design repository"
+msgstr ""
+
+msgid "DesignManagement|%{current_design} of %{designs_count}"
+msgstr ""
+
+msgid "DesignManagement|%{filename} did not change."
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
+msgstr ""
+
+msgid "DesignManagement|Archive design"
+msgstr ""
+
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "DesignManagement|Cancel changes"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment confirmation"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment update confirmation"
+msgstr ""
+
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
+
+msgid "DesignManagement|Comment"
+msgstr ""
+
+msgid "DesignManagement|Comments you resolve can be viewed and unresolved by going to the \"Resolved Comments\" section below"
+msgstr ""
+
+msgid "DesignManagement|Could not add a new comment. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not create new discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update note. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Deselect all"
+msgstr ""
+
+msgid "DesignManagement|Designs"
+msgstr ""
+
+msgid "DesignManagement|Discard comment"
+msgstr ""
+
+msgid "DesignManagement|Download design"
+msgstr ""
+
+msgid "DesignManagement|Error uploading a new design. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Go back to designs"
+msgstr ""
+
+msgid "DesignManagement|Go to next design"
+msgstr ""
+
+msgid "DesignManagement|Go to previous design"
+msgstr ""
+
+msgid "DesignManagement|Keep changes"
+msgstr ""
+
+msgid "DesignManagement|Keep comment"
+msgstr ""
+
+msgid "DesignManagement|Learn more about resolving comments"
+msgstr ""
+
+msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
+msgstr ""
+
+msgid "DesignManagement|Resolve thread"
+msgstr ""
+
+msgid "DesignManagement|Resolved Comments"
+msgstr ""
+
+msgid "DesignManagement|Save comment"
+msgstr ""
+
+msgid "DesignManagement|Select all"
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
+msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
+msgstr ""
+
+msgid "DesignManagement|To upload designs, you'll need to enable LFS and have an admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+msgstr ""
+
+msgid "DesignManagement|Unresolve thread"
+msgstr ""
+
+msgid "DesignManagement|Upload designs"
+msgstr ""
+
+msgid "DesignManagement|Upload skipped. %{reason}"
+msgstr ""
+
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps Adoption"
+msgstr ""
+
+msgid "DevOps Reports"
+msgstr ""
+
+msgid "DevOps adoption"
+msgstr ""
+
+msgid "Devices (optional)"
+msgstr ""
+
+msgid "DevopsAdoption|%{adoptedCount}/%{featuresCount} %{title} features adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Add a group to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add or remove groups"
+msgstr ""
+
+msgid "DevopsAdoption|Add or remove subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption by group"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption by subgroup"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
+msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on a merge request"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
+msgstr ""
+
+msgid "DevopsAdoption|At least one issue opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one merge request opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one pipeline successfully run"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Confirm remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|DAST"
+msgstr ""
+
+msgid "DevopsAdoption|DAST enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Dependency Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
+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 ""
+
+msgid "DevopsAdoption|Edit groups"
+msgstr ""
+
+msgid "DevopsAdoption|Edit subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Feature adoption is based on usage in the previous calendar month. Data is updated at the beginning of each month. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsAdoption|Fuzz Testing"
+msgstr ""
+
+msgid "DevopsAdoption|Fuzz Testing enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|No results…"
+msgstr ""
+
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
+msgid "DevopsAdoption|Not adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
+msgid "DevopsAdoption|Overall adoption"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group from the table."
+msgstr ""
+
+msgid "DevopsAdoption|Runner configured for project/group"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|SAST"
+msgstr ""
+
+msgid "DevopsAdoption|SAST enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
+msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|This group has no subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
+msgid "DevopsAdoption|You cannot remove the group you are currently in."
+msgstr ""
+
+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|High"
+msgstr ""
+
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
+msgstr ""
+
+msgid "DevopsReport|Overview"
+msgstr ""
+
+msgid "DevopsReport|Score"
+msgstr ""
+
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
+msgid "Didn't receive a confirmation email?"
+msgstr ""
+
+msgid "Didn't receive confirmation instructions?"
+msgstr ""
+
+msgid "Didn't receive unlock instructions?"
+msgstr ""
+
+msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|%d addition"
+msgid_plural "Diffs|%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|%d deletion"
+msgid_plural "Diffs|%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
+msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Diffs|with %{additions} and %{deletions}"
+msgstr ""
+
+msgid "Direct member"
+msgstr ""
+
+msgid "Direct non-authenticated users to this page."
+msgstr ""
+
+msgid "Direct users to this page after they sign out."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
+msgid "Disable Two-factor Authentication"
+msgstr ""
+
+msgid "Disable What's new"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group 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 ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Send notifications about project events to a Discord channel."
+msgstr ""
+
+msgid "Discover"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
+msgstr ""
+
+msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
+msgstr ""
+
+msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
+msgstr ""
+
+msgid "Discover|Start a free trial"
+msgstr ""
+
+msgid "Discover|Upgrade now"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question."
+msgstr ""
+
+msgid "Discussion to reply to cannot be found"
+msgstr ""
+
+msgid "Disk Usage"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss %d selected vulnerability as"
+msgid_plural "Dismiss %d selected vulnerabilities as"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dismiss merge request promotion"
+msgstr ""
+
+msgid "Dismiss selected"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Dismissable"
+msgstr ""
+
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
+msgid "Display alerts from all configured monitoring tools."
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Display time tracking in issues in total hours only."
+msgstr ""
+
+msgid "Do not display content for customer experience improvement and offers from third parties"
+msgstr ""
+
+msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
+msgstr ""
+
+msgid "Do you want to remove this deploy key?"
+msgstr ""
+
+msgid "Dockerfile"
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Documentation pages URL"
+msgstr ""
+
+msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
+msgstr ""
+
+msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
+msgstr ""
+
+msgid "Does not delete the source branch."
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Domain Name"
+msgstr ""
+
+msgid "Don't have an account yet?"
+msgstr ""
+
+msgid "Don't include description in commit message"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
+msgid "Don't send service data"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Dormant users"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download (%{fileSizeReadable})"
+msgstr ""
+
+msgid "Download (%{size})"
+msgstr ""
+
+msgid "Download CSV"
+msgstr ""
+
+msgid "Download PDF"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download as"
+msgstr ""
+
+msgid "Download codes"
+msgstr ""
+
+msgid "Download evidence JSON"
+msgstr ""
+
+msgid "Download export"
+msgstr ""
+
+msgid "Download image"
+msgstr ""
+
+msgid "Download raw data (.csv)"
+msgstr ""
+
+msgid "Download source code"
+msgstr ""
+
+msgid "Download this directory"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Draft"
+msgstr ""
+
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
+msgstr ""
+
+msgid "Drop your designs to start your upload."
+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 "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
+msgid "Due Date"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "Duration"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "E-mail:"
+msgstr ""
+
+msgid "Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{issuable}"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Comment"
+msgstr ""
+
+msgid "Edit Deploy Key"
+msgstr ""
+
+msgid "Edit Geo Site"
+msgstr ""
+
+msgid "Edit Group Hook"
+msgstr ""
+
+msgid "Edit Identity"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Password"
+msgstr ""
+
+msgid "Edit Pipeline Schedule"
+msgstr ""
+
+msgid "Edit Release"
+msgstr ""
+
+msgid "Edit Requirement"
+msgstr ""
+
+msgid "Edit Slack integration"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit System Hook"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit commit message"
+msgstr ""
+
+msgid "Edit deploy freeze"
+msgstr ""
+
+msgid "Edit deploy key"
+msgstr ""
+
+msgid "Edit description"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit epics"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit fork in Web IDE"
+msgstr ""
+
+msgid "Edit group application"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit in Web IDE"
+msgstr ""
+
+msgid "Edit in single-file editor"
+msgstr ""
+
+msgid "Edit inline"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Edit merge requests"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit sidebar"
+msgstr ""
+
+msgid "Edit table"
+msgstr ""
+
+msgid "Edit this file only."
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit title and description"
+msgstr ""
+
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
+msgid "Edit user: %{user_name}"
+msgstr ""
+
+msgid "Edit wiki page"
+msgstr ""
+
+msgid "Edit your most recent comment in a thread (from an empty textarea)"
+msgstr ""
+
+msgid "Edited"
+msgstr ""
+
+msgid "Edited %{timeago}"
+msgstr ""
+
+msgid "Editing"
+msgstr ""
+
+msgid "Elapsed time"
+msgstr ""
+
+msgid "Elasticsearch AWS IAM credentials"
+msgstr ""
+
+msgid "Elasticsearch HTTP client timeout value in seconds."
+msgstr ""
+
+msgid "Elasticsearch indexing"
+msgstr ""
+
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
+msgid "Elasticsearch migration halted"
+msgstr ""
+
+msgid "Elasticsearch reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
+msgid "Elasticsearch returned status code: %{status_code}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elasticsearch's region."
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Eligible users"
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email a new %{name} to this project"
+msgstr ""
+
+msgid "Email address suffix"
+msgstr ""
+
+msgid "Email address to use for Support Desk"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+msgstr ""
+
+msgid "Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Email not verified. Please verify your email in Salesforce."
+msgstr ""
+
+msgid "Email notification for unknown sign-ins"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipeline status to a list of recipients."
+msgstr ""
+
+msgid "Email updates (optional)"
+msgstr ""
+
+msgid "Email:"
+msgstr ""
+
+msgid "Email: %{email}"
+msgstr ""
+
+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 ""
+
+msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't find the project. Please check if there's any typo."
+msgstr ""
+
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|and %{moreCount} more"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
+
+msgid "Emails sent to %{email} are also supported."
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace."
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains})."
+msgstr ""
+
+msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
+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 Amazon EKS integration"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
+msgid "Enable Kroki"
+msgstr ""
+
+msgid "Enable Mailgun event receiver"
+msgstr ""
+
+msgid "Enable PlantUML"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable Registration Features"
+msgstr ""
+
+msgid "Enable SSL verification"
+msgstr ""
+
+msgid "Enable Sentry error tracking"
+msgstr ""
+
+msgid "Enable Service Ping"
+msgstr ""
+
+msgid "Enable Snowplow tracking"
+msgstr ""
+
+msgid "Enable Spam Check via external API endpoint"
+msgstr ""
+
+msgid "Enable What's new: All tiers"
+msgstr ""
+
+msgid "Enable What's new: Current tier only"
+msgstr ""
+
+msgid "Enable a Prometheus endpoint that exposes health and performance statistics. The Health Check menu item appears in the Monitoring section of the Admin Area. Restart required."
+msgstr ""
+
+msgid "Enable access to the performance bar for non-administrators in a given group."
+msgstr ""
+
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
+msgid "Enable admin mode"
+msgstr ""
+
+msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Enable authenticated API request rate limit"
+msgstr ""
+
+msgid "Enable authenticated Git LFS request rate limit"
+msgstr ""
+
+msgid "Enable authenticated web request rate limit"
+msgstr ""
+
+msgid "Enable authentication"
+msgstr ""
+
+msgid "Enable automatic repository housekeeping"
+msgstr ""
+
+msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
+msgstr ""
+
+msgid "Enable delayed project deletion by default for newly-created groups."
+msgstr ""
+
+msgid "Enable email notification"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable feature to choose access level"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group runners"
+msgstr ""
+
+msgid "Enable header and footer in emails"
+msgstr ""
+
+msgid "Enable health and performance metrics endpoint"
+msgstr ""
+
+msgid "Enable in-product marketing emails"
+msgstr ""
+
+msgid "Enable incident management inbound alert limit"
+msgstr ""
+
+msgid "Enable integration"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
+msgid "Enable logs collection"
+msgstr ""
+
+msgid "Enable maintenance mode"
+msgstr ""
+
+msgid "Enable multipart emails"
+msgstr ""
+
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and Service Ping."
+msgstr ""
+
+msgid "Enable rate limiting for POST requests to the specified paths"
+msgstr ""
+
+msgid "Enable reCAPTCHA"
+msgstr ""
+
+msgid "Enable reCAPTCHA for login."
+msgstr ""
+
+msgid "Enable repository checks"
+msgstr ""
+
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable shared runners for this project"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable unauthenticated API request rate limit"
+msgstr ""
+
+msgid "Enable unauthenticated web request rate limit"
+msgstr ""
+
+msgid "Enable user deactivation emails"
+msgstr ""
+
+msgid "Enable version check"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
+msgstr ""
+
+msgid "EnableReviewApp|Close"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet text"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Enabled Git access protocols"
+msgstr ""
+
+msgid "Enabled OAuth authentication sources"
+msgstr ""
+
+msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
+msgstr ""
+
+msgid "Encountered an error while rendering: %{err}"
+msgstr ""
+
+msgid "End Time"
+msgstr ""
+
+msgid "Ends"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
+msgid "Enforce SSH key expiration"
+msgstr ""
+
+msgid "Enforce personal access token expiration"
+msgstr ""
+
+msgid "Enforce two-factor authentication"
+msgstr ""
+
+msgid "Enforce two-factor authentication for all user sign-ins."
+msgstr ""
+
+msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
+msgstr ""
+
+msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd} of your CI pipeline to track deployments to your cluster."
+msgstr ""
+
+msgid "Enter %{weights_link_start}weights%{weights_link_end} for storages for new repositories. Configured storages appear below."
+msgstr ""
+
+msgid "Enter 2FA for Admin Mode"
+msgstr ""
+
+msgid "Enter Admin Mode"
+msgstr ""
+
+msgid "Enter a number"
+msgstr ""
+
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter license key"
+msgstr ""
+
+msgid "Enter merge request URLs"
+msgstr ""
+
+msgid "Enter new AWS Secret Access Key"
+msgstr ""
+
+msgid "Enter number of issues"
+msgstr ""
+
+msgid "Enter one or more user ID separated by commas"
+msgstr ""
+
+msgid "Enter the %{name} description"
+msgstr ""
+
+msgid "Enter the %{name} title"
+msgstr ""
+
+msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
+msgstr ""
+
+msgid "Enter the name of your application, and we'll return a unique %{type}."
+msgstr ""
+
+msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
+msgid "Enter the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter your Packagist server. Defaults to https://packagist.org."
+msgstr ""
+
+msgid "Enter your Packagist token."
+msgstr ""
+
+msgid "Enter your Packagist username."
+msgstr ""
+
+msgid "Enter your password to approve"
+msgstr ""
+
+msgid "Enterprise"
+msgstr ""
+
+msgid "Environment"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Environment does not have deployments"
+msgstr ""
+
+msgid "Environment is required for Stages::MetricEndpointInserter"
+msgstr ""
+
+msgid "Environment is required for Stages::VariableEndpointInserter"
+msgstr ""
+
+msgid "Environment scope"
+msgstr ""
+
+msgid "Environment variable %{code_start}%{environment_variable}%{code_end} does not exist or is not pointing to a valid directory."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "EnvironmentDashboard|API"
+msgstr ""
+
+msgid "EnvironmentDashboard|Created through the Deployment API"
+msgstr ""
+
+msgid "EnvironmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments Dashboard"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
+msgstr ""
+
+msgid "Environments in %{name}"
+msgstr ""
+
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
+msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "Environments|An error occurred while canceling the auto stop, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while re-deploying the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while rolling back the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Auto stop"
+msgstr ""
+
+msgid "Environments|Auto stops %{autoStopAt}"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Currently showing %{fetched} results."
+msgstr ""
+
+msgid "Environments|Currently showing all results."
+msgstr ""
+
+msgid "Environments|Delete"
+msgstr ""
+
+msgid "Environments|Delete '%{environmentName}'?"
+msgstr ""
+
+msgid "Environments|Delete environment"
+msgstr ""
+
+msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
+msgid "Environments|Enable review app"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Install Elastic Stack on your cluster to enable advanced querying capabilities such as full text search."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn about environments"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|Logs from %{start} to %{end}."
+msgstr ""
+
+msgid "Environments|More information"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployed environments"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod selected"
+msgstr ""
+
+msgid "Environments|No pods to display"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Open"
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod name"
+msgstr ""
+
+msgid "Environments|Re-deploy"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Rollback"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Rollback environment %{name}?"
+msgstr ""
+
+msgid "Environments|Select pod"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping %{environmentName}"
+msgstr ""
+
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
+msgid "Environments|There was an error fetching the logs. Please try again."
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|by %{avatar}"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic Boards"
+msgstr ""
+
+msgid "Epic cannot be found."
+msgstr ""
+
+msgid "Epic details"
+msgstr ""
+
+msgid "Epic events"
+msgstr ""
+
+msgid "Epic not found for given params"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics and Issues"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics, issues, and merge requests"
+msgstr ""
+
+msgid "Epics|%{startDate} – %{dueDate}"
+msgstr ""
+
+msgid "Epics|%{startDate} – No due date"
+msgstr ""
+
+msgid "Epics|Add a new epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|An error occurred while updating labels."
+msgstr ""
+
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Assign Epic"
+msgstr ""
+
+msgid "Epics|Enter a title for your epic"
+msgstr ""
+
+msgid "Epics|Leave empty to inherit from milestone dates"
+msgstr ""
+
+msgid "Epics|No start date – %{dueDate}"
+msgstr ""
+
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
+msgid "Epics|Show more"
+msgstr ""
+
+msgid "Epics|Something went wrong while assigning issue to epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating issue."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching epics list."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching group epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while moving item."
+msgstr ""
+
+msgid "Epics|Something went wrong while ordering item."
+msgstr ""
+
+msgid "Epics|Something went wrong while removing issue from epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while updating epics."
+msgstr ""
+
+msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|Unable to save epic. Please try again"
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Details"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error creating label."
+msgstr ""
+
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
+msgid "Error creating new iteration"
+msgstr ""
+
+msgid "Error creating repository for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Error creating the snippet"
+msgstr ""
+
+msgid "Error deleting project. Check logs for error details."
+msgstr ""
+
+msgid "Error fetching burnup chart data"
+msgstr ""
+
+msgid "Error fetching diverging counts for branches. Please try again."
+msgstr ""
+
+msgid "Error fetching forked projects. Please try again."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching payload data."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading countries data."
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
+msgid "Error loading issues"
+msgstr ""
+
+msgid "Error loading iterations"
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading milestone tab"
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
+msgid "Error occurred when saving assignees"
+msgstr ""
+
+msgid "Error occurred when saving reviewers"
+msgstr ""
+
+msgid "Error occurred while updating the %{issuableType} status"
+msgstr ""
+
+msgid "Error occurred while updating the issue status"
+msgstr ""
+
+msgid "Error occurred while updating the issue weight"
+msgstr ""
+
+msgid "Error occurred. A blocked user cannot be deactivated"
+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 ""
+
+msgid "Error occurred. User was not unlocked"
+msgstr ""
+
+msgid "Error parsing CSV file. Please make sure it has"
+msgstr ""
+
+msgid "Error rendering Markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error setting up editor. Please try again."
+msgstr ""
+
+msgid "Error tracking"
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all to-do items."
+msgstr ""
+
+msgid "Error updating status of to-do item."
+msgstr ""
+
+msgid "Error updating the snippet"
+msgstr ""
+
+msgid "Error uploading file"
+msgstr ""
+
+msgid "Error uploading file. Please try again."
+msgstr ""
+
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error while migrating %{upload_id}: %{error_message}"
+msgstr ""
+
+msgid "Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Error: %{error_message}"
+msgstr ""
+
+msgid "Error: %{error}"
+msgstr ""
+
+msgid "Error: Couldn't load some or all of the changes."
+msgstr ""
+
+msgid "Error: No AWS credentials were supplied"
+msgstr ""
+
+msgid "Error: No AWS provision role found for user"
+msgstr ""
+
+msgid "Error: Unable to create deploy freeze"
+msgstr ""
+
+msgid "Error: Unable to delete deploy freeze"
+msgstr ""
+
+msgid "Error: Unable to find AWS role for current user"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection failed. Check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|Enable error tracking"
+msgstr ""
+
+msgid "ErrorTracking|Error tracking backend"
+msgstr ""
+
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
+
+msgid "ErrorTracking|No projects available"
+msgstr ""
+
+msgid "ErrorTracking|Select project"
+msgstr ""
+
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
+msgstr ""
+
+msgid "Errors:"
+msgstr ""
+
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies may not have more than %{rule_count} rules"
+msgstr ""
+
+msgid "Escalation policies must have at least one rule"
+msgstr ""
+
+msgid "Escalation policy:"
+msgstr ""
+
+msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
+msgstr ""
+
+msgid "EscalationPolicies|%{notificationIcon} THEN %{doAction} %{forScheduleOrUser}"
+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|A user is required for adding an escalation policy."
+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|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Email user"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation policies"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
+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|Maximum of 10 rules has been reached."
+msgstr ""
+
+msgid "EscalationPolicies|Minutes must be between 0 and 1440."
+msgstr ""
+
+msgid "EscalationPolicies|Remove escalation rule"
+msgstr ""
+
+msgid "EscalationPolicies|Search for user"
+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} %{scheduleOrUser}"
+msgstr ""
+
+msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
+msgstr ""
+
+msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
+msgstr ""
+
+msgid "EscalationPolicies|This policy has no escalation rules."
+msgstr ""
+
+msgid "EscalationPolicies|mins"
+msgstr ""
+
+msgid "Estimate"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by designs"
+msgstr ""
+
+msgid "EventFilterBy|Filter by epic events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "EventFilterBy|Filter by wiki"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every 3 months"
+msgstr ""
+
+msgid "Every 3 months on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every 6 months"
+msgstr ""
+
+msgid "Every 6 months on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every day"
+msgstr ""
+
+msgid "Every day (at %{time})"
+msgstr ""
+
+msgid "Every day at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every month"
+msgstr ""
+
+msgid "Every month (Day %{day} at %{time})"
+msgstr ""
+
+msgid "Every month on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every three months"
+msgstr ""
+
+msgid "Every two weeks"
+msgstr ""
+
+msgid "Every week"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Every week (%{weekday} at %{time})"
+msgstr ""
+
+msgid "Every week on %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every year"
+msgstr ""
+
+msgid "Every year on %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Everyone With Access"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything on your to-do list is marked as done."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Gatsby"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
+
+msgid "Evidence collection"
+msgstr ""
+
+msgid "Exactly one of %{attributes} is required"
+msgstr ""
+
+msgid "Example: @sub\\.company\\.com$"
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Exceptions"
+msgstr ""
+
+msgid "Excluding merge commits. Limited to %{limit} commits."
+msgstr ""
+
+msgid "Excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "Execution time"
+msgstr ""
+
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "Existing projects may be moved into a group"
+msgstr ""
+
+msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
+msgstr ""
+
+msgid "Existing sign in methods may be removed"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand all files"
+msgstr ""
+
+msgid "Expand all threads"
+msgstr ""
+
+msgid "Expand approvers"
+msgstr ""
+
+msgid "Expand file"
+msgstr ""
+
+msgid "Expand issues"
+msgstr ""
+
+msgid "Expand milestones"
+msgstr ""
+
+msgid "Expand panel"
+msgstr ""
+
+msgid "Expand pipeline"
+msgstr ""
+
+msgid "Expand settings section"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "ExperimentSubject|Must have exactly one of User, Namespace, or Project."
+msgstr ""
+
+msgid "Expiration"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expiration date (optional)"
+msgstr ""
+
+msgid "Expiration date:"
+msgstr ""
+
+msgid "Expired"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expired:"
+msgstr ""
+
+msgid "Expires"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Expires on"
+msgstr ""
+
+msgid "Expires:"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
+msgid "Export"
+msgstr ""
+
+msgid "Export %{requirementsCount} requirements?"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export commit custody report"
+msgstr ""
+
+msgid "Export group"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
+msgid "Export project"
+msgstr ""
+
+msgid "Export requirements"
+msgstr ""
+
+msgid "Export this group with all related data."
+msgstr ""
+
+msgid "Export this project with all its related data in order to move it to a new GitLab instance. When the exported file is ready, you can download it from this page or from the download link in the email notification you will receive. You can then import it when creating a new project. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Export variable to pipelines running on protected branches and tags only."
+msgstr ""
+
+msgid "Exported requirements"
+msgstr ""
+
+msgid "External ID"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External User:"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External storage URL"
+msgstr ""
+
+msgid "External storage authentication token"
+msgstr ""
+
+msgid "External storage for repository static objects"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
+
+msgid "ExternalWikiService|Link to an external wiki from the sidebar."
+msgstr ""
+
+msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed on"
+msgstr ""
+
+msgid "Failed to add a Zoom meeting"
+msgstr ""
+
+msgid "Failed to apply commands."
+msgstr ""
+
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Failed to assign a reviewer because no user was found."
+msgstr ""
+
+msgid "Failed to assign a user because no user was found."
+msgstr ""
+
+msgid "Failed to cancel auto stop because failed to update the environment."
+msgstr ""
+
+msgid "Failed to cancel auto stop because the environment is not set as auto stop."
+msgstr ""
+
+msgid "Failed to cancel auto stop because you do not have permission to update the environment."
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to clone this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to clone this issue: wrong parameters."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create a to-do item for the design."
+msgstr ""
+
+msgid "Failed to create framework"
+msgstr ""
+
+msgid "Failed to create import label for jira import."
+msgstr ""
+
+msgid "Failed to create new access token: %{token_response_message}"
+msgstr ""
+
+msgid "Failed to create repository"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr ""
+
+msgid "Failed to create wiki"
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
+msgstr ""
+
+msgid "Failed to fetch the iteration for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to fetch the iterations for the group. Please try again."
+msgstr ""
+
+msgid "Failed to find import label for Jira import."
+msgstr ""
+
+msgid "Failed to generate export, please try again later."
+msgstr ""
+
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
+msgid "Failed to load"
+msgstr ""
+
+msgid "Failed to load assignees."
+msgstr ""
+
+msgid "Failed to load assignees. Please try again."
+msgstr ""
+
+msgid "Failed to load authors. Please try again."
+msgstr ""
+
+msgid "Failed to load branches. Please try again."
+msgstr ""
+
+msgid "Failed to load deploy keys."
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load error details from Sentry."
+msgstr ""
+
+msgid "Failed to load errors from Sentry."
+msgstr ""
+
+msgid "Failed to load group activity metrics. Please try again."
+msgstr ""
+
+msgid "Failed to load groups, users and deploy keys."
+msgstr ""
+
+msgid "Failed to load iterations."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+msgstr ""
+
+msgid "Failed to load milestones."
+msgstr ""
+
+msgid "Failed to load milestones. Please try again."
+msgstr ""
+
+msgid "Failed to load projects"
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
+msgid "Failed to load stacktrace."
+msgstr ""
+
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
+msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
+msgstr ""
+
+msgid "Failed to move this issue because label was not found."
+msgstr ""
+
+msgid "Failed to move this issue because only a single label can be provided."
+msgstr ""
+
+msgid "Failed to move this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to promote issue to incident"
+msgstr ""
+
+msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr ""
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
+msgid "Failed to publish issue on status page."
+msgstr ""
+
+msgid "Failed to remove a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove a to-do item for the design."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to remove user identity."
+msgstr ""
+
+msgid "Failed to remove user key."
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to retrieve page"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
+msgid "Failed to save new settings"
+msgstr ""
+
+msgid "Failed to save preferences (%{error_message})."
+msgstr ""
+
+msgid "Failed to save preferences."
+msgstr ""
+
+msgid "Failed to set due date because the date format is invalid."
+msgstr ""
+
+msgid "Failed to set iteration on this issue. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to toggle the to-do status for the design."
+msgstr ""
+
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
+msgid "Failed to update framework"
+msgstr ""
+
+msgid "Failed to update issue status"
+msgstr ""
+
+msgid "Failed to update the Canary Ingress."
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "False positive"
+msgstr ""
+
+msgid "Fast timeout"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster releases. Better code. Less pain."
+msgstr ""
+
+msgid "Favicon"
+msgstr ""
+
+msgid "Favicon was successfully removed."
+msgstr ""
+
+msgid "Favicon will be removed. Are you sure?"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "Feature flag status"
+msgstr ""
+
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
+msgid "FeatureFlags|%d user"
+msgid_plural "FeatureFlags|%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Add strategy"
+msgstr ""
+
+msgid "FeatureFlags|All Environments"
+msgstr ""
+
+msgid "FeatureFlags|All Users"
+msgstr ""
+
+msgid "FeatureFlags|All users"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Edit User List"
+msgstr ""
+
+msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+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 ""
+
+msgid "FeatureFlags|Feature Flag has no strategies"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|List details"
+msgstr ""
+
+msgid "FeatureFlags|Loading feature flags"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|New User List"
+msgstr ""
+
+msgid "FeatureFlags|New feature flag"
+msgstr ""
+
+msgid "FeatureFlags|No user list selected"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Strategies"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+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 ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "FeatureFlags|User IDs"
+msgstr ""
+
+msgid "FeatureFlags|User List"
+msgstr ""
+
+msgid "FeatureFlags|User Lists"
+msgstr ""
+
+msgid "FeatureFlags|View user lists"
+msgstr ""
+
+msgid "FeatureFlag|Percentage"
+msgstr ""
+
+msgid "FeatureFlag|Select a user list"
+msgstr ""
+
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
+msgid "FeatureFlag|There are no configured user lists"
+msgstr ""
+
+msgid "FeatureFlag|Type"
+msgstr ""
+
+msgid "FeatureFlag|User IDs"
+msgstr ""
+
+msgid "FeatureFlag|User List"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fetch and check out the branch for this merge request"
+msgstr ""
+
+msgid "Fetching incoming email"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "File %{current} of %{total}"
+msgstr ""
+
+msgid "File Hooks"
+msgstr ""
+
+msgid "File Hooks (%{count})"
+msgstr ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File name"
+msgstr ""
+
+msgid "File renamed with no changes."
+msgstr ""
+
+msgid "File suppressed by a .gitattributes entry or the file's encoding is unsupported."
+msgstr ""
+
+msgid "File synchronization concurrency limit"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Filename"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files API Rate Limits"
+msgstr ""
+
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by"
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently open."
+msgstr ""
+
+msgid "Filter by Git revision"
+msgstr ""
+
+msgid "Filter by issues that are currently closed."
+msgstr ""
+
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
+msgid "Filter by label"
+msgstr ""
+
+msgid "Filter by merge requests that are currently closed and unmerged."
+msgstr ""
+
+msgid "Filter by merge requests that are currently merged."
+msgstr ""
+
+msgid "Filter by milestone"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently open."
+msgstr ""
+
+msgid "Filter by user"
+msgstr ""
+
+msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
+msgstr ""
+
+msgid "Filter pipelines"
+msgstr ""
+
+msgid "Filter results"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter results..."
+msgstr ""
+
+msgid "Filter users"
+msgstr ""
+
+msgid "Filter your repositories by name"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find File"
+msgstr ""
+
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
+msgid "Find bugs in your code with coverage-guided fuzzing."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Fingerprint"
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish setting up your dedicated account for %{group_name}."
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "Finished at"
+msgstr ""
+
+msgid "First Name"
+msgstr ""
+
+msgid "First Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed burndown chart"
+msgstr ""
+
+msgid "Fixed:"
+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 ""
+
+msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows."
+msgstr ""
+
+msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}"
+msgstr ""
+
+msgid "Focus filter bar"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Folder/%{name}"
+msgstr ""
+
+msgid "Follow"
+msgstr ""
+
+msgid "Followed Users' Activity"
+msgstr ""
+
+msgid "Followed users"
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For a faster browsing experience, some files are collapsed by default."
+msgstr ""
+
+msgid "For additional information, review your %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For additional information, review your group membership: %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For each job, clone the repository."
+msgstr ""
+
+msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
+msgstr ""
+
+msgid "For example, the application using the token or the purpose of the token."
+msgstr ""
+
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
+msgid "For general work"
+msgstr ""
+
+msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
+msgstr ""
+
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_service_ping_link_start}deactivating service ping%{deactivating_service_ping_link_end}."
+msgstr ""
+
+msgid "Forgot your password?"
+msgstr ""
+
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
+msgid "Fork project?"
+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 ""
+
+msgid "ForkProject|Create a group"
+msgstr ""
+
+msgid "ForkProject|Fork project"
+msgstr ""
+
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
+msgid "ForkProject|Internal"
+msgstr ""
+
+msgid "ForkProject|Please select a namespace"
+msgstr ""
+
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
+msgid "ForkProject|Private"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "ForkProject|Public"
+msgstr ""
+
+msgid "ForkProject|Select a namespace"
+msgstr ""
+
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
+msgid "ForkProject|The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "ForkProject|The project can be accessed without any authentication."
+msgstr ""
+
+msgid "ForkProject|Visibility level"
+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 ""
+
+msgid "ForkedFromProjectPath|Forked from an inaccessible project"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format: %{dateFormat}"
+msgstr ""
+
+msgid "Forward %{package_type} package requests to the %{registry_type} Registry if the packages are not found in the GitLab Package Registry"
+msgstr ""
+
+msgid "Found errors in your %{gitlab_ci_yml}:"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Framework successfully deleted"
+msgstr ""
+
+msgid "Free"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Ultimate"
+msgstr ""
+
+msgid "Freeze end"
+msgstr ""
+
+msgid "Freeze start"
+msgstr ""
+
+msgid "Frequency"
+msgstr ""
+
+msgid "Frequently searched"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "From %{code_open}%{source_title}%{code_close} into"
+msgstr ""
+
+msgid "From %{providerTitle}"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "Full"
+msgstr ""
+
+msgid "Full log"
+msgstr ""
+
+msgid "Full name"
+msgstr ""
+
+msgid "GPG Key ID:"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
+msgid "GPG signature (loading...)"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General Settings"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "General settings"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Generate new export"
+msgstr ""
+
+msgid "Generate new token"
+msgstr ""
+
+msgid "Generate project access tokens scoped to this project for your applications that need access to the GitLab API."
+msgstr ""
+
+msgid "Generate site and private keys at"
+msgstr ""
+
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
+msgid "Generic"
+msgstr ""
+
+msgid "Generic package file size in bytes"
+msgstr ""
+
+msgid "GenericReport|After"
+msgstr ""
+
+msgid "GenericReport|Before"
+msgstr ""
+
+msgid "GenericReport|Diff"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Replication"
+msgstr ""
+
+msgid "Geo Settings"
+msgstr ""
+
+msgid "Geo Sites"
+msgstr ""
+
+msgid "Geo sites"
+msgstr ""
+
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
+msgid "Geo|%{component} synced"
+msgstr ""
+
+msgid "Geo|%{component} verified"
+msgstr ""
+
+msgid "Geo|%{label} can't be blank"
+msgstr ""
+
+msgid "Geo|%{label} should be between 1-999"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-verify"
+msgstr ""
+
+msgid "Geo|%{timeAgoStr} (%{pendingEvents} events)"
+msgstr ""
+
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
+msgid "Geo|Add site"
+msgstr ""
+
+msgid "Geo|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 "Geo|All"
+msgstr ""
+
+msgid "Geo|All %{replicable_name}"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for resync"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for reverify"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP can't be blank"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
+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 ""
+
+msgid "Geo|Connection timeout must be a number"
+msgstr ""
+
+msgid "Geo|Connection timeout should be between 1-120"
+msgstr ""
+
+msgid "Geo|Consult Geo troubleshooting information"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Data replication lag"
+msgstr ""
+
+msgid "Geo|Data type"
+msgstr ""
+
+msgid "Geo|Disabled"
+msgstr ""
+
+msgid "Geo|Discover GitLab Geo"
+msgstr ""
+
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|Filter by name"
+msgstr ""
+
+msgid "Geo|Filter by status"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Geo sites"
+msgstr ""
+
+msgid "Geo|Geo sites are paused using a command run on the site"
+msgstr ""
+
+msgid "Geo|Geo supports replication of many data types."
+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 ""
+
+msgid "Geo|In progress"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Learn more about Geo"
+msgstr ""
+
+msgid "Geo|Learn more about Geo site statuses"
+msgstr ""
+
+msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|No available replication slots"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
+msgstr ""
+
+msgid "Geo|Open replications"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Primary node"
+msgstr ""
+
+msgid "Geo|Primary site"
+msgstr ""
+
+msgid "Geo|Project"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Queued"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove site"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
+msgstr ""
+
+msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
+msgstr ""
+
+msgid "Geo|Replicated data is verified with the secondary site(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|Resync all %{replicableType}"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Reverify"
+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 site."
+msgstr ""
+
+msgid "Geo|Secondary node"
+msgstr ""
+
+msgid "Geo|Secondary site"
+msgstr ""
+
+msgid "Geo|Selective (%{syncLabel})"
+msgstr ""
+
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
+msgid "Geo|Site's status was updated %{timeAgo}."
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Storage config"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synced at"
+msgstr ""
+
+msgid "Geo|Synchronization"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Synchronization settings"
+msgstr ""
+
+msgid "Geo|Synchronization status"
+msgstr ""
+
+msgid "Geo|The database is currently %{db_lag} behind the primary site."
+msgstr ""
+
+msgid "Geo|The site is currently %{minutes_behind} behind the primary site."
+msgstr ""
+
+msgid "Geo|There are no %{replicable_type} to show"
+msgstr ""
+
+msgid "Geo|There was an error deleting the Geo Site"
+msgstr ""
+
+msgid "Geo|There was an error fetching the Geo Sites"
+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 ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|URL can't be blank"
+msgstr ""
+
+msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
+msgstr ""
+
+msgid "Geo|Undefined"
+msgstr ""
+
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Updated %{timeAgo}"
+msgstr ""
+
+msgid "Geo|Verification"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Verification information"
+msgstr ""
+
+msgid "Geo|Verification status"
+msgstr ""
+
+msgid "Geo|Verified"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|With GitLab Geo, you can install a special read-only and replicated instance anywhere. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo site."
+msgstr ""
+
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get a free trial"
+msgstr ""
+
+msgid "Get a support subscription"
+msgstr ""
+
+msgid "Get started"
+msgstr ""
+
+msgid "Get started with GitLab"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Get started with performance monitoring"
+msgstr ""
+
+msgid "Get started!"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git GC period"
+msgstr ""
+
+msgid "Git LFS Rate Limits"
+msgstr ""
+
+msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr ""
+
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
+msgstr ""
+
+msgid "Git LFS status:"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git shallow clone"
+msgstr ""
+
+msgid "Git strategy"
+msgstr ""
+
+msgid "Git transfer in progress"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitHubImporter|*Merged by: %{author} at %{timestamp}*"
+msgstr ""
+
+msgid "GitLab"
+msgstr ""
+
+msgid "GitLab / Unsubscribe"
+msgstr ""
+
+msgid "GitLab API"
+msgstr ""
+
+msgid "GitLab Account Request"
+msgstr ""
+
+msgid "GitLab Billing Team."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Issue"
+msgstr ""
+
+msgid "GitLab Pages"
+msgstr ""
+
+msgid "GitLab Shell"
+msgstr ""
+
+msgid "GitLab Support Bot"
+msgstr ""
+
+msgid "GitLab Team Member"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab Workhorse"
+msgstr ""
+
+msgid "GitLab account request rejected"
+msgstr ""
+
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
+msgid "GitLab commit"
+msgstr ""
+
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
+msgid "GitLab informs you if a new version is available."
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
+msgstr ""
+
+msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
+msgstr ""
+
+msgid "GitLab is open source software to collaborate on code."
+msgstr ""
+
+msgid "GitLab is undergoing maintenance and is operating in read-only mode."
+msgstr ""
+
+msgid "GitLab logo"
+msgstr ""
+
+msgid "GitLab member or Email address"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
+msgstr ""
+
+msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs"
+msgstr ""
+
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
+msgid "GitLab.com"
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLabPagesDomains|Retry"
+msgstr ""
+
+msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "GitLabPages|Access pages"
+msgstr ""
+
+msgid "GitLabPages|Are you sure?"
+msgstr ""
+
+msgid "GitLabPages|Certificate: %{subject}"
+msgstr ""
+
+msgid "GitLabPages|Configure pages"
+msgstr ""
+
+msgid "GitLabPages|Domains"
+msgstr ""
+
+msgid "GitLabPages|Edit"
+msgstr ""
+
+msgid "GitLabPages|Expired"
+msgstr ""
+
+msgid "GitLabPages|Force HTTPS (requires valid certificates)"
+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|Maximum size of pages (MB)"
+msgstr ""
+
+msgid "GitLabPages|New Domain"
+msgstr ""
+
+msgid "GitLabPages|Only project maintainers can remove pages"
+msgstr ""
+
+msgid "GitLabPages|Pages"
+msgstr ""
+
+msgid "GitLabPages|Remove"
+msgstr ""
+
+msgid "GitLabPages|Remove pages"
+msgstr ""
+
+msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
+msgstr ""
+
+msgid "GitLabPages|Save changes"
+msgstr ""
+
+msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgstr ""
+
+msgid "GitLabPages|Unverified"
+msgstr ""
+
+msgid "GitLabPages|Verified"
+msgstr ""
+
+msgid "GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with sub-subdomains. This means that if your username/groupname contains a dot it will not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages will continue to work provided you don't redirect HTTP to HTTPS. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Your pages are served under:"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly relative path:"
+msgstr ""
+
+msgid "Gitaly storage name:"
+msgstr ""
+
+msgid "Gitaly timeouts"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
+msgid "Gitpod"
+msgstr ""
+
+msgid "Gitpod|Enable Gitpod integration"
+msgstr ""
+
+msgid "Gitpod|Gitpod URL"
+msgstr ""
+
+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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
+
+msgid "Given epic is already related to this epic."
+msgstr ""
+
+msgid "Global Search is disabled for this scope"
+msgstr ""
+
+msgid "Global Shortcuts"
+msgstr ""
+
+msgid "Global notification settings"
+msgstr ""
+
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go back (while searching for files)"
+msgstr ""
+
+msgid "Go back to configuration"
+msgstr ""
+
+msgid "Go full screen"
+msgstr ""
+
+msgid "Go to %{source_name}"
+msgstr ""
+
+msgid "Go to commits"
+msgstr ""
+
+msgid "Go to definition"
+msgstr ""
+
+msgid "Go to environments"
+msgstr ""
+
+msgid "Go to epic"
+msgstr ""
+
+msgid "Go to file"
+msgstr ""
+
+msgid "Go to file permalink (while viewing a file)"
+msgstr ""
+
+msgid "Go to files"
+msgstr ""
+
+msgid "Go to find file"
+msgstr ""
+
+msgid "Go to fork"
+msgstr ""
+
+msgid "Go to issue boards"
+msgstr ""
+
+msgid "Go to issues"
+msgstr ""
+
+msgid "Go to jobs"
+msgstr ""
+
+msgid "Go to kubernetes"
+msgstr ""
+
+msgid "Go to merge requests"
+msgstr ""
+
+msgid "Go to metrics"
+msgstr ""
+
+msgid "Go to next page"
+msgstr ""
+
+msgid "Go to page %{page}"
+msgstr ""
+
+msgid "Go to parent"
+msgstr ""
+
+msgid "Go to parent directory"
+msgstr ""
+
+msgid "Go to previous page"
+msgstr ""
+
+msgid "Go to primary site"
+msgstr ""
+
+msgid "Go to project"
+msgstr ""
+
+msgid "Go to releases"
+msgstr ""
+
+msgid "Go to repository charts"
+msgstr ""
+
+msgid "Go to repository graph"
+msgstr ""
+
+msgid "Go to snippets"
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Email restrictions for sign-ups'."
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check the 'Domain denylist'."
+msgstr ""
+
+msgid "Go to the activity feed"
+msgstr ""
+
+msgid "Go to the group’s 'Settings &gt; General' page, and check 'Restrict membership by email domain'."
+msgstr ""
+
+msgid "Go to the milestone list"
+msgstr ""
+
+msgid "Go to the project's activity feed"
+msgstr ""
+
+msgid "Go to the project's overview page"
+msgstr ""
+
+msgid "Go to wiki"
+msgstr ""
+
+msgid "Go to your To-Do list"
+msgstr ""
+
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Go to your groups"
+msgstr ""
+
+msgid "Go to your issues"
+msgstr ""
+
+msgid "Go to your merge requests"
+msgstr ""
+
+msgid "Go to your projects"
+msgstr ""
+
+msgid "Go to your snippets"
+msgstr ""
+
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
+msgid "Google Cloud"
+msgstr ""
+
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
+msgstr ""
+
+msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it"
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grafana URL"
+msgstr ""
+
+msgid "Grafana response contains invalid json"
+msgstr ""
+
+msgid "GrafanaIntegration|API token"
+msgstr ""
+
+msgid "GrafanaIntegration|Active"
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana URL"
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana authentication"
+msgstr ""
+
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Grant write permissions to this key"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "GraphViewType|Job dependencies"
+msgstr ""
+
+msgid "GraphViewType|Show dependencies"
+msgstr ""
+
+msgid "GraphViewType|Stage"
+msgstr ""
+
+msgid "Graphs"
+msgstr ""
+
+msgid "Gravatar"
+msgstr ""
+
+msgid "Gravatar enabled"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group %{group_name} couldn't be exported."
+msgstr ""
+
+msgid "Group %{group_name} was exported successfully."
+msgstr ""
+
+msgid "Group %{group_name} was scheduled for deletion."
+msgstr ""
+
+msgid "Group %{group_name} was successfully created."
+msgstr ""
+
+msgid "Group Access Tokens"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group Hooks"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
+msgid "Group audit events"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group by"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group export could not be started."
+msgstr ""
+
+msgid "Group export download requests"
+msgstr ""
+
+msgid "Group export error"
+msgstr ""
+
+msgid "Group export link has expired. Please generate a new export from your group settings."
+msgstr ""
+
+msgid "Group export requests"
+msgstr ""
+
+msgid "Group export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Group has been already marked for deletion"
+msgstr ""
+
+msgid "Group has not been marked for deletion"
+msgstr ""
+
+msgid "Group import could not be scheduled"
+msgstr ""
+
+msgid "Group import requests"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group information"
+msgstr ""
+
+msgid "Group is required when cluster_type is :group"
+msgstr ""
+
+msgid "Group jobs by"
+msgstr ""
+
+msgid "Group members"
+msgstr ""
+
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
+msgid "Group milestone"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group name (your organization)"
+msgstr ""
+
+msgid "Group navigation"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group path is already taken. We've suggested one that is available."
+msgstr ""
+
+msgid "Group path is available."
+msgstr ""
+
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "Group project URLs are prefixed with the group namespace"
+msgstr ""
+
+msgid "Group requires separate account"
+msgstr ""
+
+msgid "Group runners"
+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 ""
+
+msgid "Group was exported"
+msgstr ""
+
+msgid "Group was successfully updated."
+msgstr ""
+
+msgid "Group wikis"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "Group: %{name}"
+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"
+msgstr ""
+
+msgid "GroupImport|Failed to import group."
+msgstr ""
+
+msgid "GroupImport|Group '%{group_name}' is being imported."
+msgstr ""
+
+msgid "GroupImport|Group could not be imported: %{errors}"
+msgstr ""
+
+msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
+msgstr ""
+
+msgid "GroupImport|The group was successfully imported."
+msgstr ""
+
+msgid "GroupImport|Unable to process group import file"
+msgstr ""
+
+msgid "GroupPage|Copy group ID"
+msgstr ""
+
+msgid "GroupPage|Group ID: %{group_id}"
+msgstr ""
+
+msgid "GroupRoadmap|%{dateWord} – No end date"
+msgstr ""
+
+msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading epics"
+msgstr ""
+
+msgid "GroupRoadmap|No start and end date"
+msgstr ""
+
+msgid "GroupRoadmap|No start date – %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching milestones"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|This quarter"
+msgstr ""
+
+msgid "GroupRoadmap|This year"
+msgstr ""
+
+msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Within 3 years"
+msgstr ""
+
+msgid "GroupSAML|\"persistent\" recommended"
+msgstr ""
+
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
+msgstr ""
+
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|An error occurred generating your SCIM token. Please try again."
+msgstr ""
+
+msgid "GroupSAML|An error occurred resetting your SCIM token. Please try again."
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
+msgstr ""
+
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+msgstr ""
+
+msgid "GroupSAML|Certificate fingerprint"
+msgstr ""
+
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Copy SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
+msgid "GroupSAML|Default membership role"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
+msgstr ""
+
+msgid "GroupSAML|Identity"
+msgstr ""
+
+msgid "GroupSAML|Identity provider single sign-on URL"
+msgstr ""
+
+msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
+msgstr ""
+
+msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "GroupSAML|Members"
+msgstr ""
+
+msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "GroupSAML|NameID"
+msgstr ""
+
+msgid "GroupSAML|NameID Format"
+msgstr ""
+
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks for this group"
+msgstr ""
+
+msgid "GroupSAML|Reset SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
+msgid "GroupSAML|SAML Response Output"
+msgstr ""
+
+msgid "GroupSAML|SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On Settings"
+msgstr ""
+
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
+msgid "GroupSAML|SCIM Token"
+msgstr ""
+
+msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
+msgstr ""
+
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
+msgid "GroupSAML|This will be set as the access level of users added to the group."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
+msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
+msgstr ""
+
+msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
+msgstr ""
+
+msgid "GroupSAML|Valid SAML Response"
+msgstr ""
+
+msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
+msgstr ""
+
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
+msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" to identify user and allow sign in"
+msgstr ""
+
+msgid "GroupSAML|recommend persistent ID instead of email"
+msgstr ""
+
+msgid "GroupSaml|Copy SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSaml|Copy SCIM token"
+msgstr ""
+
+msgid "GroupSaml|SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSaml|Your SCIM token"
+msgstr ""
+
+msgid "GroupSelect|No matching results"
+msgstr ""
+
+msgid "GroupSelect|Search groups"
+msgstr ""
+
+msgid "GroupSelect|Select a group"
+msgstr ""
+
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
+msgstr ""
+
+msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Available only on the top-level group. Applies to all subgroups. Groups already shared with a group outside %{group} are still shared unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_link_end}"
+msgstr ""
+
+msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "GroupSettings|Change group URL"
+msgstr ""
+
+msgid "GroupSettings|Changing a group's URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|Compliance frameworks"
+msgstr ""
+
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
+
+msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
+msgstr ""
+
+msgid "GroupSettings|Disable email notifications"
+msgstr ""
+
+msgid "GroupSettings|Disable group mentions"
+msgstr ""
+
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
+msgid "GroupSettings|Enable delayed project deletion"
+msgstr ""
+
+msgid "GroupSettings|Export group"
+msgstr ""
+
+msgid "GroupSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
+msgstr ""
+
+msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
+msgstr ""
+
+msgid "GroupSettings|New runners registration token has been generated!"
+msgstr ""
+
+msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
+msgstr ""
+
+msgid "GroupSettings|Pipeline settings was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Please choose a group URL with no special characters or spaces."
+msgstr ""
+
+msgid "GroupSettings|Prevent forking outside of the group"
+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 ""
+
+msgid "GroupSettings|Prevents group members from being notified if the group is mentioned."
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
+msgstr ""
+
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
+msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
+msgstr ""
+
+msgid "GroupSettings|Select parent group"
+msgstr ""
+
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
+msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "GroupSettings|The default name for the initial branch of new repositories created in the group."
+msgstr ""
+
+msgid "GroupSettings|The projects in this subgroup can be selected as templates for new projects created in the group. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+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|Transfer group"
+msgstr ""
+
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
+msgstr ""
+
+msgid "GroupSettings|What are badges?"
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
+msgid "GroupSettings|You can only transfer the group to a group you manage."
+msgstr ""
+
+msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "GroupSettings|cannot be changed by you"
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|cannot change when group contains projects with NPM packages"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups (%{count})"
+msgstr ""
+
+msgid "Groups and projects"
+msgstr ""
+
+msgid "Groups and subgroups"
+msgstr ""
+
+msgid "Groups to synchronize"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+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."
+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 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|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
+
+msgid "GroupsNew|Import group"
+msgstr ""
+
+msgid "GroupsNew|Import groups from another instance of GitLab"
+msgstr ""
+
+msgid "GroupsNew|My Awesome Group"
+msgstr ""
+
+msgid "GroupsNew|Navigate to user settings to find your %{link_start}personal access token%{link_end}."
+msgstr ""
+
+msgid "GroupsNew|No import options available"
+msgstr ""
+
+msgid "GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}."
+msgstr ""
+
+msgid "GroupsNew|Personal access token"
+msgstr ""
+
+msgid "GroupsNew|Please fill in GitLab source URL."
+msgstr ""
+
+msgid "GroupsNew|Please fill in your personal access token."
+msgstr ""
+
+msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
+msgstr ""
+
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
+msgstr ""
+
+msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
+msgstr ""
+
+msgid "GroupsNew|Upload file"
+msgstr ""
+
+msgid "GroupsNew|e.g. h8d3f016698e..."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Guideline"
+msgstr ""
+
+msgid "HAR (HTTP Archive)"
+msgstr ""
+
+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}"
+msgstr ""
+
+msgid "Hashed Storage must be enabled to use Geo"
+msgstr ""
+
+msgid "Hashed repository storage paths"
+msgstr ""
+
+msgid "Hashed storage can't be disabled anymore for new projects"
+msgstr ""
+
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
+msgstr ""
+
+msgid "Header logo"
+msgstr ""
+
+msgid "Header logo was successfully removed."
+msgstr ""
+
+msgid "Header logo will be removed. Are you sure?"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
+msgstr ""
+
+msgid "Headers"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
+msgid "Heading 4"
+msgstr ""
+
+msgid "Headings"
+msgstr ""
+
+msgid "Health"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "Health status"
+msgstr ""
+
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Hello %{name},"
+msgstr ""
+
+msgid "Hello, %{name}!"
+msgstr ""
+
+msgid "Hello, %{username}!"
+msgstr ""
+
+msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
+msgstr ""
+
+msgid "HelloMessage|%{magnifier_emoji} Create a new GitLab issue: %{new_issue_link}"
+msgstr ""
+
+msgid "HelloMessage|%{rocket_emoji} We like your curiosity! Help us improve GitLab by joining the team: %{jobs_page_link}"
+msgstr ""
+
+msgid "HelloMessage|Does this page need fixes or improvements? Open an issue or contribute a merge request to help make GitLab more lovable. At GitLab, everyone can contribute!"
+msgstr ""
+
+msgid "HelloMessage|Welcome to GitLab!"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Helps prevent bots from brute-force attacks."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts."
+msgstr ""
+
+msgid "Helps prevent bots from creating issues."
+msgstr ""
+
+msgid "Helps prevent malicious users hide their activity."
+msgstr ""
+
+msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
+msgstr ""
+
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
+
+msgid "Here you will find recent merge request activity"
+msgstr ""
+
+msgid "Hi %{username}!"
+msgstr ""
+
+msgid "Hidden"
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "Hide archived projects"
+msgstr ""
+
+msgid "Hide chart"
+msgid_plural "Hide charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide comments on this file"
+msgstr ""
+
+msgid "Hide details"
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide group projects"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide list"
+msgstr ""
+
+msgid "Hide marketing-related entries from the Help page"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide tooltips or popovers"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest role:"
+msgstr ""
+
+msgid "HighlightBar|Alert events:"
+msgstr ""
+
+msgid "HighlightBar|Alert start time:"
+msgstr ""
+
+msgid "HighlightBar|Original alert:"
+msgstr ""
+
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Holder name:"
+msgstr ""
+
+msgid "Home page URL"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully created."
+msgstr ""
+
+msgid "Hook was successfully updated."
+msgstr ""
+
+msgid "Hostname"
+msgstr ""
+
+msgid "Hostname used in private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "Hour (UTC)"
+msgstr ""
+
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "How do I configure Akismet?"
+msgstr ""
+
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
+msgid "How do I configure it?"
+msgstr ""
+
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I configure this integration?"
+msgstr ""
+
+msgid "How do I generate it?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
+msgid "How do I rename an environment?"
+msgstr ""
+
+msgid "How do I set up a Google Chat webhook?"
+msgstr ""
+
+msgid "How do I set up this service?"
+msgstr ""
+
+msgid "How do I use a web terminal?"
+msgstr ""
+
+msgid "How do I use file templates?"
+msgstr ""
+
+msgid "How many days need to pass between marking entity for deletion and actual removing it."
+msgstr ""
+
+msgid "How many seconds an IP counts toward the IP address limit."
+msgstr ""
+
+msgid "How the job limiter handles jobs exceeding the thresholds specified below. The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and raises an exception if the compressed size exceeds the limit."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+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 store my code"
+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 ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Commit to %{branchName} branch"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IDE|Successful commit"
+msgstr ""
+
+msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
+msgstr ""
+
+msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
+msgstr ""
+
+msgid "INFO: Your SSH key has expired. Please generate a new key."
+msgstr ""
+
+msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "IP address expiration time"
+msgstr ""
+
+msgid "IP address restrictions"
+msgstr ""
+
+msgid "IP addresses per user"
+msgstr ""
+
+msgid "IP subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
+msgstr ""
+
+msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
+msgstr ""
+
+msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
+msgstr ""
+
+msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
+msgstr ""
+
+msgid "If checked, new group memberships and permissions can only be added via LDAP synchronization"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, only administrators can configure repository mirroring."
+msgstr ""
+
+msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "If enabled, only protected branches will be mirrored."
+msgstr ""
+
+msgid "If no options are selected, only administrators can register runners."
+msgstr ""
+
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
+msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
+msgstr ""
+
+msgid "If there isn't any existing index, GitLab creates one."
+msgstr ""
+
+msgid "If this email was added in error, you can remove it here:"
+msgstr ""
+
+msgid "If this email was added in error, you can remove it here: %{profile_emails_url}"
+msgstr ""
+
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
+msgstr ""
+
+msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
+msgstr ""
+
+msgid "If you did not initiate this change, please contact your administrator immediately."
+msgstr ""
+
+msgid "If you did not perform this request, you can safely ignore this email."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+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 ""
+
+msgid "Ignore"
+msgstr ""
+
+msgid "Ignored"
+msgstr ""
+
+msgid "Image URL"
+msgstr ""
+
+msgid "Image details"
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "ImageViewerDimensions|H"
+msgstr ""
+
+msgid "ImageViewerDimensions|W"
+msgstr ""
+
+msgid "Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior."
+msgstr ""
+
+msgid "Impersonate"
+msgstr ""
+
+msgid "Impersonation Tokens"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import %d compatible repository"
+msgid_plural "Import %d compatible repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import %d repository"
+msgid_plural "Import %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import and export rate limits"
+msgstr ""
+
+msgid "Import failed due to a GitHub error: %{original}"
+msgstr ""
+
+msgid "Import from"
+msgstr ""
+
+msgid "Import from Jira"
+msgstr ""
+
+msgid "Import group"
+msgstr ""
+
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
+msgid "Import history"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import in progress. Refresh page to see newly added issues."
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project from"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import requirements"
+msgstr ""
+
+msgid "Import started by: %{importInitiator}"
+msgstr ""
+
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportAProjectModal|Import from a project"
+msgstr ""
+
+msgid "ImportAProjectModal|Import members from another project"
+msgstr ""
+
+msgid "ImportAProjectModal|Import project members"
+msgstr ""
+
+msgid "ImportAProjectModal|Only project members (not group members) are imported, and they get the same permissions as the project you import from."
+msgstr ""
+
+msgid "ImportAProjectModal|Successfully imported"
+msgstr ""
+
+msgid "ImportAProjectModal|Unable to import project members"
+msgstr ""
+
+msgid "ImportAProjectModal|You're importing members to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
+msgstr ""
+
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "ImportProjects|Import repositories"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr ""
+
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the repositories you want to import"
+msgstr ""
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
+msgid "ImportProjects|Update of imported projects with realtime changes failed"
+msgstr ""
+
+msgid "Imported requirements"
+msgstr ""
+
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Importing..."
+msgstr ""
+
+msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
+msgstr ""
+
+msgid "Improve customer support with Service Desk"
+msgstr ""
+
+msgid "Improves Git cloning performance."
+msgstr ""
+
+msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
+msgstr ""
+
+msgid "In progress"
+msgstr ""
+
+msgid "In this page you will find information about the settings that are used in your current instance."
+msgstr ""
+
+msgid "InProductMarketing|%{organization_name} logo"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
+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 ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Ultimate"
+msgstr ""
+
+msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
+msgstr ""
+
+msgid "InProductMarketing|And finally %{deploy_link} a Python application."
+msgstr ""
+
+msgid "InProductMarketing|Are your runners ready?"
+msgstr ""
+
+msgid "InProductMarketing|Automated security scans directly within GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Be a DevOps hero"
+msgstr ""
+
+msgid "InProductMarketing|Beef up your security"
+msgstr ""
+
+msgid "InProductMarketing|Better code in less time"
+msgstr ""
+
+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 ""
+
+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 ""
+
+msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
+msgstr ""
+
+msgid "InProductMarketing|Create a custom runner"
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Deliver Better Products Faster"
+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|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
+msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
+msgstr ""
+
+msgid "InProductMarketing|Explore GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Explore the options"
+msgstr ""
+
+msgid "InProductMarketing|Explore the power of GitLab CI/CD"
+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 ""
+
+msgid "InProductMarketing|Find out how your teams are really doing"
+msgstr ""
+
+msgid "InProductMarketing|Follow our steps"
+msgstr ""
+
+msgid "InProductMarketing|Free 30-day trial"
+msgstr ""
+
+msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy."
+msgstr ""
+
+msgid "InProductMarketing|Get our import guides"
+msgstr ""
+
+msgid "InProductMarketing|Get started today"
+msgstr ""
+
+msgid "InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get to know GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get your team set up on GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Git basics"
+msgstr ""
+
+msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
+msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
+msgstr ""
+
+msgid "InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"
+msgstr ""
+
+msgid "InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"
+msgstr ""
+
+msgid "InProductMarketing|Give us one minute..."
+msgstr ""
+
+msgid "InProductMarketing|Go farther with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
+msgstr ""
+
+msgid "InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}."
+msgstr ""
+
+msgid "InProductMarketing|Here's what you need to know"
+msgstr ""
+
+msgid "InProductMarketing|How (and why) mirroring makes sense"
+msgstr ""
+
+msgid "InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?"
+msgstr ""
+
+msgid "InProductMarketing|How many days does it take our team to complete various tasks?"
+msgstr ""
+
+msgid "InProductMarketing|How to build and test faster"
+msgstr ""
+
+msgid "InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}."
+msgstr ""
+
+msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
+msgstr ""
+
+msgid "InProductMarketing|Import your project and code from GitHub, Bitbucket and others"
+msgstr ""
+
+msgid "InProductMarketing|Improve app security with a 30-day trial"
+msgstr ""
+
+msgid "InProductMarketing|Improve code quality and streamline reviews"
+msgstr ""
+
+msgid "InProductMarketing|Increase Operational Efficiencies"
+msgstr ""
+
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues to join in less than one minute"
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues today"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team in less than 60 seconds"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team now"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
+msgid "InProductMarketing|It's all in the stats"
+msgstr ""
+
+msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
+msgstr ""
+
+msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
+msgstr ""
+
+msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
+msgstr ""
+
+msgid "InProductMarketing|Master the art of importing!"
+msgstr ""
+
+msgid "InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}"
+msgstr ""
+
+msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"
+msgstr ""
+
+msgid "InProductMarketing|Need an alternative to importing?"
+msgstr ""
+
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
+msgid "InProductMarketing|No credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+msgstr ""
+
+msgid "InProductMarketing|Reduce Security & Compliance Risk"
+msgstr ""
+
+msgid "InProductMarketing|Security that's integrated into your development lifecycle"
+msgstr ""
+
+msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
+msgstr ""
+
+msgid "InProductMarketing|Spin up an autoscaling runner in GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
+msgstr ""
+
+msgid "InProductMarketing|Start a trial"
+msgstr ""
+
+msgid "InProductMarketing|Start by %{performance_link}"
+msgstr ""
+
+msgid "InProductMarketing|Start by importing your projects"
+msgstr ""
+
+msgid "InProductMarketing|Start with a GitLab Ultimate free trial"
+msgstr ""
+
+msgid "InProductMarketing|Start your trial now!"
+msgstr ""
+
+msgid "InProductMarketing|Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!"
+msgstr ""
+
+msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
+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 ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+msgstr ""
+
+msgid "InProductMarketing|Team up in GitLab for greater efficiency"
+msgstr ""
+
+msgid "InProductMarketing|Team work makes the dream work"
+msgstr ""
+
+msgid "InProductMarketing|Test, create, deploy"
+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 %{current_series} of %{total_series} in the %{track} series."
+msgstr ""
+
+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"
+msgstr ""
+
+msgid "InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}."
+msgstr ""
+
+msgid "InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}."
+msgstr ""
+
+msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
+msgstr ""
+
+msgid "InProductMarketing|Try GitLab Ultimate for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+msgstr ""
+
+msgid "InProductMarketing|Turn coworkers into collaborators"
+msgstr ""
+
+msgid "InProductMarketing|Twitter"
+msgstr ""
+
+msgid "InProductMarketing|Understand repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|Understand your project options"
+msgstr ""
+
+msgid "InProductMarketing|Use GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Use our AWS cloudformation template to spin up your runners in just a few clicks!"
+msgstr ""
+
+msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
+msgstr ""
+
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
+
+msgid "InProductMarketing|When your team is on GitLab these answers are a click away."
+msgstr ""
+
+msgid "InProductMarketing|Working in GitLab = more efficient"
+msgstr ""
+
+msgid "InProductMarketing|YouTube"
+msgstr ""
+
+msgid "InProductMarketing|Your teams can be more efficient"
+msgstr ""
+
+msgid "InProductMarketing|comprehensive guide"
+msgstr ""
+
+msgid "InProductMarketing|connect an external repository"
+msgstr ""
+
+msgid "InProductMarketing|create a project"
+msgstr ""
+
+msgid "InProductMarketing|from Bitbucket"
+msgstr ""
+
+msgid "InProductMarketing|go to about.gitlab.com"
+msgstr ""
+
+msgid "InProductMarketing|how easy it is to get started"
+msgstr ""
+
+msgid "InProductMarketing|quick start guide"
+msgstr ""
+
+msgid "InProductMarketing|repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|set up a repo"
+msgstr ""
+
+msgid "InProductMarketing|test and deploy"
+msgstr ""
+
+msgid "InProductMarketing|testing browser performance"
+msgstr ""
+
+msgid "InProductMarketing|unsubscribe"
+msgstr ""
+
+msgid "InProductMarketing|update your preferences"
+msgstr ""
+
+msgid "InProductMarketing|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
+msgid "Inactive"
+msgstr ""
+
+msgid "Incident"
+msgstr ""
+
+msgid "Incident Management Limits"
+msgstr ""
+
+msgid "Incident details"
+msgstr ""
+
+msgid "Incident template (optional)."
+msgstr ""
+
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
+msgid "IncidentManagement|All"
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
+msgid "IncidentManagement|Assignees"
+msgstr ""
+
+msgid "IncidentManagement|Closed"
+msgstr ""
+
+msgid "IncidentManagement|Create incident"
+msgstr ""
+
+msgid "IncidentManagement|Critical - S1"
+msgstr ""
+
+msgid "IncidentManagement|Date created"
+msgstr ""
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
+msgid "IncidentManagement|High - S2"
+msgstr ""
+
+msgid "IncidentManagement|Incident"
+msgstr ""
+
+msgid "IncidentManagement|Incidents"
+msgstr ""
+
+msgid "IncidentManagement|Low - S4"
+msgstr ""
+
+msgid "IncidentManagement|Medium - S3"
+msgstr ""
+
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
+msgid "IncidentManagement|No incidents to display."
+msgstr ""
+
+msgid "IncidentManagement|Open"
+msgstr ""
+
+msgid "IncidentManagement|Published"
+msgstr ""
+
+msgid "IncidentManagement|Published to status page"
+msgstr ""
+
+msgid "IncidentManagement|Severity"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
+msgid "IncidentManagement|There was an error displaying the incidents."
+msgstr ""
+
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
+msgid "IncidentManagement|Unassigned"
+msgstr ""
+
+msgid "IncidentManagement|Unknown"
+msgstr ""
+
+msgid "IncidentManagement|Unpublished"
+msgstr ""
+
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+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 ""
+
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|Introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer starts automatically when the incident is created, and sets a time limit for resolving the incident. When activated, the time to SLA countdown appears on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number."
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0."
+msgstr ""
+
+msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
+msgid "Incidents"
+msgstr ""
+
+msgid "Incidents|Add a URL"
+msgstr ""
+
+msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
+msgstr ""
+
+msgid "Incidents|Must start with http or https"
+msgstr ""
+
+msgid "Incidents|There was an issue deleting the image."
+msgstr ""
+
+msgid "Incidents|There was an issue loading metric images."
+msgstr ""
+
+msgid "Incidents|There was an issue uploading your image."
+msgstr ""
+
+msgid "Incidents|You can optionally add a URL to link users to the original graph."
+msgstr ""
+
+msgid "Incident|Alert details"
+msgstr ""
+
+msgid "Incident|Are you sure you wish to delete this image?"
+msgstr ""
+
+msgid "Incident|Deleting %{filename}"
+msgstr ""
+
+msgid "Incident|Metrics"
+msgstr ""
+
+msgid "Incident|Summary"
+msgstr ""
+
+msgid "Incident|There was an issue loading alert data. Please try again."
+msgstr ""
+
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include new features from all tiers."
+msgstr ""
+
+msgid "Include the name of the author of the issue, merge request or comment in the email body. By default, GitLab overrides the email sender's name. Some email servers don't support that option."
+msgstr ""
+
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
+msgstr ""
+
+msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
+
+msgid "Incoming email"
+msgstr ""
+
+msgid "Incoming!"
+msgstr ""
+
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Incompatible project"
+msgstr ""
+
+msgid "Incomplete"
+msgstr ""
+
+msgid "Increase"
+msgstr ""
+
+msgid "Indent"
+msgstr ""
+
+msgid "Index"
+msgstr ""
+
+msgid "Index all projects"
+msgstr ""
+
+msgid "Index deletion is canceled"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
+msgstr ""
+
+msgid "Infrastructure"
+msgstr ""
+
+msgid "Infrastructure Registry"
+msgstr ""
+
+msgid "Infrastructure as Code (IaC) Scanning"
+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 ""
+
+msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "InfrastructureRegistry|Terraform"
+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 ""
+
+msgid "Inherited"
+msgstr ""
+
+msgid "Inherited:"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Inline math"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input the remote repository URL"
+msgstr ""
+
+msgid "Insert"
+msgstr ""
+
+msgid "Insert a %{rows}x%{cols} table."
+msgstr ""
+
+msgid "Insert a code block"
+msgstr ""
+
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert a video"
+msgstr ""
+
+msgid "Insert an image"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
+msgid "Insert column after"
+msgstr ""
+
+msgid "Insert column before"
+msgstr ""
+
+msgid "Insert image"
+msgstr ""
+
+msgid "Insert inline code"
+msgstr ""
+
+msgid "Insert link"
+msgstr ""
+
+msgid "Insert row after"
+msgstr ""
+
+msgid "Insert row before"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Insert video"
+msgstr ""
+
+msgid "Insights"
+msgstr ""
+
+msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
+
+msgid "Install on clusters"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Configuration"
+msgstr ""
+
+msgid "Instance access request"
+msgstr ""
+
+msgid "Instance access request approved"
+msgstr ""
+
+msgid "Instance access request rejected"
+msgstr ""
+
+msgid "Instance administrators group already exists"
+msgstr ""
+
+msgid "Instance audit events"
+msgstr ""
+
+msgid "Instance overview"
+msgstr ""
+
+msgid "Insufficient permissions"
+msgstr ""
+
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|%{integrationTitle}: active"
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+msgstr ""
+
+msgid "Integrations|Active integrations"
+msgstr ""
+
+msgid "Integrations|Add an integration"
+msgstr ""
+
+msgid "Integrations|Add namespace"
+msgstr ""
+
+msgid "Integrations|All details"
+msgstr ""
+
+msgid "Integrations|All projects inheriting these settings will also be reset."
+msgstr ""
+
+msgid "Integrations|An error occurred while loading projects using custom settings."
+msgstr ""
+
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
+msgid "Integrations|Comment detail:"
+msgstr ""
+
+msgid "Integrations|Comment settings:"
+msgstr ""
+
+msgid "Integrations|Connection failed. Please check your settings."
+msgstr ""
+
+msgid "Integrations|Connection successful."
+msgstr ""
+
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
+msgid "Integrations|Create new issue in ZenTao"
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Edit project alias"
+msgstr ""
+
+msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Enter your alias"
+msgstr ""
+
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to unlink namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and 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}instance-level integration management%{link_end}."
+msgstr ""
+
+msgid "Integrations|GitLab administrators can set up integrations that all projects in a group 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 project if the settings are necessary at that level. Learn more about %{integrations_link_start}group-level integration management%{link_end}."
+msgstr ""
+
+msgid "Integrations|Group-level integration management"
+msgstr ""
+
+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|Instance-level integration management"
+msgstr ""
+
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Keep your PHP dependencies updated on Packagist."
+msgstr ""
+
+msgid "Integrations|Known limitations"
+msgstr ""
+
+msgid "Integrations|Link namespaces"
+msgstr ""
+
+msgid "Integrations|Linked namespaces"
+msgstr ""
+
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
+msgid "Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance."
+msgstr ""
+
+msgid "Integrations|No available namespaces."
+msgstr ""
+
+msgid "Integrations|No linked namespaces"
+msgstr ""
+
+msgid "Integrations|Projects using custom settings"
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be affected."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
+msgstr ""
+
+msgid "Integrations|Reset integration?"
+msgstr ""
+
+msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
+msgstr ""
+
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
+msgid "Integrations|Save settings?"
+msgstr ""
+
+msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
+msgstr ""
+
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
+msgid "Integrations|Search ZenTao issues"
+msgstr ""
+
+msgid "Integrations|Send notifications about project events to Unify Circuit."
+msgstr ""
+
+msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
+msgstr ""
+
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
+msgid "Integrations|Standard"
+msgstr ""
+
+msgid "Integrations|There are no projects using custom settings"
+msgstr ""
+
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Integrations|This integration, and inheriting projects were reset."
+msgstr ""
+
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+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 can use this alias in your Slack commands"
+msgstr ""
+
+msgid "Integrations|You haven't activated any integrations yet."
+msgstr ""
+
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "Integrations|You've activated every integration 🎉"
+msgstr ""
+
+msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
+msgstr ""
+
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
+msgid "Interactive mode"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal URL (optional)"
+msgstr ""
+
+msgid "Internal error occurred while delivering this webhook."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
+msgstr ""
+
+msgid "Invalid Insights config file detected"
+msgstr ""
+
+msgid "Invalid OS"
+msgstr ""
+
+msgid "Invalid URL"
+msgstr ""
+
+msgid "Invalid URL: %{url}"
+msgstr ""
+
+msgid "Invalid container_name"
+msgstr ""
+
+msgid "Invalid cursor parameter"
+msgstr ""
+
+msgid "Invalid cursor value provided"
+msgstr ""
+
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
+msgstr ""
+
+msgid "Invalid date range"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
+msgid "Invalid file format with specified file type"
+msgstr ""
+
+msgid "Invalid file."
+msgstr ""
+
+msgid "Invalid hash"
+msgstr ""
+
+msgid "Invalid import params"
+msgstr ""
+
+msgid "Invalid input, please avoid emojis"
+msgstr ""
+
+msgid "Invalid login or password"
+msgstr ""
+
+msgid "Invalid period"
+msgstr ""
+
+msgid "Invalid pin code."
+msgstr ""
+
+msgid "Invalid pod_name"
+msgstr ""
+
+msgid "Invalid policy type"
+msgstr ""
+
+msgid "Invalid repository bundle for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid search parameter"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
+msgid "Invalid start or end time format"
+msgstr ""
+
+msgid "Invalid status"
+msgstr ""
+
+msgid "Invalid two-factor code."
+msgstr ""
+
+msgid "Invalid yaml"
+msgstr ""
+
+msgid "Investigate vulnerability: %{title}"
+msgstr ""
+
+msgid "Invisible Captcha"
+msgstr ""
+
+msgid "Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form."
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invitation declined"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
+msgid "Invite Members"
+msgstr ""
+
+msgid "Invite a group"
+msgstr ""
+
+msgid "Invite email has already been taken"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invite members"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{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} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} details"
+msgstr ""
+
+msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
+msgstr ""
+
+msgid "InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}"
+msgstr ""
+
+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'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}"
+msgstr ""
+
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+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"
+msgstr ""
+
+msgid "InviteMembersModal|Access expiration date (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|Cancel"
+msgstr ""
+
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
+msgid "InviteMembersModal|Close invite team members"
+msgstr ""
+
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
+msgstr ""
+
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab is better with colleagues!"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab member or email address"
+msgstr ""
+
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
+msgid "InviteMembersModal|Invite"
+msgstr ""
+
+msgid "InviteMembersModal|Invite a group"
+msgstr ""
+
+msgid "InviteMembersModal|Invite members"
+msgstr ""
+
+msgid "InviteMembersModal|Members were successfully added"
+msgstr ""
+
+msgid "InviteMembersModal|Search for a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select a role"
+msgstr ""
+
+msgid "InviteMembersModal|Select members or type email addresses"
+msgstr ""
+
+msgid "InviteMembersModal|Something went wrong"
+msgstr ""
+
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembers|Invite a group"
+msgstr ""
+
+msgid "InviteMembers|Invite team members"
+msgstr ""
+
+msgid "InviteMember|Add members to this project and start collaborating with your team."
+msgstr ""
+
+msgid "InviteMember|Invite Members (optional)"
+msgstr ""
+
+msgid "InviteMember|Invite another member"
+msgstr ""
+
+msgid "InviteMember|Invite members"
+msgstr ""
+
+msgid "InviteMember|Invite your team"
+msgstr ""
+
+msgid "InviteMember|Invited users will be added with developer level permissions. %{linkStart}View the documentation%{linkEnd} to see how to change this later."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
+msgid "Invocations"
+msgstr ""
+
+msgid "IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}"
+msgstr ""
+
+msgid "IrkerService|Default IRC URI (optional)"
+msgstr ""
+
+msgid "IrkerService|How to enter channels or users?"
+msgstr ""
+
+msgid "IrkerService|Recipients"
+msgstr ""
+
+msgid "IrkerService|Send update messages to an irker server."
+msgstr ""
+
+msgid "IrkerService|Send update messages to an irker server. Before you can use this, you need to set up the irker daemon. %{docs_link}"
+msgstr ""
+
+msgid "IrkerService|Server host (optional)"
+msgstr ""
+
+msgid "IrkerService|Server port (optional)"
+msgstr ""
+
+msgid "IrkerService|URI to add before each recipient."
+msgstr ""
+
+msgid "IrkerService|irker (IRC gateway)"
+msgstr ""
+
+msgid "IrkerService|irker daemon hostname (defaults to localhost)."
+msgstr ""
+
+msgid "IrkerService|irker daemon port (defaults to 6659)."
+msgstr ""
+
+msgid "Is blocked by"
+msgstr ""
+
+msgid "Is using license seat:"
+msgstr ""
+
+msgid "Is using seat"
+msgstr ""
+
+msgid "IssuableStatus|Closed"
+msgstr ""
+
+msgid "IssuableStatus|Closed (%{link})"
+msgstr ""
+
+msgid "IssuableStatus|duplicated"
+msgstr ""
+
+msgid "IssuableStatus|moved"
+msgstr ""
+
+msgid "IssuableStatus|promoted"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
+msgstr ""
+
+msgid "Issue Analytics"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue Type"
+msgstr ""
+
+msgid "Issue already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr ""
+
+msgid "Issue creation requests"
+msgstr ""
+
+msgid "Issue details"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first deployed to production"
+msgstr ""
+
+msgid "Issue has been promoted to incident"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or merge request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue types"
+msgstr ""
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
+msgid "Issue weight"
+msgstr ""
+
+msgid "Issue(s) already assigned"
+msgstr ""
+
+msgid "IssueAnalytics|Age"
+msgstr ""
+
+msgid "IssueAnalytics|Assignees"
+msgstr ""
+
+msgid "IssueAnalytics|Due date"
+msgstr ""
+
+msgid "IssueAnalytics|Failed to load issues. Please try again."
+msgstr ""
+
+msgid "IssueAnalytics|Issue"
+msgstr ""
+
+msgid "IssueAnalytics|Milestone"
+msgstr ""
+
+msgid "IssueAnalytics|Opened by"
+msgstr ""
+
+msgid "IssueAnalytics|Status"
+msgstr ""
+
+msgid "IssueAnalytics|Weight"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "IssueList|created %{timeAgoString} by %{user}"
+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 ""
+
+msgid "IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use Redmine as the issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use Redmine as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use YouTrack as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use a custom issue tracker as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and merge requests"
+msgstr ""
+
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
+msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
+msgstr ""
+
+msgid "Issues with label %{label}"
+msgstr ""
+
+msgid "Issues with no epic assigned"
+msgstr ""
+
+msgid "Issues, merge requests, pushes, and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Avg/Month:"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "IssuesAnalytics|Total:"
+msgstr ""
+
+msgid "Issue|Title"
+msgstr ""
+
+msgid "It is not possible to %{action} files that are stored in LFS using the web interface"
+msgstr ""
+
+msgid "It looks like you have some draft commits in this branch."
+msgstr ""
+
+msgid "It may be several days before you see feature usage data."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
+msgstr ""
+
+msgid "It seems that there is currently no available data for code coverage"
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Italic text"
+msgstr ""
+
+msgid "Iteration"
+msgstr ""
+
+msgid "Iteration changed to"
+msgstr ""
+
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
+msgid "Iteration removed"
+msgstr ""
+
+msgid "Iteration updated"
+msgstr ""
+
+msgid "Iterations"
+msgstr ""
+
+msgid "Iterations|Add iteration"
+msgstr ""
+
+msgid "Iterations|Automated scheduling"
+msgstr ""
+
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
+msgid "Iterations|Cadence name"
+msgstr ""
+
+msgid "Iterations|Couldn't find iteration cadence"
+msgstr ""
+
+msgid "Iterations|Create cadence"
+msgstr ""
+
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
+msgid "Iterations|Create iteration"
+msgstr ""
+
+msgid "Iterations|Delete cadence"
+msgstr ""
+
+msgid "Iterations|Delete iteration cadence?"
+msgstr ""
+
+msgid "Iterations|Delete iteration?"
+msgstr ""
+
+msgid "Iterations|Duration"
+msgstr ""
+
+msgid "Iterations|Edit cadence"
+msgstr ""
+
+msgid "Iterations|Edit iteration"
+msgstr ""
+
+msgid "Iterations|Edit iteration cadence"
+msgstr ""
+
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
+msgid "Iterations|Future iterations"
+msgstr ""
+
+msgid "Iterations|Iteration cadences"
+msgstr ""
+
+msgid "Iterations|Iteration scheduling will be handled automatically"
+msgstr ""
+
+msgid "Iterations|Move incomplete issues to the next iteration"
+msgstr ""
+
+msgid "Iterations|New iteration"
+msgstr ""
+
+msgid "Iterations|New iteration cadence"
+msgstr ""
+
+msgid "Iterations|No closed iterations."
+msgstr ""
+
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
+msgid "Iterations|No open iterations."
+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 ""
+
+msgid "Iterations|Select number"
+msgstr ""
+
+msgid "Iterations|Select start date"
+msgstr ""
+
+msgid "Iterations|Start date"
+msgstr ""
+
+msgid "Iterations|The duration for each iteration (in weeks)"
+msgstr ""
+
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
+msgid "Iterations|The start date of your first iteration"
+msgstr ""
+
+msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
+msgstr ""
+
+msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
+msgstr ""
+
+msgid "Iterations|Title"
+msgstr ""
+
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
+msgid "Iterations|Unable to find iteration."
+msgstr ""
+
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
+msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
+msgstr ""
+
+msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
+msgstr ""
+
+msgid "Iteration|cannot be more than 500 years in the future"
+msgstr ""
+
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Japanese language support using"
+msgstr ""
+
+msgid "Jira display name"
+msgstr ""
+
+msgid "Jira import is already running."
+msgstr ""
+
+msgid "Jira integration not configured."
+msgstr ""
+
+msgid "Jira project key is not configured."
+msgstr ""
+
+msgid "Jira project: %{importProject}"
+msgstr ""
+
+msgid "Jira service not configured."
+msgstr ""
+
+msgid "Jira user"
+msgstr ""
+
+msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
+msgstr ""
+
+msgid "Jira-GitLab user mapping template"
+msgstr ""
+
+msgid "JiraConnect|Create branch for Jira issue %{jiraIssue}"
+msgstr ""
+
+msgid "JiraConnect|Failed to create branch."
+msgstr ""
+
+msgid "JiraConnect|Failed to create branch. Please try again."
+msgstr ""
+
+msgid "JiraConnect|New branch was successfully created."
+msgstr ""
+
+msgid "JiraConnect|You can now close this window and return to Jira."
+msgstr ""
+
+msgid "JiraRequest|A connection error occurred while connecting to Jira. Try your request again."
+msgstr ""
+
+msgid "JiraRequest|A timeout error occurred while connecting to Jira. Try your request again."
+msgstr ""
+
+msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
+msgstr ""
+
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
+
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
+
+msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
+msgstr ""
+
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
+msgstr ""
+
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
+msgstr ""
+
+msgid "JiraService| on branch %{branch_link}"
+msgstr ""
+
+msgid "JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgstr ""
+
+msgid "JiraService|An error occurred while fetching issue list"
+msgstr ""
+
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Base URL of the Jira instance."
+msgstr ""
+
+msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
+msgstr ""
+
+msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
+msgstr ""
+
+msgid "JiraService|Enable Jira issues"
+msgstr ""
+
+msgid "JiraService|Enable Jira issues creation from vulnerabilities"
+msgstr ""
+
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
+msgid "JiraService|For example, AB"
+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 ""
+
+msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
+msgstr ""
+
+msgid "JiraService|Jira API URL"
+msgstr ""
+
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
+
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue type"
+msgstr ""
+
+msgid "JiraService|Jira issues"
+msgstr ""
+
+msgid "JiraService|Jira project key"
+msgstr ""
+
+msgid "JiraService|Leave blank to use your current password or API token."
+msgstr ""
+
+msgid "JiraService|Move to Done"
+msgstr ""
+
+msgid "JiraService|Open Jira"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Project key changed, refresh list"
+msgstr ""
+
+msgid "JiraService|Project key is required to generate issue types"
+msgstr ""
+
+msgid "JiraService|Select issue type"
+msgstr ""
+
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
+msgid "JiraService|This is a Premium feature"
+msgstr ""
+
+msgid "JiraService|This is an Ultimate feature"
+msgstr ""
+
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
+msgid "JiraService|Upgrade your plan to enable this feature of the Jira Integration."
+msgstr ""
+
+msgid "JiraService|Use Jira as this project's issue tracker."
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version."
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version."
+msgstr ""
+
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
+msgid "JiraService|View Jira issues in GitLab"
+msgstr ""
+
+msgid "JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below."
+msgstr ""
+
+msgid "JiraService|Web URL"
+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|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 ""
+
+msgid "Job %{jobName}"
+msgstr ""
+
+msgid "Job Failed #%{build_id}"
+msgstr ""
+
+msgid "Job ID"
+msgstr ""
+
+msgid "Job artifact"
+msgstr ""
+
+msgid "Job artifacts"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job has been successfully erased!"
+msgstr ""
+
+msgid "Job has wrong arguments format."
+msgstr ""
+
+msgid "Job is missing the `model_type` argument."
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job logs and artifacts"
+msgstr ""
+
+msgid "Job to create self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job to delete self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Jobs fail if they run longer than the timeout time. Input value is in seconds by default. Human readable input is also accepted, for example %{code_open}1 hour%{code_close}."
+msgstr ""
+
+msgid "Jobs older than the configured time are considered expired and are archived. Archived jobs can no longer be retried. Leave empty to never archive jobs automatically. The default unit is in days, but you can use other units, for example %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}. Minimum value is 1 day."
+msgstr ""
+
+msgid "Jobs|Are you sure you want to proceed?"
+msgstr ""
+
+msgid "Jobs|Are you sure you want to retry this job?"
+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 ""
+
+msgid "Jobs|No jobs to show"
+msgstr ""
+
+msgid "Jobs|Use jobs to automate your tasks"
+msgstr ""
+
+msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log and artifacts"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Pipeline"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
+msgstr ""
+
+msgid "Job|This job failed because the necessary resources were not successfully created."
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners online or available with any of these tags assigned to them:"
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "Job|allowed to fail"
+msgstr ""
+
+msgid "Job|delayed"
+msgstr ""
+
+msgid "Job|for"
+msgstr ""
+
+msgid "Job|into"
+msgstr ""
+
+msgid "Job|manual"
+msgstr ""
+
+msgid "Job|triggered"
+msgstr ""
+
+msgid "Job|with"
+msgstr ""
+
+msgid "Join Zoom meeting"
+msgstr ""
+
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
+msgid "Joined %{time_ago}"
+msgstr ""
+
+msgid "Joined %{user_created_time}"
+msgstr ""
+
+msgid "Joined projects (%{projects_count})"
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jump to next unresolved thread"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Just me"
+msgstr ""
+
+msgid "K8s pod health"
+msgstr ""
+
+msgid "KEY"
+msgstr ""
+
+msgid "Keep"
+msgstr ""
+
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Keep editing"
+msgstr ""
+
+msgid "Keeping all SAST analyzers enabled future-proofs the project in case new languages are added later on. Determining which analyzers apply is a process that consumes minimal resources and adds minimal time to the pipeline. Leaving all SAST analyzers enabled ensures maximum coverage."
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key: %{key}"
+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 ""
+
+msgid "Ki"
+msgstr ""
+
+msgid "Kontra"
+msgstr ""
+
+msgid "Kroki"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes API returned status code: %{error_code}"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration and resources are being removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes clusters"
+msgstr ""
+
+msgid "Kubernetes deployment not found"
+msgstr ""
+
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
+msgid "LDAP"
+msgstr ""
+
+msgid "LDAP Synchronization"
+msgstr ""
+
+msgid "LDAP group settings"
+msgstr ""
+
+msgid "LDAP settings"
+msgstr ""
+
+msgid "LDAP settings updated"
+msgstr ""
+
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
+msgid "LDAP synchronizations"
+msgstr ""
+
+msgid "LDAP uid:"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFS objects"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "LICENSE"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label priority"
+msgstr ""
+
+msgid "Label was created"
+msgstr ""
+
+msgid "Label was removed"
+msgstr ""
+
+msgid "Label was successfully updated."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels with no issues in this iteration:"
+msgstr ""
+
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Language"
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last %{days} days"
+msgstr ""
+
+msgid "Last 2 weeks"
+msgstr ""
+
+msgid "Last 30 days"
+msgstr ""
+
+msgid "Last 60 days"
+msgstr ""
+
+msgid "Last 90 days"
+msgstr ""
+
+msgid "Last Accessed On"
+msgstr ""
+
+msgid "Last Activity"
+msgstr ""
+
+msgid "Last Name"
+msgstr ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+msgstr ""
+
+msgid "Last Sync"
+msgstr ""
+
+msgid "Last Used"
+msgstr ""
+
+msgid "Last accessed on"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
+
+msgid "Last item before this page loaded in your browser:"
+msgstr ""
+
+msgid "Last modified"
+msgstr ""
+
+msgid "Last month"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last sign-in"
+msgstr ""
+
+msgid "Last sign-in IP:"
+msgstr ""
+
+msgid "Last sign-in at:"
+msgstr ""
+
+msgid "Last successful sync"
+msgstr ""
+
+msgid "Last successful update"
+msgstr ""
+
+msgid "Last time checked"
+msgstr ""
+
+msgid "Last time verified"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last update attempt"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
+msgid "Last week"
+msgstr ""
+
+msgid "Last year"
+msgstr ""
+
+msgid "LastCommit|authored"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for the most recent commit on this branch"
+msgstr ""
+
+msgid "Launch a ready-to-code development environment for your project."
+msgstr ""
+
+msgid "Layout|Fixed"
+msgstr ""
+
+msgid "Layout|Fluid"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Lead time"
+msgstr ""
+
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn GitLab - Ultimate trial"
+msgstr ""
+
+msgid "Learn GitLab|Trial only"
+msgstr ""
+
+msgid "Learn More"
+msgstr ""
+
+msgid "Learn More."
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
+msgid "Learn more about %{username}"
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Needs relationships"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about X.509 signed commits"
+msgstr ""
+
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about deploying to AWS"
+msgstr ""
+
+msgid "Learn more about deploying to a cluster"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about groups."
+msgstr ""
+
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
+msgstr ""
+
+msgid "Learn more about signing commits"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more."
+msgstr ""
+
+msgid "LearnGitLab|%{percentage}%{percentSymbol} completed"
+msgstr ""
+
+msgid "LearnGitLab|Add code owners"
+msgstr ""
+
+msgid "LearnGitLab|Add merge request approval"
+msgstr ""
+
+msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
+msgstr ""
+
+msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
+msgstr ""
+
+msgid "LearnGitLab|Create an issue"
+msgstr ""
+
+msgid "LearnGitLab|Create or import a repository"
+msgstr ""
+
+msgid "LearnGitLab|Create or import your first repository into your new project."
+msgstr ""
+
+msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work."
+msgstr ""
+
+msgid "LearnGitLab|Deploy"
+msgstr ""
+
+msgid "LearnGitLab|Enable require merge approvals"
+msgstr ""
+
+msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features."
+msgstr ""
+
+msgid "LearnGitLab|Invite your colleagues"
+msgstr ""
+
+msgid "LearnGitLab|Learn GitLab"
+msgstr ""
+
+msgid "LearnGitLab|Plan and execute"
+msgstr ""
+
+msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths."
+msgstr ""
+
+msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
+msgstr ""
+
+msgid "LearnGitLab|Review and edit proposed changes to source code."
+msgstr ""
+
+msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
+msgstr ""
+
+msgid "LearnGitLab|Run a Security scan using CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
+msgstr ""
+
+msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
+msgstr ""
+
+msgid "LearnGitLab|Set up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Set up your workspace"
+msgstr ""
+
+msgid "LearnGitLab|Set-up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Start a free Ultimate trial"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request (MR)"
+msgstr ""
+
+msgid "LearnGitLab|Try GitLab Ultimate for free"
+msgstr ""
+
+msgid "LearnGitLab|Try all GitLab features for 30 days, no credit card required."
+msgstr ""
+
+msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
+msgstr ""
+
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
+msgid "LearnGitlab|Trial only"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave Admin Mode"
+msgstr ""
+
+msgid "Leave edit mode? All unsaved changes will be lost."
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave zen mode"
+msgstr ""
+
+msgid "Leaving this setting enabled is recommended."
+msgstr ""
+
+msgid "Legacy burndown chart"
+msgstr ""
+
+msgid "Let's Encrypt does not accept emails on example.com"
+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 Compliance"
+msgstr ""
+
+msgid "License compliance"
+msgstr ""
+
+msgid "License file"
+msgstr ""
+
+msgid "License key"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related policy"
+msgstr ""
+
+msgid "LicenseCompliance|Add license policy"
+msgstr ""
+
+msgid "LicenseCompliance|Allow"
+msgstr ""
+
+msgid "LicenseCompliance|Allowed"
+msgstr ""
+
+msgid "LicenseCompliance|Denied"
+msgstr ""
+
+msgid "LicenseCompliance|Deny"
+msgstr ""
+
+msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
+msgstr ""
+
+msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
+msgstr ""
+
+msgid "LicenseCompliance|License Approvals"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected no new licenses"
+msgstr ""
+
+msgid "LicenseCompliance|License name"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license?"
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
+
+msgid "LicenseCompliance|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "LicenseManagement|Allowed"
+msgstr ""
+
+msgid "LicenseManagement|Denied"
+msgstr ""
+
+msgid "LicenseManagement|Uncategorized"
+msgstr ""
+
+msgid "Licensed Enterprise Edition features can be used if the project namespace's plan includes the feature, or if the project is public."
+msgstr ""
+
+msgid "Licensed Features"
+msgstr ""
+
+msgid "Licensed to:"
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Licenses|%{remainingComponentsCount} more"
+msgstr ""
+
+msgid "Licenses|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "Licenses|Component"
+msgstr ""
+
+msgid "Licenses|Components"
+msgstr ""
+
+msgid "Licenses|Detected in Project"
+msgstr ""
+
+msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
+msgstr ""
+
+msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Licenses|License Compliance"
+msgstr ""
+
+msgid "Licenses|Name"
+msgstr ""
+
+msgid "Licenses|Policies"
+msgstr ""
+
+msgid "Licenses|Policy"
+msgstr ""
+
+msgid "Licenses|Policy violation: denied"
+msgstr ""
+
+msgid "Licenses|Specified policies in this project"
+msgstr ""
+
+msgid "Licenses|The license list details information about the licenses used within your project."
+msgstr ""
+
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
+msgid "Licenses|View license details for your project"
+msgstr ""
+
+msgid "Limit display of time tracking units to hours."
+msgstr ""
+
+msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Limit sign in from multiple IP addresses"
+msgstr ""
+
+msgid "Limit the number of concurrent operations this secondary site can run in the background."
+msgstr ""
+
+msgid "Limit the number of inbound incident management alerts that can be sent to a project."
+msgstr ""
+
+msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
+msgstr ""
+
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
+msgid "Limit the size of Sidekiq jobs stored in Redis."
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Limiting mode"
+msgstr ""
+
+msgid "Line changes"
+msgstr ""
+
+msgid "Link"
+msgstr ""
+
+msgid "Link Prometheus monitoring to GitLab."
+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 ""
+
+msgid "Link copied"
+msgstr ""
+
+msgid "Link text"
+msgstr ""
+
+msgid "Link title"
+msgstr ""
+
+msgid "Link title is required"
+msgstr ""
+
+msgid "Link to an image"
+msgstr ""
+
+msgid "Link to go to GitLab pipeline documentation"
+msgstr ""
+
+msgid "Link to your Grafana instance."
+msgstr ""
+
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
+msgid "Linked issues"
+msgstr ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "LinkedIn:"
+msgstr ""
+
+msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List of all merge commits"
+msgstr ""
+
+msgid "List options"
+msgstr ""
+
+msgid "List settings"
+msgstr ""
+
+msgid "List the merge requests that must be merged before this one."
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Load more"
+msgstr ""
+
+msgid "Load more users"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "Loading %{name}"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
+msgid "Loading more"
+msgstr ""
+
+msgid "Loading snippet"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Location"
+msgstr ""
+
+msgid "Location:"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock File?"
+msgstr ""
+
+msgid "Lock memberships to LDAP synchronization"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock the discussion"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked by %{fileLockUserName}"
+msgstr ""
+
+msgid "Locked the discussion."
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Locks the discussion."
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logo was successfully removed."
+msgstr ""
+
+msgid "Logo will be removed. Are you sure?"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Logs|To see the logs, deploy your code to an environment."
+msgstr ""
+
+msgid "Low vulnerabilities present"
+msgstr ""
+
+msgid "MB"
+msgstr ""
+
+msgid "MD5"
+msgstr ""
+
+msgid "MERGED"
+msgstr ""
+
+msgid "MR widget|Back to the merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
+msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
+msgstr ""
+
+msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgstr ""
+
+msgid "MRApprovals|Approvals"
+msgstr ""
+
+msgid "MRApprovals|Approved by"
+msgstr ""
+
+msgid "MRApprovals|Approvers"
+msgstr ""
+
+msgid "MRApprovals|Commented by"
+msgstr ""
+
+msgid "MRDiffFile|Changes are too large to be shown."
+msgstr ""
+
+msgid "MRDiffFile|View file @ %{commitSha}"
+msgstr ""
+
+msgid "MRDiff|Show changes only"
+msgstr ""
+
+msgid "MRDiff|Show full file"
+msgstr ""
+
+msgid "Made this issue confidential."
+msgstr ""
+
+msgid "Mailgun"
+msgstr ""
+
+msgid "Mailgun HTTP webhook signing key"
+msgstr ""
+
+msgid "Mailgun events"
+msgstr ""
+
+msgid "Maintenance mode"
+msgstr ""
+
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make issue confidential"
+msgstr ""
+
+msgid "Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "Makes this issue confidential."
+msgstr ""
+
+msgid "Manage %{workspace} labels"
+msgstr ""
+
+msgid "Manage Web IDE features."
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that use GitLab as an OAuth provider."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage git repositories with fine-grained access controls that keep your code secure."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage milestones"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage projects."
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your license"
+msgstr ""
+
+msgid "Manage your project's triggers"
+msgstr ""
+
+msgid "Managed Account"
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Manifest import"
+msgstr ""
+
+msgid "Manual"
+msgstr ""
+
+msgid "ManualOrdering|Couldn't save the order of the issues"
+msgstr ""
+
+msgid "Manually link this issue by adding it to the linked issue section of the %{linkStart}originating vulnerability%{linkEnd}."
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark as done"
+msgstr ""
+
+msgid "Mark as draft"
+msgstr ""
+
+msgid "Mark as ready"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark this issue as related to another issue"
+msgstr ""
+
+msgid "Mark to do as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown Help"
+msgstr ""
+
+msgid "Markdown enabled."
+msgstr ""
+
+msgid "Markdown is supported"
+msgstr ""
+
+msgid "Markdown supported."
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
+msgstr ""
+
+msgid "Marked For Deletion At - %{deletion_time}"
+msgstr ""
+
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
+msgid "Marked as ready. Merging is now allowed."
+msgstr ""
+
+msgid "Marked this %{noun} as a draft."
+msgstr ""
+
+msgid "Marked this issue as a duplicate of %{duplicate_param}."
+msgstr ""
+
+msgid "Marked this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marked to do as done."
+msgstr ""
+
+msgid "Marks this %{noun} as a draft."
+msgstr ""
+
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marks to do as done."
+msgstr ""
+
+msgid "Mask variable"
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
+msgid "Mattermost"
+msgstr ""
+
+msgid "Mattermost URL:"
+msgstr ""
+
+msgid "Mattermost notifications"
+msgstr ""
+
+msgid "MattermostService|Add to Mattermost"
+msgstr ""
+
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
+msgid "MattermostService|Command trigger word"
+msgstr ""
+
+msgid "MattermostService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "MattermostService|Request URL"
+msgstr ""
+
+msgid "MattermostService|Request method"
+msgstr ""
+
+msgid "MattermostService|Response icon"
+msgstr ""
+
+msgid "MattermostService|Response username"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max 100,000 events"
+msgstr ""
+
+msgid "Max authenticated Git LFS requests per period per user"
+msgstr ""
+
+msgid "Max file size is 200 KB."
+msgstr ""
+
+msgid "Max role"
+msgstr ""
+
+msgid "Max session time"
+msgstr ""
+
+msgid "Maximum 20 characters"
+msgstr ""
+
+msgid "Maximum Conan package file size in bytes"
+msgstr ""
+
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
+msgid "Maximum Maven package file size in bytes"
+msgstr ""
+
+msgid "Maximum NuGet package file size in bytes"
+msgstr ""
+
+msgid "Maximum PyPI package file size in bytes"
+msgstr ""
+
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
+msgid "Maximum Users"
+msgstr ""
+
+msgid "Maximum allowable lifetime for personal access token (days)"
+msgstr ""
+
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
+msgid "Maximum artifacts size"
+msgstr ""
+
+msgid "Maximum artifacts size (MB)"
+msgstr ""
+
+msgid "Maximum attachment size"
+msgstr ""
+
+msgid "Maximum attachment size (MB)"
+msgstr ""
+
+msgid "Maximum authenticated API requests per rate limit period per user"
+msgstr ""
+
+msgid "Maximum authenticated web requests per rate limit period per user"
+msgstr ""
+
+msgid "Maximum bulk request size (MiB)"
+msgstr ""
+
+msgid "Maximum capacity"
+msgstr ""
+
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
+msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
+msgstr ""
+
+msgid "Maximum delay (Minutes)"
+msgstr ""
+
+msgid "Maximum diff patch size"
+msgstr ""
+
+msgid "Maximum diff patch size (Bytes)"
+msgstr ""
+
+msgid "Maximum duration of a session."
+msgstr ""
+
+msgid "Maximum field length"
+msgstr ""
+
+msgid "Maximum file size indexed (KiB)"
+msgstr ""
+
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}."
+msgstr ""
+
+msgid "Maximum file size is 1MB. Pages are optimized for a 28px tall header logo"
+msgstr ""
+
+msgid "Maximum file size is 1MB. Pages are optimized for a 640x360 px logo."
+msgstr ""
+
+msgid "Maximum file size is 2MB. Please select a smaller file."
+msgstr ""
+
+msgid "Maximum files in a diff"
+msgstr ""
+
+msgid "Maximum group export download requests per minute"
+msgstr ""
+
+msgid "Maximum group export requests per minute"
+msgstr ""
+
+msgid "Maximum group import requests per minute"
+msgstr ""
+
+msgid "Maximum import size"
+msgstr ""
+
+msgid "Maximum import size (MB)"
+msgstr ""
+
+msgid "Maximum job artifact size"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "Maximum job timeout has a value which could not be accepted"
+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 ""
+
+msgid "Maximum number of %{name} (%{count}) exceeded"
+msgstr ""
+
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
+msgid "Maximum number of comments exceeded"
+msgstr ""
+
+msgid "Maximum number of mirrors that can be synchronizing at the same time."
+msgstr ""
+
+msgid "Maximum number of projects."
+msgstr ""
+
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
+msgid "Maximum number of unique IP addresses per user."
+msgstr ""
+
+msgid "Maximum page reached"
+msgstr ""
+
+msgid "Maximum page size"
+msgstr ""
+
+msgid "Maximum project export download requests per minute"
+msgstr ""
+
+msgid "Maximum project export requests per minute"
+msgstr ""
+
+msgid "Maximum project import requests per minute"
+msgstr ""
+
+msgid "Maximum push size"
+msgstr ""
+
+msgid "Maximum push size (MB)"
+msgstr ""
+
+msgid "Maximum requests per minute"
+msgstr ""
+
+msgid "Maximum running slices"
+msgstr ""
+
+msgid "Maximum size limit for a single commit."
+msgstr ""
+
+msgid "Maximum size limit for each repository."
+msgstr ""
+
+msgid "Maximum size of Elasticsearch bulk indexing requests."
+msgstr ""
+
+msgid "Maximum size of import files."
+msgstr ""
+
+msgid "Maximum size of individual attachments in comments."
+msgstr ""
+
+msgid "Maximum size of pages (MB)"
+msgstr ""
+
+msgid "Maximum snippet size"
+msgstr ""
+
+msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
+msgstr ""
+
+msgid "Maximum time that users are allowed to skip the setup of two-factor authentication (in hours). Set to 0 (zero) to enforce at next sign in."
+msgstr ""
+
+msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited."
+msgstr ""
+
+msgid "Maximum unauthenticated API requests per rate limit period per IP"
+msgstr ""
+
+msgid "Maximum unauthenticated web requests per rate limit period per IP"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Mean time to merge"
+msgstr ""
+
+msgid "Measured in bytes of code. Excludes generated and vendored code."
+msgstr ""
+
+msgid "Medium timeout"
+msgstr ""
+
+msgid "Medium vulnerabilities present"
+msgstr ""
+
+msgid "Member since"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Member since:"
+msgstr ""
+
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr ""
+
+msgid "Members listed as CODEOWNERS of affected files."
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "Members of a group may only view projects they have permission to access"
+msgstr ""
+
+msgid "Membership"
+msgstr ""
+
+msgid "Members|%{time} by %{user}"
+msgstr ""
+
+msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|2FA"
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Direct"
+msgstr ""
+
+msgid "Members|Disabled"
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Enabled"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
+msgid "Members|Filter members"
+msgstr ""
+
+msgid "Members|Inherited"
+msgstr ""
+
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
+msgid "Members|Membership"
+msgstr ""
+
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
+msgid "Members|Search groups"
+msgstr ""
+
+msgid "Members|Search invited"
+msgstr ""
+
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Menu"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge Conflicts"
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request Analytics"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge Requests in Review"
+msgstr ""
+
+msgid "Merge Requests merged"
+msgstr ""
+
+msgid "Merge automatically (%{strategy})"
+msgstr ""
+
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
+msgid "Merge blocked: new changes were just added."
+msgstr ""
+
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
+msgid "Merge blocked: the source branch must be rebased onto the target branch."
+msgstr ""
+
+msgid "Merge commit SHA"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge details"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge locally"
+msgstr ""
+
+msgid "Merge options"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
+msgstr ""
+
+msgid "Merge request analytics"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge request commits"
+msgstr ""
+
+msgid "Merge request dependencies"
+msgstr ""
+
+msgid "Merge request events"
+msgstr ""
+
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
+msgid "Merge request reports"
+msgstr ""
+
+msgid "Merge request was scheduled to merge after pipeline succeeds"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge the branch and fix any conflicts that come up"
+msgstr ""
+
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
+msgstr ""
+
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "Merge..."
+msgstr ""
+
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Select comment starting line"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Create issue to resolve thread"
+msgstr ""
+
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|This project does not allow squashing commits when merge requests are accepted."
+msgstr ""
+
+msgid "MergeRequests|Thread stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a thread"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest|Approved by @%{username}"
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch."
+msgstr ""
+
+msgid "MergeRequest|Compare %{target} and %{source}"
+msgstr ""
+
+msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
+msgstr ""
+
+msgid "MergeRequest|Error loading full diff. Please try again."
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files (%{modifier_key}P)"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Merged MRs"
+msgstr ""
+
+msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Merged by"
+msgstr ""
+
+msgid "Merged this merge request."
+msgstr ""
+
+msgid "Merged: %{merged}"
+msgstr ""
+
+msgid "Merges this merge request immediately."
+msgstr ""
+
+msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
+msgstr ""
+
+msgid "Message"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Method"
+msgstr ""
+
+msgid "Method call threshold (ms)"
+msgstr ""
+
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
+msgid "Metric:"
+msgstr ""
+
+msgid "MetricChart|Please select a metric"
+msgstr ""
+
+msgid "MetricChart|Selected"
+msgstr ""
+
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Grafana"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics Dashboard"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is invalid:"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is valid."
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics:"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
+msgstr ""
+
+msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
+msgstr ""
+
+msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
+msgstr ""
+
+msgid "MetricsSettings|Dashboard timezone"
+msgstr ""
+
+msgid "MetricsSettings|External dashboard URL"
+msgstr ""
+
+msgid "MetricsSettings|Manage metrics dashboard settings."
+msgstr ""
+
+msgid "MetricsSettings|Metrics"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
+msgid "Metrics|1. Define and preview panel"
+msgstr ""
+
+msgid "Metrics|2. Paste panel YAML into dashboard"
+msgstr ""
+
+msgid "Metrics|Add metric"
+msgstr ""
+
+msgid "Metrics|Add panel"
+msgstr ""
+
+msgid "Metrics|Avg"
+msgstr ""
+
+msgid "Metrics|Back to dashboard"
+msgstr ""
+
+msgid "Metrics|Cancel"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
+msgid "Metrics|Copy YAML"
+msgstr ""
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr ""
+
+msgid "Metrics|Create custom dashboard %{fileName}"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Create new dashboard"
+msgstr ""
+
+msgid "Metrics|Create your dashboard configuration file"
+msgstr ""
+
+msgid "Metrics|Current"
+msgstr ""
+
+msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Define panel YAML below to preview panel."
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Duplicate"
+msgstr ""
+
+msgid "Metrics|Duplicate current dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
+msgid "Metrics|Duplicating..."
+msgstr ""
+
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgid_plural "Metrics|Edit metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Metrics|Expand panel"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Invalid time range, please verify."
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
+msgstr ""
+
+msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
+msgstr ""
+
+msgid "Metrics|Manage chart links"
+msgstr ""
+
+msgid "Metrics|Max"
+msgstr ""
+
+msgid "Metrics|Metrics Settings"
+msgstr ""
+
+msgid "Metrics|Min"
+msgstr ""
+
+msgid "Metrics|More actions"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|Open repository"
+msgstr ""
+
+msgid "Metrics|Panel YAML"
+msgstr ""
+
+msgid "Metrics|Panel YAML copied"
+msgstr ""
+
+msgid "Metrics|Preview panel"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
+msgid "Metrics|Refresh dashboard"
+msgstr ""
+
+msgid "Metrics|Select a value"
+msgstr ""
+
+msgid "Metrics|Set refresh rate"
+msgstr ""
+
+msgid "Metrics|Star dashboard"
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard."
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard. %{error}"
+msgstr ""
+
+msgid "Metrics|There was an error fetching annotations. Please try again."
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting annotations information."
+msgstr ""
+
+msgid "Metrics|There was an error getting dashboard validation warnings information."
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error getting options for variable \"%{name}\"."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics. %{message}"
+msgstr ""
+
+msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Unstar dashboard"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Validating query"
+msgstr ""
+
+msgid "Metrics|Values"
+msgstr ""
+
+msgid "Metrics|View documentation"
+msgstr ""
+
+msgid "Metrics|View logs"
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You can save a copy of this dashboard to your repository so it can be customized. Select a file name and branch to save it."
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Mi"
+msgstr ""
+
+msgid "Middleman project with Static Site Editor support"
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration"
+msgstr ""
+
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone due date"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Group milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
+msgid "MilestoneSidebar|Closed:"
+msgstr ""
+
+msgid "MilestoneSidebar|Copy reference"
+msgstr ""
+
+msgid "MilestoneSidebar|Due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Edit"
+msgstr ""
+
+msgid "MilestoneSidebar|From"
+msgstr ""
+
+msgid "MilestoneSidebar|Issues"
+msgstr ""
+
+msgid "MilestoneSidebar|Merge requests"
+msgstr ""
+
+msgid "MilestoneSidebar|Merged:"
+msgstr ""
+
+msgid "MilestoneSidebar|New Issue"
+msgstr ""
+
+msgid "MilestoneSidebar|New issue"
+msgstr ""
+
+msgid "MilestoneSidebar|No due date"
+msgstr ""
+
+msgid "MilestoneSidebar|No start date"
+msgstr ""
+
+msgid "MilestoneSidebar|None"
+msgstr ""
+
+msgid "MilestoneSidebar|Open:"
+msgstr ""
+
+msgid "MilestoneSidebar|Reference:"
+msgstr ""
+
+msgid "MilestoneSidebar|Start date"
+msgstr ""
+
+msgid "MilestoneSidebar|Toggle sidebar"
+msgstr ""
+
+msgid "MilestoneSidebar|Until"
+msgstr ""
+
+msgid "MilestoneSidebar|complete"
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|Close Milestone"
+msgstr ""
+
+msgid "Milestones|Completed Issues (closed)"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Group Milestone"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Ongoing Issues (open and assigned)"
+msgstr ""
+
+msgid "Milestones|Project Milestone"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promote to Group Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|Reopen Milestone"
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Milestones|Unstarted Issues (open and unassigned)"
+msgstr ""
+
+msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr ""
+
+msgid "Minimum interval in days"
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror only protected branches"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror settings are only available to GitLab administrators."
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "Mirroring settings were successfully updated."
+msgstr ""
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Add SSH key"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Don't show again"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "ModalButton|Add projects"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modified"
+msgstr ""
+
+msgid "Modified in this version"
+msgstr ""
+
+msgid "Modify commit message"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
+msgid "Monitor the health and performance of GitLab with Prometheus."
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry."
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Month"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More Information"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More details"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information and share feedback"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "More information."
+msgstr ""
+
+msgid "More than %{number_commits_distance} commits different with %{default_branch}"
+msgstr ""
+
+msgid "More topics"
+msgstr ""
+
+msgid "Most relevant"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Mount point %{mounted_as} not found in %{model_class}."
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move down"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move selection down"
+msgstr ""
+
+msgid "Move selection up"
+msgstr ""
+
+msgid "Move test case"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "Move up"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
+msgstr ""
+
+msgid "Moved issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moved this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
+msgid "MrDeploymentActions|Deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Re-deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Stop environment"
+msgstr ""
+
+msgid "Multi-project"
+msgstr ""
+
+msgid "Multi-project Runners cannot be removed"
+msgstr ""
+
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
+msgid "Multiple IP address ranges are supported."
+msgstr ""
+
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
+msgid "Multiple domains are supported."
+msgstr ""
+
+msgid "Multiple model types found: %{model_types}"
+msgstr ""
+
+msgid "Multiple uploaders found: %{uploader_types}"
+msgstr ""
+
+msgid "Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1."
+msgstr ""
+
+msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
+msgstr ""
+
+msgid "Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "My Awesome Group"
+msgstr ""
+
+msgid "My company or team"
+msgstr ""
+
+msgid "My topic"
+msgstr ""
+
+msgid "My-Reaction"
+msgstr ""
+
+msgid "N/A"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name can't be blank"
+msgstr ""
+
+msgid "Name has already been taken"
+msgstr ""
+
+msgid "Name is already taken."
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Namespace"
+msgstr ""
+
+msgid "Namespace ID:"
+msgstr ""
+
+msgid "Namespace is empty"
+msgstr ""
+
+msgid "Namespace:"
+msgstr ""
+
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
+msgstr ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
+msgstr ""
+
+msgid "NamespaceUserCap|View pending approvals"
+msgstr ""
+
+msgid "NamespaceUserCap|Your group has reached its billable member limit"
+msgstr ""
+
+msgid "Namespaces"
+msgstr ""
+
+msgid "Namespaces to index"
+msgstr ""
+
+msgid "Naming, topics, avatar"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
+msgid "Navigation bar"
+msgstr ""
+
+msgid "NavigationTheme|Blue"
+msgstr ""
+
+msgid "NavigationTheme|Dark"
+msgstr ""
+
+msgid "NavigationTheme|Dark Mode (alpha)"
+msgstr ""
+
+msgid "NavigationTheme|Green"
+msgstr ""
+
+msgid "NavigationTheme|Indigo"
+msgstr ""
+
+msgid "NavigationTheme|Light"
+msgstr ""
+
+msgid "NavigationTheme|Light Blue"
+msgstr ""
+
+msgid "NavigationTheme|Light Green"
+msgstr ""
+
+msgid "NavigationTheme|Light Indigo"
+msgstr ""
+
+msgid "NavigationTheme|Light Red"
+msgstr ""
+
+msgid "NavigationTheme|Red"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Needs"
+msgstr ""
+
+msgid "Needs attention"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Network:"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}And%{labelEnd} %{spanStart}send an Alert to GitLab.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml mode"
+msgstr ""
+
+msgid "NetworkPolicies|Add alert"
+msgstr ""
+
+msgid "NetworkPolicies|Alerts are intended to be selectively used for a limited number of events that are potentially concerning and warrant a manual review. Alerts should not be used as a substitute for a SIEM or a logging tool. High volume alerts are likely to be dropped so as to preserve the stability of GitLab's integration with Kubernetes."
+msgstr ""
+
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
+msgstr ""
+
+msgid "NetworkPolicies|Create policy"
+msgstr ""
+
+msgid "NetworkPolicies|Define this policy's location, conditions and actions."
+msgstr ""
+
+msgid "NetworkPolicies|Delete policy"
+msgstr ""
+
+msgid "NetworkPolicies|Delete policy: %{policy}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
+msgid "NetworkPolicies|Edit policy"
+msgstr ""
+
+msgid "NetworkPolicies|Environment does not have deployment platform"
+msgstr ""
+
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
+msgid "NetworkPolicies|Invalid or empty policy"
+msgstr ""
+
+msgid "NetworkPolicies|Invalid or unsupported policy kind"
+msgstr ""
+
+msgid "NetworkPolicies|Kubernetes error: %{error}"
+msgstr ""
+
+msgid "NetworkPolicies|Network"
+msgstr ""
+
+msgid "NetworkPolicies|Network Policies can be used to limit which network traffic is allowed between containers inside the cluster."
+msgstr ""
+
+msgid "NetworkPolicies|Network policy can be created after the environment is loaded successfully."
+msgstr ""
+
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
+msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
+msgstr ""
+
+msgid "NetworkPolicies|Policy definition"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
+msgid "NetworkPolicies|Save changes"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, failed to update policy"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
+msgstr ""
+
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New %{issueType}"
+msgstr ""
+
+msgid "New %{type} in %{project}"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Branch"
+msgstr ""
+
+msgid "New Deploy Key"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Epic"
+msgstr ""
+
+msgid "New File"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Group Name"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Jira import"
+msgstr ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Project"
+msgstr ""
+
+msgid "New Requirement"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Test Case"
+msgstr ""
+
+msgid "New User"
+msgstr ""
+
+msgid "New application"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New confidential epic title "
+msgstr ""
+
+msgid "New confidential issue title"
+msgstr ""
+
+msgid "New deploy key"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New discussion"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New epic title"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
+msgid "New health check access token has been generated!"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New issue in %{project}"
+msgstr ""
+
+msgid "New issue title"
+msgstr ""
+
+msgid "New iteration created"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New list"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New name"
+msgstr ""
+
+msgid "New password"
+msgstr ""
+
+msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New project page"
+msgstr ""
+
+msgid "New project pages"
+msgstr ""
+
+msgid "New project/repository"
+msgstr ""
+
+msgid "New public deploy key"
+msgstr ""
+
+msgid "New release"
+msgstr ""
+
+msgid "New requirement"
+msgstr ""
+
+msgid "New response for issue #%{issue_iid}:"
+msgstr ""
+
+msgid "New runners registration token has been generated!"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New test case"
+msgstr ""
+
+msgid "New topic"
+msgstr ""
+
+msgid "New users set to external"
+msgstr ""
+
+msgid "New! Suggest changes directly"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "Newest first"
+msgstr ""
+
+msgid "Newly-registered users are external by default"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next design"
+msgstr ""
+
+msgid "Next file in diff"
+msgstr ""
+
+msgid "Next scan"
+msgstr ""
+
+msgid "Next unresolved discussion"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No %{header} for this request."
+msgstr ""
+
+msgid "No %{providerTitle} repositories found"
+msgstr ""
+
+msgid "No CSV data to display."
+msgstr ""
+
+msgid "No Epic"
+msgstr ""
+
+msgid "No Matching Results"
+msgstr ""
+
+msgid "No Milestone"
+msgstr ""
+
+msgid "No Scopes"
+msgstr ""
+
+msgid "No Tag"
+msgstr ""
+
+msgid "No active admin user found"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No application_settings found"
+msgstr ""
+
+msgid "No approvers"
+msgstr ""
+
+msgid "No artifacts found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No authentication methods configured."
+msgstr ""
+
+msgid "No available branches"
+msgstr ""
+
+msgid "No available groups to fork the project."
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{source} and %{target}"
+msgstr ""
+
+msgid "No child epics match applied filters"
+msgstr ""
+
+msgid "No commenters"
+msgstr ""
+
+msgid "No commits present here"
+msgstr ""
+
+msgid "No committers"
+msgstr ""
+
+msgid "No compliance frameworks are in use."
+msgstr ""
+
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
+msgstr ""
+
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No containers available"
+msgstr ""
+
+msgid "No contributions"
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card data for matching"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No data found"
+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 ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No email participants were added. Either none were provided, or they already exist."
+msgstr ""
+
+msgid "No endpoint provided"
+msgstr ""
+
+msgid "No errors to display."
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen."
+msgstr ""
+
+msgid "No file hooks found."
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No forks are available to you."
+msgstr ""
+
+msgid "No group provided"
+msgstr ""
+
+msgid "No grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+msgstr ""
+
+msgid "No iterations found"
+msgstr ""
+
+msgid "No iterations to show"
+msgstr ""
+
+msgid "No job log"
+msgstr ""
+
+msgid "No jobs to show"
+msgstr ""
+
+msgid "No label"
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matches found"
+msgstr ""
+
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
+msgid "No matching labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No matching results..."
+msgstr ""
+
+msgid "No member provided"
+msgstr ""
+
+msgid "No members found"
+msgstr ""
+
+msgid "No memberships found"
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestone"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No namespace"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No panels matching properties %{opts}"
+msgstr ""
+
+msgid "No parent group"
+msgstr ""
+
+msgid "No plan"
+msgstr ""
+
+msgid "No pods available"
+msgstr ""
+
+msgid "No policy matches this license"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritized labels with such name or description"
+msgstr ""
+
+msgid "No profiles found"
+msgstr ""
+
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
+msgid "No projects found"
+msgstr ""
+
+msgid "No public deploy keys"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No ref selected"
+msgstr ""
+
+msgid "No related merge requests found."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runner executable"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No service accounts"
+msgstr ""
+
+msgid "No severity matches the provided parameter"
+msgstr ""
+
+msgid "No source selected"
+msgstr ""
+
+msgid "No stack trace for this error"
+msgstr ""
+
+msgid "No starrers matched your search"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No tag selected"
+msgstr ""
+
+msgid "No template"
+msgstr ""
+
+msgid "No template selected"
+msgstr ""
+
+msgid "No test coverage"
+msgstr ""
+
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
+msgid "No vulnerabilities present"
+msgstr ""
+
+msgid "No webhook events"
+msgstr ""
+
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
+
+msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
+msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "No. of commits"
+msgstr ""
+
+msgid "Nobody has starred this repository yet"
+msgstr ""
+
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "Non-admin users are restricted to read-only access, in both GitLab UI and API."
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
+msgid "Normal text"
+msgstr ""
+
+msgid "Not Implemented"
+msgstr ""
+
+msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
+msgstr ""
+
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not found"
+msgstr ""
+
+msgid "Not found."
+msgstr ""
+
+msgid "Not permitted to destroy framework"
+msgstr ""
+
+msgid "Not ready yet. Try again later."
+msgstr ""
+
+msgid "Not started"
+msgstr ""
+
+msgid "Not supported"
+msgstr ""
+
+msgid "Note"
+msgstr ""
+
+msgid "Note creation requests"
+msgstr ""
+
+msgid "Note parameters are invalid: %{errors}"
+msgstr ""
+
+msgid "Note that pushing to GitLab requires write access to this repository."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: current forks will keep their visibility level."
+msgstr ""
+
+msgid "NoteForm|Note"
+msgstr ""
+
+msgid "Notes rate limit"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Confidential comments are only visible to members with the role of Reporter or higher"
+msgstr ""
+
+msgid "Notes|Make this comment confidential"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Notes|This comment is confidential and only visible to project members"
+msgstr ""
+
+msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
+msgid "Nothing found…"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "Notification settings saved"
+msgstr ""
+
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEvent|Change reviewer merge request"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Fixed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Issue due"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|Merge when pipeline succeeds"
+msgstr ""
+
+msgid "NotificationEvent|Moved project"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|New release"
+msgstr ""
+
+msgid "NotificationEvent|Push to merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Reopen merge request"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications have been disabled by the project or group owner"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Notify users by email when sign-in location is not recognized."
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "Now, personalize your GitLab experience"
+msgstr ""
+
+msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
+msgstr ""
+
+msgid "Number of Elasticsearch shards and replicas per index:"
+msgstr ""
+
+msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full %{code_start}git repack%{code_end} is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run."
+msgstr ""
+
+msgid "Number of LOCs per commit"
+msgstr ""
+
+msgid "Number of commits"
+msgstr ""
+
+msgid "Number of commits per MR"
+msgstr ""
+
+msgid "Number of employees"
+msgstr ""
+
+msgid "Number of events"
+msgstr ""
+
+msgid "Number of events for this project: %{total_count}."
+msgstr ""
+
+msgid "Number of files touched"
+msgstr ""
+
+msgid "Number of replicas"
+msgstr ""
+
+msgid "Number of shards"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Object Storage replication"
+msgstr ""
+
+msgid "Object does not exist on the server or you don't have permissions to access it"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Off"
+msgstr ""
+
+msgid "Oh no!"
+msgstr ""
+
+msgid "Ok, let's go"
+msgstr ""
+
+msgid "Okay"
+msgstr ""
+
+msgid "Oldest first"
+msgstr ""
+
+msgid "OmniAuth"
+msgstr ""
+
+msgid "On"
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "On-call Schedules"
+msgstr ""
+
+msgid "On-call schedules"
+msgstr ""
+
+msgid "OnCallScheduless|Any escalation rules that are using this schedule will also be deleted."
+msgstr ""
+
+msgid "OnCallSchedules|1 day"
+msgstr ""
+
+msgid "OnCallSchedules|2 weeks"
+msgstr ""
+
+msgid "OnCallSchedules|Add a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add a schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Add an additional schedule to your project"
+msgstr ""
+
+msgid "OnCallSchedules|Add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteRotation}\" rotation? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\" schedule? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Collapse schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Create on-call schedules in GitLab"
+msgstr ""
+
+msgid "OnCallSchedules|Currently no rotation."
+msgstr ""
+
+msgid "OnCallSchedules|Delete rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Delete schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Edit rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
+msgid "OnCallSchedules|Expand schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedules"
+msgstr ""
+
+msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
+msgstr ""
+
+msgid "OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification."
+msgstr ""
+
+msgid "OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification."
+msgstr ""
+
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation length"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation name cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation participants cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation start date cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotations"
+msgstr ""
+
+msgid "OnCallSchedules|Route alerts directly to specific members of your team"
+msgstr ""
+
+msgid "OnCallSchedules|Select participant"
+msgstr ""
+
+msgid "OnCallSchedules|Select timezone"
+msgstr ""
+
+msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully created a new rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully edited your rotation"
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|Try adding a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|User %{name} is currently part of:"
+msgstr ""
+
+msgid "OnCallSchedules|View next timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|View previous timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|You are currently a part of:"
+msgstr ""
+
+msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Are you sure you want to delete this scan?"
+msgstr ""
+
+msgid "OnDemandScans|Could not delete saved scan. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not run the scan. Please try again."
+msgstr ""
+
+msgid "OnDemandScans|Create new scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Create new site profile"
+msgstr ""
+
+msgid "OnDemandScans|Delete profile"
+msgstr ""
+
+msgid "OnDemandScans|Description (optional)"
+msgstr ""
+
+msgid "OnDemandScans|Edit on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|Edit profile"
+msgstr ""
+
+msgid "OnDemandScans|For example: Tests the login page for SQL injections"
+msgstr ""
+
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|New on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
+msgid "OnDemandScans|On-demand Scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Repeats"
+msgstr ""
+
+msgid "OnDemandScans|Run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save and run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan library"
+msgstr ""
+
+msgid "OnDemandScans|Scan name"
+msgstr ""
+
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
+msgid "OnDemandScans|Scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Schedule scan"
+msgstr ""
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profile"
+msgstr ""
+
+msgid "OnDemandScans|Start time"
+msgstr ""
+
+msgid "OnDemandScans|Target"
+msgstr ""
+
+msgid "OnDemandScans|The scan could not be canceled."
+msgstr ""
+
+msgid "OnDemandScans|The scan could not be retried."
+msgstr ""
+
+msgid "OnDemandScans|There are no finished scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no running scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no saved scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no scheduled scans."
+msgstr ""
+
+msgid "OnDemandScans|Use existing scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "OnDemandScans|View results"
+msgstr ""
+
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
+
+msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
+msgstr ""
+
+msgid "Once you confirm and press \"Reduce project visibility\":"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
+msgid "One or more groups that you don't have access to."
+msgstr ""
+
+msgid "One or more of you personal access tokens were revoked"
+msgstr ""
+
+msgid "One or more of your %{provider} projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
+msgid "One or more of your personal access tokens has expired."
+msgstr ""
+
+msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less:"
+msgstr ""
+
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
+msgstr ""
+
+msgid "Only 1 appearances row can exist"
+msgstr ""
+
+msgid "Only Issue ID or merge request ID is required"
+msgstr ""
+
+msgid "Only Project Members"
+msgstr ""
+
+msgid "Only active projects show up in the search and on the dashboard."
+msgstr ""
+
+msgid "Only admins can delete project"
+msgstr ""
+
+msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
+msgstr ""
+
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
+msgid "Only include features new to your current subscription tier."
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Only projects created under a Ultimate license are available in Security Dashboards."
+msgstr ""
+
+msgid "Only reCAPTCHA v2 is supported:"
+msgstr ""
+
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
+msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
+msgstr ""
+
+msgid "Only verified users with an email address in any of these domains can be added to the group."
+msgstr ""
+
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Selection"
+msgstr ""
+
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgstr ""
+
+msgid "Open epics"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Web IDE"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open in your IDE"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open registration is enabled on your instance."
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{open}"
+msgstr ""
+
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI Specification file path or URL"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MRs"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation not allowed"
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add projects"
+msgstr ""
+
+msgid "OperationsDashboard|More information"
+msgstr ""
+
+msgid "OperationsDashboard|Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "Optimize your workflow with CI/CD Pipelines"
+msgstr ""
+
+msgid "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+msgstr ""
+
+msgid "Optional."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Organizations"
+msgstr ""
+
+msgid "Orphaned member"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other available runners"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Other merge requests block this MR"
+msgstr ""
+
+msgid "Other versions"
+msgstr ""
+
+msgid "Other visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Otherwise, click the link below to complete the process."
+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 ""
+
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "Outdent"
+msgstr ""
+
+msgid "Overridden"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owned by %{image_tag}"
+msgstr ""
+
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
+msgid "Owned by:"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
+msgid "Package Registry"
+msgstr ""
+
+msgid "Package Registry: authenticated API requests"
+msgstr ""
+
+msgid "Package Registry: unauthenticated API requests"
+msgstr ""
+
+msgid "Package already exists"
+msgstr ""
+
+msgid "Package deleted successfully"
+msgstr ""
+
+msgid "Package file size limits"
+msgstr ""
+
+msgid "Package recipe already exists"
+msgstr ""
+
+msgid "Package registry rate limits"
+msgstr ""
+
+msgid "Package type"
+msgstr ""
+
+msgid "Package type must be Conan"
+msgstr ""
+
+msgid "Package type must be Debian"
+msgstr ""
+
+msgid "Package type must be Helm"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NPM"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "Package type must be RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Accept packages with the same name and version."
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Reject packages with the same name and version."
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+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 ""
+
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
+msgid "PackageRegistry|App group: %{group}"
+msgstr ""
+
+msgid "PackageRegistry|App name: %{name}"
+msgstr ""
+
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|Composer"
+msgstr ""
+
+msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
+msgstr ""
+
+msgid "PackageRegistry|Conan"
+msgstr ""
+
+msgid "PackageRegistry|Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy .pypirc content"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Setup Command"
+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 ""
+
+msgid "PackageRegistry|Copy Maven command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven registry XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Pip command"
+msgstr ""
+
+msgid "PackageRegistry|Copy SHA"
+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 ""
+
+msgid "PackageRegistry|Copy npm command"
+msgstr ""
+
+msgid "PackageRegistry|Copy npm setup command"
+msgstr ""
+
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
+msgid "PackageRegistry|Copy target SHA"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn command"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn setup command"
+msgstr ""
+
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
+msgid "PackageRegistry|Debian"
+msgstr ""
+
+msgid "PackageRegistry|Delete Package File"
+msgstr ""
+
+msgid "PackageRegistry|Delete Package Version"
+msgstr ""
+
+msgid "PackageRegistry|Delete package"
+msgstr ""
+
+msgid "PackageRegistry|Failed to load the package data"
+msgstr ""
+
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|Generic"
+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|Helm"
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|Install package version"
+msgstr ""
+
+msgid "PackageRegistry|Instance-level"
+msgstr ""
+
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
+msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
+msgstr ""
+
+msgid "PackageRegistry|License information located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Manually Published"
+msgstr ""
+
+msgid "PackageRegistry|Maven"
+msgstr ""
+
+msgid "PackageRegistry|Maven Command"
+msgstr ""
+
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Package Registry"
+msgstr ""
+
+msgid "PackageRegistry|Package deleted successfully"
+msgstr ""
+
+msgid "PackageRegistry|Package file deleted successfully"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Pip Command"
+msgstr ""
+
+msgid "PackageRegistry|Project-level"
+msgstr ""
+
+msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|Publish packages if their name or version matches this regex."
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPI"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|Required Python: %{pythonVersion}"
+msgstr ""
+
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
+msgid "PackageRegistry|Settings for Maven packages"
+msgstr ""
+
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+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 ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Target SHA: %{sha}"
+msgstr ""
+
+msgid "PackageRegistry|There are no other versions of this package."
+msgstr ""
+
+msgid "PackageRegistry|There are no packages yet"
+msgstr ""
+
+msgid "PackageRegistry|There was a problem fetching the details for this package."
+msgstr ""
+
+msgid "PackageRegistry|This NuGet package has no dependencies."
+msgstr ""
+
+msgid "PackageRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "PackageRegistry|Type"
+msgstr ""
+
+msgid "PackageRegistry|Unable to fetch package version information."
+msgstr ""
+
+msgid "PackageRegistry|Unable to load package"
+msgstr ""
+
+msgid "PackageRegistry|Use GitLab as a private registry for common package formats. %{linkStart}Learn more.%{linkEnd}"
+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 ""
+
+msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
+msgstr ""
+
+msgid "PackageRegistry|npm"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "Packages & Registries"
+msgstr ""
+
+msgid "Page not found"
+msgstr ""
+
+msgid "Page settings"
+msgstr ""
+
+msgid "PagerDutySettings|Active"
+msgstr ""
+
+msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
+msgstr ""
+
+msgid "PagerDutySettings|Failed to update Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Reset webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL update was successful"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pagination|First"
+msgstr ""
+
+msgid "Pagination|Go to first page"
+msgstr ""
+
+msgid "Pagination|Go to last page"
+msgstr ""
+
+msgid "Pagination|Go to next page"
+msgstr ""
+
+msgid "Pagination|Go to previous page"
+msgstr ""
+
+msgid "Pagination|Last"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
+msgstr ""
+
+msgid "Parent"
+msgstr ""
+
+msgid "Parent epic doesn't exist."
+msgstr ""
+
+msgid "Parent epic is not present."
+msgstr ""
+
+msgid "Parsing error for param :embed_json. %{message}"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Pass job variables"
+msgstr ""
+
+msgid "Pass the header %{codeOpen} X-Profile-Token: %{profile_token} %{codeClose} to profile the request"
+msgstr ""
+
+msgid "Passed"
+msgstr ""
+
+msgid "Passed on"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password (optional)"
+msgstr ""
+
+msgid "Password authentication is unavailable."
+msgstr ""
+
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
+
+msgid "PasswordPrompt|Confirm password"
+msgstr ""
+
+msgid "PasswordPrompt|Confirm password to continue"
+msgstr ""
+
+msgid "PasswordPrompt|Password is required"
+msgstr ""
+
+msgid "PasswordPrompt|Please enter your password to confirm"
+msgstr ""
+
+msgid "Passwords should be unique and not used for any other sites or services."
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste a public key here."
+msgstr ""
+
+msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
+msgstr ""
+
+msgid "Paste confidential epic link"
+msgstr ""
+
+msgid "Paste confidential issue link"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste project path (i.e. gitlab-org/gitlab)"
+msgstr ""
+
+msgid "Paste this DSN into your Sentry SDK"
+msgstr ""
+
+msgid "Patch to apply"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
+msgid "Paused"
+msgstr ""
+
+msgid "Paused runners don't accept new jobs"
+msgstr ""
+
+msgid "Peer review by"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "Pending Deletion"
+msgstr ""
+
+msgid "Pending comments"
+msgstr ""
+
+msgid "Pending deletion"
+msgstr ""
+
+msgid "Pending owner approval"
+msgstr ""
+
+msgid "Pending sync…"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "People without permission will never get a notification."
+msgstr ""
+
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "Percentage"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
+msgstr ""
+
+msgid "Perform code reviews and enhance collaboration with merge requests."
+msgstr ""
+
+msgid "Perform common operations on GitLab project"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Backend"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|DOM Content Loaded"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
+msgid "PerformanceBar|First Contentful Paint"
+msgstr ""
+
+msgid "PerformanceBar|Flamegraph with mode:"
+msgstr ""
+
+msgid "PerformanceBar|Frontend resources"
+msgstr ""
+
+msgid "PerformanceBar|Gitaly calls"
+msgstr ""
+
+msgid "PerformanceBar|Memory"
+msgstr ""
+
+msgid "PerformanceBar|Redis calls"
+msgstr ""
+
+msgid "PerformanceBar|Rugged calls"
+msgstr ""
+
+msgid "PerformanceBar|SQL queries"
+msgstr ""
+
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
+msgid "PerformanceBar|Stats"
+msgstr ""
+
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
+
+msgid "PerformanceBar|cpu"
+msgstr ""
+
+msgid "PerformanceBar|object"
+msgstr ""
+
+msgid "PerformanceBar|wall"
+msgstr ""
+
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
+msgid "Period in seconds"
+msgstr ""
+
+msgid "Permalink"
+msgstr ""
+
+msgid "Permanently delete project"
+msgstr ""
+
+msgid "Permanently remove group"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions Help"
+msgstr ""
+
+msgid "Permissions and group features"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal Access Token prefix"
+msgstr ""
+
+msgid "Personal access tokens are not revoked upon expiration."
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Personal projects"
+msgstr ""
+
+msgid "Personal projects limit:"
+msgstr ""
+
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pin code"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline %{label}"
+msgstr ""
+
+msgid "Pipeline %{label} for \"%{dataTitle}\""
+msgstr ""
+
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
+msgid "Pipeline ID"
+msgstr ""
+
+msgid "Pipeline IID"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline URL"
+msgstr ""
+
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
+msgid "Pipeline ran in fork of project"
+msgstr ""
+
+msgid "Pipeline status emails"
+msgstr ""
+
+msgid "Pipeline subscriptions"
+msgstr ""
+
+msgid "Pipeline subscriptions trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "Pipeline: %{status}"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the analytics data"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
+msgstr ""
+
+msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
+msgstr ""
+
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|There was an error parsing the data for the charts."
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
+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|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|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|The pipeline status is at the top of the page."
+msgstr ""
+
+msgid "PipelineEditorTutorial|This template creates a simple test pipeline. To use it:"
+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|âš™ï¸ 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 ""
+
+msgid "PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax."
+msgstr ""
+
+msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSource|API"
+msgstr ""
+
+msgid "PipelineSource|Chat"
+msgstr ""
+
+msgid "PipelineSource|External"
+msgstr ""
+
+msgid "PipelineSource|External Pull Request"
+msgstr ""
+
+msgid "PipelineSource|Merge Request"
+msgstr ""
+
+msgid "PipelineSource|On-Demand DAST Scan"
+msgstr ""
+
+msgid "PipelineSource|On-Demand DAST Validation"
+msgstr ""
+
+msgid "PipelineSource|Parent Pipeline"
+msgstr ""
+
+msgid "PipelineSource|Pipeline"
+msgstr ""
+
+msgid "PipelineSource|Push"
+msgstr ""
+
+msgid "PipelineSource|Schedule"
+msgstr ""
+
+msgid "PipelineSource|Trigger"
+msgstr ""
+
+msgid "PipelineSource|Web"
+msgstr ""
+
+msgid "PipelineSource|Web IDE"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+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 ""
+
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
+msgstr ""
+
+msgid "Pipelines|CI lint"
+msgstr ""
+
+msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
+msgstr ""
+
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
+
+msgid "Pipelines|Clear runner caches"
+msgstr ""
+
+msgid "Pipelines|Configuration validation currently not available."
+msgstr ""
+
+msgid "Pipelines|Copy trigger token"
+msgstr ""
+
+msgid "Pipelines|Could not load artifacts."
+msgstr ""
+
+msgid "Pipelines|Could not load merged YAML content"
+msgstr ""
+
+msgid "Pipelines|Description"
+msgstr ""
+
+msgid "Pipelines|Edit"
+msgstr ""
+
+msgid "Pipelines|Editor"
+msgstr ""
+
+msgid "Pipelines|Get familiar with GitLab CI/CD syntax by starting with a basic 3 stage CI/CD pipeline."
+msgstr ""
+
+msgid "Pipelines|Get started with GitLab CI/CD"
+msgstr ""
+
+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 ""
+
+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|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 ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading pipelines"
+msgstr ""
+
+msgid "Pipelines|Merged YAML is view only"
+msgstr ""
+
+msgid "Pipelines|More Information"
+msgstr ""
+
+msgid "Pipelines|No triggers have been created yet. Add one using the form above."
+msgstr ""
+
+msgid "Pipelines|Owner"
+msgstr ""
+
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Revoke"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|The %{namespace_name} namespace has %{percentage}%% or less Shared Runner Pipeline minutes remaining. After it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|The %{namespace_name} namespace has exceeded its pipeline minutes quota. Buy additional pipeline minutes, or no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|The CI configuration was not loaded, please try again."
+msgstr ""
+
+msgid "Pipelines|The GitLab CI configuration could not be updated."
+msgstr ""
+
+msgid "Pipelines|There are currently no finished pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid:"
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is valid."
+msgstr ""
+
+msgid "Pipelines|This is a child pipeline within the parent pipeline"
+msgstr ""
+
+msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
+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 ""
+
+msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Pipelines|Use a CI/CD template"
+msgstr ""
+
+msgid "Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works."
+msgstr ""
+
+msgid "Pipelines|Use a sample CI/CD template"
+msgstr ""
+
+msgid "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD."
+msgstr ""
+
+msgid "Pipelines|Use template"
+msgstr ""
+
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
+msgid "Pipelines|View merged YAML"
+msgstr ""
+
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
+msgid "Pipelines|invalid"
+msgstr ""
+
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
+
+msgid "Pipeline|Actions"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Branches or tags could not be loaded."
+msgstr ""
+
+msgid "Pipeline|Canceled"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
+msgid "Pipeline|Date"
+msgstr ""
+
+msgid "Pipeline|Detached merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Failed"
+msgstr ""
+
+msgid "Pipeline|In progress"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline jobs can not be retried"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
+msgstr ""
+
+msgid "Pipeline|Pipeline cannot be run."
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Run pipeline"
+msgstr ""
+
+msgid "Pipeline|Running"
+msgstr ""
+
+msgid "Pipeline|Skipped"
+msgstr ""
+
+msgid "Pipeline|Source"
+msgstr ""
+
+msgid "Pipeline|Source|Security Policy"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Tag name"
+msgstr ""
+
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|Trigger author"
+msgstr ""
+
+msgid "Pipeline|Triggerer"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|View commit"
+msgstr ""
+
+msgid "Pipeline|View pipeline"
+msgstr ""
+
+msgid "Pipeline|We are currently unable to fetch pipeline data"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|for"
+msgstr ""
+
+msgid "Pipeline|on"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "PivotalTrackerService|Add commit messages as comments to Pivotal Tracker stories."
+msgstr ""
+
+msgid "PivotalTrackerService|Comma-separated list of branches to automatically inspect. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user."
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "Plain-text response to send to clients that hit a rate limit"
+msgstr ""
+
+msgid "Plan"
+msgstr ""
+
+msgid "Plan:"
+msgstr ""
+
+msgid "Planning hierarchy"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "PlantUML URL"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Play all manual"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
+msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+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 confirm your account"
+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}."
+msgstr ""
+
+msgid "Please choose a file"
+msgstr ""
+
+msgid "Please complete your profile with email address"
+msgstr ""
+
+msgid "Please confirm your email address"
+msgstr ""
+
+msgid "Please contact an admin to register runners."
+msgstr ""
+
+msgid "Please contact your GitLab administrator if you think this is an error."
+msgstr ""
+
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
+msgid "Please contact your administrator."
+msgstr ""
+
+msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
+msgstr ""
+
+msgid "Please copy, download, or print your recovery codes before proceeding."
+msgstr ""
+
+msgid "Please create a password for your new account."
+msgstr ""
+
+msgid "Please create a username with only alphanumeric characters."
+msgstr ""
+
+msgid "Please create an index before enabling indexing"
+msgstr ""
+
+msgid "Please delete your current license if you want to downgrade to the free plan."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please enter a non-negative number"
+msgstr ""
+
+msgid "Please enter a number greater than %{number} (from the project settings)"
+msgstr ""
+
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
+msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
+msgstr ""
+
+msgid "Please enter a valid number"
+msgstr ""
+
+msgid "Please enter a valid time interval"
+msgstr ""
+
+msgid "Please enter or upload a valid license."
+msgstr ""
+
+msgid "Please enter your current password."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please fill in a name for your topic."
+msgstr ""
+
+msgid "Please fill out this field."
+msgstr ""
+
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr ""
+
+msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+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 ""
+
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please provide attributes to update"
+msgstr ""
+
+msgid "Please reach out if you have any questions and we'll be happy to assist."
+msgstr ""
+
+msgid "Please refer to %{docs_url}"
+msgstr ""
+
+msgid "Please review the updated escalation policies for %{project_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "Please review the updated escalation policies for %{project}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "Please select"
+msgstr ""
+
+msgid "Please select a Jira project"
+msgstr ""
+
+msgid "Please select a country"
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
+msgid "Please select a group"
+msgstr ""
+
+msgid "Please select a group."
+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 ""
+
+msgid "Please select at least one filter to see results"
+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 ""
+
+msgid "Please solve the captcha"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
+msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "Please type the following to confirm:"
+msgstr ""
+
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Pod does not exist"
+msgstr ""
+
+msgid "Pod not found"
+msgstr ""
+
+msgid "Pods in use"
+msgstr ""
+
+msgid "Point to any links you like: documentation, built binaries, or other related materials. These can be internal or external links from your GitLab instance. Duplicate URLs are not allowed."
+msgstr ""
+
+msgid "Policies"
+msgstr ""
+
+msgid "Policy management project does have any policies in %{policy_path}"
+msgstr ""
+
+msgid "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Port"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
+msgid "Postman collection file path or URL"
+msgstr ""
+
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
+msgid "Pre-defined push rules."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences saved."
+msgstr ""
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
+msgid "Preferences|Configure how dates and times display for you."
+msgstr ""
+
+msgid "Preferences|Customize integrations with third party services."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|Enable Gitpod integration"
+msgstr ""
+
+msgid "Preferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "Preferences|Failed to save preferences."
+msgstr ""
+
+msgid "Preferences|For example: 30 minutes ago."
+msgstr ""
+
+msgid "Preferences|Gitpod"
+msgstr ""
+
+msgid "Preferences|Homepage content"
+msgstr ""
+
+msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgstr ""
+
+msgid "Preferences|Integrations"
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
+msgid "Preferences|Must be a number between %{min} and %{max}"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Render whitespace characters in the Web IDE"
+msgstr ""
+
+msgid "Preferences|Show one file at a time on merge request's Changes tab"
+msgstr ""
+
+msgid "Preferences|Show whitespace changes in diffs"
+msgstr ""
+
+msgid "Preferences|Sourcegraph"
+msgstr ""
+
+msgid "Preferences|Surround text selection when typing quotes or brackets"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|Tab width"
+msgstr ""
+
+msgid "Preferences|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
+
+msgid "Prevent auto-stopping"
+msgstr ""
+
+msgid "Prevent editing approval rules in projects and merge requests."
+msgstr ""
+
+msgid "Prevent environment from auto-stopping"
+msgstr ""
+
+msgid "Prevent project forking outside current group"
+msgstr ""
+
+msgid "Prevent users from changing their profile name"
+msgstr ""
+
+msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
+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 ""
+
+msgid "Preview changes"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Previous Artifacts"
+msgstr ""
+
+msgid "Previous commit"
+msgstr ""
+
+msgid "Previous design"
+msgstr ""
+
+msgid "Previous file in diff"
+msgstr ""
+
+msgid "Previous unresolved discussion"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Primary Action"
+msgstr ""
+
+msgid "Print codes"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Priority"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Guest users are not allowed to view detailed release information like title and source code."
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private group(s)"
+msgstr ""
+
+msgid "Private profile"
+msgstr ""
+
+msgid "Private projects Minutes cost factor"
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Proceed"
+msgstr ""
+
+msgid "Product Analytics"
+msgstr ""
+
+msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
+msgstr ""
+
+msgid "Productivity"
+msgstr ""
+
+msgid "Productivity Analytics"
+msgstr ""
+
+msgid "Productivity analytics can help identify the problems that are delaying your team"
+msgstr ""
+
+msgid "ProductivityAanalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Ascending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Descending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Hours"
+msgstr ""
+
+msgid "ProductivityAnalytics|List"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Time to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Trendline"
+msgstr ""
+
+msgid "ProductivityAnalytics|is earlier than the given merged at after date"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profile failed to delete"
+msgstr ""
+
+msgid "Profile image guideline"
+msgstr ""
+
+msgid "Profile page:"
+msgstr ""
+
+msgid "Profile parameter missing"
+msgstr ""
+
+msgid "ProfileSession|on"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|%{provider} Active"
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|An error occurred while updating your username, please try again."
+msgstr ""
+
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
+msgid "Profiles|Bio"
+msgstr ""
+
+msgid "Profiles|Busy"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Commit email"
+msgstr ""
+
+msgid "Profiles|Connect %{provider}"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Default notification email"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Disconnect %{provider}"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Ensure you have two-factor authentication recovery codes stored in a safe place."
+msgstr ""
+
+msgid "Profiles|Enter how your name is pronounced to help people address you correctly"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Enter your password to confirm the email change"
+msgstr ""
+
+msgid "Profiles|Enter your pronouns to let people know how to refer to you"
+msgstr ""
+
+msgid "Profiles|Expiration date"
+msgstr ""
+
+msgid "Profiles|Expired key is not valid."
+msgstr ""
+
+msgid "Profiles|Expired:"
+msgstr ""
+
+msgid "Profiles|Expires:"
+msgstr ""
+
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|GitLab is unable to verify your identity automatically. For security purposes, you must set a password by %{openingTag}resetting your password%{closingTag} to delete your account."
+msgstr ""
+
+msgid "Profiles|Give your individual key a title. This will be publicly visible."
+msgstr ""
+
+msgid "Profiles|If after setting a password, the option to delete your account is still not available, please email %{data_request} to begin the account deletion process."
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid key."
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Job title"
+msgstr ""
+
+msgid "Profiles|Key"
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date."
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
+msgstr ""
+
+msgid "Profiles|Last used:"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Location"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|Manage two-factor authentication"
+msgstr ""
+
+msgid "Profiles|No file chosen."
+msgstr ""
+
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Primary email"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
+msgid "Profiles|Pronouns"
+msgstr ""
+
+msgid "Profiles|Pronunciation"
+msgstr ""
+
+msgid "Profiles|Public avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Publicly visible private SSH keys can compromise your system."
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Set your local time zone"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Static object token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The ability to update your name has been disabled by your administrator."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Time settings"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|User ID"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|Website url"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|https://website.com"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profile|%{job_title} at %{organization}"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
+msgid "Project %{project_repo} could not be found"
+msgstr ""
+
+msgid "Project & Group can not be assigned at the same time"
+msgstr ""
+
+msgid "Project '%{project_name}' is being imported."
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' is restored."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted on %{date}"
+msgstr ""
+
+msgid "Project Access Tokens"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+msgstr ""
+
+msgid "Project Templates"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Project already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+msgstr ""
+
+msgid "Project audit events"
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
+msgid "Project configuration, excluding integrations"
+msgstr ""
+
+msgid "Project description (optional)"
+msgstr ""
+
+msgid "Project does not exist or you don't have permission to perform this action"
+msgstr ""
+
+msgid "Project does not have a policy configuration"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export download requests"
+msgstr ""
+
+msgid "Project export enabled"
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export requests"
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Project has too many %{label_for_message} to search"
+msgstr ""
+
+msgid "Project import requests"
+msgstr ""
+
+msgid "Project info:"
+msgstr ""
+
+msgid "Project information"
+msgstr ""
+
+msgid "Project is required when cluster_type is :project"
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project milestone"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project navigation"
+msgstr ""
+
+msgid "Project order will not be saved as local storage is not available."
+msgstr ""
+
+msgid "Project path"
+msgstr ""
+
+msgid "Project security status"
+msgstr ""
+
+msgid "Project security status help page"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project uploads"
+msgstr ""
+
+msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
+msgstr ""
+
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "Project: %{name}"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Starrer"
+msgstr ""
+
+msgid "ProjectOverview|Starrers"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Failure"
+msgstr ""
+
+msgid "ProjectQualitySummary|Latest pipeline results"
+msgstr ""
+
+msgid "ProjectQualitySummary|Learn more about test coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Learn more about test reports"
+msgstr ""
+
+msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
+msgstr ""
+
+msgid "ProjectQualitySummary|See full report"
+msgstr ""
+
+msgid "ProjectQualitySummary|See project Code Coverage Statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Skipped"
+msgstr ""
+
+msgid "ProjectQualitySummary|Success"
+msgstr ""
+
+msgid "ProjectQualitySummary|Test coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Test runs"
+msgstr ""
+
+msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
+msgstr ""
+
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|No matching results"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSelect|Search projects"
+msgstr ""
+
+msgid "ProjectSelect|Select a project"
+msgstr ""
+
+msgid "ProjectSelect|There was an error fetching the projects. Please try again."
+msgstr ""
+
+msgid "ProjectService|Drone server URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Enter new password."
+msgstr ""
+
+msgid "ProjectService|Enter new token"
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins server URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password."
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with Buildkite."
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with Drone."
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
+msgstr ""
+
+msgid "ProjectService|TeamCity server URL"
+msgstr ""
+
+msgid "ProjectService|The build configuration ID of the TeamCity project."
+msgstr ""
+
+msgid "ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository."
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectService|Token for the Drone project."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments on confidential issues."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new tags pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event for pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
+msgstr ""
+
+msgid "ProjectService|Trigger event when a pipeline status changes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a wiki page is created or updated."
+msgstr ""
+
+msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
+msgstr ""
+
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Build, test, and deploy your changes."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and selected by default."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and unselected by default."
+msgstr ""
+
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
+
+msgid "ProjectSettings|Configure your project resources and monitor their health."
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Container registry"
+msgstr ""
+
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
+
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
+msgid "ProjectSettings|Disable email notifications"
+msgstr ""
+
+msgid "ProjectSettings|Do not allow"
+msgstr ""
+
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
+
+msgid "ProjectSettings|Enable merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Enable merged results pipelines"
+msgstr ""
+
+msgid "ProjectSettings|Encourage"
+msgstr ""
+
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its Docker images"
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its packages."
+msgstr ""
+
+msgid "ProjectSettings|Everyone"
+msgstr ""
+
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
+
+msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
+msgstr ""
+
+msgid "ProjectSettings|Forks"
+msgstr ""
+
+msgid "ProjectSettings|Git Large File Storage (LFS)"
+msgstr ""
+
+msgid "ProjectSettings|Global"
+msgstr ""
+
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
+msgid "ProjectSettings|Internal"
+msgstr ""
+
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
+msgid "ProjectSettings|Issues"
+msgstr ""
+
+msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgstr ""
+
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
+msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
+msgstr ""
+
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
+msgid "ProjectSettings|Merge suggestions"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
+
+msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Operations"
+msgstr ""
+
+msgid "ProjectSettings|Override user notification preferences for all project members."
+msgstr ""
+
+msgid "ProjectSettings|Packages"
+msgstr ""
+
+msgid "ProjectSettings|Pages"
+msgstr ""
+
+msgid "ProjectSettings|Pages for project documentation."
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Private"
+msgstr ""
+
+msgid "ProjectSettings|Project visibility"
+msgstr ""
+
+msgid "ProjectSettings|Public"
+msgstr ""
+
+msgid "ProjectSettings|Repository"
+msgstr ""
+
+msgid "ProjectSettings|Require"
+msgstr ""
+
+msgid "ProjectSettings|Require an associated issue from Jira"
+msgstr ""
+
+msgid "ProjectSettings|Requirements"
+msgstr ""
+
+msgid "ProjectSettings|Requirements management system."
+msgstr ""
+
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance for this project"
+msgstr ""
+
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Share code with others outside the project."
+msgstr ""
+
+msgid "ProjectSettings|Show default award emojis"
+msgstr ""
+
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|Skipped pipelines are considered successful"
+msgstr ""
+
+msgid "ProjectSettings|Snippets"
+msgstr ""
+
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
+msgid "ProjectSettings|Squash commits when merging"
+msgstr ""
+
+msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
+msgstr ""
+
+msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
+msgstr ""
+
+msgid "ProjectSettings|Submit changes to be merged upstream."
+msgstr ""
+
+msgid "ProjectSettings|Target project"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when applying merge request suggestions."
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits."
+msgstr ""
+
+msgid "ProjectSettings|The default target project for merge requests created in this fork project."
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
+msgstr ""
+
+msgid "ProjectSettings|This project"
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Transfer project"
+msgstr ""
+
+msgid "ProjectSettings|Upstream project"
+msgstr ""
+
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
+msgid "ProjectSettings|Users can copy the repository to a new project."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "ProjectSettings|Users can request access"
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project."
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
+msgstr ""
+
+msgid "ProjectSettings|View project analytics."
+msgstr ""
+
+msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
+msgstr ""
+
+msgid "ProjectSettings|Visualize the project's performance metrics."
+msgstr ""
+
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
+msgid "ProjectSettings|What are badges?"
+msgstr ""
+
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
+
+msgid "ProjectSettings|Wiki"
+msgstr ""
+
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|GitLab Cluster Management"
+msgstr ""
+
+msgid "ProjectTemplates|Gitpod/Spring Petclinic"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|HIPAA Audit Protocol"
+msgstr ""
+
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Gatsby"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|SalesforceDX"
+msgstr ""
+
+msgid "ProjectTemplates|Sample GitLab Project"
+msgstr ""
+
+msgid "ProjectTemplates|Serverless Framework/JS"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|Static Site Editor/Middleman"
+msgstr ""
+
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
+msgid "ProjectView|Activity"
+msgstr ""
+
+msgid "ProjectView|Files and Readme (default)"
+msgstr ""
+
+msgid "ProjectView|Readme"
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects (%{count})"
+msgstr ""
+
+msgid "Projects Successfully Retrieved"
+msgstr ""
+
+msgid "Projects are graded based on the highest severity vulnerability present"
+msgstr ""
+
+msgid "Projects are organized into groups"
+msgstr ""
+
+msgid "Projects contributed to"
+msgstr ""
+
+msgid "Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more."
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that can be accessed"
+msgstr ""
+
+msgid "Projects to index"
+msgstr ""
+
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
+msgstr ""
+
+msgid "Projects will be permanently deleted immediately."
+msgstr ""
+
+msgid "Projects with critical vulnerabilities"
+msgstr ""
+
+msgid "Projects with high or unknown vulnerabilities"
+msgstr ""
+
+msgid "Projects with low vulnerabilities"
+msgstr ""
+
+msgid "Projects with medium vulnerabilities"
+msgstr ""
+
+msgid "Projects with no vulnerabilities and security scanning enabled"
+msgstr ""
+
+msgid "Projects with this topic"
+msgstr ""
+
+msgid "Projects with write access"
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+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|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
+msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
+msgstr ""
+
+msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
+msgstr ""
+
+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 from template"
+msgstr ""
+
+msgid "ProjectsNew|Create new project"
+msgstr ""
+
+msgid "ProjectsNew|Description format"
+msgstr ""
+
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "ProjectsNew|Import"
+msgstr ""
+
+msgid "ProjectsNew|Import project"
+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|Project Configuration"
+msgstr ""
+
+msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
+msgstr ""
+
+msgid "ProjectsNew|Run CI/CD for external repository"
+msgstr ""
+
+msgid "ProjectsNew|Visibility Level"
+msgstr ""
+
+msgid "ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
+msgstr ""
+
+msgid "Prometheus"
+msgstr ""
+
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
+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 ""
+
+msgid "PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope \"*\" OR a manually configured Prometheus to be available."
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|Monitor application health with Prometheus metrics and dashboards"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
+msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
+msgstr ""
+
+msgid "PrometheusService|Prometheus cluster integration"
+msgstr ""
+
+msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
+msgstr ""
+
+msgid "PrometheusService|The ID of the IAP-secured resource."
+msgstr ""
+
+msgid "PrometheusService|The Prometheus API base URL."
+msgstr ""
+
+msgid "PrometheusService|The contents of the credentials.json file of your service account."
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+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"
+msgstr ""
+
+msgid "PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page have been deprecated."
+msgstr ""
+
+msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
+msgstr ""
+
+msgid "PrometheusService|https://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote issue to an epic"
+msgstr ""
+
+msgid "Promote issue to incident"
+msgstr ""
+
+msgid "Promote to epic"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
+msgid "Promoted issue to an epic."
+msgstr ""
+
+msgid "Promotes issue to incident"
+msgstr ""
+
+msgid "Promotion is not supported."
+msgstr ""
+
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
+msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Better Protected Branches"
+msgstr ""
+
+msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
+msgstr ""
+
+msgid "Promotions|Buy EE"
+msgstr ""
+
+msgid "Promotions|Buy GitLab Enterprise Edition"
+msgstr ""
+
+msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact your Administrator to upgrade your license."
+msgstr ""
+
+msgid "Promotions|Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Promotions|Dismiss burndown charts promotion"
+msgstr ""
+
+msgid "Promotions|Dismiss repository features promotion"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Improve repositories with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Keep track of events in your project"
+msgstr ""
+
+msgid "Promotions|Learn more"
+msgstr ""
+
+msgid "Promotions|Merge request approvals"
+msgstr ""
+
+msgid "Promotions|Not now, thanks!"
+msgstr ""
+
+msgid "Promotions|Push Rules"
+msgstr ""
+
+msgid "Promotions|Push Rules are defined per project so you can have different rules applied to different projects depends on your needs."
+msgstr ""
+
+msgid "Promotions|Repository Mirroring"
+msgstr ""
+
+msgid "Promotions|Repository Mirroring is a way to mirror repositories from external sources. It can be used to mirror all branches, tags, and commits that you have in your repository."
+msgstr ""
+
+msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
+msgstr ""
+
+msgid "Promotions|Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
+msgid "Promotions|Start GitLab Ultimate trial"
+msgstr ""
+
+msgid "Promotions|The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Try it for free"
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Advanced Search."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Audit Events."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve merge requests."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve repositories."
+msgstr ""
+
+msgid "Promotions|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 "Promotions|Weight"
+msgstr ""
+
+msgid "Promotions|Weighting your issue"
+msgstr ""
+
+msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them."
+msgstr ""
+
+msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
+msgstr ""
+
+msgid "Promotions|description templates"
+msgstr ""
+
+msgid "Promotions|to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "Prompt users to upload SSH keys"
+msgstr ""
+
+msgid "Protect"
+msgstr ""
+
+msgid "Protect a tag"
+msgstr ""
+
+msgid "Protect variable"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Branches"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
+msgid "Protected Paths: requests"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
+msgid "Protected Tags"
+msgstr ""
+
+msgid "Protected branches"
+msgstr ""
+
+msgid "Protected environments"
+msgstr ""
+
+msgid "Protected paths"
+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 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|Allowed to force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to force push:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push:"
+msgstr ""
+
+msgid "ProtectedBranch|Branch"
+msgstr ""
+
+msgid "ProtectedBranch|Branch will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
+msgid "ProtectedBranch|By default, protected branches restrict who can modify the branch."
+msgstr ""
+
+msgid "ProtectedBranch|Code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
+msgstr ""
+
+msgid "ProtectedBranch|Keep stable branches secure and force developers to use merge requests."
+msgstr ""
+
+msgid "ProtectedBranch|Learn more."
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branches"
+msgstr ""
+
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
+
+msgid "ProtectedBranch|Require approval from code owners:"
+msgstr ""
+
+msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
+msgstr ""
+
+msgid "ProtectedBranch|Toggle allowed to force push"
+msgstr ""
+
+msgid "ProtectedBranch|Toggle code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Unprotect"
+msgstr ""
+
+msgid "ProtectedBranch|What are protected branches?"
+msgstr ""
+
+msgid "ProtectedBranch|default"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "ProtectedTags|default"
+msgstr ""
+
+msgid "ProtectedTag|By default, protected branches restrict who can modify the tag."
+msgstr ""
+
+msgid "ProtectedTag|Learn more."
+msgstr ""
+
+msgid "ProtectedTag|Limit access to creating and updating tags."
+msgstr ""
+
+msgid "ProtectedTag|Protected tags"
+msgstr ""
+
+msgid "ProtectedTag|What are protected tags?"
+msgstr ""
+
+msgid "ProtectedTag|default"
+msgstr ""
+
+msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Provision instructions"
+msgstr ""
+
+msgid "Provisioned by:"
+msgstr ""
+
+msgid "Proxy support for this API is not available currently"
+msgstr ""
+
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public Access Help"
+msgstr ""
+
+msgid "Public deploy keys"
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Public projects Minutes cost factor"
+msgstr ""
+
+msgid "Publish to status page"
+msgstr ""
+
+msgid "Published"
+msgstr ""
+
+msgid "Published on status page"
+msgstr ""
+
+msgid "Publishes this issue to the associated status page."
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Pull requests from fork are not supported"
+msgstr ""
+
+msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
+msgstr ""
+
+msgid "Purchase more minutes"
+msgstr ""
+
+msgid "Purchase more storage"
+msgstr ""
+
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rule updated successfully."
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push Rules updated successfully."
+msgstr ""
+
+msgid "Push an existing Git repository"
+msgstr ""
+
+msgid "Push an existing folder"
+msgstr ""
+
+msgid "Push commits to the source branch or add previously merged commits to review them."
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push the result of the merge to GitLab"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRules|All branch names must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any branch name is allowed."
+msgstr ""
+
+msgid "PushRules|All commit author's email must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any email is allowed."
+msgstr ""
+
+msgid "PushRules|All commit messages must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not required to match any expression."
+msgstr ""
+
+msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
+msgstr ""
+
+msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
+msgstr ""
+
+msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
+msgstr ""
+
+msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
+msgstr ""
+
+msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
+msgstr ""
+
+msgid "PushRules|Restrict commits to existing GitLab users."
+msgstr ""
+
+msgid "PushRules|Restrict push operations for this project."
+msgstr ""
+
+msgid "PushRules|Save push rules"
+msgstr ""
+
+msgid "PushRules|Select push rules"
+msgstr ""
+
+msgid "PushRules|Users can still delete tags through the GitLab UI."
+msgstr ""
+
+msgid "PushRule|Push rules"
+msgstr ""
+
+msgid "PushRule|Reject unverified users"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|Enter your application key."
+msgstr ""
+
+msgid "PushoverService|Enter your user key."
+msgstr ""
+
+msgid "PushoverService|Get real-time notifications on your device."
+msgstr ""
+
+msgid "PushoverService|High priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices."
+msgstr ""
+
+msgid "PushoverService|Low priority"
+msgstr ""
+
+msgid "PushoverService|Lowest priority"
+msgstr ""
+
+msgid "PushoverService|Normal priority"
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "QualitySummary|Project quality"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query cannot be processed"
+msgstr ""
+
+msgid "Queued"
+msgstr ""
+
+msgid "Quick actions can be used in description and comment boxes."
+msgstr ""
+
+msgid "Quick help"
+msgstr ""
+
+msgid "Quick range"
+msgstr ""
+
+msgid "Quickly and easily edit multiple files in your project."
+msgstr ""
+
+msgid "Quota of CI/CD minutes"
+msgstr ""
+
+msgid "Quota of CI/CD minutes:"
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Rails"
+msgstr ""
+
+msgid "Rake Tasks Help"
+msgstr ""
+
+msgid "Random"
+msgstr ""
+
+msgid "Rate Limits"
+msgstr ""
+
+msgid "Rate limit"
+msgstr ""
+
+msgid "Rate limit access to specified paths."
+msgstr ""
+
+msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
+msgstr ""
+
+msgid "Raw blob request rate limit per minute"
+msgstr ""
+
+msgid "Raw blob requests"
+msgstr ""
+
+msgid "Re-authentication period expired or never requested. Please try again"
+msgstr ""
+
+msgid "Re-authentication required"
+msgstr ""
+
+msgid "Re-import"
+msgstr ""
+
+msgid "Re-request review"
+msgstr ""
+
+msgid "Re-verification interval"
+msgstr ""
+
+msgid "Read documentation"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about GitLab at %{link_to_promo}."
+msgstr ""
+
+msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Read their documentation."
+msgstr ""
+
+msgid "Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
+msgstr ""
+
+msgid "Ready to merge by members who can write to the target branch."
+msgstr ""
+
+msgid "Ready to merge!"
+msgstr ""
+
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
+msgid "Rebase"
+msgstr ""
+
+msgid "Rebase in progress"
+msgstr ""
+
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
+msgid "Recaptcha verified?"
+msgstr ""
+
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Receive any notifications from GitLab."
+msgstr ""
+
+msgid "Receive notification of abuse reports by email."
+msgstr ""
+
+msgid "Receive notifications about your own activity"
+msgstr ""
+
+msgid "Receive product marketing emails"
+msgstr ""
+
+msgid "Recent"
+msgstr ""
+
+msgid "Recent Project Activity"
+msgstr ""
+
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
+msgid "Recent events"
+msgstr ""
+
+msgid "Recent jobs served by this runner"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Recently used"
+msgstr ""
+
+msgid "Reconfigure"
+msgstr ""
+
+msgid "Recovering projects"
+msgstr ""
+
+msgid "Recovery Codes"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Redirecting"
+msgstr ""
+
+msgid "Redis"
+msgstr ""
+
+msgid "Reduce incident management alert volume (for example, if too many issues are being created)."
+msgstr ""
+
+msgid "Reduce project visibility"
+msgstr ""
+
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
+msgid "Reduce this project’s visibility?"
+msgstr ""
+
+msgid "Reference"
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid "Refine your search criteria (select a %{strong_open}group%{strong_close} and %{strong_open}project%{strong_close} when possible)"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refresh the page and try again."
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate export"
+msgstr ""
+
+msgid "Regenerate instance ID"
+msgstr ""
+
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
+msgid "Register WebAuthn Device"
+msgstr ""
+
+msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
+msgstr ""
+
+msgid "Register device"
+msgstr ""
+
+msgid "Register now"
+msgstr ""
+
+msgid "Register the runner with this URL:"
+msgstr ""
+
+msgid "Register with two-factor app"
+msgstr ""
+
+msgid "Registration Features include:"
+msgstr ""
+
+msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
+msgstr ""
+
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
+msgstr ""
+
+msgid "RegistrationFeatures|Registration Features Program"
+msgstr ""
+
+msgid "RegistrationFeatures|Want to %{feature_title} for free?"
+msgstr ""
+
+msgid "RegistrationFeatures|send emails to users"
+msgstr ""
+
+msgid "RegistrationFeatures|use this feature"
+msgstr ""
+
+msgid "RegistrationVerification|Are you sure you want to skip this step?"
+msgstr ""
+
+msgid "RegistrationVerification|Enable free CI/CD minutes"
+msgstr ""
+
+msgid "RegistrationVerification|GitLab will not charge your card, it will only be used for validation."
+msgstr ""
+
+msgid "RegistrationVerification|Pipelines using shared GitLab runners will fail until you validate your account."
+msgstr ""
+
+msgid "RegistrationVerification|Skip this for now"
+msgstr ""
+
+msgid "RegistrationVerification|To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method, such as a debit or credit card. Until then, you can't use free CI/CD minutes to build your application."
+msgstr ""
+
+msgid "RegistrationVerification|Validate account"
+msgstr ""
+
+msgid "RegistrationVerification|Verify your identity"
+msgstr ""
+
+msgid "RegistrationVerification|Yes, I'd like to skip"
+msgstr ""
+
+msgid "RegistrationVerification|You can alway verify your account at a later time."
+msgstr ""
+
+msgid "Registration|Checkout"
+msgstr ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
+msgstr ""
+
+msgid "Rejected (closed)"
+msgstr ""
+
+msgid "Related feature flags"
+msgstr ""
+
+msgid "Related issues"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Related to #%{issue_id}."
+msgstr ""
+
+msgid "Relates to"
+msgstr ""
+
+msgid "Release"
+msgid_plural "Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Release assets"
+msgstr ""
+
+msgid "Release assets documentation"
+msgstr ""
+
+msgid "Release does not have the same project as the milestone"
+msgstr ""
+
+msgid "Release notes"
+msgstr ""
+
+msgid "Release notes:"
+msgstr ""
+
+msgid "Release title"
+msgstr ""
+
+msgid "Release with tag \"%{tag}\" was not found"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Image"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Images"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Other"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Package"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Packages"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbook"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbooks"
+msgstr ""
+
+msgid "Released date"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
+msgstr ""
+
+msgid "Releases documentation"
+msgstr ""
+
+msgid "Releases|New Release"
+msgstr ""
+
+msgid "Release|Something went wrong while creating a new release."
+msgstr ""
+
+msgid "Release|Something went wrong while getting the release details."
+msgstr ""
+
+msgid "Release|Something went wrong while saving the release details."
+msgstr ""
+
+msgid "Reload page"
+msgstr ""
+
+msgid "Remediations"
+msgstr ""
+
+msgid "Remember me"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remote object has no absolute path."
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove %{displayReference}"
+msgstr ""
+
+msgid "Remove Zoom meeting"
+msgstr ""
+
+msgid "Remove Zoom meeting."
+msgstr ""
+
+msgid "Remove access"
+msgstr ""
+
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr ""
+
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove approvers"
+msgstr ""
+
+msgid "Remove approvers?"
+msgstr ""
+
+msgid "Remove asset link"
+msgstr ""
+
+msgid "Remove assignee"
+msgstr ""
+
+msgid "Remove attention request"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove card"
+msgstr ""
+
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
+msgid "Remove deploy key"
+msgstr ""
+
+msgid "Remove description history"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
+msgid "Remove favicon"
+msgstr ""
+
+msgid "Remove file"
+msgstr ""
+
+msgid "Remove fork relationship"
+msgstr ""
+
+msgid "Remove from batch"
+msgstr ""
+
+msgid "Remove from epic"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove header logo"
+msgstr ""
+
+msgid "Remove iteration"
+msgstr ""
+
+msgid "Remove license"
+msgstr ""
+
+msgid "Remove limit"
+msgstr ""
+
+msgid "Remove link"
+msgstr ""
+
+msgid "Remove list"
+msgstr ""
+
+msgid "Remove log"
+msgstr ""
+
+msgid "Remove logo"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove report"
+msgstr ""
+
+msgid "Remove reviewer"
+msgstr ""
+
+msgid "Remove runner"
+msgstr ""
+
+msgid "Remove secondary email"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Remove user"
+msgstr ""
+
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+msgstr ""
+
+msgid "Remove user from project"
+msgstr ""
+
+msgid "Remove..."
+msgstr ""
+
+msgid "Removed"
+msgstr ""
+
+msgid "Removed %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removed %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removed %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removed %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removed %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removed all labels."
+msgstr ""
+
+msgid "Removed an issue from an epic."
+msgstr ""
+
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removed parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removed spent time."
+msgstr ""
+
+msgid "Removed the due date."
+msgstr ""
+
+msgid "Removed time estimate."
+msgstr ""
+
+msgid "Removed upload with id %{id}"
+msgstr ""
+
+msgid "RemovedProjects|No projects pending deletion found"
+msgstr ""
+
+msgid "RemovedProjects|Projects that are pending deletion that you have access to are listed here."
+msgstr ""
+
+msgid "Removes %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removes %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes an issue from an epic."
+msgstr ""
+
+msgid "Removes parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
+msgid "Removing this group also removes all child projects, including archived projects, and their resources."
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Rename/Move"
+msgstr ""
+
+msgid "Render diagrams in your documents using PlantUML."
+msgstr ""
+
+msgid "Renew subscription"
+msgstr ""
+
+msgid "Renews"
+msgstr ""
+
+msgid "Reopen"
+msgstr ""
+
+msgid "Reopen %{issueType}"
+msgstr ""
+
+msgid "Reopen %{noteable}"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reopen test case"
+msgstr ""
+
+msgid "Reopen this %{quick_action_target}"
+msgstr ""
+
+msgid "Reopened this %{quick_action_target}."
+msgstr ""
+
+msgid "Reopens this %{quick_action_target}."
+msgstr ""
+
+msgid "Repeats"
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace %{blob_name}"
+msgstr ""
+
+msgid "Replace %{name}"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replace file"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Reply by email"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Reply…"
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report %{display_issuable_type} that are abusive, inappropriate or spam."
+msgstr ""
+
+msgid "Report abuse"
+msgstr ""
+
+msgid "Report abuse to admin"
+msgstr ""
+
+msgid "Reported %{timeAgo} by %{reportedBy}"
+msgstr ""
+
+msgid "Reported by"
+msgstr ""
+
+msgid "Reported by %{reporter}"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{combinedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
+msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected no issues for the source branch only"
+msgstr ""
+
+msgid "Reports|Accessibility scanning failed loading results"
+msgstr ""
+
+msgid "Reports|Accessibility scanning results are being parsed"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Activity"
+msgstr ""
+
+msgid "Reports|An error occurred while loading %{name} results"
+msgstr ""
+
+msgid "Reports|An error occurred while loading report"
+msgstr ""
+
+msgid "Reports|Base report parsing error:"
+msgstr ""
+
+msgid "Reports|Classname"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failed %{count} time in %{baseBranch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{baseBranch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failed %{count} time in %{base_branch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{base_branch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
+msgid "Reports|Identifier"
+msgstr ""
+
+msgid "Reports|Metrics reports are loading"
+msgstr ""
+
+msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
+msgstr ""
+
+msgid "Reports|Metrics reports did not change"
+msgstr ""
+
+msgid "Reports|Metrics reports failed loading results"
+msgstr ""
+
+msgid "Reports|Scanner"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Tool"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|Vulnerability Name"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repositories"
+msgstr ""
+
+msgid "Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average Coverage by Job"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average test coverage last 30 days"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Jobs with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|No test coverage to display"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Projects with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Test Code Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|There was an error fetching the projects."
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Analytics"
+msgstr ""
+
+msgid "Repository Graph"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository already read-only"
+msgstr ""
+
+msgid "Repository check"
+msgstr ""
+
+msgid "Repository check was triggered."
+msgstr ""
+
+msgid "Repository checks"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository clone URL"
+msgstr ""
+
+msgid "Repository files count over the limit"
+msgstr ""
+
+msgid "Repository has an invalid default branch name."
+msgstr ""
+
+msgid "Repository has more than one branch."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository has tags."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirroring"
+msgstr ""
+
+msgid "Repository mirroring configuration"
+msgstr ""
+
+msgid "Repository must contain at least 1 file."
+msgstr ""
+
+msgid "Repository size is above the limit."
+msgstr ""
+
+msgid "Repository size limit (MB)"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "Repository synchronization concurrency limit"
+msgstr ""
+
+msgid "Repository update events"
+msgstr ""
+
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Request a new one"
+msgstr ""
+
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
+msgid "Request details"
+msgstr ""
+
+msgid "Request parameter %{param} is missing."
+msgstr ""
+
+msgid "Request review from"
+msgstr ""
+
+msgid "Request time"
+msgstr ""
+
+msgid "Request to link SAML account must be authorized"
+msgstr ""
+
+msgid "Requested"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requested attention from @%{username}"
+msgstr ""
+
+msgid "Requested design version does not exist."
+msgstr ""
+
+msgid "Requested review"
+msgstr ""
+
+msgid "Requested states are invalid"
+msgstr ""
+
+msgid "Requests"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}"
+msgstr ""
+
+msgid "Requests per period"
+msgstr ""
+
+msgid "Require additional authentication for administrative tasks."
+msgstr ""
+
+msgid "Require all users in this group to set up two-factor authentication"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given)"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given, you've approved)"
+msgstr ""
+
+msgid "Required in this project."
+msgstr ""
+
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
+msgid "Requirement"
+msgstr ""
+
+msgid "Requirement %{reference} has been added"
+msgstr ""
+
+msgid "Requirement %{reference} has been archived"
+msgstr ""
+
+msgid "Requirement %{reference} has been reopened"
+msgstr ""
+
+msgid "Requirement %{reference} has been updated"
+msgstr ""
+
+msgid "Requirement title cannot have more than %{limit} characters."
+msgstr ""
+
+msgid "Requirements"
+msgstr ""
+
+msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
+msgstr ""
+
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires values to meet regular expression requirements."
+msgstr ""
+
+msgid "Requires you to deploy or set up cloud-hosted Sentry."
+msgstr ""
+
+msgid "Requires your primary GitLab email address."
+msgstr ""
+
+msgid "Resend"
+msgstr ""
+
+msgid "Resend Request"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Resend it"
+msgstr ""
+
+msgid "Resend unlock instructions"
+msgstr ""
+
+msgid "Reset"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset file"
+msgstr ""
+
+msgid "Reset filters"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset link will be generated and sent to the user. %{break} User will be forced to set the password on first sign in."
+msgstr ""
+
+msgid "Reset password"
+msgstr ""
+
+msgid "Reset registration token"
+msgstr ""
+
+msgid "Reset template"
+msgstr ""
+
+msgid "Reset to project defaults"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve"
+msgstr ""
+
+msgid "Resolve conflicts"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
+msgid "Resolve thread"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Resolved 1 discussion."
+msgstr ""
+
+msgid "Resolved all discussions."
+msgstr ""
+
+msgid "Resolved by"
+msgstr ""
+
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response didn't include `service_desk_address`"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Response text"
+msgstr ""
+
+msgid "Restart GitLab to apply changes."
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Restore"
+msgstr ""
+
+msgid "Restore group"
+msgstr ""
+
+msgid "Restore project"
+msgstr ""
+
+msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
+msgstr ""
+
+msgid "Restoring the project will prevent the project from being removed on this date and restore people's ability to make changes to it."
+msgstr ""
+
+msgid "Restrict group access by IP address. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Restrict membership by email domain"
+msgstr ""
+
+msgid "Restrict projects for this runner"
+msgstr ""
+
+msgid "Restricted shift times are not available for hourly shifts"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Resync"
+msgstr ""
+
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry job"
+msgstr ""
+
+msgid "Retry migration"
+msgstr ""
+
+msgid "Retry the downstream pipeline"
+msgstr ""
+
+msgid "Retry the trigger job"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry this job in order to create the necessary resources."
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review App|View app"
+msgstr ""
+
+msgid "Review App|View latest app"
+msgstr ""
+
+msgid "Review changes"
+msgstr ""
+
+msgid "Review requested from %{name}"
+msgstr ""
+
+msgid "Review requests for you"
+msgstr ""
+
+msgid "Review the changes locally"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
+msgid "Review time"
+msgstr ""
+
+msgid "Review time is defined as the time it takes from first comment until merged."
+msgstr ""
+
+msgid "ReviewApp|Enable Review App"
+msgstr ""
+
+msgid "Reviewer"
+msgid_plural "%d Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reviewer(s)"
+msgstr ""
+
+msgid "Reviewers"
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoked"
+msgstr ""
+
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
+msgid "Revoked impersonation token %{token_name}!"
+msgstr ""
+
+msgid "Revoked personal access token %{personal_access_token_name}!"
+msgstr ""
+
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
+msgstr ""
+
+msgid "RightSidebar|adding a"
+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 ""
+
+msgid "Roadmap settings"
+msgstr ""
+
+msgid "Role"
+msgstr ""
+
+msgid "Rollback"
+msgstr ""
+
+msgid "Ruby"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
+msgstr ""
+
+msgid "Run %{code_start}git fsck%{code_end} periodically in all project and wiki repositories to look for silent disk corruption issues."
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}"
+msgstr ""
+
+msgid "Run CI/CD pipelines with Jenkins."
+msgstr ""
+
+msgid "Run housekeeping"
+msgstr ""
+
+msgid "Run manual or delayed jobs"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner API"
+msgstr ""
+
+msgid "Runner tokens"
+msgstr ""
+
+msgid "Runner was not deleted because it is assigned to multiple projects."
+msgstr ""
+
+msgid "Runner was not updated."
+msgstr ""
+
+msgid "Runner was successfully updated."
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|Active"
+msgstr ""
+
+msgid "Runners|All"
+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|Assigned Group"
+msgstr ""
+
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Change to project runner"
+msgstr ""
+
+msgid "Runners|Command to register runner"
+msgstr ""
+
+msgid "Runners|Configuration"
+msgstr ""
+
+msgid "Runners|Copy instructions"
+msgstr ""
+
+msgid "Runners|Copy registration token"
+msgstr ""
+
+msgid "Runners|Delete runner"
+msgstr ""
+
+msgid "Runners|Delete runner %{name}?"
+msgstr ""
+
+msgid "Runners|Deploy GitLab Runner in AWS"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Details"
+msgstr ""
+
+msgid "Runners|Download and install binary"
+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|Group"
+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 ""
+
+msgid "Runners|Instance"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Members of the %{type} can register runners"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Never contacted"
+msgstr ""
+
+msgid "Runners|New registration token generated!"
+msgstr ""
+
+msgid "Runners|New runner, has not contacted yet"
+msgstr ""
+
+msgid "Runners|No contact from this runner in over 3 months"
+msgstr ""
+
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Offline runners"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Online runners"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Project"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
+msgid "Runners|Reset token"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Runner"
+msgstr ""
+
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
+msgid "Runners|Runner %{name} was deleted"
+msgstr ""
+
+msgid "Runners|Runner ID"
+msgstr ""
+
+msgid "Runners|Runner assigned to project."
+msgstr ""
+
+msgid "Runners|Runner is offline, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
+msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner registration"
+msgstr ""
+
+msgid "Runners|Runner unassigned from project."
+msgstr ""
+
+msgid "Runners|Runners"
+msgstr ""
+
+msgid "Runners|Runs untagged jobs"
+msgstr ""
+
+msgid "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."
+msgstr ""
+
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
+msgid "Runners|Show runner installation instructions"
+msgstr ""
+
+msgid "Runners|Something went wrong while fetching runner data."
+msgstr ""
+
+msgid "Runners|Something went wrong while fetching the tags suggestions"
+msgstr ""
+
+msgid "Runners|Stale"
+msgstr ""
+
+msgid "Runners|Stale runners"
+msgstr ""
+
+msgid "Runners|Status"
+msgstr ""
+
+msgid "Runners|Stop the runner from accepting new jobs."
+msgstr ""
+
+msgid "Runners|Tags"
+msgstr ""
+
+msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Runners|This runner has never contacted this instance"
+msgstr ""
+
+msgid "Runners|This runner is associated with specific projects."
+msgstr ""
+
+msgid "Runners|This runner is available to all groups and projects in your GitLab instance."
+msgstr ""
+
+msgid "Runners|This runner is available to all projects and subgroups in a group."
+msgstr ""
+
+msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
+msgstr ""
+
+msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
+msgstr ""
+
+msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
+msgstr ""
+
+msgid "Runners|Use the runner for jobs without tags, in addition to tagged jobs."
+msgstr ""
+
+msgid "Runners|Use the runner for the currently assigned projects only."
+msgstr ""
+
+msgid "Runners|Use the runner on pipelines for protected branches only."
+msgstr ""
+
+msgid "Runners|Value"
+msgstr ""
+
+msgid "Runners|Version"
+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 are about to change this instance runner to a project runner. This operation is not reversible. Are you sure you want to continue?"
+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 ""
+
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
+msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Runners|active"
+msgstr ""
+
+msgid "Runners|group"
+msgstr ""
+
+msgid "Runners|locked"
+msgstr ""
+
+msgid "Runners|never contacted"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
+msgstr ""
+
+msgid "Runners|shared"
+msgstr ""
+
+msgid "Runners|specific"
+msgstr ""
+
+msgid "Runners|stale"
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
+msgstr ""
+
+msgid "SAML"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML discovery tokens"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SAST Configuration"
+msgstr ""
+
+msgid "SHA256"
+msgstr ""
+
+msgid "SSH Key"
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH Keys Help"
+msgstr ""
+
+msgid "SSH host key fingerprints"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
+msgstr ""
+
+msgid "SSH key"
+msgstr ""
+
+msgid "SSH keys"
+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 ""
+
+msgid "SSL Verification:"
+msgstr ""
+
+msgid "SSL verification"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save %{name} size limits"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save deploy freeze"
+msgstr ""
+
+msgid "Save password"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "Scanner"
+msgstr ""
+
+msgid "Scanner profile failed to delete"
+msgstr ""
+
+msgid "Scanner profile not found for given parameters"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Schedule-based escalation rules must have a schedule in the same project as the policy"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+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 ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Schedules to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scope board to current iteration"
+msgstr ""
+
+msgid "Scopes"
+msgstr ""
+
+msgid "Scopes (select at least one)"
+msgstr ""
+
+msgid "Scopes can't be blank"
+msgstr ""
+
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
+msgid "Scroll down"
+msgstr ""
+
+msgid "Scroll left"
+msgstr ""
+
+msgid "Scroll right"
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Scroll up"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search GitLab"
+msgstr ""
+
+msgid "Search a group"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search assignees"
+msgstr ""
+
+msgid "Search authors"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search branches, tags, and commits"
+msgstr ""
+
+msgid "Search by Git revision"
+msgstr ""
+
+msgid "Search by author"
+msgstr ""
+
+msgid "Search by commit title or SHA"
+msgstr ""
+
+msgid "Search by message"
+msgstr ""
+
+msgid "Search by name"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for Namespace"
+msgstr ""
+
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search for this text"
+msgstr ""
+
+msgid "Search forks"
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search iterations"
+msgstr ""
+
+msgid "Search labels"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or create tag"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search projects..."
+msgstr ""
+
+msgid "Search refs"
+msgstr ""
+
+msgid "Search requirements"
+msgstr ""
+
+msgid "Search settings"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search users or groups"
+msgstr ""
+
+msgid "Search your project dependencies for their licenses and apply policies."
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in group %{groupName}"
+msgstr ""
+
+msgid "SearchAutocomplete|in project %{projectName}"
+msgstr ""
+
+msgid "SearchCodeResults|of %{link_to_project}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for %{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|code result"
+msgid_plural "SearchResults|code results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|comment"
+msgid_plural "SearchResults|comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|commit"
+msgid_plural "SearchResults|commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|epic"
+msgid_plural "SearchResults|epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|issue"
+msgid_plural "SearchResults|issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|merge request"
+msgid_plural "SearchResults|merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|milestone"
+msgid_plural "SearchResults|milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|project"
+msgid_plural "SearchResults|projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|snippet"
+msgid_plural "SearchResults|snippets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|user"
+msgid_plural "SearchResults|users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|wiki result"
+msgid_plural "SearchResults|wiki results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Searching by both author and message is currently not supported."
+msgstr ""
+
+msgid "Seats"
+msgstr ""
+
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
+msgstr ""
+
+msgid "Seats usage data is updated every day at 12:00pm UTC"
+msgstr ""
+
+msgid "Secondary"
+msgstr ""
+
+msgid "Secondary email:"
+msgstr ""
+
+msgid "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "Secret access key"
+msgstr ""
+
+msgid "Secret token"
+msgstr ""
+
+msgid "Secure token that identifies an external storage request."
+msgstr ""
+
+msgid "SecureCodeWarrior"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security & Compliance"
+msgstr ""
+
+msgid "Security Configuration"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "Security navigation"
+msgstr ""
+
+msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
+msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
+msgstr ""
+
+msgid "SecurityApprovals|A merge request approval is required when test coverage declines."
+msgstr ""
+
+msgid "SecurityApprovals|A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
+
+msgid "SecurityApprovals|Coverage-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Learn more about Coverage-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Learn more about License-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Learn more about Vulnerability-Check"
+msgstr ""
+
+msgid "SecurityApprovals|License-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilities. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Vulnerability-Check"
+msgstr ""
+
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
+msgid "SecurityConfiguration|%{scanType} configuration code snippet"
+msgstr ""
+
+msgid "SecurityConfiguration|An error occurred while creating the merge request."
+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|Configuration history"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure %{feature}"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure with a 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 ""
+
+msgid "SecurityConfiguration|Create merge request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST 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 %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable Auto DevOps"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups"
+msgstr ""
+
+msgid "SecurityConfiguration|Immediately begin risk analysis and remediation with application security features. Start with SAST and Secret Detection, available to all plans. Upgrade to Ultimate to get all features, including:"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage corpus"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage corpus files used as mutation sources in coverage fuzzing."
+msgstr ""
+
+msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
+msgstr ""
+
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
+msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Not enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
+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"
+msgstr ""
+
+msgid "SecurityConfiguration|Security testing"
+msgstr ""
+
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
+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|Vulnerability Management"
+msgstr ""
+
+msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
+msgstr ""
+
+msgid "SecurityOrchestration| or "
+msgstr ""
+
+msgid "SecurityOrchestration|%{branches} %{plural}"
+msgstr ""
+
+msgid "SecurityOrchestration|%{branches} and %{lastBranch} %{plural}"
+msgstr ""
+
+msgid "SecurityOrchestration|.yaml preview"
+msgstr ""
+
+msgid "SecurityOrchestration|Action"
+msgstr ""
+
+msgid "SecurityOrchestration|Actions"
+msgstr ""
+
+msgid "SecurityOrchestration|Add rule"
+msgstr ""
+
+msgid "SecurityOrchestration|All policies"
+msgstr ""
+
+msgid "SecurityOrchestration|An error occurred assigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
+msgid "SecurityOrchestration|Description"
+msgstr ""
+
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Enabled"
+msgstr ""
+
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityOrchestration|Executes a %{scanType} scan"
+msgstr ""
+
+msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
+msgid "SecurityOrchestration|Latest scan"
+msgstr ""
+
+msgid "SecurityOrchestration|Network"
+msgstr ""
+
+msgid "SecurityOrchestration|New policy"
+msgstr ""
+
+msgid "SecurityOrchestration|No rules defined - policy will not run."
+msgstr ""
+
+msgid "SecurityOrchestration|Only owners can update Security Policy Project"
+msgstr ""
+
+msgid "SecurityOrchestration|Policies"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy description"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy editor"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy status"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy summary"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy type"
+msgstr ""
+
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
+msgid "SecurityOrchestration|Rule"
+msgstr ""
+
+msgid "SecurityOrchestration|Rules"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan Execution"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan execution"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project was linked successfully"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
+msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityOrchestration|Select security project"
+msgstr ""
+
+msgid "SecurityOrchestration|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
+msgid "SecurityOrchestration|There was a problem creating the new security policy"
+msgstr ""
+
+msgid "SecurityOrchestration|This project does not contain any security policies."
+msgstr ""
+
+msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
+msgstr ""
+
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|view results"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
+msgid "SecurityPolicies|+%{count} more"
+msgstr ""
+
+msgid "SecurityPolicies|Environment(s)"
+msgstr ""
+
+msgid "SecurityPolicies|Policy type"
+msgstr ""
+
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
+
+msgid "SecurityReports|Add projects"
+msgstr ""
+
+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."
+msgstr ""
+
+msgid "SecurityReports|At GitLab, we're all about iteration and feedback. That's why we are reaching out to customers like you to help guide what we work on this year for Vulnerability Management. We have a lot of exciting ideas and ask that you assist us by taking a short survey %{boldStart}no longer than 10 minutes%{boldEnd} to evaluate a few of our potential features."
+msgstr ""
+
+msgid "SecurityReports|Change status"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
+msgid "SecurityReports|Create Jira issue"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Create policy"
+msgstr ""
+
+msgid "SecurityReports|Development vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Dismiss vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr ""
+
+msgid "SecurityReports|Download %{artifactName}"
+msgstr ""
+
+msgid "SecurityReports|Download results"
+msgstr ""
+
+msgid "SecurityReports|Download scanned URLs"
+msgstr ""
+
+msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
+msgstr ""
+
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
+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 ""
+
+msgid "SecurityReports|Hide dismissed"
+msgstr ""
+
+msgid "SecurityReports|Issue Created"
+msgstr ""
+
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
+msgid "SecurityReports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Maximum selected projects limit reached"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|No activity"
+msgstr ""
+
+msgid "SecurityReports|No longer detected"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found for this pipeline"
+msgstr ""
+
+msgid "SecurityReports|Oops, something doesn't seem right."
+msgstr ""
+
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Project"
+msgstr ""
+
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "SecurityReports|Projects added"
+msgstr ""
+
+msgid "SecurityReports|Remove project from dashboard"
+msgstr ""
+
+msgid "SecurityReports|Scan details"
+msgstr ""
+
+msgid "SecurityReports|Security Dashboard"
+msgstr ""
+
+msgid "SecurityReports|Security reports can only be accessed by authorized users."
+msgstr ""
+
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run"
+msgstr ""
+
+msgid "SecurityReports|Select a project to add by using the project search field above."
+msgstr ""
+
+msgid "SecurityReports|Set status"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Software and container dependency survey"
+msgstr ""
+
+msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|Take survey"
+msgstr ""
+
+msgid "SecurityReports|The Composition Analysis group is planning significant updates to how we make available the list of software and container dependency information in your projects. Therefore, we ask that you assist us by taking a short -no longer than 5 minute- survey to help align our direction with your needs."
+msgstr ""
+
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+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 ""
+
+msgid "SecurityReports|There was an error creating the issue."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the merge request."
+msgstr ""
+
+msgid "SecurityReports|There was an error deleting the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error while generating the report."
+msgstr ""
+
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
+msgid "SecurityReports|To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "SecurityReports|Tool"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjects}"
+msgstr ""
+
+msgid "SecurityReports|Undo dismiss"
+msgstr ""
+
+msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
+msgstr ""
+
+msgid "SecurityReports|Upgrade to manage vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Management feature survey"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Report"
+msgstr ""
+
+msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
+msgstr ""
+
+msgid "SecurityReports|With issues"
+msgstr ""
+
+msgid "SecurityReports|You do not have sufficient permissions to access this report"
+msgstr ""
+
+msgid "SecurityReports|You must sign in as an authorized user to see this report"
+msgstr ""
+
+msgid "SecurityReports|Your feedback is important to us! We will ask again in 7 days."
+msgstr ""
+
+msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
+msgstr ""
+
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See our website for help"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "See the list of available commands in Slack after setting up this service by entering"
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select Git revision"
+msgstr ""
+
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a branch"
+msgstr ""
+
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a label"
+msgstr ""
+
+msgid "Select a milestone"
+msgstr ""
+
+msgid "Select a new namespace"
+msgstr ""
+
+msgid "Select a project"
+msgstr ""
+
+msgid "Select a reason"
+msgstr ""
+
+msgid "Select a repository containing templates for common files."
+msgstr ""
+
+msgid "Select a role"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a template type"
+msgstr ""
+
+msgid "Select a time zone"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select all"
+msgstr ""
+
+msgid "Select an assignee"
+msgstr ""
+
+msgid "Select an iteration"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select assignee(s)"
+msgstr ""
+
+msgid "Select branch"
+msgstr ""
+
+msgid "Select due date"
+msgstr ""
+
+msgid "Select epic"
+msgstr ""
+
+msgid "Select file"
+msgstr ""
+
+msgid "Select group"
+msgstr ""
+
+msgid "Select group or project"
+msgstr ""
+
+msgid "Select groups to replicate"
+msgstr ""
+
+msgid "Select health status"
+msgstr ""
+
+msgid "Select iteration"
+msgstr ""
+
+msgid "Select label"
+msgstr ""
+
+msgid "Select labels"
+msgstr ""
+
+msgid "Select merge moment"
+msgstr ""
+
+msgid "Select milestone"
+msgstr ""
+
+msgid "Select private project"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select project to create %{type}"
+msgstr ""
+
+msgid "Select project to create issue"
+msgstr ""
+
+msgid "Select projects"
+msgstr ""
+
+msgid "Select reviewer(s)"
+msgstr ""
+
+msgid "Select shards to replicate"
+msgstr ""
+
+msgid "Select source"
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select start date"
+msgstr ""
+
+msgid "Select status"
+msgstr ""
+
+msgid "Select strategy activation method"
+msgstr ""
+
+msgid "Select subgroup"
+msgstr ""
+
+msgid "Select subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select timezone"
+msgstr ""
+
+msgid "Select type"
+msgstr ""
+
+msgid "Selected"
+msgstr ""
+
+msgid "Selected commits"
+msgstr ""
+
+msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
+msgstr ""
+
+msgid "Selected projects"
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Self monitoring"
+msgstr ""
+
+msgid "Self monitoring project does not exist"
+msgstr ""
+
+msgid "Self-monitoring project does not exist. Please check logs for any error messages"
+msgstr ""
+
+msgid "Self-monitoring project has been successfully deleted"
+msgstr ""
+
+msgid "Self-monitoring project was not deleted. Please check logs for any error messages"
+msgstr ""
+
+msgid "SelfMonitoring|Activate or deactivate instance self monitoring."
+msgstr ""
+
+msgid "SelfMonitoring|Activate self monitoring to create a project to use to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Deactivate self monitoring?"
+msgstr ""
+
+msgid "SelfMonitoring|Deactivating self monitoring deletes the self monitoring project. Are you sure you want to deactivate self monitoring and delete the project?"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring is active. Use the %{projectLinkStart}self monitoring project%{projectLinkEnd} to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project successfully created."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project successfully deleted."
+msgstr ""
+
+msgid "Send"
+msgstr ""
+
+msgid "Send a single email notification to Owners and Maintainers for new alerts."
+msgstr ""
+
+msgid "Send confirmation email"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send email in multipart format (HTML and plain text). Uncheck to send email messages in plain text only."
+msgstr ""
+
+msgid "Send email notification"
+msgstr ""
+
+msgid "Send emails to help guide new users through the onboarding process."
+msgstr ""
+
+msgid "Send emails to users upon account deactivation."
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Send notifications about project events to Mattermost channels."
+msgstr ""
+
+msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
+msgstr ""
+
+msgid "Send notifications about project events to a Discord channel. %{docs_link}"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send service data"
+msgstr ""
+
+msgid "Sentry"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sentry event"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "SeriesFinalConjunction|and"
+msgstr ""
+
+msgid "Serve repository static objects (for example, archives and blobs) from external storage."
+msgstr ""
+
+msgid "Server (optional)"
+msgstr ""
+
+msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "Serverless platform"
+msgstr ""
+
+msgid "ServerlessDetails|Configure cluster."
+msgstr ""
+
+msgid "ServerlessDetails|Function invocation metrics require the Prometheus cluster integration."
+msgstr ""
+
+msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Invocations"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|More information"
+msgstr ""
+
+msgid "ServerlessDetails|No pods loaded at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|Help shape the future of Serverless at GitLab"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+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|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|Sign up for First Look"
+msgstr ""
+
+msgid "Serverless|The deploy job has not finished."
+msgstr ""
+
+msgid "Serverless|The functions listed in the %{startTag}serverless.yml%{endTag} file don't match the namespace of your cluster."
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly."
+msgstr ""
+
+msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
+msgstr ""
+
+msgid "Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file."
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
+msgid "Service Usage Data"
+msgstr ""
+
+msgid "Service account generated successfully"
+msgstr ""
+
+msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
+msgstr ""
+
+msgid "Service usage data"
+msgstr ""
+
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
+msgid "ServicePing|Service ping is off"
+msgstr ""
+
+msgid "ServicePing|To view instance-level analytics, ask an admin to turn on %{docLinkStart}service ping%{docLinkEnd}."
+msgstr ""
+
+msgid "ServicePing|Turn on service ping"
+msgstr ""
+
+msgid "ServicePing|Turn on service ping to review instance-level analytics."
+msgstr ""
+
+msgid "Services"
+msgstr ""
+
+msgid "Session ID"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set access permissions for this token."
+msgstr ""
+
+msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set due date"
+msgstr ""
+
+msgid "Set health status"
+msgstr ""
+
+msgid "Set health status to %{health_status}."
+msgstr ""
+
+msgid "Set iteration"
+msgstr ""
+
+msgid "Set limit to 0 to allow any file size."
+msgstr ""
+
+msgid "Set limits for web and API requests."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set per-user rate limits for imports and exports of projects and groups."
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set rate limits for package registry API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Set severity"
+msgstr ""
+
+msgid "Set sign-in restrictions for all users."
+msgstr ""
+
+msgid "Set size limits for displaying diffs in the browser."
+msgstr ""
+
+msgid "Set target branch"
+msgstr ""
+
+msgid "Set target branch to %{branch_name}."
+msgstr ""
+
+msgid "Set the default branch for this project. All merge requests and commits are made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Set the default expiration time for job artifacts in all projects. Set to %{code_open}0%{code_close} to never expire artifacts by default. If no unit is written, it defaults to seconds. For example, these are all equivalent: %{code_open}3600%{code_close}, %{code_open}60 minutes%{code_close}, or %{code_open}one hour%{code_close}."
+msgstr ""
+
+msgid "Set the due date to %{due_date}."
+msgstr ""
+
+msgid "Set the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Set 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 "Set the maximum session time for a web terminal."
+msgstr ""
+
+msgid "Set the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Set the per-user rate limit for notes created by web or API requests."
+msgstr ""
+
+msgid "Set the timeout in seconds to send a secondary site status to the primary and IPs allowed for the secondary sites."
+msgstr ""
+
+msgid "Set time estimate"
+msgstr ""
+
+msgid "Set time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up Jira Integration"
+msgstr ""
+
+msgid "Set up a %{type} runner for a project"
+msgstr ""
+
+msgid "Set up a hardware device as a second factor to sign in."
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new device"
+msgstr ""
+
+msgid "Set up new password"
+msgstr ""
+
+msgid "Set up shared runner availability"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "Set verification limit and frequency."
+msgstr ""
+
+msgid "Set weight"
+msgstr ""
+
+msgid "Set weight to %{weight}."
+msgstr ""
+
+msgid "Set what should be replicated by this secondary site."
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
+msgid "SetStatusModal|Busy"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|Status updated"
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
+msgid "Sets %{epic_ref} as parent epic."
+msgstr ""
+
+msgid "Sets health status to %{health_status}."
+msgstr ""
+
+msgid "Sets target branch to %{branch_name}."
+msgstr ""
+
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets the severity"
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
+msgid "Setting"
+msgstr ""
+
+msgid "Setting enforced"
+msgstr ""
+
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
+msgstr ""
+
+msgid "Setup"
+msgstr ""
+
+msgid "Severity"
+msgstr ""
+
+msgid "Severity updated to %{severity}."
+msgstr ""
+
+msgid "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
+msgid "Shards to synchronize"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners are disabled on group level"
+msgstr ""
+
+msgid "Shared runners details"
+msgstr ""
+
+msgid "Shared runners help link"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{boldStart}will%{boldEnd} lose access to your account."
+msgstr ""
+
+msgid "Show Pipeline ID"
+msgstr ""
+
+msgid "Show Pipeline IID"
+msgstr ""
+
+msgid "Show all %{issuable_type}."
+msgstr ""
+
+msgid "Show all activity"
+msgstr ""
+
+msgid "Show all breadcrumbs"
+msgstr ""
+
+msgid "Show all epics"
+msgstr ""
+
+msgid "Show all issues."
+msgstr ""
+
+msgid "Show all test cases."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show closed epics"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments on this file"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show details"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show file contents"
+msgstr ""
+
+msgid "Show labels"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show list"
+msgstr ""
+
+msgid "Show one file at a time"
+msgstr ""
+
+msgid "Show open epics"
+msgstr ""
+
+msgid "Show the Closed list"
+msgstr ""
+
+msgid "Show the Open list"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{conflict} between %{sourceBranch} and %{targetBranch}"
+msgstr ""
+
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{limit} of %{total_count} issues. "
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
+msgid "Showing all epics"
+msgstr ""
+
+msgid "Showing all issues"
+msgstr ""
+
+msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgstr ""
+
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
+msgstr ""
+
+msgid "Showing graphs based on events of the last %{timerange} days."
+msgstr ""
+
+msgid "Showing last %{size} of log -"
+msgstr ""
+
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
+msgid "Sidebar|Assign health status"
+msgstr ""
+
+msgid "Sidebar|Health status"
+msgstr ""
+
+msgid "Sidebar|No status"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sidekiq job compression threshold (bytes)"
+msgstr ""
+
+msgid "Sidekiq job size limit (bytes)"
+msgstr ""
+
+msgid "Sidekiq job size limits"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in as a user with the matching email address, add the email to this account, or sign-up for a new account using the matching email."
+msgstr ""
+
+msgid "Sign in preview"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in to GitLab"
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign in/Sign up pages"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up now"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in and Help page"
+msgstr ""
+
+msgid "Sign-in count:"
+msgstr ""
+
+msgid "Sign-in page"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-in text"
+msgstr ""
+
+msgid "Sign-out page URL"
+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 ""
+
+msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
+msgid "Signing in using %{label} has been disabled"
+msgstr ""
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
+msgid "Site profile failed to delete"
+msgstr ""
+
+msgid "Site profile not found for given parameters"
+msgstr ""
+
+msgid "Sites"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size Limits"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "Skipped deployment to"
+msgstr ""
+
+msgid "Skype:"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
+msgid "SlackIntegration|Sends notifications about project events to Slack channels."
+msgstr ""
+
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
+msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
+msgstr ""
+
+msgid "SlackService|2. Paste the token from Slack in the %{strong_open}Token%{strong_close} field below."
+msgstr ""
+
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, select %{strong_open}Save changes%{strong_close}, and start using slash commands in Slack!"
+msgstr ""
+
+msgid "SlackService|After setup, get a list of available Slack slash commands by entering"
+msgstr ""
+
+msgid "SlackService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "Slice multiplier"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Snippets with non-text files can only be edited via Git."
+msgstr ""
+
+msgid "SnippetsEmptyState|Code snippets"
+msgstr ""
+
+msgid "SnippetsEmptyState|Documentation"
+msgstr ""
+
+msgid "SnippetsEmptyState|New snippet"
+msgstr ""
+
+msgid "SnippetsEmptyState|No snippets found"
+msgstr ""
+
+msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
+msgstr ""
+
+msgid "SnippetsEmptyState|There are no snippets to show."
+msgstr ""
+
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
+msgid "Snippets|Description (optional)"
+msgstr ""
+
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Snippets|Files"
+msgstr ""
+
+msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
+msgstr ""
+
+msgid "Snowplow"
+msgstr ""
+
+msgid "Solution"
+msgstr ""
+
+msgid "Some changes are not shown"
+msgstr ""
+
+msgid "Some child epics may be hidden due to applied filters"
+msgstr ""
+
+msgid "Some common domains are not allowed. %{learn_more_link}."
+msgstr ""
+
+msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
+msgstr ""
+
+msgid "Something went wrong"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the batch of suggestions. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while archiving a requirement."
+msgstr ""
+
+msgid "Something went wrong while closing the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while closing the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while creating a requirement."
+msgstr ""
+
+msgid "Something went wrong while deleting description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting your note. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deploying this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while editing your comment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while exporting requirements"
+msgstr ""
+
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching details"
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
+msgid "Something went wrong while fetching projects"
+msgstr ""
+
+msgid "Something went wrong while fetching projects."
+msgstr ""
+
+msgid "Something went wrong while fetching related merge requests."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements count."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements list."
+msgstr ""
+
+msgid "Something went wrong while fetching source branches."
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the packages list."
+msgstr ""
+
+msgid "Something went wrong while initializing the OpenAPI viewer"
+msgstr ""
+
+msgid "Something went wrong while inserting your image. Please try again."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while obtaining the Let's Encrypt certificate."
+msgstr ""
+
+msgid "Something went wrong while promoting the issue to an epic. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening a requirement."
+msgstr ""
+
+msgid "Something went wrong while reopening the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while reopening the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} %{dateType} date."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} confidentiality."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} health status."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} to-do item."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} weight."
+msgstr ""
+
+msgid "Something went wrong while stopping this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while updating a requirement."
+msgstr ""
+
+msgid "Something went wrong while updating assignees"
+msgstr ""
+
+msgid "Something went wrong while updating work item. Please try again"
+msgstr ""
+
+msgid "Something went wrong while updating your list settings"
+msgstr ""
+
+msgid "Something went wrong with your automatic subscription renewal."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to add projects to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
+msgid "Something went wrong, unable to get projects"
+msgstr ""
+
+msgid "Something went wrong, unable to search projects"
+msgstr ""
+
+msgid "Something went wrong. Please try again later"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Something went wrong. Try again later."
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further."
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "Sort direction: Ascending"
+msgstr ""
+
+msgid "Sort direction: Descending"
+msgstr ""
+
+msgid "SortOptions|Blocking"
+msgstr ""
+
+msgid "SortOptions|Closed date"
+msgstr ""
+
+msgid "SortOptions|Closed earlier"
+msgstr ""
+
+msgid "SortOptions|Closed recently"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Expired date"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+msgstr ""
+
+msgid "SortOptions|Merged date"
+msgstr ""
+
+msgid "SortOptions|Merged earlier"
+msgstr ""
+
+msgid "SortOptions|Merged recently"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest starred"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Project"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Recently starred"
+msgstr ""
+
+msgid "SortOptions|Size"
+msgstr ""
+
+msgid "SortOptions|Sort by:"
+msgstr ""
+
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Title"
+msgstr ""
+
+msgid "SortOptions|Type"
+msgstr ""
+
+msgid "SortOptions|Version"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source Branch"
+msgstr ""
+
+msgid "Source IP"
+msgstr ""
+
+msgid "Source branch"
+msgstr ""
+
+msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
+msgstr ""
+
+msgid "Source code (%{fileExtension})"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
+msgid "Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Block on private and internal projects"
+msgstr ""
+
+msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
+msgstr ""
+
+msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
+msgstr ""
+
+msgid "SourcegraphAdmin|More information"
+msgstr ""
+
+msgid "SourcegraphAdmin|Save changes"
+msgstr ""
+
+msgid "SourcegraphAdmin|Sourcegraph URL"
+msgstr ""
+
+msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
+msgstr ""
+
+msgid "Spam Check"
+msgstr ""
+
+msgid "Spam Check API key"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Spam log successfully submitted as ham."
+msgstr ""
+
+msgid "Specific runners"
+msgstr ""
+
+msgid "Specified URL cannot be used: \"%{reason}\""
+msgstr ""
+
+msgid "Specify an email address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Speed up your pipelines with Needs relationships"
+msgstr ""
+
+msgid "Spent At"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stack trace"
+msgstr ""
+
+msgid "Stacktrace snippet"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Standard"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "Star labels to start sorting by priority"
+msgstr ""
+
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
+msgstr ""
+
+msgid "StarredProjectsEmptyState|You don't have starred projects yet."
+msgstr ""
+
+msgid "Starrers"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Date"
+msgstr ""
+
+msgid "Start Time"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a Free Ultimate Trial"
+msgstr ""
+
+msgid "Start a new discussion…"
+msgstr ""
+
+msgid "Start a new merge request"
+msgstr ""
+
+msgid "Start a new merge request with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Start merge train..."
+msgstr ""
+
+msgid "Start search"
+msgstr ""
+
+msgid "Start thread"
+msgstr ""
+
+msgid "Start your Free Ultimate Trial"
+msgstr ""
+
+msgid "Start your free trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Started asynchronous removal of all repository check states."
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts"
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "Starts on"
+msgstr ""
+
+msgid "Starts: %{startsAt}"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "State/Province"
+msgstr ""
+
+msgid "State/Province/City"
+msgstr ""
+
+msgid "Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "StaticSiteEditor|1. Add a clear title to describe the change."
+msgstr ""
+
+msgid "StaticSiteEditor|2. Add a description to explain why the change is being made."
+msgstr ""
+
+msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|A link to view the merge request will appear once ready."
+msgstr ""
+
+msgid "StaticSiteEditor|An error occurred while submitting your changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Automatic formatting changes"
+msgstr ""
+
+msgid "StaticSiteEditor|Branch could not be created."
+msgstr ""
+
+msgid "StaticSiteEditor|Copy update"
+msgstr ""
+
+msgid "StaticSiteEditor|Could not commit the content changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Could not create merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|Creating your merge request"
+msgstr ""
+
+msgid "StaticSiteEditor|Incompatible file content"
+msgstr ""
+
+msgid "StaticSiteEditor|Markdown formatting preferences introduced by the Static Site Editor"
+msgstr ""
+
+msgid "StaticSiteEditor|Return to site"
+msgstr ""
+
+msgid "StaticSiteEditor|Static site editor"
+msgstr ""
+
+msgid "StaticSiteEditor|The Static Site Editor is currently configured to only edit Markdown content on pages generated from Middleman. Visit the documentation to learn more about configuring your site to use the Static Site Editor."
+msgstr ""
+
+msgid "StaticSiteEditor|To see your changes live you will need to do the following things:"
+msgstr ""
+
+msgid "StaticSiteEditor|Update %{sourcePath} file"
+msgstr ""
+
+msgid "StaticSiteEditor|View documentation"
+msgstr ""
+
+msgid "StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created."
+msgstr ""
+
+msgid "StaticSiteEditor|Your merge request has been created"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status was retried."
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Status: %{title}"
+msgstr ""
+
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
+msgid "StatusCheck|%{pending} pending"
+msgstr ""
+
+msgid "StatusCheck|API to check"
+msgstr ""
+
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|All passed"
+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 all branches 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|Failed to load status checks"
+msgstr ""
+
+msgid "StatusCheck|Failed to load status checks."
+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 checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
+msgid "StatusCheck|Status to check"
+msgstr ""
+
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
+msgid "StatusCheck|When this merge request is updated, a call is sent to the following APIs to confirm their status. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "StatusCheck|You are about to remove the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|status checks"
+msgstr ""
+
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS region"
+msgstr ""
+
+msgid "StatusPage|Active"
+msgstr ""
+
+msgid "StatusPage|Bucket %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+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 ""
+
+msgid "StatusPage|configuration documentation"
+msgstr ""
+
+msgid "StatusPage|your status page frontend."
+msgstr ""
+
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
+msgid "Step 1."
+msgstr ""
+
+msgid "Step 2."
+msgstr ""
+
+msgid "Step 3."
+msgstr ""
+
+msgid "Step 4."
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage nodes for new repositories"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "StorageSize|Unknown"
+msgstr ""
+
+msgid "Strikethrough"
+msgstr ""
+
+msgid "Subgroup information"
+msgstr ""
+
+msgid "Subgroup milestone"
+msgstr ""
+
+msgid "Subgroup navigation"
+msgstr ""
+
+msgid "SubgroupCreationLevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Maintainers"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Owners"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Subject Key Identifier:"
+msgstr ""
+
+msgid "Subkeys"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Submit a review"
+msgstr ""
+
+msgid "Submit as ham"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit changes"
+msgstr ""
+
+msgid "Submit changes..."
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submit your changes"
+msgstr ""
+
+msgid "Submitted as ham"
+msgstr ""
+
+msgid "Submitted the current review."
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Subscribed to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscribed to this project"
+msgstr ""
+
+msgid "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription History"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription service outage"
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionBanner|Export license usage file"
+msgstr ""
+
+msgid "SubscriptionBanner|Upload new license"
+msgstr ""
+
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Refresh Seats"
+msgstr ""
+
+msgid "SubscriptionTable|Renew"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|See usage"
+msgstr ""
+
+msgid "SubscriptionTable|Something went wrong trying to refresh seats"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Subscriptions"
+msgstr ""
+
+msgid "Subscription|Your subscription for %{strong}%{namespace_name}%{strong_close} has expired and you are now on %{pricing_link_start}the GitLab Free tier%{pricing_link_end}. Don't worry, your data is safe. Get in touch with our support team (%{support_email}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "Subtracted"
+msgstr ""
+
+msgid "Subtracts"
+msgstr ""
+
+msgid "Succeeded"
+msgstr ""
+
+msgid "Successful purchase image"
+msgstr ""
+
+msgid "Successfully activated"
+msgstr ""
+
+msgid "Successfully approved"
+msgstr ""
+
+msgid "Successfully banned"
+msgstr ""
+
+msgid "Successfully blocked"
+msgstr ""
+
+msgid "Successfully confirmed"
+msgstr ""
+
+msgid "Successfully deactivated"
+msgstr ""
+
+msgid "Successfully deleted U2F device."
+msgstr ""
+
+msgid "Successfully deleted WebAuthn device."
+msgstr ""
+
+msgid "Successfully removed email."
+msgstr ""
+
+msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
+msgstr ""
+
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
+msgid "Successfully unbanned"
+msgstr ""
+
+msgid "Successfully unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully updated %{last_updated_timeago}."
+msgstr ""
+
+msgid "Successfully updated the environment."
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "SuggestedColors|Aztec Gold"
+msgstr ""
+
+msgid "SuggestedColors|Blue"
+msgstr ""
+
+msgid "SuggestedColors|Blue-gray"
+msgstr ""
+
+msgid "SuggestedColors|Carrot orange"
+msgstr ""
+
+msgid "SuggestedColors|Champagne"
+msgstr ""
+
+msgid "SuggestedColors|Charcoal grey"
+msgstr ""
+
+msgid "SuggestedColors|Crimson"
+msgstr ""
+
+msgid "SuggestedColors|Dark coral"
+msgstr ""
+
+msgid "SuggestedColors|Dark green"
+msgstr ""
+
+msgid "SuggestedColors|Dark sea green"
+msgstr ""
+
+msgid "SuggestedColors|Dark violet"
+msgstr ""
+
+msgid "SuggestedColors|Deep violet"
+msgstr ""
+
+msgid "SuggestedColors|Gray"
+msgstr ""
+
+msgid "SuggestedColors|Green screen"
+msgstr ""
+
+msgid "SuggestedColors|Green-cyan"
+msgstr ""
+
+msgid "SuggestedColors|Lavendar"
+msgstr ""
+
+msgid "SuggestedColors|Magenta-pink"
+msgstr ""
+
+msgid "SuggestedColors|Medium sea green"
+msgstr ""
+
+msgid "SuggestedColors|Red"
+msgstr ""
+
+msgid "SuggestedColors|Rose red"
+msgstr ""
+
+msgid "SuggestedColors|Titanium yellow"
+msgstr ""
+
+msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as one or more suggestions were not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as their lines cannot overlap."
+msgstr ""
+
+msgid "Suggestions must all be on the same branch."
+msgstr ""
+
+msgid "Suggestions:"
+msgstr ""
+
+msgid "Suite"
+msgstr ""
+
+msgid "Summary"
+msgstr ""
+
+msgid "Summary / Note"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+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|Cloud licensing"
+msgstr ""
+
+msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
+msgid "SuperSonics|Export license usage file"
+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|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|Please agree to the Subscription Agreement"
+msgstr ""
+
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
+msgid "SuperSonics|Subscription details"
+msgstr ""
+
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
+msgid "SuperSonics|Sync subscription details"
+msgstr ""
+
+msgid "SuperSonics|Sync subscription request."
+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 activation code should be a 24-character alphanumeric string"
+msgstr ""
+
+msgid "SuperSonics|There is a connectivity issue."
+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|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|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 have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
+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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
+msgid "SuperSonics|Your future dated license was successfully added"
+msgstr ""
+
+msgid "SuperSonics|Your subscription"
+msgstr ""
+
+msgid "SuperSonics|Your subscription details will sync shortly."
+msgstr ""
+
+msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
+msgstr ""
+
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
+msgid "Support"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Support page URL"
+msgstr ""
+
+msgid "Survey Response"
+msgstr ""
+
+msgid "Switch Branches"
+msgstr ""
+
+msgid "Switch branch"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy the file contents"
+msgstr ""
+
+msgid "Symbolic link"
+msgstr ""
+
+msgid "Sync LDAP"
+msgstr ""
+
+msgid "Sync now"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronization settings"
+msgstr ""
+
+msgid "Synchronize LDAP"
+msgstr ""
+
+msgid "Syncing…"
+msgstr ""
+
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Dark"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Light"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Monokai"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|None"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Solarized Dark"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Solarized Light"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Hooks Help"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System OAuth applications"
+msgstr ""
+
+msgid "System OAuth applications don't belong to any user and can only be managed by admins"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System hook was successfully updated."
+msgstr ""
+
+msgid "System hooks are triggered on sets of events like creating a project or adding an SSH key. You can also enable extra triggers, such as push events."
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "System output"
+msgstr ""
+
+msgid "Table of Contents"
+msgstr ""
+
+msgid "Table of contents"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tag name"
+msgstr ""
+
+msgid "Tag name is required"
+msgstr ""
+
+msgid "Tag push events"
+msgstr ""
+
+msgid "Tag this commit."
+msgstr ""
+
+msgid "Tag:"
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target Path"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Target-Branch"
+msgstr ""
+
+msgid "Task"
+msgstr ""
+
+msgid "Task ID: %{elastic_task}"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Team domain"
+msgstr ""
+
+msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
+msgstr ""
+
+msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
+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|Create common files more quickly, and standardize their format."
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set once"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
+msgstr ""
+
+msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
+msgstr ""
+
+msgid "TemporaryStorage|Increase storage temporarily"
+msgstr ""
+
+msgid "TemporaryStorage|Temporarily increase storage now?"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terminal sync service is running"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Terms of service"
+msgstr ""
+
+msgid "Terraform"
+msgstr ""
+
+msgid "TerraformBanner|Learn more about GitLab's Backend State"
+msgstr ""
+
+msgid "TerraformBanner|The GitLab managed Terraform state backend can store your Terraform state easily and securely, and spares you from setting up additional remote resources. Its features include: versioning, encryption of the state file both in transit and at rest, locking, and remote Terraform plan/apply execution."
+msgstr ""
+
+msgid "TerraformBanner|Using Terraform? Try the GitLab Managed Terraform State"
+msgstr ""
+
+msgid "Terraform|%{name} successfully removed"
+msgstr ""
+
+msgid "Terraform|%{number} Terraform report failed to generate"
+msgid_plural "Terraform|%{number} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{number} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
+msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{user} updated %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|A Terraform report failed to generate."
+msgstr ""
+
+msgid "Terraform|A Terraform report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|A report failed to generate."
+msgstr ""
+
+msgid "Terraform|A report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|Actions"
+msgstr ""
+
+msgid "Terraform|An error occurred while changing the state file"
+msgstr ""
+
+msgid "Terraform|An error occurred while loading your Terraform States"
+msgstr ""
+
+msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
+msgstr ""
+
+msgid "Terraform|Cancel"
+msgstr ""
+
+msgid "Terraform|Copy Terraform init command"
+msgstr ""
+
+msgid "Terraform|Details"
+msgstr ""
+
+msgid "Terraform|Download JSON"
+msgstr ""
+
+msgid "Terraform|Failed to load Terraform reports"
+msgstr ""
+
+msgid "Terraform|Generating the report caused an error."
+msgstr ""
+
+msgid "Terraform|Get started with Terraform"
+msgstr ""
+
+msgid "Terraform|How to use GitLab-managed Terraform State?"
+msgstr ""
+
+msgid "Terraform|Job status"
+msgstr ""
+
+msgid "Terraform|Loading Terraform reports..."
+msgstr ""
+
+msgid "Terraform|Lock"
+msgstr ""
+
+msgid "Terraform|Locked"
+msgstr ""
+
+msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|Locking state"
+msgstr ""
+
+msgid "Terraform|Name"
+msgstr ""
+
+msgid "Terraform|Pipeline"
+msgstr ""
+
+msgid "Terraform|Remove"
+msgstr ""
+
+msgid "Terraform|Remove state file and versions"
+msgstr ""
+
+msgid "Terraform|Removing"
+msgstr ""
+
+msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
+msgstr ""
+
+msgid "Terraform|States"
+msgstr ""
+
+msgid "Terraform|Terraform init command"
+msgstr ""
+
+msgid "Terraform|Terraform reports"
+msgstr ""
+
+msgid "Terraform|The job %{name} failed to generate a report."
+msgstr ""
+
+msgid "Terraform|The job %{name} generated a report."
+msgstr ""
+
+msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
+msgstr ""
+
+msgid "Terraform|The job %{strong_start}%{name}%{strong_end} generated a report."
+msgstr ""
+
+msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
+msgstr ""
+
+msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
+msgstr ""
+
+msgid "Terraform|Unknown User"
+msgstr ""
+
+msgid "Terraform|Unlock"
+msgstr ""
+
+msgid "Terraform|Unlocking state"
+msgstr ""
+
+msgid "Terraform|You are about to remove the state file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously will remain intact, and only the state file with all its versions will be removed. This action cannot be undone."
+msgstr ""
+
+msgid "Terraform|You cannot remove the State file because it's locked. Unlock the State file first before removing it."
+msgstr ""
+
+msgid "Test"
+msgstr ""
+
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test case"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test coverage: %d hit"
+msgid_plural "Test coverage: %d hits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test settings"
+msgstr ""
+
+msgid "TestCases|Move test case"
+msgstr ""
+
+msgid "TestCases|Moving test case"
+msgstr ""
+
+msgid "TestCases|New Test Case"
+msgstr ""
+
+msgid "TestCases|New test case"
+msgstr ""
+
+msgid "TestCases|Search test cases"
+msgstr ""
+
+msgid "TestCases|Something went wrong while adding test case to a to-do item."
+msgstr ""
+
+msgid "TestCases|Something went wrong while creating a test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test cases list."
+msgstr ""
+
+msgid "TestCases|Something went wrong while marking test case to-do item as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while moving test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
+msgid "TestCases|Submit test case"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has deployments."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has releases."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
+msgid "TestReports|%{count} errors"
+msgstr ""
+
+msgid "TestReports|%{count} failures"
+msgstr ""
+
+msgid "TestReports|%{count} tests"
+msgstr ""
+
+msgid "TestReports|%{rate}%{sign} success rate"
+msgstr ""
+
+msgid "TestReports|Attachment"
+msgstr ""
+
+msgid "TestReports|Jobs"
+msgstr ""
+
+msgid "TestReports|Learn how to upload pipeline test reports"
+msgstr ""
+
+msgid "TestReports|Learn more about pipeline test reports"
+msgstr ""
+
+msgid "TestReports|No test cases were found in the test report."
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test reports for this pipeline"
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to display"
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "TestReports|You can configure your job to use unit test reports, and GitLab displays a report here and in the related merge request."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Text added to the body of all email messages. %{character_limit} character limit"
+msgstr ""
+
+msgid "Text style"
+msgstr ""
+
+msgid "Thank you for your business."
+msgstr ""
+
+msgid "Thank you for your feedback!"
+msgstr ""
+
+msgid "Thank you for your report. A GitLab administrator will look into it shortly."
+msgstr ""
+
+msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
+msgstr ""
+
+msgid "Thanks for signing up to GitLab!"
+msgstr ""
+
+msgid "Thanks for your purchase!"
+msgstr ""
+
+msgid "That's OK, I don't want to renew"
+msgstr ""
+
+msgid "That's it, well done!"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+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 ""
+
+msgid "The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}."
+msgstr ""
+
+msgid "The %{type} contains the following error:"
+msgid_plural "The %{type} contains the following errors:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+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 ""
+
+msgid "The ID of the application."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
+msgstr ""
+
+msgid "The Snowplow cookie domain."
+msgstr ""
+
+msgid "The URL of the Jenkins server."
+msgstr ""
+
+msgid "The URL should start with http:// or https://"
+msgstr ""
+
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
+
+msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
+msgstr ""
+
+msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
+msgstr ""
+
+msgid "The branch for this project has no active pipeline configuration."
+msgstr ""
+
+msgid "The branch or tag does not exist"
+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 comment you are editing has been changed by another user. Would you like to keep your changes and overwrite the new description or discard your changes?"
+msgstr ""
+
+msgid "The commit does not exist"
+msgstr ""
+
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
+msgid "The compliance report captures merged changes that violate compliance best practices."
+msgstr ""
+
+msgid "The compliance report shows the merge request violations merged in protected environments."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The contact does not belong to the issue group or an ancestor"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
+msgstr ""
+
+msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr ""
+
+msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
+msgstr ""
+
+msgid "The current issue"
+msgstr ""
+
+msgid "The current user is not authorized to access the job log."
+msgstr ""
+
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
+msgid "The data source is connected, but there is no data to display. %{documentationLink}"
+msgstr ""
+
+msgid "The default CI/CD configuration file and path for new projects."
+msgstr ""
+
+msgid "The default branch for this project has been changed. Please update your bookmarks."
+msgstr ""
+
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The directory has been successfully created."
+msgstr ""
+
+msgid "The domain you entered is misformatted."
+msgstr ""
+
+msgid "The domain you entered is not allowed."
+msgstr ""
+
+msgid "The download link will expire in 24 hours."
+msgstr ""
+
+msgid "The environment tier must be one of %{environment_tiers}."
+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 could not be displayed because it is empty or larger than the maximum file size indexed (%{size})."
+msgstr ""
+
+msgid "The file has been successfully created."
+msgstr ""
+
+msgid "The file has been successfully deleted."
+msgstr ""
+
+msgid "The file name should have a .yml extension"
+msgstr ""
+
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
+msgid "The following items will NOT be exported:"
+msgstr ""
+
+msgid "The following items will be exported:"
+msgstr ""
+
+msgid "The following personal access token: %{token_names} was revoked, because a new policy to expire personal access tokens were set."
+msgid_plural "The following personal access tokens: %{token_names} were revoked, because a new policy to expire personal access tokens were set."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The form contains the following errors:"
+msgstr ""
+
+msgid "The form contains the following warning:"
+msgstr ""
+
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
+msgid "The global settings require you to enable Two-Factor Authentication for your account."
+msgstr ""
+
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "The group export can be downloaded from:"
+msgstr ""
+
+msgid "The group has already been shared with this group"
+msgstr ""
+
+msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
+msgstr ""
+
+msgid "The group_project_ids parameter is only allowed for a group"
+msgstr ""
+
+msgid "The hostname of your PlantUML server."
+msgstr ""
+
+msgid "The hostname of your Snowplow collector."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+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 ""
+
+msgid "The invitation could not be declined."
+msgstr ""
+
+msgid "The invitation has already been accepted."
+msgstr ""
+
+msgid "The invitation was successfully resent."
+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 latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
+msgid "The latest pipeline for this merge request has failed."
+msgstr ""
+
+msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
+msgstr ""
+
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
+msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
+msgstr ""
+
+msgid "The list creation wizard is already open"
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size for job artifacts."
+msgstr ""
+
+msgid "The maximum file size in megabytes for individual job artifacts."
+msgstr ""
+
+msgid "The maximum file size is %{size}."
+msgstr ""
+
+msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
+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 ""
+
+msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
+msgstr ""
+
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
+msgid "The name \"%{name}\" is already taken in this directory."
+msgstr ""
+
+msgid "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})."
+msgstr ""
+
+msgid "The name of the Jenkins project. Copy the name from the end of the URL to the project."
+msgstr ""
+
+msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
+msgstr ""
+
+msgid "The number of merge requests merged by month."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
+msgid "The page could not be displayed because it timed out."
+msgstr ""
+
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
+
+msgid "The password for the Jenkins server."
+msgstr ""
+
+msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
+msgstr ""
+
+msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
+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 project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
+msgid "The project was successfully forked."
+msgstr ""
+
+msgid "The project was successfully imported."
+msgstr ""
+
+msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
+msgstr ""
+
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
+msgid "The remote repository is being updated..."
+msgstr ""
+
+msgid "The repository can be committed to, and issues, comments and other entities can be created."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository is being updated..."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
+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 same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "The snippet can be accessed without any authentication."
+msgstr ""
+
+msgid "The snippet is visible only to me."
+msgstr ""
+
+msgid "The snippet is visible only to project members."
+msgstr ""
+
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
+
+msgid "The specified tab is invalid, please select another"
+msgstr ""
+
+msgid "The start date must be ealier than the end date."
+msgstr ""
+
+msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
+msgstr ""
+
+msgid "The tag name can't be changed for an existing release."
+msgstr ""
+
+msgid "The time period in seconds that the maximum requests per project limit applies to."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
+msgstr ""
+
+msgid "The user is being deleted."
+msgstr ""
+
+msgid "The user map has been saved. Continue by selecting the projects you want to import."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The user you are trying to approve is not pending approval"
+msgstr ""
+
+msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
+msgstr ""
+
+msgid "The username for the Jenkins server."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
+msgstr ""
+
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
+msgid "There are currently no events."
+msgstr ""
+
+msgid "There are merge conflicts"
+msgstr ""
+
+msgid "There are no %{replicableTypeName} to show"
+msgstr ""
+
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
+
+msgid "There are no Spam Logs"
+msgstr ""
+
+msgid "There are no abuse reports!"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no archived requirements"
+msgstr ""
+
+msgid "There are no archived test cases"
+msgstr ""
+
+msgid "There are no changes"
+msgstr ""
+
+msgid "There are no charts configured for this page"
+msgstr ""
+
+msgid "There are no closed epics"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no commits yet."
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no issues with the selected labels"
+msgstr ""
+
+msgid "There are no matching files"
+msgstr ""
+
+msgid "There are no open epics"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no open requirements"
+msgstr ""
+
+msgid "There are no open test cases"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no topics to show."
+msgstr ""
+
+msgid "There are no variables yet."
+msgstr ""
+
+msgid "There are running deployments on the environment. Please retry later."
+msgstr ""
+
+msgid "There are several file size limits in place for the Package Registry."
+msgstr ""
+
+msgid "There are several rate limits in place to protect the system."
+msgstr ""
+
+msgid "There are several size limits in place."
+msgstr ""
+
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There is already a to-do item for this design."
+msgstr ""
+
+msgid "There is no chart data available."
+msgstr ""
+
+msgid "There is no data available."
+msgstr ""
+
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no table data available."
+msgstr ""
+
+msgid "There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem fetching branches."
+msgstr ""
+
+msgid "There was a problem fetching emojis."
+msgstr ""
+
+msgid "There was a problem fetching epics."
+msgstr ""
+
+msgid "There was a problem fetching groups."
+msgstr ""
+
+msgid "There was a problem fetching iterations."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+msgstr ""
+
+msgid "There was a problem fetching linked pipelines."
+msgstr ""
+
+msgid "There was a problem fetching milestones."
+msgstr ""
+
+msgid "There was a problem fetching project branches."
+msgstr ""
+
+msgid "There was a problem fetching project tags."
+msgstr ""
+
+msgid "There was a problem fetching project users."
+msgstr ""
+
+msgid "There was a problem fetching recent groups."
+msgstr ""
+
+msgid "There was a problem fetching recent projects."
+msgstr ""
+
+msgid "There was a problem fetching releases."
+msgstr ""
+
+msgid "There was a problem fetching the job token scope value"
+msgstr ""
+
+msgid "There was a problem fetching the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was a problem fetching the projects"
+msgstr ""
+
+msgid "There was a problem fetching users."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was a problem updating the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was an error %{message} to-do item."
+msgstr ""
+
+msgid "There was an error adding a To Do."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error creating the issue"
+msgstr ""
+
+msgid "There was an error deleting the To Do."
+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 ""
+
+msgid "There was an error fetching data for the tasks by type chart"
+msgstr ""
+
+msgid "There was an error fetching label data for the selected group"
+msgstr ""
+
+msgid "There was an error fetching median data for stages"
+msgstr ""
+
+msgid "There was an error fetching projects"
+msgstr ""
+
+msgid "There was an error fetching search autocomplete suggestions"
+msgstr ""
+
+msgid "There was an error fetching stage total counts"
+msgstr ""
+
+msgid "There was an error fetching the %{replicableType}"
+msgstr ""
+
+msgid "There was an error fetching the Geo Settings"
+msgstr ""
+
+msgid "There was an error fetching the Sites's Groups"
+msgstr ""
+
+msgid "There was an error fetching the deploy freezes."
+msgstr ""
+
+msgid "There was an error fetching the environments information."
+msgstr ""
+
+msgid "There was an error fetching the jobs for your project."
+msgstr ""
+
+msgid "There was an error fetching the top labels for the selected group"
+msgstr ""
+
+msgid "There was an error fetching the variables."
+msgstr ""
+
+msgid "There was an error fetching value stream analytics stages."
+msgstr ""
+
+msgid "There was an error gathering the chart data"
+msgstr ""
+
+msgid "There was an error getting the epic participants."
+msgstr ""
+
+msgid "There was an error importing the Jira project."
+msgstr ""
+
+msgid "There was an error loading related feature flags"
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error parsing the data for this graph."
+msgstr ""
+
+msgid "There was an error removing the e-mail."
+msgstr ""
+
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
+msgid "There was an error retrieving the Jira users."
+msgstr ""
+
+msgid "There was an error saving this Geo Site"
+msgstr ""
+
+msgid "There was an error saving your changes."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error syncing project %{name}"
+msgstr ""
+
+msgid "There was an error syncing the %{replicableType}"
+msgstr ""
+
+msgid "There was an error trying to validate your query"
+msgstr ""
+
+msgid "There was an error updating the Geo Settings"
+msgstr ""
+
+msgid "There was an error updating the Maintenance Mode Settings"
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics data."
+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 ""
+
+msgid "These dates affect how your epics appear in the roadmap. Set a fixed date or one inherited from the milestones assigned to issues in this epic."
+msgstr ""
+
+msgid "These examples show how to trigger this project's pipeline for a branch or tag."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
+msgstr ""
+
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
+msgstr ""
+
+msgid "These will be sent to %{email} in an attachment once finished."
+msgstr ""
+
+msgid "Third Party Advisory Link"
+msgstr ""
+
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgstr ""
+
+msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
+msgstr ""
+
+msgid "This %{noteableTypeText} is locked."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This Cron pattern is invalid"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
+msgstr ""
+
+msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
+msgstr ""
+
+msgid "This GitLab instance is undergoing maintenance and is operating in read-only mode."
+msgstr ""
+
+msgid "This PDF is too large to display. Please download to view."
+msgstr ""
+
+msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
+msgstr ""
+
+msgid "This URL is already used for another link; duplicate URLs are not allowed"
+msgstr ""
+
+msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
+msgstr ""
+
+msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues and merge requests."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues and merge requests."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}immediately%{strongClose}."
+msgstr ""
+
+msgid "This also resolves all related threads"
+msgstr ""
+
+msgid "This also resolves this thread"
+msgstr ""
+
+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 ""
+
+msgid "This archive has been requested too many times. Try again later."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{requirements_count} requirements have been included. Consider re-exporting with a narrower selection of requirements."
+msgstr ""
+
+msgid "This block is self-referential"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
+msgid "This clears repository check states for all projects in the database and cannot be undone. Are you sure?"
+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 ""
+
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+msgstr ""
+
+msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a different user's verified signature."
+msgstr ""
+
+msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
+msgstr ""
+
+msgid "This content could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
+msgid "This credential has expired"
+msgstr ""
+
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This endpoint has been requested too many times. Try again later."
+msgstr ""
+
+msgid "This environment has no deployments yet."
+msgstr ""
+
+msgid "This environment is being deployed"
+msgstr ""
+
+msgid "This environment is being re-deployed"
+msgstr ""
+
+msgid "This environment's canary ingress has been updated recently. Please retry later."
+msgstr ""
+
+msgid "This epic already has the maximum number of child epics."
+msgstr ""
+
+msgid "This epic does not exist or you don't have sufficient permission."
+msgstr ""
+
+msgid "This feature requires local storage to be enabled"
+msgstr ""
+
+msgid "This field is required"
+msgstr ""
+
+msgid "This field is required."
+msgstr ""
+
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
+msgid "This form is disabled in preview"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group and its subgroups and projects will be placed in a 'pending deletion' state for %{deletion_adjourned_period} days, then permanently deleted on %{date}. The group can be fully restored before that date."
+msgstr ""
+
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
+msgid "This group can't be transfered because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
+msgid "This group cannot be invited to a project inside a group with enforced SSO"
+msgstr ""
+
+msgid "This group does not have any group runners yet."
+msgstr ""
+
+msgid "This group has been scheduled for permanent removal on %{date}"
+msgstr ""
+
+msgid "This group has no active access tokens."
+msgstr ""
+
+msgid "This group is linked to a subscription"
+msgstr ""
+
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
+msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
+msgstr ""
+
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
+
+msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
+msgid "This is a Jira user."
+msgstr ""
+
+msgid "This is a confidential %{noteableTypeText}."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a merge train pipeline"
+msgstr ""
+
+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 authentication events involving your account."
+msgstr ""
+
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
+msgid "This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "This is your current session"
+msgstr ""
+
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
+msgid "This issue is hidden because its author has been banned"
+msgstr ""
+
+msgid "This issue is in a child epic of the filtered epic"
+msgstr ""
+
+msgid "This job depends on other jobs with expired/erased artifacts: %{invalid_dependencies}"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is performing tasks that must complete before it can start"
+msgstr ""
+
+msgid "This job is preparing to start"
+msgstr ""
+
+msgid "This job is waiting for resource: "
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes."
+msgstr ""
+
+msgid "This job triggers a downstream pipeline"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This license has already expired."
+msgstr ""
+
+msgid "This link points to external content"
+msgstr ""
+
+msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
+msgid "This merge request does not have accessibility reports"
+msgstr ""
+
+msgid "This merge request does not have codequality reports"
+msgstr ""
+
+msgid "This merge request is closed. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This merge request is from a private project to a public project."
+msgstr ""
+
+msgid "This merge request is from a private project to an internal project."
+msgstr ""
+
+msgid "This merge request is from an internal project to a public project."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This merge request was merged. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This namespace has already been taken! Please choose another one."
+msgstr ""
+
+msgid "This only applies to repository indexing operations."
+msgstr ""
+
+msgid "This option is only available on GitLab.com"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page sends a payload. Go back to the events page to see a newly created event."
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline was triggered by a schedule."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
+msgid "This project does not belong to a group and cannot make use of group runners."
+msgstr ""
+
+msgid "This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project has no active access tokens."
+msgstr ""
+
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
+msgid "This project is archived and cannot be commented on."
+msgstr ""
+
+msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
+msgstr ""
+
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
+msgid "This project path either does not exist or you do not have access."
+msgstr ""
+
+msgid "This project will be deleted on %{date}"
+msgstr ""
+
+msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
+msgstr ""
+
+msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This repository has never been checked."
+msgstr ""
+
+msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check passed."
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This service allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
+msgid "This subscription is for"
+msgstr ""
+
+msgid "This suggestion already matches its content."
+msgstr ""
+
+msgid "This user cannot be unlocked manually from GitLab"
+msgstr ""
+
+msgid "This user has an unconfirmed email address (%{email}). You may force a confirmation."
+msgstr ""
+
+msgid "This user has an unconfirmed email address. You may force a confirmation."
+msgstr ""
+
+msgid "This user has no active %{type}."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user has no personal projects."
+msgstr ""
+
+msgid "This user has previously committed to the %{name} project."
+msgstr ""
+
+msgid "This user has the %{access} role in the %{name} project."
+msgstr ""
+
+msgid "This user is the author of this %{noteable}."
+msgstr ""
+
+msgid "This variable can not be masked."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and %{fork_source}."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and other projects in the fork network."
+msgstr ""
+
+msgid "Thread to reply to cannot be found"
+msgstr ""
+
+msgid "Threat monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Alert Details"
+msgstr ""
+
+msgid "ThreatMonitoring|Alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|All Environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Anomalous Requests"
+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 ""
+
+msgid "ThreatMonitoring|Container Network Policy"
+msgstr ""
+
+msgid "ThreatMonitoring|Container NetworkPolicies not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Date and time"
+msgstr ""
+
+msgid "ThreatMonitoring|Dismissed"
+msgstr ""
+
+msgid "ThreatMonitoring|Dropped Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Environment"
+msgstr ""
+
+msgid "ThreatMonitoring|Events"
+msgstr ""
+
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
+msgid "ThreatMonitoring|Hide dismissed alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|In review"
+msgstr ""
+
+msgid "ThreatMonitoring|Incident"
+msgstr ""
+
+msgid "ThreatMonitoring|Name"
+msgstr ""
+
+msgid "ThreatMonitoring|No alerts available to display. See %{linkStart}enabling threat alerts%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "ThreatMonitoring|No alerts to display."
+msgstr ""
+
+msgid "ThreatMonitoring|No environments detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Operations Per Second"
+msgstr ""
+
+msgid "ThreatMonitoring|Packet Activity"
+msgstr ""
+
+msgid "ThreatMonitoring|Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
+msgid "ThreatMonitoring|Show last"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|Statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|Status"
+msgstr ""
+
+msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "ThreatMonitoring|There was an error while updating the status of the alert. Please try again."
+msgstr ""
+
+msgid "ThreatMonitoring|Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Threat Monitoring help page link"
+msgstr ""
+
+msgid "ThreatMonitoring|Time"
+msgstr ""
+
+msgid "ThreatMonitoring|To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ThreatMonitoring|Total Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Total Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
+msgid "ThreatMonitoring|View documentation"
+msgstr ""
+
+msgid "Threshold in bytes at which to compress Sidekiq job arguments."
+msgstr ""
+
+msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
+msgstr ""
+
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
+msgid "Throughput"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
+msgstr ""
+
+msgid "Time Spent"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time from first comment to last commit"
+msgstr ""
+
+msgid "Time from first commit until first comment"
+msgstr ""
+
+msgid "Time from last commit to merge"
+msgstr ""
+
+msgid "Time in seconds"
+msgstr ""
+
+msgid "Time of import: %{importTime}"
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time to merge"
+msgstr ""
+
+msgid "Time to subtract exceeds the total time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time tracking report"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "Time zone"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "TimeTracking|Time remaining: %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout connecting to the Google API. Please try again."
+msgstr ""
+
+msgid "Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout."
+msgstr ""
+
+msgid "Timeout for most Gitaly operations (in seconds)."
+msgstr ""
+
+msgid "Timeout for the fastest Gitaly operations (in seconds)."
+msgstr ""
+
+msgid "Timezone"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip: Hover over a job to see the jobs it depends on to run."
+msgstr ""
+
+msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Title:"
+msgstr ""
+
+msgid "Titles and Descriptions"
+msgstr ""
+
+msgid "To"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
+
+msgid "To Do"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
+msgid "To confirm, type %{phrase_code}"
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To continue using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
+msgid "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}"
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable Registration Features, first enable Service Ping."
+msgstr ""
+
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
+msgstr ""
+
+msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
+msgstr ""
+
+msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To get started, use the link below to confirm your account."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab periodically collects usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To learn more about this project, read %{link_to_wiki}"
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+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 pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
+
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you"
+msgstr ""
+
+msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, %{linkStart}fork this project%{linkEnd} and set the fork's visibility to private."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, a private fork of this project was selected."
+msgstr ""
+
+msgid "To reactivate your account, %{gitlab_link_start}sign in to GitLab.%{link_end}"
+msgstr ""
+
+msgid "To reactivate your account, sign in to GitLab at %{gitlab_url}."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
+msgid "To resolve this, try to:"
+msgstr ""
+
+msgid "To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings."
+msgstr ""
+
+msgid "To see all the user's personal access tokens you must impersonate them first."
+msgstr ""
+
+msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Premium%{linkEnd}. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To set up this integration:"
+msgstr ""
+
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
+msgid "To start using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
+msgid "To unsubscribe from this issue, please paste the following link into your browser:"
+msgstr ""
+
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
+msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
+msgstr ""
+
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
+msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters above."
+msgstr ""
+
+msgid "To-Do List"
+msgstr ""
+
+msgid "To-do item successfully marked as done."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
+msgstr ""
+
+msgid "Todos|Filter by author"
+msgstr ""
+
+msgid "Todos|Filter by group"
+msgstr ""
+
+msgid "Todos|Filter by project"
+msgstr ""
+
+msgid "Todos|It's how you always know what to work on next."
+msgstr ""
+
+msgid "Todos|Mark all as done"
+msgstr ""
+
+msgid "Todos|Nothing is on your to-do list. Nice work!"
+msgstr ""
+
+msgid "Todos|Undo mark all as done"
+msgstr ""
+
+msgid "Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List."
+msgstr ""
+
+msgid "Todos|You're all done!"
+msgstr ""
+
+msgid "Todos|Your To-Do List shows what to work on next"
+msgstr ""
+
+msgid "Toggle GitLab Next"
+msgstr ""
+
+msgid "Toggle Markdown preview"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle backtrace"
+msgstr ""
+
+msgid "Toggle collapse"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle dropdown"
+msgstr ""
+
+msgid "Toggle emoji award"
+msgstr ""
+
+msgid "Toggle focus mode"
+msgstr ""
+
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle project select"
+msgstr ""
+
+msgid "Toggle shortcuts"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "Toggle the Performance Bar"
+msgstr ""
+
+msgid "Toggle thread"
+msgstr ""
+
+msgid "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Token Access"
+msgstr ""
+
+msgid "Token name"
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tokens|Scopes set the permission levels granted to the token."
+msgstr ""
+
+msgid "Tokens|Select scopes"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
+
+msgid "TopNav|Go back"
+msgstr ""
+
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Score"
+msgstr ""
+
+msgid "Total artifacts size: %{total_size}"
+msgstr ""
+
+msgid "Total cores (CPUs)"
+msgstr ""
+
+msgid "Total issues"
+msgstr ""
+
+msgid "Total memory (GB)"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total users"
+msgstr ""
+
+msgid "Total weight"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "TotalMilestonesIndicator|1000+"
+msgstr ""
+
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track important events in your GitLab instance."
+msgstr ""
+
+msgid "Track important events in your group."
+msgstr ""
+
+msgid "Track important events in your project."
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Training mode"
+msgstr ""
+
+msgid "Transfer"
+msgstr ""
+
+msgid "Transfer group to another parent group."
+msgstr ""
+
+msgid "Transfer ownership"
+msgstr ""
+
+msgid "Transfer project"
+msgstr ""
+
+msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "TransferGroup|Cannot transfer group to one of its subgroup."
+msgstr ""
+
+msgid "TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group contains projects with NPM packages."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project is already in this namespace."
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
+msgstr ""
+
+msgid "TransferProject|You don't have permission to transfer projects into that namespace."
+msgstr ""
+
+msgid "TransferProject|You don't have permission to transfer this project."
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trials|%{planName} Trial %{enDash} %{num} day left"
+msgid_plural "Trials|%{planName} Trial %{enDash} %{num} days left"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Trials|Compare all plans"
+msgstr ""
+
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
+msgstr ""
+
+msgid "Trials|Go back to GitLab"
+msgstr ""
+
+msgid "Trials|Hey there"
+msgstr ""
+
+msgid "Trials|Skip Trial"
+msgstr ""
+
+msgid "Trials|Upgrade %{groupName} to %{planName}"
+msgstr ""
+
+msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group or an existing group."
+msgstr ""
+
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
+msgstr ""
+
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
+msgid "Trial|Company name"
+msgstr ""
+
+msgid "Trial|Continue"
+msgstr ""
+
+msgid "Trial|Continue using the basic features of GitLab for free."
+msgstr ""
+
+msgid "Trial|Country"
+msgstr ""
+
+msgid "Trial|Dismiss"
+msgstr ""
+
+msgid "Trial|GitLab Ultimate trial (optional)"
+msgstr ""
+
+msgid "Trial|Number of employees"
+msgstr ""
+
+msgid "Trial|Please select a country"
+msgstr ""
+
+msgid "Trial|Successful trial activation image"
+msgstr ""
+
+msgid "Trial|Telephone number"
+msgstr ""
+
+msgid "Trial|Upgrade to Ultimate to keep using GitLab with advanced features."
+msgstr ""
+
+msgid "Trial|We will activate your trial on your group after you complete this step. After 30 days, you can:"
+msgstr ""
+
+msgid "Trial|Your GitLab Ultimate trial lasts for 30 days, but you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions."
+msgstr ""
+
+msgid "Trigger cluster reindexing"
+msgstr ""
+
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
+msgstr ""
+
+msgid "Trigger manual job"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated in the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger removed."
+msgstr ""
+
+msgid "Trigger repository check"
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Trigger was created successfully."
+msgstr ""
+
+msgid "Trigger was successfully updated."
+msgstr ""
+
+msgid "Triggerer"
+msgstr ""
+
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Trusted"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Try changing or removing filters."
+msgstr ""
+
+msgid "Try grouping with different labels"
+msgstr ""
+
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
+msgid "Try to fork again"
+msgstr ""
+
+msgid "Try to keep the first line under 52 characters and the others under 72."
+msgstr ""
+
+msgid "Try using a different search term to find the file you are looking for."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if needed) and press the button on the device now."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Tuning settings"
+msgstr ""
+
+msgid "Turn off"
+msgstr ""
+
+msgid "Turn on"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Twitter:"
+msgstr ""
+
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-Factor Authentication code"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
+msgid "Two-factor Authentication:"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
+msgid "Two-factor grace period"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Type/State"
+msgstr ""
+
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
+msgid "URL is required"
+msgstr ""
+
+msgid "URL is triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "URL is triggered when a merge request is created, updated, or merged"
+msgstr ""
+
+msgid "URL is triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "URL is triggered when repository is updated"
+msgstr ""
+
+msgid "URL must be percent-encoded if neccessary."
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage to serve the repository static objects."
+msgstr ""
+
+msgid "URL or request ID"
+msgstr ""
+
+msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER %{user} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER WILL BE BLOCKED! Are you sure?"
+msgstr ""
+
+msgid "UTC"
+msgstr ""
+
+msgid "Unable to apply suggestions to a deleted line."
+msgstr ""
+
+msgid "Unable to build Slack link."
+msgstr ""
+
+msgid "Unable to collect CPU info"
+msgstr ""
+
+msgid "Unable to collect memory info"
+msgstr ""
+
+msgid "Unable to connect to Elasticsearch"
+msgstr ""
+
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
+msgid "Unable to connect to server: %{error}"
+msgstr ""
+
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
+msgid "Unable to convert Kubernetes logs encoding to UTF-8"
+msgstr ""
+
+msgid "Unable to create link to vulnerability"
+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 upstream and downstream pipelines."
+msgstr ""
+
+msgid "Unable to fetch vulnerable projects"
+msgstr ""
+
+msgid "Unable to find Jira project to import data from."
+msgstr ""
+
+msgid "Unable to generate new instance ID"
+msgstr ""
+
+msgid "Unable to load commits. Try again later."
+msgstr ""
+
+msgid "Unable to load file contents. Try again later."
+msgstr ""
+
+msgid "Unable to load the diff"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to load the merge request widget. Try reloading the page."
+msgstr ""
+
+msgid "Unable to save iteration. Please try again"
+msgstr ""
+
+msgid "Unable to save your changes. Please try again."
+msgstr ""
+
+msgid "Unable to save your preference"
+msgstr ""
+
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to suggest a path. Please refresh and try again."
+msgstr ""
+
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
+msgid "Unapprove a merge request"
+msgstr ""
+
+msgid "Unapprove the current merge request."
+msgstr ""
+
+msgid "Unapproved the current merge request."
+msgstr ""
+
+msgid "Unarchive project"
+msgstr ""
+
+msgid "Unarchiving the project will restore its members' ability to make changes to it. The repository can be committed to, and issues, comments, and other entities can be created. %{strong_start}Once active, this project shows up in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Unassign from commenting user"
+msgstr ""
+
+msgid "Unassigned"
+msgstr ""
+
+msgid "Unauthenticated API rate limit period in seconds"
+msgstr ""
+
+msgid "Unauthenticated requests"
+msgstr ""
+
+msgid "Unauthenticated web rate limit period in seconds"
+msgstr ""
+
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Undo Ignore"
+msgstr ""
+
+msgid "Undo ignore"
+msgstr ""
+
+msgid "Unexpected error"
+msgstr ""
+
+msgid "Unfollow"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unhappy?"
+msgstr ""
+
+msgid "Units|ms"
+msgstr ""
+
+msgid "Units|s"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unknown Error"
+msgstr ""
+
+msgid "Unknown cache key"
+msgstr ""
+
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
+msgid "Unknown screen"
+msgstr ""
+
+msgid "Unknown user"
+msgstr ""
+
+msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
+msgstr ""
+
+msgid "Unlimited"
+msgstr ""
+
+msgid "Unlink"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock account"
+msgstr ""
+
+msgid "Unlock the discussion"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unlocked the discussion."
+msgstr ""
+
+msgid "Unlocks the discussion."
+msgstr ""
+
+msgid "Unmarked this %{noun} as a draft."
+msgstr ""
+
+msgid "Unmarks this %{noun} as a draft."
+msgstr ""
+
+msgid "Unreachable"
+msgstr ""
+
+msgid "Unrecognized cluster type"
+msgstr ""
+
+msgid "Unresolve"
+msgstr ""
+
+msgid "Unresolve thread"
+msgstr ""
+
+msgid "Unresolved"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unstarted"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unsubscribed from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsubscribes from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
+msgstr ""
+
+msgid "Until revoked, expired personal access tokens pose a security risk."
+msgstr ""
+
+msgid "Unused"
+msgstr ""
+
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Upcoming Release"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update %{sourcePath} file"
+msgstr ""
+
+msgid "Update Now"
+msgstr ""
+
+msgid "Update Scheduled…"
+msgstr ""
+
+msgid "Update all"
+msgstr ""
+
+msgid "Update appearance settings"
+msgstr ""
+
+msgid "Update approval rule"
+msgstr ""
+
+msgid "Update approvers"
+msgstr ""
+
+msgid "Update broadcast message"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update it"
+msgstr ""
+
+msgid "Update iteration"
+msgstr ""
+
+msgid "Update milestone"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update username"
+msgstr ""
+
+msgid "Update variable"
+msgstr ""
+
+msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
+msgstr ""
+
+msgid "Updated"
+msgstr ""
+
+msgid "Updated %{updated_at} by %{updated_by}"
+msgstr ""
+
+msgid "Updated date"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
+msgid "Updating…"
+msgstr ""
+
+msgid "Upgrade offers available!"
+msgstr ""
+
+msgid "Upgrade your plan"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "Upload %{file_name} file"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload File"
+msgstr ""
+
+msgid "Upload License"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload an image"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload image"
+msgstr ""
+
+msgid "Upload license"
+msgstr ""
+
+msgid "Upload new file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Uploading changes to terminal"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Uptime"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage Trends"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|%{linkTitle} help link"
+msgstr ""
+
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
+
+msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
+msgstr ""
+
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|CI minutes usage by month"
+msgstr ""
+
+msgid "UsageQuota|CI minutes usage by project"
+msgstr ""
+
+msgid "UsageQuota|Code packages and container images."
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|File attachments and smaller design graphics."
+msgstr ""
+
+msgid "UsageQuota|Git repository."
+msgstr ""
+
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about excess storage usage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about usage quotas"
+msgstr ""
+
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
+msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Seats"
+msgstr ""
+
+msgid "UsageQuota|Shared bits of code and text."
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Something went wrong while fetching project storage statistics"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|Storage type"
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Uploads"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project"
+msgstr ""
+
+msgid "UsageQuota|Usage of resources across your projects"
+msgstr ""
+
+msgid "UsageQuota|Usage quotas help link"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "UsageQuota|Wiki content."
+msgstr ""
+
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
+msgid "UsageQuota|You used: %{usage} %{limit}"
+msgstr ""
+
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
+msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
+msgstr ""
+
+msgid "UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Groups"
+msgstr ""
+
+msgid "UsageTrends|Issues"
+msgstr ""
+
+msgid "UsageTrends|Issues & merge requests"
+msgstr ""
+
+msgid "UsageTrends|Items"
+msgstr ""
+
+msgid "UsageTrends|Merge requests"
+msgstr ""
+
+msgid "UsageTrends|Month"
+msgstr ""
+
+msgid "UsageTrends|No data available."
+msgstr ""
+
+msgid "UsageTrends|Pipelines"
+msgstr ""
+
+msgid "UsageTrends|Pipelines canceled"
+msgstr ""
+
+msgid "UsageTrends|Pipelines failed"
+msgstr ""
+
+msgid "UsageTrends|Pipelines skipped"
+msgstr ""
+
+msgid "UsageTrends|Pipelines succeeded"
+msgstr ""
+
+msgid "UsageTrends|Pipelines total"
+msgstr ""
+
+msgid "UsageTrends|Projects"
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the cancelled pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the failed pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the groups. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the issues. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the merge requests. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the projects. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the skipped pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the successful pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the total pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|Total groups"
+msgstr ""
+
+msgid "UsageTrends|Total projects"
+msgstr ""
+
+msgid "UsageTrends|Total projects & groups"
+msgstr ""
+
+msgid "UsageTrends|Users"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+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 authorized_keys file to authenticate SSH keys"
+msgstr ""
+
+msgid "Use cURL"
+msgstr ""
+
+msgid "Use custom color #FF0000"
+msgstr ""
+
+msgid "Use double quotes for multiple keywords, such as %{code_open}\"your search\"%{code_close}"
+msgstr ""
+
+msgid "Use hashed storage"
+msgstr ""
+
+msgid "Use hashed storage paths for newly created and renamed repositories. Always enabled since 13.0."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use primary email (%{email})"
+msgstr ""
+
+msgid "Use shortcuts"
+msgstr ""
+
+msgid "Use slash commands."
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
+msgid "Use the link below to confirm your email address (%{email})"
+msgstr ""
+
+msgid "Use the link below to confirm your email address."
+msgstr ""
+
+msgid "Use the public cloud instance URL (%{kroki_public_url}) or %{install_link_start}install Kroki%{install_link_end} on your own infrastructure and use your own instance URL."
+msgstr ""
+
+msgid "Use the search bar on the top of this page"
+msgstr ""
+
+msgid "Use this token to validate received payloads."
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
+
+msgid "Use your global notification setting"
+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 ""
+
+msgid "Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises."
+msgstr ""
+
+msgid "Used programming language"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "User %{current_user_username} has started impersonating %{username}"
+msgstr ""
+
+msgid "User %{username} was successfully removed."
+msgstr ""
+
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
+msgid "User ID"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP rate limits"
+msgstr ""
+
+msgid "User cap"
+msgstr ""
+
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
+msgid "User does not have a pending request"
+msgstr ""
+
+msgid "User identity was successfully created."
+msgstr ""
+
+msgid "User identity was successfully removed."
+msgstr ""
+
+msgid "User identity was successfully updated."
+msgstr ""
+
+msgid "User is not allowed to resolve thread"
+msgstr ""
+
+msgid "User key"
+msgstr ""
+
+msgid "User key was successfully removed."
+msgstr ""
+
+msgid "User list %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "User restrictions"
+msgstr ""
+
+msgid "User settings"
+msgstr ""
+
+msgid "User was successfully created."
+msgstr ""
+
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully updated."
+msgstr ""
+
+msgid "User-based escalation rules must have a user with access to the project"
+msgstr ""
+
+msgid "UserAvailability|%{author} %{spanStart}(Busy)%{spanEnd}"
+msgstr ""
+
+msgid "UserAvailability|%{author} (Busy)"
+msgstr ""
+
+msgid "UserAvailability|(Busy)"
+msgstr ""
+
+msgid "UserLists|Add"
+msgstr ""
+
+msgid "UserLists|Add Users"
+msgstr ""
+
+msgid "UserLists|Add users"
+msgstr ""
+
+msgid "UserLists|Cancel"
+msgstr ""
+
+msgid "UserLists|Create"
+msgstr ""
+
+msgid "UserLists|Define a set of users to be used within feature flag strategies"
+msgstr ""
+
+msgid "UserLists|Edit"
+msgstr ""
+
+msgid "UserLists|Edit %{name}"
+msgstr ""
+
+msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
+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 ""
+
+msgid "UserList|created %{timeago}"
+msgstr ""
+
+msgid "UserProfile|(Busy)"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Blocked user"
+msgstr ""
+
+msgid "UserProfile|Bot activity"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Followers"
+msgstr ""
+
+msgid "UserProfile|Following"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Pronounced as: %{pronunciation}"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Retry"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Star projects to track their progress and show your appreciation."
+msgstr ""
+
+msgid "UserProfile|Starred projects"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any followers."
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|This user hasn't starred any projects"
+msgstr ""
+
+msgid "UserProfile|This user is blocked"
+msgstr ""
+
+msgid "UserProfile|This user isn't following other users."
+msgstr ""
+
+msgid "UserProfile|Unconfirmed user"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You are not following other users."
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You do not have any followers."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "UserProfile|at"
+msgstr ""
+
+msgid "UserProfile|made a private contribution"
+msgstr ""
+
+msgid "Username"
+msgstr ""
+
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
+msgid "Username or email"
+msgstr ""
+
+msgid "Username:"
+msgstr ""
+
+msgid "Username: %{username}"
+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 can reactivate their account by signing in."
+msgstr ""
+
+msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
+msgstr ""
+
+msgid "Users in License"
+msgstr ""
+
+msgid "Users or groups set as approvers in the project's or merge request's settings."
+msgstr ""
+
+msgid "Users over License"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Users to exclude from the rate limit"
+msgstr ""
+
+msgid "Users were successfully added."
+msgstr ""
+
+msgid "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 "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
+msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgstr ""
+
+msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
+msgstr ""
+
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
+msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
+msgstr ""
+
+msgid "Valid From"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
+msgid "Validations failed."
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Value Stream Analytics"
+msgstr ""
+
+msgid "Value Stream Analytics can help you determine your team’s velocity"
+msgstr ""
+
+msgid "Value might contain a variable reference"
+msgstr ""
+
+msgid "Value stream"
+msgstr ""
+
+msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{stageCount}+ items"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Average number of deployments to production per day."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Number of new issues created."
+msgstr ""
+
+msgid "ValueStreamAnalytics|There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Total number of deploys to production."
+msgstr ""
+
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
+msgid "ValueStreamEvent|Stage time (median)"
+msgstr ""
+
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
+msgid "Values that contain the %{codeStart}$%{codeEnd} character can be considered a variable reference and expanded. %{docsLinkStart}Learn more.%{docsLinkEnd}"
+msgstr ""
+
+msgid "Variable"
+msgstr ""
+
+msgid "Variable will be masked in job logs."
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables can be:"
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts."
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification concurrency limit"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity."
+msgstr ""
+
+msgid "VerificationReminder|Until then, shared runners will be unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated"
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD minutes on shared runners."
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Verify SAML Configuration"
+msgstr ""
+
+msgid "Verify code"
+msgstr ""
+
+msgid "Verify configuration"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
+msgid "View Documentation"
+msgstr ""
+
+msgid "View Stage: %{title}"
+msgstr ""
+
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
+msgid "View all environments."
+msgstr ""
+
+msgid "View all issues"
+msgstr ""
+
+msgid "View blame"
+msgstr ""
+
+msgid "View blame prior to this change"
+msgstr ""
+
+msgid "View chart"
+msgid_plural "View charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View dependency details for your project"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View downstream pipeline"
+msgstr ""
+
+msgid "View eligible approvers"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View exposed artifact"
+msgid_plural "View %d exposed artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View file @ %{commitSha}"
+msgstr ""
+
+msgid "View full dashboard"
+msgstr ""
+
+msgid "View full log"
+msgstr ""
+
+msgid "View group in admin area"
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View incident details at"
+msgstr ""
+
+msgid "View incident details."
+msgstr ""
+
+msgid "View incident issues."
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View issues"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View job"
+msgstr ""
+
+msgid "View job log"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View logs"
+msgstr ""
+
+msgid "View merge request"
+msgstr ""
+
+msgid "View milestones"
+msgstr ""
+
+msgid "View on %{url}"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View page @ "
+msgstr ""
+
+msgid "View performance dashboard."
+msgstr ""
+
+msgid "View project"
+msgstr ""
+
+msgid "View project in admin area"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View public GPG key"
+msgid_plural "View public GPG keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View seat usage"
+msgstr ""
+
+msgid "View setting"
+msgstr ""
+
+msgid "View supported languages and frameworks"
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "View the latest successful deployment to this environment"
+msgstr ""
+
+msgid "View the performance dashboard at"
+msgstr ""
+
+msgid "View usage details"
+msgstr ""
+
+msgid "View users statistics"
+msgstr ""
+
+msgid "Viewed"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Violation"
+msgstr ""
+
+msgid "Visibility"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Visibility, project features, permissions"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Visit settings page"
+msgstr ""
+
+msgid "Visual Studio Code (HTTPS)"
+msgstr ""
+
+msgid "Visual Studio Code (SSH)"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability report"
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "VulnerabilityChart|%{formattedStartDate} to today"
+msgstr ""
+
+msgid "VulnerabilityChart|Severity"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|(optional) Include the solution to the vulnerability if available."
+msgstr ""
+
+msgid "VulnerabilityManagement|A removed or remediated vulnerability"
+msgstr ""
+
+msgid "VulnerabilityManagement|A true-positive and will fix"
+msgstr ""
+
+msgid "VulnerabilityManagement|A verified true-positive vulnerability"
+msgstr ""
+
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
+msgid "VulnerabilityManagement|An unverified non-confirmed finding"
+msgstr ""
+
+msgid "VulnerabilityManagement|Change status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
+msgstr ""
+
+msgid "VulnerabilityManagement|Create Jira issue"
+msgstr ""
+
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
+
+msgid "VulnerabilityManagement|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityManagement|Read more about related issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Related Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a method"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to fetch related Jira issues. Please check the %{linkStart}Jira integration settings%{linkEnd} and try again."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not get user."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
+msgstr ""
+
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
+msgid "VulnerabilityManagement|Verified as fixed or mitigated"
+msgstr ""
+
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
+msgid "VulnerabilityManagement|Will not fix or a false-positive"
+msgstr ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All statuses"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Resolved"
+msgstr ""
+
+msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
+msgstr ""
+
+msgid "Vulnerability|Activity"
+msgstr ""
+
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
+msgid "Vulnerability|Actual received response is the one received when this fault was detected"
+msgstr ""
+
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
+msgid "Vulnerability|Additional Info"
+msgstr ""
+
+msgid "Vulnerability|Bug Bounty"
+msgstr ""
+
+msgid "Vulnerability|CVSS v3"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Code Review"
+msgstr ""
+
+msgid "Vulnerability|Comments"
+msgstr ""
+
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|Details"
+msgstr ""
+
+msgid "Vulnerability|Detected"
+msgstr ""
+
+msgid "Vulnerability|Detection method"
+msgstr ""
+
+msgid "Vulnerability|Download"
+msgstr ""
+
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
+msgid "Vulnerability|Evidence"
+msgstr ""
+
+msgid "Vulnerability|External Security Report"
+msgstr ""
+
+msgid "Vulnerability|False positive detected"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|GitLab Security Report"
+msgstr ""
+
+msgid "Vulnerability|Identifier"
+msgstr ""
+
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Image"
+msgstr ""
+
+msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
+msgstr ""
+
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Method"
+msgstr ""
+
+msgid "Vulnerability|Namespace"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
+msgid "Vulnerability|Request/Response"
+msgstr ""
+
+msgid "Vulnerability|Scanner Provider"
+msgstr ""
+
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
+msgid "Vulnerability|Security Audit"
+msgstr ""
+
+msgid "Vulnerability|Select a severity"
+msgstr ""
+
+msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Status"
+msgstr ""
+
+msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
+msgstr ""
+
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
+msgid "Vulnerability|Tool"
+msgstr ""
+
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
+msgid "Vulnerability|Unmodified Response"
+msgstr ""
+
+msgid "Vulnerability|View training"
+msgstr ""
+
+msgid "WARNING:"
+msgstr ""
+
+msgid "Wait for the file to load to copy its contents"
+msgstr ""
+
+msgid "Waiting for merge (open and assigned)"
+msgstr ""
+
+msgid "Waiting for performance data"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "Warning"
+msgstr ""
+
+msgid "Warning:"
+msgstr ""
+
+msgid "Warning: Displaying this diagram might cause performance issues on this page."
+msgstr ""
+
+msgid "Warning: Synchronizing LDAP removes direct members' access."
+msgstr ""
+
+msgid "We are currently unable to fetch data for the pipeline header."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this graph."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this pipeline."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
+msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
+msgstr ""
+
+msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We have found the following errors:"
+msgstr ""
+
+msgid "We heard back from your device. You have been authenticated."
+msgstr ""
+
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
+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 ""
+
+msgid "We recommend leaving all SAST analyzers enabled"
+msgstr ""
+
+msgid "We recommend that you buy additional Pipeline minutes to avoid any interruption of service."
+msgstr ""
+
+msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
+msgstr ""
+
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
+msgstr ""
+
+msgid "We would like to inform you that your subscription GitLab Enterprise Edition %{plan_name} is nearing its user limit. You have %{active_user_count} active users, which is almost at the user limit of %{maximum_user_count}."
+msgstr ""
+
+msgid "We'll continuously validate your pipeline configuration. The validation results will appear here."
+msgstr ""
+
+msgid "We'll use this to help surface the right features and information to you."
+msgstr ""
+
+msgid "We're experiencing difficulties and this tab content is currently unavailable."
+msgstr ""
+
+msgid "We've found no vulnerabilities"
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "WebAuthn Devices (%{length})"
+msgstr ""
+
+msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
+msgid "WebIDE|Merge request"
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
+msgstr ""
+
+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 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."
+msgstr ""
+
+msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
+msgstr ""
+
+msgid "WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}"
+msgstr ""
+
+msgid "WebexTeamsService|Webex Teams"
+msgstr ""
+
+msgid "Webhook"
+msgstr ""
+
+msgid "Webhook Logs"
+msgstr ""
+
+msgid "Webhook Settings"
+msgstr ""
+
+msgid "Webhook events will be displayed here."
+msgstr ""
+
+msgid "Webhook:"
+msgstr ""
+
+msgid "Webhooks"
+msgstr ""
+
+msgid "Webhooks Help"
+msgstr ""
+
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential comments"
+msgstr ""
+
+msgid "Webhooks|Confidential issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Failed to connect"
+msgstr ""
+
+msgid "Webhooks|Fails to connect"
+msgstr ""
+
+msgid "Webhooks|Feature flag events"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Member events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
+msgid "Webhooks|Releases events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret token"
+msgstr ""
+
+msgid "Webhooks|Subgroup events"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgstr ""
+
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgstr ""
+
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
+msgstr ""
+
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
+msgstr ""
+
+msgid "Webhooks|Webhook failed to connect"
+msgstr ""
+
+msgid "Webhooks|Webhook fails to connect"
+msgstr ""
+
+msgid "Webhooks|Webhook was automatically disabled"
+msgstr ""
+
+msgid "Webhooks|Wiki page events"
+msgstr ""
+
+msgid "Website:"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Weekday"
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
+msgstr ""
+
+msgid "Welcome to GitLab"
+msgstr ""
+
+msgid "Welcome to GitLab, %{first_name}!"
+msgstr ""
+
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
+msgid "Welcome, %{name}!"
+msgstr ""
+
+msgid "What are CI/CD minutes?"
+msgstr ""
+
+msgid "What are group audit events?"
+msgstr ""
+
+msgid "What are instance audit events?"
+msgstr ""
+
+msgid "What are project audit events?"
+msgstr ""
+
+msgid "What are you searching for?"
+msgstr ""
+
+msgid "What does this command do?"
+msgstr ""
+
+msgid "What is Auto DevOps?"
+msgstr ""
+
+msgid "What is Markdown?"
+msgstr ""
+
+msgid "What is repository mirroring?"
+msgstr ""
+
+msgid "What is squashing?"
+msgstr ""
+
+msgid "What is time tracking?"
+msgstr ""
+
+msgid "What is your job title? (optional)"
+msgstr ""
+
+msgid "What templates can I create?"
+msgstr ""
+
+msgid "What will you use this group for?"
+msgstr ""
+
+msgid "What would you like to do?"
+msgstr ""
+
+msgid "What's new"
+msgstr ""
+
+msgid "When a deployment job is successful, skip older deployment jobs that are still pending."
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
+msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
+msgstr ""
+
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
+msgstr ""
+
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
+
+msgid "When merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
+msgstr ""
+
+msgid "When this merge request is accepted"
+msgid_plural "When these merge requests are accepted"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Which API requests are affected?"
+msgstr ""
+
+msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Who can approve?"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Who will be using GitLab?"
+msgstr ""
+
+msgid "Who will be using this GitLab subscription?"
+msgstr ""
+
+msgid "Who will be using this GitLab trial?"
+msgstr ""
+
+msgid "Who will be using this group?"
+msgstr ""
+
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "Wiki page was successfully created."
+msgstr ""
+
+msgid "Wiki page was successfully deleted."
+msgstr ""
+
+msgid "Wiki page was successfully updated."
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Confluence is enabled"
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Enable the Confluence Wiki integration"
+msgstr ""
+
+msgid "WikiEmpty|Go to Confluence"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your group"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This group has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a group member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "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}."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+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 back to the classic editor?"
+msgstr ""
+
+msgid "WikiPage|Cancel"
+msgstr ""
+
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Get a richer editing experience"
+msgstr ""
+
+msgid "WikiPage|Keep editing"
+msgstr ""
+
+msgid "WikiPage|Learn more."
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Retry"
+msgstr ""
+
+msgid "WikiPage|Save changes"
+msgstr ""
+
+msgid "WikiPage|Switch me back to the classic editor."
+msgstr ""
+
+msgid "WikiPage|Switch to classic editor"
+msgstr ""
+
+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. 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."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+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 the new editor"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wikis"
+msgstr ""
+
+msgid "Wiki|Create New Page"
+msgstr ""
+
+msgid "Wiki|Created date"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
+msgstr ""
+
+msgid "Wiki|Title"
+msgstr ""
+
+msgid "Wiki|View All Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will be created"
+msgstr ""
+
+msgid "Will be mapped to"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With requirements, you can set criteria to check your products against."
+msgstr ""
+
+msgid "With test cases, you can define conditions for your project to meet in determining quality"
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Won't fix / Accept risk"
+msgstr ""
+
+msgid "Work in progress (open and unassigned)"
+msgstr ""
+
+msgid "Work in progress Limit"
+msgstr ""
+
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
+msgstr ""
+
+msgid "WorkItem|Work Items"
+msgstr ""
+
+msgid "Would you like to create a new branch?"
+msgstr ""
+
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write a comment…"
+msgstr ""
+
+msgid "Write a description or drag your files here…"
+msgstr ""
+
+msgid "Write a description…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Write your release notes or drag your files here…"
+msgstr ""
+
+msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
+msgstr ""
+
+msgid "Xcode"
+msgstr ""
+
+msgid "YYYY-MM-DD"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes or No"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, close issue"
+msgstr ""
+
+msgid "Yes, delete project"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You already have pending todo for this alert"
+msgstr ""
+
+msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
+msgstr ""
+
+msgid "You are about to permanently delete this project"
+msgstr ""
+
+msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
+msgstr ""
+
+msgid "You are already a member of this %{member_source}."
+msgstr ""
+
+msgid "You are already impersonating another user"
+msgstr ""
+
+msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are connected to the Prometheus server, but there is currently no data to display."
+msgstr ""
+
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{group_name}. This will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on confidentiality. Only team members with %{strongStart}at least Reporter access%{strongEnd} will be able to see and leave comments on the %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to %{action} a user"
+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 ""
+
+msgid "You are not allowed to reject a user"
+msgstr ""
+
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
+msgid "You are not authorized to delete this site profile"
+msgstr ""
+
+msgid "You are not authorized to perform this action"
+msgstr ""
+
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
+msgid "You are not authorized to update this profile"
+msgstr ""
+
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
+msgid "You are now impersonating %{username}"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You are signed in to GitLab as %{user_link}"
+msgstr ""
+
+msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
+msgstr ""
+
+msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
+msgstr ""
+
+msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
+msgstr ""
+
+msgid "You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
+msgstr ""
+
+msgid "You can also upload existing files from your computer using the instructions below."
+msgstr ""
+
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "You can always change your URL later"
+msgstr ""
+
+msgid "You can always edit this later"
+msgstr ""
+
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
+msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}."
+msgstr ""
+
+msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
+msgstr ""
+
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
+msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
+msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
+msgstr ""
+
+msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
+msgstr ""
+
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
+msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
+
+msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You can invite another group to %{project_name}."
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can notify the app / group or a project by sending them an email notification"
+msgstr ""
+
+msgid "You can now close this window."
+msgstr ""
+
+msgid "You can now export your security dashboard to a CSV report."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original branch."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original project."
+msgstr ""
+
+msgid "You can only %{action} files when you are on a branch"
+msgstr ""
+
+msgid "You can only add up to %{max_contacts} contacts at one time"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only transfer the project to namespaces you manage."
+msgstr ""
+
+msgid "You can only upload one design when dropping onto an existing design."
+msgstr ""
+
+msgid "You can recover this project until %{date}"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can see your chat accounts."
+msgstr ""
+
+msgid "You can set up jobs to only use runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
+msgstr ""
+
+msgid "You cannot %{action} %{state} users."
+msgstr ""
+
+msgid "You cannot access the raw file. Please wait a minute."
+msgstr ""
+
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
+msgid "You cannot impersonate a blocked user"
+msgstr ""
+
+msgid "You cannot impersonate a user who cannot log in"
+msgstr ""
+
+msgid "You cannot impersonate an internal user"
+msgstr ""
+
+msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
+msgstr ""
+
+msgid "You cannot rename an environment after it's created."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+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 can’t edit 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 ""
+
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
+msgid "You do not have permission to approve a member"
+msgstr ""
+
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have permission to update the environment."
+msgstr ""
+
+msgid "You do not have permissions to run the import."
+msgstr ""
+
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any WebAuthn devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You don't have any open merge requests"
+msgstr ""
+
+msgid "You don't have any projects available."
+msgstr ""
+
+msgid "You don't have any recent searches"
+msgstr ""
+
+msgid "You don't have sufficient permission to perform this action."
+msgstr ""
+
+msgid "You don't have write access to the source branch."
+msgstr ""
+
+msgid "You don’t have access to Productivity Analytics in this group"
+msgstr ""
+
+msgid "You don’t have access to Value Stream Analytics for this group"
+msgstr ""
+
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to group %{name}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to project %{name}."
+msgstr ""
+
+msgid "You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}"
+msgstr ""
+
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
+msgid "You have been unsubscribed from this thread."
+msgstr ""
+
+msgid "You have declined the invitation to join %{title} %{name}."
+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 ""
+
+msgid "You have insufficient permissions to create an HTTP integration 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 manage timeline events for this incident"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call rotation from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call schedule from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
+msgid "You have insufficient permissions to update an on-call schedule for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to view shifts for this rotation"
+msgstr ""
+
+msgid "You have more active users than are allowed by your license. Before %{date} GitLab must reconcile your subscription. To complete this process, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
+msgid "You have more active users than are allowed by your license. GitLab must now reconcile your subscription. To complete this process, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have not added any approvers. Start by adding users or groups."
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
+msgstr ""
+
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr ""
+
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
+msgstr ""
+
+msgid "You have unsaved changes"
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must be authenticated to access this path."
+msgstr ""
+
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You must have permission to create a project in a group before forking."
+msgstr ""
+
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
+msgid "You must sign in to search for specific projects."
+msgstr ""
+
+msgid "You must sign in to search for specific terms."
+msgstr ""
+
+msgid "You must solve the CAPTCHA in order to submit"
+msgstr ""
+
+msgid "You must upload a file with the same file name when dropping onto an existing design."
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a device."
+msgstr ""
+
+msgid "You need to set terms to be enforced"
+msgstr ""
+
+msgid "You need to specify both an Access Token and a Host URL."
+msgstr ""
+
+msgid "You need to upload a GitLab project export archive (ending in .gz)."
+msgstr ""
+
+msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
+msgstr ""
+
+msgid "You successfully declined the invitation"
+msgstr ""
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
+msgid "You will be removed from existing projects/groups"
+msgstr ""
+
+msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "You will first need to set up Jira Integration to use this feature."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to create new projects because you have reached your project limit."
+msgstr ""
+
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end} in %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
+msgstr ""
+
+msgid "You're at the first commit"
+msgstr ""
+
+msgid "You're at the last commit"
+msgstr ""
+
+msgid "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "You're receiving this email because of your activity on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been assigned an item on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}."
+msgstr ""
+
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
+msgid "You've rejected %{user}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "YouTube URL or ID"
+msgstr ""
+
+msgid "Your %{group} membership will now expire in %{days}."
+msgstr ""
+
+msgid "Your %{host} account was signed in to from a new location"
+msgstr ""
+
+msgid "Your %{plan} subscription expired on %{expiry_date}"
+msgstr ""
+
+msgid "Your %{plan} subscription expires on %{expiry_date}"
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more details."
+msgstr ""
+
+msgid "Your CSV export has started. It will be emailed to %{email} when complete."
+msgstr ""
+
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV import for project"
+msgstr ""
+
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
+msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now."
+msgstr ""
+
+msgid "Your GitLab account request has been approved!"
+msgstr ""
+
+msgid "Your GitLab group"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your SSH key has expired"
+msgstr ""
+
+msgid "Your SSH key is expiring soon."
+msgstr ""
+
+msgid "Your SSH key was deleted"
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
+msgid "Your To-Do List"
+msgstr ""
+
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your WebAuthn device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your WebAuthn device was registered!"
+msgstr ""
+
+msgid "Your access request to the %{source_type} has been withdrawn."
+msgstr ""
+
+msgid "Your account has been deactivated"
+msgstr ""
+
+msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
+msgstr ""
+
+msgid "Your account has been deactivated. You will not be able to: "
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is locked."
+msgstr ""
+
+msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
+msgstr ""
+
+msgid "Your action succeeded."
+msgstr ""
+
+msgid "Your applications (%{size})"
+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 ""
+
+msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your changes have been successfully committed."
+msgstr ""
+
+msgid "Your comment could not be submitted because %{error}"
+msgstr ""
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+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 current password is required to register a two-factor authenticator app."
+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 ""
+
+msgid "Your device is not compatible with GitLab. Please try another device"
+msgstr ""
+
+msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your file must contain a column named %{codeStart}title%{codeEnd}. A %{codeStart}description%{codeEnd} column is optional. The maximum file size allowed is 10 MB."
+msgstr ""
+
+msgid "Your first project"
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
+msgstr ""
+
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
+msgid "Your instance is approaching its licensed user count"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your license does not support on-call rotations"
+msgstr ""
+
+msgid "Your license does not support on-call schedules"
+msgstr ""
+
+msgid "Your license is valid from"
+msgstr ""
+
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
+msgid "Your message here"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your new %{type}"
+msgstr ""
+
+msgid "Your new access token has been created."
+msgstr ""
+
+msgid "Your new comment"
+msgstr ""
+
+msgid "Your new personal access token has been created."
+msgstr ""
+
+msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
+msgstr ""
+
+msgid "Your password reset token has expired."
+msgstr ""
+
+msgid "Your personal access token has expired"
+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 ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your project will be created at:"
+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 ""
+
+msgid "Your request for access has been queued for review."
+msgstr ""
+
+msgid "Your request to join %{host} has been rejected."
+msgstr ""
+
+msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
+msgstr ""
+
+msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your response has been recorded."
+msgstr ""
+
+msgid "Your search didn't match any commits."
+msgstr ""
+
+msgid "Your search didn't match any commits. Try a different query."
+msgstr ""
+
+msgid "Your search timed out"
+msgstr ""
+
+msgid "Your sign-in page is %{url}."
+msgstr ""
+
+msgid "Your snippets"
+msgstr ""
+
+msgid "Your subscription expired!"
+msgstr ""
+
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
+msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
+msgstr ""
+
+msgid "Your subscription will expire in %{remaining_days} day."
+msgid_plural "Your subscription will expire in %{remaining_days} days."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Your username is %{username}."
+msgstr ""
+
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|If different from Web URL."
+msgstr ""
+
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
+msgstr ""
+
+msgid "Zoom meeting added"
+msgstr ""
+
+msgid "Zoom meeting removed"
+msgstr ""
+
+msgid "[No reason]"
+msgstr ""
+
+msgid "[REDACTED]"
+msgstr ""
+
+msgid "[Redacted]"
+msgstr ""
+
+msgid "`end_time` should not exceed one month after `start_time`"
+msgstr ""
+
+msgid "`start_time` should precede `end_time`"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "about 1 hour"
+msgid_plural "about %d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "access:"
+msgstr ""
+
+msgid "added"
+msgstr ""
+
+msgid "added %{emails}"
+msgstr ""
+
+msgid "added a Zoom call to this issue"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "alert"
+msgstr ""
+
+msgid "allowed to fail"
+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 ""
+
+msgid "already shared with this group"
+msgstr ""
+
+msgid "and"
+msgstr ""
+
+msgid "any-approver for the merge request already exists"
+msgstr ""
+
+msgid "any-approver for the project already exists"
+msgstr ""
+
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "approved by: "
+msgstr ""
+
+msgid "archived"
+msgstr ""
+
+msgid "archived:"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "at"
+msgstr ""
+
+msgid "at risk"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
+msgid "banned user already exists"
+msgstr ""
+
+msgid "blocks"
+msgstr ""
+
+msgid "branch"
+msgid_plural "branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "cURL:"
+msgstr ""
+
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+msgstr ""
+
+msgid "can contain only lowercase letters, digits, and '_'."
+msgstr ""
+
+msgid "can only be changed by a group admin."
+msgstr ""
+
+msgid "can only have one escalation policy"
+msgstr ""
+
+msgid "can't be nil"
+msgstr ""
+
+msgid "can't be solely blank"
+msgstr ""
+
+msgid "can't be the same as the source project"
+msgstr ""
+
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
+msgid "cannot be a date in the past"
+msgstr ""
+
+msgid "cannot be changed"
+msgstr ""
+
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be changed if shared runners are enabled"
+msgstr ""
+
+msgid "cannot be enabled"
+msgstr ""
+
+msgid "cannot be enabled because parent group does not allow it"
+msgstr ""
+
+msgid "cannot be enabled because parent group has shared Runners disabled"
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot be enabled until a valid credit card is on file"
+msgstr ""
+
+msgid "cannot be used for user namespace"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
+msgid "cannot merge"
+msgstr ""
+
+msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}"
+msgstr ""
+
+msgid "ciReport|%{degradedNum} degraded"
+msgstr ""
+
+msgid "ciReport|%{improvedNum} improved"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|%{sameNum} same"
+msgstr ""
+
+msgid "ciReport|: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|API Fuzzing"
+msgstr ""
+
+msgid "ciReport|API fuzzing"
+msgstr ""
+
+msgid "ciReport|All projects"
+msgstr ""
+
+msgid "ciReport|All severities"
+msgstr ""
+
+msgid "ciReport|All tools"
+msgstr ""
+
+msgid "ciReport|Automatically apply the patch in a new branch"
+msgstr ""
+
+msgid "ciReport|Base pipeline codequality artifact not found"
+msgstr ""
+
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: %{strong_start}%{changesFound}%{strong_end} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strong_start}%{changesFound}%{strong_end} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Browser performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Checks"
+msgstr ""
+
+msgid "ciReport|Cluster Image Scanning"
+msgstr ""
+
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
+
+msgid "ciReport|Container Scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|Could not dismiss vulnerability because the associated pipeline no longer exists. Refresh the page and try again."
+msgstr ""
+
+msgid "ciReport|Coverage Fuzzing"
+msgstr ""
+
+msgid "ciReport|Coverage fuzzing"
+msgstr ""
+
+msgid "ciReport|Create Jira issue"
+msgstr ""
+
+msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
+msgstr ""
+
+msgid "ciReport|Create issue"
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Download patch to resolve"
+msgstr ""
+
+msgid "ciReport|Download the patch to apply it manually"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
+msgid "ciReport|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+msgstr ""
+
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|New"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No code quality issues found"
+msgstr ""
+
+msgid "ciReport|RPS"
+msgstr ""
+
+msgid "ciReport|Resolve with merge request"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Secret Detection"
+msgstr ""
+
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Secret detection"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error creating the merge request. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error fetching the codequality report."
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|This report contains all Code Quality issues in the source branch."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|is loading"
+msgstr ""
+
+msgid "ciReport|is loading, errors when loading results"
+msgstr ""
+
+msgid "closed"
+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 ""
+
+msgid "comment"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "commit %{commit_id}"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
+msgid "compliance violation has already been recorded"
+msgstr ""
+
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
+msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "container_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
+msgid "contribute to this project."
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "created"
+msgstr ""
+
+msgid "created %{issuable_created} by %{author}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgo}"
+msgstr ""
+
+msgid "created %{timeAgo} by %{author}"
+msgstr ""
+
+msgid "created by"
+msgstr ""
+
+msgid "data"
+msgstr ""
+
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "days"
+msgstr ""
+
+msgid "default branch"
+msgstr ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy"
+msgstr ""
+
+msgid "design"
+msgstr ""
+
+msgid "detached"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "does not exist"
+msgstr ""
+
+msgid "does not have a supported extension. Only %{extension_list} are supported"
+msgstr ""
+
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
+msgid "download it"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "e.g. %{token}"
+msgstr ""
+
+msgid "element is not a hierarchy"
+msgstr ""
+
+msgid "eligible users"
+msgstr ""
+
+msgid "email '%{email}' is not a verified email."
+msgstr ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
+msgid "ending with a reserved file extension is not allowed."
+msgstr ""
+
+msgid "entries cannot be larger than 255 characters"
+msgstr ""
+
+msgid "entries cannot be nil"
+msgstr ""
+
+msgid "entries cannot contain HTML tags"
+msgstr ""
+
+msgid "environment_id parameter is required when type is container_policy"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
+msgstr ""
+
+msgid "example.com"
+msgstr ""
+
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
+msgstr ""
+
+msgid "expired on %{timebox_due_date}"
+msgstr ""
+
+msgid "expires on %{timebox_due_date}"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
+msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
+msgstr ""
+
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
+msgid "failed to revert associated finding(id=%{finding_id}) to detected"
+msgstr ""
+
+msgid "file"
+msgid_plural "files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "finding is not found or is already attached to a vulnerability"
+msgstr ""
+
+msgid "following"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
+msgstr ""
+
+msgid "for %{link_to_pipeline_ref}"
+msgstr ""
+
+msgid "for %{ref}"
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "fork"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "frontmatter"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
+msgid "group members"
+msgstr ""
+
+msgid "group's CI/CD settings."
+msgstr ""
+
+msgid "groups"
+msgstr ""
+
+msgid "has already been linked to another vulnerability"
+msgstr ""
+
+msgid "has already been taken"
+msgstr ""
+
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
+msgid "has been completed."
+msgstr ""
+
+msgid "has too deep level of nesting"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "http:"
+msgstr ""
+
+msgid "http://www.example.com"
+msgstr ""
+
+msgid "https://bamboo.example.com"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "impersonation token"
+msgstr ""
+
+msgid "impersonation tokens"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "in"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is"
+msgstr ""
+
+msgid "is already associated to a GitLab Issue. New issue will not be associated."
+msgstr ""
+
+msgid "is an invalid IP address range"
+msgstr ""
+
+msgid "is blocked by"
+msgstr ""
+
+msgid "is forbidden by a top-level group"
+msgstr ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not"
+msgstr ""
+
+msgid "is not a descendant of the Group owning the template"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is not allowed for sign-up."
+msgstr ""
+
+msgid "is not allowed for this group."
+msgstr ""
+
+msgid "is not allowed for this project."
+msgstr ""
+
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
+msgid "is not allowed."
+msgstr ""
+
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+msgstr ""
+
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
+msgid "is not valid. The iteration group has to match the iteration cadence group."
+msgstr ""
+
+msgid "is read-only"
+msgstr ""
+
+msgid "is too long (%{current_value}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
+msgid "is too long (maximum is 100 entries)"
+msgstr ""
+
+msgid "is too long (maximum is 1000 entries)"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issues at risk"
+msgstr ""
+
+msgid "issues need attention"
+msgstr ""
+
+msgid "issues on track"
+msgstr ""
+
+msgid "it is larger than %{limit}"
+msgstr ""
+
+msgid "it is stored as a job artifact"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "jigsaw is not defined"
+msgstr ""
+
+msgid "kuromoji custom analyzer"
+msgstr ""
+
+msgid "last commit:"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "leave %{group_name}"
+msgstr ""
+
+msgid "less than a minute"
+msgstr ""
+
+msgid "level: %{level}"
+msgstr ""
+
+msgid "limit of %{project_limit} reached"
+msgstr ""
+
+msgid "load it anyway"
+msgstr ""
+
+msgid "loading"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "merged %{timeAgo}"
+msgstr ""
+
+msgid "metric_id must be unique across a project"
+msgstr ""
+
+msgid "missing"
+msgstr ""
+
+msgid "most recent deployment"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
+
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
+msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
+msgstr ""
+
+msgid "mrWidget|%{mergeError}."
+msgstr ""
+
+msgid "mrWidget|%{mergeError}. Try again."
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
+msgid "mrWidget|Added to the merge train by %{merge_author}"
+msgstr ""
+
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approve additionally"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
+msgid "mrWidget|Cancel auto-merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking if merge request can be merged…"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes issue"
+msgid_plural "mrWidget|Closes issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Create issue to resolve all threads"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Dismiss"
+msgstr ""
+
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
+msgid "mrWidget|Hide %{widget} details"
+msgstr ""
+
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
+
+msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
+msgstr ""
+
+msgid "mrWidget|Jump to first unresolved thread"
+msgstr ""
+
+msgid "mrWidget|Learn more"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mark as ready"
+msgstr ""
+
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
+msgid "mrWidget|Mentions issue"
+msgid_plural "mrWidget|Mentions issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
+msgid "mrWidget|Merging! Changes are being shipped…"
+msgstr ""
+
+msgid "mrWidget|Merging! Changes will land soon…"
+msgstr ""
+
+msgid "mrWidget|Merging! Drum roll, please…"
+msgstr ""
+
+msgid "mrWidget|Merging! Everything's good…"
+msgstr ""
+
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
+msgid "mrWidget|Merging! This is going to be great…"
+msgstr ""
+
+msgid "mrWidget|Merging! We're almost there…"
+msgstr ""
+
+msgid "mrWidget|More information"
+msgstr ""
+
+msgid "mrWidget|Open in Gitpod"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove from merge train"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Revoke approval"
+msgstr ""
+
+msgid "mrWidget|SAST and Secret Detection is not enabled."
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Show %{widget} details"
+msgstr ""
+
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{link} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
+msgstr ""
+
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
+msgid "mrWidget|Your password"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "must be a Debian package"
+msgstr ""
+
+msgid "must be a boolean value"
+msgstr ""
+
+msgid "must be a root namespace"
+msgstr ""
+
+msgid "must be a valid IPv4 or IPv6 address"
+msgstr ""
+
+msgid "must be a valid json schema"
+msgstr ""
+
+msgid "must be after start"
+msgstr ""
+
+msgid "must be an email you have verified"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
+msgid "must be inside the fork network"
+msgstr ""
+
+msgid "must be less than the limit of %{tag_limit} tags"
+msgstr ""
+
+msgid "must be set for a project namespace"
+msgstr ""
+
+msgid "must be unique by status and elapsed time within a policy"
+msgstr ""
+
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
+msgid "my-awesome-group"
+msgstr ""
+
+msgid "my-channel"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "need attention"
+msgstr ""
+
+msgid "needs to be between 10 minutes and 1 month"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "never expires"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "no approvers"
+msgstr ""
+
+msgid "no expiration"
+msgstr ""
+
+msgid "no name set"
+msgstr ""
+
+msgid "no one can merge"
+msgstr ""
+
+msgid "no scopes selected"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "not found"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "on track"
+msgstr ""
+
+msgid "only available on top-level groups."
+msgstr ""
+
+msgid "open issue"
+msgstr ""
+
+msgid "opened %{timeAgo}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "other card matches"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "pending comment"
+msgstr ""
+
+msgid "pending deletion"
+msgstr ""
+
+msgid "per day"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "personal access tokens"
+msgstr ""
+
+msgid "pipeline"
+msgstr ""
+
+msgid "pipeline schedules documentation"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
+msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "pod_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "point"
+msgid_plural "points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "previously merged commits"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "processing"
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "project access token"
+msgstr ""
+
+msgid "project access tokens"
+msgstr ""
+
+msgid "project avatar"
+msgstr ""
+
+msgid "project bots cannot be added to other groups / projects"
+msgstr ""
+
+msgid "project is read-only"
+msgstr ""
+
+msgid "project members"
+msgstr ""
+
+msgid "project name"
+msgstr ""
+
+msgid "project namespace cannot be the parent of another namespace"
+msgstr ""
+
+msgid "projects"
+msgstr ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "reCAPTCHA"
+msgstr ""
+
+msgid "reCAPTCHA helps prevent credential stuffing."
+msgstr ""
+
+msgid "reCAPTCHA private key"
+msgstr ""
+
+msgid "reCAPTCHA site key"
+msgstr ""
+
+msgid "recent activity"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "relates to"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove start date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "removed"
+msgstr ""
+
+msgid "removed a Zoom call from this issue"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "repository:"
+msgstr ""
+
+msgid "required"
+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 ""
+
+msgid "severity|Blocker"
+msgstr ""
+
+msgid "severity|Critical"
+msgstr ""
+
+msgid "severity|High"
+msgstr ""
+
+msgid "severity|Info"
+msgstr ""
+
+msgid "severity|Low"
+msgstr ""
+
+msgid "severity|Major"
+msgstr ""
+
+msgid "severity|Medium"
+msgstr ""
+
+msgid "severity|Minor"
+msgstr ""
+
+msgid "severity|None"
+msgstr ""
+
+msgid "severity|Unknown"
+msgstr ""
+
+msgid "should be an array of %{object_name} objects"
+msgstr ""
+
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show %{count} more"
+msgstr ""
+
+msgid "show fewer"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "smartcn custom analyzer"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} adds or subtracts time already spent."
+msgstr ""
+
+msgid "ssh:"
+msgstr ""
+
+msgid "started a discussion on %{design_link}"
+msgstr ""
+
+msgid "started on %{timebox_start_date}"
+msgstr ""
+
+msgid "starts on %{timebox_start_date}"
+msgstr ""
+
+msgid "structure is too large"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "success"
+msgstr ""
+
+msgid "suggestPipeline|1/2: Choose a template"
+msgstr ""
+
+msgid "suggestPipeline|2/2: Commit your changes"
+msgstr ""
+
+msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
+msgstr ""
+
+msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
+msgstr ""
+
+msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
+msgstr ""
+
+msgid "tag name"
+msgstr ""
+
+msgid "the correct format."
+msgstr ""
+
+msgid "the file"
+msgstr ""
+
+msgid "the following issue(s)"
+msgstr ""
+
+msgid "the wiki"
+msgstr ""
+
+msgid "then"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "this issue cannot be assigned to a confidential epic since it is public"
+msgstr ""
+
+msgid "this issue cannot be made public since it belongs to a confidential epic"
+msgstr ""
+
+msgid "time summary"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "train"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "type must be Debian"
+msgstr ""
+
+msgid "type parameter is missing and is required"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "updated %{timeAgo}"
+msgstr ""
+
+msgid "updated %{time_ago}"
+msgstr ""
+
+msgid "uploads"
+msgstr ""
+
+msgid "user avatar"
+msgstr ""
+
+msgid "user namespace cannot be the parent of another namespace"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "v%{version} published %{timeAgo}"
+msgstr ""
+
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "version %{versionIndex}"
+msgstr ""
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "view the source"
+msgstr ""
+
+msgid "visibility"
+msgstr ""
+
+msgid "vulnerability"
+msgid_plural "vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "vulnerability|Add a comment"
+msgstr ""
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Save comment"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
+msgid "was scheduled to merge after pipeline succeeds by"
+msgstr ""
+
+msgid "wiki page"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
+msgstr ""
+
+msgid "with expiry remaining unchanged at %{old_expiry}"
+msgstr ""
+
+msgid "yaml invalid"
+msgstr ""
+
+msgid "your settings"
+msgstr ""
+
+msgid "{group}"
+msgstr ""
+
+msgid "{project}"
+msgstr ""
+
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 13e17a72b29..5627e5655ad 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: 2022-01-06 17:23\n"
+"PO-Revision-Date: 2022-02-02 15:46\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 4c8ab4554a4..acead49e610 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2022-01-06 17:22\n"
+"PO-Revision-Date: 2022-02-02 15:45\n"
msgid " %{start} to %{end}"
msgstr " %{start} do %{end}"
@@ -132,6 +132,34 @@ msgstr[1] "%d URLe przeskanowane"
msgstr[2] "%d URLi przeskanowanych"
msgstr[3] "%d URLu przeskanowanego"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d zatwierdzajÄ…cy"
@@ -603,6 +631,12 @@ msgstr[1] "%{bold_start}%{count}%{bold_end} otwarte merge requesty"
msgstr[2] "%{bold_start}%{count}%{bold_end} otwartych merge requestów"
msgstr[3] "%{bold_start}%{count}%{bold_end} otwartego merge requesta"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open} Maskowanie:%{code_close} Ukryte w logu zadań. Musi spełnić wymagania maskowania."
@@ -780,6 +814,9 @@ msgstr "aktywność %{group_name}"
msgid "%{group_name} group members"
msgstr "członkowie grupy %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
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}."
@@ -876,6 +913,9 @@ 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 "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr "%{placeholder} nie jest prawidłowym motywem"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "Osobiste tokeny dostępu"
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr "Dowiedz się więcej"
@@ -2211,9 +2242,6 @@ msgstr "Dodaj CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Dodaj CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Dodaj GitLaba do Slacka"
-
msgid "Add Jaeger URL"
msgstr "Dodaj adres URL Jaegera"
@@ -2223,8 +2251,8 @@ msgstr "Dodaj klaster Kubernetes"
msgid "Add LICENSE"
msgstr "Dodaj LICENCJĘ"
-msgid "Add New Node"
-msgstr "Dodaj nowy węzeł"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Dodaj README"
@@ -2238,6 +2266,9 @@ msgstr "Dodaj %{type}"
msgid "Add a GPG key"
msgstr "Dodaj klucz GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Dodaj adres URL Jaeger, aby zastąpić tę stronę linkiem do Twojego serwera Jaeger. Najpierw musisz %{link_start_tag}zainstalować Jaeger%{link_end_tag}."
@@ -2304,6 +2335,9 @@ msgstr "Dodaj zadanie"
msgid "Add an SSH key"
msgstr "Dodaj klucz SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Dodaj istniejące zgłoszenie."
@@ -2421,9 +2455,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Dodaj do Slacka"
-
msgid "Add to board"
msgstr "Dodaj do tablicy"
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Użytkownik zostanie wylogowany"
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr "Zezwól projektom w tej grupie korzystać z Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Zezwalaj na żądania do sieci lokalnej z hook'ów i usług."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Zezwalaj na żądania do sieci lokalnej z hooków systemowych"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Zezwalaj na żądania do sieci lokalnej z webhooków i usług"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Zezwalaj podgrupom na ustawianie własnych reguł uwierzytelniania dwuskładnikowego"
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr "Wystapił błąd"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Wystąpił błąd podczas dodawania szkicu do wątku."
@@ -4041,18 +4075,15 @@ msgstr "Wystąpił błąd podczas pobierania zadań."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Wystąpił błąd podczas wczytywania najnowszego potoku."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Wystąpił błąd podczas pobierania wydań. Spróbuj ponownie."
msgid "An error occurred while fetching this tab."
msgstr "Wystąpił błąd podczas pobierania tej karty."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Wystąpił błąd podczas generowania nazwy użytkownika. Proszę, spróbuj ponownie."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "Wystąpił błąd podczas pobierania danych autouzupełniania. Proszę, odśwież stronę i spróbuj ponownie."
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "Wystąpił błąd podczas pobierania plików dla - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr "Cofnij"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Harmonogram"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Przepraszamy, żadne epiki nie pasują do Twoich wyszukiwań"
-
msgid "Sorry, no projects matched your search"
msgstr "Przepraszamy, żadne projekty nie pasują do Twoich wyszukiwań"
@@ -33790,9 +34238,6 @@ msgstr "Ostatni Kontakt"
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Określ swoją wiadomość, aby aktywować"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr "Subskrybowany"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr "Warunki Użytkowania oraz Polityka Prywatności"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Przetwarzanie pokrycia testowego"
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Certyfikat X509 służy do użycia w przypadku, gdy do komunikacji z zewnętrzną usługą autoryzacji jest wymagany wspólny TLS. Jeśli pozostanie puste, certyfikat serwera będzie nadal sprawdzany podczas uzyskiwania dostępu za pośrednictwem protokołu HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym zajmuje to dłużej, użyj kombinacji klonuj/pchnij."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 "Harmonogram potoków uruchamia procesy w przyszłości, wielokrotnie, dla określonych branch'ów lub znaczników. Te zaplanowane procesy odziedziczą ograniczony dostęp do projektu na podstawie powiązanego użytkownika."
-msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "Klucz prywatny służy do użycia w przypadku, gdy dostarczony jest certyfikat klienta. Ta wartość jest zaszyfrowana w trybie spoczynku."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index e372d5b55a4..652e52cacb9 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr " %{start} até %{end}"
@@ -71,7 +71,7 @@ msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit
msgstr "\"%{repository_name}\" tamanho (%{repository_size}) é maior que o limite de %{limit}."
msgid "#%{issueIid} (closed)"
-msgstr "#%{issueIid} (fechado)"
+msgstr "#%{issueIid} (fechada)"
msgid "#general, #development"
msgstr "#geral, #desenvolvimento"
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL verificada"
msgstr[1] "%d URLs verificadas"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprovador"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} solicitação de mesclagem aberta"
msgstr[1] "%{bold_start}%{count}%{bold_end} solicitações de mesclagem abertas"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Mascarado:%{code_close} Escondidos nos logs de tarefas. Deve corresponder a requisitos de mascaramento."
@@ -564,7 +590,7 @@ msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last
msgstr "%{description}- Evento Sentry: %{errorUrl}- Visto pela primeira vez: %{firstSeen}- Visto pela última vez: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
-msgstr ""
+msgstr "%{doc_link_start}A pesquisa avançada%{doc_link_end} está desativada, pois %{ref_elem} não é a ramificação padrão. %{docs_link}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}A pesquisa avançada%{doc_link_end} está ativada."
@@ -626,6 +652,9 @@ msgstr "atividade de %{group_name}"
msgid "%{group_name} group members"
msgstr "Membros do grupo %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} usa contas gerenciadas por grupo. Você precisa criar uma nova conta do GitLab que será gerenciada por %{group_name}."
@@ -722,6 +751,9 @@ msgstr "%{level_name} não é permitido em um grupo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} não é permitido, pois o projeto de origem do fork possui menor visibilidade."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}Saiba mais%{link_end} sobre cargos."
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr "%{link_start}Inicie o título com %{draft_snippet}%{link_end} para evitar que uma solicitação de mesclagem de código de um trabalho em andamento seja executada antes de estar pronta."
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} não é um tema válido"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} resultados para o termo '%{term}'"
@@ -1108,13 +1143,13 @@ msgid "'%{level}' is not a valid visibility level"
msgstr "'%{level}' não é um nível de visibilidade válido"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "'%{name}' Fluxo de Valor criado"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "Fluxo de valor '%{name}' excluído"
msgid "'%{name}' Value Stream saved"
-msgstr ""
+msgstr "'%{name}' Fluxo de valor salvo"
msgid "'%{source}' is not a import source"
msgstr "'%{source}' não é uma fonte de importação"
@@ -1161,7 +1196,7 @@ msgid "(max size 15 MB)"
msgstr "(tamanho máximo de 15MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(opcional)"
msgid "(removed)"
msgstr "(removido)"
@@ -1181,7 +1216,7 @@ msgid "(we need your current password to confirm your changes)"
msgstr "(precisamos da sua senha atual para confirmar as alterações)"
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* Todos os horários estão em UTC, a menos que especificado"
msgid "*Required"
msgstr "*Obrigatório"
@@ -1689,7 +1724,7 @@ msgid "APIFuzzing|To prevent a security leak, authentication info must be added
msgstr ""
msgid "APIFuzzing|Username for basic authentication"
-msgstr ""
+msgstr "Nome de usuário para autenticação básica"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "Ele não pode ser usado para acessar outros dados."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr "Mantenha este token em segredo. Qualquer pessoa que o tiver poderá acessar objetos estáticos do repositório como se fosse você. Se isso acontecer,%{linkStart} reinicie este token%{linkEnd}."
-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 "Mantenha este token em segredo. Qualquer pessoa que o tiver poderá acessar objetos estáticos do repositório como se fosse você. Se isso acontecer,%{reset_link_start} reinicie este token%{reset_link_end}."
-
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr "AccessTokens|Mantenha este token em segredo. Qualquer pessoa que o tiver poderá criar issues como se fosse você. Se isso acontecer, %{linkStart}redefina o token%{linkEnd}."
-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 "Mantenha este token em segredo. Qualquer pessoa que o tiver poderá criar issues como se fosse você. Se isso acontecer %{link_reset_it}."
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr "Mantenha este token em segredo. Qualquer pessoa que o tenha pode ler a atividade e emitir feeds RSS ou o feed do seu calendário como se fosse você. Se isso acontecer, %{linkStart}redefina o token%{linkEnd}."
-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 "Mantenha este token em segredo. Qualquer pessoa que o tenha pode ler a atividade e emitir feeds RSS ou o feed do seu calendário como se fosse você. Se isso acontecer, %{link_reset_it}."
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "Token de acesso pessoal"
@@ -1871,9 +1897,6 @@ msgstr "Seu token de e-mail de entrada autentica você quando você cria um novo
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 this token"
-msgstr "redefinir este token"
-
msgid "AccessibilityReport|Learn more"
msgstr "Saiba mais"
@@ -1926,7 +1949,7 @@ msgid "AccountValidation|Verification is required to discourage and reduce the a
msgstr ""
msgid "AccountValidation|unsubscribe"
-msgstr ""
+msgstr "cancelar inscrição"
msgid "AccountValidation|you may %{unsubscribe_link} at any time."
msgstr ""
@@ -1956,7 +1979,7 @@ msgid "Active Sessions"
msgstr "Sessões ativas"
msgid "Active chat names (%{count})"
-msgstr ""
+msgstr "Nomes ativos no bate-papo (%{count})"
msgid "Activity"
msgstr "Atividade"
@@ -1979,9 +2002,6 @@ msgstr "Adicionar CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Adicionar CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Adicionar GitLab ao Slack"
-
msgid "Add Jaeger URL"
msgstr "Adicionar URL Jaeger"
@@ -1991,8 +2011,8 @@ msgstr "Adicionar cluster Kubernetes"
msgid "Add LICENSE"
msgstr "Adicionar LICENSE"
-msgid "Add New Node"
-msgstr "Adicionar um novo nó"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Adicionar README"
@@ -2006,6 +2026,9 @@ msgstr "Adicionar um %{type}"
msgid "Add a GPG key"
msgstr "Adicionar chave GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Adicione uma URL Jaeger para substituir esta página com um link para seu servidor Jaeger. Você precisa primeiro %{link_start_tag}instalar Jaeger%{link_end_tag}"
@@ -2072,6 +2095,9 @@ msgstr "Adicionar uma tarefa pendente"
msgid "Add an SSH key"
msgstr "Adicionar chave SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Adicionar uma issue existente"
@@ -2189,9 +2215,6 @@ msgstr "Adicionar system hook"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Adicionar ao Slack"
-
msgid "Add to board"
msgstr "Adicionar ao painel"
@@ -2370,13 +2393,13 @@ msgid "Admin notes"
msgstr "Notas de administração"
msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
-msgstr ""
+msgstr "%{billable_users_link_start}Saiba mais%{billable_users_link_end} sobre o que define um usuário faturável"
msgid "AdminArea|Active users"
msgstr "Usuários ativos"
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
-msgstr ""
+msgstr "Todos os usuários criados na instância, incluindo usuários que não foram %{billable_users_link_start}usuários faturáveis%{billable_users_link_end}."
msgid "AdminArea|Billable users"
msgstr "Usuários passíveis de cobrança"
@@ -2489,6 +2512,12 @@ msgstr "Você parará todas as tarefas. Os processos em execução serão abrupt
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erro ao carregar as estatísticas. Por favor, tente novamente"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2553,7 +2582,7 @@ msgid "AdminSettings|Let's Encrypt email"
msgstr "E-mail de Let's Encrypt"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr ""
+msgstr "Duração máxima de uma sessão para operações Git quando o 2FA está ativado."
msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
msgstr "Novas variáveis CI/CD em projetos e grupos padrão para protegidos."
@@ -2580,7 +2609,7 @@ msgid "AdminSettings|Select to disable public access for Pages sites, which requ
msgstr ""
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr ""
+msgstr "Duração da sessão para operações do Git quando 2FA está ativado (minutos)"
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 ""
@@ -2645,6 +2674,9 @@ msgstr "(Desativado)"
msgid "AdminUsers|(Internal)"
msgstr "(Interno)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Aprovação pendente)"
@@ -2655,7 +2687,7 @@ 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 ""
+msgstr "Um usuário pode validar a si mesmo inserindo um cartão de crédito/débito, ou um administrador pode validar manualmente um usuário."
msgid "AdminUsers|Access"
msgstr "Acesso"
@@ -2681,8 +2713,8 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Administrador"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr "Administradores tem acesso a todos os grupos, projetos e usuários e podem gerenciar todos os recursos nesta instalação."
+msgid "AdminUsers|Administrator"
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administradores"
@@ -2775,7 +2807,7 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "Excluir o usuário e suas contribuições"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "Exportar permissões como CSV (máximo de 100.000 usuários)"
msgid "AdminUsers|External"
msgstr "Externo"
@@ -2807,6 +2839,9 @@ msgstr "É você!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "Saiba mais sobre %{link_start}usuários banidos.%{link_end}"
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Entrar"
@@ -2865,11 +2900,14 @@ msgid "AdminUsers|Sort by"
msgstr "Ordenar por"
msgid "AdminUsers|The user can't access git repositories."
-msgstr ""
+msgstr "O usuário não pode acessar os repositórios git."
msgid "AdminUsers|The user can't log in."
msgstr "O usuário não pode entrar."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "O usuário será desconectado"
@@ -2972,8 +3010,8 @@ msgstr "Você pode banir suas contas no futuro, se necessário."
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr "Você pode reverter o banimento dessas contas no futuro. Os dados permanecerão intactos."
-msgid "AdminUsers|You cannot remove your own admin rights."
-msgstr "Você não pode remover seus próprios direitos de administrador."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "Você deve transferir a propriedade ou excluir os grupos pertencentes a este usuário antes de excluir sua conta"
@@ -3533,22 +3571,13 @@ msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr "Permitir o acesso público a pipelines e detalhes de tarefas, incluindo logs de saída e artefatos."
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Permitir requisições de hooks e serviços para a rede local."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Permitir requisições à rede local a partir de hooks de sistema"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Permitir requisições à rede local de web hooks e serviços"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Permitir que subgrupos configurem suas próprias regras de autenticação de dois fatores"
msgid "Allow this key to push to this repository"
msgstr "Permitir que esta chave faça push para este repositório"
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Ocorreu um erro"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr "Ocorreu um erro ao buscar as tarefas de pipelines."
-
msgid "An error occurred adding a draft to the thread."
msgstr "Ocorreu um erro ao adicionar um rascunho à discussão."
@@ -3809,18 +3835,15 @@ msgstr "Ocorreu um erro ao recuperar as tarefas."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Ocorreu um erro ao recuperar o último pipeline."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Ocorreu um erro ao buscar as releases. Por favor, tente novamente."
msgid "An error occurred while fetching this tab."
msgstr "Ocorreu um erro enquanto busca nesta aba."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Um erro ocorreu ao gerar um nome de usuário. Por favor tente novamente."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "Ocorreu um erro ao obter arquivos para - %{branchId}"
@@ -4112,7 +4135,7 @@ msgid "Anti-spam verification"
msgstr "Verificação anti-spam"
msgid "Any"
-msgstr "Qualquer um"
+msgstr "Qualquer"
msgid "Any %{header}"
msgstr "Qualquer %{header}"
@@ -4257,7 +4280,7 @@ msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
-msgstr ""
+msgstr "Enviar e-mail de confirmação no cadastro"
msgid "ApplicationSettings|Sign-up enabled"
msgstr ""
@@ -4284,7 +4307,7 @@ msgid "ApplicationSettings|domain.com"
msgstr "domínio.com"
msgid "Applications"
-msgstr "Aplicações"
+msgstr "Aplicativos"
msgid "Applied"
msgstr "Aplicado"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Adicionar aprovadores"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr "Todas as verificações"
@@ -4407,9 +4427,6 @@ msgstr "Tipo de aprovador"
msgid "ApprovalRule|Approvers"
msgstr "Aprovadores"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr "Confirmado"
@@ -4419,13 +4436,13 @@ msgstr "Dispensado"
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr "Detectado anteriormente"
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr "Verificações de segurança"
msgid "ApprovalRule|Select All"
msgstr "Selecionar tudo"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Selecionar verificação"
@@ -4482,7 +4502,7 @@ msgstr "Níveis de severidade"
msgid "ApprovalRule|Target branch"
msgstr "Ramificação de destino"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,23 +4514,29 @@ msgstr "Estados de vulnerabilidade"
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "As configurações de solicitação de mesclagem foram atualizadas"
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr "Evitar a aprovação por autor."
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "Evitar aprovações por usuários que adicionarem commits."
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "Evitar a edição de regras de aprovação em solicitações de mesclagem."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Evitar a edição de regras de aprovação em projetos e solicitações de mesclagem."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "Remover todas as aprovações quando commits forem adicionados a ramificação de origem."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
-msgstr "Exigir senha do usuário para aprovar."
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr ""
@@ -4623,6 +4649,9 @@ msgstr "Tem certeza que deseja desarquivar este projeto?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr "Tem certeza de que deseja tentar mesclar?"
@@ -4715,9 +4744,6 @@ msgstr "Você tem certeza de que deseja excluir este item?"
msgid "Are you sure you want to remove this list?"
msgstr "Tem certeza que deseja remover esta lista?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Tem certeza de que deseja redefinir o token SCIM? O provisionamento SCIM irá parar de funcionar até que o novo token seja atualizado."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Você tem certeza que quer reiniciar o token de status de saúde?"
@@ -4797,12 +4823,12 @@ msgid "Ascending"
msgstr "Ascendente"
msgid "Ask again later"
-msgstr "Pergunte novamente mais tarde"
+msgstr "Perguntar novamente mais tarde"
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4839,7 +4865,7 @@ msgid "Assign reviewer(s)"
msgstr "Atribuir revisor(es)"
msgid "Assign severity"
-msgstr ""
+msgstr "Atribuir severidade"
msgid "Assign some issues to this milestone."
msgstr "Atribua alguns issues a este marco."
@@ -5244,6 +5270,9 @@ msgstr "Foto de perfil será removida. Tem certeza?"
msgid "Average per day: %{average}"
msgstr "Média diária: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr "Prêmio adicionado"
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr "Baseado em"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Cuidado. Alterar o espaço de nome do projeto pode ter efeitos colaterais indesejados."
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Abaixo você encontrará todos os grupos que são públicos."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Cobertura semestral de código"
@@ -5418,14 +5453,11 @@ msgstr "%{group_name} está atualmente usando o %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name} você está usando atualmente o %{plan_name}."
-msgid "BillingPlans|Compare all plans"
-msgstr "Comparar todos os planos"
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Parabéns, a sua nova avaliação está ativa."
msgid "BillingPlans|End of availability for the Bronze Plan"
-msgstr ""
+msgstr "Fim da disponibilidade para o plano Bronze"
msgid "BillingPlans|Free upgrade!"
msgstr "Atualização grátis!"
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5473,7 +5502,7 @@ msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "cobrado anualmente em %{price_per_year}"
msgid "BillingPlans|for the remainder of your subscription"
-msgstr ""
+msgstr "para o restante de sua assinatura"
msgid "BillingPlans|frequently asked questions"
msgstr "perguntas frequentes"
@@ -5536,9 +5565,15 @@ msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on sh
msgstr ""
msgid "Billings|Your account has been validated"
+msgstr "A sua conta foi validada."
+
+msgid "Billing|%{user} was successfully approved"
msgstr ""
msgid "Billing|An email address is only visible for users with public emails."
+msgstr "Um endereço de e-mail só é visível para usuários com e-mails públicos."
+
+msgid "Billing|An error occurred while approving %{user}"
msgstr ""
msgid "Billing|An error occurred while getting a billable member details"
@@ -5548,7 +5583,7 @@ msgid "Billing|An error occurred while loading billable members list"
msgstr ""
msgid "Billing|An error occurred while loading pending members list"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar a lista de membros pendentes."
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
@@ -5587,7 +5622,7 @@ msgid "Billing|Project invite"
msgstr "Convite de projeto"
msgid "Billing|Remove user %{username} from your subscription"
-msgstr ""
+msgstr "Remover usuário %{username} da sua assinatura"
msgid "Billing|Toggle seat details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Importar do Bitbucket"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Bloquear usuário"
@@ -5931,18 +5969,12 @@ msgstr "Apagar ramificações que foram mescladas"
msgid "Branches|Delete protected branch"
msgstr "Apagar ramificação protegida"
-msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr "Apagar ramificação protegida '%{branch_name}'?"
-
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
msgstr "Excluir ramificação protegida. Você tem CERTEZA ABSOLUTA disso?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
msgstr "Excluir a ramificação %{strongStart}%{branchName}%{strongEnd} não pode ser desfeito. Você tem certeza?"
-msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "Apagar a ramificação '%{branch_name}' não pode ser desfeito. Você tem certeza?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Apagar ramificações mescladas não pode ser desfeita. Você tem certeza?"
@@ -5958,9 +5990,6 @@ msgstr "Nova ramificação"
msgid "Branches|No branches to show"
msgstr "Nenhuma ramificação 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 "Uma vez que você confirmar e pressionar %{strongStart}%{buttonText},%{strongEnd} isso não poderá ser desfeito ou recuperado."
@@ -6009,15 +6038,6 @@ msgstr "A ramificação 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 "Essa ramificação não foi mesclado para %{defaultBranchName}. Para evitar perca de dados, considere fazer o merge dessa ramificação antes de deletá-lo."
-msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr "Essa ramificação não foi mesclado para '%{default_branch}'."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Para evitar perda de dados, considere fazer um merge dessa branch antes de apagá-la."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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."
@@ -6036,9 +6056,6 @@ msgstr "Você está prestes a excluir permanentemente a ramificação %{strongSt
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr "Você está prestes a excluir permanentemente a ramificação protegida %{strongStart}%{branchName}.%{strongEnd}"
-msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "Você irá apagar irreparavelmente a branch protegida '%{branch_name}'."
-
msgid "Branches|diverged from upstream"
msgstr "divergido do upstream"
@@ -6136,7 +6153,7 @@ msgid "BulkImport|Import selected"
msgstr "Importar selecionado"
msgid "BulkImport|Importing the group failed."
-msgstr ""
+msgstr "Falha na importação do grupo."
msgid "BulkImport|Last imported to %{link}"
msgstr "Última importação para %{link}"
@@ -6234,6 +6251,15 @@ msgstr "Ao autenticar com uma conta vinculada a um endereço de e-mail corporati
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Por padrão, todos os projetos e grupos usarão as configurações de notificações globais."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -6299,9 +6325,21 @@ msgstr "Estatísticas de versão"
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr "Adicione um %{base_domain_link_start}domínio base%{link_end} para o seu %{kubernetes_cluster_link_start}cluster Kubernetes%{link_end} para que a sua estratégia de deploy funcione."
@@ -6417,10 +6455,10 @@ msgid "CampfireService|From the end of the room URL."
msgstr "Do final da URL da sala."
msgid "CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}"
-msgstr ""
+msgstr "Envia notificações sobre eventos push para salas de bate-papo do Campfire. %{docs_link}"
msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
-msgstr ""
+msgstr "O subdomínio %{code_open}.campfirenow.com%{code_close}"
msgid "Can be manually deployed to"
msgstr "Pode ser implantado manualmente para"
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Não pode ser mesclado automaticamente"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Não é possível criar o relatório de abuso. O usuário foi excluído."
@@ -6729,7 +6770,7 @@ msgid "ChangeTypeAction|This will create a new commit in order to revert the exi
msgstr "Isso criará um novo commit para reverter as mudanças existentes."
msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
-msgstr ""
+msgstr "Suas mudanças serão confirmadas para %{branchName} porque a sua solicitação de mesclagem está aberta."
msgid "Changed assignee(s)."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Endereço de cobrança"
@@ -7092,6 +7136,9 @@ msgstr "Cherry-pick esse merge request"
msgid "Child"
msgstr "Filho"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "O épico filho não existe."
@@ -7392,15 +7439,6 @@ msgstr "Clique para esconder"
msgid "Click to reveal"
msgstr "Clique para revelar"
-msgid "Client authentication certificate"
-msgstr "Certificado de autenticação do cliente"
-
-msgid "Client authentication key"
-msgstr "Chave de autenticação do cliente"
-
-msgid "Client authentication key password"
-msgstr "Senha da chave de autenticação do cliente"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr "Fechado: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Fecha este %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Cluster"
@@ -7521,23 +7565,23 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr "%{number} de %{total} agentes"
+msgid "ClusterAgents|%{number} of %{total} Agents"
+msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
-msgstr ""
+msgstr "%{number} de %{total} cluster conectado por meio de certificados de cluster"
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon}Conectado"
msgid "ClusterAgents|%{titleIcon}Not connected"
-msgstr ""
+msgstr "%{titleIcon}Não conectado"
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} criado"
msgid "ClusterAgents|%{tokenName} revoked"
-msgstr ""
+msgstr "%{tokenName} revogado"
msgid "ClusterAgents|Access tokens"
msgstr "Tokens de acesso"
@@ -7546,7 +7590,7 @@ msgid "ClusterAgents|Actions"
msgstr "Ações"
msgid "ClusterAgents|Advanced installation methods"
-msgstr ""
+msgstr "Métodos avançados de instalação"
msgid "ClusterAgents|Agent"
msgstr "Agente"
@@ -7566,8 +7610,8 @@ msgstr "Agente nunca conectado ao GitLab"
msgid "ClusterAgents|All"
msgstr "Todos"
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr "Ocorreu um erro ao carregar seu GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr "Ocorreu um erro ao carregar seu agente."
@@ -7596,14 +7640,14 @@ msgstr "Conectar um cluster existente"
msgid "ClusterAgents|Connect with a certificate"
msgstr "Conectar com o certificado"
-msgid "ClusterAgents|Connect with the Agent"
-msgstr "Conectar com o Agente"
+msgid "ClusterAgents|Connect with agent"
+msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
msgstr "Conectar com o GitLab Agent"
msgid "ClusterAgents|Connect your cluster through the Agent"
-msgstr ""
+msgstr "Conecte seu cluster através do agente"
msgid "ClusterAgents|Connected"
msgstr "Conectado"
@@ -7642,7 +7686,7 @@ msgid "ClusterAgents|Event occurred"
msgstr ""
msgid "ClusterAgents|Failed to register an agent"
-msgstr ""
+msgstr "Falha ao registrar um agente"
msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -7653,14 +7697,17 @@ msgstr "GitLab Agent"
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr "GitLab Agent para Kubernetes"
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr "Ir para o repositório de arquivos"
msgid "ClusterAgents|How to register an agent?"
msgstr "Como registrar um agente?"
-msgid "ClusterAgents|Install a new agent"
-msgstr "Instalar um novo agente"
+msgid "ClusterAgents|Install new Agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Última conexão %{timeAgo}."
@@ -7686,8 +7733,8 @@ msgstr "Nunca"
msgid "ClusterAgents|Never connected"
msgstr "Nunca conectado"
-msgid "ClusterAgents|No agents"
-msgstr "Sem agentes"
+msgid "ClusterAgents|No Agents"
+msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr "Nenhum cluster conectado por meio de certificados de cluster"
@@ -7713,6 +7760,18 @@ msgstr "Registrando o agente"
msgid "ClusterAgents|Registration token"
msgstr "Token de registro"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr "Segurança"
@@ -7725,6 +7784,9 @@ msgstr "Selecione um agente"
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,14 +7810,14 @@ msgstr "Este agente não tem tokens"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
-msgstr "Para instalar um novo agente, primeiro inclua o arquivo de configuração do agente neste repositório. %{linkStart}Qual é o arquivo de configuração do agente?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
-msgstr ""
+msgstr "Token criado por %{userName}"
msgid "ClusterAgents|Token revoked by %{userName}"
-msgstr ""
+msgstr "Token revogado por %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Usuário desconhecido"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8229,7 +8294,7 @@ msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "O número de nós deve ser um valor numérico."
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
-msgstr ""
+msgstr "Por favor, insira a informação de acesso para o seu cluster Kubernetes. Se precisar de ajuda, você pode ser a nossa %{linkStart}documentação%{linkEnd} em Kubernetes"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Por favor, tenha certeza que sua conta no Google cumpre com os requisitos:"
@@ -8649,7 +8714,7 @@ msgid "ComboSearch is not defined"
msgstr "ComboSearch não está definido"
msgid "Comma-separated list of email addresses."
-msgstr ""
+msgstr "Lista de endereços de e-mail separados por vírgula."
msgid "Comma-separated list of users allowed to exceed the rate limit."
msgstr ""
@@ -8716,8 +8781,11 @@ msgstr "Commit (ao editar mensagem do commit)"
msgid "Commit Message"
msgstr "Mensagem de Commit"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
-msgstr "Fazer commit das alterações"
+msgstr "Confirmar mudanças"
msgid "Commit deleted"
msgstr "Commit excluído"
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Componente"
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr "Configurar rastreamento"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Configure um arquivo %{codeStart}.gitlab-webide.yml%{codeEnd} no %{codeStart}.gitLab%{codeEnd} para começar a usar o Terminal Web. %{helpStart}Saiba mais.%{helpEnd}"
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr "Configure permissões avançadas, armazenamento de arquivos grandes e configurações de autenticação de dois fatores."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
+msgstr ""
msgid "Configure existing installation"
msgstr "Configurar instalação existente"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "Configurar espelhamento de repositório."
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configurar a forma como o usuário cria uma nova conta."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "Configure quais listas são mostradas para qualquer pessoa que visita este painel"
msgid "Confirm"
msgstr "Confirmar"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Confirmar a nova senha"
@@ -9637,7 +9723,7 @@ msgstr "Controle e-mails vinculados à sua conta"
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr "Ações"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr "Corpus são usados em testes de fuzz como fonte de mutação para melhorar testes futuros."
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr "Nome do corpus"
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr "Último uso"
msgid "CorpusManagement|Latest Job:"
msgstr "Última tarefa:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr "Novo envio"
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "Não foi possível encontrar o design."
@@ -9895,14 +9996,17 @@ msgstr "Não foi possível remover o gatilho."
msgid "Could not restore the group"
msgstr "Não foi possível restaurar o grupo"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "Não foi possível revogar o token de representação %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "Não foi possível revogar o token de acesso pessoal %{personal_access_token_name}."
-msgid "Could not revoke project access token %{project_access_token_name}."
-msgstr "Não foi possível revogar o token de acesso do projeto %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
msgid "Could not save group ID"
msgstr "Não foi possível salvar o ID do grupo"
@@ -9974,7 +10078,7 @@ msgid "Create a new branch"
msgstr "Criar uma nova branch"
msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
-msgstr ""
+msgstr "Crie um novo arquivo, pois ainda não há arquivos. Depois, você poderá confirmar suas mudanças."
msgid "Create a new issue"
msgstr "Criar uma nova issue"
@@ -10045,6 +10149,9 @@ msgstr "Crie uma issue para resolver todos os tópicos"
msgid "Create iteration"
msgstr "Criar interação"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "Criar lista"
@@ -10070,7 +10177,7 @@ msgid "Create new CI/CD pipeline"
msgstr "Criar novo pipeline CI/CD"
msgid "Create new Value Stream"
-msgstr ""
+msgstr "Criar novo fluxo de valor"
msgid "Create new branch"
msgstr "Criar novo branch"
@@ -10151,7 +10258,7 @@ msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (padrão)"
msgid "CreateValueStreamForm|'%{name}' Value Stream created"
-msgstr ""
+msgstr "%{name}' Fluxo de Valor criado"
msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
msgstr ""
@@ -10214,7 +10321,7 @@ msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
-msgstr ""
+msgstr "O nome é obrigatório"
msgid "CreateValueStreamForm|New stage"
msgstr "Novo estágio"
@@ -10238,7 +10345,7 @@ msgid "CreateValueStreamForm|Restore stage"
msgstr "Restaurar estágio"
msgid "CreateValueStreamForm|Save value stream"
-msgstr ""
+msgstr "Salvar fluxo de valor"
msgid "CreateValueStreamForm|Select end event"
msgstr "Selecionar evento de término"
@@ -10303,6 +10410,9 @@ msgstr "Criado por mim"
msgid "Created by:"
msgstr "Criado por:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "Data de criação"
@@ -10403,13 +10513,13 @@ msgid "Crm|Last name"
msgstr "Sobrenome"
msgid "Crm|New Organization"
-msgstr ""
+msgstr "Nova organização"
msgid "Crm|New contact"
msgstr "Novo contato"
msgid "Crm|New organization"
-msgstr ""
+msgstr "Nova organização"
msgid "Crm|No contacts found"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Data"
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr "Frequência de implantação"
-msgid "DORA4Metrics|Lead time"
-msgstr "Tempo de espera"
+msgid "DORA4Metrics|Lead time for changes"
+msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr "Não foi possível criar o perfil da verificação. Por favor, tente nov
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr "Verificações de DAST"
-
msgid "DastProfiles|Debug messages"
msgstr "Mensagens de depuração"
@@ -10979,9 +11083,6 @@ msgstr "Novo perfil de site"
msgid "DastProfiles|No scanner profiles created yet"
msgstr "Nenhum perfil de verificação criado ainda"
-msgid "DastProfiles|No scans saved yet"
-msgstr "Nenhuma verificação salva ainda"
-
msgid "DastProfiles|No site profiles created yet"
msgstr "Nenhum perfil de site criado ainda"
@@ -11009,9 +11110,6 @@ msgstr "Cabeçalhos de requisição"
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr "Executar verificação"
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr "Salvar configurações comumente usadas para sites de destino e especifi
msgid "DastProfiles|Save profile"
msgstr "Salvar perfil"
-msgid "DastProfiles|Saved Scans"
-msgstr "Verificações salvas"
-
-msgid "DastProfiles|Scan"
-msgstr "Verificar"
-
msgid "DastProfiles|Scan mode"
msgstr "Modo de verificação"
@@ -11039,9 +11131,6 @@ msgstr "Perfis de verificação"
msgid "DastProfiles|Scanner name"
msgstr "Nome da verificação"
-msgid "DastProfiles|Schedule"
-msgstr "Agendamento"
-
msgid "DastProfiles|Select branch"
msgstr "Selecionar branch"
@@ -11063,9 +11152,6 @@ msgstr "Tipo de site"
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr "Alvo"
-
msgid "DastProfiles|Target URL"
msgstr "URL alvo"
@@ -11216,10 +11302,10 @@ msgid "Database update failed"
msgstr "Falha na atualização do banco de dados"
msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
-msgstr ""
+msgstr "%{linkOpen}Chave da API%{linkClose} usada para autenticação com Datadog."
msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
-msgstr ""
+msgstr "(Avançado) O URL completo do seu site de Datadog."
msgid "DatadogIntegration|API URL"
msgstr "URL da API"
@@ -11335,9 +11421,6 @@ msgstr "Branch padrão e branches protegidos"
msgid "Default branch protection"
msgstr "Proteção padrão de ramificação"
-msgid "Default classification label"
-msgstr "Etiqueta de classificação padrão"
-
msgid "Default delayed project deletion"
msgstr "Atraso padrão para exclusão de projeto"
@@ -11561,13 +11644,13 @@ msgid "DeleteProject|Failed to restore wiki repository. Please contact the admin
msgstr "Falha ao restaurar o repositório wiki. Por favor, contate o administrador."
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "%{name}' Fluxo de Valor excluído"
msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
-msgstr ""
+msgstr "Você tem certeza que deseja excluir o fluxo de valor \"%{name}\"?"
msgid "DeleteValueStream|Delete %{name}"
-msgstr ""
+msgstr "Excluir %{name}"
msgid "Deleted"
msgstr "Excluído"
@@ -11579,10 +11662,10 @@ msgid "Deleted projects cannot be restored!"
msgstr "Projetos excluídos não podem ser restaurados!"
msgid "Deletes the source branch"
-msgstr ""
+msgstr "Excluir ramificação de origem"
msgid "Deletes the source branch."
-msgstr ""
+msgstr "Excluir ramificação de origem"
msgid "Deleting"
msgstr "Excluíndo"
@@ -11764,6 +11847,9 @@ msgstr[1] "Implantações"
msgid "Deploy Keys"
msgstr "Chave de implantação"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Implantar em..."
@@ -11915,7 +12004,7 @@ msgid "DeployTokens|Expires"
msgstr "Expira"
msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
-msgstr ""
+msgstr "Os tokens de implantação do grupo permitem acesso aos pacotes, repositórios e imagens de registro dentro do grupo."
msgid "DeployTokens|Name"
msgstr "Nome"
@@ -11991,9 +12080,39 @@ msgstr[1] "%{deployments} ambientes impactados."
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "cancelado"
@@ -12465,10 +12584,10 @@ msgid "Direct member"
msgstr "Membro direto"
msgid "Direct non-authenticated users to this page."
-msgstr ""
+msgstr "Direcionar usuários não autenticados para esta página."
msgid "Direct users to this page after they sign out."
-msgstr ""
+msgstr "Direcionar usuários para esta página depois que eles saírem."
msgid "Direction"
msgstr "Direção"
@@ -12480,7 +12599,7 @@ msgid "Disable"
msgstr "Desabilitar"
msgid "Disable Elasticsearch until indexing completes."
-msgstr ""
+msgstr "Desativar o Elasticsearch até que a indexação seja concluída."
msgid "Disable Two-factor Authentication"
msgstr "Desativar a autenticação de dois fatores"
@@ -12554,9 +12673,6 @@ msgstr "Recursos de segurança, integrados ao seu ciclo de vida de desenvolvimen
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr "Veja os outros recursos do %{linkStart}plano ultimate%{linkEnd}"
-msgid "Discover|Send feedback"
-msgstr "Enviar feedback"
-
msgid "Discover|Start a free trial"
msgstr "Testar"
@@ -12622,7 +12738,7 @@ msgstr "Exibir fonte"
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12698,7 +12814,7 @@ msgid "Download CSV"
msgstr "Baixar CSV"
msgid "Download PDF"
-msgstr ""
+msgstr "Baixar PDF"
msgid "Download artifacts"
msgstr "Baixar artefatos"
@@ -12817,7 +12933,7 @@ msgstr "Editar comentário"
msgid "Edit Deploy Key"
msgstr "Editar chave de implantação"
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13019,7 +13135,7 @@ msgid "Email display name"
msgstr "Nome de exibição no e-mail"
msgid "Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "E-mail do GitLab - e-mail de usuários diretamente da área do administrador. %{link_start}Saiba mais%{link_end}."
msgid "Email not verified. Please verify your email in Salesforce."
msgstr "E-mail não verificado. Por favor, verifique o seu email no Salesforce."
@@ -13063,6 +13179,9 @@ msgstr "Não conseguimos descobrir qual usuário corresponde ao e-mail. Por favo
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "Não conseguimos encontrar o projeto. Por favor, verifique se há algum erro de digitação."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Você não tem permissão para realizar esta ação. Se você acredita que isso é um erro, entre em contato com um membro da equipe."
@@ -13070,10 +13189,10 @@ msgid "EmailError|Your account has been blocked. If you believe this is in error
msgstr "Sua conta foi bloqueada. Se você acredita que isso é um erro, entre em contato com um membro da equipe."
msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
-msgstr ""
+msgstr "%{emails} será notificado do seu comentário."
msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
-msgstr ""
+msgstr "%{emails}, %{andMore} será notificado do seu comentário."
msgid "EmailParticipantsWarning|and %{moreCount} more"
msgstr "e %{moreCount} mais"
@@ -13172,10 +13291,10 @@ msgid "Enable Spam Check via external API endpoint"
msgstr ""
msgid "Enable What's new: All tiers"
-msgstr ""
+msgstr "Ativar novidades: Todos os níveis"
msgid "Enable What's new: Current tier only"
-msgstr ""
+msgstr "Ativar novidades: Somente o nível atual"
msgid "Enable a Prometheus endpoint that exposes health and performance statistics. The Health Check menu item appears in the Monitoring section of the Admin Area. Restart required."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr "Ativar autenticação"
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "Ativar controle de classificação usando um serviço externo"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Ativar modo de manutenção"
@@ -13279,6 +13398,12 @@ msgstr "Ativar reCAPTCHA para login."
msgid "Enable repository checks"
msgstr "Ativar as verificações de repositório"
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr "Ativar executores compartilhados para todos os projetos e subgrupos neste grupo."
@@ -13357,9 +13482,6 @@ msgstr "Termina em"
msgid "Ends: %{endsAt}"
msgstr "Termina em: %{endsAt}"
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr "Forçar expiração de chave SSH"
@@ -13397,7 +13519,7 @@ msgid "Enter any color or choose one of the suggested colors below."
msgstr ""
msgid "Enter any color."
-msgstr ""
+msgstr "Digite qualquer cor."
msgid "Enter at least three characters to search"
msgstr "Digite pelo menos três caracteres para pesquisar"
@@ -13408,6 +13530,9 @@ msgstr "Digite o seu URL do servidor do Bitbucket e o token de acesso pessoal ab
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "Informe o URL do servidor do Phabricator e o token de acesso pessoal abaixo"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Digite as URLs de solicitações de mesclagem"
@@ -13531,7 +13656,7 @@ msgid "EnvironmentsDashboard|The environments dashboard provides a summary of ea
msgstr "O dashboard de ambientes fornece um resumo do status dos ambientes de cada projeto, incluindo status de pipelines e alertas."
msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Esse painel exibe 3 ambientes por projeto e está vinculado ao painel de operações. Quando você adiciona ou remove um projeto de um painel, o GitLab adiciona ou remove o projeto do outro. %{linkStart}Mais informações%{linkEnd}"
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr "Parar ambiente"
msgid "Environments|Stopping %{environmentName}"
msgstr "Parar %{environmentName}"
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr "por %{avatar}"
msgid "Environments|protected"
msgstr "protegido"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Épico"
@@ -13771,7 +13902,7 @@ msgid "Epics|Enter a title for your epic"
msgstr "Digite um título para o seu épico"
msgid "Epics|Leave empty to inherit from milestone dates"
-msgstr ""
+msgstr "Deixe em branco para herdar as datas do marco"
msgid "Epics|No start date – %{dueDate}"
msgstr "Sem data de início - %{dueDate}"
@@ -14495,9 +14626,6 @@ msgstr "Exporte a variável para pipelines em execução apenas em branches e ta
msgid "Exported requirements"
msgstr "Requisitos exportados"
-msgid "External Classification Policy Authorization"
-msgstr "Autorização de Política de Classificação Externa"
-
msgid "External ID"
msgstr "ID externo"
@@ -14507,15 +14635,9 @@ msgstr "URL externo"
msgid "External User:"
msgstr "Usuário externo:"
-msgid "External authentication"
-msgstr "Autenticação externa"
-
msgid "External authorization denied access to this project"
msgstr "Autorização externa negou acesso a este projeto"
-msgid "External authorization request timeout"
-msgstr "A requisição de autorização externa esgotou o tempo limite"
-
msgid "External storage URL"
msgstr "URL do armazenamento externo"
@@ -14531,6 +14653,54 @@ msgstr "Etiqueta de classificação"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Quando nenhum etiqueta de classificação está definida, a etiqueta padrão `%{default_label}` será usada."
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr "alha ao criar o framework"
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr "IDs de usuário"
msgid "FeatureFlag|User List"
msgstr "Lista de usuário"
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Fev"
@@ -15149,12 +15308,6 @@ msgstr "Filtro"
msgid "Filter by"
msgstr "Filtrar por"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrar por %{issuable_type} que estão atualmente fechados."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr "Erros encontrados em seu %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erros encontrados em seu .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr "Configurações gerais"
msgid "Generate a default set of labels"
msgstr "Gerar etiquetas padrão"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Gerar chave"
@@ -15590,29 +15749,32 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Nós do Geo"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
-msgid "Geo|%{component} synced"
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
msgstr ""
+msgid "Geo|%{component} synced"
+msgstr "%{component} sincronizado"
+
msgid "Geo|%{component} verified"
-msgstr ""
+msgstr "%{component} verificado"
msgid "Geo|%{label} can't be blank"
-msgstr ""
+msgstr "%{label} não pode estar em branco"
msgid "Geo|%{label} should be between 1-999"
-msgstr ""
+msgstr "%{label} deve estar entre 1-999"
msgid "Geo|%{name} is scheduled for forced re-download"
msgstr "%{name} está agendado para forçar download novamente"
@@ -15638,6 +15800,9 @@ msgstr "Adicionar site"
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Falha"
@@ -15714,7 +15882,7 @@ msgid "Geo|Geo supports replication of many data types."
msgstr ""
msgid "Geo|Go to the primary site"
-msgstr ""
+msgstr "Ir para o site primário"
msgid "Geo|Healthy"
msgstr "Saudável"
@@ -15729,7 +15897,7 @@ msgid "Geo|In sync"
msgstr "Em sincronia"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "Geo|Last event ID from primary"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr "Próxima sincronização programada às"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Ainda não sincronizado"
@@ -15780,12 +15942,15 @@ msgid "Geo|Nothing to checksum"
msgstr ""
msgid "Geo|Nothing to synchronize"
-msgstr ""
+msgstr "Nada para sincronizar"
msgid "Geo|Nothing to verify"
msgstr "Nada para verificar"
msgid "Geo|Offline"
+msgstr "Off-line"
+
+msgid "Geo|Open replications"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15821,16 +15986,19 @@ msgstr "Baixar novamente"
msgid "Geo|Remove"
msgstr "Remover"
-msgid "Geo|Remove entry"
+msgid "Geo|Remove %{nodeType} site"
msgstr ""
-msgid "Geo|Remove node"
-msgstr "Remover nó"
+msgid "Geo|Remove entry"
+msgstr "Remover entrada"
+
+msgid "Geo|Remove site"
+msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr "Detalhes da replicação"
-msgid "Geo|Replication details"
-msgstr "Detalhes da replicação"
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15861,13 +16026,13 @@ msgid "Geo|Resync"
msgstr "Ressincronizar"
msgid "Geo|Resync all"
-msgstr ""
+msgstr "Ressincronizar todos"
msgid "Geo|Resync all %{replicableType}"
msgstr ""
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "Ressincronizar todos os projetos"
msgid "Geo|Retry count"
msgstr "Contagem de retentativas"
@@ -15876,10 +16041,10 @@ msgid "Geo|Reverify"
msgstr "Verificar novamente"
msgid "Geo|Reverify all"
-msgstr ""
+msgstr "Reverificar todos"
msgid "Geo|Reverify all projects"
-msgstr ""
+msgstr "Reverificar todos os projetos"
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary site."
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr "Site secundário"
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr "O status do site foi atualizado em %{timeAgo}."
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr "secundário"
msgid "Get a free instance review"
msgstr "Obter gratuitamente uma instância de revisão"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16083,7 +16257,7 @@ msgid "GitLab"
msgstr "GitLab"
msgid "GitLab / Unsubscribe"
-msgstr ""
+msgstr "GitLab / Cancelar inscrição"
msgid "GitLab API"
msgstr "GitLab API"
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr "GitLab para Slack"
-
msgid "GitLab group: %{source_link}"
msgstr "Grupo do GitLab: %{source_link}"
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "Membro do GitLab ou endereço de e-mail"
@@ -16340,6 +16514,9 @@ msgstr "URL do Gitpod"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr "Voltar para a página anterior"
@@ -16646,6 +16826,9 @@ msgstr "O grupo %{group_name} foi agendado para exclusão."
msgid "Group %{group_name} was successfully created."
msgstr "O grupo %{group_name} foi criado com sucesso."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Status do LFS do grupo Git:"
@@ -16664,6 +16847,9 @@ msgstr "O grupo SAML deve ser habilitado para testar"
msgid "Group URL"
msgstr "URL do grupo"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr "Grupo de tarefas por"
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Os mantenedores podem registrar grupos de executores em %{link}"
-
msgid "Group members"
msgstr "Membros do grupo"
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr "Conteúdo da visão geral do grupo"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr "Os minutos do pipeline do grupo foram redefinidos com sucesso."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr "Projetos do grupo"
-
msgid "Group requires separate account"
msgstr "Grupo requer uma conta separada"
@@ -16776,7 +16959,7 @@ msgid "Group runners"
msgstr "Executores de grupo"
msgid "Group runners can be managed with the %{link}."
-msgstr ""
+msgstr "Os executores de grupo podem ser gerenciados com o %{link}."
msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
msgstr "O compartilhamento de grupo fornece acesso a todos os membros do grupo (incluindo membros que herdaram a associação ao grupo de um grupo pai)."
@@ -16791,7 +16974,7 @@ msgid "Group was successfully updated."
msgstr "O grupo foi atualizado com sucesso."
msgid "Group wikis"
-msgstr ""
+msgstr "Grupo de wikis"
msgid "Group: %{group_name}"
msgstr "Grupo: %{group_name}"
@@ -17009,18 +17192,12 @@ msgstr "Configurações de entrada única SAML"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "URL do endpoint de API de SCIM"
-
msgid "GroupSAML|SCIM Token"
msgstr "Token de SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Impressão digital SHA1 do certificado de assinatura de token SAML. Obtenha isso do seu provedor de identidade, onde ele também pode ser chamado de \"Thumbprint\"."
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "O token SCIM agora está oculto. Para ver o valor do token novamente, você precisa "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Seu token SCIM"
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,8 +17252,11 @@ msgstr "Pesquisar grupos"
msgid "GroupSelect|Select a group"
msgstr "Selecionar grupos"
-msgid "GroupSettings|Allow project access token creation"
-msgstr "Permitir a criação de token de acesso ao projeto"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
+msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
msgstr "Aplicado a todos os subgrupos, a menos que seja substituído por um proprietário do grupo. Os grupos já adicionados ao projeto perdem o acesso."
@@ -17126,6 +17303,9 @@ msgstr "Desativar notificações por e-mail"
msgid "GroupSettings|Disable group mentions"
msgstr "Desabilitar menções de grupo"
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr "Ativar exclusão atrasada do projeto"
@@ -17136,7 +17316,7 @@ msgid "GroupSettings|If not specified at the group or instance level, the defaul
msgstr "Se não for especificado no nível de grupo ou instância, o padrão é %{default_initial_branch_name}. Não afeta os repositórios existentes."
msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
-msgstr ""
+msgstr "Se a visibilidade do grupo pai for menor que a visibilidade atual do grupo, os níveis de visibilidade para subgrupos e projetos serão mudados para corresponder à visibilidade do novo grupo pai."
msgid "GroupSettings|New runners registration token has been generated!"
msgstr "Um novo token de registro de executores foi gerado!"
@@ -17144,9 +17324,6 @@ msgstr "Um novo token de registro de executores foi gerado!"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr "Substitui as preferências de notificação do usuário para todos os membros do grupo, subgrupos e projetos."
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr "Os projetos serão excluídos permanentemente após um %{waiting_period}
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr "Os projetos serão excluídos permanentemente após um %{waiting_period}-atraso de dia(s). Este atraso pode ser %{link_start}personalizado por um administrador%{link_end} nas configurações de instância. Herdado por subgrupos."
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr "Selecione um projeto com o arquivo %{code_start}.gitlab/insights.yml%{code_end}"
@@ -17184,7 +17358,7 @@ msgid "GroupSettings|Select a subgroup to use as the source for custom project t
msgstr "Selecione um subgrupo para usar como fonte para modelos de projeto personalizados para este grupo."
msgid "GroupSettings|Select parent group"
-msgstr ""
+msgstr "Selecionar o grupo pai"
msgid "GroupSettings|Select the project that contains your custom Insights file."
msgstr "Selecione o projeto que contém seu arquivo personalizado do Insights."
@@ -17219,7 +17393,7 @@ msgstr "Essa configuração foi aplicada no grupo %{ancestor_group}. Você pode
msgid "GroupSettings|Transfer group"
msgstr "Transferir grupo"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para c
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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr "Peça ao seu administrador para ativar a %{enable_link_start}migração de grupo.%{enable_link_end}"
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr "Reúne projetos relacionados e concede aos membros acesso a vários projetos ao mesmo tempo."
@@ -17357,8 +17528,8 @@ msgstr "Por favor preencha o seu token de acesso pessoal"
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr "Forneça as credenciais para outra instância do GitLab para importar seus grupos diretamente."
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
-msgstr "Este recurso foi descontinuado e substituído por %{docs_link_start}migração de grupo%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
+msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
msgstr ""
@@ -17586,6 +17757,33 @@ msgstr[1] "Ocultar valores"
msgid "Hide values"
msgstr "Ocultar valores"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr "Vulnerabilidades altas ou desconhecidas encontradas"
@@ -17646,9 +17844,6 @@ msgstr "Manutenção"
msgid "Housekeeping successfully started"
msgstr "Manutenção iniciada com sucesso"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "Manutenção, exportação, caminho, transferência, remoção e arquivamento."
-
msgid "How do I configure Akismet?"
msgstr "Como eu configuro o Akismet?"
@@ -17677,17 +17872,14 @@ msgid "How do I set up a Google Chat webhook?"
msgstr ""
msgid "How do I set up this service?"
-msgstr ""
+msgstr "Como configuro este serviço?"
msgid "How do I use a web terminal?"
-msgstr ""
+msgstr "Como uso um terminal web?"
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "Como funciona"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr "Eu aceito o %{terms_link}"
msgid "I forgot my password"
msgstr "Esqueci minha senha"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "Se ativado, o acesso aos projetos será validado em um serviço externo usando sua etiqueta de classificação."
-
msgid "If enabled, only protected branches will be mirrored."
msgstr "Se ativado, apenas ramificações protegidas serão espelhados."
@@ -18139,7 +18343,7 @@ msgid "In this page you will find information about the settings that are used i
msgstr ""
msgid "InProductMarketing|%{organization_name} logo"
-msgstr ""
+msgstr "Logotipo de %{organization_name}"
msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
msgstr ""
@@ -18190,7 +18394,7 @@ msgid "InProductMarketing|Better code in less time"
msgstr ""
msgid "InProductMarketing|Blog"
-msgstr ""
+msgstr "Blog"
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 ""
@@ -18259,7 +18463,7 @@ msgid "InProductMarketing|Find out how your teams are really doing"
msgstr ""
msgid "InProductMarketing|Follow our steps"
-msgstr ""
+msgstr "Siga nossos passos"
msgid "InProductMarketing|Free 30-day trial"
msgstr "Avaliação gratuita de 30 dias"
@@ -18286,7 +18490,7 @@ msgid "InProductMarketing|Get your team set up on GitLab"
msgstr ""
msgid "InProductMarketing|Git basics"
-msgstr ""
+msgstr "Conceitos básicos de Git"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr "Muito difícil"
msgid "InProductMarketing|Very easy"
msgstr "Muito fácil"
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18586,7 +18796,7 @@ msgid "InProductMarketing|testing browser performance"
msgstr ""
msgid "InProductMarketing|unsubscribe"
-msgstr ""
+msgstr "cancelar inscrição"
msgid "InProductMarketing|update your preferences"
msgstr ""
@@ -18606,6 +18816,9 @@ msgstr "Incidente"
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18790,7 +19003,7 @@ msgid "Include description in commit message"
msgstr ""
msgid "Include new features from all tiers."
-msgstr ""
+msgstr "Inclua novidades de todas as camadas."
msgid "Include the name of the author of the issue, merge request or comment in the email body. By default, GitLab overrides the email sender's name. Some email servers don't support that option."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr "Adicionar uma integração"
msgid "Integrations|Add namespace"
msgstr "Adicionar espaço de nome"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Todos os detalhes"
@@ -19041,10 +19251,7 @@ msgid "Integrations|An error occurred while loading projects using custom settin
msgstr "Ocorreu um erro ao carregar projetos usando configurações personalizadas."
msgid "Integrations|Branches for which notifications are to be sent"
-msgstr ""
-
-msgid "Integrations|Browser limitations"
-msgstr "Limitações do navegador"
+msgstr "Ramificações para as quais as notificações devem ser enviadas"
msgid "Integrations|Comment detail:"
msgstr "Detalhe do comentário:"
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr "Mantenha suas dependências de PHP atualizadas no Packagist."
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr "Envie notificações sobre eventos de projeto para Unify Circuit."
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr "Entre para adicionar espaço de nome"
@@ -19181,6 +19391,9 @@ msgstr "Padrão"
msgid "Integrations|There are no projects using custom settings"
msgstr "Não há projetos usando configurações personalizadas"
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr "Interno - O projeto pode ser acessado por qualquer usuário entrado, exc
msgid "Internal URL (optional)"
msgstr "URL interno (opcional)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -19317,7 +19530,7 @@ msgid "Invalid period"
msgstr "Período inválido"
msgid "Invalid pin code."
-msgstr ""
+msgstr "Código PIN inválido."
msgid "Invalid pod_name"
msgstr ""
@@ -19374,7 +19587,7 @@ msgid "Invite \"%{trimmed}\" by email"
msgstr "Convidar \"%{trimmed}\" por e-mail"
msgid "Invite Members"
-msgstr ""
+msgstr "Convidar membros"
msgid "Invite a group"
msgstr "Convidar um grupo"
@@ -19473,16 +19686,16 @@ msgid "InviteMembersModal|Invite"
msgstr "Convidar"
msgid "InviteMembersModal|Invite a group"
-msgstr ""
+msgstr "Convidar um grupo"
msgid "InviteMembersModal|Invite members"
-msgstr ""
+msgstr "Convidar membros"
msgid "InviteMembersModal|Members were successfully added"
msgstr "Membros foram adicionados com sucesso"
msgid "InviteMembersModal|Search for a group to invite"
-msgstr ""
+msgstr "Pesquisar um grupo para convidar"
msgid "InviteMembersModal|Select a group to invite"
msgstr ""
@@ -19500,13 +19713,13 @@ msgid "InviteMembersModal|To assign issues to a new team member, you need a proj
msgstr ""
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "Vocêestá convidando membros para o grupo %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "Vocêestá convidando membros para o grupo %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "Vocêestá convidando membros para o grupo %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr "Vocêestá convidando membros para o projeto %{strongStart}%{name}%{strongEnd}."
@@ -19527,7 +19740,7 @@ msgid "InviteMember|Invite another member"
msgstr "Convidar outro membro"
msgid "InviteMember|Invite members"
-msgstr ""
+msgstr "Convidar membros"
msgid "InviteMember|Invite your team"
msgstr ""
@@ -20472,7 +20685,7 @@ msgid "July"
msgstr "Julho"
msgid "Jump to next unresolved thread"
-msgstr ""
+msgstr "Ir para o próximo tópico não resolvido"
msgid "Jun"
msgstr "Jun"
@@ -20963,7 +21176,7 @@ msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning o
msgstr ""
msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
-msgstr ""
+msgstr "Pronto para começar com o GitLab? Siga estas etapas para configurar sua área de trabalho, planejar e comprometer as alterações e publicar seu projeto."
msgid "LearnGitLab|Review and edit proposed changes to source code."
msgstr ""
@@ -21056,11 +21269,14 @@ msgid "License Compliance"
msgstr "License Compliance"
msgid "License compliance"
-msgstr ""
+msgstr "Conformidade de licença"
msgid "License file"
msgstr "Arquivo de licença"
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21203,7 +21419,7 @@ msgid "Licenses|Error fetching the license list. Please check your network conne
msgstr ""
msgid "Licenses|License Compliance"
-msgstr "Licença de conformidade"
+msgstr "Conformidade de licença"
msgid "Licenses|Name"
msgstr "Nome"
@@ -21384,9 +21600,6 @@ msgstr "Carregando..."
msgid "Loading…"
msgstr "Carregando…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Localização"
@@ -21402,6 +21615,9 @@ msgstr "Bloquear"
msgid "Lock %{issuableDisplayName}"
msgstr "Bloquear %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr "Travas possibilitam travar um arquivo ou uma pasta específica."
msgid "Locks the discussion."
msgstr "Bloqueia a discussão."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Entrar com cartão inteligente"
@@ -21547,7 +21796,7 @@ msgid "Manage applications that can use GitLab as an OAuth provider, and applica
msgstr "Gerencie aplicativos que podem utilizar o GitLab como um provedor OAuth e aplicativos que você autorizou a utilizar sua conta."
msgid "Manage applications that use GitLab as an OAuth provider."
-msgstr ""
+msgstr "Gerenciar aplicações que usam o GitLab como provedor OAuth."
msgid "Manage applications that you've authorized to use your account."
msgstr "Gerencie aplicativos que você autorizou a utilizar sua conta."
@@ -21751,7 +22000,7 @@ msgid "Max role"
msgstr "Cargo max"
msgid "Max session time"
-msgstr ""
+msgstr "Tempo máximo de sessão"
msgid "Maximum 20 characters"
msgstr "Máximo de 20 caracteres"
@@ -22212,6 +22461,12 @@ msgstr "Dependências de solicitação de mesclagem"
msgid "Merge request events"
msgstr "Eventos de solicitação de mesclagem"
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr "Relatórios de solicitação de mesclagem"
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "Realizar merge quando o pipeline for bem sucedido"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "Commit para o branch de origem"
@@ -22381,7 +22645,7 @@ msgid "Merged MRs"
msgstr ""
msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
-msgstr "Branches com merge realizado estão sendo excluídas. Isso pode levar algum tempo dependendo do número de branches. Por favor, atualize a página para ver as alterações."
+msgstr "Ramificações mescladas estão sendo excluídas. Isso pode levar algum tempo dependendo do número de ramificações . Por favor, atualize a página para ver as alterações."
msgid "Merged by"
msgstr "Merged por"
@@ -23053,9 +23317,6 @@ msgstr "Meses"
msgid "More Information"
msgstr "Mais informações"
-msgid "More Slack commands"
-msgstr "Mais comandos do Slack"
-
msgid "More actions"
msgstr "Mais ações"
@@ -23077,9 +23338,6 @@ msgstr "Mais informações disponíveis|aqui"
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr "Mais opções"
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "Mais de %{number_commits_distance} diferentes commits com %{default_branch}"
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23290,7 +23548,7 @@ msgid "NavigationTheme|Dark"
msgstr "Escuro"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "Modo escuro (alpha)"
msgid "NavigationTheme|Green"
msgstr "Verde"
@@ -23364,9 +23622,6 @@ msgstr "%{strongOpen}todos%{strongClose} pods"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr "%{strongOpen}qualquer%{strongClose} port"
-msgid "NetworkPolicies|.yaml"
-msgstr ".yaml"
-
msgid "NetworkPolicies|.yaml mode"
msgstr "Modo .yaml"
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr "Definição de política"
-msgid "NetworkPolicies|Rule"
-msgstr "Regra"
-
msgid "NetworkPolicies|Rule mode"
msgstr "Modo de regra"
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr "O tráfego que não corresponder a nenhuma regra será bloqueado."
-
msgid "NetworkPolicies|all DNS names"
msgstr "todos os nomes de DNS"
@@ -23757,7 +24006,7 @@ msgid "Next file in diff"
msgstr "Próximo arquivo em diff"
msgid "Next scan"
-msgstr ""
+msgstr "Próxima verificação"
msgid "Next unresolved discussion"
msgstr "Próxima discussão não resolvida"
@@ -23984,6 +24233,9 @@ msgstr "Nenhum marco"
msgid "No milestones to show"
msgstr "Sem marcos para mostrar"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Sem outras etiquetas com esse nome ou descrição"
@@ -24011,6 +24263,9 @@ msgstr "Sem etiquetas priorizadas com esse nome ou descrição"
msgid "No profiles found"
msgstr "Nenhum perfil encontrado"
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr "Nenhum projeto encontrado"
@@ -24077,8 +24332,8 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
-msgstr "Nenhum webhooks encontrados, adicione um no formulário acima."
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -24119,7 +24374,7 @@ msgid "Not all browsers support U2F devices. Therefore, we require that you set
msgstr "Nem todos os navegadores suportam dispositivos U2F. Portanto, exigimos que você configure um aplicativo de autenticação de dois fatores primeiro. Dessa forma, você sempre será capaz de entrar - mesmo quando você estiver usando um navegador não suportado."
msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
-msgstr ""
+msgstr "Nem todos os navegadores são compatíveis com WebAuthn. Portanto, exigimos que você configure primeiro um aplicativo de autenticação de dois fatores. Dessa forma, você sempre poderá entrar - mesmo em um navegador não compatível."
msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
msgstr "Nem todos os dados foram processados ainda, a precisão do gráfico para o período selecionado é limitada."
@@ -24586,7 +24841,7 @@ msgid "OnCallSchedules|User %{name} is currently part of:"
msgstr ""
msgid "OnCallSchedules|View next timeframe"
-msgstr ""
+msgstr "Ver próximo período de tempo"
msgid "OnCallSchedules|View previous timeframe"
msgstr ""
@@ -24727,7 +24982,7 @@ msgid "OnDemandScans|There are no running scans."
msgstr ""
msgid "OnDemandScans|There are no saved scans."
-msgstr ""
+msgstr "Não há verificações salvas."
msgid "OnDemandScans|There are no scheduled scans."
msgstr ""
@@ -24807,7 +25062,7 @@ msgid "Only enable search after installing the plugin, enabling indexing, and re
msgstr ""
msgid "Only include features new to your current subscription tier."
-msgstr ""
+msgstr "Inclua apenas novos recursos no seu nível de assinatura atual."
msgid "Only policy:"
msgstr ""
@@ -24909,7 +25164,7 @@ msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "A operação expirou. Verifique os registros do pod para %{pod_name} para mais detalhes."
msgid "Operations"
-msgstr ""
+msgstr "Operações"
msgid "Operations Dashboard"
msgstr "Painel de operações"
@@ -24986,8 +25241,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Pedidos de saída"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25589,7 +25865,7 @@ msgid "Paste confidential epic link"
msgstr ""
msgid "Paste confidential issue link"
-msgstr ""
+msgstr "Colar link de issue confidencial"
msgid "Paste epic link"
msgstr "Colar link de épico"
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr "Cole a sua chave SSH pública, que geralmente é encontrada no arquivo '~/.ssh/id_ed25519.pub' ou '~/.ssh/id_rsa.pub' e começa com 'ssh-ed25519' ou 'ssh-rsa'. Não cole sua chave SSH privada, pois isso pode comprometer sua identidade."
-
msgid "Patch to apply"
msgstr ""
@@ -25744,11 +26017,14 @@ msgstr "objeto"
msgid "PerformanceBar|wall"
msgstr "parede"
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr "Período em segundos"
msgid "Permalink"
-msgstr ""
+msgstr "Link permanente"
msgid "Permanently delete project"
msgstr "Excluir projeto permanentemente"
@@ -25762,14 +26038,14 @@ msgstr "Permissões"
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
-msgstr "Permissões, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Token de acesso pessoal"
msgid "Personal Access Token prefix"
-msgstr ""
+msgstr "Prefixo do token de acesso pessoal"
msgid "Personal access tokens are not revoked upon expiration."
msgstr ""
@@ -26029,9 +26305,6 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Gráficos de pipelines"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr "Adicionar uma tarefa de qualidade de código"
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "Tem certeza de que deseja executar este pipeline?"
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Construa com confiança"
@@ -26056,8 +26332,8 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr "Modelo CI/CD para testar e implantar no seu projeto %{name}."
-msgid "Pipelines|Child pipeline"
-msgstr "Pipeline filho"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
msgid "Pipelines|Clear runner caches"
msgstr "Limpar cache dos executores"
@@ -26221,11 +26497,29 @@ msgstr "Análise de YAML mesclado"
msgid "Pipelines|Visualize"
msgstr "Visualizar"
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr "Inválido"
-msgid "Pipelines|parent"
-msgstr "pai"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "Ações"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26422,6 +26719,12 @@ msgstr "Iniciar todas manualmente"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Por favor, %{link_to_register} ou %{link_to_sign_in} para comentar"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "Por favor %{startTagRegister}cadastre-se%{endRegisterTag} ou %{startTagSignIn}entre%{endSignInTag} para responder"
@@ -26510,7 +26813,7 @@ msgid "Please enter or upload a valid license."
msgstr ""
msgid "Please enter your current password."
-msgstr ""
+msgstr "Por favor digite sua senha atual."
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor, preencha um nome descritivo para o seu grupo."
@@ -26579,7 +26882,7 @@ msgid "Please select a file"
msgstr "Por favor, selecione um arquivo"
msgid "Please select a group"
-msgstr ""
+msgstr "Por favor, selecione um grupo"
msgid "Please select a group."
msgstr "Por favor, selecione um grupo."
@@ -26776,6 +27079,9 @@ msgstr "Preferências de hora"
msgid "Preferences|Use relative times"
msgstr "Usar tempos relativos"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26990,10 +27296,10 @@ msgid "Profiles|Add status emoji"
msgstr "Adicionar emoji de status"
msgid "Profiles|An error occurred while updating your username, please try again."
-msgstr ""
+msgstr "Ocorreu um erro ao atualizar seu nome de usuário, por favor, tente novamente."
msgid "Profiles|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Um indicador aparece ao lado do seu nome e avatar"
msgid "Profiles|Avatar cropper"
msgstr "Recortar Avatar"
@@ -27001,6 +27307,9 @@ msgstr "Recortar Avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "O avatar será removido. Você tem certeza?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "Bio"
@@ -27025,9 +27334,6 @@ msgstr "Cidade, país"
msgid "Profiles|Clear status"
msgstr "Limpar status"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Clique no ícone para ativar a entrada com um dos seguintes serviços"
-
msgid "Profiles|Commit email"
msgstr "E-mail de commit"
@@ -27128,7 +27434,7 @@ msgid "Profiles|Invalid username"
msgstr "Nome de usuário inválido"
msgid "Profiles|Job title"
-msgstr ""
+msgstr "Título do trabalho"
msgid "Profiles|Key"
msgstr "Chave"
@@ -27188,10 +27494,10 @@ msgid "Profiles|Profile was successfully updated"
msgstr "O perfil foi atualizado com sucesso"
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "Pronomes"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "Pronúncia"
msgid "Profiles|Public avatar"
msgstr "Avatar público"
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Remover avatar"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Definir nova foto de perfil"
@@ -27250,9 +27559,6 @@ msgstr "Autenticação de dois fatores"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escreva sua %{confirmationValue} para confirmar:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Normalmente incia com \"ssh-ed25519 …\" ou \"ssh-rsa …\""
-
msgid "Profiles|Update profile settings"
msgstr "Atualizar configurações do perfil"
@@ -27278,7 +27584,7 @@ msgid "Profiles|Using emojis in names seems fun, but please try to set a status
msgstr "Usar emojis em nomes parece divertido, mas tente definir uma mensagem de status"
msgid "Profiles|Website url"
-msgstr ""
+msgstr "URL do site"
msgid "Profiles|What's your status?"
msgstr "Qual é o seu status?"
@@ -27641,16 +27947,16 @@ msgid "ProjectService|Enter new API key"
msgstr ""
msgid "ProjectService|Enter new password"
-msgstr ""
+msgstr "Insira a nova senha"
msgid "ProjectService|Enter new password."
-msgstr ""
+msgstr "Insira a nova senha."
msgid "ProjectService|Enter new token"
msgstr "Insira o novo token"
msgid "ProjectService|Issue URL"
-msgstr ""
+msgstr "URL da issue"
msgid "ProjectService|Jenkins server URL"
msgstr ""
@@ -27704,10 +28010,10 @@ msgid "ProjectService|Trigger event for new comments on confidential issues."
msgstr ""
msgid "ProjectService|Trigger event for new comments."
-msgstr ""
+msgstr "Evento de gatilho para novos comentários."
msgid "ProjectService|Trigger event for new tags pushed to the repository."
-msgstr ""
+msgstr "Evento de gatilho para novas tags enviadas para o repositório."
msgid "ProjectService|Trigger event for pushes to the repository."
msgstr "Evento de gatilho para envios para o repositório."
@@ -27716,16 +28022,16 @@ msgid "ProjectService|Trigger event when a commit is created or updated."
msgstr ""
msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
-msgstr ""
+msgstr "Evento de gatilho quando uma issue confidencial é criada, atualizada ou fechada."
msgid "ProjectService|Trigger event when a deployment starts or finishes."
-msgstr ""
+msgstr "Evento de gatilho quando uma implantação inicia ou termina."
msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
-msgstr ""
+msgstr "Evento de gatilho quando uma solicitação de mesclagem é criada, atualizada ou mesclada."
msgid "ProjectService|Trigger event when a new, unique alert is recorded."
-msgstr ""
+msgstr "Evento de gatilho quando um alerta novo e exclusivo é registrado."
msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
msgstr ""
@@ -27734,16 +28040,16 @@ msgid "ProjectService|Trigger event when a pipeline status changes."
msgstr ""
msgid "ProjectService|Trigger event when a wiki page is created or updated."
-msgstr ""
+msgstr "Evento de gatilho quando uma página da wiki é criada ou atualizada."
msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
-msgstr ""
+msgstr "Evento de gatilho quando uma issue é criada, atualizada ou fechada."
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
-msgstr ""
+msgstr "%{link_start}O que são modelos de descrição?%{link_end}"
msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Que variáveis posso usar?%{link_end}"
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr "Configurações adicionais que influenciam como e onde as mesclagem são feitas."
@@ -27775,11 +28081,14 @@ msgstr "A caixa de seleção está visível e selecionada por padrão."
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr "A caixa de seleção está visível e não selecionada por padrão."
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
-msgstr "Escolha seu método de merge, opções de mesclar, verificações de mesclar, sugestões de mesclagem e configure um modelo de descrição padrão para solicitações de mesclagem."
+msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
+msgstr "Escolha seu método de mesclagem, opções de mesclagem, verificações de mesclagem e sugestões de mesclagem."
+
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "Configure os recursos do projeto e monitore a saúde deles."
@@ -27839,7 +28148,7 @@ msgid "ProjectSettings|Fast-forward merge"
msgstr "Executar mesclagem com fast-forward"
msgid "ProjectSettings|Fast-forward merges only."
-msgstr ""
+msgstr "Merges com fast-forward apenas."
msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
msgstr "Ferramenta flexível para desenvolver ideias e planejar as tarefas nesse projeto."
@@ -27856,11 +28165,17 @@ msgstr "Global"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Interno"
msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
-msgstr ""
+msgstr "Introduz o risco de mesclar alterações que não passam pelo pipeline."
msgid "ProjectSettings|Issues"
msgstr "Issues"
@@ -27887,7 +28202,7 @@ msgid "ProjectSettings|Merge commit message template"
msgstr "Modelo de mensagem de commit de mesclagem"
msgid "ProjectSettings|Merge commit with semi-linear history"
-msgstr "Commit de mesclagem com uma história semilinear"
+msgstr "Commit de mesclagem com uma histórico semilinear"
msgid "ProjectSettings|Merge method"
msgstr "Método de mesclagem"
@@ -27901,6 +28216,9 @@ msgstr "Solicitações de mesclagem"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "Sugestões de mesclagem"
@@ -27983,7 +28301,7 @@ msgid "ProjectSettings|Snippets"
msgstr "Snippets"
msgid "ProjectSettings|Squash commit message template"
-msgstr ""
+msgstr "Modelo de mensagem de commit de squash"
msgid "ProjectSettings|Squash commits when merging"
msgstr "Squash commit ao mesclar"
@@ -28001,13 +28319,13 @@ msgid "ProjectSettings|Target project"
msgstr "Projeto alvo"
msgid "ProjectSettings|The commit message used when applying merge request suggestions."
-msgstr ""
+msgstr "A mensagem de commit usada ao aplicar sugestões de solicitação de mesclagem."
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
-msgstr ""
+msgstr "A mensagem de commit usada ao mesclar, se o método de mesclagem criar uma commit de mesclagem."
msgid "ProjectSettings|The commit message used when squashing commits."
-msgstr ""
+msgstr "A mensagem de commit usada para squash de commits."
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr "O projeto de destino padrão para solicitações de mesclagem criadas neste projeto de fork."
@@ -28027,9 +28345,6 @@ msgstr "Essa configuração está aplicada no nível do servidor, mas foi sobres
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Essa configuração será aplicada a todos os projetos a menos que seja sobrescrita por um administrador."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr "Para ativar este recurso, configure pipelines. %{link_start}Como configurar pipelines para solicitações de mesclagem?%{link_end}"
-
msgid "ProjectSettings|Transfer project"
msgstr "Transferir projeto"
@@ -28051,14 +28366,14 @@ msgstr "Usuários podem solicitar acesso"
msgid "ProjectSettings|View and edit files in this project."
msgstr "Visualize e edite arquivos neste projeto."
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
-msgstr "Veja e edite arquivos nesse projeto. Não membros do projeto terão apenas acesso a leitura."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
+msgstr ""
msgid "ProjectSettings|View project analytics."
msgstr "Ver análise de projeto."
msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
-msgstr ""
+msgstr "As opções de visibilidade para este fork são limitadas pela visibilidade atual do projeto fonte."
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "Visualize as métricas de desempenho do projeto."
@@ -28069,7 +28384,7 @@ msgstr "Avisar sobre caracteres potencialmente indesejados"
msgid "ProjectSettings|What are badges?"
msgstr "O que são selos?"
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28163,13 +28478,13 @@ msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
msgid "ProjectView|Activity"
-msgstr ""
+msgstr "Atividade"
msgid "ProjectView|Files and Readme (default)"
-msgstr ""
+msgstr "Arquivos e Readme (padrão)"
msgid "ProjectView|Readme"
-msgstr ""
+msgstr "Readme"
msgid "Projects"
msgstr "Projetos"
@@ -28538,7 +28853,7 @@ msgid "Promotions|Repository Mirroring"
msgstr "Espelhamento de repositório"
msgid "Promotions|Repository Mirroring is a way to mirror repositories from external sources. It can be used to mirror all branches, tags, and commits that you have in your repository."
-msgstr ""
+msgstr "Espelhamento de repositório é uma forma de espelhar repositórios de fontes externas. Pode ser usado para espelhar todos as ramificações, tags e commits que você tem em seu repositório."
msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
msgstr "Veja outras funcionalidade do %{subscription_link_start}plano Premium%{subscription_link_end}"
@@ -28589,7 +28904,7 @@ msgid "Promotions|Weighting your issue"
msgstr "Ponderar sua issue"
msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them."
-msgstr ""
+msgstr "Quando você tem muitas issues, pode ser difícil obter uma visão geral. Ao adicionar um peso para as suas issues, você pode ter uma ideia melhor do esforço, custo, tempo necessário ou valor de cada um e, assim, gerenciá-los melhor."
msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
msgstr "Você pode restringir o acesso a ramificações protegidas escolhendo um cargo (Mantenedores, Desenvolveres) e também determinados usuários."
@@ -28721,13 +29036,13 @@ msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
msgid "ProtectedBranch|Unprotect"
-msgstr ""
+msgstr "Desproteger"
msgid "ProtectedBranch|What are protected branches?"
msgstr "O que são ramificações protegidas?"
msgid "ProtectedBranch|default"
-msgstr ""
+msgstr "padrão"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} poderá ser editado por desenvolvedores. Tem certeza disso?"
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr "Chaves públicas de implantação"
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "Chaves de implantação públicas (%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "Pipelines públicos"
@@ -28867,7 +29179,7 @@ msgstr "Comprar mais minutos"
msgid "Purchase more storage"
msgstr "Comprar mais armazenamento"
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29021,10 +29333,10 @@ msgid "Quickly and easily edit multiple files in your project."
msgstr "Edite rapidamente e facilmente vários arquivos em seu projeto."
msgid "Quota of CI/CD minutes"
-msgstr ""
+msgstr "Cota de minutos de CI/CD"
msgid "Quota of CI/CD minutes:"
-msgstr ""
+msgstr "Cota de minutos de CI/CD:"
msgid "README"
msgstr "README"
@@ -29113,6 +29425,12 @@ msgstr "ramificação de origem de rebase"
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29266,7 +29587,7 @@ msgid "RegistrationFeatures|Want to %{feature_title} for free?"
msgstr ""
msgid "RegistrationFeatures|send emails to users"
-msgstr ""
+msgstr "Enviar e-mails para usuários"
msgid "RegistrationFeatures|use this feature"
msgstr ""
@@ -29694,7 +30015,7 @@ msgid "Reopen"
msgstr "Reabrir"
msgid "Reopen %{issueType}"
-msgstr "Abrir novamente %{issueType}"
+msgstr "Reabrir %{issueType}"
msgid "Reopen %{noteable}"
msgstr ""
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr "O repositório deve conter pelo menos 1 arquivo."
msgid "Repository size is above the limit."
msgstr "O tamanho do repositório está acima do limite."
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Armazenamento do Repositório"
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr "Requisições por período"
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "O requisito%{reference} foi adicionado"
@@ -30150,7 +30479,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "Requires values to meet regular expression requirements."
-msgstr ""
+msgstr "Requer que valores atendam aos requisitos de expressão regular."
msgid "Requires you to deploy or set up cloud-hosted Sentry."
msgstr "Requer que você implante ou configure o Sentry hospedado na nuvem."
@@ -30189,7 +30518,7 @@ msgid "Reset file"
msgstr ""
msgid "Reset filters"
-msgstr ""
+msgstr "Redefinir filtros"
msgid "Reset health check access token"
msgstr "Recriar o token de status de saúde"
@@ -30245,9 +30574,6 @@ msgstr "Resolvido por"
msgid "Resolved by %{name}"
msgstr "Resolvido por %{name}"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr "Resolve endereços IP uma vez e os usa para enviar requisições"
-
msgid "Response"
msgstr "Resposta"
@@ -30314,7 +30640,7 @@ msgstr "Continuar"
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,15 +30740,15 @@ msgstr "Revogar"
msgid "Revoked"
msgstr "Revogado"
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "Revogado o token de representação %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Revogado o token de acesso pessoal %{personal_access_token_name}!"
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr ""
-
msgid "RightSidebar|Copy email address"
msgstr "Copiar endereço de e-mail"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Planejamento"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Cargo"
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr "Arquitetura"
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr "Comando para registrar o executor"
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr "Copiar instruções"
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr "Descrição"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr "Baixar e instalar o binário"
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr "Grupo"
-msgid "Runners|Group Runners"
-msgstr "Executores de grupo"
-
msgid "Runners|IP Address"
msgstr "Endereço de IP"
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revisão"
@@ -30705,18 +31049,18 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Executores"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
-msgstr "Executores nesse grupo: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
+msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
-msgstr "Mostrar instruções de instalação do executor"
-
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
+msgid "Runners|Show runner installation instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr "Verificação SSL:"
msgid "SSL verification"
msgstr "Verificação SSL"
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr "Satisfeito"
@@ -31026,9 +31367,6 @@ msgstr "Pesquisar"
msgid "Search GitLab"
msgstr "Pesquisar no GitLab"
-msgid "Search Jira issues"
-msgstr "Pesquisar issues do Jira"
-
msgid "Search a group"
msgstr "Pesquisar um grupo"
@@ -31253,7 +31591,7 @@ msgid "Seats usage data is updated every day at 12:00pm UTC"
msgstr ""
msgid "Secondary"
-msgstr ""
+msgstr "Secundário"
msgid "Secondary email:"
msgstr "E-mail Secundário:"
@@ -31330,8 +31668,8 @@ msgstr "Saiba mais sobre a verificação de vulnerabilidade"
msgid "SecurityApprovals|License-Check"
msgstr "Verificação de licença"
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
-msgstr "Requer aprovação para licenças negadas. %{linkStart}Mais informações%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
msgstr "Requer aprovação para reduções de cobertura de teste. %{linkStart}Saiba mais%{linkEnd}"
@@ -31418,7 +31756,7 @@ msgid "SecurityConfiguration|Manage scans"
msgstr "Gerenciar verificações"
msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr ""
+msgstr "Mais tipos de verificação, incluindo verificação de contêiner, DAST, verificação de dependência, fuzzing e conformidade de licença"
msgid "SecurityConfiguration|Not enabled"
msgstr "Não ativado"
@@ -31462,6 +31800,9 @@ msgstr "Gerenciamento de vulnerabilidades"
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "Detalhes de vulnerabilidade e estatísticas na solicitação de mesclagem"
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr "Executa uma verificação %{scanType}"
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr "Última verificação"
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr "Políticas"
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr "Descrição da política"
msgid "SecurityOrchestration|Policy editor"
msgstr "Editor de política"
-msgid "SecurityOrchestration|Policy preview"
-msgstr "Pré-visualizar política"
-
msgid "SecurityOrchestration|Policy status"
msgstr "Status da política"
+msgid "SecurityOrchestration|Policy summary"
+msgstr ""
+
msgid "SecurityOrchestration|Policy type"
msgstr "Tipo de política"
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr "Regra"
@@ -31558,12 +31911,21 @@ msgstr "Regras"
msgid "SecurityOrchestration|Scan Execution"
msgstr "Execução de verificação"
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr "Execução de verificação"
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr "Status"
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr "ver resultados"
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr "+%{count} mais"
@@ -31621,6 +32037,9 @@ msgstr "Ambiente(s)"
msgid "SecurityPolicies|Policy type"
msgstr "Tipo de política"
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} e %{secondProject}"
@@ -31718,22 +32137,22 @@ msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
-msgstr "Gerenciar e acompanhe vulnerabilidades identificadas em projetos dentro de seu grupo. Vulnerabilidades em projetos são mostradas aqui quando o teste de segurança é configurado."
+msgstr "Gerenciar e acompanhar vulnerabilidades identificadas em projetos dentro de seu grupo. Vulnerabilidades em projetos são mostradas aqui quando o teste de segurança é configurado."
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
-msgstr ""
+msgstr "Gerenciar e acompanhar vulnerabilidades identificadas em seus clusters Kubernetes. Vulnerabilidades aparecem aqui depois de criar uma política de execução de verificação em qualquer projeto neste grupo."
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
-msgstr ""
+msgstr "Gerenciar e acompanhar vulnerabilidades identificadas em seus clusters Kubernetes. Vulnerabilidades aparecem aqui depois de criar uma política de execução de verificação em qualquer projeto nessa instância."
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
-msgstr ""
+msgstr "Gerenciar e acompanhar vulnerabilidades identificadas em seus clusters Kubernetes. Vulnerabilidades aparecem aqui depois de criar uma política de execução de verificação nesse grupo."
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr "Gerenciar e acompanhar vulnerabilidades identificadas em seu projeto. Vulnerabilidades são mostradas aqui quando o teste de segurança é configurado."
msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
-msgstr ""
+msgstr "Gerencie e acompanhar vulnerabilidades identificadas em seus projetos selecionados. Vulnerabilidades para projetos selecionados com testes de segurança configurados são mostradas aqui."
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Selecionar Formato do Arquivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr "Selecione o projeto GitLab para vincular com sua equipe Slack"
-
msgid "Select Page"
msgstr "Selecionar Página"
@@ -32332,8 +32748,8 @@ msgstr "Central de serviços"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "URL de serviço"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr "Ativar central de Serviços"
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "issues criadas a partir da central de serviços aparecerão aqui. Cada comentário torna-se da conversa por e-mail"
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32477,7 +32890,7 @@ msgid "Set the maximum number of slices allowed to run concurrently during Elast
msgstr ""
msgid "Set the maximum session time for a web terminal."
-msgstr ""
+msgstr "Defina o tempo máximo de sessão para um terminal web."
msgid "Set the milestone to %{milestone_reference}."
msgstr "Definir o marco como %{milestone_reference}."
@@ -32500,7 +32913,7 @@ msgstr "Configurar CI/CD"
msgid "Set up Jira Integration"
msgstr "Configurar integração do Jira"
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32537,7 +32950,7 @@ msgid "SetStatusModal|Add status emoji"
msgstr "Adicionar emoji de status"
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Um indicador aparece ao lado do seu nome e avatar"
msgid "SetStatusModal|Busy"
msgstr ""
@@ -32673,9 +33086,6 @@ msgstr "Redefinir minutos de pipeline"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Redefinir minutos usados de pipeline"
-msgid "Sherlock Transactions"
-msgstr "Transações de Sherlock"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr "Mostrar todas as atividades"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr "Mostrar todas as issues"
@@ -32727,6 +33140,9 @@ msgstr "Mostrar projetos arquivados"
msgid "Show archived projects only"
msgstr "Mostrar somente projetos arquivados"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Exibir comando"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr "Mostrar apenas comentários"
-msgid "Show commit description"
-msgstr "Mostrar descrição do commit"
-
msgid "Show complete raw log"
msgstr "Visualizar raw log completo"
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr "Mostra a lista fechada"
@@ -32806,7 +33222,7 @@ msgstr "Mostrando todas as issues"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr "Cadastre-se"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "O registro foi bem sucedido! Confirme seu e-mail para fazer entrar."
@@ -33001,9 +33420,33 @@ msgstr "Aplicativo Slack"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "A integração com o Slack permite que você interaja com o GitLab por meio de comandos de barra em uma janela de bate-papo."
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr "Envia notificações sobre eventos do projeto para os canais do Slack."
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr "Algo deu errado. Por favor, tente novamente."
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Desculpe, nenhum épico corresponde à sua pesquisa"
-
msgid "Sorry, no projects matched your search"
msgstr "Desculpe, nenhum projeto corresponde à sua pesquisa"
@@ -33376,9 +33816,6 @@ msgstr "Último contato"
msgid "SortOptions|Last created"
msgstr "Últimos criados"
-msgid "SortOptions|Last updated"
-msgstr "Últimos atualizados"
-
msgid "SortOptions|Least popular"
msgstr "Menos populares"
@@ -33602,7 +34039,7 @@ msgid "Spam and Anti-bot Protection"
msgstr "Proteção contra spam e anti-bot"
msgid "Spam log successfully submitted as ham."
-msgstr ""
+msgstr "Registro de spam foi enviado com sucesso como ham."
msgid "Specific runners"
msgstr "Executores específicos"
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Iniciar pesquisa"
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Regitre sua mensagem para ativar"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr "Estado/Província/Cidade"
@@ -34096,6 +34539,9 @@ msgstr "Inscrito"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr "Adicionar lugares"
@@ -34204,9 +34671,6 @@ msgstr "Data final da avaliação"
msgid "SubscriptionTable|Trial start date"
msgstr "Data de início da avaliação"
-msgid "SubscriptionTable|Upgrade"
-msgstr "Atualizar"
-
msgid "SubscriptionTable|Usage"
msgstr "Uso"
@@ -34375,9 +34839,6 @@ msgstr "Resumo / Nota"
msgid "Sunday"
msgstr "Domingo"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34388,7 +34849,7 @@ msgid "SuperSonics|An error occurred while activating your subscription."
msgstr ""
msgid "SuperSonics|Billable users"
-msgstr ""
+msgstr "Usuários faturáveis"
msgid "SuperSonics|Buy subscription"
msgstr "Comprar assinatura"
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr "Iniciar a avaliação gratuita"
msgid "SuperSonics|Subscription details"
msgstr "Detalhes da assinatura"
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Suporte"
@@ -34568,16 +35047,16 @@ msgid "SynthaxHighlightingTheme|Light"
msgstr "Claro"
msgid "SynthaxHighlightingTheme|Monokai"
-msgstr ""
+msgstr "Monokai"
msgid "SynthaxHighlightingTheme|None"
msgstr "Nenhum"
msgid "SynthaxHighlightingTheme|Solarized Dark"
-msgstr ""
+msgstr "Solarized escuro"
msgid "SynthaxHighlightingTheme|Solarized Light"
-msgstr ""
+msgstr "Solarized claro"
msgid "System"
msgstr "Sistema"
@@ -34750,6 +35229,9 @@ msgstr "Ramificação de destino"
msgid "Target-Branch"
msgstr "Ramificação de destino"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr "ID da tarefa: %{elastic_task}"
@@ -34822,6 +35304,9 @@ msgstr "Contrato de Termos de Serviço e Política de Privacidade"
msgid "Terms of Service and Privacy Policy"
msgstr "Termos de Serviço e Política de Privacidade"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr "Terraform"
@@ -34992,6 +35477,9 @@ msgstr "Teste"
msgid "Test Cases"
msgstr "Casos de teste"
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
@@ -35147,7 +35635,7 @@ msgid "Thank you for your report. A GitLab administrator will look into it short
msgstr "Obrigado pelo seu relatório. Um administrador do GitLab irá analisá-lo em breve."
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
-msgstr ""
+msgstr "Obrigado pela sua solicitação de suporte! Estamos acompanhando sua solicitação através do ticket #%{issue_iid} e responderemos o quanto antes."
msgid "Thanks for signing up to GitLab!"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35182,7 +35667,7 @@ msgid "The API key used by GitLab for accessing the Spam Check service endpoint.
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
-msgstr ""
+msgstr "A exportação CSV será criada em segundo plano. Quando concluída, será enviada para %{email} em um anexo."
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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "O Certificado X509 a ser usado quando o TLS mútuo é necessário para se comunicar com o serviço de autorização externa. Se deixado em branco, o certificado do servidor ainda será validado ao acessar por HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr "Os artefatos mais recentes criados por tarefas no pipeline mais recente
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "A senha necessária para descriptografar a chave privada. Isso é opcional e o seu valor é criptografado."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35511,14 +35987,11 @@ msgid "The password for your GitLab account on %{link_to_gitlab} has successfull
msgstr ""
msgid "The pipeline has been deleted"
-msgstr ""
+msgstr "O pipeline foi excluído"
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 "Os agendamentos de pipelines rodam pipelines no futuro, de forma repetida, para branchs ou tags específicas. Esses agendamentos de pipeline terão acesso limitado com base no seu usuário associado."
-msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "A chave privada a ser usada quando um certificado de cliente é fornecido. Este valor é criptografado."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35670,7 +36143,7 @@ msgid "There are no SSH keys with access to your account."
msgstr "Não há chaves SSH com acesso à sua conta."
msgid "There are no Spam Logs"
-msgstr ""
+msgstr "Não há registros de spam"
msgid "There are no abuse reports!"
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr "Estes serão enviados para %{email} em um anexo quando terminado."
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Essa %{issuableDisplayName} está bloqueada. Só membros do projeto podem comentar."
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Esse épico não existe ou você não tem permissão suficiente."
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr "Esta funcionalidade requer que o armazenamento local esteja ativado"
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr "Este pipeline foi disparando por um agendamento."
msgid "This project"
msgstr "Este projeto"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr "Este projeto não pertence a um grupo e não pode usar executores de grupo."
@@ -36473,6 +36952,9 @@ msgstr "Este projeto está arquivado e não pode ser comentado."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Este projeto está licenciado sob o %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr "Este serviço permite aos usuários executar operações comuns neste pr
msgid "This setting can be overridden in each project."
msgstr "Essa configuração pode ser substituída em cada projeto."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36549,10 +37034,10 @@ msgid "This variable can not be masked."
msgstr ""
msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
+msgstr "Isso invalidará seus aplicativos registrados e dispositivos U2F / WebAuthn."
msgid "This will invalidate your registered applications and U2F devices."
-msgstr ""
+msgstr "Isso invalidará seus aplicativos registrados e dispositivos U2F."
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Tempo em segundos o GitLab aguardará uma resposta do serviço externo. Quando o serviço não responder a tempo, o acesso será negado."
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,11 +37472,8 @@ msgstr "Para acessar este domínio crie um novo registro DNS"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Para adicionar uma chave SSH, você precisa %{generate_link_start}gerar uma%{link_end} ou usar uma %{existing_link_start}chave existente%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
-msgstr ""
+msgstr "Para adicionar a entrada manualmente, forneça os seguintes detalhes ao aplicativo em seu telefone."
msgid "To confirm, type %{phrase_code}"
msgstr ""
@@ -37114,7 +37593,7 @@ msgid "To see this project's operational details, contact an owner of group %{gr
msgstr "Para ver os detalhes operacionais deste projeto, entre em contato com um proprietário do grupo %{groupName} para atualizar o plano. Você também pode remover o projeto do dashboard."
msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
-msgstr ""
+msgstr "Para ver o que mudou ou criar uma solicitação de mesclagem, escolha uma ramificação ou tag (como %{branch}) ou insira um commit (como %{sha})."
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Para configurar a autenticação SAML para o seu grupo por meio de um provedor de identidade, como Azure, Okta, Onelogin, Ping Identity ou seu provedor SAML 2.0 personalizado:"
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr "Para ampliar sua pesquisa, altere ou remova os filtros acima"
msgid "To widen your search, change or remove filters above."
msgstr "Para ampliar sua pesquisa, altere ou remova os filtros acima."
-msgid "To widen your search, change or remove filters."
-msgstr "Para ampliar sua pesquisa, alterar ou remover filtros."
-
msgid "To-Do List"
msgstr "Lista de tarefas pendentes"
@@ -37165,7 +37638,7 @@ msgid "Today"
msgstr "Hoje"
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
-msgstr ""
+msgstr "Você está procurando coisas para fazer? Dê uma olhada em %{strongStart}%{openIssuesLinkStart}issues abertas%{openIssuesLinkEnd}%{strongEnd}, contribua para %{strongStart}%{mergeRequestLinkStart}uma solicitação de mesclagem%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}ou mencione alguém em um comentário para atribuir automaticamente uma nova tarefa."
msgid "Todos|Filter by author"
msgstr "Filtrar por autor"
@@ -37180,7 +37653,7 @@ msgid "Todos|It's how you always know what to work on next."
msgstr ""
msgid "Todos|Mark all as done"
-msgstr ""
+msgstr "Marcar tudo como concluído"
msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr "Acompanhe eventos importantes no seu projeto."
msgid "Track time with quick actions"
msgstr "Acompanhe o tempo com ações rápidas"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr "Modo de treinamento"
@@ -37475,6 +37945,9 @@ msgstr "Você não obterá uma avaliação gratuita agora, mas pode sempre retom
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr "Sua avaliação termina em %{boldStart}%{trialEndDate}%{boldEnd}. Esperamos que você esteja gostando dos recursos do GitLab %{planName}.Para manter esses recursos após o término da avaliação, você precisará comprar uma assinatura. (Você também pode escolher o GitLab Premium se ele atender às suas necessidades.)"
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr "Nome da empresa"
@@ -37490,15 +37963,9 @@ msgstr "País"
msgid "Trial|Dismiss"
msgstr "Dispensar"
-msgid "Trial|First name"
-msgstr "Nome"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr "Avaliação do GitLab Ultimate (opcional)"
-msgid "Trial|Last name"
-msgstr "Sobrenome"
-
msgid "Trial|Number of employees"
msgstr "Número de funcionários"
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr "Gatilho"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "Solucionar problemas e monitorar sua aplicação com rastreamento"
@@ -37590,7 +38063,7 @@ msgid "Try out GitLab Pipelines"
msgstr ""
msgid "Try the troubleshooting steps here."
-msgstr ""
+msgstr "Tente as etapas de solução de problemas aqui."
msgid "Try to fork again"
msgstr "Tente realizar o fork novamente"
@@ -38084,6 +38557,9 @@ msgstr "Atualizado"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Atualizado em %{updated_at} por %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "Atualizações"
@@ -38105,6 +38581,9 @@ msgstr "Atualize seu plano"
msgid "Upload"
msgstr "Enviar"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Enviar arquivo CSV"
@@ -38540,6 +39019,9 @@ msgstr "Limite de taxa do usuário e IP"
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr "Usuário criado em"
@@ -38928,7 +39410,7 @@ msgid "Value might contain a variable reference"
msgstr ""
msgid "Value stream"
-msgstr ""
+msgstr "Fluxo de valor"
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -39009,7 +39491,7 @@ msgid "Variable"
msgstr "Variável"
msgid "Variable will be masked in job logs."
-msgstr ""
+msgstr "A variável será mascarada nos registros de tarefa."
msgid "Variables"
msgstr "Variáveis"
@@ -39071,6 +39553,18 @@ msgstr "Versão %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
msgstr "Versão %{versionNumber} (última)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "Ver documentação"
@@ -39142,7 +39636,7 @@ msgid "View full log"
msgstr "Ver log completo"
msgid "View group in admin area"
-msgstr ""
+msgstr "Ver grupo na área do administrador"
msgid "View group labels"
msgstr "Visualizar etiquetas de grupo"
@@ -39218,6 +39712,9 @@ msgstr[1] "Ver chaves GPG públicas"
msgid "View replaced file @ "
msgstr "Ver arquivo substituído @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr "Ver configuração"
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "Informações adicionais"
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr "Baixar"
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "Identificadores"
@@ -39512,6 +40021,9 @@ msgstr "Imagem"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "Links"
@@ -39524,6 +40036,9 @@ msgstr "Espaço de nome"
msgid "Vulnerability|Project"
msgstr "Projeto"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Ferramenta"
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "AVISO:"
@@ -39636,7 +40163,7 @@ msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %
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 ""
+msgstr "Recomendamos aplicativos de autenticação móvel baseados em nuvem, como Authy, Duo Mobile e LastPass. Podem restaurar o acesso se você perder seu dispositivo de hardware."
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -39678,10 +40205,10 @@ msgid "Web IDE"
msgstr "IDE Web"
msgid "Web Terminal"
-msgstr "Terminal Web"
+msgstr "Terminal web"
msgid "Web terminal"
-msgstr "Terminal Web"
+msgstr "Terminal web"
msgid "WebAuthn Devices (%{length})"
msgstr ""
@@ -39743,6 +40270,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr "Ajuda do Webhooks"
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "Comentários"
@@ -39785,6 +40354,9 @@ msgstr "Eventos de pipeline"
msgid "Webhooks|Push events"
msgstr "Eventos de push"
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr "Eventos de versões"
@@ -39815,56 +40387,11 @@ msgstr "Gatilho"
msgid "Webhooks|URL"
msgstr "URL"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr "URL é acionado por push para o repositório"
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr "O URL é acionado quando uma issue confidencial é criada, atualizada, fechada ou reaberta"
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr "URL é acionado quando uma implantação começa, termina, falha ou é cancelada"
-
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr "O URL é acionado quando um feature flag é ativado ou desativado"
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr "O URL é acionado quando um membro do grupo é criado, atualizado ou removido"
-
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr "O URL é acionado quando uma solicitação de mesclagem é criada, atualizada ou mesclada"
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr "O URL é acionado quando uma nova tag é enviada para o repositório"
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr "O URL é acionado quando uma versão é criada ou atualizada"
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr "O URL é acionado quando um subgrupo é criado ou removido"
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr "URL é acionado quando uma página wiki é criada ou atualizada"
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr "O URL é acionado quando uma issue é criada, atualizada, fechada ou reaberta"
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr "O URL é acionado quando alguém adiciona um comentário"
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr "O URL é acionado quando alguém adiciona um comentário sobre uma issue confidencial confidencial"
-
-msgid "Webhooks|URL is triggered when the job status changes"
-msgstr "O URL é acionado quando o status da tarefa muda"
-
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr "O URL é acionado quando o status do pipeline muda"
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr "O URL deve ser codificado em porcentagem, se necessário."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
+msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
-msgstr "Use este token para validar as cargas recebidas. Ele é enviado com a solicitação no cabeçalho Gitlab-Token HTTP."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
+msgstr ""
msgid "Webhooks|Webhook failed to connect"
msgstr ""
@@ -39971,11 +40498,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem ser especificadas sem desativar os recursos do projeto ou executar verificações de autorização externas."
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "Quando as solicitações de mesclagem e commits na ramificação padrão são fechadas, todas as issues aos quais eles fazem referência também são encerrados."
@@ -40282,7 +40809,13 @@ msgstr "Trabalho em andamento (aberto e não atribuído)"
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr "Você removerá %{group_name}. Isso também excluirá todos os seus subg
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "Você está prestes a remover a relação de fork do %{project_full_name}. Você tem CERTEZA disso?"
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr "Você irá transferir %{project_full_name} para outro espaço de nome. Tem certeza ABSOLUTA?"
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr "Você não está autorizado a atualizar este perfil"
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Você pode facilmente contribuir para eles pedindo para se juntar nesses
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40574,7 +41119,7 @@ msgid "You can recover this project until %{date}"
msgstr "Você pode recuperar este projeto até %{date}"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
-msgstr "Você pode resolver o conflito de mesclagem usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
+msgstr "Você pode resolver o conflito de mesclagem usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas mudanças em %{branch_name}"
msgid "You can see your chat accounts."
msgstr "Você pode ver suas contas de bate-papo."
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Você não tem permissão para deixar este %{namespaceType}."
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40717,7 +41265,7 @@ msgid "You have been redirected to the only result; see the %{a_start}search res
msgstr ""
msgid "You have been unsubscribed from this thread."
-msgstr ""
+msgstr "Você não está mais inscrito neste tópico."
msgid "You have declined the invitation to join %{title} %{name}."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40774,9 +41325,9 @@ msgid "You have reached your project limit"
msgstr "Você atingiu o limite de seu projeto"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
-msgstr ""
+msgstr "Você configurou o 2FA para sua conta! Se você perder o acesso ao seu dispositivo 2FA, poderá usar seus códigos de recuperação para acessar sua conta. Como alternativa, se você enviar uma chave SSH, poderá %{anchorOpen}usar essa chave para gerar códigos de recuperação adicionais%{anchorClose}."
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr "Você deve estar conectado para pesquisar em todo o GitLab"
@@ -41032,7 +41586,7 @@ msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
msgid "Your WebAuthn device was registered!"
-msgstr ""
+msgstr "Seu dispositivo WebAuthn foi registrado!"
msgid "Your access request to the %{source_type} has been withdrawn."
msgstr ""
@@ -41086,7 +41640,7 @@ msgid "Your changes have been saved"
msgstr "Suas alterações foram salvas"
msgid "Your changes have been successfully committed."
-msgstr "Suas alterações foram salvadas com sucesso."
+msgstr "Suas mudanças foram salvadas com sucesso."
msgid "Your comment could not be submitted because %{error}"
msgstr ""
@@ -41104,7 +41658,7 @@ msgid "Your commit email is used for web based operations, such as edits and mer
msgstr "Seu e-mail de commit é usado para operações baseadas na web, como edições e merges."
msgid "Your current password is required to register a two-factor authenticator app."
-msgstr ""
+msgstr "Sua senha atual é necessária para registrar um aplicativo autenticador de dois fatores."
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Seu nome"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41342,7 +41896,7 @@ msgid "access:"
msgstr ""
msgid "added"
-msgstr ""
+msgstr "adicionado"
msgid "added %{emails}"
msgstr "adicionou %{emails}"
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr "aprovado por: "
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr "criado em %{issuable_created} por %{author}"
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "criado em %{timeAgoString} por %{email} via %{user}"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "criado em %{timeAgoString} por %{user}"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "criado em %{timeAgoString} por %{user} no Jira"
-
msgid "created %{timeAgo}"
msgstr "criado em %{timeAgo}"
@@ -41995,6 +42554,9 @@ msgstr "falhou"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr "grupo"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr "não é permitido para este projeto."
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueador por %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr "Essa solicitação de mesclagem não contém alterações"
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Por favor, restaurar ou usar um branch %{missingBranchName} diferente"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,8 +42987,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr "Ocultar detalhe de %{widget}"
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr "Se a ramificação %{missingBranchName} existir em seu repositório local, você poderá fazer solicitação de mesclagem manualmente usando a linha de comando"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr "Se o ultimo pipeline foi executado no fork do projeto, pode ser impreciso. Antes de fazer o merge, recomendamos a execução de um pipeline nesse projeto"
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Falha ao mesclar."
@@ -42523,6 +43091,9 @@ msgstr "Abrir no IDE Web"
msgid "mrWidget|Plain diff"
msgstr "Diff em texto"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Pronto para ser mesclado automaticamente. Peça a alguém com acesso de gravação a este repositório para mesclar nessa requisição"
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr "Exibir detalhes de %{widget}"
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Houve merge das alterações em"
@@ -42577,9 +43151,6 @@ msgstr "Não houve merge para as mudanças em"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr "O pipeline para essse merge request não foi concluído. Faça um push em um novo commit para corrigir a falha, ou verifique a %{linkStart}documentação de solução de problemas%{linkEnd} para ver as possíveis ações."
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "O branch de origem foi excluído"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Sua senha"
-msgid "mrWidget|branch does not exist."
-msgstr "ramificação não existe."
-
msgid "mrWidget|into"
msgstr "para"
@@ -42899,9 +43467,6 @@ msgstr "repositório:"
msgid "required"
msgstr "obrigatório"
-msgid "reset it."
-msgstr "redefini-lo."
-
msgid "satisfied"
msgstr "satisfeito"
@@ -43002,7 +43567,7 @@ msgid "suggestPipeline|1/2: Choose a template"
msgstr ""
msgid "suggestPipeline|2/2: Commit your changes"
-msgstr ""
+msgstr "2/2: Confirme suas mudanças"
msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr "avatar do usuário"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "preferências do usuário"
-
msgid "username"
msgstr "nome do usuário"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 5c130c4c7ad..1822427e306 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} usa contas de gestão de grupo. Precisas de criar uma nova conta no GitLab que será gerida por %{group_name}."
@@ -722,6 +751,9 @@ msgstr "%{level_name} não é permitido num grupo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} não é permitido uma vez que o projeto de origem do fork tem uma visibilidade mais baixa."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "Não pode ser usado para acessar nenhum outro dado."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "Tokens de Acesso Pessoal"
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr "Adicionar CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Adicionar CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr "Adicionar URL Jaeger"
@@ -1991,7 +2011,7 @@ msgstr "Adicionar cluster Kubernetes"
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "Adicionar uma chave GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "Adicionar uma chave SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Administrador"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr "És tu!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Permitir pedidos à rede local dos hooks e serviços."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Ocorreu um erro"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,18 +3835,15 @@ msgstr "Ocorreu um erro ao buscar os trabalhos."
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Ocorreu um erro ao buscar os lançamentos. Por favor, tenta novamente."
msgid "An error occurred while fetching this tab."
msgstr "Ocorreu um erro ao buscar esta aba."
-msgid "An error occurred while generating a username. Please try again."
-msgstr ""
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr ""
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr "Tens a certeza de que desejas desarquivar este projeto?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "Tens a certeza de que queres remover esta identidade?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Tens a certeza de que desejas repor o token SCIM? O aprovisionamento de SCIM irá parar de funcionar até que o novo token seja atualizado."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Tens a certeza de que queres reiniciar o token de verificação de saúde?"
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "O avatar será removido. Tens a certeza?"
msgid "Average per day: %{average}"
msgstr "Média diária: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tem cuidado. Alterar o espaço de nomes do projeto pode ter efeitos secundários não intencionais."
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Abaixo vais encontrar todos os grupos que são públicos."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr "Importar do Bitbucket"
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Apagar ramos que foram mesclados"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Apagar ramos mesclados não pode ser desfeito. Tens a certeza?"
@@ -5958,9 +5990,6 @@ msgstr "Novo ramo"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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}'."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Para evitar a perda de dados, considera mesclar este ramo antes de apagá-lo."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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."
@@ -6036,9 +6056,6 @@ 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}."
-
msgid "Branches|diverged from upstream"
msgstr "divergiu da upstream"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Por padrão, todos os projetos e grupos usarão as definições globais de notificações."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Não pode ser mesclado automaticamente"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Não foi possível criar o relatório de abuso. O utilizador foi apagado."
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr "Cherry-pick este pedido de mesclagem"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "Certificado de autenticação do cliente"
-
-msgid "Client authentication key"
-msgstr "Chave de autenticação do cliente"
-
-msgid "Client authentication key password"
-msgstr "Palavra-chave de autenticação do cliente"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "Configurar instalação existente"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr "Erros encontrados no teu %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Os responsáveis do grupo podem registar executadores de grupo no %{link}"
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr "Nenhum objetivo para mostrar"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Nenhumas outras etiquetas com tal nome ou descrição"
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr "Repor os minutos do pipeline"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Repor os minutos de pipeline que foram usados"
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr "Mostrar descrição do envio"
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr "Último Contacto"
msgid "SortOptions|Last created"
msgstr "Último criado"
-msgid "SortOptions|Last updated"
-msgstr "Última atualização"
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Enviar ficheiro CSV"
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr "Também podes testar o teu %{gitlab_ci_yml} em %{lint_link_start}CI Lint
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Também podes enviar ficheiros existentes do teu computador ao usar as instruções abaixo."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "Não tens permissão para executar o Terminal de Web. Por favor, contacta um administrador de projeto."
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index a680cd102d2..eeb6add7633 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:41\n"
msgid " %{start} to %{end}"
msgstr " de la %{start} până la %{end}"
@@ -124,6 +124,30 @@ msgstr[0] "%d URL scanat"
msgstr[1] "%d URL-uri scanate"
msgstr[2] "%d de URL-uri scanate"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprobator"
@@ -532,6 +556,12 @@ msgstr[0] "%{bold_start}%{count}%{bold_end} merge request deschis"
msgstr[1] "%{bold_start}%{count}%{bold_end} cereri de îmbinare deschise"
msgstr[2] "%{bold_start}%{count}%{bold_end} de cereri de îmbinare deschise"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}Mascat:%{code_close} Ascuns în log-urile de joburi. Trebuie să corespundă cerințelor de mascare."
@@ -539,10 +569,10 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr "%{code_open}Protejat:%{code_close} Este expus numai la ramurile sau etichetele protejate."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} redactat %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} a redactat %{commit_authored_timeago} și %{commit_committer_avatar}%{commit_committer_link} a făcut commit %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} greutate finalizată"
@@ -703,6 +733,9 @@ msgstr "%{group_name} activitate"
msgid "%{group_name} group members"
msgstr "%{group_name} membri ai grupului"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} utilizează conturi gestionate de grup. Trebuie să creați un nou cont GitLab care va fi gestionat de %{group_name}."
@@ -799,6 +832,9 @@ msgstr "%{level_name} nu este permisă într-un grup %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} nu este permis, deoarece proiectul sursă al bifurcației are o vizibilitate mai mică."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}Învățați mai multe%{link_end} despre roluri."
@@ -808,6 +844,9 @@ msgstr "%{link_start}Eliminați %{draft_snippet} prefixul%{link_end} din titlu p
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Ce informații colectează GitLab Inc.?%{link_end}"
@@ -919,9 +958,6 @@ msgstr "%{placeholder} nu este o temă validă"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -955,6 +991,9 @@ msgstr "%{rotation} a fost recalculat cu participanții rămași. Vă rugăm să
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 "%{rotation} a fost recalculat cu participanții rămași. Vă rugăm să examinați noua configurare pentru %{rotation}. Este recomandat să luați legătura cu respondentul de apel curent pentru a asigura continuitatea acoperirii de apel."
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} rezultate pentru termenul '%{term}'"
@@ -1010,7 +1049,7 @@ msgid "%{start} to %{end}"
msgstr "de la %{start} până la %{end}"
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
-msgstr ""
+msgstr "%{strongOpen}Avertisment:%{strongClose} Link-urile grupului SAML pot determina GitLab să elimine automat membrii din grupuri."
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr "%{strongStart}Sfat:%{strongEnd} Puteți de asemenea să verificați cererile de îmbinare la nivel local %{linkStart}urmând aceste instrucțiuni%{linkEnd}"
@@ -1250,7 +1289,7 @@ msgid "(max size 15 MB)"
msgstr "(dimensiunea maximă 15 MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(opțional)"
msgid "(removed)"
msgstr "(eliminat)"
@@ -1948,21 +1987,12 @@ msgstr "Nu poate fi utilizat pentru a accesa alte date."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Păstrați acest token secret. Oricine îl are poate accesa obiectele statice ale depozitului ca și cum ar fi în locul dvs. Dacă se întâmplă asta vreodată, %{reset_link_start}resetați acest token%{reset_link_end}."
-
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Păstrați acest simbol secret. Oricine îl are poate crea probleme ca și cum ar fi în locul dvs. Dacă se întâmplă acest lucru, %{link_reset_it}."
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Păstrați acest simbol secret. Oricine îl are poate citi fluxurile RSS de activități și de probleme sau fluxul de calendar ca și cum ar fi în locul dvs. Dacă se întâmplă acest lucru, %{link_reset_it}."
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "Token-uri de acces personal"
@@ -1987,9 +2017,6 @@ msgstr "Tokenul dvs. de e-mail primit vă autentifică atunci când creați o no
msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
msgstr "Tokenul dvs. pentru obiecte statice vă autentifică atunci când obiectele statice din depozit (cum ar fi arhivele sau blob-urile) sunt servite dintr-un depozit extern."
-msgid "AccessTokens|reset this token"
-msgstr "resetează acest token"
-
msgid "AccessibilityReport|Learn more"
msgstr "Aflați mai multe"
@@ -2095,9 +2122,6 @@ msgstr "Adăugați CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Adăugați CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Adaugă GitLab la Slack"
-
msgid "Add Jaeger URL"
msgstr "Adăugați URL Jaeger"
@@ -2107,8 +2131,8 @@ msgstr "Adăugați cluster Kubernetes"
msgid "Add LICENSE"
msgstr "Adăugați LICENȚĂ"
-msgid "Add New Node"
-msgstr "Adăugați un nou nod"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Adăugați README"
@@ -2122,6 +2146,9 @@ msgstr "Adăugați un %{type}"
msgid "Add a GPG key"
msgstr "Adăugați o cheie GPG"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Adăugați un URL Jaeger pentru a înlocui această pagină cu un link către serverul Jaeger. Mai întâi trebuie să %{link_start_tag}instalați Jaeger%{link_end_tag}."
@@ -2188,6 +2215,9 @@ msgstr "Adăugați o acțiune de făcut"
msgid "Add an SSH key"
msgstr "Adăugați o cheie SSH"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Adăugați o problemă existentă"
@@ -2305,9 +2335,6 @@ msgstr "Adăugare hook sistem"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "Adăugați text paginii de autentificare. Markdown activat."
-msgid "Add to Slack"
-msgstr "Adăugare la Slack"
-
msgid "Add to board"
msgstr "Adăugare la bord"
@@ -2605,6 +2632,12 @@ msgstr "Sunteți pe cale de a opri toate joburile. Acest lucru va opri toate job
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Eroare la încărcarea statisticilor. Vă rugăm încercați din nou"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2761,6 +2794,9 @@ msgstr "(Dezactivat)"
msgid "AdminUsers|(Internal)"
msgstr "(Intern)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Aprobare în așteptare)"
@@ -2797,7 +2833,7 @@ msgstr "Ajustați setarea plafonului de utilizatori pe instanța dvs."
msgid "AdminUsers|Admin"
msgstr "Administrator"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2923,6 +2959,9 @@ msgstr "Dvs. sunteți!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "Aflați mai multe despre %{link_start}utilizatori interziși.%{link_end}"
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Autentificare"
@@ -2986,6 +3025,9 @@ msgstr "Acest utilizator nu poate accesa repozitorii git."
msgid "AdminUsers|The user can't log in."
msgstr "Acest utilizator nu se poate autentifica."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Utilizatorul va fi deconectat"
@@ -3088,8 +3130,8 @@ msgstr "Le puteți bana contul în viitor dacă este necesar."
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr "Puteți mereu să le debanați contul dacă este necesar. Datele lor vor rămâne intacte."
-msgid "AdminUsers|You cannot remove your own admin rights."
-msgstr "Nu vă puteți elimina propriile drepturi administrative."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "Trebuie să transferați proprietatea sau să ștergeți grupurile deținute de acest utilizator înainte de a le șterge contul."
@@ -3649,23 +3691,14 @@ msgstr "Permiteți proiectelor din cadrul acestui grup să utilizeze Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr "Permiteți accesul public la conducte și detalii de joburi, inclusiv la jurnalele de ieșire și la artefacte."
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Permiteți solicitări către rețeaua locală din hook-uri și servicii."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Permitere solicitări către rețeaua locală din hook-uri sistem"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Permiteți solicitări către rețeaua locală de la hook-uri și servicii web"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Permiteți subgrupurilor să își configureze propriile reguli de autentificare cu doi factori"
msgid "Allow this key to push to this repository"
msgstr "Permiteți acestei chei să facă push către acest repozitoriu"
-msgid "Allow this secondary node to replicate content on Object Storage"
-msgstr "Permiteți acestui nod secundar să reproducă conținutul pe Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
+msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
@@ -3775,9 +3808,6 @@ msgstr "A apărut o eroare"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr "O eroare de raportare în care rezultatul unui test indică incorect prezența unei vulnerabilități într-un sistem, când vulnerabilitatea nu este prezentă."
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "A apărut o eroare adăugând o schiță la subiect."
@@ -3925,18 +3955,15 @@ msgstr "A apărut o eroare la preluarea joburilor."
msgid "An error occurred while fetching the latest pipeline."
msgstr "A apărut o eroare la preluarea celei mai recente conducte."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "A apărut o eroare la preluarea lansărilor. Vă rugăm încercați din nou."
msgid "An error occurred while fetching this tab."
msgstr "A apărut o eroare la preluarea acestei file."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "A apărut o eroare în timpul generării unui nume de utilizator. Vă rugăm să încercați din nou."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "S-a produs o eroare în timpul obținerii datelor de autocompletare. Vă rugăm să reîmprospătați pagina și să încercați din nou."
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "A apărut o eroare în timpul obținerii fișierelor pentru - %{branchId}"
@@ -4190,7 +4217,7 @@ msgid "An unknown error occurred."
msgstr "A apărut o eroare necunoscută."
msgid "Analytics"
-msgstr ""
+msgstr "Statistici"
msgid "Analyze a review version of your web application."
msgstr "Analizați o versiune de revizuire a aplicației dvs. web."
@@ -4498,9 +4525,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Adăugați aprobatori"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr "Toate scanerele"
@@ -4531,9 +4555,6 @@ msgstr "Tip aprobator"
msgid "ApprovalRule|Approvers"
msgstr "Aprobatori"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4543,13 +4564,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Exemple: QA, Securitate."
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4576,7 +4597,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4591,6 +4612,9 @@ msgstr "Scanere de securitate"
msgid "ApprovalRule|Select All"
msgstr "Selectați tot"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Selectați scanerele"
@@ -4606,7 +4630,7 @@ msgstr "Nivele severitate"
msgid "ApprovalRule|Target branch"
msgstr "Ramura țintă"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4618,23 +4642,29 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Setările de aprobare a cererilor de îmbinare au fost actualizate."
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr "Prevenire aprobare de către autor."
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "Preveniți aprobări de la utilizatori care adaugă commit-uri."
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "Preveniți editarea regulilor de aprobare în merge request-uri."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Preveniți editarea regulilor de aprobare în proiecte și merge request-uri."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "Eliminați toate aprobările când commit-uri sunt adăugate ramurii sursă."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
-msgstr "Solicitați parola utilizator pentru aprobare."
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr "S-a întâmplat o eroare încărcând setările de aprobare a cererilor de îmbinare."
@@ -4747,6 +4777,9 @@ msgstr "Sunteți sigur că doriți să dezarhivați acest proiect?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr "Sunteți sigur că doriți să %{action} %{name}?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr "Sunteți sigur că vreți să încercați să îmbinați?"
@@ -4840,9 +4873,6 @@ msgstr "Sunteți sigur că doriți să eliminați această identitate?"
msgid "Are you sure you want to remove this list?"
msgstr "Sunteți sigur că doriți să eliminați această listă?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Sunteți sigur că doriți să resetați tokenul SCIM? Asigurarea accesului SCIM nu va mai funcționa până când noul token este actualizat."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Sunteți sigur că doriți să resetați tokenul de verificare a sănătății?"
@@ -4927,8 +4957,8 @@ msgstr "Întrebați din nou mai târziu"
msgid "Ask someone with write access to resolve it."
msgstr "Rugați pe cineva cu permisiuni de scriere să o rezolve."
-msgid "Ask your group maintainer to set up a group runner."
-msgstr "Solicitați întreținătorului grupului să configureze un executor de grup."
+msgid "Ask your group owner to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL aserțiune serviciu consumator"
@@ -5249,13 +5279,13 @@ msgid "Auto stop successfully canceled."
msgstr "Oprirea automată a fost anulată cu succes."
msgid "Auto-cancel redundant pipelines"
-msgstr ""
+msgstr "Auto-anularea conductelor redundante"
msgid "Auto-close referenced issues on default branch"
-msgstr ""
+msgstr "Închiderea automată a problemelor la care se face referire pe ramura implicită"
msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
-msgstr ""
+msgstr "%{auto_devops_start}Automatizați construirea, testarea și implementarea%{auto_devops_end} aplicațiilor dvs. pe baza integrării continue și a configurației de livrare. %{quickstart_start}Cum pot începe?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -5264,7 +5294,7 @@ msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Documentație Auto DevOps"
msgid "AutoDevOps|Dismiss Auto DevOps box"
-msgstr ""
+msgstr "Respingeți caseta Auto DevOps"
msgid "AutoDevOps|Enable in settings"
msgstr "Activați în setări"
@@ -5285,7 +5315,7 @@ msgid "AutoRemediation| 1 Merge Request"
msgstr "1 Merge Request"
msgid "AutoRemediation|%{mrsCount} ready for review"
-msgstr ""
+msgstr "%{mrsCount} gata pentru revizuire"
msgid "AutoRemediation|Auto-fix"
msgstr "Auto-fix"
@@ -5294,19 +5324,19 @@ msgid "AutoRemediation|Auto-fix solutions"
msgstr "Soluții Auto-fix"
msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
-msgstr ""
+msgstr "Dacă utilizați scanarea de dependență și/sau de container, iar auto-fix este activat, auto-fix creează automat cereri de îmbinare cu remedieri de vulnerabilități."
msgid "AutoRemediation|Introducing GitLab auto-fix"
-msgstr ""
+msgstr "Vă prezentăm GitLab auto-fix"
msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
-msgstr ""
+msgstr "Rollback-ul automat începe atunci când este declanșată o alertă critică. Dacă ultima implementare reușită nu reușește să se facă o revenire automată, aceasta se poate face în continuare manual."
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "Întoarceți automat la ultima implementare reușită atunci când este detectată o problemă critică."
msgid "AutoRollback|Enable automatic rollbacks"
-msgstr ""
+msgstr "Activați reveniri automate"
msgid "Autocomplete"
msgstr "Autocompletare"
@@ -5327,13 +5357,13 @@ msgid "Automatic certificate management using Let's Encrypt"
msgstr "Gestionarea automată a certificatelor utilizând Let's Encrypt"
msgid "Automatic deployment rollbacks"
-msgstr ""
+msgstr "Reveniri automate de implementare"
msgid "Automatic event tracking provides a traceable history for audits."
msgstr "Urmărire automată evenimente oferă un istoric traceable pentru audituri."
msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
-msgstr ""
+msgstr "Închideți automat incidentul asociat atunci când o notificare de alertă de recuperare rezolvă o alertă"
msgid "Automatically resolved"
msgstr "Rezolvată automat"
@@ -5371,6 +5401,9 @@ msgstr "Avatarul va fi eliminat. Sunteți sigur?"
msgid "Average per day: %{average}"
msgstr "Media pe zi: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr "Premiu adăugat"
@@ -5503,6 +5536,9 @@ msgstr "Utilizatorul cu acces API la serverul Bamboo."
msgid "Based on"
msgstr "Bazat pe"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Fiți atent. Schimbarea spațiului de nume al proiectului poate avea efecte secundare nedorite."
@@ -5516,13 +5552,13 @@ msgid "Before inserting code, be sure to read the comment that separated each co
msgstr "Înainte de a insera codul, asigurați-vă că ați citit comentariul care separă fiecare grup de cod."
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
-msgstr ""
+msgstr "Înainte ca aceasta să poată fi îmbinată, o problemă Jira trebuie să fie legată în titlu sau în descriere"
msgid "Begin with the selected commit"
msgstr "Începeți cu commit-ul selectat"
msgid "Below are the fingerprints for the current instance SSH host keys."
-msgstr ""
+msgstr "Mai jos sunt amprentele digitale pentru cheile gazdă SSH ale instanței curente."
msgid "Below are the settings for %{link_to_gitlab_pages}."
msgstr "Mai jos sunt setările pentru %{link_to_gitlab_pages}."
@@ -5530,11 +5566,14 @@ msgstr "Mai jos sunt setările pentru %{link_to_gitlab_pages}."
msgid "Below you will find all the groups that are public."
msgstr "Mai jos veți găsi toate grupurile care sunt publice."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Acoperire bi-săptămânală a codului"
msgid "Billable Users"
-msgstr ""
+msgstr "Utilizatori facturabili"
msgid "Billing"
msgstr "Facturare"
@@ -5545,9 +5584,6 @@ msgstr "%{group_name} utilizează în prezent %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name} utilizați în prezent %{plan_name}."
-msgid "BillingPlans|Compare all plans"
-msgstr "Comparați toate planurile"
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Felicitări, evaluarea dvs. gratuită este activată."
@@ -5561,13 +5597,13 @@ msgid "BillingPlans|If you would like to downgrade your plan please contact %{su
msgstr "Dacă doriți să vă reduceți planul, vă rugăm să contactați %{support_link_start}Suport Clienți%{support_link_end}."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
-msgstr ""
+msgstr "Aflați mai multe despre fiecare plan citind %{faq_link} nostru sau începeți o încercare gratuită de 30 de zile GitLab.com Ultimate."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Aflați mai multe despre fiecare plan vizitând pagina noastră %{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 ""
+msgstr "Încercați să achiziționați sau să gestionați un abonament pentru grupul dumneavoastră? Navigați la %{groups_link} și mergeți la %{strong_open}Setări &gt; Facturare.%{strong_close}"
msgid "BillingPlans|Manage plan"
msgstr "Gestionați planul"
@@ -5584,14 +5620,11 @@ msgstr "Acest grup utilizează planul asociat grupului său părinte."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Pentru a gestiona planul pentru acest grup, vizitați secțiunea de facturare a %{parent_billing_page_link}."
-msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
-msgstr "Actualizați la GitLab %{planNameForUpgrade}"
-
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 ""
+msgstr "Deși GitLab termină disponibilitatea planului de Bronz, încă mai puteți reînnoi abonamentul Bronz încă o dată înainte de %{eoa_bronze_plan_end_date}. Oferim, de asemenea, un upgrade gratuit pe timp limitat la planul nostru Premium (până la 25 de utilizatori)! Aflați mai multe despre modificările și ofertele noastre din %{announcement_link}."
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
-msgstr ""
+msgstr "Evaluarea ta GitLab.com %{plan} va %{strong_open} expira după %{expiration_date}%{strong_close}. Puteți păstra accesul la funcțiile %{plan} prin actualizarea de mai jos."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
msgstr "Perioada dvs. de evaluare GitLab.com a expirat la %{expiration_date}. Puteți restabili accesul la funcții în orice moment prin actualizarea de mai jos."
@@ -5615,10 +5648,10 @@ msgid "BillingPlans|per user"
msgstr "per utilizator"
msgid "BillingPlan|Upgrade"
-msgstr ""
+msgstr "Actualizare"
msgid "BillingPlan|Upgrade for free"
-msgstr ""
+msgstr "Actualizați gratuit"
msgid "Billings|%{planName} plan"
msgstr "Plan %{planName}"
@@ -5642,7 +5675,7 @@ msgid "Billings|Reactivate trial"
msgstr "Reactivați perioada de încercare"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr ""
+msgstr "Nu se pot activa executorii partajați până când nu este înregistrat un card de credit valabil."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -5665,20 +5698,26 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr "O adresă de e-mail este vizibilă doar pentru utilizatorii cu e-mailuri publice."
-msgid "Billing|An error occurred while getting a billable member details"
+msgid "Billing|An error occurred while approving %{user}"
msgstr ""
+msgid "Billing|An error occurred while getting a billable member details"
+msgstr "S-a produs o eroare în timpul obținerii detaliilor unui membru facturabil"
+
msgid "Billing|An error occurred while loading billable members list"
-msgstr ""
+msgstr "S-a produs o eroare la încărcarea listei membrilor facturabili"
msgid "Billing|An error occurred while loading pending members list"
msgstr ""
msgid "Billing|An error occurred while removing a billable member"
-msgstr ""
+msgstr "A apărut o eroare în timpul eliminării unui membru facturabil"
msgid "Billing|Awaiting member signup"
msgstr ""
@@ -5687,7 +5726,7 @@ msgid "Billing|Cannot remove user"
msgstr "Nu se poate elimina utilizatorul"
msgid "Billing|Direct memberships"
-msgstr ""
+msgstr "Abonamente directe"
msgid "Billing|Enter at least three characters to search."
msgstr "Introduceți cel puțin trei caractere pentru a căuta."
@@ -5717,7 +5756,7 @@ msgid "Billing|Remove user %{username} from your subscription"
msgstr "Eliminați utilizatorul %{username} din abonament"
msgid "Billing|Toggle seat details"
-msgstr ""
+msgstr "Comută detaliile locului"
msgid "Billing|Type %{username} to confirm"
msgstr "Tastați %{username} pentru a confirma"
@@ -5726,26 +5765,29 @@ msgid "Billing|User was successfully removed"
msgstr "Utilizatorul a fost eliminat cu succes"
msgid "Billing|Users occupying seats in"
-msgstr ""
+msgstr "Utilizatori care ocupă locuri în"
msgid "Billing|View pending approvals"
msgstr ""
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
-msgstr ""
+msgstr "Ești pe cale să elimini utilizatorul %{username} din abonament. Dacă continuați, utilizatorul va fi eliminat din grupul %{namespace} și din toate subgrupurile și proiectele acestuia. Această acțiune nu poate fi anulată."
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Import server Bitbucket"
msgid "Bitbucket Server import"
-msgstr ""
+msgstr "Import server Bitbucket"
msgid "Bitbucket import"
-msgstr ""
+msgstr "Import din Bitbucket"
msgid "Blame"
msgstr "Blame"
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Blocați utilizatorul"
@@ -5762,10 +5804,10 @@ msgid "Blocked issue"
msgstr "Problemă blocată"
msgid "Blocking"
-msgstr ""
+msgstr "Blocare"
msgid "Blocking issues"
-msgstr ""
+msgstr "Blocarea problemelor"
msgid "Blocks"
msgstr "Blocuri"
@@ -5777,25 +5819,25 @@ msgid "Board scope affects which epics are displayed for anyone who visits this
msgstr ""
msgid "Board scope affects which issues are displayed for anyone who visits this board"
-msgstr ""
+msgstr "Domeniul de aplicare al forumului afectează ce probleme sunt afișate pentru oricine vizitează acest panou"
msgid "BoardNewEpic|Groups"
msgstr "Grupuri"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Se încarcă grupurile"
msgid "BoardNewEpic|No matching results"
msgstr ""
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Căutați grupuri"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Selectați un grup"
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "Nu există rezultate potrivite"
msgid "BoardNewIssue|Projects"
msgstr "Proiecte"
@@ -5900,13 +5942,13 @@ msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr "A apărut o eroare în timpul preluării etichetelor. Vă rugăm să reîncărcați pagina."
msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
-msgstr ""
+msgstr "A apărut o eroare în timpul preluării epicelor panoului. Vă rugăm să reîncărcați pagina."
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "A apărut o eroare în timpul preluării problemelor de bord. Vă rugăm să reîncărcați pagina."
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
-msgstr ""
+msgstr "S-a produs o eroare în timpul preluării listelor de bord. Vă rugăm să reîncărcați pagina."
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr "A apărut o eroare în timpul preluării secțiunilor swimlanes. Vă rugăm să reîncărcați pagina."
@@ -5933,7 +5975,7 @@ msgstr[1] "Blocat de %{blockedByCount} %{issuableType}s"
msgstr[2] "Blocat de %{blockedByCount} %{issuableType}s"
msgid "Boards|Collapse"
-msgstr ""
+msgstr "Colapsare"
msgid "Boards|Edit board"
msgstr "Editați panoul"
@@ -5942,49 +5984,49 @@ msgid "Boards|Expand"
msgstr "Extindeți"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
-msgstr ""
+msgstr "Nu s-a putut prelua blocarea %{issuableType}s"
msgid "Boards|New board"
msgstr ""
msgid "Boards|New epic"
-msgstr ""
+msgstr "Epic nou"
msgid "Boards|Retrieving blocking %{issuableType}s"
-msgstr ""
+msgstr "Retragerea blocării %{issuableType}s"
msgid "Boards|View all blocking %{issuableType}s"
-msgstr ""
+msgstr "Vezi toate tipurile de blocare %{issuableType}s"
msgid "Boards|View scope"
-msgstr ""
+msgstr "Vezi domeniul de aplicare"
msgid "Board|An error occurred while fetching the board, please try again."
msgstr ""
msgid "Board|Are you sure you want to delete this board?"
-msgstr ""
+msgstr "Sunteți sigur că vreți să ștergeți acest bord?"
msgid "Board|Board scope"
-msgstr ""
+msgstr "Domeniul de aplicare"
msgid "Board|Create board"
-msgstr ""
+msgstr "Creare bord"
msgid "Board|Create new board"
-msgstr ""
+msgstr "Creare bord nou"
msgid "Board|Delete board"
-msgstr ""
+msgstr "Ștergere panou"
msgid "Board|Edit board"
-msgstr ""
+msgstr "Editare panou"
msgid "Board|Enter board name"
-msgstr ""
+msgstr "Introducere nume panou"
msgid "Board|Failed to delete board. Please try again."
-msgstr ""
+msgstr "Nu s-a reușit ștergerea panoului. Vă rugăm să încercați din nou."
msgid "Board|Load more epics"
msgstr "Încărcați mai multe epice"
@@ -5996,10 +6038,10 @@ msgid "Board|Loading epics"
msgstr "Se încarcă epicele"
msgid "Bold text"
-msgstr ""
+msgstr "Text îngroșat"
msgid "Both project and dashboard_path are required"
-msgstr ""
+msgstr "Atât proiectul cât și dashboard_path sunt necesare"
msgid "Branch"
msgstr "Ramură"
@@ -6008,7 +6050,7 @@ msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Ramura %{branchName} nu a fost găsită în repozitoriul acestui proiect."
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr ""
+msgstr "A fost creată ramura %{branch_name}. Pentru a configura implementarea automată, alegeți un șablon GitLab CI Yaml și commit modificările dvs. %{link_to_autodeploy_doc}"
msgid "Branch already exists"
msgstr "Ramura există deja"
@@ -6061,18 +6103,12 @@ msgstr "Ștergeți ramurile îmbinate"
msgid "Branches|Delete protected branch"
msgstr "Ștergeți ramura protejată"
-msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr "Ștergeți ramura protejată '%{branch_name}'?"
-
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
msgstr "Ștergeți ramura protejată. Sunteți ABSOLUT SIGUR?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
msgstr "Ștergerea %{strongStart}%{branchName}%{strongEnd} nu poate fi anulată. Sunteți sigur?"
-msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "Ștergerea ramurii '%{branch_name}' nu poate fi anulată. Sunteți sigur?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Ștergerea ramurilor îmbinate nu poate fi anulată. Sunteți sigur?"
@@ -6086,10 +6122,7 @@ msgid "Branches|New branch"
msgstr "Ramură nouă"
msgid "Branches|No branches to show"
-msgstr ""
-
-msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr "Odată ce confirmați și apăsați %{delete_protected_branch}, aceasta nu poate fi anulată sau recuperată."
+msgstr "Fără ramuri de afișat"
msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
msgstr "Odată ce confirmați și apăsați %{strongStart}%{buttonText},%{strongEnd} nu poate fi anulat sau recuperat."
@@ -6131,25 +6164,16 @@ msgid "Branches|Stale branches"
msgstr "Ramuri vechi"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr ""
+msgstr "Ramurile nu au putut fi actualizate automat, deoarece au deviat de la omologul său de mai sus."
msgid "Branches|The default branch cannot be deleted"
msgstr "Ramura implicită nu poate fi ștearsă"
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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-msgstr "Pentru a confirma, tastați %{branch_name_confirmation}:"
+msgstr "Această ramură nu a fost îmbinată în %{defaultBranchName}. Pentru a evita pierderea de date, luați în considerare îmbinarea acestei ramuri înainte de a o șterge."
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
-msgstr ""
+msgstr "Pentru a renunța la modificările locale și pentru a suprascrie ramura cu versiunea upstream, ștergeți-o aici și alegeți 'Actualizare imediată' de mai sus."
msgid "Branches|Unable to load branches"
msgstr ""
@@ -6166,14 +6190,11 @@ msgstr "Sunteți pe cale să ștergeți definitiv ramura %{strongStart}%{branchN
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr "Sunteți pe cale să ștergeți definitiv ramura protejată %{strongStart}%{branchName}.%{strongEnd}"
-msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "Sunteți pe cale să ștergeți definitiv ramura protejată %{branch_name}."
-
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "deviat din upstream"
msgid "Branches|merged"
-msgstr ""
+msgstr "îmbinate"
msgid "Branches|project settings"
msgstr "setările proiectului"
@@ -6182,22 +6203,22 @@ msgid "Branches|protected"
msgstr "protejat"
msgid "Breadcrumbs"
-msgstr ""
+msgstr "Breadcrumb-uri"
msgid "Brief title about the change"
msgstr "Titlu scurt despre schimbare"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "Mesajul difuzat a fost creat cu succes."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "Mesajul difuzat a fost actualizat cu succes."
msgid "Broadcast Messages"
-msgstr ""
+msgstr "Mesaje difuzate"
msgid "Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more."
-msgstr ""
+msgstr "Mesajele difuzate sunt afișate pentru fiecare utilizator și pot fi utilizate pentru a notifica utilizatorii cu privire la întreținerea programată, actualizările recente și multe altele."
msgid "Browse Directory"
msgstr "Explorați directorul"
@@ -6221,13 +6242,13 @@ msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "A apărut o eroare la preluarea artefactelor"
msgid "BuildArtifacts|Loading artifacts"
-msgstr ""
+msgstr "Încărcarea artefactelor"
msgid "Built-in"
-msgstr ""
+msgstr "ÃŽncorporat"
msgid "Bulk request concurrency"
-msgstr ""
+msgstr "Concurența cererilor în masă"
msgid "Bulk update"
msgstr "Actualizare în bloc"
@@ -6269,7 +6290,7 @@ msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
-msgstr ""
+msgstr "Ultima importare la %{link}"
msgid "BulkImport|Name already exists."
msgstr "Numele există deja."
@@ -6278,13 +6299,13 @@ msgid "BulkImport|Name already used as a target for another group."
msgstr ""
msgid "BulkImport|New group"
-msgstr ""
+msgstr "Grup nou"
msgid "BulkImport|No history is available"
msgstr ""
msgid "BulkImport|No parent"
-msgstr ""
+msgstr "Fără părinte"
msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
msgstr ""
@@ -6296,10 +6317,10 @@ msgid "BulkImport|Showing %{start}-%{end} of %{total} from %{link}"
msgstr "Se afișează %{start}-%{end} din %{total} de la %{link}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter}\" from %{link}"
-msgstr ""
+msgstr "Se afișează %{start}-%{end} din %{total} care se potrivește filtrului \"%{filter}\" din %{link}"
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "Grup sursă"
msgid "BulkImport|To new group"
msgstr ""
@@ -6364,6 +6385,15 @@ msgstr "Prin autentificarea cu un cont legat de o adresă de e-mail Întreprinde
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "În mod implicit, toate proiectele și grupurile vor utiliza setarea globală a notificărilor."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "de"
@@ -6410,34 +6440,46 @@ msgid "CICDAnalytics|All time"
msgstr ""
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "Frecvența de desfășurare"
msgid "CICDAnalytics|Lead time"
-msgstr ""
+msgstr "Timp de execuție"
msgid "CICDAnalytics|Projects with releases"
-msgstr ""
+msgstr "Proiecte cu lansări"
msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "Lansare"
+msgstr[1] "Lansări"
+msgstr[2] "Lansări"
msgid "CICDAnalytics|Release statistics"
-msgstr ""
+msgstr "Statistici de lansare"
msgid "CICDAnalytics|Releases"
+msgstr "Lansări"
+
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
msgstr ""
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
+msgstr "Ceva nu a funcționat la preluarea statisticilor de lansare"
+
+msgid "CICDAnalytics|What is shared runner usage?"
msgstr ""
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
-msgstr ""
+msgstr "Adaugați un %{base_domain_link_start}domeniu de bază%{link_end} la clusterul dvs. %{kubernetes_cluster_link_start}Kubernetes%{link_end} pentru ca strategia dvs. de implementare să funcționeze."
msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
-msgstr ""
+msgstr "Adaugați un %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} cu un domeniu, sau creați o variabilă CI AUTO_DEVOPS_PLATFORM_TARGET."
msgid "CICD|Add an existing project to the scope"
msgstr "Adăugați un proiect existent la domeniul de aplicare"
@@ -6446,13 +6488,13 @@ msgid "CICD|Auto DevOps"
msgstr "Auto DevOps"
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr ""
+msgstr "Implementarea automată în etape, implementarea manuală în producție"
msgid "CICD|Continuous deployment to production"
-msgstr ""
+msgstr "Implementarea continuă în producție"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Implementarea continuă a producției utilizând o lansare progresivă temporizată"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Implicit la conducta Auto DevOps"
@@ -6461,7 +6503,7 @@ msgid "CICD|Default to Auto DevOps pipeline for all projects"
msgstr "Implicit la conducta Auto DevOps pentru toate proiectele"
msgid "CICD|Deployment strategy"
-msgstr ""
+msgstr "Strategia de implementare"
msgid "CICD|Jobs"
msgstr "Job-uri"
@@ -6503,25 +6545,25 @@ msgid "CSV is being generated and will be emailed to you upon completion."
msgstr "CSV-ul se generează și va fi trimis dvs. prin e-mail la finalizare."
msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
-msgstr ""
+msgstr "În calitate de administrator, solicitarea unui CVE pentru o vulnerabilitate din proiectul dvs. va ajuta utilizatorii să rămână în siguranță și informați."
msgid "CVE|CVE ID Request"
-msgstr ""
+msgstr "Cerere ID CVE"
msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
msgstr "Identificatorii Common Vulnerability Enumeration (CVE) sunt utilizați pentru a urmări vulnerabilitățile distincte în anumite versiuni de cod."
msgid "CVE|Create CVE ID Request"
-msgstr ""
+msgstr "Crearea cererii CVE ID"
msgid "CVE|Enable CVE ID requests in the issue sidebar"
-msgstr ""
+msgstr "Activați cererile de ID CVE în bara laterală a problemei"
msgid "CVE|Request CVE ID"
msgstr "Solicitați ID-ul CVE"
msgid "CVE|Why Request a CVE ID?"
-msgstr ""
+msgstr "De ce solicitați un ID CVE?"
msgid "Cadence is not automated"
msgstr "Cadența nu este automatizată"
@@ -6530,7 +6572,7 @@ msgid "Calculate the number of slices during reindexing. The multiplier is appli
msgstr ""
msgid "Callback URL"
-msgstr ""
+msgstr "URL callback"
msgid "Campfire room ID (optional)"
msgstr "ID cameră Campfire (opțional)"
@@ -6560,7 +6602,7 @@ msgid "Can be overridden in each project."
msgstr "Poate fi suprascris în fiecare proiect."
msgid "Can create groups:"
-msgstr ""
+msgstr "Poate crea grupuri:"
msgid "Can't apply as the source branch was deleted."
msgstr "Nu se poate aplica deoarece ramura sursă a fost ștearsă."
@@ -6578,7 +6620,7 @@ msgid "Can't be empty"
msgstr "Nu poate fi gol"
msgid "Can't create snippet: %{err}"
-msgstr ""
+msgstr "Nu se poate crea un fragment: %{err}"
msgid "Can't fetch content for the blob: %{err}"
msgstr "Nu se poate prelua conținutul pentru blob: %{err}"
@@ -6596,16 +6638,16 @@ msgid "Can't scan the code?"
msgstr "Nu puteți scana codul?"
msgid "Can't update snippet: %{err}"
-msgstr ""
+msgstr "Nu se poate actualiza fragmentul: %{err}"
msgid "Canary"
-msgstr ""
+msgstr "Canary"
msgid "Canary Ingress does not exist in the environment."
-msgstr ""
+msgstr "Canary Ingress nu există în mediu."
msgid "Canary weight must be specified and valid range (0..100)."
-msgstr ""
+msgstr "Greutatea canarului trebuie să fie specificată și intervalul valabil (0..100)."
msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
msgstr ""
@@ -6667,6 +6709,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Nu se poate crea raportul de abuz. Utilizatorul a fost șters."
@@ -7048,6 +7093,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Adresa de facturare"
@@ -7225,6 +7273,9 @@ msgstr "Cherry-pick acest merge request"
msgid "Child"
msgstr "Copil"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7525,15 +7576,6 @@ msgstr "Clic pentru ascundere"
msgid "Click to reveal"
msgstr "Faceți clic pentru afișare"
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7630,6 +7672,12 @@ msgstr "ÃŽnchis: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Închide această %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Cluster"
@@ -7654,7 +7702,7 @@ msgstr "Tipul de cluster trebuie să fie specificat pentru Stages::ClusterEndpoi
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7699,7 +7747,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7729,7 +7777,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7786,13 +7834,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7819,7 +7870,7 @@ msgstr "Niciodată"
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7846,6 +7897,18 @@ msgstr "ÃŽnregistrarea Agentului"
msgid "ClusterAgents|Registration token"
msgstr "Token de înregistrare"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7858,6 +7921,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7882,7 +7948,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7900,6 +7966,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8851,6 +8920,9 @@ msgstr "Commit (la editarea mesajului de commit)"
msgid "Commit Message"
msgstr "Commit mesaj"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9100,6 +9172,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Component"
@@ -9130,6 +9205,12 @@ msgstr "Configurați %{repository_checks_link_start} controalele de repozitoriu%
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9175,12 +9256,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9208,12 +9292,18 @@ msgstr "ConfiguraÈ›i prima zi implicită a săptămânii È™i unitățile de urmÄ
msgid "Configure the way a user creates a new account."
msgstr "Configurați modul în care un utilizator creează un cont nou."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Confirmați noua parolă"
@@ -9775,7 +9865,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr "Controlați modul în care funcționează Registrul Pachetului GitLab."
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9916,9 +10006,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9931,9 +10036,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10006,6 +10108,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr "Nu s-a putut prelua politica, deoarece politica existentă YAML este invalidă"
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10033,13 +10138,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10183,6 +10291,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10441,6 +10552,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10675,6 +10789,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10909,6 +11026,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10918,10 +11038,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11011,12 +11131,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11029,9 +11143,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11044,9 +11155,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11119,9 +11227,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11149,9 +11254,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11161,12 +11263,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11179,9 +11275,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11203,9 +11296,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11476,9 +11566,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr "Ștergerea pretabilită întârziată a proiectului"
@@ -11911,6 +11998,9 @@ msgstr[2] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11926,6 +12016,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12139,9 +12232,39 @@ msgstr[2] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12706,9 +12829,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12775,7 +12895,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr "Afișați urmărirea timpului în probleme în ore totale numai."
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12970,7 +13090,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13216,6 +13336,9 @@ msgstr "Nu ne-am putut da seama ce utilizator corespunde e-mailului. Vă rugăm
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "Nu am putut găsi proiectul. Verificați dacă există vreo greșeală de scriere."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Nu aveți voie să efectuați această acțiune. Dacă credeți că este o eroare, contactați un reprezentant al personalului."
@@ -13360,9 +13483,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr "Activați menajul automat al repozitoriului"
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13405,6 +13525,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13432,6 +13555,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr "Activați verificările repozitoriului"
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13510,9 +13639,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13561,6 +13687,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13837,6 +13966,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr "de %{avatar}"
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14650,9 +14785,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14662,15 +14794,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14686,6 +14812,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14767,10 +14941,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15211,15 +15382,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15307,12 +15469,6 @@ msgstr "Filtru"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Filtrați după %{issuable_type} care sunt închise în prezent."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15637,6 +15793,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15712,6 +15871,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15748,18 +15910,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15796,6 +15961,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15850,6 +16018,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15925,12 +16096,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15946,6 +16111,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15979,16 +16147,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16000,9 +16171,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16051,6 +16219,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16087,10 +16261,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16168,6 +16342,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16291,9 +16468,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16318,6 +16492,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16498,6 +16675,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16636,6 +16816,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16804,6 +16987,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16822,6 +17008,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16885,9 +17074,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16912,6 +17098,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16924,9 +17113,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17167,18 +17353,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "Token-ul SCIM este ascuns. Pentru a vedea din nou valoarea tokenului, trebuie să "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17203,9 +17383,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17236,7 +17413,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17284,6 +17464,9 @@ msgstr "Dezactivați notificările prin e-mail"
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr "Activați eliminarea întârziată a proiectului"
@@ -17302,9 +17485,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17332,9 +17512,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17377,7 +17554,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17458,9 +17635,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17515,7 +17689,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17746,6 +17920,33 @@ msgstr[2] "Ascundeți valorile"
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17806,9 +18007,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17845,9 +18043,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17863,6 +18058,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr "Vreau să explorez GitLab pentru a vedea dacă merită să fac schimbarea"
@@ -17962,6 +18160,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17986,9 +18196,6 @@ msgstr "Dacă dezactivat, numai administratorii pot configura replicarea repozit
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18592,6 +18799,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18694,6 +18904,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18769,6 +18982,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19192,9 +19408,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr "Adăugarea unui spațiu de nume funcționează numai în browsere care permit cookie-uri cross-site. Utilizați %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, sau activați cookie-urile cross-site în browserul dvs., când adăugați un spațiu de nume."
-
msgid "Integrations|All details"
msgstr ""
@@ -19207,9 +19420,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19279,6 +19489,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr "Păstrați-vă dependențele PHP actualizate pe Packagist."
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19297,9 +19510,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr "Proiecte utilizând setări personalizate"
@@ -19336,6 +19546,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19345,6 +19558,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19405,7 +19621,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21226,6 +21442,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21556,9 +21775,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21574,6 +21790,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21610,6 +21829,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22384,6 +22636,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22402,9 +22660,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23227,9 +23494,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23251,9 +23515,6 @@ msgstr "Mai multe informații sunt disponibile|aici"
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23431,10 +23692,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23539,9 +23800,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23620,9 +23878,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23641,9 +23896,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24160,6 +24412,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24187,6 +24442,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24253,7 +24511,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25168,7 +25426,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25786,9 +26065,6 @@ msgstr "Inserați traiectoria proiectului (i.e. gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
msgstr "Lipiți acest DSN în SDK-ul dvs. Sentry"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25927,6 +26203,9 @@ msgstr "obiect"
msgid "PerformanceBar|wall"
msgstr "perete"
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr "Perioadă în secunde"
@@ -25945,7 +26224,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26212,9 +26491,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26227,6 +26503,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26239,7 +26518,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26404,10 +26683,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26590,6 +26887,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26605,6 +26905,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26959,6 +27265,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27184,6 +27493,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27208,9 +27520,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27388,6 +27697,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27433,9 +27745,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27958,10 +28267,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28039,6 +28351,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28084,6 +28402,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28210,9 +28531,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28234,7 +28552,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28252,7 +28570,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29014,9 +29332,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29050,7 +29365,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29296,6 +29611,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29365,6 +29686,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29440,7 +29764,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29983,6 +30307,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30211,6 +30541,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30286,9 +30619,6 @@ msgstr "Solicitări pentru pagini la %{code_start}%{help_text_url}%{code_end} su
msgid "Requests per period"
msgstr "Solicitări pe perioadă"
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr "Necesită autentificare suplimentară pentru sarcini administrative."
@@ -30307,6 +30637,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30436,9 +30769,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30505,7 +30835,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30607,13 +30937,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30634,6 +30964,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30721,6 +31054,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30733,9 +31069,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30754,6 +31096,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30769,9 +31114,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr "Executori grup"
-
msgid "Runners|IP Address"
msgstr ""
@@ -30820,10 +31162,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30859,6 +31204,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30898,16 +31246,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Executori"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30919,6 +31267,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30934,9 +31285,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr "Acest executor este asociat cu unul sau mai multe proiecte."
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31090,9 +31438,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31219,9 +31564,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31534,7 +31876,7 @@ msgstr "Aflați mai multe despre verificarea vulnerabilităților"
msgid "SecurityApprovals|License-Check"
msgstr "Verificarea licenței"
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31666,6 +32008,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "Detalii vulnerabilitate și statistici în cererea de îmbinare"
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr "%{branches}%{plural}"
@@ -31720,6 +32065,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr "Ultima scanare"
@@ -31738,21 +32086,30 @@ msgstr "Doar proprietarii pot actualiza Proiectul Politicii de Securitate"
msgid "SecurityOrchestration|Policies"
msgstr "Politici"
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr "Descrierea politicii"
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr "Tip politică"
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr "Regulă"
@@ -31762,12 +32119,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,6 +32161,12 @@ msgstr "Ne pare rău, filtrul dvs. nu a produs rezultate"
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31810,12 +32182,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr "+%{count} mai mult"
@@ -31825,6 +32245,9 @@ msgstr "Mediu (medii)"
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32146,9 +32569,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32536,7 +32956,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32545,6 +32965,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr "Ping serviciu este dezactivat în fișierul dvs. de configurație și nu poate fi activat prin acest formular."
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32554,18 +32977,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32704,7 +33121,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32878,9 +33295,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32920,6 +33334,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32932,6 +33349,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32944,9 +33364,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32971,6 +33388,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33013,7 +33433,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33106,6 +33526,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33208,9 +33631,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33517,9 +33964,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33583,9 +34027,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33919,6 +34360,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33961,6 +34405,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34303,6 +34750,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34333,6 +34783,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34411,9 +34882,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34582,9 +35050,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34609,6 +35074,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34648,6 +35116,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34702,6 +35173,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34714,6 +35188,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34957,6 +35440,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35029,6 +35515,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35203,6 +35692,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35377,9 +35869,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35419,12 +35908,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35434,9 +35917,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35470,7 +35950,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35638,6 +36118,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35713,9 +36196,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35731,9 +36211,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35852,7 +36329,7 @@ msgid "The vulnerability is known, and has not been remediated or mitigated, but
msgstr ""
msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
-msgstr ""
+msgstr "Această vulnerabilitate este cunoscută și nu a fost remediată sau atenuată, dar este considerată a fi o parte a aplicației care nu va fi actualizată."
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -36103,7 +36580,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36154,7 +36631,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36238,9 +36715,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36364,6 +36838,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36403,9 +36880,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36445,9 +36919,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36667,6 +37147,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36688,6 +37171,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36727,6 +37213,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36955,9 +37444,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37207,9 +37693,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37351,9 +37834,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr "Pentru a folosi formate suplimentare, trebuie să porniți %{container_link_start}containerele însoțitoare%{container_link_end}."
@@ -37369,9 +37849,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37579,9 +38056,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37693,6 +38167,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37708,15 +38185,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr "Prenume"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr "Nume"
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37757,7 +38228,7 @@ msgid "Trigger pipelines for mirror updates"
msgstr ""
msgid "Trigger pipelines when branches or tags are updated in the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "Declanșează conducte când ramuri sau etichete sunt actualizate în repozitoriul upstream. În funcție de activitatea repozitoriului upstream, acest lucru poate crește foarte mult sarcina executorilor voștri CI. Activați acest lucru doar dacă știți că se pot ocupa de sarcină."
msgid "Trigger removed."
msgstr ""
@@ -37783,6 +38254,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38228,7 +38705,7 @@ msgid "Update %{sourcePath} file"
msgstr ""
msgid "Update Now"
-msgstr ""
+msgstr "Actualizare imediată"
msgid "Update Scheduled…"
msgstr ""
@@ -38261,7 +38738,7 @@ msgid "Update milestone"
msgstr ""
msgid "Update now"
-msgstr ""
+msgstr "Actualizare imediată"
msgid "Update username"
msgstr ""
@@ -38302,6 +38779,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38323,6 +38803,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38758,6 +39241,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39289,6 +39775,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39439,6 +39937,9 @@ msgstr[2] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39664,6 +40165,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39706,6 +40210,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39724,6 +40231,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39733,6 +40246,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39745,6 +40261,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39757,6 +40276,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39781,9 +40303,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "ATENÈšIE:"
@@ -39964,127 +40495,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr "URL-ul este declanșat atunci când este creat, actualizat sau îmbinat un merge request."
+msgid "Webhooks|Releases events"
+msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40192,12 +40723,12 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
+msgstr ""
+
msgid "When inactive, an external authentication provider must be used."
msgstr "Când inactiv, un furnizor de autentificare extern trebuie utilizat."
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr ""
-
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40504,7 +41035,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40606,6 +41143,9 @@ msgstr "Veți elimina %{group_name}. Această acțiune va elimina de asemenea ș
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40639,6 +41179,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40687,6 +41230,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40732,6 +41278,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr "Puteți activa Funcțiile de Înregistrare pentru că Ping Serviciu este activat. Pentru a continua să folosiți Funcțiile de Întregistrare în viitor, va trebui de asemenea să vă înregistrați cu GitLab printr-un nou serviciu de licențiere cloud."
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40867,6 +41416,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40960,6 +41512,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40999,7 +41554,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41014,6 +41569,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41395,8 +41953,8 @@ msgstr "Numele dvs."
msgid "Your new %{type}"
msgstr "Noul tău %{type}"
-msgid "Your new SCIM token"
-msgstr "Noul dvs. token SCIM"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr "Noul dvs. comentariu"
@@ -41404,9 +41962,6 @@ msgstr "Noul dvs. comentariu"
msgid "Your new personal access token has been created."
msgstr "Token-ul dvs. de acces personal a fost creat."
-msgid "Your new project access token has been created."
-msgstr "Noul dvs. token de acces la proiect a fost creat."
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "Parola dvs. nu este necesară pentru a vizualiza această pagină. Dacă se solicită o parolă sau orice alte detalii personale, vă rugăm să contactați administratorul pentru a raporta abuzul."
@@ -41473,6 +42028,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "Abonamentul dvs. a expirat!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41605,6 +42163,12 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "approved by: "
msgstr "aprobat de: "
@@ -41689,6 +42253,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr "nu poate fi activat deoarece grupul părinte nu o permite"
@@ -42064,6 +42631,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "container_name poate conține numai litere mici, cifre, '-' și '.' și trebuie să înceapă și să se termine cu un caracter alfanumeric"
@@ -42091,12 +42661,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "creat %{timeAgoString} de %{email} prin %{user}"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "creat %{timeAgoString} de %{user}"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "creat %{timeAgoString} de %{user} în Jira"
-
msgid "created %{timeAgo}"
msgstr "creat %{timeAgo}"
@@ -42226,6 +42790,9 @@ msgstr "eșuat"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42274,6 +42841,12 @@ msgstr ""
msgid "group"
msgstr "grup"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "membrii grupului"
@@ -42391,6 +42964,9 @@ msgstr "nu este permis pentru acest proiect."
msgid "is not allowed since the group is not top-level group."
msgstr "nu este permis, deoarece grupul nu este un grup de nivel superior."
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42487,9 +43063,6 @@ msgstr "se încarcă"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "blocat de %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "autentificare"
-
msgid "manual"
msgstr "manual"
@@ -42532,9 +43105,6 @@ msgstr "Acest merge request nu conține modificări."
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42658,7 +43228,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42706,6 +43276,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42760,6 +43333,9 @@ msgstr "Deschideți în Web IDE"
msgid "mrWidget|Plain diff"
msgstr "Diff simplu"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42805,6 +43381,9 @@ msgstr "Setat de %{merge_author} pentru a începe un merge train când conducta
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42814,9 +43393,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Ramura sursă a fost ștearsă"
@@ -42853,9 +43429,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Parola dvs."
-msgid "mrWidget|branch does not exist."
-msgstr "ramura nu există."
-
msgid "mrWidget|into"
msgstr "în"
@@ -43141,9 +43714,6 @@ msgstr "repozitoriu:"
msgid "required"
msgstr "necesar"
-msgid "reset it."
-msgstr "resetați-l."
-
msgid "satisfied"
msgstr "satisfăcut"
@@ -43324,9 +43894,6 @@ msgstr "avatar utilizator"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "preferințele utilizatorului"
-
msgid "username"
msgstr "utilizator"
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 242e89881a0..be894296c2b 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -68,27 +68,27 @@ 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 "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (закрыто)"
msgid "#general, #development"
msgstr ""
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Оповещение"
+msgstr[1] "%d ОповещениÑ"
+msgstr[2] "%d Оповещений"
+msgstr[3] "%d Оповещений"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Оповещение:"
+msgstr[1] "%d ОповещениÑ:"
+msgstr[2] "%d Оповещений:"
+msgstr[3] "%d Оповещений:"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -132,6 +132,34 @@ msgstr[1] "%dURL проÑканировано"
msgstr[2] "%d URL проÑканировано"
msgstr[3] "%d URL проÑканировано"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d утверждающий"
@@ -190,10 +218,10 @@ msgstr[3] "%d комментариев к Ñтому коммиту"
msgid "%d commenter"
msgid_plural "%d commenters"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d комментатор"
+msgstr[1] "%d комментатора"
+msgstr[2] "%d комментаторов"
+msgstr[3] "%d комментаторов"
msgid "%d commit"
msgid_plural "%d commits"
@@ -204,10 +232,10 @@ msgstr[3] "%d коммитов"
msgid "%d commit author"
msgid_plural "%d commit authors"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d автор коммита"
+msgstr[1] "%d автора коммита"
+msgstr[2] "%d авторов коммита"
+msgstr[3] "%d авторов коммита"
msgid "%d commit behind"
msgid_plural "%d commits behind"
@@ -302,10 +330,10 @@ msgstr[3] "%d иÑправленные результаты теÑта"
msgid "%d fork"
msgid_plural "%d forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d ответвление"
+msgstr[1] "%d ответвлениÑ"
+msgstr[2] "%d ответвлений"
+msgstr[3] "%d ответвлений"
msgid "%d group"
msgid_plural "%d groups"
@@ -379,10 +407,10 @@ msgstr[3] "%d запроÑов на ÑлиÑние, к которым у ваÑ
msgid "%d merge requests"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgstr[1] "%d запроÑа на ÑлиÑние"
+msgstr[2] "%d запроÑов на ÑлиÑние"
+msgstr[3] "%d запроÑов на ÑлиÑние"
msgid "%d metric"
msgid_plural "%d metrics"
@@ -477,10 +505,10 @@ msgstr[3] "%d шардов выбрано"
msgid "%d star"
msgid_plural "%d stars"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d звезда"
+msgstr[1] "%d звезды"
+msgstr[2] "%d звёзд"
+msgstr[3] "%d звёзд"
msgid "%d tag"
msgid_plural "%d tags"
@@ -556,10 +584,10 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{actionText} & close %{noteable}"
-msgstr ""
+msgstr "%{actionText} и закрыть %{noteable}"
msgid "%{actionText} & reopen %{noteable}"
-msgstr ""
+msgstr "%{actionText} и переоткрыть %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} — недопуÑтимый диапазон IP-адреÑов"
@@ -568,7 +596,7 @@ msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disab
msgstr "%{anchorOpen}Узнайте больше%{anchorClose} о том, как наÑтроить/отключить региÑтрацию на Ñвоем ÑкземплÑре."
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}. У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к новому проекту."
@@ -584,10 +612,10 @@ msgstr ""
msgid "%{bold_start}%{count}%{bold_end} issue"
msgid_plural "%{bold_start}%{count}%{bold_end} issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} обÑуждение"
+msgstr[1] "%{bold_start}%{count}%{bold_end} обÑуждениÑ"
+msgstr[2] "%{bold_start}%{count}%{bold_end} обÑуждений"
+msgstr[3] "%{bold_start}%{count}%{bold_end} обÑуждений"
msgid "%{bold_start}%{count}%{bold_end} member"
msgid_plural "%{bold_start}%{count}%{bold_end} members"
@@ -598,10 +626,16 @@ msgstr[3] "%{bold_start}%{count}%{bold_end} пользователей"
msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} открытый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgstr[1] "%{bold_start}%{count}%{bold_end} открытых запроÑа на ÑлиÑние"
+msgstr[2] "%{bold_start}%{count}%{bold_end} открытых запроÑов на ÑлиÑние"
+msgstr[3] "%{bold_start}%{count}%{bold_end} открытых запроÑов на ÑлиÑние"
+
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -649,23 +683,23 @@ msgstr "%{count} ÑоглаÑований от %{name}"
msgid "%{count} contact"
msgid_plural "%{count} contacts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} контакт"
+msgstr[1] "%{count} контакта"
+msgstr[2] "%{count} контактов"
+msgstr[3] "%{count} контактов"
msgid "%{count} files touched"
msgstr "затронуто %{count} файлов"
msgid "%{count} item"
msgid_plural "%{count} items"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} Ñлемент"
+msgstr[1] "%{count} Ñлемента"
+msgstr[2] "%{count} Ñлементов"
+msgstr[3] "%{count} Ñлементов"
msgid "%{count} items per page"
-msgstr ""
+msgstr "%{count} Ñлементов на Ñтранице"
msgid "%{count} more"
msgstr "ещё %{count}"
@@ -712,7 +746,7 @@ 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} или docker-образ Ð´Ð»Ñ %{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}"
@@ -721,16 +755,16 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_e
msgstr ""
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}РаÑширенный поиÑк%{doc_link_end} включен."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Узнайте об уровнÑÑ… видимоÑти.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Что такое хранилище больших файлов?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Что такое Ð´Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr ""
@@ -751,7 +785,7 @@ msgid "%{edit_in_new_fork_notice} Try to upload a file again."
msgstr "%{edit_in_new_fork_notice} Попробуйте загрузить файл еще раз."
msgid "%{emailPrefix}@company.com"
-msgstr ""
+msgstr "%{emailPrefix}@company.com"
msgid "%{extra} more downstream pipelines"
msgstr "%{extra} больше загруженных Ñборочных линий"
@@ -766,25 +800,28 @@ 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 ""
+msgstr "%{gitlab_experience_text}. Мы никому не будем передавать Ñту информацию."
msgid "%{global_id} is not a valid ID for %{expected_types}."
-msgstr ""
+msgstr "%{global_id} не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым ID Ð´Ð»Ñ %{expected_types}."
msgid "%{group_name} activity"
-msgstr ""
+msgstr "активноÑÑ‚ÑŒ %{group_name}"
msgid "%{group_name} group members"
msgstr "УчаÑтники группы %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} иÑпользует управлÑемые групповые аккаунты. Вам нужно Ñоздать новый аккаунт GitLab, который будет управлÑÑ‚ÑŒÑÑ %{group_name}."
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}&%{epic_iid} &middot; Ñоздана пользователем %{author} %{epic_created}"
msgid "%{hook_type} was deleted"
msgstr ""
@@ -823,7 +860,7 @@ msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}КлаÑÑ:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}ÐÐ´Ñ€ÐµÑ ÑбоÑ:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}СоÑтоÑние ÑбоÑ:%{labelEnd} %{stacktrace_snippet}"
@@ -856,19 +893,19 @@ msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Ðемодифицированный ответ:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупно"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
msgstr ""
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} — Ñто беÑплатный, автоматизированный и открытый центр Ñертификации (CA), который предоÑтавлÑет цифровые Ñертификаты Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ HTTPS (SSL/TLS) на веб-Ñайтах."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr "%{level_name} не допуÑкаетÑÑ Ð² %{group_level_name} группе."
@@ -876,29 +913,35 @@ msgstr "%{level_name} не допуÑкаетÑÑ Ð² %{group_level_name} груÐ
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} запрещено, Ñ‚.к. проект-иÑточник Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ более узкую облаÑÑ‚ÑŒ видимоÑти."
-msgid "%{link_start}Learn more%{link_end} about roles."
+msgid "%{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "%{link_start}Learn more%{link_end} about roles."
+msgstr "%{link_start}Подробнее%{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 "%{link_start}Удалите Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ %{draft_snippet}%{link_end} из заголовка, чтобы позволить Ñтому запроÑу на ÑлиÑние выполнитьÑÑ Ð¿Ñ€Ð¸ готовноÑти."
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr "%{link_start}Ðачните заголовок Ñ %{draft_snippet}%{link_end}, чтобы предотвратить ÑлиÑние черновика запроÑа на ÑлиÑние до того, как он будет готов."
+
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Какую информацию Ñобирает GitLab Inc.?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
-msgstr ""
+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} можно объединить"
@@ -952,7 +995,7 @@ msgid "%{name}(%{url}) namespace has run out of Shared Runner Pipeline minutes s
msgstr ""
msgid "%{name}, confirm your email address now!"
-msgstr ""
+msgstr "%{name}, подтвердите ваш email ÑейчаÑ!"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
@@ -968,10 +1011,10 @@ msgid "%{oneMonthAgo} - %{today}"
msgstr ""
msgid "%{oneWeekAgo} - %{today}"
-msgstr ""
+msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
-msgstr ""
+msgstr "%{oneYearAgo} - %{today}"
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} открыто, %{closedEpics} закрыто"
@@ -997,9 +1040,6 @@ msgstr "%{placeholder} не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимой темой"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1126,10 +1169,10 @@ msgstr[3] ""
msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{strong_start}%{count} учаÑтник%{strong_end} должен одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
+msgstr[1] "%{strong_start}%{count} учаÑтника%{strong_end} должны одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
+msgstr[2] "%{strong_start}%{count} учаÑтников%{strong_end} должны одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
+msgstr[3] "%{strong_start}%{count} учаÑтников%{strong_end} должны одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} Файлов"
@@ -1224,25 +1267,25 @@ msgid "%{user_name} profile page"
msgstr "Ñтраница Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %{user_name}"
msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
+msgstr "%{username} изменил ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡ÐµÑ€Ð½Ð¾Ð²Ð¸ÐºÐ° запроÑа на ÑлиÑние %{mr_link}"
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
-msgstr ""
+msgstr "%{username} запрашивает Ð´Ð»Ñ ÑÐµÐ±Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½ÑƒÑŽ запиÑÑŒ GitLab на вашем ÑкземплÑре %{host}:"
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} is not included in the list"
-msgstr ""
+msgstr "%{value} не ÑодержитÑÑ Ð² ÑпиÑке"
msgid "%{value} s"
msgstr "%{value} Ñ"
@@ -1251,34 +1294,34 @@ msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} потраченного времени."
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} позволÑÑŽÑ‚ отправлÑÑ‚ÑŒ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÐ±-приложениÑм в ответ на ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð² группе или проекте."
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} позволÑÑŽÑ‚ отправлÑÑ‚ÑŒ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÐ±-приложениÑм в ответ на ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð² группе или проекте. Мы рекомендуем иÑпользовать %{integrations_link_start}интеграции%{link_end} вмеÑто веб-обработчиков."
msgid "%{widget} options"
msgstr ""
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}шаблоны%{wildcards_link_end}, такие как %{code_tag_start}v*%{code_tag_end} или %{code_tag_start}*-release%{code_tag_end}."
msgid "'%{data}' at %{location} does not match format: %{format}"
-msgstr ""
+msgstr "'%{data}' в %{location} не ÑоответÑтвует формату: %{format}"
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "%{data}' в %{location} не ÑоответÑтвует шаблону: %{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "'%{data}' в %{location} ÑвлÑетÑÑ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтимым: error_type=%{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "'%{data}' в %{location} не отноÑитÑÑ Ðº типу: %{type}"
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}' не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым уровнем видимоÑти"
@@ -1309,10 +1352,10 @@ msgid "(%{mrCount} merged)"
msgstr "(%{mrCount} объединено)"
msgid "(%{value}) has already been taken"
-msgstr ""
+msgstr "(%{value}) уже иÑпользуетÑÑ"
msgid "(+%{count}&nbsp;rules)"
-msgstr ""
+msgstr "(+%{count}&nbsp;правил)"
msgid "(Group Managed Account)"
msgstr ""
@@ -1321,7 +1364,7 @@ msgid "(No changes)"
msgstr "(Без изменений)"
msgid "(UTC %{offset}) %{timezone}"
-msgstr ""
+msgstr "(UTC %{offset}) %{timezone}"
msgid "(check progress)"
msgstr "(прогреÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸)"
@@ -1333,7 +1376,7 @@ msgid "(expired)"
msgstr ""
msgid "(leave blank if you don't want to change it)"
-msgstr ""
+msgstr "(не заполнÑйте, еÑли хотите оÑтавить без изменений)"
msgid "(max size 15 MB)"
msgstr "(макÑ. размер 15 Мбайт)"
@@ -1349,22 +1392,22 @@ msgstr "(отозван)"
msgid "(squashes %d commit)"
msgid_plural "(squashes %d commits)"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "(объединÑет иÑторию %d коммита)"
+msgstr[1] "(объединÑет иÑторию %d коммитов)"
+msgstr[2] "(объединÑет иÑторию %d коммитов)"
+msgstr[3] "(объединÑет иÑторию %d коммитов)"
msgid "(this user)"
-msgstr ""
+msgstr "(Ñтот пользователь)"
msgid "(we need your current password to confirm your changes)"
-msgstr ""
+msgstr "(нам нужен ваш текущий пароль Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹)"
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* Ð’Ñ€ÐµÐ¼Ñ Ð¾Ñ‚Ð½Ð¾Ñительно UTC, еÑли не указано иное."
msgid "*Required"
-msgstr ""
+msgstr "*ОбÑзательно"
msgid "+ %{amount} more"
msgstr "+%{amount} ещё"
@@ -1389,7 +1432,7 @@ msgid "+%{approvers} more approvers"
msgstr "+ещё %{approvers} утверждающих"
msgid "+%{extra} more"
-msgstr ""
+msgstr "+ещё %{extra}"
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
@@ -1398,7 +1441,7 @@ msgid "+%{more_assignees_count} more assignees"
msgstr ""
msgid "+%{more_reviewers_count}"
-msgstr ""
+msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
msgstr ""
@@ -1407,7 +1450,7 @@ msgid "+%{tags} more"
msgstr "+ещё %{tags}"
msgid ", and "
-msgstr ""
+msgstr ", и "
msgid ", or "
msgstr ", или "
@@ -1429,7 +1472,7 @@ msgid "- Not available to run jobs."
msgstr ""
msgid "- Select -"
-msgstr ""
+msgstr "- Выбрать -"
msgid "- User"
msgid_plural "- Users"
@@ -1448,7 +1491,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 байт"
@@ -1493,10 +1536,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 day selected"
msgid_plural "%d days selected"
@@ -1514,10 +1557,10 @@ msgstr[3] "%d ключей развёртываниÑ"
msgid "1 follower"
msgid_plural "%{count} followers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 подпиÑчик"
+msgstr[1] "%{count} подпиÑчика"
+msgstr[2] "%{count} подпиÑчиков"
+msgstr[3] "%{count} подпиÑчиков"
msgid "1 group"
msgid_plural "%d groups"
@@ -1535,17 +1578,17 @@ msgstr[3] "%d чаÑов"
msgid "1 issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "выбрано 1 обÑуждение"
+msgstr[1] "выбраны %d обÑуждениÑ"
+msgstr[2] "выбрано %d обÑуждений"
+msgstr[3] "выбрано %d обÑуждений"
msgid "1 merge request selected"
msgid_plural "%d merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "выбран 1 Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgstr[1] "выбрано %d запроÑа на ÑлиÑние"
+msgstr[2] "выбрано %d запроÑов на ÑлиÑние"
+msgstr[3] "выбрано %d запроÑов на ÑлиÑние"
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
@@ -1563,10 +1606,10 @@ msgstr[3] "%d минут"
msgid "1 month remaining"
msgid_plural "%d months remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "оÑталÑÑ 1 меÑÑц"
+msgstr[1] "оÑталоÑÑŒ %d меÑÑца"
+msgstr[2] "оÑталоÑÑŒ %d меÑÑцев"
+msgstr[3] "оÑталоÑÑŒ %d меÑÑцев"
msgid "1 open issue"
msgid_plural "%{issues} open issues"
@@ -1605,17 +1648,17 @@ msgstr[3] "%{num} пользователей"
msgid "1 week remaining"
msgid_plural "%d weeks remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "оÑталаÑÑŒ 1 неделÑ"
+msgstr[1] "оÑталоÑÑŒ %d недели"
+msgstr[2] "оÑталоÑÑŒ %d недель"
+msgstr[3] "оÑталоÑÑŒ %d недель"
msgid "1 year remaining"
msgid_plural "%d years remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "оÑталÑÑ 1 год"
+msgstr[1] "оÑталоÑÑŒ %d года"
+msgstr[2] "оÑталоÑÑŒ %d лет"
+msgstr[3] "оÑталоÑÑŒ %d лет"
msgid "1-9 contributions"
msgstr "1-9 ÑодейÑтвий"
@@ -1624,10 +1667,10 @@ msgid "10-19 contributions"
msgstr "10-19 ÑодейÑтвий"
msgid "1000+"
-msgstr ""
+msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "Первый вклад!"
@@ -1678,7 +1721,7 @@ msgid "8 hours"
msgstr "8 чаÑов"
msgid ":%{startLine} to %{endLine}"
-msgstr ""
+msgstr ": Ñ %{startLine} по %{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
@@ -1687,22 +1730,22 @@ msgid "A .NET Core console application template, customizable for any .NET Core
msgstr "Шаблон конÑольного Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ .NET Core, наÑтраиваемый Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ проекта .NET Core"
msgid "A CI/CD pipeline must run and be successful before merge."
-msgstr ""
+msgstr "Сборка CI/CD должна быть запущена и завершитьÑÑ ÑƒÑпешно до ÑлиÑниÑ."
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Сайт GitBook иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
msgid "A Gitpod configured Webapplication in Spring and Java"
msgstr "ÐаÑтроенное через Gitpod веб-приложение на Spring и Java"
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Сайт Hexo иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Сайт Hugo иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Сайт Jekyll иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
msgstr "SSL Ñертификат Let's Encrypt не может быть получен, пока ваш домен не будет проверен."
@@ -1714,7 +1757,7 @@ msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gatewa
msgstr "ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñтраница и беÑÑÐµÑ€Ð²ÐµÑ€Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ, иÑпользующие 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 complete DevOps platform"
msgstr "КомплекÑÐ½Ð°Ñ DevOps-платформа"
@@ -1726,7 +1769,7 @@ msgid "A deleted user"
msgstr "Удаленный пользователь"
msgid "A different reason"
-msgstr ""
+msgstr "Ð”Ñ€ÑƒÐ³Ð°Ñ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½Ð°"
msgid "A file has been changed."
msgstr "Файл был изменён."
@@ -1738,13 +1781,13 @@ msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "Файл '%{file_name}' уже ÑущеÑтвует в ветке %{branch}"
msgid "A group is a collection of several projects"
-msgstr ""
+msgstr "Группа — Ñто набор из неÑкольких проектов"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
-msgstr ""
+msgstr "Группа предÑтавлÑет вашу организацию в GitLab. Группы позволÑÑŽÑ‚ вам управлÑÑ‚ÑŒ пользователÑми и ÑовмеÑтно работать над неÑколькими проектами."
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 ""
@@ -1756,10 +1799,10 @@ msgid "A member of the abuse team will review your report as soon as possible."
msgstr "УчаÑтник команды по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñми раÑÑмотрит ваш отчет при первой возможноÑти."
msgid "A merge request hasn't yet been merged"
-msgstr ""
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние еще не Ñлит"
msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps Ñоздана, обратитеÑÑŒ к Ñтранице, поÑвÑщенной Сборочным линиÑм за подробноÑÑ‚Ñми"
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "Ðовый релиз %{tag} Ð´Ð»Ñ %{name} опубликован. ПоÑетите Ñтраницу %{release_link_start}Релизов%{release_link_end}, чтобы узнать больше."
@@ -1774,40 +1817,40 @@ msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
msgstr "ÐÐµÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ñ†ÐµÐ»ÑŒ не может иметь конфиденциальную цель в качеÑтве родителÑ"
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Сайт на проÑтом HTML иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
msgid "A platform value can be web, mob or app."
-msgstr ""
+msgstr "Параметр платформы может принимать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ web, mob или app."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
-msgstr ""
+msgstr "Шаблон проекта Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ приложений Salesforce Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ инÑтрументов разработчика Salesforce."
msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
-msgstr ""
+msgstr "Шаблон проекта Ð´Ð»Ñ Tencent Serverless Framework, который иÑпользует Next.js SSR."
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’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 ""
+msgstr "Ðазвание Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° определÑет его URL-Ð°Ð´Ñ€ÐµÑ (тот, который вы иÑпользуете Ð´Ð»Ñ Ð´Ð¾Ñтупа к проекту через браузер) и раÑположение в файловой ÑиÑтеме, где уÑтановлен GitLab. %{link_start}Узнать больше.%{link_end}"
msgid "A quarterly reconciliation is due on %{date}"
msgstr ""
msgid "A ready-to-go template for use with Android apps"
-msgstr ""
+msgstr "Готовый шаблон Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñми Android"
msgid "A ready-to-go template for use with iOS Swift apps"
-msgstr ""
+msgstr "Готовый шаблон Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñми iOS Swift"
msgid "A rebase is already in progress."
-msgstr ""
+msgstr "Перебазирование уже началоÑÑŒ."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
-msgstr ""
+msgstr "Выполнен вход в вашу учётную запиÑÑŒ Ñо Ñледующего IP-адреÑа: %{ip}"
msgid "A title is required"
-msgstr ""
+msgstr "ТребуетÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº"
msgid "A user with write access to the source branch selected this option"
msgstr "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в ветку иÑточника выбрал Ñтот вариант"
@@ -1816,7 +1859,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 ""
@@ -1831,16 +1874,16 @@ msgid "API Token"
msgstr "API токен"
msgid "API key"
-msgstr ""
+msgstr "Ключ API"
msgid "API?"
-msgstr ""
+msgstr "API?"
msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
-msgstr ""
+msgstr "$VARIABLE_WITH_PASSWORD"
msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
-msgstr ""
+msgstr "$VARIABLE_WITH_USERNAME"
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1849,10 +1892,10 @@ msgid "APIFuzzing|Base URL of API testing target. For example, http://www.exampl
msgstr ""
msgid "APIFuzzing|Choose a method"
-msgstr ""
+msgstr "Выберите метод"
msgid "APIFuzzing|Choose a profile"
-msgstr ""
+msgstr "Выберите профиль"
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1861,13 +1904,13 @@ msgid "APIFuzzing|Customize your project's API fuzzing configuration options and
msgstr ""
msgid "APIFuzzing|Enable authentication"
-msgstr ""
+msgstr "Включить аутентификацию"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
-msgstr ""
+msgstr "Введите Ð¸Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ CI, Ñодержащей пароль. Ðапример, $VARIABLE_WITH_PASSWORD."
msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
-msgstr ""
+msgstr "Введите Ð¸Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ CI, Ñодержащей Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. Ðапример, $VARIABLE_WITH_USERNAME."
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 ""
@@ -1882,19 +1925,19 @@ msgid "APIFuzzing|Generate code snippet"
msgstr "Создать Ñниппет"
msgid "APIFuzzing|Make sure your credentials are secured"
-msgstr ""
+msgstr "УбедитеÑÑŒ, что ваши учётные данные защищены"
msgid "APIFuzzing|Password for basic authentication"
-msgstr ""
+msgstr "Пароль Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ð¹ аутентификации"
msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
-msgstr ""
+msgstr "Режим ÑканированиÑ"
msgid "APIFuzzing|Scan profile"
-msgstr ""
+msgstr "Профиль ÑканированиÑ"
msgid "APIFuzzing|Show code snippet for the profile"
msgstr "Показать Ñниппет Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ"
@@ -1903,7 +1946,7 @@ msgid "APIFuzzing|Target URL"
msgstr ""
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr ""
+msgstr "ЕÑÑ‚ÑŒ три ÑпоÑоба выполнить Ñканирование."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr ""
@@ -1915,25 +1958,25 @@ msgid "APIFuzzing|Tip: Insert this part below all stages"
msgstr ""
msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ ÑƒÑ‚ÐµÑ‡ÐºÐ¸ информации, идентификационные данные должны быть добавлены в виде %{ciVariablesLinkStart}CI-переменной%{ciVariablesLinkEnd}. УправлÑÑ‚ÑŒ CI-переменными в %{ciSettingsLinkStart}ÐаÑтройках%{ciSettingsLinkEnd} может пользователь Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ mantainer'а. Мы обнаружили, что вы не maintainer. ЗафикÑируйте Ñвои Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² виде коммита и назначьте maintainer'а Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ñ‹Ñ… данных перед ÑлиÑнием."
msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ ÑƒÑ‚ÐµÑ‡ÐºÐ¸ информации, идентификационные данные должны быть добавлены в виде %{ciVariablesLinkStart}CI-переменной%{ciVariablesLinkEnd}. Как maintainer, вы можете управлÑÑ‚ÑŒ CI-переменными в %{ciSettingsLinkStart}ÐаÑтройках%{ciSettingsLinkEnd}."
msgid "APIFuzzing|Username for basic authentication"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ð¹ аутентификации"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
-msgstr ""
+msgstr "Вам может потребоватьÑÑ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒ maintainer'а Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ñ‹ ваших учетных данных"
msgid "APIFuzzing|folder/example.postman_collection.json"
-msgstr ""
+msgstr "folder/example.postman_collection.json"
msgid "APIFuzzing|folder/example_fuzz.har"
-msgstr ""
+msgstr "folder/example_fuzz.har"
msgid "APIFuzzing|folder/openapi.json"
-msgstr ""
+msgstr "folder/openapi.json"
msgid "AWS Access Key"
msgstr "Ключ доÑтупа AWS"
@@ -1948,7 +1991,7 @@ msgid "AWS Secret Access Key. Only required if not using role instance credentia
msgstr ""
msgid "AWS service error: %{error}"
-msgstr ""
+msgstr "Ошибка ÑервиÑа AWS: %{error}"
msgid "Abort"
msgstr "Отменить"
@@ -1981,7 +2024,7 @@ msgid "Acceptable for use in this project"
msgstr "Разрешены к иÑпользованию в Ñтом проекте"
msgid "Access Git repositories or the API."
-msgstr ""
+msgstr "ДоÑтуп к репозиториÑм Git или API."
msgid "Access Tokens"
msgstr "Токены доÑтупа"
@@ -1990,7 +2033,7 @@ msgid "Access denied for your LDAP account."
msgstr "ДоÑтуп запрещен Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи LDAP."
msgid "Access denied: %{error}"
-msgstr ""
+msgstr "ДоÑтуп запрещён: %{error}"
msgid "Access expiration date"
msgstr "Дата Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа"
@@ -2002,22 +2045,22 @@ msgid "Access forbidden. Check your access level."
msgstr "ДоÑтуп запрещен. Проверьте Ñвой уровень доÑтупа."
msgid "Access granted"
-msgstr ""
+msgstr "ДоÑтуп предоÑтавлен"
msgid "Access key ID"
-msgstr ""
+msgstr "ID ключа доÑтупа"
msgid "Access requests"
-msgstr ""
+msgstr "ЗапроÑÑ‹ доÑтупа"
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп к '%{classification_label}' не разрешён"
msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
-msgstr ""
+msgstr "Срок дейÑÑ‚Ð²Ð¸Ñ Ñ‚Ð¾ÐºÐµÐ½Ð¾Ð² доÑтупа ÑоÑтавлÑет 2 чаÑа. Токен Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть иÑпользован в любое Ð²Ñ€ÐµÐ¼Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ токена доÑтупа. БеÑÑрочные токены не рекомендуютÑÑ. Чтобы обеÑпечить обратную ÑовмеÑтимоÑÑ‚ÑŒ, очиÑтите Ñтот параметр."
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "Ключи развертываниÑ"
msgid "AccessDropdown|Groups"
msgstr "Группы"
@@ -2062,22 +2105,13 @@ msgid "AccessTokens|It cannot be used to access any other data."
msgstr "Его Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать Ð´Ð»Ñ Ð´Ð¾Ñтупа к любым другим данным."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
-msgstr ""
-
-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 ""
+msgstr "Храните Ñтот токен в Ñекрете. Любой, у кого он еÑÑ‚ÑŒ, может получить доÑтуп к ÑтатичеÑким объектам репозиториÑ, как еÑли бы Ñто были вы. ЕÑли Ñто вÑÑ‘-таки произошло, %{linkStart}обновите токен%{linkEnd}."
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
-msgstr ""
-
-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 ""
+msgstr "Храните Ñтот токен в Ñекрете. Любой, у кого он еÑÑ‚ÑŒ, может Ñоздавать обÑуждениÑ, как еÑли бы Ñто были вы. ЕÑли Ñто вÑÑ‘-таки произошло, %{linkStart}обновите токен%{linkEnd}."
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, %{linkStart}reset this token%{linkEnd}."
-msgstr ""
-
-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 ""
+msgstr "Храните Ñтот токен в Ñекрете. Любой, у кого он еÑÑ‚ÑŒ, может Ñледить за вашей активноÑтью и читать RSS ленту или ваш календарь, как еÑли бы Ñто были вы. ЕÑли Ñто вÑÑ‘-таки произошло, %{linkStart}обновите токен%{linkEnd}."
msgid "AccessTokens|Personal Access Tokens"
msgstr "Личные токены доÑтупа"
@@ -2095,19 +2129,16 @@ msgid "AccessTokens|You can generate a personal access token for each applicatio
msgstr "Ð’Ñ‹ можете Ñгенерировать личный токен доÑтупа Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ иÑпользуемого вами приложениÑ, которому необходим доÑтуп к GitLab API."
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 ""
+msgstr "Ваш токен канала идентифицирует ваÑ, когда программа Ñ‡Ñ‚ÐµÐ½Ð¸Ñ RSS загружает перÑонализированный канал RSS, или когда приложение ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶Ð°ÐµÑ‚ ваш перÑонализированный календарь. Его можно увидеть в URL-адреÑах Ñтих каналов."
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 ""
+msgstr "Токен входÑщей Ñлектронной почты аутентифицирует ваÑ, когда вы Ñоздаете новое обÑуждение по Ñлектронной почте и включаетÑÑ Ð² ваши личные адреÑа Ñлектронной почты Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð³Ð¾ проекта."
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 this token"
-msgstr ""
+msgstr "Токен ÑтатичеÑких объектов идентифицирует ваÑ, когда ÑтатичеÑкие объекты Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ (например, архивы или большие двоичные объекты (blobs)) обÑлуживаютÑÑ Ð²Ð½ÐµÑˆÐ½Ð¸Ð¼ хранилищем."
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "Узнать больше"
msgid "AccessibilityReport|Message: %{message}"
msgstr "Сообщение: %{message}"
@@ -2128,7 +2159,7 @@ msgid "Account and limit"
msgstr "Ðккаунт и ограничениÑ"
msgid "Account:"
-msgstr ""
+msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ:"
msgid "Account: %{account}"
msgstr "Ðккаунт: %{account}"
@@ -2146,28 +2177,28 @@ msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, y
msgstr ""
msgid "AccountValidation|Learn more."
-msgstr ""
+msgstr "Узнать больше."
msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
msgstr ""
msgid "AccountValidation|Validate your account"
-msgstr ""
+msgstr "Подтвердите Ñвою учётную запиÑÑŒ"
msgid "AccountValidation|Verification is required to discourage and reduce the abuse on GitLab infrastructure. If you verify with a credit or debit card, %{strong_start}GitLab will not charge your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
msgstr ""
msgid "AccountValidation|unsubscribe"
-msgstr ""
+msgstr "отпиÑатьÑÑ"
msgid "AccountValidation|you may %{unsubscribe_link} at any time."
msgstr ""
msgid "Action"
-msgstr ""
+msgstr "ДейÑтвие"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "ДейÑтвиÑ, принимаемые при получении предупреждениÑ. %{docsLink}"
msgid "Actions"
msgstr "ДейÑтвиÑ"
@@ -2182,7 +2213,7 @@ msgid "Active"
msgstr "Ðктивный"
msgid "Active %{type} (%{token_length})"
-msgstr ""
+msgstr "Ðктивный %{type} (%{token_length})"
msgid "Active Sessions"
msgstr "Ðктивные ÑеÑÑии"
@@ -2194,13 +2225,13 @@ msgid "Activity"
msgstr "ÐктивноÑÑ‚ÑŒ"
msgid "Activity|An error occured while retrieving activity. Reload the page to try again."
-msgstr ""
+msgstr "Произошла ошибка при получении активноÑти. Перезагрузите Ñтраницу, чтобы повторить попытку."
msgid "Add"
msgstr "Добавить"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "Добавить \"%{value}\""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr "Добавить CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "Добавить CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Добавить GitLab в Slack"
-
msgid "Add Jaeger URL"
msgstr "Добавить URL-Ð°Ð´Ñ€ÐµÑ Jaeger"
@@ -2223,8 +2251,8 @@ msgstr "Добавить клаÑтер Kubernetes"
msgid "Add LICENSE"
msgstr "Добавить LICENSE"
-msgid "Add New Node"
-msgstr "Добавить новый узел"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Добавить README"
@@ -2238,23 +2266,26 @@ msgstr "Добавить %{type}"
msgid "Add a GPG key"
msgstr "Добавить ключ GPG"
-msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr "Добавьте URL-Ð°Ð´Ñ€ÐµÑ Jaeger, чтобы заменить Ñту Ñтраницу ÑÑылкой на ваш Jaeger-Ñервер. Сначала необходимо %{link_start_tag}уÑтановить Jaeger%{link_end_tag}."
+
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
-msgstr ""
+msgstr "Добавить УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Политику конфиденциальноÑти Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ Ñтого ÑкземплÑра GitLab."
msgid "Add a bullet list"
msgstr "Добавить маркированный ÑпиÑок"
msgid "Add a collapsible section"
-msgstr ""
+msgstr "Добавить Ñворачиваемую Ñекцию"
msgid "Add a comment to this line"
-msgstr ""
+msgstr "Добавить комментарий к Ñтой Ñтроке"
msgid "Add a comment to this line or drag for multiple lines"
-msgstr ""
+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 ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "Добавить SSH ключ"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2323,7 +2357,7 @@ msgid "Add bold text"
msgstr "Добавить жирный текÑÑ‚"
msgid "Add broadcast message"
-msgstr ""
+msgstr "Добавить широковещательное Ñообщение"
msgid "Add child epic to an epic"
msgstr "Добавить дочерний Ñлемент в другой Ñлемент"
@@ -2421,11 +2455,8 @@ msgstr "Добавить ÑиÑтемный обработчик"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Добавить в Slack"
-
msgid "Add to board"
-msgstr ""
+msgstr "Добавить на доÑку"
msgid "Add to epic"
msgstr "Добавить к цели"
@@ -2446,7 +2477,7 @@ msgid "Add topics to projects to help users find them."
msgstr ""
msgid "Add trigger"
-msgstr ""
+msgstr "Добавить триггер"
msgid "Add user(s) to the group:"
msgstr "Добавить пользовател(Ñ/ей) в группу:"
@@ -2470,10 +2501,10 @@ msgid "AddContextCommits|Add previously merged commits"
msgstr "Добавить ранее Ñлитые коммиты"
msgid "AddContextCommits|Add/remove"
-msgstr ""
+msgstr "Добавить/удалить"
msgid "AddMember|Emails cannot be blank"
-msgstr ""
+msgstr "ÐдреÑа Ñлектронной почты не могут быть пуÑтыми"
msgid "AddMember|Invite email is invalid"
msgstr ""
@@ -2533,10 +2564,10 @@ msgid "Additional text to show on the Help page"
msgstr ""
msgid "Additional text to show on the sign-in page"
-msgstr ""
+msgstr "Дополнительный текÑÑ‚ Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ð° на Ñтранице входа."
msgid "Address"
-msgstr ""
+msgstr "ÐдреÑ"
msgid "Adds"
msgstr "ДобавлÑет"
@@ -2548,10 +2579,10 @@ msgid "Adds %{labels} %{label_text}."
msgstr "ДобавлÑетÑÑ %{labels}%{label_text}."
msgid "Adds a Zoom meeting."
-msgstr ""
+msgstr "ДобавлÑет вÑтречу в Zoom."
msgid "Adds a to do."
-msgstr ""
+msgstr "ДобавлÑет задачу."
msgid "Adds an issue to an epic."
msgstr "К цели добавлÑетÑÑ Ð·Ð°Ð´Ð°Ñ‡Ð°."
@@ -2560,19 +2591,19 @@ msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "ÐаÑтройте чаÑтоту обновлений GitLab UI."
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 ""
+msgstr "ÐаÑтройте критерии фильтров и поиÑка выше. ЕÑли вы Ñчитаете, что здеÑÑŒ может быть ошибка, обратитеÑÑŒ к документации %{linkStart}по уÑтранению неполадок Geo%{linkEnd} Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации."
msgid "Admin"
-msgstr ""
+msgstr "ÐдминиÑтратор"
msgid "Admin Area"
msgstr "Панель управлениÑ"
msgid "Admin Mode"
-msgstr ""
+msgstr "Режим ÐдминиÑтратора"
msgid "Admin Note"
msgstr ""
@@ -2584,7 +2615,7 @@ msgid "Admin Overview"
msgstr "Обзор ÐдминиÑтратора"
msgid "Admin Section"
-msgstr ""
+msgstr "Раздел ÐдминиÑтрированиÑ"
msgid "Admin mode already enabled"
msgstr "Режим админиÑтратора уже включен"
@@ -2602,13 +2633,13 @@ msgid "Admin notes"
msgstr "Заметки админиÑтратора"
msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
-msgstr ""
+msgstr "%{billable_users_link_start}Узнайте больше%{billable_users_link_end} о том, что предÑтавлÑет Ñобой платный пользователь"
msgid "AdminArea|Active users"
msgstr "Ðктивные пользователи"
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
-msgstr ""
+msgstr "Ð’Ñе пользователи, Ñозданные в данном ÑкземплÑре, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‚ÐµÑ…, которые не ÑвлÑÑŽÑ‚ÑÑ %{billable_users_link_start}платными%{billable_users_link_end}."
msgid "AdminArea|Billable users"
msgstr "Оплачиваемые пользователи"
@@ -2653,7 +2684,7 @@ msgid "AdminArea|Maintainer"
msgstr "Maintainer"
msgid "AdminArea|Minimal access"
-msgstr ""
+msgstr "Минимальный доÑтуп"
msgid "AdminArea|New group"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
@@ -2677,7 +2708,7 @@ msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for
msgstr "ПодпишитеÑÑŒ на раÑÑылку новоÑтей по безопаÑноÑти GitLab, чтобы получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± обновлениÑÑ… безопаÑноÑти."
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "ПодпиÑатьÑÑ Ð½Ð° раÑÑылку GitLab"
msgid "AdminArea|Stop all jobs"
msgstr "ОÑтановить вÑе заданиÑ"
@@ -2698,7 +2729,7 @@ msgid "AdminArea|Users"
msgstr "Пользователи"
msgid "AdminArea|Users statistics"
-msgstr "СтатиÑтика пользователей"
+msgstr "СтатиÑтика"
msgid "AdminArea|Users with highest role"
msgstr "Пользователи Ñ Ð½Ð°Ð¸Ð²Ñ‹Ñшей ролью"
@@ -2716,11 +2747,17 @@ msgid "AdminArea|View latest users"
msgstr "ПоÑмотреть недавних пользователей"
msgid "AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running."
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ оÑтановить вÑе заданиÑ. Выполнение вÑех запущенных заданий будет прервано."
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Ошибка загрузки ÑтатиÑтики. ПожалуйÑта, попробуйте еще раз"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2731,7 +2768,7 @@ msgid "AdminLabels|They can be used to categorize issues and merge requests."
msgstr ""
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить проект %{projectName}, его репозиторий и вÑе ÑвÑзанные реÑурÑÑ‹, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ запроÑÑ‹ ÑлиÑниÑ. ПоÑле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ %{strong_start}Удалить проект%{strong_end}, его Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ð¾ÑÑтановить или отменить удаление."
msgid "AdminProjects|Delete"
msgstr "Удалить"
@@ -2740,7 +2777,7 @@ msgid "AdminProjects|Delete Project %{projectName}?"
msgstr "Удалить Проект %{projectName}?"
msgid "AdminSettings|A Let's Encrypt account will be configured for this GitLab instance using this email address. You will receive emails to warn of expiring certificates. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Let's Encrypt будет наÑтроена Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ ÑкземплÑра GitLab Ñ Ð¸Ñпользованием Ñтого адреÑа Ñлектронной почты. Ð’Ñ‹ будете получать Ñлектронные пиÑьма Ñ Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñми об иÑтечении Ñрока дейÑÑ‚Ð²Ð¸Ñ Ñертификатов. %{link_start}Подробнее.%{link_end}"
msgid "AdminSettings|All new projects can use the instance's shared runners by default."
msgstr "Ð’Ñе новые проекты могут иÑпользовать общие runner'Ñ‹ ÑкземплÑра по умолчанию."
@@ -2749,85 +2786,85 @@ msgid "AdminSettings|Auto DevOps domain"
msgstr "Домен Auto DevOps"
msgid "AdminSettings|Configure Let's Encrypt"
-msgstr ""
+msgstr "ÐаÑтроить Let's Encrypt"
msgid "AdminSettings|Disable feed token"
-msgstr ""
+msgstr "Отключить токен канала"
msgid "AdminSettings|Disable public access to Pages sites"
-msgstr ""
+msgstr "Отключить публичный доÑтуп к Ñайтам Pages"
msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
-msgstr ""
+msgstr "Отображать баннер Ñ Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸ÐµÐ¼ добавить файл .gitlab-ci.yml на Ñтранице запроÑа о ÑлиÑнии Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð¾Ð² без Ñборочных линий."
msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Проверка домена - Ð²Ð°Ð¶Ð½Ð°Ñ Ð¼ÐµÑ€Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑти Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… Ñайтов GitLab. Пользователи должны подтвердить, что домен принадлежит им, прежде чем Ñайт будет включен. %{link_start}Подробнее.%{link_end}"
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "Включить баннер, рекомендующий добавить Ñборочную линию"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "ИÑпользовать общие Runner'Ñ‹ в новых проектах"
msgid "AdminSettings|Feed token"
-msgstr ""
+msgstr "Токен канала"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
-msgstr ""
+msgstr "Я прочёл и принимаю %{link_start}УÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ð±ÑлуживаниÑ%{link_end} (PDF) Let's Encrypt."
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
-msgstr ""
+msgstr "По умолчанию %{default_initial_branch_name}, еÑли не указано на уровне группы или ÑкземплÑра. Ðе влиÑет на ÑущеÑтвующие репозитории."
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "СохранÑÑ‚ÑŒ поÑледние артефакты Ð´Ð»Ñ Ð²Ñех заданий в поÑледних уÑпешных Ñборочных линиÑÑ…"
msgid "AdminSettings|Let's Encrypt email"
-msgstr ""
+msgstr "Почта Let's Encrypt"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr ""
+msgstr "МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾ÑÑ‚ÑŒ ÑеанÑа Ð´Ð»Ñ Git-операций, когда включена 2FA."
msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
-msgstr ""
+msgstr "Ðовые переменные CI/CD в проектах и группах по умолчанию защищены."
msgid "AdminSettings|No required pipeline"
msgstr "Ðе требуетÑÑ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
msgid "AdminSettings|Protect CI/CD variables by default"
-msgstr ""
+msgstr "Защищать переменные CI/CD по умолчанию"
msgid "AdminSettings|Require users to prove ownership of custom domains"
-msgstr ""
+msgstr "Требовать от пользователей Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð°Ð²Ð° ÑобÑтвенноÑти на Ñторонние домены"
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ð¢Ñ€ÐµÐ±ÑƒÐµÐ¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборочной линии"
msgid "AdminSettings|Select a CI/CD template"
-msgstr ""
+msgstr "Выберите шаблон CI/CD"
msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
-msgstr ""
+msgstr "Выберите группу Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² качеÑтве иÑточника шаблонов проектов на уровне ÑкземплÑра."
msgid "AdminSettings|Select to disable public access for Pages sites, which requires users to sign in for access to the Pages sites in your instance. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Выберите, чтобы отключить общий доÑтуп к Ñайтам Pages. Это потребует от пользователей авторизации Ð´Ð»Ñ Ð´Ð¾Ñтупа к Ñайтам Pages вашего ÑкземплÑра. %{link_start}Подробнее.%{link_end}"
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr ""
+msgstr "ПродолжительноÑÑ‚ÑŒ ÑеанÑа Ð´Ð»Ñ Git-операций когда включена 2FA (в минутах)"
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 ""
+msgstr "Задайте шаблон CI/CD в качеÑтве обÑзательной конфигурации Ñборочной линии Ð´Ð»Ñ Ð²Ñех проектов данного ÑкземплÑра. ÐŸÑ€Ð¾ÐµÐºÑ‚Ð½Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD ÑливаетÑÑ Ñ Ð¾Ð±Ñзательной при запуÑке Ñборочной линии. %{link_start}Что такое обÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборочной линии?%{link_end}"
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Задайте макÑимальный размер GitLab Pages на проект (0 — без ограничений). %{link_start}Подробнее.%{link_end}"
msgid "AdminSettings|Size and domain settings for Pages static sites."
-msgstr ""
+msgstr "ÐаÑтройки размера и домена Ð´Ð»Ñ ÑтатичеÑких Ñайтов Pages."
msgid "AdminSettings|The default domain to use for Auto Review Apps and Auto Deploy stages in all projects."
msgstr ""
msgid "AdminSettings|The default name for the initial branch of new repositories created in the instance."
-msgstr ""
+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 "ПоÑледние артефакты Ð´Ð»Ñ Ð²Ñех заданий в недавних уÑпешных Ñборочных линиÑÑ… каждого проекта ÑохранÑÑŽÑ‚ÑÑ Ð±ÐµÑÑрочно."
@@ -2836,7 +2873,7 @@ msgid "AdminSettings|The projects in this group can be selected as templates for
msgstr "Проекты в Ñтой группе могут быть выбраны в качеÑтве шаблонов Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… проектов, Ñозданных в ÑкземплÑре. %{link_start}Подробнее.%{link_end} "
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 ""
+msgstr "Шаблон обÑзательной конфигурации Ñборочной линии может быть как одним из предоÑтавленных GitLab, так и пользовательÑким, добавленным в репозиторий шаблонов ÑкземплÑра. %{link_start}Как мне Ñоздать репозиторий шаблонов ÑкземплÑра?%{link_end}"
msgid "AdminStatistics|Active Users"
msgstr "Ðктивные пользователи"
@@ -2863,22 +2900,25 @@ msgid "AdminStatistics|Snippets"
msgstr "Сниппеты"
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "(ÐдминиÑтратор)"
msgid "AdminUsers|(Banned)"
-msgstr ""
+msgstr "(Забанен)"
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(Заблокирован)"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "(Деактивирован)"
msgid "AdminUsers|(Internal)"
+msgstr "(Внутренний)"
+
+msgid "AdminUsers|(Locked)"
msgstr ""
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "(Ожидает подтверждениÑ)"
msgid "AdminUsers|2FA Disabled"
msgstr "2FA отключена"
@@ -2887,22 +2927,22 @@ 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 ""
+msgstr "Пользователь может подтвердить ÑебÑ, указав кредитную/дебетовую карту, или админиÑтратор может вручную проверить пользователÑ."
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "ДоÑтуп"
msgid "AdminUsers|Access Git repositories"
-msgstr ""
+msgstr "ДоÑтуп к Git-репозиториÑм"
msgid "AdminUsers|Access the API"
-msgstr ""
+msgstr "ДоÑтуп к API"
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "Ðктивировать"
msgid "AdminUsers|Activate user %{username}?"
-msgstr ""
+msgstr "Ðктивировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Active"
msgstr "Ðктивные"
@@ -2913,29 +2953,29 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "ÐдминиÑтратор"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
msgstr "ÐдминиÑтраторы"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "Одобрить"
msgid "AdminUsers|Approve user %{username}?"
-msgstr ""
+msgstr "Одобрить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Approved users can:"
-msgstr ""
+msgstr "Одобренные пользователи могут:"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "Ðудитор"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr "Ðудиторы имеют право на проÑмотр вÑех групп, проектов и пользователей."
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "ÐвтоматичеÑки помечен как внутренний пользователь по умолчанию."
msgid "AdminUsers|Ban user"
msgstr "Забанить пользователÑ"
@@ -2965,28 +3005,28 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Блокировка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð¼ÐµÐµÑ‚ Ñледующие Ñффекты:"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "Ðе удаетÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ или получить доÑтуп к информации об ÑкземплÑре"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Ðе удалоÑÑŒ разблокировать заблокированных пользователей LDAP"
msgid "AdminUsers|Cohorts"
-msgstr ""
+msgstr "Когорты"
msgid "AdminUsers|Confirm user"
-msgstr ""
+msgstr "Подтвердить пользователÑ"
msgid "AdminUsers|Confirm user %{username}?"
-msgstr ""
+msgstr "Подтвердить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить количеÑтво групп пользователей. ПожалуйÑта, обновите Ñтраницу, чтобы повторить попытку."
msgid "AdminUsers|Deactivate"
-msgstr "Отключить"
+msgstr "Деактивировать"
msgid "AdminUsers|Deactivate user %{username}?"
-msgstr ""
+msgstr "Деактивировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Deactivated"
msgstr "Отключено"
@@ -3007,7 +3047,7 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ внеÑённые им изменениÑ"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "ЭкÑпорт разрешений в формате CSV (макÑимум 100 000 пользователей)"
msgid "AdminUsers|External"
msgstr "Внешние"
@@ -3016,22 +3056,22 @@ msgid "AdminUsers|External users cannot see internal or private projects unless
msgstr "Внешние пользователи не могут видеть внутренние или приватные проекты, еÑли доÑтуп не предоÑтавлен Ñвно. Внешние пользователи также не могут Ñоздавать проекты, группы или личные Ñниппеты."
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации, пожалуйÑта, обратитеÑÑŒ к %{link_start}документации по удалению учётной запиÑи пользователÑ.%{link_end}"
msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
-msgstr ""
+msgstr "Вот неÑколько полезных ÑÑылок, которые помогут вам управлÑÑ‚ÑŒ Ñвоим ÑкземплÑром:"
msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
-msgstr ""
+msgstr "ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ какие-либо вопроÑÑ‹ об Ñтом процеÑÑе, обратитеÑÑŒ к %{doc_link} или %{support_link}."
msgid "AdminUsers|Important information about usage on your GitLab instance"
-msgstr ""
+msgstr "Ð’Ð°Ð¶Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± иÑпользовании вашего ÑкземплÑра GitLab"
msgid "AdminUsers|Is using seat"
msgstr "ИÑпользует меÑто"
msgid "AdminUsers|Issues authored by this user are hidden from other users."
-msgstr ""
+msgstr "ОбÑуждениÑ, Ñозданные Ñтим пользователем, Ñкрыты от других пользователей."
msgid "AdminUsers|It's you!"
msgstr "Это вы!"
@@ -3039,11 +3079,14 @@ msgstr "Это вы!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "Узнать больше о %{link_start}забаненных пользователÑÑ….%{link_end}"
-msgid "AdminUsers|Log in"
+msgid "AdminUsers|Locked"
msgstr ""
+msgid "AdminUsers|Log in"
+msgstr "Войти"
+
msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
-msgstr ""
+msgstr "Управление (принÑтие/отклонение) ожидающих региÑтрации пользователей"
msgid "AdminUsers|New user"
msgstr "Ðовый пользователь"
@@ -3055,7 +3098,7 @@ msgid "AdminUsers|Owned groups will be left"
msgstr "Группы, имеющиеÑÑ Ð² ÑобÑтвенноÑти будут Ñохранены"
msgid "AdminUsers|Pending approval"
-msgstr ""
+msgstr "Ожидают подтверждениÑ"
msgid "AdminUsers|Personal projects will be left"
msgstr "Личные проекты будут Ñохранены"
@@ -3073,13 +3116,13 @@ msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
-msgstr ""
+msgstr "Отклонить"
msgid "AdminUsers|Reject user %{username}?"
-msgstr ""
+msgstr "Отклонить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Rejected users:"
-msgstr ""
+msgstr "Отклонённые пользователи:"
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr "ВоÑÑтановить доÑтуп Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ðº учетной запиÑи, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²ÐµÐ±, Git и API."
@@ -3097,9 +3140,12 @@ msgid "AdminUsers|Sort by"
msgstr "Сортировать по"
msgid "AdminUsers|The user can't access git repositories."
-msgstr ""
+msgstr "Пользователь не имеет доÑтупа к репозиториÑм git."
msgid "AdminUsers|The user can't log in."
+msgstr "Пользователь не может войти"
+
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
msgstr ""
msgid "AdminUsers|The user will be logged out"
@@ -3127,19 +3173,19 @@ msgid "AdminUsers|Unban user"
msgstr "Разбанить пользователÑ"
msgid "AdminUsers|Unban user %{username}?"
-msgstr ""
+msgstr "Разбанить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Unblock"
-msgstr ""
+msgstr "Разблокировать"
msgid "AdminUsers|Unblock user %{username}?"
-msgstr ""
+msgstr "Разблокировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|Unlock user %{username}?"
-msgstr ""
+msgstr "Разблокировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}?"
msgid "AdminUsers|User administration"
-msgstr ""
+msgstr "Управление пользователем"
msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
msgstr ""
@@ -3154,10 +3200,10 @@ msgid "AdminUsers|Users"
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 ""
+msgstr "Пользователи вÑÑ‘ ещё могут быть приглашены в ваш ÑкземплÑÑ€ и/или добавлÑÑ‚ÑŒ ÑебÑ, еÑли Ñто разрешено наÑтройками. У них не будет доÑтупа к вашему ÑкземплÑру и они не будут учитыватьÑÑ Ð¿Ñ€Ð¸ подÑчёте количеÑтва меÑÑ‚, на которые вы подпиÑаны, пока вы не %{approve_link}."
msgid "AdminUsers|Validate user account"
-msgstr ""
+msgstr "Подтвердить учётную запиÑÑŒ пользователÑ"
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -3190,10 +3236,10 @@ msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
msgid "AdminUsers|You can always deactivate their account again if needed."
-msgstr ""
+msgstr "При необходимоÑти вы вÑегда можете повторно деактивировать аккаунт."
msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
-msgstr ""
+msgstr "Ð’Ñ‹ вÑегда можете реактивировать учётную запиÑÑŒ, данные оÑтанутÑÑ Ð½ÐµÑ‚Ñ€Ð¾Ð½ÑƒÑ‚Ñ‹Ð¼Ð¸."
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3244,7 +3290,7 @@ msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
msgstr ""
msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "МакÑимальное количеÑтво меÑÑ‚ в проÑтранÑтве имён превышает количеÑтво меÑÑ‚ в вашей подпиÑке. %{qrtlyDate} произойдёт ÐµÐ¶ÐµÐºÐ²Ð°Ñ€Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ñверка и вам автоматичеÑки будет выÑтавлен Ñчёт за превышение на пропорциональную Ñумму. От Ð²Ð°Ñ Ð½Ðµ требуетÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ñ… дейÑтвий. ЕÑли у Ð²Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзана ÐºÑ€ÐµÐ´Ð¸Ñ‚Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°, оплата ÑпишетÑÑ Ñ Ð½ÐµÑ‘. Ð’ противном Ñлучае вы получите Ñчёт на оплату. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации о Ñроках выÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñчетов, ознакомьтеÑÑŒ Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸ÐµÐ¹."
msgid "Admin|The number of max users in your instance exceeds the number of users in your license. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
msgstr ""
@@ -3253,7 +3299,7 @@ msgid "Admin|View pending user approvals"
msgstr ""
msgid "Admin|Your instance has reached its user cap"
-msgstr ""
+msgstr "Ваш ÑкземплÑÑ€ доÑтиг макÑимального количеÑтва пользователей"
msgid "Advanced"
msgstr "РаÑширенные"
@@ -3265,10 +3311,10 @@ msgid "Advanced Settings"
msgstr "Дополнительные наÑтройки"
msgid "Advanced export options"
-msgstr ""
+msgstr "РаÑширенные параметры ÑкÑпорта"
msgid "AdvancedSearch|Reindex required"
-msgstr ""
+msgstr "ТребуетÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ Ð¸Ð½Ð´ÐµÐºÑациÑ"
msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
msgstr ""
@@ -3298,13 +3344,13 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr ""
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
-msgstr ""
+msgstr "API-ключ Akismet:"
msgid "Akismet helps prevent the creation of spam issues in public projects."
-msgstr ""
+msgstr "Akismet помогает боротьÑÑ Ñо Ñпамом в публичных проектах."
msgid "AlertManagement|Acknowledged"
msgstr "Прочитано"
@@ -3319,22 +3365,22 @@ msgid "AlertManagement|Alert assignee(s): %{assignees}"
msgstr ""
msgid "AlertManagement|Alert detail"
-msgstr ""
+msgstr "ПодробноÑти оповещениÑ"
msgid "AlertManagement|Alert details"
-msgstr ""
+msgstr "ПодробноÑти оповещениÑ"
msgid "AlertManagement|Alert status: %{status}"
-msgstr ""
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ: %{status}"
msgid "AlertManagement|Alerts"
-msgstr ""
+msgstr "ОповещениÑ"
msgid "AlertManagement|All alerts"
-msgstr ""
+msgstr "Ð’Ñе оповещениÑ"
msgid "AlertManagement|Assign status"
-msgstr ""
+msgstr "Ðазначить ÑтатуÑ"
msgid "AlertManagement|Assignees"
msgstr "ОтветÑтвенные"
@@ -3343,7 +3389,7 @@ msgid "AlertManagement|Authorize external service"
msgstr "Ðвторизовать внешнюю Ñлужбу"
msgid "AlertManagement|Create incident"
-msgstr ""
+msgstr "Создать инцидент"
msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
msgstr "Выводите ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ вÑех Ñвоих инÑтрументов мониторинга непоÑредÑтвенно в Gitlab. УпроÑтите раÑÑмотрение оповещений и их превращение в инциденты."
@@ -3352,13 +3398,13 @@ msgid "AlertManagement|Edit"
msgstr "Редактировать"
msgid "AlertManagement|Environment"
-msgstr ""
+msgstr "Окружение"
msgid "AlertManagement|Events"
msgstr "СобытиÑ"
msgid "AlertManagement|Incident"
-msgstr ""
+msgstr "Инцидент"
msgid "AlertManagement|Key"
msgstr ""
@@ -3418,7 +3464,7 @@ msgid "AlertManagement|Surface alerts in GitLab"
msgstr "Вывод оповещений в GitLab"
msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
-msgstr ""
+msgstr "Возникла ошибка при отображении оповещениÑ. ПожалуйÑта, обновите Ñтраницу, чтобы повторить попытку."
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr "Произошла ошибка при отображении оповещений. Проверьте наÑтройки конечной точки, чтобы убедитьÑÑ, что Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÑŽÑ‚ÑÑ."
@@ -3439,214 +3485,214 @@ msgid "AlertManagement|This assignee cannot be assigned to this alert."
msgstr ""
msgid "AlertManagement|Tool"
-msgstr ""
+msgstr "ИнÑтрумент"
msgid "AlertManagement|Triggered"
msgstr "Получено"
msgid "AlertManagement|Value"
-msgstr ""
+msgstr "Значение"
msgid "AlertManagement|View incident"
-msgstr ""
+msgstr "ПроÑмотр инцидента"
msgid "AlertMappingBuilder|Define fallback"
-msgstr ""
+msgstr "Определить запаÑной вариант"
msgid "AlertMappingBuilder|GitLab alert key"
-msgstr ""
+msgstr "Ключ оповещений GitLab"
msgid "AlertMappingBuilder|Make selection"
-msgstr ""
+msgstr "Сделать выбор"
msgid "AlertMappingBuilder|Payload alert key"
msgstr ""
msgid "AlertMappingBuilder|Select key"
-msgstr ""
+msgstr "Выбрать ключ"
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
-msgstr ""
+msgstr "Заголовок — обÑзательное поле Ð´Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ð¹ в GitLab. ЕÑли указанное вами поле полезной нагрузки недоÑтупно, укажите, какое поле мы должны иÑпользовать вмеÑто него. "
msgid "AlertSettings|A webhook URL and authorization key is generated for the integration. After you save the integration, both are visible under the “View credentials†tab."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ð¸ генерируетÑÑ URL-Ð°Ð´Ñ€ÐµÑ Ð²ÐµÐ±-обработчика и ключ авторизации. ПоÑле ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ð¸ оба Ñлемента видны во вкладке «ПроÑмотр учётных данных»."
msgid "AlertSettings|Add new integration"
-msgstr ""
+msgstr "Добавить новую интеграцию"
msgid "AlertSettings|Alert settings"
-msgstr ""
+msgstr "ÐаÑтройки оповещений"
msgid "AlertSettings|Authorization key"
-msgstr ""
+msgstr "Ключ авторизации"
msgid "AlertSettings|Configure details"
msgstr ""
msgid "AlertSettings|Current integrations"
-msgstr ""
+msgstr "Текущие интеграции"
msgid "AlertSettings|Customize alert payload mapping (optional)"
-msgstr ""
+msgstr "ÐаÑтройка ÑопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ (необÑзательно)"
msgid "AlertSettings|Delete integration"
-msgstr ""
+msgstr "Удалить интеграцию"
msgid "AlertSettings|Edit integration"
-msgstr ""
+msgstr "Изменить интеграцию"
msgid "AlertSettings|Edit payload"
-msgstr ""
+msgstr "Изменить нагрузку"
msgid "AlertSettings|Enable integration"
-msgstr ""
+msgstr "Включить интеграцию"
msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
-msgstr ""
+msgstr "Введите пример нагрузки из выбранного вами инÑтрумента мониторинга. Это помогает отправлÑÑ‚ÑŒ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð² конечную точку GitLab."
msgid "AlertSettings|Enter integration name"
-msgstr ""
+msgstr "Введите название интеграции"
msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
-msgstr ""
+msgstr "БеÑплатные верÑии GitLab ограничены одной интеграцией на тип. Чтобы добавить больше, %{linkStart}обновите подпиÑку%{linkEnd}."
msgid "AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab."
-msgstr ""
+msgstr "GitLab Ñоздал URL-Ð°Ð´Ñ€ÐµÑ Ð¸ ключ авторизации Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ интеграции. Ð’Ñ‹ можете иÑпользовать их Ð´Ð»Ñ Ð½Ð°Ñтройки веб-обработчика и авторизации вашей конечной точки Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ оповещений в GitLab."
msgid "AlertSettings|HTTP Endpoint"
-msgstr ""
+msgstr "ÐšÐ¾Ð½ÐµÑ‡Ð½Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ° HTTP"
msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
-msgstr ""
+msgstr "ЕÑли вы изменÑете полезную нагрузку, необходимо заново ÑопоÑтавить полÑ"
msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
-msgstr ""
+msgstr "ЕÑли вы ÑброÑите ключ авторизации Ð´Ð»Ñ Ñтого проекта, вам необходимо будет обновить ключ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ включенного иÑточника уведомлений"
msgid "AlertSettings|Integration successfully saved"
-msgstr ""
+msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÑƒÑпешно Ñохранена"
msgid "AlertSettings|Name integration"
msgstr ""
msgid "AlertSettings|Parse payload fields"
-msgstr ""
+msgstr "Ðнализировать Ð¿Ð¾Ð»Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾Ð¹ нагрузки"
msgid "AlertSettings|Proceed with editing"
-msgstr ""
+msgstr "Продолжить редактирование"
msgid "AlertSettings|Prometheus"
-msgstr ""
+msgstr "Prometheus"
msgid "AlertSettings|Prometheus API base URL"
-msgstr ""
+msgstr "Базовый URL Prometheus API"
msgid "AlertSettings|Reset Key"
-msgstr ""
+msgstr "Ключ ÑброÑа"
msgid "AlertSettings|Reset the mapping"
-msgstr ""
+msgstr "СброÑить ÑопоÑтавление"
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
-msgstr ""
+msgstr "Образец полезной нагрузки проанализирован. Теперь вы можете ÑопоÑтавить полÑ."
msgid "AlertSettings|Save & create test alert"
-msgstr ""
+msgstr "Сохранить и Ñоздать теÑтовое оповещение"
msgid "AlertSettings|Save integration"
-msgstr ""
+msgstr "Сохранить интеграцию"
msgid "AlertSettings|Save integration & send"
-msgstr ""
+msgstr "Сохранить интеграцию и отправить"
msgid "AlertSettings|Select integration type"
-msgstr ""
+msgstr "Выберите тип интеграции"
msgid "AlertSettings|Send test alert"
-msgstr ""
+msgstr "Отправить теÑтовое оповещение"
msgid "AlertSettings|Send without saving"
-msgstr ""
+msgstr "Отправить без ÑохранениÑ"
msgid "AlertSettings|The form has unsaved changes"
-msgstr ""
+msgstr "Форма Ñодержит неÑохранённые изменениÑ"
msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
-msgstr ""
+msgstr "Форма Ñодержит неÑохранённые изменениÑ. Как бы вы хотели продолжить?"
msgid "AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the \"Parse payload fields\" button to continue."
-msgstr ""
+msgstr "Чтобы Ñоздать пользовательÑкое ÑопоÑтавление, введите пример полезной нагрузки из вашего инÑтрумента мониторинга в формате JSON. Чтобы продолжить, нажмите кнопку «Ðнализировать Ð¿Ð¾Ð»Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾Ð¹ нагрузки»."
msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
-msgstr ""
+msgstr "URL не может быть пуÑтым и должен начинатьÑÑ Ñ http: или https:."
msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
-msgstr ""
+msgstr "ИÑпользуйте указанный ниже URL-Ð°Ð´Ñ€ÐµÑ Ð¸ ключ авторизации в наÑтройках Prometheus Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ оповещений в GitLab. ИÑпользуйте %{linkStart}документацию GitLab%{linkEnd}, чтобы узнать, как наÑтроить конечную точку."
msgid "AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}"
-msgstr ""
+msgstr "ИÑпользуйте указанный ниже URL-Ð°Ð´Ñ€ÐµÑ Ð¸ ключ авторизации, Ð´Ð»Ñ Ð½Ð°Ñтройки внешнего ÑервиÑа отправки оповещений в GitLab. %{linkStart}Как мне наÑтроить конечную точку?%{linkEnd}"
msgid "AlertSettings|View URL and authorization key"
-msgstr ""
+msgstr "ПроÑмотр URL и ключа авторизации"
msgid "AlertSettings|View credentials"
-msgstr ""
+msgstr "ПроÑмотр учётных данных"
msgid "AlertSettings|Webhook URL"
-msgstr ""
+msgstr "URL веб-обработчика"
msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
-msgstr ""
+msgstr "Ð’Ñ‹ можете ÑопоÑтавить Ð¿Ð¾Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ð¹ GitLab по умолчанию Ñ ÐºÐ»ÑŽÑ‡Ð°Ð¼Ð¸ полезной нагрузки в раÑкрывающихÑÑ ÑпиÑках ниже."
msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
msgstr ""
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
-msgstr ""
+msgstr "{ \"events\": [{ \"application\": \"Ðазвание приложениÑ\" }] }"
msgid "Alerts"
msgstr "ОповещениÑ"
msgid "AlertsIntegrations|Alerts will be created through this integration"
-msgstr ""
+msgstr "ÐžÐ¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ ÑоздаватьÑÑ Ð¿Ð¾ÑредÑтвом Ñтой интеграции"
msgid "AlertsIntegrations|Alerts will not be created through this integration"
-msgstr ""
+msgstr "ÐžÐ¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð½Ðµ будут ÑоздаватьÑÑ Ð¿Ð¾ÑредÑтвом Ñтой интеграции"
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
-msgstr ""
+msgstr "ЕÑли вы удалите интеграцию %{integrationName}, Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ не будут отправлÑÑ‚ÑŒÑÑ Ð¸Ð· Ñтой конечной точки. Это дейÑтвие Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ."
msgid "AlertsIntegrations|Integration Name"
-msgstr ""
+msgstr "Ðазвание Интеграции"
msgid "AlertsIntegrations|Integration payload is invalid."
-msgstr ""
+msgstr "ÐŸÐ¾Ð»ÐµÐ·Ð½Ð°Ñ Ð½Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° интеграции некорректна."
msgid "AlertsIntegrations|No integrations have been added yet."
-msgstr ""
+msgstr "Интеграции пока не добавлены."
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ обновить текущую интеграцию. ПожалуйÑта, попробуйте ещё раз."
msgid "AlertsIntegrations|The integration could not be added. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ добавить интеграцию. ПожалуйÑта, попробуйте ещё раз."
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ удалить интеграцию. ПожалуйÑта, попробуйте ещё раз."
msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
-msgstr ""
+msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ð² наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÐ°ÐºÑ‚Ð¸Ð²Ð½Ð°. Включите интеграцию Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ теÑтового оповещениÑ."
msgid "AlertsIntegrations|The integration is deleted."
-msgstr ""
+msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð°."
msgid "AlertsIntegrations|The integration is saved."
-msgstr ""
+msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ñохранена."
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
-msgstr ""
+msgstr "Токен интеграции не может быть Ñброшен. ПожалуйÑта, попробуйте ещё раз."
msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
-msgstr ""
+msgstr "ТеÑтовое предупреждение теперь должно быть видно в вашем ÑпиÑке оповещений."
msgid "Algorithm"
msgstr "Ðлгоритм"
@@ -3655,13 +3701,13 @@ msgid "All"
msgstr "Ð’Ñе"
msgid "All %{replicableType} are being scheduled for %{action}"
-msgstr ""
+msgstr "Ð’Ñе %{replicableType} запланированы на %{action}"
msgid "All (default)"
msgstr "Ð’Ñе (по умолчанию)"
msgid "All GitLab"
-msgstr ""
+msgstr "ВеÑÑŒ GitLab"
msgid "All Members"
msgstr "Ð’Ñе УчаÑтники"
@@ -3679,13 +3725,13 @@ msgid "All environments"
msgstr "Ð’Ñе окружениÑ"
msgid "All epics"
-msgstr ""
+msgstr "Ð’Ñе цели"
msgid "All groups and projects"
msgstr "Ð’Ñе группы и проекты"
msgid "All issues"
-msgstr ""
+msgstr "Ð’Ñе обÑуждениÑ"
msgid "All issues for this milestone are closed."
msgstr "Ð’Ñе обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñтому Ñтапу закрыты."
@@ -3706,13 +3752,13 @@ msgid "All projects"
msgstr "Ð’Ñе проекты"
msgid "All projects selected"
-msgstr ""
+msgstr "Выбраны вÑе проекты"
msgid "All threads resolved"
msgstr "Ð’Ñе темы решены"
msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
-msgstr ""
+msgstr "Ð’Ñе пользователи должны принÑÑ‚ÑŒ УÑÐ»Ð¾Ð²Ð¸Ñ Ð¾ÐºÐ°Ð·Ð°Ð½Ð¸Ñ ÑƒÑлуг и Политику конфиденциальноÑти Ð´Ð»Ñ Ð´Ð¾Ñтупа к GitLab"
msgid "All users must have a name."
msgstr "У вÑех пользователей должно быть имÑ."
@@ -3724,10 +3770,10 @@ msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Разрешить %{group_name} Ð²Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñать"
msgid "Allow access to members of the following group"
-msgstr ""
+msgstr "Разрешить доÑтуп учаÑтникам Ñледующей группы"
msgid "Allow access to the following IP addresses"
-msgstr ""
+msgstr "Разрешить доÑтуп к Ñледующим IP-адреÑам"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Разрешить коммиты от учаÑтников, которые могут выполнÑÑ‚ÑŒ ÑлиÑние Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ веткой."
@@ -3736,7 +3782,7 @@ msgid "Allow group owners to manage LDAP-related settings"
msgstr "Разрешить владельцам групп управлÑÑ‚ÑŒ наÑтройками, ÑвÑзанными Ñ LDAP"
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "Разрешить пользователÑм без прав админиÑтратора доÑтуп к панели производительноÑти"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Разрешить иÑпользовать только выбранные протоколы Ð´Ð»Ñ Ð´Ð¾Ñтупа к Git."
@@ -3748,39 +3794,30 @@ msgid "Allow owners to manually add users outside of LDAP"
msgstr "Разрешить владельцам вручную добавлÑÑ‚ÑŒ пользователей вне LDAP"
msgid "Allow password authentication for Git over HTTP(S)"
-msgstr ""
+msgstr "Разрешить аутентификацию по паролю Ð´Ð»Ñ Git через HTTP(S)"
msgid "Allow password authentication for the web interface"
-msgstr ""
+msgstr "Разрешить аутентификацию по паролю через веб-интерфейÑ"
msgid "Allow project maintainers to configure repository mirroring"
-msgstr ""
+msgstr "Разрешить maintainer'ам проекта наÑтраивать зеркалирование репозиториÑ"
msgid "Allow projects and subgroups to override the group setting"
-msgstr ""
+msgstr "Разрешить проектам и подгруппам переопределÑÑ‚ÑŒ групповые наÑтройки"
msgid "Allow projects within this group to use Git LFS"
msgstr "Разрешить проектам в Ñтой группе иÑпользовать Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
-msgstr ""
-
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Разрешить запроÑÑ‹ к локальной Ñети из ÑиÑтемных хуков"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Разрешать запроÑÑ‹ в локальной Ñети Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ web-перехватов и Ñлужб"
+msgstr "Разрешить публичный доÑтуп к Ñборочным линиÑм и деталÑм заданий, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð»Ð¾Ð³Ð¸ и артефакты."
msgid "Allow subgroups to set up their own two-factor authentication rules"
-msgstr ""
+msgstr "Разрешить подгруппам уÑтанавливать Ñвои ÑобÑтвенные правила двухфакторной аутентификации"
msgid "Allow this key to push to this repository"
-msgstr ""
+msgstr "Разрешить Ñтому ключу выполнÑÑ‚ÑŒ push в данный репозиторий"
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3799,10 +3836,10 @@ msgid "Allowed"
msgstr "Разрешено"
msgid "Allowed Geo IP"
-msgstr ""
+msgstr "Разрешённые Geo IP"
msgid "Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "ДопуÑтимые Ñимволы: +, 0-9, -, и пробелы."
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Разрешено ограничение доменов Ñлектронной почты только Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿ верхнего уровнÑ"
@@ -3811,10 +3848,10 @@ msgid "Allowed to create:"
msgstr ""
msgid "Allowed to fail"
-msgstr ""
+msgstr "Ðеудача разрешена"
msgid "Allows projects or subgroups in this group to override the global setting."
-msgstr ""
+msgstr "Разрешает проектам или подгруппам в Ñтой группе переопределÑÑ‚ÑŒ глобальные наÑтройки."
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ПозволÑет добавлÑÑ‚ÑŒ и управлÑÑ‚ÑŒ клаÑтерами Kubernetes."
@@ -3823,13 +3860,13 @@ msgid "Almost there"
msgstr "Почти готово"
msgid "Almost there..."
-msgstr ""
+msgstr "Почти готово..."
msgid "Already blocked"
-msgstr ""
+msgstr "Уже заблокировано"
msgid "Already have login and password?"
-msgstr ""
+msgstr "Уже еÑÑ‚ÑŒ логин и пароль?"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "Также называетÑÑ \"Ñмитент\" или \"идентификатор Ð´Ð¾Ð²ÐµÑ€Ð¸Ñ Ñтороны\""
@@ -3841,7 +3878,7 @@ msgid "Also remove direct user membership from subgroups and projects"
msgstr ""
msgid "Also unassign this user from related issues and merge requests"
-msgstr ""
+msgstr "Также уберите назначение Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· ÑвÑзанных обÑуждений и запроÑов на ÑлиÑние"
msgid "Alternate support URL for Help page and Help dropdown."
msgstr ""
@@ -3856,7 +3893,7 @@ msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ñ Amazon EKS позволÑет вам предоÑтавлÑÑ‚ÑŒ клаÑтеры EKS из GitLab."
msgid "Amazon Web Services Logo"
-msgstr ""
+msgstr "Логотип Amazon Web Sёrvices"
msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Amazon не %{link_start}наÑтроена%{link_end}. ОбратитеÑÑŒ к Ñвоему админиÑтратору GitLab, еÑли хотите иÑпользовать Ñту Ñлужбу."
@@ -3865,10 +3902,10 @@ msgid "An %{link_start}alert%{link_end} with the same fingerprint is already ope
msgstr ""
msgid "An Enterprise User GitLab account has been created for you by your organization:"
-msgstr ""
+msgstr "ÐšÐ¾Ñ€Ð¿Ð¾Ñ€Ð°Ñ‚Ð¸Ð²Ð½Ð°Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ GitLab была Ñоздана Ð´Ð»Ñ Ð²Ð°Ñ Ð²Ð°ÑˆÐµÐ¹ организацией:"
msgid "An administrator changed the password for your GitLab account on %{link_to}."
-msgstr ""
+msgstr "ÐдминиÑтратор изменил пароль вашей учётной запиÑи GitLab на %{link_to}."
msgid "An alert has been resolved in %{project_path}."
msgstr ""
@@ -3889,10 +3926,7 @@ msgid "An error has occurred"
msgstr "Произошла ошибка"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
-msgstr ""
-
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
+msgstr "Ошибка в отчёте, в которой результат теÑта неверно указывает на наличие уÑзвимоÑти в ÑиÑтеме, тогда как Ñта уÑзвимоÑÑ‚ÑŒ отÑутÑтвует."
msgid "An error occurred adding a draft to the thread."
msgstr "Произошла ошибка при добавлении черновика в тему."
@@ -3913,31 +3947,31 @@ msgid "An error occurred fetching the dropdown data."
msgstr "Произошла ошибка при извлечении данных выпадающего ÑпиÑка."
msgid "An error occurred fetching the project authors."
-msgstr ""
+msgstr "Произошла ошибка при загрузке авторов проекта."
msgid "An error occurred fetching the public deploy keys. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при получении публичных ключей развертываниÑ. ПожалуйÑта, попробуйте ещё раз."
msgid "An error occurred previewing the blob"
msgstr "Произошла ошибка при предварительном проÑмотре объекта"
msgid "An error occurred when updating the title"
-msgstr ""
+msgstr "Произошла ошибка при обновлении заголовка"
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
-msgstr ""
+msgstr "Произошла ошибка при подтверждении уведомлениÑ. Обновите Ñтраницу и повторите попытку."
msgid "An error occurred while adding approvers"
-msgstr ""
+msgstr "Произошла ошибка при добавлении утверждающих"
msgid "An error occurred while adding formatted title for epic"
msgstr "Произошла ошибка при Ñоздании форматированного заголовка Ð´Ð»Ñ Ñ†ÐµÐ»Ð¸."
msgid "An error occurred while authorizing your role"
-msgstr ""
+msgstr "Произошла ошибка при авторизации вашей роли"
msgid "An error occurred while checking group path. Please refresh and try again."
-msgstr ""
+msgstr "Ошибка при проверке пути к группе. Обновите Ñтраницу и попробуйте ещё раз."
msgid "An error occurred while decoding the file."
msgstr "Произошла ошибка при декодировании файла."
@@ -3970,22 +4004,22 @@ msgid "An error occurred while enabling Service Desk."
msgstr "Произошла ошибка при включении Ñлужбы поддержки."
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "Произошла ошибка при получении предпроÑмотра Markdown"
msgid "An error occurred while fetching ancestors"
-msgstr ""
+msgstr "Произошла ошибка при получении предков"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "Произошла ошибка при получении веток. Повторите поиÑк."
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
msgid "An error occurred while fetching commit data."
-msgstr ""
+msgstr "Произошла ошибка при загрузке данных коммита."
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "Произошла ошибка при получении коммитов. Повторите поиÑк."
msgid "An error occurred while fetching coverage reports."
msgstr "Произошла ошибка при извлечении отчетов о покрытии теÑтами."
@@ -4006,16 +4040,16 @@ msgid "An error occurred while fetching label colors."
msgstr "Произошла ошибка при получении цветов меток."
msgid "An error occurred while fetching participants"
-msgstr ""
+msgstr "Произошла ошибка при получении учаÑтников"
msgid "An error occurred while fetching participants."
-msgstr ""
+msgstr "Произошла ошибка при получении учаÑтников."
msgid "An error occurred while fetching pending comments"
msgstr "Во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð·Ð²Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð¶Ð¸Ð´Ð°ÑŽÑ‰Ð¸Ñ… комментариев произошла ошибка"
msgid "An error occurred while fetching projects autocomplete."
-msgstr ""
+msgstr "Произошла ошибка при загрузке Ð°Ð²Ñ‚Ð¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð¾Ð²."
msgid "An error occurred while fetching reference"
msgstr ""
@@ -4030,7 +4064,7 @@ msgid "An error occurred while fetching the job log."
msgstr "Произошла ошибка при получении журнала заданий."
msgid "An error occurred while fetching the job logs."
-msgstr ""
+msgstr "Ошибка при получении журналов заданий"
msgid "An error occurred while fetching the job."
msgstr "Произошла ошибка при извлечении заданиÑ."
@@ -4041,18 +4075,15 @@ msgstr "Ошибка при извлечении заданий."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Произошла ошибка при извлечении поÑледней Ñборочной линии."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Произошла ошибка при выборке релизов. ПожалуйÑта, попробуйте ещё раз."
msgid "An error occurred while fetching this tab."
msgstr "Произошла ошибка при получении Ñтой вкладки."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Произошла ошибка при генерации имени пользователÑ. ПожалуйÑта, попробуйте ещё раз."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² Ð´Ð»Ñ - %{branchId}"
@@ -4199,10 +4230,10 @@ msgstr ""
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Произошла ошибка при Ñохранении параметра"
+msgstr[1] "Произошла ошибка при Ñохранении параметров"
+msgstr[2] "Произошла ошибка при Ñохранении параметров"
+msgstr[3] "Произошла ошибка при Ñохранении параметров"
msgid "An error occurred while subscribing to notifications."
msgstr "При подпиÑке на ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка."
@@ -4331,7 +4362,7 @@ msgid "Ancestors"
msgstr ""
msgid "And this registration token:"
-msgstr ""
+msgstr "И Ñтот токен региÑтрации:"
msgid "Anonymous"
msgstr "Ðноним"
@@ -4513,7 +4544,7 @@ msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s
msgstr ""
msgid "ApplicationSettings|When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
-msgstr ""
+msgstr "ЕÑли Ñтот параметр включен, любой пользователь, поÑещающий %{host} и Ñоздающий учётную запиÑÑŒ, должен быть Ñвно одобрен админиÑтратором, прежде чем Ñможет войти. Этот параметр дейÑтвует только в том Ñлучае, еÑли разрешена региÑтрациÑ."
msgid "ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account."
msgstr ""
@@ -4532,10 +4563,10 @@ msgstr "Применить"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Применить %d предложение"
+msgstr[1] "Применить %d предложениÑ"
+msgstr[2] "Применить %d предложений"
+msgstr[3] "Применить %d предложений"
msgid "Apply a label"
msgstr "Применить метку"
@@ -4571,7 +4602,7 @@ msgid "Applying suggestion..."
msgstr ""
msgid "Applying suggestions..."
-msgstr ""
+msgstr "Применение предложений..."
msgid "Approval Status"
msgstr ""
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Утверждающие"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4824,13 +4858,13 @@ msgid "April"
msgstr "Ðпрель"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "Ðрхитектура не найдена Ð´Ð»Ñ ÐžÐ¡"
msgid "Archive"
msgstr "Ðрхив"
msgid "Archive jobs"
-msgstr ""
+msgstr "Ðрхивные заданиÑ"
msgid "Archive project"
msgstr "Ðрхивировать проект"
@@ -4842,10 +4876,10 @@ msgid "Archived"
msgstr "Ðрхивные"
msgid "Archived (%{movedToStart}moved%{movedToEnd})"
-msgstr ""
+msgstr "Заархивировано (%{movedToStart}перемещено%{movedToEnd})"
msgid "Archived in this version"
-msgstr ""
+msgstr "Заархивировано в Ñтой верÑии"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
@@ -4854,13 +4888,13 @@ 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}"
-msgstr ""
+msgstr "ÐÑ€Ñ…Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° Ñделает его Ñовершенно недоÑтупным Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи. Он не будет отображатьÑÑ Ð½Ð° панели ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ в результатах поиÑка. %{strong_start}Ð’ репозиторий Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ вноÑить изменениÑ, Ñоздавать обÑуждениÑ, комментарии, а также другие ÑущноÑти.%{strong_end} %{link_start}Узнать подробнее.%{link_end}"
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
-msgstr ""
+msgstr "Ð’Ñ‹ ÐБСОЛЮТÐО УВЕРЕÐЫ, что хотите удалить Ñтот проект?"
msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
-msgstr ""
+msgstr "Ð’Ñ‹ ÐБСОЛЮТÐО УВЕРЕÐЫ, что хотите удалить Ñту группу?"
msgid "Are you sure that you want to archive this project?"
msgstr "Ð’Ñ‹ уверены, что хотите архивировать Ñтот проект?"
@@ -4869,6 +4903,9 @@ msgid "Are you sure that you want to unarchive this project?"
msgstr "Ð’Ñ‹ уверены, что хотите воÑÑтановить Ñтот проект?"
msgid "Are you sure you want to %{action} %{name}?"
+msgstr "Вы уверены, что хотите %{action} %{name}?"
+
+msgid "Are you sure you want to approve %{user}?"
msgstr ""
msgid "Are you sure you want to attempt to merge?"
@@ -4878,7 +4915,7 @@ msgid "Are you sure you want to cancel editing this comment?"
msgstr "Ð’Ñ‹ уверены, что хотите отменить редактирование данного комментариÑ?"
msgid "Are you sure you want to close this blocked issue?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите закрыть заблокированное обÑуждение?"
msgid "Are you sure you want to delete %{name}?"
msgstr "Вы точно хотите удалить %{name}?"
@@ -4890,10 +4927,10 @@ msgid "Are you sure you want to delete this %{typeOfComment}?"
msgstr "Ð’Ñ‹ уверены что дейÑтвительно хотите удалить Ñто %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñтот SSH ключ?"
msgid "Are you sure you want to delete this deploy key?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñтот ключ развёртываниÑ?"
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñто уÑтройÑтво? Это дейÑтвие не может быть отменено."
@@ -4905,29 +4942,29 @@ msgid "Are you sure you want to delete this pipeline? Doing so will expire all p
msgstr ""
msgid "Are you sure you want to deploy this environment?"
-msgstr ""
+msgstr "Ð’Ñ‹ точно хотите развернуть Ñто окружение?"
msgid "Are you sure you want to discard this comment?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите отменить Ñтот комментарий?"
msgid "Are you sure you want to discard your changes?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите отменить изменениÑ?"
msgid "Are you sure you want to erase this build?"
msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту Ñборку?"
msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Вы уверены, что хотите импортировать %d репозиторий?"
+msgstr[1] "Ð’Ñ‹ уверены, что хотите импортировать %d репозиториÑ?"
+msgstr[2] "Вы уверены, что хотите импортировать %d репозиториев?"
+msgstr[3] "Вы уверены, что хотите импортировать %d репозиториев?"
msgid "Are you sure you want to lock %{path}?"
-msgstr ""
+msgstr "Вы уверены, что хотите заблокировать %{path}?"
msgid "Are you sure you want to lock this directory?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите заблокировать Ñту директорию?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ð’Ñ‹ уверены, что вы хотите потерÑÑ‚ÑŒ не Ñохранённые изменениÑ?"
@@ -4939,13 +4976,13 @@ msgid "Are you sure you want to merge immediately?"
msgstr ""
msgid "Are you sure you want to re-deploy this environment?"
-msgstr ""
+msgstr "Ð’Ñ‹ точно хотите развернуть Ñто окружение повторно?"
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите переиндекÑировать?"
msgid "Are you sure you want to remove %{email}?"
-msgstr ""
+msgstr "Вы уверены, что хотите удалить %{email}?"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Вы уверены, что вы хотите удалить %{group_name}?"
@@ -4954,37 +4991,34 @@ msgid "Are you sure you want to remove the attachment?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить вложение?"
msgid "Are you sure you want to remove the license?"
-msgstr ""
+msgstr "Вы уверены, что хотите удалить лицензию?"
msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñтот ключ развертываниÑ? ЕÑли что-либо еще иÑпользует Ñтот ключ, оно переÑтанет работать."
msgid "Are you sure you want to remove this identity?"
msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту идентификацию?"
msgid "Are you sure you want to remove this list?"
-msgstr ""
-
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить токен SCIM? Выполнение SCIM переÑтанет работать до тех пор, пока новый токен не будет обновлен."
+msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñтот ÑпиÑок?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен проверки работоÑпоÑобноÑти?"
msgid "Are you sure you want to reset the registration token?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен региÑтрации?"
msgid "Are you sure you want to retry this migration?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите попробовать повторить Ñту миграцию?"
msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите отозвать %{type}? Это дейÑтвие Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ."
msgid "Are you sure you want to revoke this nickname?"
msgstr "Ð’Ñ‹ уверены, что хотите отменить Ñтот ник?"
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите отозвать Ñтот перÑональный токен доÑтупа? Это дейÑтвие не может быть отменено."
msgid "Are you sure you want to stop this environment?"
msgstr "Ð’Ñ‹ уверены, что вы хотите оÑтановить Ñто окружение?"
@@ -4993,10 +5027,10 @@ msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Вы уверены, что вы хотите разблокировать %{path_lock_path}?"
msgid "Are you sure you want to unlock %{path}?"
-msgstr ""
+msgstr "Вы уверены, что хотите разблокировать %{path}?"
msgid "Are you sure you want to unlock this directory?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что хотите разблокировать Ñту директорию?"
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите отпиÑатьÑÑ Ð¾Ñ‚ %{type}: %{link_to_noteable_text}?"
@@ -5011,7 +5045,7 @@ msgid "Are you sure? Removing this GPG key does not affect already signed commit
msgstr "Ð’Ñ‹ уверены? Удаление Ñтого ключа GPG не повлиÑет на уже подпиÑанные коммиты."
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
-msgstr ""
+msgstr "Ð’Ñ‹ уверены? УÑтройÑтво будет разлогинено из GitLab, а вÑе токены \"запомнить менÑ\" будут отозваны."
msgid "Arrange charts"
msgstr "УпорÑдочить диаграммы"
@@ -5029,30 +5063,30 @@ msgid "Artifacts"
msgstr "Ðртефакты"
msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
-msgstr ""
+msgstr "ПоÑкольку мы продолжаем Ñоздавать больше возможноÑтей Ð´Ð»Ñ SAST, мы будем рады вашему отзыву о функции наÑтройки SAST в %{linkStart}Ñтом обÑуждении%{linkEnd}."
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} помеÑтил в ветку %{branch} проекта %{project_name} ( %{commit_url} ):"
msgid "AsanaService|Add commit messages as comments to Asana tasks."
-msgstr ""
+msgstr "Добавить ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ð¾Ð² в качеÑтве комментариев к задачам Asana."
msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
-msgstr ""
+msgstr "СпиÑок разделённых запÑтыми веток, которые будет проверÑÑ‚ÑŒÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки. ОÑтавьте пуÑтым, чтобы включить вÑе ветки."
msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
-msgstr ""
+msgstr "ПерÑональный ключ доÑтупа пользователÑ. Пользователь должен иметь доÑтуп к задаче. Ð’Ñе комментарии — от имени Ñтого пользователÑ."
msgid "Ascending"
msgstr "По возраÑтанию"
msgid "Ask again later"
-msgstr ""
+msgstr "СпроÑите Ñнова позже"
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5168,10 +5202,10 @@ msgid "At least one approval from a code owner is required to change files match
msgstr ""
msgid "At least one field of %{one_of_required_fields} must be present"
-msgstr ""
+msgstr "Должно приÑутÑтвовать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно поле из %{one_of_required_fields}"
msgid "At least one of group_id or project_id must be specified"
-msgstr ""
+msgstr "По крайней мере одно из значений, group_id или project_id, должно быть указано"
msgid "At least one of your Personal Access Tokens is expired, but expiration enforcement is disabled. %{generate_new}"
msgstr ""
@@ -5189,7 +5223,7 @@ msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Приложить файл через drag &amp; drop или %{upload_link}"
msgid "Attaching File - %{progress}"
-msgstr ""
+msgstr "Прикрепление файла - %{progress}"
msgid "Attaching a file"
msgid_plural "Attaching %d files"
@@ -5205,13 +5239,13 @@ msgid "Audit Events"
msgstr "Ðудит Ñобытий"
msgid "Audit events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð°ÑƒÐ´Ð¸Ñ‚Ð°"
msgid "AuditLogs|(removed)"
-msgstr ""
+msgstr "(удалено)"
msgid "AuditLogs|Action"
-msgstr ""
+msgstr "ДейÑтвие"
msgid "AuditLogs|Author"
msgstr "Ðвтор"
@@ -5223,19 +5257,19 @@ msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
msgstr ""
msgid "AuditLogs|Failed to find %{type}. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ найти %{type}. ПожалуйÑта, попробуйте ещё раз."
msgid "AuditLogs|Group Events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹"
msgid "AuditLogs|IP Address"
msgstr "IP-адреÑ"
msgid "AuditLogs|Member Events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ ÑƒÑ‡Ð°Ñтника"
msgid "AuditLogs|No matching %{type} found."
-msgstr ""
+msgstr "Ðе найдено подходÑщих %{type}."
msgid "AuditLogs|Object"
msgstr "Объект"
@@ -5250,7 +5284,7 @@ msgid "AuditLogs|This month"
msgstr "Этот меÑÑц"
msgid "AuditLogs|User Events"
-msgstr ""
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
msgid "Aug"
msgstr "Ðвг."
@@ -5289,13 +5323,13 @@ msgid "Authenticated web requests"
msgstr ""
msgid "Authenticating"
-msgstr ""
+msgstr "ÐутентификациÑ"
msgid "Authentication"
-msgstr ""
+msgstr "ÐутентификациÑ"
msgid "Authentication Failure"
-msgstr ""
+msgstr "Ошибка аутентификации"
msgid "Authentication Log"
msgstr "Журнал аутентификации"
@@ -5310,13 +5344,13 @@ msgid "Authentication method"
msgstr "Метод аутентификации"
msgid "Authentication method updated"
-msgstr ""
+msgstr "Метод аутентификации обновлён"
msgid "Authentication via U2F device failed."
msgstr "Проверка подлинноÑти через U2F уÑтройÑтва не удалоÑÑŒ."
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "Ошибка аутентификации через уÑтройÑтво WebAuthn."
msgid "Author"
msgstr "Ðвтор"
@@ -5337,13 +5371,13 @@ msgid "Authorization key"
msgstr "Ключ авторизации"
msgid "Authorization required"
-msgstr ""
+msgstr "ТребуетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ"
msgid "Authorization token duration (minutes)"
-msgstr ""
+msgstr "Срок дейÑÑ‚Ð²Ð¸Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° авторизации (в минутах)"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "Ðвторизовано вводом имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð² приложении."
msgid "Authorize"
msgstr "Ðвторизовать"
@@ -5376,13 +5410,13 @@ msgid "Auto stop successfully canceled."
msgstr "ÐвтоматичеÑÐºÐ°Ñ Ð¾Ñтановка уÑпешно отменена."
msgid "Auto-cancel redundant pipelines"
-msgstr ""
+msgstr "ÐвтоматичеÑÐºÐ°Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð° избыточных Ñборочных линий"
msgid "Auto-close referenced issues on default branch"
msgstr ""
msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
-msgstr ""
+msgstr "%{auto_devops_start}Ðвтоматизируйте Ñоздание, теÑтирование и развертывание%{auto_devops_end} Ñвоих приложений на оÑнове наÑтроек непрерывной интеграции и доÑтавки. %{quickstart_start}С чего мне начать?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -5391,7 +5425,7 @@ msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ Auto DevOps"
msgid "AutoDevOps|Dismiss Auto DevOps box"
-msgstr ""
+msgstr "Закрыть окно Auto DevOps"
msgid "AutoDevOps|Enable in settings"
msgstr "Включить в наÑтройках"
@@ -5406,10 +5440,10 @@ msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps была включена и будет иÑпользоватьÑÑ, еÑли не найдётÑÑ Ð°Ð»ÑŒÑ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð½Ð¾Ð³Ð¾ файла конфигурации CI."
msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "ИнÑтрументы теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑти включены Ñ %{linkStart}Auto DevOps%{linkEnd}"
msgid "AutoRemediation| 1 Merge Request"
-msgstr ""
+msgstr "1 Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
@@ -5430,10 +5464,10 @@ msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered
msgstr ""
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "ÐвтоматичеÑкий откат к поÑледнему уÑпешному развертыванию при обнаружении критичеÑкой проблемы."
msgid "AutoRollback|Enable automatic rollbacks"
-msgstr ""
+msgstr "Включить автоматичеÑкие откаты"
msgid "Autocomplete"
msgstr "Ðвтозаполнение"
@@ -5454,10 +5488,10 @@ msgid "Automatic certificate management using Let's Encrypt"
msgstr "ÐвтоматичеÑкое управление Ñертификатами Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Let's Encrypt"
msgid "Automatic deployment rollbacks"
-msgstr ""
+msgstr "ÐвтоматичеÑкий откат развертываниÑ"
msgid "Automatic event tracking provides a traceable history for audits."
-msgstr ""
+msgstr "ÐвтоматичеÑкое отÑлеживание Ñобытий обеÑпечивает отÑлеживаемую иÑторию Ð´Ð»Ñ Ð°ÑƒÐ´Ð¸Ñ‚Ð°."
msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
@@ -5475,16 +5509,16 @@ msgid "Available"
msgstr "ДоÑтупен"
msgid "Available ID"
-msgstr ""
+msgstr "ДоÑтупный ID"
msgid "Available group runners: %{runners}"
-msgstr ""
+msgstr "ДоÑтупные групповые runner'Ñ‹: %{runners}"
msgid "Available runners: %{runners}"
-msgstr ""
+msgstr "ДоÑтупные runner'Ñ‹: %{runners}"
msgid "Available shared runners:"
-msgstr ""
+msgstr "ДоÑтупные общие runner'Ñ‹:"
msgid "Available specific runners"
msgstr "ДоÑтупные ÑпецифичеÑкие runner'Ñ‹"
@@ -5498,9 +5532,12 @@ msgstr "Ðватар будет удален. Ð’Ñ‹ уверены?"
msgid "Average per day: %{average}"
msgstr "Ð’ Ñреднем за день: %{average}"
-msgid "Award added"
+msgid "Awaiting user signup"
msgstr ""
+msgid "Award added"
+msgstr "Ðаграда добавлена"
+
msgid "Award removed"
msgstr ""
@@ -5520,7 +5557,7 @@ msgid "Background Jobs"
msgstr "Фоновые заданиÑ"
msgid "Background Migrations"
-msgstr ""
+msgstr "Фоновые Миграции"
msgid "Background color"
msgstr "Цвет фона"
@@ -5619,7 +5656,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 ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте оÑторожны. Изменение пути проекта может вызвать нежелательные побочные Ñффекты."
@@ -5637,10 +5677,10 @@ msgid "Be careful. Renaming a project's repository can have unintended side effe
msgstr "Будьте оÑторожны. Переименование Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° может вызвать нежелательные побочные Ñффекты."
msgid "Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}"
-msgstr ""
+msgstr "Перед включением данной интеграции Ñоздайте веб-обработчик Ð´Ð»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ Google Chat, в которой вы хотите получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ Ñтого проекта. %{docs_link}"
msgid "Before inserting code, be sure to read the comment that separated each code group."
-msgstr ""
+msgstr "Перед вÑтавкой кода обÑзательно прочтите комментарий, разделÑющий каждую группу кода."
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
msgstr ""
@@ -5652,43 +5692,43 @@ msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "Ðиже приведены отпечатки ключей SSH текущего ÑкземплÑра."
msgid "Below are the settings for %{link_to_gitlab_pages}."
-msgstr ""
+msgstr "Ðиже приведены наÑтройки Ð´Ð»Ñ %{link_to_gitlab_pages}."
msgid "Below you will find all the groups that are public."
msgstr "Ðиже показаны вÑе открытые группы."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Двухнедельное покрытие кода"
msgid "Billable Users"
-msgstr ""
+msgstr "Оплачиваемые пользователи"
msgid "Billing"
msgstr "Тарифы"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
-msgstr ""
+msgstr "%{group_name} ÑÐµÐ¹Ñ‡Ð°Ñ Ð¸Ñпользует тарифный план %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
-msgstr ""
-
-msgid "BillingPlans|Compare all plans"
-msgstr ""
+msgstr "%{user_name}, ваш текущий тарифный план — %{plan_name}."
msgid "BillingPlans|Congratulations, your free trial is activated."
-msgstr ""
+msgstr "ПоздравлÑем, беÑплатный пробный период активирован."
msgid "BillingPlans|End of availability for the Bronze Plan"
-msgstr ""
+msgstr "Окончание доÑтупа к тарифному плану Bronze"
msgid "BillingPlans|Free upgrade!"
-msgstr ""
+msgstr "БеÑплатное обновление!"
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "ЕÑли вы хотите понизить уровень Ñвоего тарифного плана, пожалуйÑта, ÑвÑжитеÑÑŒ Ñо %{support_link_start}Ñлужбой поддержки пользователей%{support_link_end}."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
-msgstr ""
+msgstr "Узнайте больше о каждом плане, прочитав %{faq_link}, или начните беÑплатный 30-дневный пробный период GitLab.com Ultimate."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Узнайте больше о каждом тарифе, поÑетив нашу %{pricing_page_link}."
@@ -5706,14 +5746,11 @@ msgid "BillingPlans|See all %{plan_name} features"
msgstr "Ð’Ñе возможноÑти %{plan_name}"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+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 ""
@@ -5727,7 +5764,7 @@ msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "%{price_per_year} в год"
msgid "BillingPlans|for the remainder of your subscription"
-msgstr ""
+msgstr "до конца подпиÑки"
msgid "BillingPlans|frequently asked questions"
msgstr "чаÑто задаваемые вопроÑÑ‹"
@@ -5760,13 +5797,13 @@ msgid "Billings|By extending your trial, you will receive an additional 30 days
msgstr ""
msgid "Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once."
-msgstr ""
+msgstr "При повторной активации пробного периода вы получите 30 дополнительных дней плана %{planName}. Повторно активировать пробный период можно лишь единожды."
msgid "Billings|Extend trial"
msgstr ""
msgid "Billings|Reactivate trial"
-msgstr ""
+msgstr "Реактивировать пробный период"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
msgstr ""
@@ -5792,74 +5829,80 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
msgid "Billing|An error occurred while loading billable members list"
-msgstr ""
+msgstr "Ошибка при загрузке ÑпиÑка оплачиваемых учаÑтников"
msgid "Billing|An error occurred while loading pending members list"
msgstr ""
msgid "Billing|An error occurred while removing a billable member"
-msgstr ""
+msgstr "Произошла ошибка при удалении оплачиваемого учаÑтника"
msgid "Billing|Awaiting member signup"
msgstr ""
msgid "Billing|Cannot remove user"
-msgstr ""
+msgstr "Ðевозможно удалить пользователÑ"
msgid "Billing|Direct memberships"
msgstr ""
msgid "Billing|Enter at least three characters to search."
-msgstr ""
+msgstr "Введите минимум три Ñимвола Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка."
msgid "Billing|Export list"
msgstr ""
msgid "Billing|Group"
-msgstr ""
+msgstr "Группа"
msgid "Billing|Group invite"
-msgstr ""
+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 ""
+msgstr "Ðет пользователей Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
msgid "Billing|Private"
msgstr ""
msgid "Billing|Project invite"
-msgstr ""
+msgstr "Приглашение в проект"
msgid "Billing|Remove user %{username} from your subscription"
-msgstr ""
+msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username} из вашей подпиÑки"
msgid "Billing|Toggle seat details"
-msgstr ""
+msgstr "Переключить подробноÑти о меÑтах"
msgid "Billing|Type %{username} to confirm"
-msgstr ""
+msgstr "Введите %{username} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ"
msgid "Billing|User was successfully removed"
-msgstr ""
+msgstr "Пользователь был уÑпешно удалён"
msgid "Billing|Users occupying seats in"
-msgstr ""
+msgstr "Пользователи, занимающие меÑта в"
msgid "Billing|View pending approvals"
msgstr ""
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{username} из вашей подпиÑки. ЕÑли вы продолжите, пользователь будет удалён из группы %{namespace} и вÑех её подгрупп и проектов. ДейÑтвие не может быть отменено."
msgid "Bitbucket Server Import"
msgstr "Импорт из Bitbucket Server"
@@ -5873,9 +5916,12 @@ msgstr "Импорт из BitBucket"
msgid "Blame"
msgstr ""
-msgid "Block user"
+msgid "BlobViewer|View on %{environmentName}"
msgstr ""
+msgid "Block user"
+msgstr "Блокировать пользователÑ"
+
msgid "Blocked"
msgstr ""
@@ -5890,7 +5936,7 @@ msgid "Blocked issue"
msgstr "Заблокированное обÑуждение"
msgid "Blocking"
-msgstr ""
+msgstr "Блокировка"
msgid "Blocking issues"
msgstr ""
@@ -5902,28 +5948,28 @@ msgid "Blog"
msgstr "Блог"
msgid "Board scope affects which epics are displayed for anyone who visits this board"
-msgstr ""
+msgstr "ОблаÑÑ‚ÑŒ дейÑÑ‚Ð²Ð¸Ñ Ð´Ð¾Ñки определÑет какие цели показываютÑÑ Ð²Ñем, кто поÑещает Ñту доÑку"
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "ОблаÑÑ‚ÑŒ дейÑÑ‚Ð²Ð¸Ñ Ð´Ð¾Ñки влиÑет на то, какие задачи отображаютÑÑ Ð´Ð»Ñ Ð²Ñех, кто поÑещает Ñту доÑку"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Группы"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Загрузка групп"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Ðичего не найдено"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "ПоиÑк групп"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Выберите группу"
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "Ðет подходÑщих результатов"
msgid "BoardNewIssue|Projects"
msgstr "Проекты"
@@ -5935,16 +5981,16 @@ msgid "BoardNewIssue|Select a project"
msgstr "Выбрать проект"
msgid "BoardScope|An error occurred while getting milestones, please try again."
-msgstr ""
+msgstr "Произошла ошибка при получении Ñтапов, пожалуйÑта, попробуйте ещё раз."
msgid "BoardScope|An error occurred while searching for labels, please try again."
msgstr ""
msgid "BoardScope|An error occurred while searching for users, please try again."
-msgstr ""
+msgstr "Произошла ошибка при поиÑке пользователей, пожалуйÑта, попробуйте ещё раз."
msgid "BoardScope|Any Milestone"
-msgstr ""
+msgstr "Любой Ñтап"
msgid "BoardScope|Any assignee"
msgstr ""
@@ -5959,13 +6005,13 @@ msgid "BoardScope|Choose labels"
msgstr ""
msgid "BoardScope|Edit"
-msgstr ""
+msgstr "Редактировать"
msgid "BoardScope|Labels"
msgstr ""
msgid "BoardScope|Milestone"
-msgstr ""
+msgstr "Этап"
msgid "BoardScope|No milestone"
msgstr ""
@@ -6008,52 +6054,52 @@ msgstr[2] ""
msgstr[3] ""
msgid "Boards|An error occurred while creating the epic. Please try again."
-msgstr ""
+msgstr "При Ñоздании цели произошла ошибка. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while creating the issue. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при Ñоздании обÑуждениÑ. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while creating the list. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при Ñоздании ÑпиÑка. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while fetching child groups. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при получении дочерних групп. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while fetching group projects. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при получении проектов группы. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
+msgstr "Возникла ошибка при получении обÑуждений. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while fetching labels. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при получении меток. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при получении ÑпиÑка целей. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при получении обÑуждений доÑки. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при получении ÑпиÑка доÑок. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при получении дорожек доÑки. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while generating lists. Please reload the page."
-msgstr ""
+msgstr "Произошла ошибка при Ñоздании ÑпиÑков. ПожалуйÑта, перезагрузите Ñтраницу."
msgid "Boards|An error occurred while moving the epic. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при перемещении цели. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while moving the issue. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при перемещении обÑуждениÑ. ПожалуйÑта, попробуйте ещё раз."
msgid "Boards|An error occurred while removing the list. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при удалении ÑпиÑка. ПожалуйÑта, попробуйте еще раз."
msgid "Boards|An error occurred while updating the board list. Please try again."
-msgstr ""
+msgstr "Произошла ошибка при обновлении ÑпиÑка. ПожалуйÑта, попробуйте еще раз."
msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
@@ -6117,7 +6163,7 @@ msgid "Board|Failed to delete board. Please try again."
msgstr ""
msgid "Board|Load more epics"
-msgstr ""
+msgstr "Загрузить больше целей"
msgid "Board|Load more issues"
msgstr ""
@@ -6171,7 +6217,7 @@ msgid "Branches|Cancel, keep branch"
msgstr ""
msgid "Branches|Can’t find HEAD commit for this branch"
-msgstr ""
+msgstr "Ðевозможно найти HEAD-коммит Ñтой ветки"
msgid "Branches|Compare"
msgstr "Сравнить"
@@ -6191,17 +6237,11 @@ msgstr "Удалить влитые ветки"
msgid "Branches|Delete protected branch"
msgstr "Удалить защищённую ветку"
-msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr "Удалить защищённую ветку '%{branch_name}'?"
-
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+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}' невозможно отменить. Вы уверены?"
+msgstr "Удаление ветки %{strongStart}%{branchName}%{strongEnd} невозможно отменить. Вы уверены?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Удаление влитых веток невозможно отменить. Вы уверены?"
@@ -6218,11 +6258,8 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
msgid "Branches|No branches to show"
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 ""
+msgstr "ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ %{strongStart}%{buttonText}%{strongEnd} отмена и воÑÑтановление Ñтанут невозможны."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Только Ñопровождающий проект или владелец может удалить защищенную ветвь"
@@ -6231,7 +6268,7 @@ msgid "Branches|Overview"
msgstr "Обзор"
msgid "Branches|Please type the following to confirm:"
-msgstr ""
+msgstr "ПожалуйÑта, введите Ñледующее Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ:"
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Управление защищёнными ветками возможно в %{project_settings_link}."
@@ -6267,37 +6304,25 @@ 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}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Чтобы избежать потери данных, раÑÑмотрите возможноÑÑ‚ÑŒ ÑлиÑÐ½Ð¸Ñ Ñтой ветки перед её удалением."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{branch_name_confirmation}:"
+msgstr "Эта ветка еще не Ñлита Ñ %{defaultBranchName}. Возможно, Ñтоит Ñлить её перед удалением, чтобы избежать потери данных."
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|Unable to load branches"
-msgstr ""
+msgstr "Ðевозможно загрузить ветки"
msgid "Branches|Yes, delete branch"
-msgstr ""
+msgstr "Да, удалить ветку"
msgid "Branches|Yes, delete protected branch"
-msgstr ""
+msgstr "Да, удалить защищённую ветку"
msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ безвозвратно удалить ветку %{strongStart}%{branchName}.%{strongEnd}"
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}."
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ безвозвратно удалить защищённую ветку %{strongStart}%{branchName}.%{strongEnd}"
msgid "Branches|diverged from upstream"
msgstr "раÑходитÑÑ Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑким репозиторием"
@@ -6318,16 +6343,16 @@ msgid "Brief title about the change"
msgstr ""
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "Широковещательное Ñообщение уÑпешно Ñоздано."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "Широковещательное Ñообщение уÑпешно обновлено."
msgid "Broadcast Messages"
-msgstr ""
+msgstr "Широковещательные СообщениÑ"
msgid "Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more."
-msgstr ""
+msgstr "Широковещательные ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÑŽÑ‚ÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ могут иÑпользоватьÑÑ Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ о плановом обÑлуживании, поÑледних обновлениÑÑ… и многом другом."
msgid "Browse Directory"
msgstr "ПроÑмотр каталога"
@@ -6360,7 +6385,7 @@ msgid "Bulk request concurrency"
msgstr "РаÑпараллеливание маÑÑовых запроÑов"
msgid "Bulk update"
-msgstr ""
+msgstr "МаÑÑовое обновление"
msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
msgstr ""
@@ -6369,31 +6394,31 @@ msgid "BulkImport|%{feature} (require v%{version})"
msgstr ""
msgid "BulkImport|Existing groups"
-msgstr ""
+msgstr "СущеÑтвующие группы"
msgid "BulkImport|Filter by source group"
-msgstr ""
+msgstr "Фильтр по иÑходной группе"
msgid "BulkImport|Following data will not be migrated: %{bullets} Contact system administrator of %{host} to upgrade GitLab if you need this data in your migration"
msgstr ""
msgid "BulkImport|From source group"
-msgstr ""
+msgstr "Из иÑходной группы"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° групп"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
-msgstr ""
+msgstr "Ошибка импорта: меÑто Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½Ðµ может быть подгруппой иÑходной группы. Измените меÑто Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ попробуйте ещё раз."
msgid "BulkImport|Import groups from GitLab"
-msgstr ""
+msgstr "Импорт групп из GitLab"
msgid "BulkImport|Import is finished. Pick another name for re-import"
msgstr ""
msgid "BulkImport|Import selected"
-msgstr ""
+msgstr "Импортировать выбранные"
msgid "BulkImport|Importing the group failed."
msgstr ""
@@ -6402,25 +6427,25 @@ msgid "BulkImport|Last imported to %{link}"
msgstr ""
msgid "BulkImport|Name already exists."
-msgstr ""
+msgstr "Ð˜Ð¼Ñ ÑƒÐ¶Ðµ ÑущеÑтвует."
msgid "BulkImport|Name already used as a target for another group."
msgstr ""
msgid "BulkImport|New group"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
msgid "BulkImport|No history is available"
-msgstr ""
+msgstr "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупна"
msgid "BulkImport|No parent"
-msgstr ""
+msgstr "Без родителÑ"
msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
msgstr ""
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
-msgstr ""
+msgstr "Показаны %{start}-%{end} из %{total}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} from %{link}"
msgstr ""
@@ -6429,19 +6454,19 @@ msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter
msgstr ""
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
msgid "BulkImport|To new group"
-msgstr ""
+msgstr "В новую группу"
msgid "BulkImport|Update of import statuses with realtime changes failed"
msgstr ""
msgid "BulkImport|You have no groups to import"
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ групп Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°"
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "ЗдеÑÑŒ поÑвÑÑ‚ÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ðµ группы."
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
@@ -6477,10 +6502,10 @@ msgid "Busy"
msgstr ""
msgid "Buy CI Minutes"
-msgstr ""
+msgstr "Купить минуты CI"
msgid "Buy Storage"
-msgstr ""
+msgstr "Купить хранилище"
msgid "Buy more Pipeline minutes"
msgstr "Купить минут Ð´Ð»Ñ CI"
@@ -6489,11 +6514,20 @@ msgid "By %{user_name}"
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 ""
+msgstr "При аутентификации Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ учётной запиÑи, привÑзанной к корпоративному адреÑу Ñлектронной почты, подразумеваетÑÑ, что Ñта ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ ÑвлÑетÑÑ ÐºÐ¾Ñ€Ð¿Ð¾Ñ€Ð°Ñ‚Ð¸Ð²Ð½Ñ‹Ð¼ пользователем. "
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "По умолчанию вÑе проекты и группы будут иÑпользовать глобальные наÑтройки уведомлений."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "по автору"
@@ -6519,51 +6553,63 @@ msgid "CI/CD"
msgstr "CI/CD"
msgid "CI/CD Analytics"
-msgstr ""
+msgstr "CI/CD аналитика"
msgid "CI/CD Settings"
-msgstr ""
+msgstr "ÐаÑтройки CI/CD"
msgid "CI/CD configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD"
msgid "CI/CD configuration file"
-msgstr ""
+msgstr "Файл конфигурации CI/CD"
msgid "CI/CD|No projects have been added to the scope"
-msgstr ""
+msgstr "Ðи один проект не был добавлен в облаÑÑ‚ÑŒ видимоÑти"
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
-msgstr ""
+msgstr "%{percent}%{percentSymbol}"
msgid "CICDAnalytics|All time"
-msgstr ""
+msgstr "Ð’ÑÑ‘ времÑ"
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "ЧаÑтота развертываниÑ"
msgid "CICDAnalytics|Lead time"
msgstr ""
msgid "CICDAnalytics|Projects with releases"
-msgstr ""
+msgstr "Проекты Ñ Ñ€ÐµÐ»Ð¸Ð·Ð°Ð¼Ð¸"
msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Релиз"
+msgstr[1] "Релиза"
+msgstr[2] "Релизов"
+msgstr[3] "Релизов"
msgid "CICDAnalytics|Release statistics"
-msgstr ""
+msgstr "СтатиÑтика релизов"
msgid "CICDAnalytics|Releases"
+msgstr "Релизы"
+
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
msgstr ""
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6622,7 +6668,7 @@ msgid "CLOSED (MOVED)"
msgstr "ЗÐКРЫТО (ПЕРЕМЕЩЕÐО)"
msgid "CODEOWNERS rule violation"
-msgstr ""
+msgstr "Ðарушение правил CODEOWNERS"
msgid "CONTRIBUTING"
msgstr "CONTRIBUTING"
@@ -6631,7 +6677,7 @@ msgid "CPU"
msgstr "CPU"
msgid "CSV is being generated and will be emailed to you upon completion."
-msgstr ""
+msgstr "CSV ÑоздаетÑÑ Ð¸ будет отправлен вам по завершении."
msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
msgstr ""
@@ -6685,16 +6731,16 @@ msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
msgstr ""
msgid "Can be manually deployed to"
-msgstr ""
+msgstr "Может быть развернуто вручную в"
msgid "Can be overridden in each project."
msgstr ""
msgid "Can create groups:"
-msgstr ""
+msgstr "Может Ñоздавать группы:"
msgid "Can't apply as the source branch was deleted."
-msgstr ""
+msgstr "Ðевозможно применить, так как иÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° была удалена."
msgid "Can't apply as these lines were changed in a more recent version."
msgstr ""
@@ -6703,10 +6749,10 @@ msgid "Can't apply as this line was changed in a more recent version."
msgstr ""
msgid "Can't apply this suggestion."
-msgstr ""
+msgstr "Ðе удаетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ Ñто предложение."
msgid "Can't be empty"
-msgstr ""
+msgstr "Ðе может быть пуÑтым"
msgid "Can't create snippet: %{err}"
msgstr "Ðе удалоÑÑŒ Ñоздать Ñниппет: %{err}"
@@ -6766,10 +6812,10 @@ msgid "Cancel"
msgstr "Отмена"
msgid "Cancel and close"
-msgstr ""
+msgstr "Отменить и закрыть"
msgid "Cancel index deletion"
-msgstr ""
+msgstr "Отменить удаление индекÑа"
msgid "Cancel running"
msgstr "Отменить запуÑк"
@@ -6778,10 +6824,10 @@ msgid "Cancel this job"
msgstr "Отменить Ñто задание"
msgid "Cancel your account"
-msgstr ""
+msgstr "Ðннулировать вашу учетную запиÑÑŒ"
msgid "Cancel, keep project"
-msgstr ""
+msgstr "Отменить, Ñохранить проект"
msgid "Canceled deployment to"
msgstr "Отменено развёртывание в"
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Ðет возможноÑти объединить автоматичеÑки"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Ðевозможно Ñоздать Ñообщение о нарушении. Пользователь удалён."
@@ -6805,7 +6854,7 @@ msgid "Cannot create the abuse report. This user has been blocked."
msgstr "Ðевозможно Ñоздать Ñообщение о нарушении. Пользователь заблокирован."
msgid "Cannot delete %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Ðе удаетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ %{profile_name}, упомÑнутый в политике безопаÑноÑти"
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "Ðевозможно проводить одновременно неÑколько импортов из Jira"
@@ -6820,13 +6869,13 @@ msgid "Cannot make the epic confidential if it contains non-confidential child e
msgstr ""
msgid "Cannot make the epic confidential if it contains non-confidential issues"
-msgstr ""
+msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ñделать цель конфиденциальной, еÑли она Ñодержит неконфиденциальные обÑуждениÑ"
msgid "Cannot merge"
msgstr "Ðе удаетÑÑ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½Ð¸Ñ‚ÑŒ"
msgid "Cannot modify %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Ðевозможно изменить %{profile_name}, упомÑнутый в политике безопаÑноÑти"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðевозможно изменить управлÑемый клаÑтер Kubernetes"
@@ -6844,7 +6893,7 @@ msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
-msgstr ""
+msgstr "Ðевозможно отобразить предварительный проÑмотр. Ð”Ð»Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ проÑмотра файлов ÑÑкизов они должны иметь формат файла, предÑтавленный в Sketch верÑии 43 и выше."
msgid "Cannot skip two factor authentication setup"
msgstr "Ðевозможно пропуÑтить наÑтройку двухфакторной аутентификации"
@@ -6853,25 +6902,25 @@ msgid "Capacity threshold"
msgstr ""
msgid "Card holder name"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†Ð° карты"
msgid "Card number:"
-msgstr ""
+msgstr "Ðомер карты:"
msgid "CascadingSettings|Enforce for all subgroups"
-msgstr ""
+msgstr "Принудительно применить Ð´Ð»Ñ Ð²Ñех подгрупп"
msgid "CascadingSettings|Setting enforced"
msgstr ""
msgid "CascadingSettings|Subgroups cannot change this setting."
-msgstr ""
+msgstr "Подгруппы не могут изменить Ñту наÑтройку."
msgid "CascadingSettings|This setting has been enforced by an instance admin."
msgstr ""
msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
-msgstr ""
+msgstr "Эта наÑтройка была принудительно применена владельцем %{link}."
msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
msgstr ""
@@ -6925,7 +6974,7 @@ msgid "Change reviewer(s)."
msgstr ""
msgid "Change role"
-msgstr ""
+msgstr "Изменить роль"
msgid "Change status"
msgstr "Изменить ÑтатуÑ"
@@ -6973,10 +7022,10 @@ msgid "ChangeTypeAction|Revert in branch"
msgstr ""
msgid "ChangeTypeAction|Search branches"
-msgstr ""
+msgstr "ПоиÑк веток"
msgid "ChangeTypeAction|Search projects"
-msgstr ""
+msgstr "ПоиÑк проектов"
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
@@ -7000,7 +7049,7 @@ msgid "Changed reviewer(s)."
msgstr ""
msgid "Changed the title to \"%{title_param}\"."
-msgstr ""
+msgstr "Заголовок изменен на \"%{title_param}\"."
msgid "Changes"
msgstr "ИзменениÑ"
@@ -7009,7 +7058,7 @@ msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being
msgstr ""
msgid "Changes saved."
-msgstr ""
+msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñохранены."
msgid "Changes suppressed. Click to show."
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñкрыты. Ðажмите, чтобы показать."
@@ -7018,7 +7067,7 @@ msgid "Changes the title to \"%{title_param}\"."
msgstr "ИзменÑет название на \"%{title_param}\"."
msgid "Changes to the title have not been saved"
-msgstr ""
+msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² заголовке не были Ñохранены"
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -7090,10 +7139,10 @@ msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why th
msgstr ""
msgid "Check the current instance configuration "
-msgstr ""
+msgstr "Проверьте текущую конфигурацию ÑкземплÑра "
msgid "Check with your administrator."
-msgstr ""
+msgstr "Проверьте Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором."
msgid "Check your Docker images for known vulnerabilities."
msgstr "Проверьте ваши образы Docker на наличие извеÑтных уÑзвимоÑтей."
@@ -7102,7 +7151,7 @@ msgid "Check your Kubernetes cluster images for known vulnerabilities."
msgstr ""
msgid "Check your source instance permissions."
-msgstr ""
+msgstr "Проверьте права доÑтупа к иÑходному ÑкземплÑру."
msgid "Checking %{text} availability…"
msgstr "Проверка доÑтупноÑти %{text} ..."
@@ -7114,10 +7163,10 @@ msgid "Checking branch availability..."
msgstr "Проверка доÑтупноÑти ветви..."
msgid "Checking group URL availability..."
-msgstr ""
+msgstr "Проверка доÑтупноÑти URL группы..."
msgid "Checking group path availability..."
-msgstr ""
+msgstr "Проверка доÑтупноÑти пути группы..."
msgid "Checking username availability..."
msgstr "Проверка доÑтупноÑти имени пользователÑ..."
@@ -7132,7 +7181,7 @@ msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per user per year"
-msgstr ""
+msgstr "$%{selectedPlanPrice} за Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² год"
msgid "Checkout|%d CI minute pack"
msgid_plural "Checkout|%d CI minute packs"
@@ -7148,7 +7197,7 @@ msgid "Checkout|%{name}'s CI minutes"
msgstr ""
msgid "Checkout|%{name}'s GitLab subscription"
-msgstr ""
+msgstr "ПодпиÑка на GitLab Ð´Ð»Ñ %{name}"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
@@ -7157,7 +7206,7 @@ msgid "Checkout|%{quantity} CI minutes"
msgstr ""
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} ГБ хранилища"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
@@ -7170,61 +7219,64 @@ msgid "Checkout|%{selectedPlanText} plan"
msgstr "план %{selectedPlanText}"
msgid "Checkout|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
msgid "Checkout|(x%{numberOfUsers})"
-msgstr ""
+msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Платёжный адреÑ"
msgid "Checkout|CI minute pack"
-msgstr ""
+msgstr "Пакет минут CI"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
-msgstr ""
+msgstr "Пакеты минут CI иÑпользуютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ поÑле того, как вы иÑчерпали меÑÑчную квоту подпиÑки. Дополнительные минуты будут переноÑитьÑÑ Ð¸Ð· меÑÑца в меÑÑц и дейÑтвительны в течение одного года."
msgid "Checkout|CI minutes"
msgstr ""
msgid "Checkout|Checkout"
-msgstr ""
+msgstr "Оформление"
msgid "Checkout|City"
msgstr "Город"
msgid "Checkout|Confirm purchase"
-msgstr ""
+msgstr "Подтвердить покупку"
msgid "Checkout|Confirming..."
-msgstr ""
+msgstr "Подтверждение..."
msgid "Checkout|Continue to billing"
msgstr "Перейти к оплате"
msgid "Checkout|Continue to payment"
-msgstr ""
+msgstr "Перейти к оплате"
msgid "Checkout|Country"
msgstr "Страна"
msgid "Checkout|Create a new group"
-msgstr ""
+msgstr "Создать новую группу"
msgid "Checkout|Credit card form failed to load. Please try again."
msgstr "Ðе удалоÑÑŒ загрузить форму кредитной карты. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Credit card form failed to load: %{message}"
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить форму кредитной карты: %{message}"
msgid "Checkout|Edit"
-msgstr ""
+msgstr "Правка"
msgid "Checkout|Enter a number greater than 0"
msgstr ""
@@ -7236,22 +7288,22 @@ msgid "Checkout|Failed to confirm your order! Please try again."
msgstr "Ðе удалить подтвердить ваш заказ! ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ подтвердить ваш заказ: %{message}. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Failed to load countries. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить Ñтраны. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Failed to load states. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить штаты. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|Failed to load the payment form. Please try again."
msgstr ""
msgid "Checkout|Failed to register credit card. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ зарегиÑтрировать кредитную карту. ПожалуйÑта, попробуйте ещё раз."
msgid "Checkout|GB"
-msgstr ""
+msgstr "ГБ"
msgid "Checkout|GitLab group"
msgstr "Группа GitLab"
@@ -7263,7 +7315,7 @@ msgid "Checkout|Group"
msgstr "Группа"
msgid "Checkout|Name of company or organization using GitLab"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ð¸ или организации, иÑпользующей GitLab"
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
msgstr ""
@@ -7281,7 +7333,7 @@ msgid "Checkout|Please select a state"
msgstr "ПожалуйÑта, выберите штат"
msgid "Checkout|Purchase details"
-msgstr ""
+msgstr "Детали покупки"
msgid "Checkout|Select"
msgstr "Выбрать"
@@ -7296,7 +7348,7 @@ msgid "Checkout|Street address"
msgstr "ÐÐ´Ñ€ÐµÑ ÑƒÐ»Ð¸Ñ†Ñ‹"
msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
-msgstr ""
+msgstr "Отправка формы кредитной карты не удалаÑÑŒ Ñ ÐºÐ¾Ð´Ð¾Ð¼ %{errorCode}: %{errorMessage}"
msgid "Checkout|Subscription details"
msgstr "Детали подпиÑки"
@@ -7311,10 +7363,10 @@ msgid "Checkout|Total"
msgstr "Итого"
msgid "Checkout|Total minutes: %{quantity}"
-msgstr ""
+msgstr "Ð’Ñего минут: %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "Ð’Ñего проÑтранÑтва: %{quantity} ГБ"
msgid "Checkout|Users"
msgstr "Пользователи"
@@ -7332,7 +7384,7 @@ msgid "Checkout|Your subscription will be applied to this group"
msgstr "Ваша подпиÑка будет применена к Ñтой группе"
msgid "Checkout|Zip code"
-msgstr ""
+msgstr "Почтовый индекÑ"
msgid "Checkout|a storage subscription"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr "Подобрать Ñтот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Child"
msgstr "ДочернÑÑ"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "Дочерний объект не ÑущеÑтвует."
@@ -7368,7 +7423,7 @@ msgid "Chinese language support using"
msgstr ""
msgid "Choose File..."
-msgstr ""
+msgstr "Выбрать файл..."
msgid "Choose a file"
msgstr "Выберите файл"
@@ -7395,10 +7450,10 @@ msgid "Choose specific groups or storage shards"
msgstr ""
msgid "Choose the preferred Runner and populate the AWS CFT."
-msgstr ""
+msgstr "Выберите предпочтительный Runner и заполните AWS CFT."
msgid "Choose the top-level group for your repository imports."
-msgstr ""
+msgstr "Выберите группу верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° репозиториÑ."
msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
msgstr ""
@@ -7407,7 +7462,7 @@ msgid "Choose what content you want to see on a group’s overview page."
msgstr "Выберите Ñодержимое, которое вы хотите видеть на Ñтранице обзора группы."
msgid "Choose which Git strategy to use when fetching the project."
-msgstr ""
+msgstr "Выберите, какую Ñтратегию Git иÑпользовать при получении проекта."
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
@@ -7416,7 +7471,7 @@ msgid "Choose your framework"
msgstr "Выберите фреймворк"
msgid "CiCdAnalytics|Date range: %{range}"
-msgstr ""
+msgstr "Диапазон дат: %{range}"
msgid "CiStatusLabel|canceled"
msgstr "отменено"
@@ -7515,7 +7570,7 @@ msgid "CiVariables|Protected"
msgstr "ЗащищеннаÑ"
msgid "CiVariables|Remove variable"
-msgstr ""
+msgstr "Удалить переменную"
msgid "CiVariables|Remove variable row"
msgstr "Удалить Ñтроку переменных"
@@ -7539,7 +7594,7 @@ msgid "CiVariables|Variables"
msgstr "Переменные"
msgid "CiVariable|* (All environments)"
-msgstr ""
+msgstr "* (Ð’Ñе Ñреды)"
msgid "CiVariable|All environments"
msgstr "Ð’Ñе Ñреды"
@@ -7593,7 +7648,7 @@ msgid "Clear"
msgstr "ОчиÑтить"
msgid "Clear all repository checks"
-msgstr ""
+msgstr "ОчиÑтить вÑе проверки репозиториÑ"
msgid "Clear chart filters"
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "Сертификат аутентификации клиента"
-
-msgid "Client authentication key"
-msgstr "Ключ аутентификации клиента"
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr "Закрыто: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7851,7 +7903,7 @@ msgid "ClusterAgents|Certificate"
msgstr ""
msgid "ClusterAgents|Configuration"
-msgstr ""
+msgstr "КонфигурациÑ"
msgid "ClusterAgents|Connect a cluster through the Agent"
msgstr ""
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7875,10 +7927,10 @@ msgid "ClusterAgents|Connected"
msgstr ""
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ"
msgid "ClusterAgents|Copy token"
-msgstr ""
+msgstr "Копировать токен"
msgid "ClusterAgents|Create a new cluster"
msgstr ""
@@ -7902,7 +7954,7 @@ msgid "ClusterAgents|Deprecated"
msgstr ""
msgid "ClusterAgents|Description"
-msgstr ""
+msgstr "ОпиÑание"
msgid "ClusterAgents|Event occurred"
msgstr ""
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8041,7 +8114,7 @@ msgid "ClusterAgents|You cannot see this token again after you close this window
msgstr ""
msgid "ClusterAgents|You will need to create a token to connect to your agent"
-msgstr ""
+msgstr "Вам необходимо Ñоздать токен Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº агенту"
msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
msgstr ""
@@ -8059,10 +8132,10 @@ msgid "ClusterApplicationsRemoved|One-click application management was removed i
msgstr ""
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Подробнее%{linkEnd}"
msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
-msgstr ""
+msgstr "Проект ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°Ñтером можно иÑпользовать Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка заданий Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸Ñми Kubernetes %{code_open}cluster-admin%{code_close}."
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr "ОблаÑÑ‚ÑŒ доÑтупа токена Ñлужбы уÑтановлена на %{code}kube-system%{end_code} Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸Ñми %{code}cluster-admin%{end_code}."
@@ -8086,19 +8159,19 @@ msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share t
msgstr "Добавление клаÑтера Kubernetes автоматичеÑки разделит клаÑтер между вÑеми проектами. ИÑпользуйте Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÑ†ÐµÐ½Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, развертывайте Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ легко запуÑкайте Ñборочные линии Ð´Ð»Ñ Ð²Ñех проектов, иÑпользующих один и тот же клаÑтер."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Добавление интеграции в вашу группу позволит иÑпользовать клаÑтер во вÑех ваших проектах."
msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
-msgstr ""
+msgstr "Добавление интеграции позволит иÑпользовать клаÑтер во вÑех проектах."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
-msgstr ""
+msgstr "РаÑширенные опции интеграции Ñтого клаÑтера Kubernetes"
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Разрешить GitLab управлÑÑ‚ÑŒ проÑтранÑтвом имён и Ñлужебными учётными запиÑÑми Ñтого клаÑтера. %{linkStart}Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ%{linkEnd}"
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
-msgstr ""
+msgstr "Разрешить GitLab управлÑÑ‚ÑŒ проÑтранÑтвами имён и Ñлужебными аккаунтами Ñтого клаÑтера."
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
msgstr ""
@@ -8122,7 +8195,7 @@ msgid "ClusterIntegration|An error occurred while trying to fetch zone machine t
msgstr "Произошла ошибка при попытке извлечь типы машин облаÑти: %{error}"
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
-msgstr ""
+msgstr "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при попытке Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Kubernetes."
msgid "ClusterIntegration|Any project namespaces"
msgstr ""
@@ -8137,7 +8210,7 @@ msgid "ClusterIntegration|Authenticate with Amazon Web Services"
msgstr "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Amazon Web Services"
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "Ошибка аутентификации"
msgid "ClusterIntegration|Base domain"
msgstr "Базовое доменное имÑ"
@@ -8152,7 +8225,7 @@ msgid "ClusterIntegration|Check your CA certificate"
msgstr ""
msgid "ClusterIntegration|Check your cluster status"
-msgstr ""
+msgstr "Проверить ÑоÑтоÑние клаÑтера"
msgid "ClusterIntegration|Check your token"
msgstr ""
@@ -8173,7 +8246,7 @@ msgid "ClusterIntegration|Clear cluster cache"
msgstr "ОчиÑтить кÑш клаÑтера"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
-msgstr ""
+msgstr "ОчиÑтить локальный кÑш проÑтранÑтв имён и Ñлужебных учётных запиÑей."
msgid "ClusterIntegration|Cluster Region"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr "Коммит (при редактировании опиÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð
msgid "Commit Message"
msgstr "ОпиÑание коммита"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9098,10 +9174,10 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr "Ðечего Ñравнивать."
msgid "CompareRevisions|Branches"
-msgstr ""
+msgstr "Ветки"
msgid "CompareRevisions|Compare"
-msgstr ""
+msgstr "Сравнить"
msgid "CompareRevisions|Create merge request"
msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr "ÐаÑтройка траÑÑировки"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "ÐаÑтроить ÑущеÑтвующую уÑтановку"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Подтвердить"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9368,7 +9462,7 @@ msgid "Confirmation required"
msgstr "ТребуетÑÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ðµ"
msgid "Confirmed at:"
-msgstr ""
+msgstr "Подтвержден:"
msgid "Confirmed:"
msgstr ""
@@ -9413,7 +9507,7 @@ msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To
msgstr ""
msgid "Congratulations, your free trial is activated."
-msgstr ""
+msgstr "ПоздравлÑем, беÑплатный пробный период активирован."
msgid "Connect"
msgstr "Подключить"
@@ -9470,7 +9564,7 @@ msgid "Container does not exist"
msgstr "Контейнер не ÑущеÑтвует"
msgid "Container must be a project or a group."
-msgstr ""
+msgstr "Контейнер должен быть проектом или группой."
msgid "Container registry images"
msgstr "Образы рееÑтра контейнеров"
@@ -9634,37 +9728,37 @@ msgid "ContainerRegistry|Keep tags matching:"
msgstr ""
msgid "ContainerRegistry|Keep the most recent:"
-msgstr ""
+msgstr "Сохранить Ñамые Ñвежие:"
msgid "ContainerRegistry|Keep these tags"
-msgstr ""
+msgstr "Сохранить Ñти теги"
msgid "ContainerRegistry|Last updated %{time}"
-msgstr ""
+msgstr "ПоÑледнее обновление %{time}"
msgid "ContainerRegistry|Login"
msgstr "Вход"
msgid "ContainerRegistry|Manifest digest: %{digest}"
-msgstr ""
+msgstr "ДайджеÑÑ‚ манифеÑта: %{digest}"
msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
-msgstr ""
+msgstr "Ðе хватает прав доÑтупа, кнопка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°"
msgid "ContainerRegistry|Next cleanup scheduled to run on:"
-msgstr ""
+msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¾Ñ‡Ð¸Ñтка запланирована на:"
msgid "ContainerRegistry|Not yet scheduled"
-msgstr ""
+msgstr "Еще не запланироано"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
+msgstr "Примечание: Любое обновление политики приведет к изменению даты и времени выполнениÑ"
msgid "ContainerRegistry|Please try different search criteria"
msgstr ""
msgid "ContainerRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "Опубликовано %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
msgstr ""
@@ -9686,28 +9780,28 @@ msgstr[2] "Удалить тегов"
msgstr[3] "Удалить тегов"
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "Удалить теги, ÑоответÑтвующие:"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "Удалить теги Ñтарше:"
msgid "ContainerRegistry|Remove these tags"
-msgstr ""
+msgstr "Удалить Ñти теги"
msgid "ContainerRegistry|Root image"
-msgstr ""
+msgstr "Корневой образ"
msgid "ContainerRegistry|Run cleanup:"
-msgstr ""
+msgstr "ЗапуÑтить очиÑтку:"
msgid "ContainerRegistry|Some tags were not deleted"
-msgstr ""
+msgstr "Ðекоторые теги не были удалены"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
-msgstr ""
+msgstr "Что-то пошло не так при получении политики очиÑтки."
msgid "ContainerRegistry|Something went wrong while fetching the image details."
-msgstr ""
+msgstr "Что-то пошло не так при получении деталей образа."
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
msgstr "Что-то пошло не так при извлечении ÑпиÑка репозиториев."
@@ -9722,52 +9816,52 @@ msgid "ContainerRegistry|Something went wrong while marking the tags for deletio
msgstr "Что-то пошло не так при отметке тегов к удалению."
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
-msgstr ""
+msgstr "Что-то пошло не так при планировании ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ %{title}. ПожалуйÑта, попробуйте ещё раз."
msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
-msgstr ""
+msgstr "Что-то пошло не так при планировании ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð°."
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
-msgstr ""
+msgstr "Что-то пошло не так при обновлении политики очиÑтки."
msgid "ContainerRegistry|Sorry, your filter produced no results."
-msgstr ""
+msgstr "К Ñожалению, нет результатов, ÑоответÑтвующих фильтру."
msgid "ContainerRegistry|Tag successfully marked for deletion."
-msgstr ""
+msgstr "Тег уÑпешно помечен Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ."
msgid "ContainerRegistry|Tags successfully marked for deletion."
-msgstr ""
+msgstr "Теги уÑпешно помечены Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
msgstr "Теги, которые ÑоответÑтвуют Ñтим правилам будут %{strongStart}Ñохранены%{strongEnd}, даже, еÑли они ÑоответÑтвуют правилам ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð½Ð¸Ð¶Ðµ. %{secondStrongStart}ПоÑледний%{secondStrongEnd} тег вÑегда ÑохранÑетÑÑ."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
+msgstr "СоответÑтвующие Ñтим правилам теги %{strongStart}удалÑÑŽÑ‚ÑÑ%{strongEnd}, еÑли только вышеприведенное правило не требует их ÑохранениÑ."
msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Теги, имена которых ÑоответÑтвуют Ñтому регулÑрному выражению, ÑохранÑÑŽÑ‚ÑÑ. %{linkStart}ПоÑмотреть примеры регулÑрных выражений.%{linkEnd}"
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Теги, имена которых ÑоответÑтвуют Ñтому регулÑрному выражению, удалÑÑŽÑ‚ÑÑ. %{linkStart}ПоÑмотреть примеры регулÑрных выражений.%{linkEnd}"
msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¸ очиÑтки иÑтекло раньше, чем произошло удаление вÑех тегов. ÐдминиÑтратор может %{adminLinkStart}запуÑтить очиÑтку вручную%{adminLinkEnd}, или можно дождатьÑÑ Ñледующего автоматичеÑкого запуÑка. %{docLinkStart}Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ%{docLinkEnd}"
msgid "ContainerRegistry|The filter returned no results"
msgstr ""
msgid "ContainerRegistry|The image repository could not be found."
-msgstr ""
+msgstr "Репозиторий образов не найден."
msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
msgstr "ПоÑледний тег, ÑвÑзанный Ñ Ñтим образом недавно был удалён. Этот пуÑтой образ и любые ÑвÑзанные Ñ Ð½Ð¸Ð¼ данные будут автоматичеÑки удалены в ходе регулÑрной Ñборки муÑора. ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ вопроÑÑ‹, ÑвÑжитеÑÑŒ Ñо Ñвоим админиÑтратором."
msgid "ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
-msgstr ""
+msgstr "Запрошенный репозиторий образов не ÑущеÑтвует или был удалён. ЕÑли вы Ñчитаете, что Ñто ошибка, попробуйте обновить Ñтраницу."
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr ""
+msgstr "Значение Ñтого Ð¿Ð¾Ð»Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть короче 256 Ñимволов"
msgid "ContainerRegistry|There are no container images available in this group"
msgstr "Ð’ Ñтой группе нет доÑтупных образов контейнеров"
@@ -9776,25 +9870,25 @@ msgid "ContainerRegistry|There are no container images stored for this project"
msgstr "Ð’ Ñтом проекте нет Docker образов"
msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
-msgstr ""
+msgstr "Произошла ошибка при удалении Ñтого Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð¾Ð², пожалуйÑта, попробуйте ещё раз."
msgid "ContainerRegistry|This image has no active tags"
msgstr "Этот образ не имеет активных тегов"
msgid "ContainerRegistry|This image repository has failed to be deleted"
-msgstr ""
+msgstr "Ðе удалоÑÑŒ удалить Ñтот репозиторий образов"
msgid "ContainerRegistry|This image repository is scheduled for deletion"
msgstr "Запланировано удаление Ñтого хранилища образов"
msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Этот репозиторий образов будет удалён. %{linkStart}Подробнее.%{linkEnd}"
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ñтого проекта не включена политика очиÑтки тегов."
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
-msgstr ""
+msgstr "Чтобы раÑширить облаÑÑ‚ÑŒ поиÑка, измените или удалите фильтры выше."
msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
@@ -9812,10 +9906,10 @@ msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{item} тегов. Ð’Ñ‹ уверены?"
msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{item}. Ð’Ñ‹ уверены?"
msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить репозиторий %{title}. ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñтот репозиторий будет удалён навÑегда."
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Ð’Ñ‹ можете добавить образ в Ñтот рееÑÑ‚Ñ€ контвейнеров при помощи данных команд:"
@@ -9824,7 +9918,7 @@ msgid "Content parsed with %{link}."
msgstr ""
msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "Содержание"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -9884,13 +9978,13 @@ msgid "ContributionAnalytics|Last week"
msgstr "ПоÑледнÑÑ Ð½ÐµÐ´ÐµÐ»Ñ"
msgid "ContributionAnalytics|Merge requests"
-msgstr ""
+msgstr "ЗапроÑÑ‹ на ÑлиÑние"
msgid "ContributionAnalytics|No issues for the selected time period."
msgstr "Ðет задач Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ периода."
msgid "ContributionAnalytics|No merge requests for the selected time period."
-msgstr ""
+msgstr "Ðет запроÑов на ÑлиÑние в выбранном периоде."
msgid "ContributionAnalytics|No pushes for the selected time period."
msgstr ""
@@ -9911,9 +10005,9 @@ msgid "Control emails linked to your account"
msgstr "Управление адреÑами Ñлектронной почты, ÑвÑзанными Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑью"
msgid "Control how the GitLab Package Registry functions."
-msgstr ""
+msgstr "УправлÑйте работой РееÑтра пакетов GitLab."
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9935,7 +10029,7 @@ msgid "Copy %{http_label} clone URL"
msgstr ""
msgid "Copy %{name}"
-msgstr ""
+msgstr "Копировать %{name}"
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -9953,7 +10047,7 @@ msgid "Copy ID"
msgstr "Копировать ID"
msgid "Copy IP Address"
-msgstr ""
+msgstr "Скопировать IP-адреÑ"
msgid "Copy KRB5 clone URL"
msgstr "Скопировать URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· KRB5"
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "Ðе удалоÑÑŒ отозвать токен Ð¸Ð¼Ð¸Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "Ðе удалоÑÑŒ отозвать токен личного доÑтупа %{personal_access_token_name}."
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10217,16 +10329,16 @@ msgid "Create %{environment}"
msgstr "Создать %{environment}"
msgid "Create %{humanized_resource_name}"
-msgstr ""
+msgstr "Создать %{humanized_resource_name}"
msgid "Create %{type}"
-msgstr ""
+msgstr "Создать %{type}"
msgid "Create %{workspace} label"
-msgstr ""
+msgstr "Создать метку %{workspace}"
msgid "Create Google Cloud project"
-msgstr ""
+msgstr "Создать проект Google Cloud"
msgid "Create New Directory"
msgstr "Создать Ðовый каталог"
@@ -10238,7 +10350,7 @@ msgid "Create a GitLab account first, and then connect it to your %{label} accou
msgstr "Сначала Ñоздайте учетную запиÑÑŒ GitLab, а затем подключите ее к вашей учетной запиÑи %{label}."
msgid "Create a Mattermost team for this group"
-msgstr ""
+msgstr "Создать команду в Mattermost Ð´Ð»Ñ Ñтой группы"
msgid "Create a merge request"
msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -10265,7 +10377,7 @@ msgid "Create a personal access token on your account to pull or push via %{prot
msgstr "Создать личный токен на аккаунте Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ отправки через %{protocol}."
msgid "Create an account using:"
-msgstr ""
+msgstr "Создать аккаунт Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ:"
msgid "Create an incident. Incidents are created for each alert triggered."
msgstr ""
@@ -10310,7 +10422,7 @@ msgid "Create group label"
msgstr "Создать метку группы"
msgid "Create incident"
-msgstr ""
+msgstr "Создать инцидент"
msgid "Create issue"
msgstr "Создать обÑуждение"
@@ -10321,9 +10433,12 @@ msgstr ""
msgid "Create iteration"
msgstr "Создать итерацию"
-msgid "Create list"
+msgid "Create label"
msgstr ""
+msgid "Create list"
+msgstr "Создать ÑпиÑок"
+
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "Создать ÑпиÑок из меток. ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ñтой меткой поÑвлÑÑŽÑ‚ÑÑ Ð² Ñтом ÑпиÑке."
@@ -10337,13 +10452,13 @@ msgid "Create milestone"
msgstr "Создать Ñтап"
msgid "Create new"
-msgstr ""
+msgstr "Создать новый"
msgid "Create new %{name} by email"
msgstr ""
msgid "Create new CI/CD pipeline"
-msgstr ""
+msgstr "Создать новую Ñборочную линию CI/CD"
msgid "Create new Value Stream"
msgstr "Создать новый Поток ценноÑти"
@@ -10370,7 +10485,7 @@ msgid "Create new project"
msgstr "Создать новый проект"
msgid "Create or import your first project"
-msgstr ""
+msgstr "Создайте или импортируйте Ñвой первый проект"
msgid "Create project"
msgstr "Создать проект"
@@ -10391,28 +10506,28 @@ msgid "Create snippet"
msgstr "Создать Ñниппет"
msgid "Create tag %{tagName}"
-msgstr ""
+msgstr "Создать тег %{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "Создать тему"
msgid "Create user"
-msgstr ""
+msgstr "Создать пользователÑ"
msgid "Create via merge request"
msgstr ""
msgid "Create wildcard: %{searchTerm}"
-msgstr ""
+msgstr "Создать шаблон: %{searchTerm}"
msgid "Create your first page"
msgstr "Создайте вашу первую Ñтраницу"
msgid "Create your group"
-msgstr ""
+msgstr "Создать группу"
msgid "Create/import your first project"
-msgstr ""
+msgstr "Создать/импортировать Ñвой первый проект"
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на Ñоздание подгруппы в Ñтой группе."
@@ -10490,10 +10605,10 @@ msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
-msgstr ""
+msgstr "ТребуетÑÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ"
msgid "CreateValueStreamForm|New stage"
-msgstr ""
+msgstr "Ðовый Ñтап"
msgid "CreateValueStreamForm|Plan stage start"
msgstr "Ðачало Ñтапа планированиÑ"
@@ -10553,7 +10668,7 @@ msgid "Created"
msgstr "Создан"
msgid "Created %{epicTimeagoDate}"
-msgstr ""
+msgstr "Создана %{epicTimeagoDate}"
msgid "Created %{timestamp}"
msgstr ""
@@ -10579,14 +10694,17 @@ msgstr "Создано мной"
msgid "Created by:"
msgstr ""
-msgid "Created date"
+msgid "Created compliance violations if any were found"
msgstr ""
+msgid "Created date"
+msgstr "Дата ÑозданиÑ"
+
msgid "Created issue %{issueLink}"
-msgstr ""
+msgstr "Создано обÑуждение %{issueLink}"
msgid "Created issue %{issueLink} at %{projectLink}"
-msgstr ""
+msgstr "Создано обÑуждение %{issueLink} в %{projectLink}"
msgid "Created merge request %{mergeRequestLink}"
msgstr "Создан Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние %{mergeRequestLink}"
@@ -10610,7 +10728,7 @@ msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue
msgstr "Создает ветку %{branch_name} и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñтого вопроÑа."
msgid "Creating"
-msgstr ""
+msgstr "Создание"
msgid "Creating epic"
msgstr "Цель ÑоздаетÑÑ"
@@ -10745,13 +10863,13 @@ msgid "Current password"
msgstr "Текущий пароль"
msgid "Current sign-in IP:"
-msgstr ""
+msgstr "Текущий IP-Ð°Ð´Ñ€ÐµÑ Ð²Ñ…Ð¾Ð´Ð°:"
msgid "Current sign-in at:"
-msgstr ""
+msgstr "Текущий вход в:"
msgid "Current sign-in ip"
-msgstr ""
+msgstr "Текущий IP-Ð°Ð´Ñ€ÐµÑ Ð²Ñ…Ð¾Ð´Ð°"
msgid "Current vulnerabilities count"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11492,10 +11586,10 @@ msgid "Data is still calculating..."
msgstr "Данные вÑе еще вычиÑлÑÑŽÑ‚ÑÑ..."
msgid "Data type"
-msgstr ""
+msgstr "Тип данных"
msgid "Database update failed"
-msgstr ""
+msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных"
msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
msgstr ""
@@ -11504,10 +11598,10 @@ msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
msgstr ""
msgid "DatadogIntegration|API URL"
-msgstr ""
+msgstr "URL-Ð°Ð´Ñ€ÐµÑ API"
msgid "DatadogIntegration|Environment"
-msgstr ""
+msgstr "Окружение"
msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}"
msgstr ""
@@ -11531,7 +11625,7 @@ msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
msgstr ""
msgid "Datasource name not found"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ð¸Ñточника данных не найдено"
msgid "Date"
msgstr "Дата"
@@ -11540,16 +11634,16 @@ msgid "Date merged"
msgstr ""
msgid "Date picker"
-msgstr ""
+msgstr "Выбор даты"
msgid "Date range"
-msgstr ""
+msgstr "Диапазон дат"
msgid "Date range limited to %{number} days"
-msgstr ""
+msgstr "Диапазон дат ограничен %{number} днÑми"
msgid "Date range must be shorter than %{max_range} days."
-msgstr ""
+msgstr "Диапазон дат должен быть короче %{max_range} дней."
msgid "Day of month"
msgstr "День меÑÑца"
@@ -11570,13 +11664,13 @@ msgid "Days"
msgstr "Дней"
msgid "Days to merge"
-msgstr ""
+msgstr "Дней до ÑлиÑниÑ"
msgid "Deactivate dormant users after 90 days of inactivity"
-msgstr ""
+msgstr "Деактивировать бездейÑтвующих пользователей поÑле 90 дней бездейÑтвиÑ"
msgid "Dear Administrator,"
-msgstr ""
+msgstr "Уважаемый админиÑтратор,"
msgid "Debian package already exists in Distribution"
msgstr ""
@@ -11597,13 +11691,13 @@ msgid "Decline and sign out"
msgstr "Отклонить и выйти"
msgid "Decompressed archive size validation failed."
-msgstr ""
+msgstr "Ошибка проверки размера раÑпакованного архива."
msgid "Decrease"
-msgstr ""
+msgstr "Уменьшить"
msgid "Default CI/CD configuration file"
-msgstr ""
+msgstr "Файл конфигурации CI/CD по умолчанию"
msgid "Default artifacts expiration"
msgstr ""
@@ -11615,16 +11709,13 @@ msgid "Default branch and protected branches"
msgstr "Ветвь по умолчанию и защищенные ветки"
msgid "Default branch protection"
-msgstr ""
-
-msgid "Default classification label"
-msgstr ""
+msgstr "Защита ветки по умолчанию"
msgid "Default delayed project deletion"
-msgstr ""
+msgstr "Отложенное удаление проекта по умолчанию"
msgid "Default deletion delay"
-msgstr ""
+msgstr "Задержка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию"
msgid "Default description template for issues"
msgstr "Шаблон опиÑÐ°Ð½Ð¸Ñ Ð¾Ð±Ñуждений по умолчанию."
@@ -11636,7 +11727,7 @@ msgid "Default first day of the week"
msgstr "Первый день недели по умолчанию"
msgid "Default first day of the week in calendars and date pickers."
-msgstr ""
+msgstr "Первый день недели по умолчанию в календарÑÑ… и ÑредÑтвах выбора даты."
msgid "Default initial branch name"
msgstr ""
@@ -11711,13 +11802,13 @@ msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This jo
msgstr ""
msgid "DelayedJobs|Run the delayed job now?"
-msgstr ""
+msgstr "ЗапуÑтить отложенное задание ÑейчаÑ?"
msgid "DelayedJobs|Start now"
-msgstr ""
+msgstr "ЗапуÑтить ÑейчаÑ"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "Убрать из очереди"
msgid "DelayedJobs|delayed"
msgstr ""
@@ -11726,19 +11817,19 @@ msgid "Delete"
msgstr "Удалить"
msgid "Delete %{issuableType}"
-msgstr ""
+msgstr "Удалить %{issuableType}"
msgid "Delete %{name}"
-msgstr ""
+msgstr "Удалить %{name}"
msgid "Delete Comment"
msgstr "Удалить комментарий"
msgid "Delete Key"
-msgstr ""
+msgstr "Удалить ключ"
msgid "Delete Selected"
-msgstr ""
+msgstr "Удалить выбранное"
msgid "Delete Value Stream"
msgstr "Удалить Поток ценноÑти"
@@ -11750,10 +11841,10 @@ msgid "Delete artifacts"
msgstr "Удалить артефакты"
msgid "Delete badge"
-msgstr ""
+msgstr "Удалить значок"
msgid "Delete column"
-msgstr ""
+msgstr "Удалить колонку"
msgid "Delete comment"
msgstr "Удалить комментарий"
@@ -11765,16 +11856,16 @@ msgid "Delete deploy key"
msgstr ""
msgid "Delete file"
-msgstr ""
+msgstr "Удалить файл"
msgid "Delete image repository"
-msgstr ""
+msgstr "Удалить репозиторий образов"
msgid "Delete label"
-msgstr ""
+msgstr "Удалить метку"
msgid "Delete label: %{labelName}"
-msgstr ""
+msgstr "Удалить метку: %{labelName}"
msgid "Delete pipeline"
msgstr "Удалить Ñборочную линию"
@@ -11783,10 +11874,10 @@ msgid "Delete project"
msgstr "Удалить проект"
msgid "Delete project. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Удалить проект. Ð’Ñ‹ ÐБСОЛЮТÐО УВЕРЕÐЫ?"
msgid "Delete row"
-msgstr ""
+msgstr "Удалить Ñтроку"
msgid "Delete self monitoring project"
msgstr ""
@@ -11801,10 +11892,10 @@ msgid "Delete source branch"
msgstr "Удалить иÑходную ветку"
msgid "Delete subscription"
-msgstr ""
+msgstr "Удалить подпиÑку"
msgid "Delete table"
-msgstr ""
+msgstr "Удалить таблицу"
msgid "Delete this attachment"
msgstr "Удалить вложение"
@@ -11813,7 +11904,7 @@ msgid "Delete this epic and all descendants?"
msgstr ""
msgid "Delete user list"
-msgstr ""
+msgstr "Удалить ÑпиÑок пользователей"
msgid "Delete variable"
msgstr "Удалить переменную"
@@ -11822,7 +11913,7 @@ msgid "DeleteProject|Failed to remove events. Please try again or contact admini
msgstr ""
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ удалить репозиторий проекта. ПожалуйÑта попробуйте ещё раз или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором."
msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
msgstr "Ðе удалоÑÑŒ удалить Ñниппеты проекта. ПожалуйÑта, попробуйте ещё раз или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором."
@@ -11834,7 +11925,7 @@ msgid "DeleteProject|Failed to remove webhooks. Please try again or contact admi
msgstr ""
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
-msgstr ""
+msgstr "Ðе получилоÑÑŒ удалить репозиторий wiki. Попробуйте ещё раз или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором."
msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
msgstr "Ошибка при воÑÑтановлении Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°. ПожалуйÑта, попробуйте Ñнова, или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором."
@@ -11861,7 +11952,7 @@ msgid "Deleted projects cannot be restored!"
msgstr "Удаленные проекты не могут воÑÑтановлены!"
msgid "Deletes the source branch"
-msgstr ""
+msgstr "УдалÑет иÑходную ветку"
msgid "Deletes the source branch."
msgstr ""
@@ -11888,7 +11979,7 @@ msgid "Deny"
msgstr "Отклонить"
msgid "Deny access request"
-msgstr ""
+msgstr "Отклонить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° доÑтуп"
msgid "Dependencies"
msgstr "ЗавиÑимоÑти"
@@ -11905,10 +11996,10 @@ msgstr[3] "%d дополнительных уÑзвимоÑтей не покаÐ
msgid "Dependencies|%d more"
msgid_plural "Dependencies|%d more"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ещё %d"
+msgstr[1] "ещё %d"
+msgstr[2] "ещё %d"
+msgstr[3] "ещё %d"
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
@@ -12058,6 +12149,9 @@ msgstr[3] "РазвертываниÑ"
msgid "Deploy Keys"
msgstr "Ключи развёртываниÑ"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr "ПрогреÑÑ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ найден. Чтобы увидеть поды, убедитеÑÑŒ, что ваша Ñреда ÑоответÑтвует %{linkStart}критериÑм уÑтановки таблицы%{linkEnd}."
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Развернуть в..."
@@ -12137,7 +12234,7 @@ msgid "DeployKeys|Expand %{count} other projects"
msgstr "Развернуть в %{count} других проектах"
msgid "DeployKeys|Grant write permissions to this key"
-msgstr ""
+msgstr "ПредоÑтавить права на запиÑÑŒ Ñтому ключу"
msgid "DeployKeys|Loading deploy keys"
msgstr "Загрузка ключей развертываниÑ"
@@ -12161,10 +12258,10 @@ msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Ðктивные токены Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (%{active_tokens})"
msgid "DeployTokens|Allows read and write access to registry images."
-msgstr ""
+msgstr "Разрешает чтение и запиÑÑŒ в образы рееÑтра."
msgid "DeployTokens|Allows read and write access to the package registry."
-msgstr ""
+msgstr "Разрешает чтение и запиÑÑŒ в рееÑÑ‚Ñ€ пакетов."
msgid "DeployTokens|Allows read-only access to registry images."
msgstr ""
@@ -12215,7 +12312,7 @@ msgid "DeployTokens|Name"
msgstr "Ðаименование"
msgid "DeployTokens|New deploy token"
-msgstr ""
+msgstr "Ðовый токен развертываниÑ"
msgid "DeployTokens|Revoke"
msgstr "Отозвать"
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "Это развёртывание было Ñоздано Ñ Ð¸Ñпользованием API"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "отменено"
@@ -12406,10 +12533,10 @@ msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr ""
msgid "DesignManagement|Could not create new discussion. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ Ñоздать новую диÑкуÑÑию. ПожалуйÑта, попробуйте ещё раз."
msgid "DesignManagement|Could not update discussion. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ обновить обÑуждение. ПожалуйÑта, попробуйте ещё раз."
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
@@ -12712,7 +12839,7 @@ msgid "Didn't receive confirmation instructions?"
msgstr ""
msgid "Didn't receive unlock instructions?"
-msgstr ""
+msgstr "Ðе получили инÑтрукции по разблокировке?"
msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
msgstr ""
@@ -12787,7 +12914,7 @@ msgid "Disable Elasticsearch until indexing completes."
msgstr ""
msgid "Disable Two-factor Authentication"
-msgstr ""
+msgstr "Отключить двухфакторную аутентификацию"
msgid "Disable What's new"
msgstr "Отключить \"Что нового\""
@@ -12858,9 +12985,6 @@ msgstr "СредÑтва безопаÑноÑти, интегрированныÐ
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Ðачать беÑплатный пробный период"
@@ -12874,7 +12998,7 @@ msgid "Discuss a specific suggestion or question."
msgstr "ОбÑудить конкретное предложение или вопроÑ."
msgid "Discussion to reply to cannot be found"
-msgstr ""
+msgstr "ДиÑкуÑÑиÑ, на которую нужно ответить не найдена"
msgid "Disk Usage"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13007,7 +13131,7 @@ msgid "Download PDF"
msgstr ""
msgid "Download artifacts"
-msgstr ""
+msgstr "Скачать артефакты"
msgid "Download as"
msgstr "Скачать как"
@@ -13123,8 +13247,8 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
-msgstr "Редактировать узел Geo"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr ""
@@ -13346,10 +13470,10 @@ msgid "Email updates (optional)"
msgstr ""
msgid "Email:"
-msgstr ""
+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 "Похоже, что ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° пуÑта. УбедитеÑÑŒ, что ваш ответ находитÑÑ Ð²Ð²ÐµÑ€Ñ…Ñƒ пиÑьма, мы не можем обрабатывать вÑтроенные ответы."
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "Мы не Ñмогли найти проект. ПожалуйÑта, проверьте, еÑÑ‚ÑŒ ли какие-либо опечатки."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Вам не разрешено выполнÑÑ‚ÑŒ Ñто дейÑтвие. ЕÑли вы Ñчитаете, что Ñто ошибка, обратитеÑÑŒ к Ñотруднику."
@@ -13508,14 +13635,11 @@ msgid "Enable authenticated web request rate limit"
msgstr ""
msgid "Enable authentication"
-msgstr ""
+msgstr "Включить аутентификацию"
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr "ÐŸÑ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð° от перепривÑÐ·Ñ‹Ð²Ð°Ð½Ð¸Ñ DNS"
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13697,7 +13827,7 @@ msgid "Enter a number"
msgstr "Введите номер"
msgid "Enter an integer number between 0 and 100"
-msgstr ""
+msgstr "Введите целое чиÑло от 0 до 100"
msgid "Enter any color or choose one of the suggested colors below."
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr "Введите URL-Ð°Ð´Ñ€ÐµÑ Ð²Ð°ÑˆÐµÐ³Ð¾ Ñервера Bitbucket и Ð
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Введите URL запроÑа на ÑлиÑние"
@@ -13736,7 +13869,7 @@ msgid "Enter the code from the two-factor app on your mobile device. If you've l
msgstr "Введите код из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ð¹ аутентификации Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ мобильного уÑтройÑтва. ЕÑли вы потерÑли Ñвоё уÑтройÑтво, можете ввеÑти один из кодов воÑÑтановлениÑ."
msgid "Enter the name of your application, and we'll return a unique %{type}."
-msgstr ""
+msgstr "Введите Ð¸Ð¼Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ приложениÑ, и мы вернем уникальный %{type}."
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
msgstr ""
@@ -13764,10 +13897,10 @@ msgstr ""
msgid "Environment"
msgid_plural "Environments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Окружение"
+msgstr[1] "ОкружениÑ"
+msgstr[2] "ОкружениÑ"
+msgstr[3] "ОкружениÑ"
msgid "Environment does not have deployments"
msgstr "Окружение не имеет развёртываний"
@@ -13991,6 +14124,9 @@ msgstr "ОÑтановить окружение"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "Произошла ошибка при извлечении журналов. ПожалуйÑта, попробуйте ещё раз."
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr "защищённое"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Цель"
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14815,17 +14951,11 @@ msgid "External URL"
msgstr "Внешний URL"
msgid "External User:"
-msgstr ""
-
-msgid "External authentication"
-msgstr "ВнешнÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
+msgstr "Внешний пользователь:"
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr "URL внешнего хранилища"
@@ -14836,11 +14966,59 @@ msgid "External storage for repository static objects"
msgstr ""
msgid "ExternalAuthorizationService|Classification label"
-msgstr ""
+msgstr "Метка клаÑÑификации"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,12 +15101,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
-msgid "Failed to create new project access token: %{token_response_message}"
-msgstr "Ðе удалоÑÑŒ Ñоздать новый токен доÑтупа к проекту: %{token_response_message}"
-
msgid "Failed to create repository"
msgstr ""
@@ -15368,16 +15543,6 @@ msgstr "ID пользователей"
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Фев."
@@ -15465,12 +15630,6 @@ msgstr "Фильтр"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15700,10 +15859,10 @@ msgid "Fork"
msgstr "Ответвление"
msgid "Fork Error!"
-msgstr ""
+msgstr "Ошибка ответвлениÑ!"
msgid "Fork project"
-msgstr ""
+msgstr "Ответвить проект"
msgid "Fork project?"
msgstr ""
@@ -15715,19 +15874,19 @@ msgid "ForkProject|An error occurred while forking the project. Please try again
msgstr ""
msgid "ForkProject|Cancel"
-msgstr ""
+msgstr "Отмена"
msgid "ForkProject|Create a group"
-msgstr ""
+msgstr "Создать группу"
msgid "ForkProject|Fork project"
-msgstr ""
+msgstr "Ответвить проект"
msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
msgstr ""
msgid "ForkProject|Internal"
-msgstr ""
+msgstr "Внутренний"
msgid "ForkProject|Please select a namespace"
msgstr ""
@@ -15736,13 +15895,13 @@ msgid "ForkProject|Please select a visibility level"
msgstr ""
msgid "ForkProject|Private"
-msgstr ""
+msgstr "Приватный"
msgid "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."
msgstr ""
msgid "ForkProject|Public"
-msgstr ""
+msgstr "Публичный"
msgid "ForkProject|Select a namespace"
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Ðайдены ошибки в вашем .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Создать Ñтандартный набор меток"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Сгенерировать ключ"
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Узлы Geo"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr "ÐаÑтройки Geo"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðе удалоÑÑŒ"
@@ -16083,12 +16257,6 @@ msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð°
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронизировано"
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Ожидание Ñинхронизации"
@@ -16137,16 +16308,19 @@ msgstr "Скачать заново"
msgid "Geo|Remove"
msgstr "Удалить"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr "Убрать запиÑÑŒ"
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr "Удалить запиÑÑŒ базы данных отÑлеживаниÑ"
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr "вторичный"
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr "GitLab Ð´Ð»Ñ Slack"
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ GitLab или Ð°Ð´Ñ€ÐµÑ Ñлектронной почты"
@@ -16656,6 +16836,9 @@ msgstr "URL Gitpod"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr "Группа %{group_name} была запланирована Ð´Ð»Ñ Ñƒ
msgid "Group %{group_name} was successfully created."
msgstr "Группа %{group_name} уÑпешно Ñоздана."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr "URL группы"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr "Содержание обзора группы"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr "Минуты групповой Ñборочной линии уÑпеш
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17128,31 +17317,31 @@ msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
msgid "GroupActivityMetrics|Recent activity"
-msgstr ""
+msgstr "ÐедавнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ"
msgid "GroupImport|Failed to import group."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ импортировать группу."
msgid "GroupImport|Group '%{group_name}' is being imported."
-msgstr ""
+msgstr "Группа '%{group_name}' импортируетÑÑ."
msgid "GroupImport|Group could not be imported: %{errors}"
-msgstr ""
+msgstr "Ðе удалоÑÑŒ импортировать группу: %{errors}"
msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
-msgstr ""
+msgstr "ПожалуйÑта, подождите пока мы импортируем группу. ОбновлÑйте Ñтраницу по желанию."
msgid "GroupImport|The group was successfully imported."
-msgstr ""
+msgstr "Группа была уÑпешно импортирована."
msgid "GroupImport|Unable to process group import file"
-msgstr ""
+msgstr "Ðевозможно обработать файл импорта группы"
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "Копировать ID группы"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "ID группы: %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
msgstr "%{dateWord} – Без конечной даты"
@@ -17161,10 +17350,10 @@ msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
-msgstr ""
+msgstr "Загрузка целей"
msgid "GroupRoadmap|No start and end date"
-msgstr ""
+msgstr "Без даты начала и окончаниÑ"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "Без начальной даты – %{dateWord}"
@@ -17179,22 +17368,22 @@ msgid "GroupRoadmap|Sorry, no epics matched your search"
msgstr "К Ñожалению, по вашему запроÑу цели не найдены"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
-msgstr ""
+msgstr "План Ñ€Ð°Ð·Ð²Ð¸Ñ‚Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ прогреÑÑ Ð²Ð°ÑˆÐ¸Ñ… целей на временной шкале"
msgid "GroupRoadmap|This quarter"
-msgstr ""
+msgstr "Ð’ Ñтом квартале"
msgid "GroupRoadmap|This year"
-msgstr ""
+msgstr "Ð’ Ñтом году"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
msgstr ""
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
-msgstr ""
+msgstr "Чтобы проÑмотреть план развитиÑ, добавьте дату начала или Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ðº одной из %{linkStart}дочерних целей%{linkEnd}."
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Чтобы проÑмотреть план развитиÑ, добавьте дату начала или Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ðº одной из ваших целей в Ñтой группе или её подгруппаx; c %{startDate} по %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Чтобы раÑширить поиÑк, измените или удалите фильтры; Ñ %{startDate} до %{endDate}."
@@ -17233,10 +17422,10 @@ msgid "GroupSAML|Certificate fingerprint"
msgstr "Отпечаток Ñертификата"
msgid "GroupSAML|Configuration"
-msgstr ""
+msgstr "КонфигурациÑ"
msgid "GroupSAML|Copy SAML Response XML"
-msgstr ""
+msgstr "Скопировать ответный XML от SAML"
msgid "GroupSAML|Could not create SAML group link: %{errors}."
msgstr ""
@@ -17254,13 +17443,13 @@ msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
-msgstr ""
+msgstr "Принудить пользователей иметь выделенные групповые управлÑемые учетные запиÑи Ð´Ð»Ñ Ñтой группы"
msgid "GroupSAML|Generate a SCIM token"
msgstr "Создать токен SCIM"
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
-msgstr ""
+msgstr "Сгенерируйте токен SCIM Ð´Ð»Ñ Ð½Ð°Ñтройки ÑиÑтемы кроÑÑ-доменного ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸ÐµÐ¹."
msgid "GroupSAML|Identity"
msgstr ""
@@ -17269,22 +17458,22 @@ msgid "GroupSAML|Identity provider single sign-on URL"
msgstr ""
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "ОбÑзательно Ñохраните Ñтот токен, так как потом вы не Ñможете получить к нему доÑтуп."
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "УправлÑйте учаÑтниками Ñвоей группы, добавлÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ð¹ уровень безопаÑноÑти Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ SAML."
msgid "GroupSAML|Members"
msgstr "УчаÑтники"
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "УчаÑтники будут отправлены Ñюда при входе в вашу группу. Получите Ñтот URL, который также может называтьÑÑ Â«SSO Service Location», «SAML Token Issuance Endpoint» или «SAML 2.0/W-Federation URL» от Ñвоего провайдера идентификации."
msgid "GroupSAML|NameID"
-msgstr ""
+msgstr "NameID"
msgid "GroupSAML|NameID Format"
-msgstr ""
+msgstr "Формат NameID"
msgid "GroupSAML|New SAML group link saved."
msgstr ""
@@ -17293,7 +17482,7 @@ msgid "GroupSAML|No active SAML group links"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group"
-msgstr ""
+msgstr "Запретить внешние Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы"
msgid "GroupSAML|Reset SCIM token"
msgstr ""
@@ -17311,13 +17500,13 @@ msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
msgstr ""
msgid "GroupSAML|SAML Response Output"
-msgstr ""
+msgstr "Вывод ответа SAML"
msgid "GroupSAML|SAML Response XML"
-msgstr ""
+msgstr "Ответный XML SAML"
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "Единый вход SAML"
msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "SAML ÐаÑтройки единого входа"
@@ -17325,17 +17514,11 @@ msgstr "SAML ÐаÑтройки единого входа"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "URL конечной точки SCIM API"
-
msgid "GroupSAML|SCIM Token"
msgstr "SCIM токен"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
-
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
+msgstr "Отпечаток SHA1 Ñертификата, подпиÑывающего SAML-токен. Получите его у провайдера идентификации, у которого он так же может называтьÑÑ \"Thumbprint\"."
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17356,14 +17539,11 @@ msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
msgstr ""
msgid "GroupSAML|Valid SAML Response"
-msgstr ""
+msgstr "ДейÑтвительный ответ SAML"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Ваш токен SCIM"
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17386,15 +17566,18 @@ msgid "GroupSaml|Your SCIM token"
msgstr ""
msgid "GroupSelect|No matching results"
-msgstr ""
+msgstr "Ðет подходÑщих результатов"
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "ПоиÑк групп"
msgid "GroupSelect|Select a group"
+msgstr "Выбрать группу"
+
+msgid "GroupSettings|Allow project and group access token creation"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17413,7 +17596,7 @@ msgid "GroupSettings|Be careful. Changing a group's parent can have unintended s
msgstr ""
msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
-msgstr ""
+msgstr "Ðевозможно обновить путь, поÑкольку в Ñтой группе ÑущеÑтвуют проекты, Ñодержащие Docker-образы в рееÑтрах контейнеров. ПожалуйÑта, Ñначала удалите образы из Ñвоих проектов, а затем попробуйте ещё раз."
msgid "GroupSettings|Change group URL"
msgstr ""
@@ -17437,9 +17620,12 @@ msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within thi
msgstr "ИÑпользовать по умолчанию Ñборочные линии Auto DevOps Ð´Ð»Ñ Ð²Ñех проектов в Ñтой группе"
msgid "GroupSettings|Disable email notifications"
-msgstr ""
+msgstr "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте"
msgid "GroupSettings|Disable group mentions"
+msgstr "Отключить групповые упоминаниÑ"
+
+msgid "GroupSettings|Enable customer relations"
msgstr ""
msgid "GroupSettings|Enable delayed project deletion"
@@ -17460,9 +17646,6 @@ msgstr "Ðовый региÑтрационный токен обработчиÐ
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr "ПереопределÑет пользовательÑкие наÑтройки уведомлений Ð´Ð»Ñ Ð²Ñех учаÑтников Ñтой группы, подгрупп и проектов."
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "ÐаÑтройки Ñборочной Ð»Ð¸Ð½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ обновлены Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹"
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17518,7 +17698,7 @@ msgid "GroupSettings|The projects in this subgroup can be selected as templates
msgstr ""
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
-msgstr ""
+msgstr "При обновлении Ñборочной линии Auto DevOps возникла проблема: %{error_messages}."
msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
msgstr "Возникла проблема Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек Ñборочной линии: %{error_messages}."
@@ -17535,8 +17715,8 @@ msgstr "Эта наÑтройка применена в %{ancestor_group}. Ð’Ñ‹
msgid "GroupSettings|Transfer group"
msgstr "ПеренеÑти группу"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
-msgstr "Пользователи могут Ñоздавать %{link_start}токены доÑтупа%{link_end} к проектам в Ñтой группе."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
+msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
@@ -17560,7 +17740,7 @@ msgid "GroupSettings|cannot be disabled when the parent group \"Share with group
msgstr "не может быть отменена до тех пор пока группа \"ПоделитьÑÑ Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð¾Ð¹ блокировкой\" включена, за иÑключением владельца группы родителÑ"
msgid "GroupSettings|cannot change when group contains projects with NPM packages"
-msgstr ""
+msgstr "невозможно изменить, когда группа Ñодержит проекты Ñ NPM-пакетами"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
msgstr "удалить возможноÑÑ‚ÑŒ поделитьÑÑ Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð¾Ð¹ блокировкой из %{ancestor_group_name}"
@@ -17572,10 +17752,10 @@ msgid "Groups (%{count})"
msgstr "Группы (%{count})"
msgid "Groups and projects"
-msgstr ""
+msgstr "Группы и проекты"
msgid "Groups and subgroups"
-msgstr ""
+msgstr "Группы и подгруппы"
msgid "Groups to synchronize"
msgstr "Группы Ð´Ð»Ñ Ñинхронизации"
@@ -17587,16 +17767,16 @@ msgid "GroupsDropdown|Groups you visit often will appear here"
msgstr "Группы, которые вы чаÑто поÑещаете, поÑвÑÑ‚ÑÑ Ð·Ð´ÐµÑÑŒ"
msgid "GroupsDropdown|Loading groups"
-msgstr ""
+msgstr "Загрузка групп"
msgid "GroupsDropdown|Search your groups"
msgstr "ПоиÑк в ваших группах"
msgid "GroupsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "Что-то пошло не так на нашей Ñтороне."
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr ""
+msgstr "К Ñожалению, по вашему запроÑу групп не найдено"
msgid "GroupsDropdown|This feature requires browser localStorage support"
msgstr "Эта функциональноÑÑ‚ÑŒ требует поддержки localStorage в вашем браузере"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17710,10 +17887,10 @@ msgid "GroupsTree|Search by name"
msgstr "ПоиÑк по имени"
msgid "Guideline"
-msgstr ""
+msgstr "РуководÑтво"
msgid "HAR (HTTP Archive)"
-msgstr ""
+msgstr "HAR (HTTP Ðрхив)"
msgid "HAR file path or URL"
msgstr ""
@@ -17906,11 +18083,38 @@ msgstr[3] "Скрыть значениÑ"
msgid "Hide values"
msgstr "Скрыть значениÑ"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr "ПриÑутÑтвуют уÑзвимоÑти выÑокого или неизвеÑтного уровнÑ"
msgid "Highest role:"
-msgstr "ÐÐ°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ€Ð¾Ð»ÑŒ:"
+msgstr "ÐаивыÑÑˆÐ°Ñ Ñ€Ð¾Ð»ÑŒ:"
msgid "HighlightBar|Alert events:"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr "ОчиÑтка"
msgid "Housekeeping successfully started"
msgstr "ОчиÑтка уÑпешно запущена"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "ОчиÑтка, ÑкÑпорт, путь, перемещение, удаление, архивирование."
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "Как Ñто работает"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr "Я забыл пароль"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18183,7 +18393,7 @@ msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be
msgstr ""
msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
-msgstr ""
+msgstr "ЕÑли вы не делали попыток войти, пожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором или включите двухфакторную аутентификацию (2FA) Ð´Ð»Ñ Ñвоей учётной запиÑи."
msgid "If you did not initiate this change, please contact your administrator immediately."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr "Инцидент"
msgid "Incident Management Limits"
msgstr "Лимиты, ÑвÑзанные Ñ Ð£Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ инцидентами"
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19477,7 +19690,7 @@ msgid "Integrations|Reset integration?"
msgstr ""
msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
-msgstr ""
+msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ð¸ очиÑтит наÑтройки и деактивирует Ñту интеграцию."
msgid "Integrations|Return to GitLab for Jira"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,14 +19788,14 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "Внутренний URL (необÑзательно)"
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
msgstr "Внутренние пользователи"
msgid "Internal users cannot be deactivated"
-msgstr ""
+msgstr "Внутренние пользователи не могут быть деактивированы"
msgid "Interval Pattern"
msgstr "Шаблон интервала"
@@ -19951,7 +20170,7 @@ msgid "Is blocked by"
msgstr ""
msgid "Is using license seat:"
-msgstr ""
+msgstr "ИÑпользует лицензионное меÑто:"
msgid "Is using seat"
msgstr "ИÑпользует меÑто"
@@ -21098,13 +21317,13 @@ msgid "Last seen"
msgstr "ПоÑледнее поÑещение"
msgid "Last sign-in"
-msgstr ""
+msgstr "ПоÑледний вход"
msgid "Last sign-in IP:"
-msgstr ""
+msgstr "IP поÑледнего входа:"
msgid "Last sign-in at:"
-msgstr ""
+msgstr "ПоÑледний вход:"
msgid "Last successful sync"
msgstr ""
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr "Загрузка..."
msgid "Loading…"
msgstr "Загрузка…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "ЛокализациÑ"
@@ -21746,6 +21965,9 @@ msgstr "Блокировка"
msgid "Lock %{issuableDisplayName}"
msgstr "Заблокировать %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr "Блокировка членÑтва в Ñинхронизации LDAP"
@@ -21753,7 +21975,7 @@ msgid "Lock not found"
msgstr "Блокировка не найдена"
msgid "Lock the discussion"
-msgstr ""
+msgstr "Заблокировать диÑкуÑÑию"
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
@@ -21771,7 +21993,7 @@ msgid "Locked by %{fileLockUserName}"
msgstr "Заблокировано %{fileLockUserName}"
msgid "Locked the discussion."
-msgstr ""
+msgstr "ДиÑкуÑÑÐ¸Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð°."
msgid "Locked to current projects"
msgstr ""
@@ -21780,6 +22002,39 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr ""
msgid "Locks the discussion."
+msgstr "Блокирует диÑкуÑÑию."
+
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
msgstr ""
msgid "Login with smartcard"
@@ -22323,13 +22578,13 @@ msgid "Medium vulnerabilities present"
msgstr ""
msgid "Member since"
-msgstr ""
+msgstr "УчаÑтник Ñ"
msgid "Member since %{date}"
msgstr "УчаÑтник Ñ %{date}"
msgid "Member since:"
-msgstr ""
+msgstr "УчаÑтник Ñ:"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr "ЗавиÑимоÑти запроÑа на ÑлиÑние"
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "Объединить при уÑпешном выполнении Ñборочной линии"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "Коммит в ветку иÑточника"
@@ -23401,9 +23671,6 @@ msgstr "МеÑÑцы"
msgid "More Information"
msgstr "Больше информации"
-msgid "More Slack commands"
-msgstr "Больше Slack команд"
-
msgid "More actions"
msgstr "Больше дейÑтвий"
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "Более %{number_commits_distance} коммитов отличаетÑÑ Ð¾Ñ‚ %{default_branch}"
@@ -23570,13 +23834,13 @@ msgid "Namespace"
msgstr ""
msgid "Namespace ID:"
-msgstr ""
+msgstr "ID проÑтранÑтва имён:"
msgid "Namespace is empty"
msgstr "ПроÑтранÑтво имён пуÑто"
msgid "Namespace:"
-msgstr ""
+msgstr "ПроÑтранÑтво:"
msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23971,7 +24226,7 @@ msgid "New directory"
msgstr "Ðовый каталог"
msgid "New discussion"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð´Ð¸ÑкуÑÑиÑ"
msgid "New environment"
msgstr "Ðовое окружение"
@@ -24112,7 +24367,7 @@ msgid "Next scan"
msgstr ""
msgid "Next unresolved discussion"
-msgstr "Следующее нерешённое обÑуждение"
+msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð½ÐµÐ·Ð°Ð²ÐµÑ€ÑˆÑ‘Ð½Ð½Ð°Ñ Ð´Ð¸ÑкуÑÑиÑ"
msgid "Nickname"
msgstr "Ðикнейм"
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr "Ðет Ñтапов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Ðет других меток Ñ Ñ‚Ð°ÐºÐ¸Ð¼ наименованием или опиÑанием"
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,8 +24690,8 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
-msgstr "Веб-обработчики не найдены, добавьте один в форме выше."
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -25350,8 +25611,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr "Ðе определена политиками проекта и должна быть удалена"
-msgid "Outbound requests"
-msgstr "ИÑходÑщие запроÑÑ‹"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr "Ð’Ñтавьте публичный SSH-ключ, который обычно ÑодержитÑÑ Ð² файле '~/.ssh/id_ed25519.pub' или '~/.ssh/id_rsa.pub' и начинаетÑÑ Ñ 'ssh-ed25519' или 'ssh-rsa'. Ðе вÑтавлÑйте закрытый SSH-ключ, так как Ñто может поÑтавить под угрозу ваши личные данные."
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,8 +26410,8 @@ msgstr "Права доÑтупа"
msgid "Permissions Help"
msgstr "Справка по разрешениÑм"
-msgid "Permissions, LFS, 2FA"
-msgstr "РазрешениÑ, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "ПерÑональный Токен ДоÑтупа"
@@ -26144,10 +26426,10 @@ msgid "Personal project creation is not allowed. Please contact your administrat
msgstr "Создание личного проекта запрещено. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором по данному вопроÑу"
msgid "Personal projects"
-msgstr ""
+msgstr "Личные проекты"
msgid "Personal projects limit:"
-msgstr ""
+msgstr "Лимит личных проектов:"
msgid "Phabricator Server Import"
msgstr ""
@@ -26395,9 +26677,6 @@ msgstr "Сборочные линии"
msgid "Pipelines charts"
msgstr "Диаграммы Ñборочных линий"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "ÐаÑтройки Ñборочных линий Ð´Ð»Ñ '%{project_name}' были уÑпешно обновлены."
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "ВыполнÑйте Ñборки Ñ ÑƒÐ²ÐµÑ€ÐµÐ½Ð½Ð¾Ñтью"
@@ -26422,8 +26704,8 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
-msgstr "ДочернÑÑ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
msgid "Pipelines|Clear runner caches"
msgstr ""
@@ -26587,11 +26869,29 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
-msgstr "родительÑкаÑ"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr ""
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr "План:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26788,6 +27091,12 @@ msgstr "ЗапуÑтить вÑе вручную"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "ПожалуйÑта, %{link_to_register} или %{link_to_sign_in} чтобы прокомментировать"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "ПожалуйÑта, %{startTagRegister}зарегиÑтрируйтеÑÑŒ%{endRegisterTag} или %{startTagSignIn}войдите%{endSignInTag}, чтобы ответить"
@@ -27142,6 +27451,9 @@ msgstr "ÐаÑтройки времени"
msgid "Preferences|Use relative times"
msgstr "ИÑпользовать отноÑительное времÑ"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Пред."
@@ -27194,7 +27506,7 @@ msgid "Previous file in diff"
msgstr "Предыдущий файл в отличиÑÑ… (diff)"
msgid "Previous unresolved discussion"
-msgstr ""
+msgstr "ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ð½ÐµÐ·Ð°Ð²ÐµÑ€ÑˆÑ‘Ð½Ð½Ð°Ñ Ð´Ð¸ÑкуÑÑиÑ"
msgid "Primary"
msgstr "ОÑновной"
@@ -27317,7 +27629,7 @@ msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
-msgstr ""
+msgstr "Страница профилÑ:"
msgid "Profile parameter missing"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr "Обрезать аватар"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Ðватар будет удален. Ð’Ñ‹ уверены?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "О Ñебе"
@@ -27391,9 +27706,6 @@ msgstr "Город, Ñтрана"
msgid "Profiles|Clear status"
msgstr "ОчиÑтить ÑтатуÑ"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Ðажмите на значок, чтобы активировать вход Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ одной из Ñледующих Ñлужб"
-
msgid "Profiles|Commit email"
msgstr "Email коммита"
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Удалить аватар"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введите значение %{confirmationValue} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Обычно начинаетÑÑ Ñ \"ssh-ed25519 …\" или \"ssh-rsa …\""
-
msgid "Profiles|Update profile settings"
msgstr "Обновить наÑтройки профилÑ"
@@ -28115,7 +28427,7 @@ msgid "ProjectSettings|Additional settings that influence how and when merges ar
msgstr "Дополнительные параметры, влиÑющие на то, как и когда проиÑходит ÑлиÑние,"
msgid "ProjectSettings|All discussions must be resolved"
-msgstr "Ð’Ñе обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ быть разрешены"
+msgstr "Ð’Ñе диÑкуÑÑии должны быть завершены"
msgid "ProjectSettings|Allow"
msgstr "Разрешать"
@@ -28141,11 +28453,14 @@ msgstr "Флажок отображаетÑÑ Ð¸ выбран по умолчаÐ
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr "Флажок отображаетÑÑ Ð¸ ÑнÑÑ‚ по умолчанию."
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "Выберите ваш метод, наÑтройки, проверки и Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑлиÑниÑ."
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
-msgstr "Выберите метод ÑлиÑниÑ, параметры ÑлиÑниÑ, проверки ÑлиÑниÑ, Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑлиÑнию и наÑтройте шаблон опиÑÐ°Ð½Ð¸Ñ Ð¿Ð¾ умолчанию Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñов на ÑлиÑние."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "ÐаÑтройка реÑурÑов проекта и мониторинг их здоровьÑ."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr "ПодÑветить иÑпользование Ñкрытых Ñимволов unicode. Они приÑутÑтвуют в Ñзыках Ñ Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ пиÑьма Ñправа налево, но также могут иÑпользоватьÑÑ Ð² потенциальных ÑкÑплойтах."
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "ВнутреннÑÑ"
@@ -28267,6 +28588,9 @@ msgstr "ЗапроÑÑ‹ на ÑлиÑние"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑлиÑнию"
@@ -28393,9 +28717,6 @@ msgstr "Эта наÑтройка применÑетÑÑ Ð½Ð° уровне ÑеÑ
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Эта наÑтройка будет применена Ð´Ð»Ñ Ð²Ñех проектов, еÑли иное поведение не переопределено админиÑтратором."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr "ПеренеÑти проект"
@@ -28417,8 +28738,8 @@ msgstr "Пользователи могут запрашивать доÑтуп"
msgid "ProjectSettings|View and edit files in this project."
msgstr "ПроÑмотр и редактирование файлов в Ñтом проекте."
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
-msgstr "ПроÑмотр и редактирование файлов в Ñтом проекте. Ðе-учаÑтники не Ñмогут вноÑить изменениÑ.."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
+msgstr ""
msgid "ProjectSettings|View project analytics."
msgstr ""
@@ -28435,7 +28756,7 @@ msgstr "Предупреждать о потенциально нежелатеÐ
msgid "ProjectSettings|What are badges?"
msgstr "Что такое значки?"
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28643,7 +28964,7 @@ msgid "ProjectsNew|Create from template"
msgstr "Создать из шаблона"
msgid "ProjectsNew|Create new project"
-msgstr ""
+msgstr "Создать новый проект"
msgid "ProjectsNew|Description format"
msgstr "Ðапишите неÑколько Ñлов про проект"
@@ -28775,7 +29096,7 @@ msgid "PrometheusService|These metrics will only be monitored after your first d
msgstr "Эти показатели будут отÑлеживатьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ поÑле вашего первого Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² окружении"
msgid "PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Prometheus, уÑтановленного на клаÑтере, отключите ручную наÑтройку."
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
msgstr "Ожидание вашего первого Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² Ñреде Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка общих показателей"
@@ -28985,7 +29306,7 @@ msgid "Protected Branch"
msgstr ""
msgid "Protected Branches"
-msgstr ""
+msgstr "Защищённые ветки"
msgid "Protected Environment"
msgstr ""
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "Публичные ключи Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "Открытые Ñборочные линии"
@@ -29233,7 +29551,7 @@ msgstr "ПриобреÑти больше минут"
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "Уменьшить облаÑÑ‚ÑŒ видимоÑти проекта"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "Уменьшить облаÑÑ‚ÑŒ видимоÑти Ñтого проекта?"
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Хранилище репозиториÑ"
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Требование %{reference} было добавлено"
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr "Ответ"
@@ -30696,7 +31030,7 @@ msgstr "Продолжить"
msgid "Resync"
msgstr "РеÑинхронизировать"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr "Отозвать"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr "Ð’ÐµÑ€Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ SSL:"
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr "ПоиÑк"
msgid "Search GitLab"
msgstr "ПоиÑк в GitLab"
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31652,19 +31998,19 @@ msgid "Searching by both author and message is currently not supported."
msgstr ""
msgid "Seats"
-msgstr ""
+msgstr "МеÑта"
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
-msgstr ""
+msgstr "Данные об иÑпользовании меÑÑ‚ на %{last_enqueue_time} (обновлÑетÑÑ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾)"
msgid "Seats usage data is updated every day at 12:00pm UTC"
-msgstr ""
+msgstr "Данные об иÑпользовании меÑÑ‚ обновлÑÑŽÑ‚ÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ð¹ день в 12:00 UTC"
msgid "Secondary"
msgstr ""
msgid "Secondary email:"
-msgstr ""
+msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°:"
msgid "Seconds"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr "Выбрать формат архива"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32546,16 +32970,16 @@ msgid "Self-monitoring project was not deleted. Please check logs for any error
msgstr ""
msgid "SelfMonitoring|Activate or deactivate instance self monitoring."
-msgstr ""
+msgstr "Включение и отключение автомониторинга ÑкземплÑра."
msgid "SelfMonitoring|Activate self monitoring to create a project to use to monitor the health of your instance."
msgstr ""
msgid "SelfMonitoring|Deactivate self monitoring?"
-msgstr ""
+msgstr "Отключить автомониторинг?"
msgid "SelfMonitoring|Deactivating self monitoring deletes the self monitoring project. Are you sure you want to deactivate self monitoring and delete the project?"
-msgstr ""
+msgstr "Отключение автомониторинга удалÑет проект автомониторинга. Ð’Ñ‹ уверены, что хотите отключить автомониторинг и удалить проект?"
msgid "SelfMonitoring|Self monitoring"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr "Служба поддержки"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr "ÐаÑтройка CI/CD"
msgid "Set up Jira Integration"
msgstr "ÐаÑтроить интеграцию Ñ Jira"
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¼Ð¸Ð½ÑƒÑ‚ Ñборочной линии"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¸Ñпользованных минут Ñборочной линии"
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr "Показывать архивные проекты"
msgid "Show archived projects only"
msgstr "Показывать только архивные проекты"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Показать команду"
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr "Показать только комментарии"
-msgid "Show commit description"
-msgstr "Показать опиÑание коммита"
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr "Показаны вÑе обÑуждениÑ"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr "Войдите"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾ÑˆÐ»Ð° уÑпешно! ПожалуйÑта, подтвердите Ñлектронную почту, чтобы войти."
@@ -33320,7 +33747,7 @@ msgid "Sign-in and Help page"
msgstr ""
msgid "Sign-in count:"
-msgstr ""
+msgstr "КоличеÑтво входов:"
msgid "Sign-in page"
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33662,7 +34113,7 @@ msgid "Something went wrong while reopening the merge request. Please try again
msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
-msgstr ""
+msgstr "Что-то пошло не так при завершении Ñтой диÑкуÑÑии. ПожалуйÑта, повторите попытку."
msgid "Something went wrong while setting %{issuableType} %{dateType} date."
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr "Произошла ошибка. Попробуйте позже."
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Извините, нет целей, ÑоответÑтвующих вашему поиÑку"
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr "По поÑледнему контакту"
msgid "SortOptions|Last created"
msgstr "Сначала недавно Ñозданные"
-msgid "SortOptions|Last updated"
-msgstr "Сначала недавно обновлённые"
-
msgid "SortOptions|Least popular"
msgstr "Ðаименее популÑрный"
@@ -34100,7 +34545,7 @@ msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion…"
-msgstr ""
+msgstr "Ðачать новую диÑкуÑÑию…"
msgid "Start a new merge request"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Ðачать поиÑк"
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,9 +34994,30 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
-msgid "SubscriptionTable|Add seats"
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
msgstr ""
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
+msgid "SubscriptionTable|Add seats"
+msgstr "Добавить меÑта"
+
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -34571,7 +35046,7 @@ msgid "SubscriptionTable|Next invoice"
msgstr "Следующий Ñчет"
msgid "SubscriptionTable|Refresh Seats"
-msgstr ""
+msgstr "Обновить МеÑта"
msgid "SubscriptionTable|Renew"
msgstr ""
@@ -34583,13 +35058,13 @@ msgid "SubscriptionTable|Seats in subscription"
msgstr "КоличеÑтво меÑÑ‚ в подпиÑке"
msgid "SubscriptionTable|Seats owed"
-msgstr ""
+msgstr "Задолженные меÑта"
msgid "SubscriptionTable|See usage"
msgstr ""
msgid "SubscriptionTable|Something went wrong trying to refresh seats"
-msgstr ""
+msgstr "Что-то пошло не так при попытке обновить меÑта"
msgid "SubscriptionTable|Subscription end date"
msgstr "Дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñки"
@@ -34618,9 +35093,6 @@ msgstr "Дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð½Ð¾Ð³Ð¾ периода"
msgid "SubscriptionTable|Trial start date"
msgstr "Дата начала пробного периода"
-msgid "SubscriptionTable|Upgrade"
-msgstr "ПовыÑить"
-
msgid "SubscriptionTable|Usage"
msgstr "ИÑпользование"
@@ -34646,10 +35118,10 @@ msgid "Successful purchase image"
msgstr ""
msgid "Successfully activated"
-msgstr ""
+msgstr "УÑпешно активировано"
msgid "Successfully approved"
-msgstr ""
+msgstr "УÑпешно одобрено"
msgid "Successfully banned"
msgstr "УÑпешно забанен"
@@ -34661,7 +35133,7 @@ msgid "Successfully confirmed"
msgstr "УÑпешно подтверждено"
msgid "Successfully deactivated"
-msgstr ""
+msgstr "УÑпешно деактивирован"
msgid "Successfully deleted U2F device."
msgstr "УÑтройÑтво U2F уÑпешно удалено."
@@ -34789,11 +35261,8 @@ msgstr ""
msgid "Sunday"
msgstr "ВоÑкреÑенье"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
-msgstr ""
+msgstr "Ðктивировать подпиÑку"
msgid "SuperSonics|Activation code"
msgstr ""
@@ -34814,6 +35283,9 @@ msgid "SuperSonics|Cloud licensing"
msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
+msgstr "ДоÑтупно облачное лицензирование. Это более проÑтой ÑпоÑоб активировать ÑкземплÑры и управлÑÑ‚ÑŒ подпиÑками. Подробнее об Ñтом читайте в %{blogPostLinkStart}нашем блоге%{blogPostLinkEnd}. Коды активации доÑтупны на %{portalLinkStart}клиентÑком портале%{portalLinkEnd}."
+
+msgid "SuperSonics|Enter activation code"
msgstr ""
msgid "SuperSonics|Export license usage file"
@@ -34829,7 +35301,7 @@ msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the
msgstr ""
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
+msgstr "Узнайте, как %{linkStart}активировать подпиÑку%{linkEnd}."
msgid "SuperSonics|Licensed to"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34877,7 +35352,7 @@ msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users
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 ""
+msgstr "Чтобы активировать подпиÑку, подключитеÑÑŒ к Ñерверам GitLab через %{linkStart}Облачное Лицензирование%{linkEnd}, безоблачный ÑпоÑоб ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñкой."
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -34889,7 +35364,7 @@ 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 ""
+msgstr "Пользователи Ñ Ñ€Ð¾Ð»ÑŒÑŽ Guest или те, кто не входит в проект или группу, не займут меÑта в вашей лицензии."
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34919,6 +35397,15 @@ msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
+msgstr "Ваша подпиÑка уÑпешно активирована. Можете ознакомитьÑÑ Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾ÑÑ‚Ñми ниже."
+
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
msgstr ""
msgid "Support"
@@ -35164,9 +35651,12 @@ msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
msgid "Target-Branch"
msgstr ""
-msgid "Task ID: %{elastic_task}"
+msgid "Task"
msgstr ""
+msgid "Task ID: %{elastic_task}"
+msgstr "ID задачи: %{elastic_task}"
+
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr "СоглаÑие Ñ Ð£ÑловиÑми иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ ПÐ
msgid "Terms of Service and Privacy Policy"
msgstr "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Политика конфиденциальноÑти"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr "ТеÑÑ‚"
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Обработка Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Группа \"%{group_path}\" позволÑет вам войти в ÑиÑтему Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ учетной запиÑи единого входа"
-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 ""
@@ -35633,12 +36126,6 @@ msgstr "Сервер Prometheus ответил Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¾Ð¼ \"bad r
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Сертификат X509, иÑпользуемый в том Ñлучае, когда Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ Ñлужбой авторизации требуетÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° подлинноÑти TLS. ЕÑли оÑтавить пуÑтым, Ñертификат Ñервера вÑе еще будет проверÑÑ‚ÑŒÑÑ Ð¿Ñ€Ð¸ доÑтупе через HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Соединение будет отключено через %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ², требующих больше времени, иÑпользуйте комбинацию clone/push."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "Пароль, необходимый Ð´Ð»Ñ Ñ€Ð°Ñшифровки закрытого ключа. Он не ÑвлÑетÑÑ Ð½ÐµÐ¾Ð±Ñзательным, а значение будет зашифровано в ÑоÑтоÑнии покоÑ."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "Закрытый ключ, иÑпользуемый при предоÑтавлении клиентÑкого Ñертификата. Он будет зашифрован в ÑоÑтоÑнии покоÑ."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36055,7 +36536,7 @@ msgid "The user you are trying to approve is not pending approval"
msgstr ""
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
-msgstr ""
+msgstr "Пользователь, которого вы пытаетеÑÑŒ деактивировать, проÑвлÑл активноÑÑ‚ÑŒ за поÑледние %{minimum_inactive_days} дней и не может быть деактивирован"
msgid "The username for the Jenkins server."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,8 +36850,8 @@ msgstr "Произошла ошибка при ÑброÑе минут польÐ
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
-msgstr "Ошибка при Ñохранении Ñтого узла Geo."
+msgid "There was an error saving this Geo Site"
+msgstr ""
msgid "There was an error saving your changes."
msgstr "Произошла ошибка при Ñохранении ваших изменений."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr "Эта цель уже имеет макÑимально возможнÐ
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Этой цели не ÑущеÑтвует, или у Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно прав."
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr "Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚, чтобы локальное хранилище было включено"
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr "Этот проект"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36949,7 +37442,7 @@ msgid "This suggestion already matches its content."
msgstr ""
msgid "This user cannot be unlocked manually from GitLab"
-msgstr ""
+msgstr "Этот пользователь не может быть разблокирован вручную из GitLab"
msgid "This user has an unconfirmed email address (%{email}). You may force a confirmation."
msgstr ""
@@ -36964,7 +37457,7 @@ msgid "This user has no identities"
msgstr ""
msgid "This user has no personal projects."
-msgstr ""
+msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½ÐµÑ‚ личных проектов."
msgid "This user has previously committed to the %{name} project."
msgstr "Этот пользователь ранее отправлÑл коммиты в проект %{name}."
@@ -37170,9 +37663,6 @@ msgstr "Ð’Ñ€ÐµÐ¼Ñ Ñ Ð¿Ð¾Ñледнего коммита до ÑлиÑниÑ"
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Чтобы добавить ключ SSH, вам нужно %{generate_link_start}Ñгенерировать его%{link_end} или иÑпользовать %{existing_link_start}ÑущеÑтвующий ключ%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Чтобы добавить запиÑÑŒ вручную, предоÑтавьте Ñледующую информацию в приложении на Ñвоем телефоне."
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr "Чтобы иÑпользовать Gitpod, Ñначала нужно включить Ñту функцию в разделе интеграций ваших %{user_prefs}."
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr "СпиÑок задач"
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "ОтÑлеживайте Ð²Ñ€ÐµÐ¼Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ быÑтрых дейÑтвий"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37954,7 +38429,7 @@ msgid "Trial|We will activate your trial on your group after you complete this s
msgstr ""
msgid "Trial|Your GitLab Ultimate trial lasts for 30 days, but you can keep your free GitLab account forever. We just need some additional information to activate your trial."
-msgstr ""
+msgstr "Пробный период GitLab Ultimate ÑоÑтавлÑет 30 дней, а беÑплатными возможноÑÑ‚Ñми GitLab вы можете пользоватьÑÑ Ñколько угодно. Ðам проÑто нужна Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, чтобы активировать ваш пробный период."
msgid "Trigger"
msgstr "СобытиÑ"
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "УÑтранÑйте неполадки и Ñледите за ÑоÑтоÑнием Ñвоего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ помощи траÑÑировки"
@@ -38074,25 +38555,25 @@ msgid "Two-factor Authentication Recovery codes"
msgstr "Коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ð¹ аутентификации"
msgid "Two-factor Authentication:"
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ ÐутентификациÑ:"
msgid "Two-factor authentication"
msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "Two-factor authentication disabled"
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°"
msgid "Two-factor authentication has been disabled for this user"
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° Ð´Ð»Ñ Ñтого пользователÑ"
msgid "Two-factor authentication has been disabled for your GitLab account."
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учётной запиÑи GitLab."
msgid "Two-factor authentication has been disabled successfully!"
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑƒÑпешно отключена!"
msgid "Two-factor authentication is not enabled for this user"
-msgstr ""
+msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð½Ðµ включена Ð´Ð»Ñ Ñтого пользователÑ"
msgid "Two-factor grace period"
msgstr ""
@@ -38101,7 +38582,7 @@ msgid "Type"
msgstr "Тип"
msgid "Type/State"
-msgstr ""
+msgstr "Тип/СоÑтоÑние"
msgid "U2F Devices (%{length})"
msgstr "УÑтройÑтва U2F (%{length})"
@@ -38353,7 +38834,7 @@ msgid "Unlock account"
msgstr ""
msgid "Unlock the discussion"
-msgstr "Разблокировать обÑуждение"
+msgstr "Разблокировать диÑкуÑÑию"
msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
@@ -38362,10 +38843,10 @@ msgid "Unlocked"
msgstr "Разблокировано"
msgid "Unlocked the discussion."
-msgstr ""
+msgstr "ДиÑкуÑÑÐ¸Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð°."
msgid "Unlocks the discussion."
-msgstr ""
+msgstr "Разблокирует диÑкуÑÑию."
msgid "Unmarked this %{noun} as a draft."
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr "Обновлено"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Обновлено %{updated_at} %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38680,7 +39167,7 @@ msgid "UsageQuota|Repository"
msgstr "Репозиторий"
msgid "UsageQuota|Seats"
-msgstr ""
+msgstr "МеÑта"
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -38851,7 +39338,7 @@ msgid "UsageTrends|Total groups"
msgstr ""
msgid "UsageTrends|Total projects"
-msgstr ""
+msgstr "Ð’Ñего проектов"
msgid "UsageTrends|Total projects & groups"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39262,10 +39752,10 @@ msgid "Username or email"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ email"
msgid "Username:"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"
msgid "Username: %{username}"
-msgstr ""
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: %{username}"
msgid "Users"
msgstr "Пользователи"
@@ -39298,7 +39788,7 @@ msgid "Users were successfully added."
msgstr "Пользователи были уÑпешно добавлены."
msgid "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 ""
+msgstr "Пользователи Ñ Ñ€Ð¾Ð»ÑŒÑŽ Guest или те, кто не входит в проект или группу, не займут меÑта в вашей лицензии."
msgid "UsersSelect|%{name} + %{length} more"
msgstr "еще %{name} + %{length}"
@@ -39349,7 +39839,7 @@ msgid "Validated:"
msgstr ""
msgid "Validations failed."
-msgstr ""
+msgstr "Проверка не удалаÑÑŒ."
msgid "Value"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr "ВерÑÐ¸Ñ %{versionNumber} (поÑледнÑÑ)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39606,7 +40108,7 @@ msgid "View it on GitLab"
msgstr ""
msgid "View job"
-msgstr ""
+msgstr "ПроÑмотр заданиÑ"
msgid "View job log"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr "ПроÑмотр заменённого файла @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39712,7 +40217,7 @@ msgid "Visibility:"
msgstr "ДоÑтуп:"
msgid "VisibilityLevel|Internal"
-msgstr "Ограниченный"
+msgstr "Внутренний"
msgid "VisibilityLevel|Private"
msgstr "Приватный"
@@ -39721,7 +40226,7 @@ msgid "VisibilityLevel|Public"
msgstr "Публичный"
msgid "VisibilityLevel|Unknown"
-msgstr "Ðе определен"
+msgstr "ÐеизвеÑтный"
msgid "Visit settings page"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr "Образ"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr "ПроÑтранÑтво имён"
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr "Веб-обработчики"
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
-msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ñборочной линии"
-
-msgid "Webhooks|Push events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Pipeline events"
+msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ñборочной линии"
+
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40339,7 +40874,7 @@ msgid "Weight %{weight}"
msgstr "Приоритет %{weight}"
msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
-msgstr "Добро пожаловать! Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была деактивирована из-за неактивноÑти, но ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ð¾ÑÑтановлена."
+msgstr "С возвращением! Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была деактивирована из-за неактивноÑти, но теперь воÑÑтановлена."
msgid "Welcome to GitLab"
msgstr ""
@@ -40405,7 +40940,7 @@ msgid "When a deployment job is successful, skip older deployment jobs that are
msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
-msgstr "Когда Runner закреплён, он не может быть назначен другим проектам"
+msgstr "Когда runner закреплён, он не может быть назначен другим проектам"
msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
msgstr ""
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40793,7 +41334,7 @@ msgid "You already have pending todo for this alert"
msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
-msgstr ""
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ добавить учаÑтников %{usersTag} в диÑкуÑÑию. Каждый из них получит уведомление."
msgid "You are about to permanently delete this project"
msgstr ""
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr "Вы также можете проверить ваш %{gitlab_ci_yml}
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Ð’Ñ‹ также можете загрузить ÑущеÑтвующие файлы Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð°, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ‘Ð½Ð½Ñ‹Ðµ ниже инÑтрукции."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr "Ð’Ñ‹ можете легко поучаÑтвовать в них, поÐ
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41078,7 +41631,7 @@ msgid "You do not have any Google Cloud projects. Please create a Google Cloud p
msgstr ""
msgid "You do not have any subscriptions yet"
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð¿Ð¾ÐºÐ° нет подпиÑок"
msgid "You do not have permission to access dora metrics."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr "Ð’Ñ‹ доÑтигли Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð² вашем проектÐ
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr "Теперь вы можете закрыть Ñтап."
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41433,10 +41995,10 @@ msgid "Your GPG keys (%{count})"
msgstr "Ваши ключи GPG (%{count})"
msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now."
-msgstr ""
+msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ GitLab заблокирована из-за Ñлишком большого количеÑтва неудачных попыток входа. Ð’Ñ‹ можете подождать, пока ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ автоматичеÑки разблокируетÑÑ Ñ‡ÐµÑ€ÐµÐ· %{duration} или вы можете щелкнуть ÑÑылку ниже, чтобы разблокировать ÑейчаÑ."
msgid "Your GitLab account request has been approved!"
-msgstr ""
+msgstr "Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° Ñоздание учетной запиÑи GitLab одобрен!"
msgid "Your GitLab group"
msgstr ""
@@ -41484,13 +42046,13 @@ msgid "Your access request to the %{source_type} has been withdrawn."
msgstr "Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа к %{source_type} был отозван."
msgid "Your account has been deactivated"
-msgstr ""
+msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ деактивирована"
msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
msgstr "Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была деактивирована админиÑтратором. ПожалуйÑта Ñнова войдите в ÑиÑтему Ð´Ð»Ñ Ñ€ÐµÐ°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸ вашей учётной запиÑи."
msgid "Your account has been deactivated. You will not be able to: "
-msgstr ""
+msgstr "Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ деактивирована. Ð’Ñ‹ не Ñможете: "
msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
msgstr ""
@@ -41618,8 +42180,8 @@ msgstr "Ваше имÑ"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
-msgstr "Ваш новый токен SCIM"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr ""
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr "Ваш новый перÑональный токен доÑтупа был Ñоздан."
-msgid "Your new project access token has been created."
-msgstr "Токен доÑтупа к проекту Ñоздан."
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "Ваш пароль не требуетÑÑ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра Ñтой Ñтраницы. ЕÑли запрашиваетÑÑ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ или Ð»ÑŽÐ±Ð°Ñ Ð´Ñ€ÑƒÐ³Ð°Ñ Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, обратитеÑÑŒ к админиÑтратору, чтобы Ñообщить о нарушении."
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr "утверждающий Ð´Ð»Ñ Ñтого запроÑа на ÑлиÑÐ
msgid "any-approver for the project already exists"
msgstr "утверждающий Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° уже ÑущеÑтвует"
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr "невозможно изменить, еÑли в личном прое
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42140,7 +42712,7 @@ msgid "ciReport|Load performance test metrics: No changes"
msgstr ""
msgid "ciReport|Loading %{reportName} report"
-msgstr ""
+msgstr "ЗагружаетÑÑ Ð¾Ñ‚Ñ‡Ñ‘Ñ‚ %{reportName}"
msgid "ciReport|Loading Code Quality report"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr "не удалоÑÑŒ"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr "группа"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "учаÑтники группы"
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr "невозможно. Ðа данный момент мы не поддерживаем итерации ÑƒÑ€Ð¾Ð²Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr "ручной"
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42856,10 +43431,10 @@ msgstr "закрыто"
msgid "mrWidget|Closes issue"
msgid_plural "mrWidget|Closes issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Закрывает обÑуждение"
+msgstr[1] "Закрывает обÑуждениÑ"
+msgstr[2] "Закрывает обÑуждениÑ"
+msgstr[3] "Закрывает обÑуждениÑ"
msgid "mrWidget|Create issue to resolve all threads"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42917,10 +43492,10 @@ msgstr ""
msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Упоминает обÑуждение"
+msgstr[1] "Упоминает обÑуждениÑ"
+msgstr[2] "Упоминает обÑуждениÑ"
+msgstr[3] "Упоминает обÑуждениÑ"
msgid "mrWidget|Merge"
msgstr "Слить"
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "СлиÑние не удалоÑÑŒ."
@@ -42997,6 +43575,9 @@ msgstr "Открыть в Web IDE"
msgid "mrWidget|Plain diff"
msgstr "Обычное отличие"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Готово к автоматичеÑкому ÑлиÑнию. ПопроÑите кого-нибудь Ñ Ð¿Ñ€Ð°Ð²Ð¾Ð¼ запиÑи в Ñтот репозиторий Ñделать ÑлиÑние данного запроÑа"
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ Ñлиты в"
@@ -43051,9 +43635,6 @@ msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ были Ñлиты в"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Ваш пароль"
-msgid "mrWidget|branch does not exist."
-msgstr "ветка не ÑущеÑтвует."
-
msgid "mrWidget|into"
msgstr "в"
@@ -43299,7 +43877,7 @@ msgid "project access token"
msgstr ""
msgid "project access tokens"
-msgstr ""
+msgstr "токены доÑтупа к проекту"
msgid "project avatar"
msgstr "логотип проекта"
@@ -43311,7 +43889,7 @@ msgid "project is read-only"
msgstr "проект доÑтупен только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
msgid "project members"
-msgstr ""
+msgstr "учаÑтники проекта"
msgid "project name"
msgstr "название проекта"
@@ -43383,9 +43961,6 @@ msgstr "репозиторий:"
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr "ÑброÑить."
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr "аватар пользователÑ"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr "наÑтройки пользователÑ"
-
msgid "username"
msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
@@ -43579,7 +44151,7 @@ msgid "value for '%{storage}' must be an integer"
msgstr ""
msgid "value for '%{storage}' must be between 0 and 100"
-msgstr ""
+msgstr "значение Ð´Ð»Ñ \"%{storage}\" должно быть от 0 до 100"
msgid "verify ownership"
msgstr "подтвердить право ÑобÑтвенноÑти"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 5f40265460b..ac845aeffac 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 77bdd802774..9283a31c47a 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: 2022-01-06 17:21\n"
+"PO-Revision-Date: 2022-02-02 15:44\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -132,6 +132,34 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -780,6 +814,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -876,6 +913,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2223,7 +2251,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2238,6 +2266,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2421,9 +2455,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4041,16 +4075,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index b8062074e34..b51de9153d5 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -132,6 +132,34 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -780,6 +814,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -876,6 +913,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -885,6 +925,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -997,9 +1040,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -2064,21 +2107,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -2103,9 +2137,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2211,9 +2242,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2223,7 +2251,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2238,6 +2266,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2304,6 +2335,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2421,9 +2455,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2721,6 +2752,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2913,7 +2953,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -3039,6 +3079,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3204,7 +3250,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3765,22 +3811,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -4041,16 +4075,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4655,9 +4683,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4667,13 +4692,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4730,7 +4758,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,22 +4770,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4871,6 +4905,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4965,9 +5002,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5052,7 +5086,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5498,6 +5532,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5657,6 +5697,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ 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 ""
@@ -5711,9 +5751,6 @@ 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 ""
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6191,18 +6237,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6218,9 +6258,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6269,15 +6306,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6296,9 +6324,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6561,9 +6595,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6798,6 +6844,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7181,6 +7230,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7358,6 +7410,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7658,15 +7713,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7763,6 +7809,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7787,7 +7839,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7832,7 +7884,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7919,13 +7971,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7952,7 +8007,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7979,6 +8034,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7991,6 +8058,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,7 +8086,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9265,6 +9344,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9310,12 +9395,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9343,12 +9431,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10171,13 +10280,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10579,6 +10694,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11058,10 +11182,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11169,9 +11287,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11184,9 +11299,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11259,9 +11371,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11319,9 +11419,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11343,9 +11440,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12928,7 +13052,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,7 +13247,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13369,6 +13493,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13991,6 +14124,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14805,9 +14944,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14817,15 +14953,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14841,6 +14971,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15465,12 +15630,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15906,18 +16071,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15954,6 +16122,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -16008,6 +16179,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -16083,12 +16257,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -16137,16 +16308,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16656,6 +16836,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16980,6 +17169,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,7 +17574,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17442,6 +17625,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17966,9 +18170,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21728,9 +21950,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21746,6 +21965,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21782,6 +22004,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22556,6 +22811,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23401,9 +23671,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24363,6 +24621,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,7 +24690,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25350,7 +25611,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,7 +26410,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26395,9 +26677,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26410,6 +26689,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26422,7 +26704,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26587,10 +26869,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26773,6 +27073,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26788,6 +27091,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -27142,6 +27451,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27367,6 +27679,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27391,9 +27706,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27616,9 +27931,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28267,6 +28588,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29233,7 +29551,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30627,9 +30964,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30696,7 +31030,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,13 +31134,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -31091,16 +31443,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32740,7 +33164,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -33176,6 +33597,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33415,9 +33842,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33790,9 +34238,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -34126,6 +34571,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34510,6 +34961,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -35164,6 +35651,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35414,6 +35907,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -37170,9 +37663,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38520,6 +39001,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38541,6 +39025,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39954,6 +40471,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39966,6 +40486,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,10 +40948,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,7 +42180,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr ""
@@ -41915,6 +42484,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,7 +43469,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42997,6 +43575,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -43051,9 +43635,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43383,9 +43961,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43566,9 +44141,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 570240d8699..ef3fdd1818c 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 47a5d0f30ce..07712753e68 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:47\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -124,6 +124,30 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -532,6 +556,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -703,6 +733,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -799,6 +832,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -808,6 +844,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -919,9 +958,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -955,6 +991,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1948,21 +1987,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1987,9 +2017,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2095,9 +2122,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2107,7 +2131,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2122,6 +2146,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2188,6 +2215,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2305,9 +2335,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2605,6 +2632,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2761,6 +2794,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2797,7 +2833,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2923,6 +2959,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3088,7 +3130,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3649,22 +3691,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3775,9 +3808,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3925,16 +3955,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4498,9 +4525,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4531,9 +4555,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4543,13 +4564,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4576,7 +4597,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4591,6 +4612,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4606,7 +4630,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4618,22 +4642,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4747,6 +4777,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4840,9 +4873,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4927,7 +4957,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5371,6 +5401,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5503,6 +5536,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5530,6 +5566,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5545,9 +5584,6 @@ 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 ""
@@ -5584,9 +5620,6 @@ 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 ""
@@ -5665,9 +5698,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5746,6 +5785,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6061,18 +6103,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6088,9 +6124,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6139,15 +6172,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6166,9 +6190,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6364,6 +6385,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6430,9 +6460,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6667,6 +6709,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7048,6 +7093,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7225,6 +7273,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7525,15 +7576,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7630,6 +7672,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7654,7 +7702,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7699,7 +7747,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7729,7 +7777,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7786,13 +7834,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7819,7 +7870,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7846,6 +7897,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7858,6 +7921,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7882,7 +7948,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7900,6 +7966,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8851,6 +8920,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9100,6 +9172,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9130,6 +9205,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9175,12 +9256,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9208,12 +9292,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9775,7 +9865,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9916,9 +10006,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9931,9 +10036,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10006,6 +10108,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10033,13 +10138,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10183,6 +10291,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10441,6 +10552,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10675,6 +10789,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10909,6 +11026,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10918,10 +11038,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11011,12 +11131,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11029,9 +11143,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11044,9 +11155,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11119,9 +11227,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11149,9 +11254,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11161,12 +11263,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11179,9 +11275,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11203,9 +11296,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11476,9 +11566,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11911,6 +11998,9 @@ msgstr[2] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11926,6 +12016,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12139,9 +12232,39 @@ msgstr[2] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12706,9 +12829,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12775,7 +12895,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12970,7 +13090,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13216,6 +13336,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13360,9 +13483,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13405,6 +13525,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13432,6 +13555,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13510,9 +13639,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13561,6 +13687,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13837,6 +13966,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14650,9 +14785,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14662,15 +14794,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14686,6 +14812,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14767,10 +14941,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15211,15 +15382,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15307,12 +15469,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15637,6 +15793,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15712,6 +15871,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15748,18 +15910,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15796,6 +15961,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15850,6 +16018,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15925,12 +16096,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15946,6 +16111,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15979,16 +16147,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16000,9 +16171,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16051,6 +16219,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16087,10 +16261,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16168,6 +16342,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16291,9 +16468,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16318,6 +16492,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16498,6 +16675,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16636,6 +16816,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16804,6 +16987,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16822,6 +17008,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16885,9 +17074,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16912,6 +17098,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16924,9 +17113,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17167,18 +17353,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17203,9 +17383,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17236,7 +17413,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17284,6 +17464,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17302,9 +17485,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17332,9 +17512,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17377,7 +17554,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17458,9 +17635,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17515,7 +17689,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17746,6 +17920,33 @@ msgstr[2] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17806,9 +18007,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17845,9 +18043,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17863,6 +18058,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17962,6 +18160,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17986,9 +18196,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18592,6 +18799,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18694,6 +18904,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18769,6 +18982,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19192,9 +19408,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19207,9 +19420,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19279,6 +19489,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19297,9 +19510,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19336,6 +19546,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19345,6 +19558,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19405,7 +19621,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21226,6 +21442,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21556,9 +21775,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21574,6 +21790,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21610,6 +21829,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22384,6 +22636,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22402,9 +22660,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23227,9 +23494,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23251,9 +23515,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23431,10 +23692,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23539,9 +23800,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23620,9 +23878,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23641,9 +23896,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24160,6 +24412,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24187,6 +24442,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24253,7 +24511,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25168,7 +25426,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25786,9 +26065,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25927,6 +26203,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25945,7 +26224,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26212,9 +26491,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26227,6 +26503,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26239,7 +26518,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26404,10 +26683,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26590,6 +26887,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26605,6 +26905,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26959,6 +27265,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27184,6 +27493,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27208,9 +27520,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27388,6 +27697,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27433,9 +27745,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27958,10 +28267,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28039,6 +28351,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28084,6 +28402,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28210,9 +28531,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28234,7 +28552,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28252,7 +28570,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29014,9 +29332,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29050,7 +29365,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29296,6 +29611,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29365,6 +29686,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29440,7 +29764,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29983,6 +30307,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30211,6 +30541,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30286,9 +30619,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30307,6 +30637,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30436,9 +30769,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30505,7 +30835,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30607,13 +30937,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30634,6 +30964,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30721,6 +31054,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30733,9 +31069,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30754,6 +31096,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30769,9 +31114,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30820,10 +31162,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30859,6 +31204,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30898,16 +31246,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30919,6 +31267,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30934,9 +31285,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31090,9 +31438,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31219,9 +31564,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31534,7 +31876,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31666,6 +32008,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31720,6 +32065,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31738,21 +32086,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31762,12 +32119,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,6 +32161,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31810,12 +32182,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31825,6 +32245,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32146,9 +32569,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32536,7 +32956,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32545,6 +32965,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32554,18 +32977,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32704,7 +33121,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32878,9 +33295,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32920,6 +33334,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32932,6 +33349,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32944,9 +33364,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32971,6 +33388,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33013,7 +33433,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33106,6 +33526,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33208,9 +33631,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33517,9 +33964,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33583,9 +34027,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33919,6 +34360,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33961,6 +34405,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34303,6 +34750,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34333,6 +34783,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34411,9 +34882,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34582,9 +35050,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34609,6 +35074,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34648,6 +35116,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34702,6 +35173,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34714,6 +35188,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34957,6 +35440,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35029,6 +35515,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35203,6 +35692,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35377,9 +35869,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35419,12 +35908,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35434,9 +35917,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35470,7 +35950,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35638,6 +36118,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35713,9 +36196,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35731,9 +36211,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36103,7 +36580,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36154,7 +36631,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36238,9 +36715,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36364,6 +36838,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36403,9 +36880,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36445,9 +36919,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36667,6 +37147,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36688,6 +37171,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36727,6 +37213,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36955,9 +37444,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37207,9 +37693,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37351,9 +37834,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37369,9 +37849,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37579,9 +38056,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37693,6 +38167,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37708,15 +38185,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37783,6 +38254,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38302,6 +38779,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38323,6 +38803,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38758,6 +39241,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39289,6 +39775,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39439,6 +39937,9 @@ msgstr[2] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39664,6 +40165,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39706,6 +40210,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39724,6 +40231,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39733,6 +40246,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39745,6 +40261,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39757,6 +40276,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39781,9 +40303,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39964,127 +40495,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40192,10 +40723,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40504,7 +41035,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40606,6 +41143,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40639,6 +41179,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40687,6 +41230,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40732,6 +41278,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40867,6 +41416,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40960,6 +41512,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40999,7 +41554,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41014,6 +41569,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41395,7 +41953,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41404,9 +41962,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41473,6 +42028,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41605,6 +42163,12 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "approved by: "
msgstr ""
@@ -41689,6 +42253,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42064,6 +42631,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42091,12 +42661,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42226,6 +42790,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42274,6 +42841,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42391,6 +42964,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42487,9 +43063,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42532,9 +43105,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42658,7 +43228,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42706,6 +43276,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42760,6 +43333,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42805,6 +43381,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42814,9 +43393,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42853,9 +43429,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43141,9 +43714,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43324,9 +43894,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index bdcfd213a9a..8475a4b362e 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -124,6 +124,30 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -532,6 +556,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -703,6 +733,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -799,6 +832,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -808,6 +844,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -919,9 +958,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -955,6 +991,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1948,21 +1987,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1987,9 +2017,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -2095,9 +2122,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -2107,7 +2131,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2122,6 +2146,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2188,6 +2215,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2305,9 +2335,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2605,6 +2632,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2761,6 +2794,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2797,7 +2833,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2923,6 +2959,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3088,7 +3130,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3649,22 +3691,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3775,9 +3808,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3925,16 +3955,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while fetching this tab."
-msgstr ""
-
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4498,9 +4525,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4531,9 +4555,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4543,13 +4564,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4576,7 +4597,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4591,6 +4612,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4606,7 +4630,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4618,22 +4642,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4747,6 +4777,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4840,9 +4873,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4927,7 +4957,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5371,6 +5401,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5503,6 +5536,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5530,6 +5566,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5545,9 +5584,6 @@ 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 ""
@@ -5584,9 +5620,6 @@ 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 ""
@@ -5665,9 +5698,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5746,6 +5785,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -6061,18 +6103,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -6088,9 +6124,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6139,15 +6172,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6166,9 +6190,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6364,6 +6385,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6430,9 +6460,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6667,6 +6709,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -7048,6 +7093,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7225,6 +7273,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7525,15 +7576,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7630,6 +7672,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7654,7 +7702,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7699,7 +7747,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7729,7 +7777,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7786,13 +7834,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7819,7 +7870,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7846,6 +7897,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7858,6 +7921,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7882,7 +7948,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7900,6 +7966,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8851,6 +8920,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -9100,6 +9172,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9130,6 +9205,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9175,12 +9256,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9208,12 +9292,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9775,7 +9865,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9916,9 +10006,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9931,9 +10036,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -10006,6 +10108,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -10033,13 +10138,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10183,6 +10291,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10441,6 +10552,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10675,6 +10789,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10909,6 +11026,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10918,10 +11038,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11011,12 +11131,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -11029,9 +11143,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -11044,9 +11155,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11119,9 +11227,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11149,9 +11254,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11161,12 +11263,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11179,9 +11275,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11203,9 +11296,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11476,9 +11566,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11911,6 +11998,9 @@ msgstr[2] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11926,6 +12016,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -12139,9 +12232,39 @@ msgstr[2] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12706,9 +12829,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12775,7 +12895,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12970,7 +13090,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13216,6 +13336,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13360,9 +13483,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13405,6 +13525,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13432,6 +13555,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13510,9 +13639,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13561,6 +13687,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13837,6 +13966,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13864,6 +13996,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14650,9 +14785,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14662,15 +14794,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14686,6 +14812,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14767,10 +14941,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15211,15 +15382,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15307,12 +15469,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15637,6 +15793,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15712,6 +15871,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15748,18 +15910,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15796,6 +15961,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15850,6 +16018,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15925,12 +16096,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15946,6 +16111,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15979,16 +16147,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16000,9 +16171,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16051,6 +16219,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16087,10 +16261,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16168,6 +16342,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16291,9 +16468,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16318,6 +16492,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16498,6 +16675,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16636,6 +16816,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16804,6 +16987,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16822,6 +17008,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16885,9 +17074,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16912,6 +17098,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16924,9 +17113,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17167,18 +17353,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17203,9 +17383,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17236,7 +17413,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17284,6 +17464,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17302,9 +17485,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17332,9 +17512,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17377,7 +17554,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17458,9 +17635,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17515,7 +17689,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17746,6 +17920,33 @@ msgstr[2] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17806,9 +18007,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17845,9 +18043,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17863,6 +18058,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17962,6 +18160,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17986,9 +18196,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18592,6 +18799,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18694,6 +18904,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18769,6 +18982,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19192,9 +19408,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19207,9 +19420,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19279,6 +19489,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19297,9 +19510,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19336,6 +19546,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19345,6 +19558,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19405,7 +19621,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21226,6 +21442,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21556,9 +21775,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21574,6 +21790,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21610,6 +21829,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22384,6 +22636,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22402,9 +22660,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23227,9 +23494,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23251,9 +23515,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23431,10 +23692,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23539,9 +23800,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23620,9 +23878,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23641,9 +23896,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24160,6 +24412,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24187,6 +24442,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24253,7 +24511,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -25168,7 +25426,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25786,9 +26065,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25927,6 +26203,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25945,7 +26224,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26212,9 +26491,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26227,6 +26503,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26239,7 +26518,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26404,10 +26683,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26590,6 +26887,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26605,6 +26905,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26959,6 +27265,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27184,6 +27493,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27208,9 +27520,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27388,6 +27697,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27433,9 +27745,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27958,10 +28267,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28039,6 +28351,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -28084,6 +28402,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28210,9 +28531,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28234,7 +28552,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28252,7 +28570,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29014,9 +29332,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -29050,7 +29365,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29296,6 +29611,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29365,6 +29686,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29440,7 +29764,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29983,6 +30307,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30211,6 +30541,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30286,9 +30619,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30307,6 +30637,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30436,9 +30769,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30505,7 +30835,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30607,13 +30937,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30634,6 +30964,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30721,6 +31054,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30733,9 +31069,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30754,6 +31096,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30769,9 +31114,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30820,10 +31162,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30859,6 +31204,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30898,16 +31246,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30919,6 +31267,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30934,9 +31285,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31090,9 +31438,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31219,9 +31564,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31534,7 +31876,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31666,6 +32008,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31720,6 +32065,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31738,21 +32086,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31762,12 +32119,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31795,6 +32161,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31810,12 +32182,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31825,6 +32245,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32146,9 +32569,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32536,7 +32956,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32545,6 +32965,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32554,18 +32977,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32704,7 +33121,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32878,9 +33295,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32920,6 +33334,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32932,6 +33349,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32944,9 +33364,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32971,6 +33388,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33013,7 +33433,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33106,6 +33526,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33208,9 +33631,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33517,9 +33964,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33583,9 +34027,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33919,6 +34360,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33961,6 +34405,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34303,6 +34750,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34333,6 +34783,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34411,9 +34882,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34582,9 +35050,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34609,6 +35074,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34648,6 +35116,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34702,6 +35173,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34714,6 +35188,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34957,6 +35440,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35029,6 +35515,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -35203,6 +35692,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35377,9 +35869,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35419,12 +35908,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35434,9 +35917,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35470,7 +35950,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35638,6 +36118,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35713,9 +36196,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35731,9 +36211,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36103,7 +36580,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36154,7 +36631,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36238,9 +36715,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36364,6 +36838,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36403,9 +36880,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36445,9 +36919,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36667,6 +37147,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36688,6 +37171,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36727,6 +37213,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36955,9 +37444,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37207,9 +37693,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37351,9 +37834,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37369,9 +37849,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37579,9 +38056,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37693,6 +38167,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37708,15 +38185,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37783,6 +38254,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38302,6 +38779,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38323,6 +38803,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38758,6 +39241,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39289,6 +39775,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39439,6 +39937,9 @@ msgstr[2] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39664,6 +40165,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39706,6 +40210,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39724,6 +40231,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39733,6 +40246,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39745,6 +40261,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39757,6 +40276,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39781,9 +40303,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39964,127 +40495,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40192,10 +40723,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40504,7 +41035,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40606,6 +41143,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40639,6 +41179,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40687,6 +41230,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40732,6 +41278,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40867,6 +41416,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40960,6 +41512,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40999,7 +41554,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41014,6 +41569,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41395,7 +41953,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41404,9 +41962,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41473,6 +42028,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41605,6 +42163,12 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "approved by: "
msgstr ""
@@ -41689,6 +42253,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42064,6 +42631,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42091,12 +42661,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42226,6 +42790,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42274,6 +42841,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42391,6 +42964,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42487,9 +43063,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42532,9 +43105,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42658,7 +43228,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42706,6 +43276,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42760,6 +43333,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42805,6 +43381,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42814,9 +43393,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42853,9 +43429,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -43141,9 +43714,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43324,9 +43894,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 675ffd8220c..10d1c88b0be 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL skannad"
msgstr[1] "%d URL:er skannade"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkännare"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr "%{group_name} gruppmedlemmar"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} är ett ogiltigt tema"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "Lägg till en GPG-nyckel"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "Lägg till en SSH-nyckel"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "Avataren kommer att tas bort! Är du säker?"
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 17807b99862..d72301d07a6 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index 610216894c5..83315a850f9 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 172d63943bd..d4ee8db70c2 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] "%d URL tarandı"
msgstr[1] "%d URL tarandı"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d onaylayan"
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr "%{group_name} grubunun üyeleri"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr "Bir %{group_level_name} grubunda %{level_name} izin verilmez."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr "%{placeholder} geçerli bir tema değil"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr "Başka hiçbir veriye erişmek için kullanılamaz."
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "Kişisel Erişim Anahtarları"
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr "Daha fazlasını öğren"
@@ -1979,9 +2002,6 @@ msgstr "CHANGELOG ekle"
msgid "Add CONTRIBUTING"
msgstr "CONTRIBUTING ekle"
-msgid "Add GitLab to Slack"
-msgstr "GitLab'i Slack'e ekle"
-
msgid "Add Jaeger URL"
msgstr "Jaeger URL ekle"
@@ -1991,8 +2011,8 @@ msgstr "Kubernetes kümesi ekle"
msgid "Add LICENSE"
msgstr "LÄ°SANS ekle"
-msgid "Add New Node"
-msgstr "Yeni Bir Düğüm Ekle"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "BENÄ°OKU ekle"
@@ -2006,6 +2026,9 @@ msgstr "Bir %{type} ekle"
msgid "Add a GPG key"
msgstr "Bir GPG anahtarı ekle"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr "Bir yapılacak ekle"
msgid "Add an SSH key"
msgstr "Bir SSH anahtarı ekle"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Mevcut sorunu ekle"
@@ -2189,9 +2215,6 @@ msgstr "Sistem kancası ekle"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "Slack'e ekle"
-
msgid "Add to board"
msgstr "Panoya ekle"
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "İstatistikler yüklenirken hata oluştu. Lütfen tekrar deneyin"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Onay bekliyor)"
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Yönetici"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr "Bu sensin!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "Kullanıcının oturumu kapatılacak"
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr "Bu gruptaki projelerin Git LFS'yi kullanmasına izin verin"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Yerel aÄŸa kanca ve servislerden gelen isteklere izin ver."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Sistem kancalarından yerel ağa gelen isteklere izin ver"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr "Bir hata oluÅŸtu"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Konuya taslak eklenirken bir hata oluÅŸtu."
@@ -3809,18 +3835,15 @@ msgstr "İşler alınırken bir hata oluştu."
msgid "An error occurred while fetching the latest pipeline."
msgstr "En son iş hattı getirilirken bir hata oluştu."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Sürümler alınırken bir hata oluştu. Lütfen tekrar deneyin."
msgid "An error occurred while fetching this tab."
msgstr "Bu sekme alınırken bir hata oluştu."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "Kullanıcı adı oluştururken bir hata oluştu. Lütfen tekrar deneyin."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr ""
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Onaylayanlar"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr "Hedef dal"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr "Bu projeyi arşivden kaldırmak istediğinizden emin misiniz?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr "Bu kimliği kaldırmak istediğinizden emin misiniz?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Sağlık kontrolü erişim anahtarını sıfırlamak istediğinizden emin misiniz?"
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr "Profil resmi kaldırılacak. Emin misiniz?"
msgid "Average per day: %{average}"
msgstr "Günlük ortalama: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Dikkatli olun. Projenin isim alanını değiştirmek, istenmeyen yan etkilere neden olabilir."
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name}, şu anda %{plan_name} planını kullanıyorsunuz."
-msgid "BillingPlans|Compare all plans"
-msgstr ""
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr "Birleştirilmiş dalları sil"
msgid "Branches|Delete protected branch"
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?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Birleştirilmiş dalı siliyorsunuz ve bu geri alınamaz. Emin misiniz?"
@@ -5958,9 +5990,6 @@ msgstr "Yeni dal"
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Veri kaybını önlemek için, bu dalı silmeden önce birleştirmeyi düşünün."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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."
@@ -6036,9 +6056,6 @@ 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."
-
msgid "Branches|diverged from upstream"
msgstr "akıştan ayrılmış"
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "Varsayılan olarak, tüm projeler ve gruplar genel bildirimler ayarını kullanacaktır."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "tarafından"
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr "Otomatik olarak birleÅŸtirilemez"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Fatura adresi"
@@ -7092,6 +7136,9 @@ msgstr "Bu birleştirme talebini ayrıntılı incele"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "Alt epik mevcut deÄŸil."
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr "İstemci kimlik doğrulama sertifikası"
-
-msgid "Client authentication key"
-msgstr "İstemci kimlik doğrulama anahtarı"
-
-msgid "Client authentication key password"
-msgstr "İstemci kimlik doğrulama anahtar parolası"
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "%{quick_action_target} bunu kapatır."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "Küme"
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr "İşlem Mesajı"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Onayla"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr "Hesabınıza bağlı e-postaları kontrol edin"
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr "Grup geri yüklenemedi"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr "Ben oluÅŸturdum"
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "OluÅŸturma tarihi"
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr "Varsayılan sınıflandırma etiketi"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] "Dağıtımlar"
msgid "Deploy Keys"
msgstr "Dağıtım Anahtarları"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Şuna dağıt..."
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "Bu dağıtım, API kullanılarak oluşturuldu"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "iptal edildi"
@@ -12554,9 +12673,6 @@ msgstr "Geliştirme sürecinize entegre güvenlik özellikleri"
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Ücretsiz deneme sürümü başlatın"
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr "Sorunlarda zaman izlemeyi yalnızca toplam saat olarak görüntüleyin."
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr "Yorumu düzenle"
msgid "Edit Deploy Key"
msgstr "Dağıtım Anahtarını Düzenle"
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Bakım modunu etkinleştir"
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr "Ortamı durdur"
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Epik"
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "Harici kimlik doÄŸrulama"
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr "Sınıflandırma etiketi"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr "Jira içe aktarımı için içe aktarma etiketi oluşturulamadı."
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "Åžub"
@@ -15149,12 +15308,6 @@ msgstr "Süzgeç"
msgid "Filter by"
msgstr "Filtrele:"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Kapalı olan %{issuable_type} türüne göre filtrele."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Varsayılan etiket kümesi oluştur"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr "CoÄŸrafi"
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr "CoÄŸrafi Ayarlar"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr "Sonraki senkronizasyon planlandı"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Senkronizasyon bekliyor"
@@ -15821,16 +15986,19 @@ msgstr "Tekrar indir"
msgid "Geo|Remove"
msgstr "Kaldır"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr "ikincil"
msgid "Get a free instance review"
msgstr "Ücretsiz bir örnek incelemesi alın"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "GitLab üyesi ya da e-posta adresi"
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16383,7 +16560,7 @@ msgid "GlobalSearch|Results updated. %{count} results available. Use the up and
msgstr ""
msgid "GlobalSearch|Search GitLab"
-msgstr ""
+msgstr "GitLab'da ara"
msgid "GlobalSearch|Search results are loading"
msgstr ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Grup Git LFS durumu:"
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Grup sorumluları, grup çalıştırıcılarını %{link} içinde kaydedebilir"
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr "Gruba genel bakış içeriği"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr "Grup iş hattı kayıtları başarıyla sıfırlandı."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] "DeÄŸerleri gizle"
msgid "Hide values"
msgstr "DeÄŸerleri gizle"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr "Temizlik hizmeti"
msgid "Housekeeping successfully started"
msgstr "Temizlik hizmeti başarıyla başlatıldı"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "Temizlik hizmeti, dışa aktarma, yol, transfer, kaldırma, arşivleme."
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr "Åžifremi unuttum"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Tüm ayrıntılar"
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr "Yorum ayrıntıları:"
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr "Standart"
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr "Yükleniyor..."
msgid "Loading…"
msgstr "Yükleniyor…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "YerelleÅŸtirme"
@@ -21402,6 +21615,9 @@ msgstr "Kilitle"
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr "Kilitler, belirli bir dosyayı veya klasörü kilitleme yeteneği sağla
msgid "Locks the discussion."
msgstr "Tartışmayı kilitler."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "İş hattı başarılı olduğunda birleştir"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr "Ay"
msgid "More Information"
msgstr "Daha Fazla Bilgi"
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr "Gösterilecek dönüm noktası yok"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr "İş hatları"
msgid "Pipelines charts"
msgstr "İş hatları çizelgeleri"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "'%{project_name}' için iş hattı ayarları başarıyla güncellendi."
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr "Zaman tercihleri"
msgid "Preferences|Use relative times"
msgstr "Göreceli zamanları kullan"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Önceki"
@@ -26993,7 +27299,7 @@ msgid "Profiles|An error occurred while updating your username, please try again
msgstr "Kullanıcı adınız güncellenirken bir hata oluştu, lütfen tekrar deneyin."
msgid "Profiles|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Adınızın ve profil resminizin yanında bir gösterge belirir"
msgid "Profiles|Avatar cropper"
msgstr "Profil resmi kırpıcı"
@@ -27001,6 +27307,9 @@ msgstr "Profil resmi kırpıcı"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Profil resmi kaldırılacak. Emin misiniz?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "Hakkında"
@@ -27025,9 +27334,6 @@ msgstr "Şehir, ülke"
msgid "Profiles|Clear status"
msgstr "Durumu temizle"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Aşağıdaki hizmetlerden biriyle giriş yapmak için simgeye tıklayın"
-
msgid "Profiles|Commit email"
msgstr "İşlem e-postası"
@@ -27205,11 +27511,14 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Profil resmini kaldır"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Yeni profil resmini ayarla"
msgid "Profiles|Set your local time zone"
-msgstr ""
+msgstr "Yerel saat diliminizi ayarlayın"
msgid "Profiles|Social sign-in"
msgstr "Sosyal oturum açma"
@@ -27250,9 +27559,6 @@ msgstr "İki Aşamalı Kimlik Doğrulama"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Onaylamak için kendi %{confirmationValue} yazınız:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Genellikle \"ssh-ed25519 …\" veya \"ssh-rsa …\" ile başlar"
-
msgid "Profiles|Update profile settings"
msgstr "Profil ayarlarını güncelle"
@@ -27775,11 +28081,14 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "Birleştirme yönteminizi, birleştirme seçeneklerini, birleştirme denetimlerini ve birleştirme önerilerini seçin."
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
-msgstr "Birleştirme yönteminizi, birleştirme seçeneklerinizi, birleştirme denetimlerinizi, birleştirme önerilerinizi seçin ve birleştirme istekleri için varsayılan bir açıklama şablonu oluşturun."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr "BirleÅŸtirme istekleri"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "Birleştirme önerileri"
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr "Daha fazla dakika satın al"
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr "%{name} tarafından çözüldü"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr "Ä°ptal et"
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr "Yol haritası"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Rol"
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr "Ara"
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr "Arşiv Biçimini Seçin"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr "Sayfa Seç"
@@ -32332,7 +32748,7 @@ msgstr "Servis Masası"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr "CI/CD'yi kur"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32537,7 +32950,7 @@ msgid "SetStatusModal|Add status emoji"
msgstr "Durum ifadesi ekle"
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Adınızın ve profil resminizin yanında bir gösterge belirir"
msgid "SetStatusModal|Busy"
msgstr ""
@@ -32673,9 +33086,6 @@ msgstr "İş hattı dakikalarını sıfırla"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Kullanılan iş hattı dakikalarını sıfırla"
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr "Arşivlenmiş projeleri göster"
msgid "Show archived projects only"
msgstr "Yalnızca arşivlenmiş projeleri göster"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Komutu göster"
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr "Tüm sorunlar gösteriliyor"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr "Oturumu kapat ve kaydol"
msgid "Sign up"
msgstr "Kaydol"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr "Üzgünüz, aramanızla eşleşen epik yok"
-
msgid "Sorry, no projects matched your search"
msgstr "Üzgünüz, aramanızla eşleşen proje yok"
@@ -33376,9 +33816,6 @@ msgstr "Son iletiÅŸim"
msgid "SortOptions|Last created"
msgstr "Son oluÅŸturulan"
-msgid "SortOptions|Last updated"
-msgstr "Son güncelleme"
-
msgid "SortOptions|Least popular"
msgstr "En az popüler"
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Aramayı başlat"
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr "Abone"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr "Deneme bitiÅŸ tarihi"
msgid "SubscriptionTable|Trial start date"
msgstr "Deneme başlangıç tarihi"
-msgid "SubscriptionTable|Upgrade"
-msgstr "Yükselt"
-
msgid "SubscriptionTable|Usage"
msgstr "Kullanım"
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr "Pazar"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Destek"
@@ -34750,6 +35229,9 @@ msgstr "Hedef dal"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr "Hizmet Koşulları Sözleşmesi ve Gizlilik Politikası"
msgid "Terms of Service and Privacy Policy"
msgstr "Hizmet Koşulları ve Gizlilik Politikası"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr "Kullanıcı iş hattı dakikaları sıfırlanırken bir hata oluştu."
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr "Bu proje"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr "Son işlemden birleştirmeye kadar geçen süre"
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr "Aramanızı genişletmek için yukarıdaki filtreleri değiştirin veya
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "Aramanızı genişletmek için süzgeçlerinizi değiştirin veya kaldırın."
-
msgid "To-Do List"
msgstr "Yapılacaklar Listesi"
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr "Tetikleyici başarıyla güncellendi."
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr "Güncellendi:"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "%{updated_by} tarafından %{updated_at} zamanında güncellendi"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr "Değiştirilen @ dosyayı görüntüle "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Proje"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "UYARI:"
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr "Bu gruplara katılmayı talep ederek onlara kolayca katkıda bulunabilir
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr "Proje sınırınıza ulaştınız"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr "Adınız"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "AboneliÄŸiniz sona erdi!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "%{user} aracılığıyla %{email} tarafından %{timeAgoString} oluşturuldu"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "%{user} tarafından %{timeAgoString} oluşturuldu"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "Jira'da %{user} tarafından %{timeAgoString} oluşturuldu"
-
msgid "created %{timeAgo}"
msgstr "%{timeAgo} oluÅŸturuldu"
@@ -41995,6 +42554,9 @@ msgstr "başarısız"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42007,7 +42569,7 @@ msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
msgid "following"
-msgstr ""
+msgstr "takip ediliyor"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr "grup"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "%{path_lock_user_name} tarafından kilitlendi %{created_at}"
-msgid "log in"
-msgstr "oturum aç"
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Birleştirme başarısız."
@@ -42523,6 +43091,9 @@ msgstr "Web IDE'de aç"
msgid "mrWidget|Plain diff"
msgstr "Düz değişiklik"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Kaynak dal silindi"
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Åžifreniz"
-msgid "mrWidget|branch does not exist."
-msgstr "dal mevcut deÄŸil."
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr "kullanıcının profil resmi"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "kullanıcı adı"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 2a89f199ae8..f7980b193c8 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -132,6 +132,34 @@ msgstr[1] "%d URL-адреÑи відÑкановано"
msgstr[2] "%d URL-Ð°Ð´Ñ€ÐµÑ Ð²Ñ–Ð´Ñкановано"
msgstr[3] "%d URL-Ð°Ð´Ñ€ÐµÑ Ð²Ñ–Ð´Ñкановано"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d затверджуюча оÑоба"
@@ -603,6 +631,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}ЗамаÑковано:%{code_close} Сховано в журналах завдань. Повинні відповідати вимогам до маÑкуваннÑ."
@@ -780,6 +814,9 @@ msgstr "%{group_name} активніÑÑ‚ÑŒ"
msgid "%{group_name} group members"
msgstr "кориÑтувачі групи %{group_name}"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} викориÑтовує облікові запиÑи керовані групою. Вам необхідно Ñтворити новий обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, Ñкий буде керуватиÑÑ %{group_name}."
@@ -876,6 +913,9 @@ msgstr "%{level_name} не дозволено в %{group_level_name} групі.
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} не допуÑкаєтьÑÑ, оÑкільки проєкт-джерело цього форку має нижчу видиміÑÑ‚ÑŒ."
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}ДовідайтеÑÑŒ більше%{link_end} про ролі."
@@ -885,6 +925,9 @@ msgstr "%{link_start}Видаліть %{draft_snippet} префікÑ%{link_end}
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Яку інформацію збирає ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ GitLab Inc.?%{link_end}"
@@ -997,9 +1040,6 @@ msgstr "%{placeholder} не є коректною темою"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -1034,6 +1074,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} результати Ð´Ð»Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ \"%{term}\""
@@ -1339,7 +1382,7 @@ msgid "(max size 15 MB)"
msgstr "(макÑимальний розмір 15 Мб)"
msgid "(optional)"
-msgstr ""
+msgstr "(необов'Ñзково)"
msgid "(removed)"
msgstr "(видалено)"
@@ -2064,21 +2107,12 @@ msgstr "Ðе може бути викориÑтоно Ð´Ð»Ñ Ð´Ð¾Ñтупу до
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 "Зберігайте цей токен в Ñекреті. Будь-хто, хто отримає до нього доÑтуп зможе читати RSS-канал активноÑÑ‚Ñ– та задач, а також канал вашого ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð²Ñ–Ð´ вашого імені. Ви повинні %{link_reset_it} Ñкщо це трапитьÑÑ."
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "ОÑобиÑÑ‚Ñ– токени доÑтупу"
@@ -2103,9 +2137,6 @@ msgstr "Ваш токен Ð´Ð»Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ñ… повідомлень елекÑ
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 this token"
-msgstr "Ñкинути цей токен"
-
msgid "AccessibilityReport|Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
@@ -2211,9 +2242,6 @@ msgstr "Додати ÑпиÑок змін (CHANGELOG)"
msgid "Add CONTRIBUTING"
msgstr "Додати CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr "Додати GitLab до Slack"
-
msgid "Add Jaeger URL"
msgstr "Додати URL-адреÑу Jaeger"
@@ -2223,8 +2251,8 @@ msgstr "Додати Kubernetes-клаÑтер"
msgid "Add LICENSE"
msgstr "Додати файл ліцензії (LICENSE)"
-msgid "Add New Node"
-msgstr "Додати новий вузол"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "Додати інÑтрукцію (README)"
@@ -2238,6 +2266,9 @@ msgstr "Додати %{type}"
msgid "Add a GPG key"
msgstr "Додати GPG ключ"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "Додайте URL-адреÑу Jaeger, щоб замінити цю Ñторінку поÑиланнÑм на ваш Ñервер Jaeger. Спочатку вам потрібно %{link_start_tag} вÑтановити Jaeger%{link_end_tag}."
@@ -2304,6 +2335,9 @@ msgstr "Додати нагадуваннÑ"
msgid "Add an SSH key"
msgstr "Додати SSH ключ"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "Додати Ñ–Ñнуючу задачу"
@@ -2421,9 +2455,6 @@ msgstr "Додати ÑиÑтемний хук"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "Додати текÑÑ‚ до Ñторінки входу. Markdown увімкнено."
-msgid "Add to Slack"
-msgstr "Додати в Slack"
-
msgid "Add to board"
msgstr "Додати на дошку"
@@ -2721,6 +2752,12 @@ msgstr "Ви збираєтеÑÑ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚Ð¸ вÑÑ– завданнÑ. Ви
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Помилка при завантаженні ÑтатиÑтики. Будь лаÑка, Ñпробуйте знову"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2877,6 +2914,9 @@ msgstr "(Вимкнено)"
msgid "AdminUsers|(Internal)"
msgstr "(Внутрішні)"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "(Очікує ÑхваленнÑ)"
@@ -2913,8 +2953,8 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "ÐдмініÑтратор"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr "ÐдмініÑтратори мають доÑтуп до вÑÑ–Ñ… груп, проєктів та кориÑтувачів Ñ– можуть керувати вÑіма функціÑми цього вÑтановленнÑ."
+msgid "AdminUsers|Administrator"
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "ÐдмініÑтратори"
@@ -3039,6 +3079,9 @@ msgstr "Це ви!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "Докладніше про %{link_start}забанених кориÑтувачів.%{link_end}"
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Вхід в ÑиÑтему"
@@ -3102,6 +3145,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr "КориÑтувач не може увійти."
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "КориÑтувач вийде із ÑиÑтеми"
@@ -3204,8 +3250,8 @@ 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 "Ви не можете видалити Ñвої права адмініÑтратора."
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "Ви повинні передати право влаÑноÑÑ‚Ñ– або видалити групи, що належать цьому кориÑтувачу, перш ніж ви зможете видалити його обліковий запиÑ"
@@ -3765,22 +3811,13 @@ msgstr "Дозволити проєктам в цій групі викориÑÑ
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr "Дозволити публічний доÑтуп до конвеєрів Ñ– завдань, включно з логами та артефактами."
-msgid "Allow requests to the local network from hooks and services."
-msgstr "Дозволити запити до локальної мережі із хуків та ÑервіÑів."
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "Дозволити запити до локальної мережі із ÑиÑтемних хуків"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "Дозволити запити до локальної мережі із вуб-хуків та ÑервіÑів"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Дозволити підгрупам вÑтановлювати влаÑні правила двофакторної аутентифікації"
msgid "Allow this key to push to this repository"
msgstr "Дозволити відправлÑти ключ до цього репозиторію"
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3891,9 +3928,6 @@ msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr "Помилка у звіті, в Ñкому результат теÑту вказує на наÑвніÑÑ‚ÑŒ вразливоÑÑ‚Ñ– в ÑиÑтемі, коли не приÑутні вразливоÑÑ‚Ñ–."
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "Помилка при додаванні чернетки до обговореннÑ."
@@ -4041,18 +4075,15 @@ msgstr "Помилка при отриманні завдань."
msgid "An error occurred while fetching the latest pipeline."
msgstr "Помилка при отриманні оÑтаннього конвеєра."
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Помилка при отриманні релізів. Будь лаÑка, Ñпробуйте знову."
msgid "An error occurred while fetching this tab."
msgstr "Помилка при отриманні цієї вкладки."
-msgid "An error occurred while generating a username. Please try again."
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при Ñтворенні імені кориÑтувача. Будь лаÑка, Ñпробуйте знову."
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "Помилка при отриманні даних автозаповненнÑ. Оновіть Ñторінку та Ñпробуйте ще раз."
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні файлів Ð´Ð»Ñ - %{branchId}"
@@ -4622,9 +4653,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr "Додати затверджувачів"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr "Ð’ÑÑ– Ñканери"
@@ -4655,9 +4683,6 @@ msgstr "Тип оÑоби, що затверджує"
msgid "ApprovalRule|Approvers"
msgstr "Затверджуючі оÑоби"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr "Підтверджено"
@@ -4667,13 +4692,13 @@ msgstr "Відхилено"
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Приклади: QA, Security."
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4700,7 +4725,7 @@ msgstr "Будь лаÑка, оберіть принаймні один Ñтан
msgid "ApprovalRule|Previously detected"
msgstr "Раніше виÑвлений"
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4715,6 +4740,9 @@ msgstr "Сканери безпеки"
msgid "ApprovalRule|Select All"
msgstr "Вибрати вÑе"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "Вибрати Ñканери"
@@ -4730,7 +4758,7 @@ msgstr "Рівні ÑерйозноÑÑ‚Ñ–"
msgid "ApprovalRule|Target branch"
msgstr "Цільова гілка"
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4742,23 +4770,29 @@ msgstr "Стани вразливоÑÑ‚Ñ–"
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð¾."
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr "Заборонити ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼."
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "Заборонити ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачами, Ñкі додають коміти."
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "Заборонити редагувати правила ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð² запитах на злиттÑ."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Заборонити редагувати правила ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ñƒ проєктах та запитах на злиттÑ."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "Видалити вÑÑ– ÑхваленнÑ, коли коміти додано до гілки-джерела."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
-msgstr "Вимагати пароль кориÑтувача Ð´Ð»Ñ ÑхваленнÑ."
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
@@ -4871,6 +4905,9 @@ msgstr "Ви впевнені, що хочете розархівувати це
msgid "Are you sure you want to %{action} %{name}?"
msgstr "Ви впевнені , що ви хочете %{action}%{name}?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr "Ви впевнені, що бажаєте Ñпробувати об'єднатиÑÑ?"
@@ -4965,9 +5002,6 @@ msgstr "Ви впевнені, що хочете видалити цю іденÑ
msgid "Are you sure you want to remove this list?"
msgstr "Ви впевнені, що хочете видалити цей ÑпиÑок?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "Ви впевнені, що хочете Ñкинути токен SCIM? Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ SCIM переÑтане працювати доти, поки новий токен не буде оновлено."
-
msgid "Are you sure you want to reset the health check token?"
msgstr "Ви впевнені, що Ви хочете перегенерувати цей ключ перевірки працездатноÑÑ‚Ñ–?"
@@ -5052,8 +5086,8 @@ msgstr "Запитати пізніше"
msgid "Ask someone with write access to resolve it."
msgstr "ПопроÑÑ–Ñ‚ÑŒ когоÑÑŒ із правом запиÑу вирішити цю проблему."
-msgid "Ask your group maintainer to set up a group runner."
-msgstr "ПопроÑÑ–Ñ‚ÑŒ Ñвого керівника групи налаштувати груповий Runner."
+msgid "Ask your group owner to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
@@ -5498,6 +5532,9 @@ msgstr "Ðватар буде видалено. Ви впевнені?"
msgid "Average per day: %{average}"
msgstr "Ð’ Ñередньому за день: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5630,6 +5667,9 @@ msgstr "КориÑтувач із API доÑтупом до Bambooo Ñервер
msgid "Based on"
msgstr "Ðа оÑнові"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте обережні. Зміна проÑтору імен проєкту може мати небажані побічні ефекти."
@@ -5657,6 +5697,9 @@ msgstr "Ðижче наведені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ %{link_to_gi
msgid "Below you will find all the groups that are public."
msgstr "Ðижче ви знайдете вÑÑ– загальнодоÑтупні групи."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5672,9 +5715,6 @@ msgstr "%{group_name} викориÑтовує %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "@%{user_name} наразі ви викориÑтовуєте %{plan_name}."
-msgid "BillingPlans|Compare all plans"
-msgstr "ПорівнÑти уÑÑ– плани."
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Вітаємо, ваша безкоштовна пробна верÑÑ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð°."
@@ -5711,9 +5751,6 @@ 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 "Оновіть до GitLab %{planNameForUpgrade}"
-
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 "Ðе дивлÑчиÑÑŒ на те, що GitLab припинÑÑ” доÑтуп до Бронзового плану, ви можете продовжити бронзову підпиÑку ще один раз до %{eoa_bronze_plan_end_date}. Також ми пропонуємо обмежене за чаÑом безкоштовне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ Преміум плану (до 25 кориÑтувачів)! ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про зміни та пропозиції у нашому %{announcement_link}."
@@ -5792,9 +5829,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5873,6 +5916,9 @@ msgstr "Імпорт з Bitbucket"
msgid "Blame"
msgstr "ВідповідальніÑÑ‚ÑŒ"
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "Заблокувати кориÑтувача"
@@ -6191,18 +6237,12 @@ msgstr "Видалити злиті гілки"
msgid "Branches|Delete protected branch"
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 "Ðе можна ÑкаÑувати Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ %{strongStart}%{branchName}%{strongEnd}. Ви впевнені?"
-msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ '%{branch_name}' неможливо буде ÑкаÑувати. Ви впевнені?"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð»Ð¸Ñ‚Ð¸Ñ… гілок неможливо буде ÑкаÑувати. Ви впевнені?"
@@ -6218,9 +6258,6 @@ msgstr "Ðова гілка"
msgid "Branches|No branches to show"
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 "ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐºÐ°Ð½Ð½Ñ %{strongStart}%{buttonText}%{strongEnd}, його не можна буде ÑкаÑувати або відновити."
@@ -6269,15 +6306,6 @@ msgstr "Гілка \"за замовчуваннÑм\" не може бути в
msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° не була об'єднана в %{defaultBranchName}. Щоб уникнути втрати даних, об’єднайте цю гілку перед Ñ—Ñ— видаленнÑм."
-msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° не була злита в %{default_branch}."
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†Ñ–Ñ”Ñ— гілки перед Ñ—Ñ— видаленнÑм."
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 "Щоб відхилити локальні зміни Ñ– перезапиÑати гілку верÑією з upstream, видаліть Ñ—Ñ— тут Ñ– виберіть \"Оновити зараз\" вище."
@@ -6296,9 +6324,6 @@ msgstr "Ви збираєтеÑÑŒ назавжди видалити гілку %
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити захищену гілку %{strongStart}%{branchName}.%{strongEnd}"
-msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ захищену гілку %{branch_name}."
-
msgid "Branches|diverged from upstream"
msgstr "розходитьÑÑ Ð· upstream"
@@ -6494,6 +6519,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "За замовчуваннÑм уÑÑ– проєкти та групи будуть викориÑтовувати глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень."
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "від"
@@ -6561,9 +6595,21 @@ msgstr "СтатиÑтика релізів"
msgid "CICDAnalytics|Releases"
msgstr "Релізів"
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr "Додайти %{base_domain_link_start}базовий домен%{link_end} у Ñвій %{kubernetes_cluster_link_start} клаÑтер Kubernetes%{link_end}, щоб ваша ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð°Ñ†ÑŽÐ²Ð°Ð»Ð°."
@@ -6697,10 +6743,10 @@ msgid "Can't apply as the source branch was deleted."
msgstr "Ðе вдаєтьÑÑ Ð·Ð°ÑтоÑувати, оÑкільки гілку джерела видалено."
msgid "Can't apply as these lines were changed in a more recent version."
-msgstr ""
+msgstr "Ðеможливо заÑтоÑувати, оÑкільки ці Ñ€Ñдки були змінені в оÑтанній верÑÑ–Ñ—."
msgid "Can't apply as this line was changed in a more recent version."
-msgstr ""
+msgstr "Ðеможливо заÑтоÑувати оÑкільки цей Ñ€Ñдок був змінений в оÑтанній верÑÑ–Ñ—."
msgid "Can't apply this suggestion."
msgstr "Ðе можна заÑтоÑувати цю пропозицію."
@@ -6712,7 +6758,7 @@ msgid "Can't create snippet: %{err}"
msgstr "Ðеможливо Ñтворити Ñніпет: %{err}"
msgid "Can't fetch content for the blob: %{err}"
-msgstr ""
+msgstr "Ðе вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ вміÑÑ‚ Ð´Ð»Ñ Ð±Ñ–Ð½Ð°Ñ€Ð½Ð¸Ñ… даних. %{err}"
msgid "Can't find HEAD commit for this branch"
msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
@@ -6798,6 +6844,9 @@ msgstr "Ðеможливо призначати конфіденційний еÐ
msgid "Cannot be merged automatically"
msgstr "Ðеможливо злити автоматично"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "Ðеможливо Ñтворити звіт про зловживаннÑ. КориÑтувача було видалено."
@@ -7181,6 +7230,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "Платіжна адреÑа"
@@ -7358,6 +7410,9 @@ msgstr "Вибрати (cherry-pick) цей запит на злиттÑ"
msgid "Child"
msgstr "Дочірний"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "Дочірній епік не Ñ–Ñнує."
@@ -7658,15 +7713,6 @@ msgstr "ÐатиÑніть, щоб Ñховати"
msgid "Click to reveal"
msgstr "ÐатиÑніть, щоб показати"
-msgid "Client authentication certificate"
-msgstr "Сертифікат автентифікації клієнта"
-
-msgid "Client authentication key"
-msgstr "Ключ автентифікації клієнта"
-
-msgid "Client authentication key password"
-msgstr "Пароль ключа автентифікації клієнта"
-
msgid "Client request timeout"
msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ клієнта"
@@ -7763,6 +7809,12 @@ msgstr "Закрито: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Закриває %{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7787,20 +7839,20 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
msgstr ""
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon}Підключено"
msgid "ClusterAgents|%{titleIcon}Not connected"
msgstr ""
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} Ñтворено"
msgid "ClusterAgents|%{tokenName} revoked"
msgstr ""
@@ -7832,8 +7884,8 @@ msgstr "Agent ніколи не підключаєтьÑÑ Ð´Ð¾ GitLab"
msgid "ClusterAgents|All"
msgstr "Ð’ÑÑ–"
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні вашого агента"
@@ -7862,7 +7914,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7893,10 +7945,10 @@ msgid "ClusterAgents|Date created"
msgstr "Дата ÑтвореннÑ"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "Видалити"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "Видалити агента"
msgid "ClusterAgents|Deprecated"
msgstr "Ðе підтримуєтьÑÑ"
@@ -7919,14 +7971,17 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
-msgstr "Ð’Ñтановити новий агент"
+msgid "ClusterAgents|Install new Agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "ОÑтаннє Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ %{timeAgo}."
@@ -7952,8 +8007,8 @@ msgstr "Ðіколи"
msgid "ClusterAgents|Never connected"
msgstr "Ðіколи не підключавÑÑ"
-msgid "ClusterAgents|No agents"
-msgstr "Ðемає агентів"
+msgid "ClusterAgents|No Agents"
+msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr ""
@@ -7979,6 +8034,18 @@ msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð°Ð³ÐµÐ½Ñ‚Ð°"
msgid "ClusterAgents|Registration token"
msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ñ‚Ð¾ÐºÐµÐ½Ð°"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr "Безпека"
@@ -7991,6 +8058,9 @@ msgstr "Вибрати агента"
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -8016,14 +8086,14 @@ msgstr "Цей агент не має токенів"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
-msgstr ""
+msgstr "Токен, Ñтворений %{userName}"
msgid "ClusterAgents|Token revoked by %{userName}"
-msgstr ""
+msgstr "Токен відкликано %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Ðевідомий кориÑтувач"
@@ -8034,6 +8104,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8986,6 +9059,9 @@ msgstr "Коміт (при редагуванні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð
msgid "Commit Message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr "ЗафікÑувати зміни"
@@ -9235,6 +9311,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "Компонент"
@@ -9265,6 +9344,12 @@ msgstr "Ðалаштувати %{repository_checks_link_start}перевірки
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CAPTCHA, Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ IP-Ð°Ð´Ñ€ÐµÑ Ñ‚Ð° інших антиÑпам-заходів."
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей в `.gitlab-ci.yml` викориÑтовуючи керований шаблон GitLab. Ви можете [додати змінну overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings), щоб налаштувати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей."
@@ -9310,12 +9395,15 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ñ–Ð´ÑтеженнÑ"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Ðалаштуйте %{codeStart}.gitlab-webide.yml%{codeEnd} файл %{codeStart}.gitlab%{codeEnd} , щоб почати викориÑтовувати Веб-термінал. %{helpStart}Докладніше%{helpEnd}"
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr "Ðалаштувати Ñ–Ñнуючу інÑталÑцію"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "Ðалаштувати Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²."
@@ -9343,12 +9431,18 @@ msgstr "Ðалаштуйте перший день Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° замовчÑ
msgid "Configure the way a user creates a new account."
msgstr "Ðалаштувати ÑпоÑіб ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачем нового облікового запиÑу."
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr "Підтвердити"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "Підвердіть новий пароль"
@@ -9860,7 +9954,7 @@ msgid "Contribution Analytics"
msgstr "Ðналітика внеÑків"
msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
-msgstr ""
+msgstr "%{created_count} Ñтворено, %{closed_count} закрито."
msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
msgstr ""
@@ -9913,7 +10007,7 @@ msgstr "Керувати адреÑами електронної пошти, пÐ
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -10054,9 +10148,24 @@ msgstr "Дії"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -10069,9 +10178,6 @@ msgstr "ОÑтаннє викориÑтаннÑ"
msgid "CorpusManagement|Latest Job:"
msgstr "ОÑтаннє завданнÑ:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr "Ðове завантаженнÑ"
@@ -10130,13 +10236,13 @@ msgid "Could not create project"
msgstr "Ðе вдалоÑÑ Ñтворити проєкт"
msgid "Could not create wiki page"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñтворити вікі-Ñторінку"
msgid "Could not delete chat nickname %{chat_name}."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ %{chat_name}."
msgid "Could not delete wiki page"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ вікі-Ñторінку"
msgid "Could not draw the lines for job relationships"
msgstr ""
@@ -10144,6 +10250,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ дизайн."
@@ -10171,14 +10280,17 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ тригер."
msgid "Could not restore the group"
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ групу"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "Ðеможливо відкликати токен Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "Ðеможливо відкликати перÑональний токен доÑтупу %{personal_access_token_name}."
-msgid "Could not revoke project access token %{project_access_token_name}."
-msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÐ»Ð¸ÐºÐ°Ñ‚Ð¸ токен доÑтупу до проєкту %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
msgid "Could not save group ID"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ID групи."
@@ -10321,6 +10433,9 @@ msgstr ""
msgid "Create iteration"
msgstr "Створити ітерацію"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "Створити ÑпиÑок"
@@ -10579,6 +10694,9 @@ msgstr "Створено мною"
msgid "Created by:"
msgstr "Ðвтор:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "Дата ÑтвореннÑ"
@@ -10813,6 +10931,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -11049,6 +11170,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Дата"
@@ -11058,10 +11182,10 @@ msgstr "Днів від Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ розгортаннÑ"
msgid "DORA4Metrics|Deployment frequency"
msgstr "ЧаÑтота розгортаннÑ"
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -11151,12 +11275,6 @@ msgstr "Ðе вдалоÑÑ Ñтворити профіль Ñканера. Бу
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr "Ðе вдалоÑÑ Ñтворити профіль Ñайту. Будь лаÑка, Ñпробуйте ще раз."
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ збережений Ñкан. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ збережені ÑкануваннÑ:"
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профіль Ñканера. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
@@ -11169,9 +11287,6 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профіль Ñайту. Будь
msgid "DastProfiles|Could not delete site profiles:"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профілі Ñайту:"
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ збережені Ñкани. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ профілі Ñканерів. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
@@ -11182,10 +11297,7 @@ msgid "DastProfiles|Could not update the scanner profile. Please try again."
msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
-msgstr ""
-
-msgid "DastProfiles|DAST Scan"
-msgstr "DAST-ÑкануваннÑ"
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ профіль Ñайту. Будь лаÑка, Ñпробуйте ще раз."
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -11200,7 +11312,7 @@ msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
-msgstr ""
+msgstr "Ви хочете ÑкаÑувати ваші зміни?"
msgid "DastProfiles|Edit profile"
msgstr "Редагувати профіль"
@@ -11245,10 +11357,10 @@ msgid "DastProfiles|Manage site profiles"
msgstr ""
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
-msgstr ""
+msgstr "Мінімум = 0 (тайм-аут не ввімкнено), МакÑимум = 2880 хвилин"
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
-msgstr ""
+msgstr "Мінімум = 1 Ñекунда, МакÑимум = 3600 Ñекунд"
msgid "DastProfiles|New scanner profile"
msgstr "Ðовий профіль Ñканера"
@@ -11259,9 +11371,6 @@ msgstr "Ðовий профіль Ñайту"
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11289,9 +11398,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr "ЗапуÑтити ÑкануваннÑ"
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11301,12 +11407,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr "Зберегти профіль"
-msgid "DastProfiles|Saved Scans"
-msgstr "Збережені ÑкануваннÑ"
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr "Режим ÑкануваннÑ"
@@ -11319,9 +11419,6 @@ msgstr "Сканувальні профілі"
msgid "DastProfiles|Scanner name"
msgstr "Ім'Ñ Ñканера"
-msgid "DastProfiles|Schedule"
-msgstr "Розклад"
-
msgid "DastProfiles|Select branch"
msgstr "Виберіть гілку"
@@ -11343,14 +11440,11 @@ msgstr "Тип Ñайту"
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr "Ціль"
-
msgid "DastProfiles|Target URL"
msgstr "Цільова URL-адреÑа"
msgid "DastProfiles|Target timeout"
-msgstr ""
+msgstr "Цільовий Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ"
msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
msgstr ""
@@ -11617,9 +11711,6 @@ msgstr "Гілка за замовчуваннÑм Ñ– захищені гілкÐ
msgid "Default branch protection"
msgstr "ЗахиÑÑ‚ гілки за замовчуваннÑм"
-msgid "Default classification label"
-msgstr "Мітка клаÑифікації за замовчуваннÑм"
-
msgid "Default delayed project deletion"
msgstr ""
@@ -12058,6 +12149,9 @@ msgstr[3] "Розгортань"
msgid "Deploy Keys"
msgstr "Ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -12073,6 +12167,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr "Хід Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ðµ знайдено. Щоб побачити pod'и, переконайтеÑÑŒ, що ваше Ñередовище відповідає %{linkStart}критеріÑм дошки розгортань%{linkEnd}."
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "Розгорнути на..."
@@ -12287,9 +12384,39 @@ msgstr[3] ""
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "Це Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтворено через API"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "відмінено"
@@ -12858,9 +12985,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr "Розпочати безкоштовну пробну верÑÑ–ÑŽ"
@@ -12928,7 +13052,7 @@ msgstr "Показати джерело"
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -13123,8 +13247,8 @@ msgstr "Редагувати коментар"
msgid "Edit Deploy Key"
msgstr "Редагувати ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
-msgid "Edit Geo Node"
-msgstr "Редагувати Гео-вузол"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr "Редагувати хук групи"
@@ -13304,7 +13428,7 @@ msgid "Email"
msgstr "Електронна пошта"
msgid "Email %{number}"
-msgstr ""
+msgstr "Електронна пошта %{number}"
msgid "Email Notification"
msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
@@ -13369,6 +13493,9 @@ msgstr "Ми не змогли визначити від імені Ñкого Ð
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "Ми не змогли знайти проєкт. Будь лаÑка, перевірте, чи немає помилок."
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Вам не дозволено виконувати цю дію. Якщо ви вважаєте, що це неправильно, звернітьÑÑ Ð´Ð¾ Ñпівробітника."
@@ -13513,9 +13640,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr "Увімкнути контроль за клаÑифікацією за допомогою зовнішньої Ñлужби"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13558,6 +13682,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "Увімкнути режим обÑлуговуваннÑ"
@@ -13585,6 +13712,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13663,9 +13796,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr "ПримуÑово активувати захиÑÑ‚ від DNS rebinding"
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13714,6 +13844,9 @@ msgstr "Введіть URL-адреÑу вашого Bitbucket Server Ñ– клюÑ
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "Введіть URL-адреÑу вашого Ñервера Phabricator Ñ– перÑональний ключ доÑтупу"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "Введіть URL-адреÑи запиту на злиттÑ"
@@ -13929,7 +14062,7 @@ msgid "Environments|Logs from %{start} to %{end}."
msgstr "Логи від %{start} до %{end}."
msgid "Environments|More information"
-msgstr ""
+msgstr "Детальніше"
msgid "Environments|New environment"
msgstr "Ðове Ñередовище"
@@ -13991,6 +14124,9 @@ msgstr "Зупинити Ñередовище"
msgid "Environments|Stopping %{environmentName}"
msgstr "Зупинка %{environmentName}"
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð»Ð¾Ð³Ñ–Ð². Будь лаÑка, Ñпробуйте ще раз."
@@ -14018,6 +14154,9 @@ msgstr ""
msgid "Environments|protected"
msgstr "захищені"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "Епік"
@@ -14805,9 +14944,6 @@ msgstr "ЕкÑпортувати змінну до конвеєрів, Ñкі п
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ ÐšÐ»Ð°ÑÐ¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÐŸÐ¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ Ðвторизації"
-
msgid "External ID"
msgstr "External ID"
@@ -14817,15 +14953,9 @@ msgstr "Зовнішній URL"
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ"
-
msgid "External authorization denied access to this project"
msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð±Ð¾Ñ€Ð¾Ð½Ð¸Ð»Ð° доÑтуп до цього проєкту"
-msgid "External authorization request timeout"
-msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на зовнішню авторизацію"
-
msgid "External storage URL"
msgstr "URL-адреÑа зовнішнього Ñховища"
@@ -14841,6 +14971,54 @@ msgstr "Мітка клаÑифікації"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Якщо клаÑифікаційну мітку не вÑтановлено, викориÑтовуватиметьÑÑ Ñтандартна мітка `%{default_label}`."
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14923,10 +15101,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15368,16 +15543,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr "СпиÑок кориÑтувачів"
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "лют."
@@ -15465,12 +15630,6 @@ msgstr "Фільтр"
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "Фільтрувати закриті за %{issuable_type}."
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15795,6 +15954,9 @@ msgstr "Знайдено помилки у вашому %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15870,6 +16032,9 @@ msgstr "Загальні налаштуваннÑ"
msgid "Generate a default set of labels"
msgstr "Створити Ñтандартний набір міток"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "Згенерувати ключ"
@@ -15906,18 +16071,21 @@ msgstr "РізницÑ"
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Гео-Вузли"
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr "Синхронізовано з%{component}"
@@ -15954,6 +16122,9 @@ msgstr "Додати Ñайт"
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr "Ð’ÑÑ– %{replicable_name}"
@@ -16008,6 +16179,9 @@ msgstr "Відкрийте Ð´Ð»Ñ Ñебе GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðевдало"
@@ -16083,12 +16257,6 @@ msgstr "ÐаÑтупна ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð° на"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr "Ім'Ñ Ð²ÑƒÐ·Ð»Ð° не може бути пуÑтим"
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронізовано"
@@ -16104,6 +16272,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr "Офлайн"
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації"
@@ -16137,16 +16308,19 @@ msgstr "Повторне завантаженнÑ"
msgid "Geo|Remove"
msgstr "Видалити"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr "Видалити запиÑ"
-msgid "Geo|Remove node"
-msgstr "Видалити вузол"
+msgid "Geo|Remove site"
+msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -16158,9 +16332,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -16209,6 +16380,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -16245,10 +16422,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16326,6 +16503,9 @@ msgstr "вторинний"
msgid "Get a free instance review"
msgstr "Отримайте безкоштовну оцінку інÑтанÑа"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16449,9 +16629,6 @@ msgstr ""
msgid "GitLab export"
msgstr "ЕкÑпорт GitLab"
-msgid "GitLab for Slack"
-msgstr "GitLab Ð´Ð»Ñ Slack"
-
msgid "GitLab group: %{source_link}"
msgstr "GitLab група : %{source_link}"
@@ -16476,6 +16653,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "УчаÑник GitLab або адреÑа електронної пошти"
@@ -16656,6 +16836,9 @@ msgstr "URL-адреÑа Gitpod"
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16750,7 +16933,7 @@ msgid "Go to environments"
msgstr "Перейти до Ñередовищ"
msgid "Go to epic"
-msgstr ""
+msgstr "Перейти до епіку"
msgid "Go to file"
msgstr "Перейти до файлу"
@@ -16765,7 +16948,7 @@ msgid "Go to find file"
msgstr "Перейти до пошуку файлів"
msgid "Go to fork"
-msgstr ""
+msgstr "Перейти до форку"
msgid "Go to issue boards"
msgstr "Перейти до дошок задач"
@@ -16794,6 +16977,9 @@ msgstr ""
msgid "Go to parent"
msgstr "Перейти на рівень вище"
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16962,6 +17148,9 @@ msgstr "Групу %{group_name} було призначено Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»
msgid "Group %{group_name} was successfully created."
msgstr "Групу %{group_name} уÑпішно Ñтворено."
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð³Ñ€ÑƒÐ¿Ð¸ Git LFS:"
@@ -16980,6 +17169,9 @@ msgstr "SAML Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ повинна бути включена Ð´Ð»Ñ Ñ
msgid "Group URL"
msgstr "URL-адреÑа групи"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -17043,9 +17235,6 @@ msgstr ""
msgid "Group jobs by"
msgstr "Групувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°"
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "Керівники групи можуть зареєÑтрувати групові runner'и через %{link}"
-
msgid "Group members"
msgstr "КориÑтувачі групи"
@@ -17070,6 +17259,9 @@ msgstr ""
msgid "Group overview content"
msgstr "ВміÑÑ‚ оглÑдової Ñторінки групи"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -17082,9 +17274,6 @@ msgstr "Групові хвилини Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² уÑпішно Ð
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr "Групові проєкти"
-
msgid "Group requires separate account"
msgstr "Група вимагає окремий обліковий запиÑ"
@@ -17242,7 +17431,7 @@ msgid "GroupSAML|Could not create SAML group link: %{errors}."
msgstr ""
msgid "GroupSAML|Default membership role"
-msgstr ""
+msgstr "Роль членÑтва за замовчуваннÑм"
msgid "GroupSAML|Enable SAML authentication for this group"
msgstr ""
@@ -17325,18 +17514,12 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу через SAML"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "URL кінцевої точки SCIM API"
-
msgid "GroupSAML|SCIM Token"
msgstr "Токен SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SHA1-відбиток Ñертифікату Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу SAML токена. Отримайте його від провайдера ідентифікації, де він також може називатиÑÑ \"Thumbprint\"."
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "Токен SCIM зараз приховоно. Щоб знову побачити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° вам потрібно "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17344,7 +17527,7 @@ msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML ide
msgstr ""
msgid "GroupSAML|This will be set as the access level of users added to the group."
-msgstr ""
+msgstr "Це буде вÑтановлено Ñк рівень доÑтупу кориÑтувачів, доданих до групи."
msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
msgstr ""
@@ -17361,9 +17544,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr "Ваш токен SCIM"
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17394,8 +17574,11 @@ msgstr "Пошук груп"
msgid "GroupSelect|Select a group"
msgstr "Вибрати групу"
-msgid "GroupSettings|Allow project access token creation"
-msgstr "Дозволити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° доÑтупу до проєкту"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
+msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
msgstr ""
@@ -17416,7 +17599,7 @@ msgid "GroupSettings|Cannot update the path because there are projects under thi
msgstr "Ðе вдалоÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ шлÑÑ… тому що в цій групі Ñ” проєкти із образами Docker у Ñвоїх РеєÑтрах контейнерів. Будь лаÑка, Ñпочатку видаліть ці образи з ваших проєктів Ñ– Ñпробуйте знову."
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "Змінити URL-адреÑу групи"
msgid "GroupSettings|Changing a group's URL can have unintended side effects."
msgstr ""
@@ -17442,6 +17625,9 @@ msgstr "Вимкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштоÑ
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17460,9 +17646,6 @@ msgstr "Згенеровано новий токен Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr "БатьківÑька група"
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² були оновлені Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
@@ -17490,9 +17673,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr "Пошук груп"
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17535,7 +17715,7 @@ msgstr "Цей параметр заÑтоÑовано до %{ancestor_group}. Ð
msgid "GroupSettings|Transfer group"
msgstr "ПеренеÑти групу"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17575,7 +17755,7 @@ msgid "Groups and projects"
msgstr "Групи та проєкти"
msgid "Groups and subgroups"
-msgstr ""
+msgstr "Групи і підгрупи"
msgid "Groups to synchronize"
msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
@@ -17616,9 +17796,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17673,7 +17850,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17906,6 +18083,33 @@ msgstr[3] "Сховати значень"
msgid "Hide values"
msgstr "Сховати значеннÑ"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr "ПриÑутні вразливоÑÑ‚Ñ– виÑокого або невідомого рівнÑ"
@@ -17966,9 +18170,6 @@ msgstr "ОчищеннÑ"
msgid "Housekeeping successfully started"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, видаленнÑ, архівуваннÑ."
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -18005,9 +18206,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr "Як це працює"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -18023,6 +18221,9 @@ msgstr "Я приймаю %{terms_link}"
msgid "I forgot my password"
msgstr "Я забув пароль"
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -18122,6 +18323,18 @@ msgstr "Ідентифікатори"
msgid "Identities"
msgstr "ІдентифікаціÑ"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -18146,9 +18359,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "Якщо це дозволено, доÑтуп до проєктів буде перевірÑтиÑÑ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾ÑŽ Ñлужбою з викориÑтаннÑм Ñ—Ñ… мітки клаÑифікації."
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18755,6 +18965,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18857,6 +19070,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18932,6 +19148,9 @@ msgstr "Інцидент"
msgid "Incident Management Limits"
msgstr "Ліміти, пов’Ñзані із УправліннÑм Інцидентами"
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19356,9 +19575,6 @@ msgstr "Додати інтеграцію"
msgid "Integrations|Add namespace"
msgstr "Додати проÑÑ‚Ñ–Ñ€ імен"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr "Ð’ÑÑ– деталі"
@@ -19371,9 +19587,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr "Деталі коментарÑ:"
@@ -19443,6 +19656,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19461,9 +19677,6 @@ msgstr "Ðемає доÑтупних проÑторів імен."
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19500,6 +19713,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19509,6 +19725,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19569,7 +19788,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21391,6 +21610,9 @@ msgstr ""
msgid "License file"
msgstr "Файл ліцензії"
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr "ПереглÑд ліцензії"
@@ -21728,9 +21950,6 @@ msgstr "ЗавантаженнÑ..."
msgid "Loading…"
msgstr "ЗавантаженнÑ…"
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr "Регіональні налаштуваннÑ"
@@ -21746,6 +21965,9 @@ msgstr "Блокувати"
msgid "Lock %{issuableDisplayName}"
msgstr "Заблокувати %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr "ЗафікÑувати належноÑÑ‚Ñ– (до груп) через LDAP Ñинхронізацію"
@@ -21782,6 +22004,39 @@ msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути заÑтоÑоване до коÐ
msgid "Locks the discussion."
msgstr "Блокує обговореннÑ."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Вхід за допомогою Ñмарт-картки"
@@ -22556,6 +22811,12 @@ msgstr "ЗалежноÑÑ‚Ñ– запиту на злиттÑ"
msgid "Merge request events"
msgstr "Події запиту на злиттÑ"
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22574,9 +22835,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "Злити, коли конвеєр уÑпішно завершитьÑÑ"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "Закомітити в гілку-джерело"
@@ -23401,9 +23671,6 @@ msgstr "МіÑÑці"
msgid "More Information"
msgstr "Більше інформації"
-msgid "More Slack commands"
-msgstr "Більше команд Slack"
-
msgid "More actions"
msgstr "Додаткові дії"
@@ -23425,9 +23692,6 @@ msgstr ""
msgid "More information."
msgstr "Докладніше."
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ñ–Ð· %{default_branch} Ñкладає більше %{number_commits_distance} комітів"
@@ -23606,10 +23870,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23634,37 +23898,37 @@ msgid "Navigation bar"
msgstr ""
msgid "NavigationTheme|Blue"
-msgstr ""
+msgstr "Синій"
msgid "NavigationTheme|Dark"
-msgstr ""
+msgstr "Темний"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "Темний режим (альфа-верÑÑ–Ñ)"
msgid "NavigationTheme|Green"
-msgstr ""
+msgstr "Зелений"
msgid "NavigationTheme|Indigo"
-msgstr ""
+msgstr "Індиго"
msgid "NavigationTheme|Light"
-msgstr ""
+msgstr "Світлий"
msgid "NavigationTheme|Light Blue"
-msgstr ""
+msgstr "Світло-Cиній"
msgid "NavigationTheme|Light Green"
-msgstr ""
+msgstr "Світло-Зелений"
msgid "NavigationTheme|Light Indigo"
-msgstr ""
+msgstr "Світло-індиго"
msgid "NavigationTheme|Light Red"
-msgstr ""
+msgstr "Світло-Червоний"
msgid "NavigationTheme|Red"
-msgstr ""
+msgstr "Червоний"
msgid "Nav|Help"
msgstr "Допомога"
@@ -23714,9 +23978,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ".yaml"
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23795,9 +24056,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23816,9 +24074,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -24336,6 +24591,9 @@ msgstr "Етап відÑутній"
msgid "No milestones to show"
msgstr "Ðемає етапів Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Ðемає інших міток з таким іменем або опиÑом"
@@ -24363,6 +24621,9 @@ msgstr "Ðемає пріоритетних міток з таким іменеÐ
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24429,8 +24690,8 @@ msgstr "ВразливоÑÑ‚Ñ– відÑутні"
msgid "No webhook events"
msgstr "Ðемає подій вебхука"
-msgid "No webhooks found, add one in the form above."
-msgstr "Ðе знайдено жодного вебхука, додайте його у формі вище."
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -25273,7 +25534,7 @@ msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰Ð¸Ð»Ð° ліміт очікуваннÑ. Перевірте журнал pod'а %{pod_name} Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації."
msgid "Operations"
-msgstr ""
+msgstr "Операції"
msgid "Operations Dashboard"
msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми"
@@ -25350,8 +25611,29 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
-msgstr "Вихідні запити"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
@@ -25969,9 +26251,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr "Патч Ð´Ð»Ñ Ð·Ð°ÑтоÑуваннÑ"
@@ -26110,6 +26389,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -26128,8 +26410,8 @@ msgstr "Права доÑтупу"
msgid "Permissions Help"
msgstr "Довідка щодо дозволів"
-msgid "Permissions, LFS, 2FA"
-msgstr "Дозволи, LFS, 2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "Токену перÑонального доÑтупу"
@@ -26395,9 +26677,6 @@ msgstr "Конвеєри"
msgid "Pipelines charts"
msgstr "СтатиÑтика конвеєрів"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr "Конвеєри Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚Ð¾Ð²Ð°Ð½Ð¾. Відділений конвеєр виконуєтьÑÑ Ð² контекÑÑ‚Ñ– запиту на злиттÑ, але не в контекÑÑ‚Ñ– результату злиттÑ. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ в документації про конвеєери Ð´Ð»Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ–Ð² злиттÑ."
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² Ð´Ð»Ñ \"%{project_name}\" уÑпішно оновлено."
@@ -26410,6 +26689,9 @@ msgstr "Додати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ ÑкоÑÑ‚Ñ– коду"
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "Ви впевнені, що хочете запуÑтити цей конвеєр?"
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "Виконуйте збірки із впевненіÑÑ‚ÑŽ"
@@ -26422,8 +26704,8 @@ msgstr "Перевірка конфігурації"
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
-msgstr "Дочірній конвеєр"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
msgid "Pipelines|Clear runner caches"
msgstr "ОчиÑтити кеш runner"
@@ -26587,11 +26869,29 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr "ВізуалізаціÑ"
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
-msgstr "БатьківÑька"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "Дії"
@@ -26773,6 +27073,9 @@ msgstr "План"
msgid "Plan:"
msgstr "План:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26788,6 +27091,12 @@ msgstr "ЗапуÑтити вÑÑ– ручні завданнÑ"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Будь лаÑка, %{link_to_register} або %{link_to_sign_in} щоб прокоментувати"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "Буль лаÑка, %{startTagRegister}зареєÑтруйтеÑÑ%{endRegisterTag} або %{startTagSignIn}увійдіть%{endSignInTag}, щоб відповіÑти"
@@ -27142,6 +27451,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡Ð°Ñу"
msgid "Preferences|Use relative times"
msgstr "ВикориÑтовувати відноÑний чаÑ"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "Ðазад"
@@ -27367,6 +27679,9 @@ msgstr "Обрізка аватарів"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Ðватар буде видалено. Ви впевнені?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "Про Ñебе"
@@ -27391,9 +27706,6 @@ msgstr "МіÑто, країна"
msgid "Profiles|Clear status"
msgstr "ОчиÑтити ÑтатуÑ"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Клікніть на іконку, щоб активувати вхід за допомогою одного із наÑтупних ÑервіÑів"
-
msgid "Profiles|Commit email"
msgstr "ÐдреÑа електронної пошти Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²"
@@ -27571,6 +27883,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr "Видалити аватар"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "Ð’Ñтановити нове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
@@ -27616,9 +27931,6 @@ msgstr "Двофакторна автентифікаціÑ"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введіть ваш %{confirmationValue} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "Як правило починаєтьÑÑ Ð· \"ssh-ed25519 …\" або \"ssh-rsa …\""
-
msgid "Profiles|Update profile settings"
msgstr "Оновити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
@@ -28141,10 +28453,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "Виберіть метод злиттÑ, Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° пропозиції щодо злиттÑ."
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -28222,6 +28537,12 @@ msgstr "Глобальні"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Внутрішні"
@@ -28267,6 +28588,9 @@ msgstr "Запити на злиттÑ"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28393,9 +28717,6 @@ msgstr "Цей параметр заÑтоÑовуєтьÑÑ Ð½Ð° рівні ÑÐ
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Цей параметр буде заÑтоÑовано до вÑÑ–Ñ… проєктів, Ñкщо адмініÑтратор не змінить його."
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr "ПеренеÑти проєкт"
@@ -28417,7 +28738,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28435,7 +28756,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -29197,9 +29518,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "Публічні ключі Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ (%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "Публічні конвеєри"
@@ -29233,7 +29551,7 @@ msgstr "Придбати більше хвилин"
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29479,6 +29797,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29548,6 +29872,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr "Знизити видиміÑÑ‚ÑŒ проєкту"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "Знизити видиміÑÑ‚ÑŒ проєкту?"
@@ -29624,7 +29951,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -30170,6 +30497,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30400,6 +30734,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "Сховище репозиторію"
@@ -30475,9 +30812,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30496,6 +30830,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Вимогу %{reference} було додано"
@@ -30627,9 +30964,6 @@ msgstr "Вирішено"
msgid "Resolved by %{name}"
msgstr "Вирішено %{name}"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr "Визначає IP-адреÑи один раз Ñ– викориÑтовує Ñ—Ñ… Ð´Ð»Ñ Ð²Ñ–Ð´Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð²"
-
msgid "Response"
msgstr "Відповідь"
@@ -30696,7 +31030,7 @@ msgstr "Продовжити"
msgid "Resync"
msgstr "Повторна ÑинхронізаціÑ"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30800,15 +31134,15 @@ msgstr "Відкликати"
msgid "Revoked"
msgstr "Відкликано"
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "Відкликано токен Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Відкликано перÑональний токен доÑтупу %{personal_access_token_name}!"
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr ""
-
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -30827,6 +31161,9 @@ msgstr ""
msgid "Roadmap"
msgstr "План-графік"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "Роль"
@@ -30914,6 +31251,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr "Ðрхітектура"
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30926,9 +31266,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30947,6 +31293,9 @@ msgstr ""
msgid "Runners|Description"
msgstr "ОпиÑ"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr "Завантажити та вÑтановити бінарний файл"
@@ -30962,9 +31311,6 @@ msgstr ""
msgid "Runners|Group"
msgstr "Група"
-msgid "Runners|Group Runners"
-msgstr "Групові Runner'и"
-
msgid "Runners|IP Address"
msgstr "IP-адреÑа"
@@ -31013,10 +31359,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -31052,6 +31401,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
@@ -31091,18 +31443,18 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Runner'и"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
-msgstr ""
-
msgid "Runners|Show runner installation and registration instructions"
msgstr "Показати інÑтрукції Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° реєÑтрації runner"
+msgid "Runners|Show runner installation instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -31112,6 +31464,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr "СтатуÑ"
@@ -31127,9 +31482,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr "Цей runner пов'Ñзаний з одним або кількома проєктами."
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -31283,9 +31635,6 @@ msgstr "Перевірка SSL:"
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31412,9 +31761,6 @@ msgstr "Пошук"
msgid "Search GitLab"
msgstr "Пошук в GitLab"
-msgid "Search Jira issues"
-msgstr "Пошук задач Jira"
-
msgid "Search a group"
msgstr ""
@@ -31738,7 +32084,7 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Vulnerity-Check"
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31870,6 +32216,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31924,6 +32273,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31942,21 +32294,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr "Політики"
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr "ÐžÐ¿Ð¸Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸"
msgid "SecurityOrchestration|Policy editor"
msgstr "Редактор політики"
-msgid "SecurityOrchestration|Policy preview"
-msgstr ""
-
msgid "SecurityOrchestration|Policy status"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸"
+msgid "SecurityOrchestration|Policy summary"
+msgstr ""
+
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31966,12 +32327,21 @@ msgstr "Правила"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31999,6 +32369,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr "СтатуÑ"
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -32014,12 +32390,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -32029,6 +32453,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -32350,9 +32777,6 @@ msgstr "Виберіть формат архіву"
msgid "Select Git revision"
msgstr "Вибрати ревізію Git"
-msgid "Select GitLab project to link with your Slack team"
-msgstr "Виберіть проєкт GitLab Ð´Ð»Ñ Ð·Ð²â€™ÑÐ·ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð· вашою командою Slack"
-
msgid "Select Page"
msgstr "Вибрати Ñторінку"
@@ -32740,8 +33164,8 @@ msgstr "Service Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
-msgstr "URL ÑервіÑу"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr ""
@@ -32749,6 +33173,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32758,18 +33185,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32908,7 +33329,7 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -33083,9 +33504,6 @@ msgstr "Скинути хвилини в конвеєрі"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Обнулити викориÑтані хвилини в конвеєрі"
-msgid "Sherlock Transactions"
-msgstr "Sherlock транзакції"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -33125,6 +33543,9 @@ msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -33137,6 +33558,9 @@ msgstr "Показати архівовані проєкти"
msgid "Show archived projects only"
msgstr "Показувати лише архівовані проєкти"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "Показати команду"
@@ -33149,9 +33573,6 @@ msgstr ""
msgid "Show comments only"
msgstr "Показати тільки коментарі"
-msgid "Show commit description"
-msgstr "Показати Ð¾Ð¿Ð¸Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ"
-
msgid "Show complete raw log"
msgstr "Показати повний неформатований журнал"
@@ -33176,6 +33597,9 @@ msgstr "Показати ÑпиÑок"
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -33220,7 +33644,7 @@ msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÑƒÑÑ–Ñ… задач"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -33313,6 +33737,9 @@ msgstr "Вийти Ñ– зареєÑтруватиÑÑ"
msgid "Sign up"
msgstr "ЗареєеÑтруватиÑÑ"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð° уÑпішно! Будь лаÑка, підтвердіть Ñвою адреÑу електронної пошти Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ."
@@ -33415,9 +33842,33 @@ msgstr "заÑтоÑунок Slack"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "Slack Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ‚ÑŒ вам взаємодіÑти з GitLab через чат за домогою команд зі Ñлешем ( / )."
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33724,9 +34175,6 @@ msgstr "ЩоÑÑŒ пішло не так. Будь лаÑка Ñпробуйте
msgid "Something went wrong. Try again later."
msgstr "ЩоÑÑŒ пішло не так. Спробуйте пізніше."
-msgid "Sorry, no epics matched your search"
-msgstr "Вибачте, жоден епік не задовольнÑÑ” критеріÑм вашого пошуку"
-
msgid "Sorry, no projects matched your search"
msgstr "Ðа жаль жоден проєкт не задовольнÑÑ” критеріÑм вашого пошуку"
@@ -33790,9 +34238,6 @@ msgstr "ОÑтанній контакт"
msgid "SortOptions|Last created"
msgstr "ОÑтанній Ñтворений"
-msgid "SortOptions|Last updated"
-msgstr "ОÑтанній оновлений"
-
msgid "SortOptions|Least popular"
msgstr "Ðайменш популÑрний"
@@ -34076,7 +34521,7 @@ msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon.
msgstr "Перейдіть до Ñторінки проєкту та натиÑніть іконку із зірочкою. Тоді цей проєкт з’ÑвитьÑÑ Ð½Ð° цій Ñторінці."
msgid "StarredProjectsEmptyState|You don't have starred projects yet."
-msgstr "Ви не маєте проєктів доданих у обране."
+msgstr "Ви не маєте проєктів доданих в обране."
msgid "Starrers"
msgstr "Додали в обране"
@@ -34126,6 +34571,9 @@ msgstr "Створити ланцюжок змін"
msgid "Start merge train when pipeline succeeds"
msgstr "Створити ланцюжок змін піÑÐ»Ñ ÑƒÑпішного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°"
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "Розпочати пошук"
@@ -34168,6 +34616,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr "Регіон/ОблаÑÑ‚ÑŒ/МіÑто"
@@ -34510,6 +34961,9 @@ msgstr "Ви підпиÑані"
msgid "Subscribed to this %{quick_action_target}."
msgstr "ПідпиÑано на %{quick_action_target}."
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr "ПідпиÑує на %{quick_action_target}."
@@ -34540,6 +34994,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34618,9 +35093,6 @@ msgstr "Дата Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð½Ð¾Ñ— верÑÑ–Ñ—"
msgid "SubscriptionTable|Trial start date"
msgstr "Дата початку пробної верÑÑ–Ñ—"
-msgid "SubscriptionTable|Upgrade"
-msgstr "Підвищити"
-
msgid "SubscriptionTable|Usage"
msgstr "ВикориÑтаннÑ"
@@ -34789,9 +35261,6 @@ msgstr ""
msgid "Sunday"
msgstr "ÐеділÑ"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34816,6 +35285,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34855,6 +35327,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34909,6 +35384,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34921,6 +35399,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "Підтримка"
@@ -35164,6 +35651,9 @@ msgstr "Цільова гілка"
msgid "Target-Branch"
msgstr "Цільова гілка"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -35236,6 +35726,9 @@ msgstr "Угода про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ– політика кон
msgid "Terms of Service and Privacy Policy"
msgstr "Правилами кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політика конфіденційноÑÑ‚Ñ–"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr "Terraform"
@@ -35414,6 +35907,9 @@ msgstr "ТеÑÑ‚"
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
@@ -35590,9 +36086,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Група \"%{group_path}\" дозволÑÑ” увійти за допомогою облікового запиÑу єдиного входу"
-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 ""
@@ -35633,12 +36126,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35648,9 +36135,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "Сертифікат X509 викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð½Ð¾Ñ— перевірки автентичноÑÑ‚Ñ– TLS Ñ– необхідний Ð´Ð»Ñ Ð·Ð²'Ñзку з зовнішньою Ñлужбою авторизації. Якщо залишити порожнім, Ñертифікат Ñервера буде перевірÑтиÑÑŒ при доÑтупі через HTTPS."
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35684,7 +36168,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35853,6 +36337,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35928,9 +36415,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "Пароль, Ñкий потрібен Ð´Ð»Ñ Ð´ÐµÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð³Ð¾ ключа. Він Ñ” необов’Ñзковим Ñ– зберігаєтьÑÑ Ñƒ зашифрованому виглÑді."
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35946,9 +36430,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "Приватний ключ, Ñкий викориÑтовуєтьÑÑ Ð¿Ñ€Ð¸ наданні клієнтÑького Ñертифіката. Його Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð°ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¾."
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -36318,7 +36799,7 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні %{replicableType
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -36369,7 +36850,7 @@ msgstr "Помилка при Ñкиданні хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36453,9 +36934,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Ð¦Ñ %{issuableDisplayName} заблокована. Лише учаÑники проєкту можуть коментувати."
@@ -36579,6 +37057,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36618,9 +37099,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Цей епік не Ñ–Ñнує або у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтатніх дозволів."
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr "Ð¦Ñ Ñ„ÑƒÐ½Ñ†Ñ–Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ–ÑÑ‚ÑŒ вимагає ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñховища"
@@ -36660,9 +37138,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36882,6 +37366,9 @@ msgstr "Цей конвеєр був ініційований розкладом
msgid "This project"
msgstr "Цей проєкт"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36903,6 +37390,9 @@ msgstr "Цей проєкт заархівовано і його не можна
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36942,6 +37432,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr "Цей параметр можна перевизначати Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ проєкту."
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "Це підпиÑка длÑ"
@@ -37170,9 +37663,6 @@ msgstr "Ð§Ð°Ñ Ð²Ñ–Ð´ оÑтаннього коміту до злиттÑ"
msgid "Time in seconds"
msgstr "Ð§Ð°Ñ Ð² Ñекундах"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "Ð§Ð°Ñ Ð² Ñекундах, протÑгом Ñкого GitLab чекатиме відповіді від зовнішньої Ñлужби. Якщо вона не відповіÑÑ‚ÑŒ вчаÑно, доÑтуп буде заборонений."
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -37424,9 +37914,6 @@ msgstr "Щоб отримати доÑтуп до цього домену, ÑÑ‚Ð
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додати ключ SSH вам необхідно %{generate_link_start}згенерувати його%{link_end} або викориÑтати %{existing_link_start}Ñ–Ñнуючий ключ%{link_end}."
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Щоб додати Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ, надайте наÑтупні відомоÑÑ‚Ñ– заÑтоÑунку у вашому телефоні."
@@ -37568,9 +38055,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37586,9 +38070,6 @@ msgstr "Щоб розширити пошук, змініть або видалі
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr "Щоб розширити пошук, змініть або видаліть фільтри."
-
msgid "To-Do List"
msgstr "СпиÑок нагадувань"
@@ -37796,9 +38277,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr "ВідÑтежуйте Ñ‡Ð°Ñ Ð·Ð° допомогою швидких дій"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr "ВідÑтежуйте Ñвої проєкти GitLab за допомогою GitLab Ð´Ð»Ñ Slack."
-
msgid "Training mode"
msgstr ""
@@ -37911,6 +38389,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37926,15 +38407,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -38001,6 +38476,12 @@ msgstr "Тригер уÑпішно оновлено."
msgid "Triggerer"
msgstr "Запущено"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "УÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÐ¿Ð¾Ð»Ð°Ð´Ð¾Ðº Ñ– моніторинг вашого заÑтоÑунку за допомогою відÑтеженнÑ"
@@ -38520,6 +39001,9 @@ msgstr "Оновлено"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Оновлено %{updated_at} %{updated_by}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "ОновленнÑ"
@@ -38541,6 +39025,9 @@ msgstr "Перейти на вищий тарифний план"
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Завантажити CSV файл"
@@ -38976,6 +39463,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39507,6 +39997,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "ПереглÑнути документацію"
@@ -39660,6 +40162,9 @@ msgstr[3] ""
msgid "View replaced file @ "
msgstr "ПереглÑд заміненого файлу @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39885,6 +40390,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "Додаткова інформаціÑ"
@@ -39927,6 +40435,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Дані"
@@ -39945,6 +40456,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "Ідентифікатори"
@@ -39954,6 +40471,9 @@ msgstr "Образ"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "ПоÑиланнÑ"
@@ -39966,6 +40486,9 @@ msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Vulnerability|Project"
msgstr "Проєкт"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39978,6 +40501,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -40002,9 +40528,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -40185,127 +40720,127 @@ msgstr "Веб-хуки"
msgid "Webhooks Help"
msgstr "Допомога по веб-хукам"
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
-msgstr "Події конвеєрів"
-
-msgid "Webhooks|Push events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|URL"
-msgstr "URL-адреÑа"
-
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Pipeline events"
+msgstr "Події конвеєрів"
+
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL"
+msgstr "URL-адреÑа"
+
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -40413,11 +40948,11 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Якщо залишити URL порожнім, можна вÑтановлювати мітки клаÑифікації без Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¹ проєкту та Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ñ— авторизації."
+msgid "When inactive, an external authentication provider must be used."
+msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
@@ -40726,7 +41261,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40828,6 +41369,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40861,6 +41405,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” повноважень на Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¾Ñ— дії"
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40909,6 +41456,9 @@ msgstr "Ви також можете протеÑтувати ваш %{gitlab_ci
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Також ви можете завантажувати файли з вашого комп'ютера за допомогою нижченаведених інÑтрукцій."
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40954,6 +41504,9 @@ msgstr "Ви можете легко робити внеÑки до них, за
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -41089,6 +41642,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу залишити це %{namespaceType}."
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "Ви не маєте дозволу запуÑкати Веб-термінал. Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора проєкту."
@@ -41183,6 +41739,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -41222,7 +41781,7 @@ msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– пр
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -41237,6 +41796,9 @@ msgstr "Ви залишили \"%{membershipable_human_name}\" %{source_type}."
msgid "You may close the milestone now."
msgstr "Зараз ви можете закрити цей етап."
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41618,8 +42180,8 @@ msgstr "Ваше ім'Ñ"
msgid "Your new %{type}"
msgstr "Ваш новий %{type}"
-msgid "Your new SCIM token"
-msgstr "Ваш новий токен SCIM"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr ""
@@ -41627,9 +42189,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr "Ваш новий перÑональний токен доÑтупу Ñтворено."
-msgid "Your new project access token has been created."
-msgstr "Ваш новий токен доÑтупу до проєкту було Ñтворено."
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "Ваш пароль не потрібен Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñторінки. Якщо вимагаєтьÑÑ Ð²Ð²ÐµÑти пароль або будь-Ñкі інші оÑобиÑÑ‚Ñ– дані, зв’ÑжітьÑÑ Ð·Ñ– Ñвоїм адмініÑтратором, щоб повідомити про порушеннÑ."
@@ -41696,6 +42255,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr "Термін дії вашої підпиÑки закінчивÑÑ!"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41830,6 +42392,13 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "approved by: "
msgstr "затверджено кориÑтувачем: "
@@ -41915,6 +42484,9 @@ msgstr "не може бути змінено Ñкщо в реєÑтрі конÑ
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -42293,6 +42865,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42320,12 +42895,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -42457,6 +43026,9 @@ msgstr "невдало"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr "не вдалоÑÑ Ð²Ñ–Ð´Ñ…Ð¸Ð»Ð¸Ñ‚Ð¸ пов’Ñзану знахідку(id=%{finding_id}): %{message}"
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42507,6 +43079,12 @@ msgstr ""
msgid "group"
msgstr "група"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "учаÑники групи"
@@ -42625,6 +43203,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42721,9 +43302,6 @@ msgstr "завантаженнÑ"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
-msgid "log in"
-msgstr "увійти"
-
msgid "manual"
msgstr "вручну"
@@ -42767,9 +43345,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "Будь лаÑка відновіть Ñ—Ñ— або викориÑтовуйте іншу %{missingBranchName} гілку"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42894,8 +43469,8 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
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} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою командного Ñ€Ñдка"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
@@ -42943,6 +43518,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
@@ -42997,6 +43575,9 @@ msgstr "Відкрити у Web IDE"
msgid "mrWidget|Plain diff"
msgstr "ПроÑте порівнÑÐ½Ð½Ñ (diff)"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Можливе автоматичне злиттÑ. ЗвернітьÑÑ Ð´Ð¾ когоÑÑŒ із правами на Ð·Ð°Ð¿Ð¸Ñ Ñƒ цей репозиторій Ð´Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ"
@@ -43042,6 +43623,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "Зміни були злиті в"
@@ -43051,9 +43635,6 @@ msgstr "Зміни не були злиті в"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr "Гілку-джерело видалено"
@@ -43090,9 +43671,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr "Ваш пароль"
-msgid "mrWidget|branch does not exist."
-msgstr "гілка не Ñ–Ñнує."
-
msgid "mrWidget|into"
msgstr "в"
@@ -43383,9 +43961,6 @@ msgstr "репозиторій:"
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr "Ñкинути його."
-
msgid "satisfied"
msgstr "задоволено"
@@ -43566,9 +44141,6 @@ msgstr "аватар кориÑтувача"
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index dcc18474ef3..aecaf9bd0db 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:43\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index d4cdc3f7fd4..8230fa9108a 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: 2022-01-06 17:24\n"
+"PO-Revision-Date: 2022-02-02 15:48\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -461,6 +481,12 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -626,6 +652,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -722,6 +751,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -731,6 +763,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -841,9 +876,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -876,6 +908,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1832,21 +1867,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1871,9 +1897,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1979,9 +2002,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1991,7 +2011,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -2006,6 +2026,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -2072,6 +2095,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2189,9 +2215,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2489,6 +2512,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2645,6 +2674,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2681,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2807,6 +2839,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2870,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2972,7 +3010,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3533,22 +3571,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3659,9 +3688,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3809,16 +3835,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4374,9 +4397,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4407,9 +4427,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4419,13 +4436,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4452,7 +4469,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4467,6 +4484,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4482,7 +4502,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4494,22 +4514,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4623,6 +4649,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4715,9 +4744,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4802,7 +4828,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5244,6 +5270,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5376,6 +5405,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5403,6 +5435,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5418,9 +5453,6 @@ 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 ""
@@ -5457,9 +5489,6 @@ 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 ""
@@ -5538,9 +5567,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5619,6 +5654,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5931,18 +5969,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5958,9 +5990,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -6009,15 +6038,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -6036,9 +6056,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6234,6 +6251,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6299,9 +6325,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6536,6 +6574,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6915,6 +6956,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -7092,6 +7136,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7392,15 +7439,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7497,6 +7535,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7521,7 +7565,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7566,7 +7610,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7596,7 +7640,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7653,13 +7697,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7686,7 +7733,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7713,6 +7760,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7725,6 +7784,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7748,7 +7810,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7766,6 +7828,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8716,6 +8781,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8965,6 +9033,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8995,6 +9066,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -9040,12 +9117,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -9073,12 +9153,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9637,7 +9723,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9778,9 +9864,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9793,9 +9894,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9868,6 +9966,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9895,13 +9996,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -10045,6 +10149,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10303,6 +10410,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10537,6 +10647,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10769,6 +10882,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10778,10 +10894,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10871,12 +10987,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10889,9 +10999,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10904,9 +11011,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10979,9 +11083,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -11009,9 +11110,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -11021,12 +11119,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -11039,9 +11131,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -11063,9 +11152,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11335,9 +11421,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11764,6 +11847,9 @@ msgstr[1] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11779,6 +11865,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11991,9 +12080,39 @@ msgstr[1] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12554,9 +12673,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12622,7 +12738,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12817,7 +12933,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -13063,6 +13179,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13207,9 +13326,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13252,6 +13368,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13279,6 +13398,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13357,9 +13482,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13408,6 +13530,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13683,6 +13808,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13710,6 +13838,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14495,9 +14626,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14507,15 +14635,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14531,6 +14653,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14611,10 +14781,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -15054,14 +15221,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -15149,12 +15308,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15479,6 +15632,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15554,6 +15710,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15590,18 +15749,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15638,6 +15800,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15692,6 +15857,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15767,12 +15935,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15788,6 +15950,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15821,16 +15986,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15842,9 +16010,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15893,6 +16058,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15929,10 +16100,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -16010,6 +16181,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -16133,9 +16307,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16160,6 +16331,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16340,6 +16514,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16478,6 +16655,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16646,6 +16826,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16664,6 +16847,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16727,9 +16913,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16754,6 +16937,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16766,9 +16952,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -17009,18 +17192,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -17045,9 +17222,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -17078,7 +17252,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -17126,6 +17303,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -17144,9 +17324,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17174,9 +17351,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17219,7 +17393,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17300,9 +17474,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17357,7 +17528,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17586,6 +17757,33 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17646,9 +17844,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17685,9 +17880,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17703,6 +17895,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17802,6 +17997,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17826,9 +18033,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18429,6 +18633,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18531,6 +18738,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18606,6 +18816,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -19028,9 +19241,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -19043,9 +19253,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -19115,6 +19322,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -19133,9 +19343,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19172,6 +19379,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19181,6 +19391,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19241,7 +19454,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -21061,6 +21274,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21384,9 +21600,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21402,6 +21615,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21438,6 +21654,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22212,6 +22461,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22230,9 +22485,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -23053,9 +23317,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -23077,9 +23338,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23256,10 +23514,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23364,9 +23622,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23445,9 +23700,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23466,9 +23718,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23984,6 +24233,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -24011,6 +24263,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -24077,7 +24332,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24986,7 +25241,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25603,9 +25879,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25744,6 +26017,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25762,7 +26038,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -26029,9 +26305,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -26044,6 +26317,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -26056,7 +26332,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26221,10 +26497,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26407,6 +26701,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26422,6 +26719,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26776,6 +27079,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -27001,6 +27307,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -27025,9 +27334,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27205,6 +27511,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27250,9 +27559,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27775,10 +28081,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27856,6 +28165,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27901,6 +28216,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -28027,9 +28345,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -28051,7 +28366,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -28069,7 +28384,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28831,9 +29146,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28867,7 +29179,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -29113,6 +29425,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -29182,6 +29500,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29256,7 +29577,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29796,6 +30117,11 @@ msgid_plural "Reports|Accessibility scanning detected %d issues for the source b
msgstr[0] ""
msgstr[1] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -30022,6 +30348,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -30097,9 +30426,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -30118,6 +30444,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30245,9 +30574,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30314,7 +30640,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30414,13 +30740,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30441,6 +30767,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30528,6 +30857,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30540,9 +30872,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30561,6 +30899,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30576,9 +30917,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30627,10 +30965,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30666,6 +31007,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30705,16 +31049,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30726,6 +31070,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30741,9 +31088,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30897,9 +31241,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31026,9 +31367,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31330,7 +31668,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31462,6 +31800,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31516,6 +31857,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31534,21 +31878,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31558,12 +31911,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31591,6 +31953,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31606,12 +31974,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31621,6 +32037,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31942,9 +32361,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32332,7 +32748,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32341,6 +32757,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32350,18 +32769,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32500,7 +32913,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32673,9 +33086,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32715,6 +33125,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32727,6 +33140,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32739,9 +33155,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32766,6 +33179,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32806,7 +33222,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32899,6 +33315,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -33001,9 +33420,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33310,9 +33753,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33376,9 +33816,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33712,6 +34149,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33754,6 +34194,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -34096,6 +34539,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -34126,6 +34572,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34204,9 +34671,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34375,9 +34839,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34402,6 +34863,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34441,6 +34905,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34495,6 +34962,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34507,6 +34977,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34750,6 +35229,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34822,6 +35304,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34992,6 +35477,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -35164,9 +35652,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -35205,12 +35690,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35220,9 +35699,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35256,7 +35732,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35423,6 +35899,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35498,9 +35977,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35516,9 +35992,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35888,7 +36361,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35939,7 +36412,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -36023,9 +36496,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -36149,6 +36619,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -36188,9 +36661,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36230,9 +36700,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36452,6 +36928,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36473,6 +36952,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36512,6 +36994,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36740,9 +37225,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36990,9 +37472,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -37134,9 +37613,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -37152,9 +37628,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37362,9 +37835,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37475,6 +37945,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37490,15 +37963,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37565,6 +38032,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -38084,6 +38557,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -38105,6 +38581,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38540,6 +39019,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -39071,6 +39553,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -39218,6 +39712,9 @@ msgstr[1] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39443,6 +39940,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39485,6 +39985,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39503,6 +40006,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39512,6 +40021,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39524,6 +40036,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39536,6 +40051,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39560,9 +40078,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39743,127 +40270,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39971,10 +40498,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40282,7 +40809,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40384,6 +40917,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40417,6 +40953,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40465,6 +41004,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40510,6 +41052,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40645,6 +41190,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40737,6 +41285,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40776,7 +41327,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40791,6 +41342,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -41172,7 +41726,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -41181,9 +41735,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41250,6 +41801,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41380,6 +41934,11 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "approved by: "
msgstr ""
@@ -41463,6 +42022,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41835,6 +42397,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41862,12 +42427,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41995,6 +42554,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -42041,6 +42603,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -42157,6 +42725,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42253,9 +42824,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42297,9 +42865,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42422,7 +42987,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42469,6 +43034,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42523,6 +43091,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42568,6 +43139,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42577,9 +43151,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42616,9 +43187,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42899,9 +43467,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -43082,9 +43647,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 3fc58c5a26d..5656fc481a5 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: 2022-01-06 17:19\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -645,6 +670,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr ""
msgid "Add CONTRIBUTING"
msgstr ""
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1875,7 +1891,7 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr ""
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr ""
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr ""
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 25d863b5e63..1c60ebc9ab5 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] "%d 个网å€å·²æ‰«æ"
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%dä½æ ¸å‡†äºº"
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] "%{bold_start}%{count}%{bold_end} 个开放中的åˆå¹¶è¯·æ±‚"
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}éšè—:%{code_close} éšè—在作业日志中。必须符åˆéšè—è¦æ±‚。"
@@ -487,7 +509,7 @@ msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last
msgstr "%{description}- Sentry事件: %{errorUrl}- 首次出现: %{firstSeen}- 最åŽå‡ºçŽ°: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
-msgstr ""
+msgstr "%{doc_link_start}高级æœç´¢%{doc_link_end}ç¦ç”¨ï¼Œå› ä¸º %{ref_elem} ä¸æ˜¯é»˜è®¤åˆ†æ”¯ã€‚ %{docs_link}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}高级æœç´¢%{doc_link_end} å·²å¯ç”¨ã€‚"
@@ -549,6 +571,9 @@ msgstr "%{group_name} 动æ€"
msgid "%{group_name} group members"
msgstr "%{group_name}群组æˆå‘˜"
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name}使用由群组托管å¸æˆ·ã€‚您需è¦åˆ›å»ºä¸€ä¸ªæ–°çš„GitLabå¸æˆ·ï¼Œè¯¥å¸æˆ·å°†é€šè¿‡%{group_name}组æ¥ç®¡ç†ã€‚"
@@ -645,6 +670,9 @@ msgstr "%{level_name} ä¸å…许在 %{group_level_name} 组。"
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "由于派生的æºé¡¹ç›®å¯è§æ€§è¾ƒä½Žï¼Œå› æ­¤ä¸å…许使用%{level_name}。"
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr "%{link_start}查看更多%{link_end} 关于角色的信æ¯ã€‚"
@@ -654,6 +682,9 @@ msgstr "%{link_start}从标题中删除%{draft_snippet}å‰ç¼€%{link_end},å…è®
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr "使用 %{link_start} %{draft_snippet}%{link_end} 开始标题,以防止åˆå¹¶è¯·æ±‚è‰ç¨¿åœ¨å‡†å¤‡å°±ç»ªä¹‹å‰åˆå¹¶ã€‚"
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}GitLab Inc. 收集哪些信æ¯ï¼Ÿ%{link_end}"
@@ -763,9 +794,6 @@ msgstr "%{placeholder}ä¸æ˜¯æœ‰æ•ˆçš„主题"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr "%{policy_link} (在 %{elapsed_time} 分钟åŽå‘出通知, 除éžçŠ¶æ€ä¸º %{status})"
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr "%{project_path} 是一个项目,您å¯ä»¥ä½¿ç”¨è¯¥é¡¹ç›®å°†è‡ªè¿°æ–‡ä»¶æ·»åŠ åˆ°æ‚¨çš„ GitLab é…置文件中,创建一个公共项目并使用 README åˆå§‹åŒ–仓库以开始使用。 %{help_link_start}了解更多。%{help_link_end}"
@@ -797,6 +825,9 @@ msgstr "%{rotation} 已与其余å‚与者é‡æ–°è®¡ç®—。请审查 %{rotation_lin
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 "%{rotation} 已与其余å‚与者é‡æ–°è®¡ç®—。请审查 %{rotation} 的新设置。建议您与目å‰çš„on-call人员å–å¾—è”系,以确ä¿on-call工作的连续性。"
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr "'%{term}' 的结果 %{scope} "
@@ -1072,7 +1103,7 @@ msgid "(max size 15 MB)"
msgstr "(最大 15 MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(å¯é€‰)"
msgid "(removed)"
msgstr "(已删除)"
@@ -1716,21 +1747,12 @@ msgstr "该令牌无法用于访问其它数æ®ã€‚"
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr "将此令牌ä¿å¯†ã€‚任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·è®¿é—®ä»“库é™æ€å¯¹è±¡ã€‚如果å‘生,%{linkStart}é‡ç½®æ­¤ä»¤ç‰Œ%{linkEnd}。"
-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 "请确ä¿è¯¥ä»¤ç‰Œçš„安全。任何æŒæœ‰è¯¥ä»¤ç‰Œçš„人,都å¯ä»¥ä»¥æ‚¨çš„身份æ¥åˆ›å»ºè®®é¢˜ã€‚如果令牌泄露,您应该%{reset_link_start}é‡ç½®ä»¤ç‰Œ %{reset_link_end} 。"
-
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr "将此令牌ä¿å¯†ã€‚任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·åˆ›å»ºè®®é¢˜ã€‚如果å‘生,%{linkStart}é‡ç½®æ­¤ä»¤ç‰Œ%{linkEnd}。"
-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 "将此令牌ä¿å¯†ã€‚任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·åˆ›å»ºè®®é¢˜ã€‚如果å‘生这ç§æƒ…况, %{link_reset_it}。"
-
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, %{linkStart}reset this token%{linkEnd}."
msgstr "将此令牌ä¿å¯†ã€‚任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·è¯»å–动æ€å¹¶å‘布 RSS feeds 或您的日历 feed。如果å‘生,%{linkStart}é‡ç½®æ­¤ä»¤ç‰Œ%{linkEnd}。"
-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 "将此令牌ä¿å¯†ã€‚任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·åˆ›å»ºè®®é¢˜ã€‚如果å‘生这ç§æƒ…况,访问%{link_reset_it}。"
-
msgid "AccessTokens|Personal Access Tokens"
msgstr "个人访问令牌"
@@ -1755,9 +1777,6 @@ msgstr "当您通过电å­é‚®ä»¶åˆ›å»ºä¸€ä¸ªæ–°è®®é¢˜æ—¶ï¼Œæ‚¨çš„接收电å­é‚®
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 this token"
-msgstr "é‡ç½®æ­¤ä»¤ç‰Œ"
-
msgid "AccessibilityReport|Learn more"
msgstr "了解更多"
@@ -1795,19 +1814,19 @@ msgid "AccountValidation|If you no longer wish to receive marketing emails from
msgstr "如果您ä¸å†å¸Œæœ›æ”¶åˆ°æˆ‘们的è¥é”€ç”µå­é‚®ä»¶ï¼Œ"
msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, you'll need to validate your account using one of our verification options. If you prefer not to, you can run pipelines by bringing your own runners and disabling shared runners for your project."
-msgstr ""
+msgstr "为了在共享 runner 上使用å…è´¹ CI/CD 分钟,您需è¦ä½¿ç”¨éªŒè¯é€‰é¡¹ä¹‹ä¸€éªŒè¯æ‚¨çš„å¸æˆ·ã€‚ 如果您ä¸æ„¿æ„æ供验è¯ï¼Œä½ å¯ä»¥é€šè¿‡è‡ªå·±çš„ runner æ¥è¿è¡Œæµæ°´çº¿å¹¶ä¸ºæ‚¨çš„项目ç¦ç”¨å…±äº« runner。"
msgid "AccountValidation|Learn more."
msgstr "了解更多。"
msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
-msgstr ""
+msgstr "您需è¦éªŒè¯æ‚¨çš„å¸æˆ·æ‰èƒ½ä½¿ç”¨å…费的 CI/CD 分钟"
msgid "AccountValidation|Validate your account"
msgstr "验è¯æ‚¨çš„å¸æˆ·"
msgid "AccountValidation|Verification is required to discourage and reduce the abuse on GitLab infrastructure. If you verify with a credit or debit card, %{strong_start}GitLab will not charge your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
-msgstr ""
+msgstr "验è¯æ˜¯ä¸ºäº†é˜»æ­¢å’Œå‡å°‘ GitLab 基础设施上的滥用。如果您使用信用å¡æˆ–借记å¡è¿›è¡ŒéªŒè¯ï¼Œ%{strong_start}GitLab å°†ä¸ä¼šæ”¶å–费用或存储您的å¡ä¿¡æ¯ï¼Œå®ƒå°†ä»…用于验è¯ï¼Œ%{strong_end} %{learn_more_link}"
msgid "AccountValidation|unsubscribe"
msgstr "å–消订阅"
@@ -1863,9 +1882,6 @@ msgstr "添加更新日志"
msgid "Add CONTRIBUTING"
msgstr "添加贡献信æ¯"
-msgid "Add GitLab to Slack"
-msgstr "将 GitLab 添加到 Slack"
-
msgid "Add Jaeger URL"
msgstr "增加 Jaeger 地å€"
@@ -1875,8 +1891,8 @@ msgstr "添加 Kubernetes 集群"
msgid "Add LICENSE"
msgstr "添加LICENSE"
-msgid "Add New Node"
-msgstr "添加新节点"
+msgid "Add New Site"
+msgstr ""
msgid "Add README"
msgstr "添加自述文件"
@@ -1890,6 +1906,9 @@ msgstr "添加一个%{type}"
msgid "Add a GPG key"
msgstr "添加GPG密钥"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr "添加一个Jaeger URL,用指å‘您的JaegeræœåŠ¡å™¨çš„链接替æ¢æ­¤é¡µé¢ã€‚æ‚¨é¦–å…ˆéœ€è¦ %{link_start_tag}安装Jaeger%{link_end_tag}。"
@@ -1956,6 +1975,9 @@ msgstr "添加一个待办事项"
msgid "Add an SSH key"
msgstr "添加SSH密钥"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr "添加一个已有议题"
@@ -2073,9 +2095,6 @@ msgstr "添加系统钩å­"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr "将文本添加到登录页é¢ã€‚Markdownå·²å¯ç”¨ã€‚"
-msgid "Add to Slack"
-msgstr "添加到Slack"
-
msgid "Add to board"
msgstr "添加到é¢æ¿"
@@ -2373,6 +2392,12 @@ msgstr "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šï¼Œè¿™ä¼šä¸­æ–­å¹¶ç»“æŸæ‰€æœ‰æ­£åœ¨è¿è¡Œçš„
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "加载统计数æ®æ—¶å‡ºé”™ã€‚请å†è¯•ä¸€æ¬¡"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr "定义项目标记的默认集"
@@ -2529,6 +2554,9 @@ msgstr "已冻结"
msgid "AdminUsers|(Internal)"
msgstr "内部"
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr "等待批准"
@@ -2565,8 +2593,8 @@ msgstr "在您的实例上调整用户上é™è®¾ç½®"
msgid "AdminUsers|Admin"
msgstr "管ç†å‘˜"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr "管ç†å‘˜å¯ä»¥è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ï¼Œå¹¶å¯ä»¥ç®¡ç†æ­¤å®‰è£…中的所有功能。"
+msgid "AdminUsers|Administrator"
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
@@ -2659,7 +2687,7 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "删除用户åŠç›¸å…³è´¡çŒ®"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "以 CSV æ ¼å¼å¯¼å‡ºæƒé™ï¼ˆæœ€å¤š 100,000 个用户)"
msgid "AdminUsers|External"
msgstr "外部"
@@ -2691,6 +2719,9 @@ msgstr "自己ï¼"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr "了解更多关于 %{link_start}å°ç¦ç”¨æˆ·ã€‚%{link_end}"
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "登录"
@@ -2754,6 +2785,9 @@ msgstr "用户无法访问 git 仓库。"
msgid "AdminUsers|The user can't log in."
msgstr "用户无法登录。"
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "此用户将被注销"
@@ -2856,8 +2890,8 @@ 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 "您ä¸èƒ½åˆ é™¤æ‚¨è‡ªå·±çš„管ç†å‘˜æƒé™ã€‚"
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
@@ -3417,23 +3451,14 @@ msgstr "å…许该群组中的项目使用Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr "å…许所有人访问æµæ°´çº¿å’Œä½œä¸šè¯¦æƒ…,包括输出日志和产物。"
-msgid "Allow requests to the local network from hooks and services."
-msgstr "å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„对本地网络的请求。"
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "å…许系统钩å­å‘本地网络å‘é€çš„请求"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "å…许Webhookå’ŒæœåŠ¡å¯¹æœ¬åœ°ç½‘络的请求"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "å…许副组设置自己的åŒé‡èº«ä»½éªŒè¯è§„则"
msgid "Allow this key to push to this repository"
msgstr "å…许此密钥推é€åˆ°è¿™ä¸ªä»“库"
-msgid "Allow this secondary node to replicate content on Object Storage"
-msgstr "å…许此次è¦èŠ‚点在对象存储上å¤åˆ¶å†…容"
+msgid "Allow this secondary site to replicate content on Object Storage"
+msgstr ""
msgid "Allow use of licensed EE features"
msgstr "å…许使用许å¯çš„EE功能"
@@ -3543,9 +3568,6 @@ msgstr "å‘生错误"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr "在报告测试结果时出现的错误,错误地表明在没有æ¼æ´žçš„情况下系统中存在æ¼æ´žã€‚"
-msgid "An error occured while fetching the pipelines jobs."
-msgstr "获å–æµæ°´çº¿ä½œä¸šæ—¶å‡ºé”™ã€‚"
-
msgid "An error occurred adding a draft to the thread."
msgstr "å‘主题添加è‰ç¨¿æ—¶å‡ºé”™ã€‚"
@@ -3693,18 +3715,15 @@ msgstr "获å–作业列表时å‘生错误"
msgid "An error occurred while fetching the latest pipeline."
msgstr "获å–最新æµæ°´çº¿æ—¶å‘生错误。"
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "获å–å‘布时å‘生错误。请é‡è¯•ã€‚"
msgid "An error occurred while fetching this tab."
msgstr "获å–æ­¤é¢æ¿æ—¶å‘生了一个错误。"
-msgid "An error occurred while generating a username. Please try again."
-msgstr "生æˆç”¨æˆ·å时出错。请é‡è¯•ã€‚"
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr "获å–自动完整数æ®æ—¶å‘生错误。请刷新页é¢å¹¶é‡è¯•ã€‚"
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "获å–文件 - %{branchId} 时出错"
@@ -3766,7 +3785,7 @@ msgid "An error occurred while loading the access tokens form, please try again.
msgstr "加载访问令牌表å•æ—¶å‘生错误,请é‡è¯•ã€‚"
msgid "An error occurred while loading the blob controls."
-msgstr ""
+msgstr "加载 blob 控件时出错。"
msgid "An error occurred while loading the data. Please try again."
msgstr "加载数æ®æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
@@ -4250,9 +4269,6 @@ msgstr "与åˆå¹¶è¯·æ±‚核准人åˆä½œçš„åˆå¹¶è¯·æ±‚作者"
msgid "ApprovalRule|Add approvers"
msgstr "添加核准人"
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr "添加所需的核准人æ¥æ”¹è¿›æ‚¨çš„代ç å®¡æŸ¥æµç¨‹"
-
msgid "ApprovalRule|All scanners"
msgstr "所有扫æ工具"
@@ -4283,9 +4299,6 @@ msgstr "核准人类型"
msgid "ApprovalRule|Approvers"
msgstr "核准人"
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr "按专业领域分é…核准人。"
-
msgid "ApprovalRule|Confirmed"
msgstr "已确认"
@@ -4295,14 +4308,14 @@ msgstr "已忽略"
msgid "ApprovalRule|Examples: QA, Security."
msgstr "示例:QAã€å®‰å…¨ã€‚"
-msgid "ApprovalRule|Increase your organization’s code quality."
-msgstr "æ高组织的代ç è´¨é‡ã€‚"
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
+msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
-msgstr "了解有关åˆå¹¶è¯·æ±‚批准的更多信æ¯ã€‚"
+msgid "ApprovalRule|Increase quality and maintain standards."
+msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
-msgstr "让系统根æ®æ›´æ”¹çš„文件指定åˆæ ¼çš„核准人。"
+msgid "ApprovalRule|Learn more about merge request approval rules."
+msgstr ""
msgid "ApprovalRule|Name"
msgstr "å称"
@@ -4328,8 +4341,8 @@ msgstr "请至少选择一ç§æ¼æ´žçŠ¶æ€"
msgid "ApprovalRule|Previously detected"
msgstr "以å‰æ£€æµ‹åˆ°"
-msgid "ApprovalRule|Reduce the overall time to merge."
-msgstr "å‡å°‘åˆå¹¶çš„总时间。"
+msgid "ApprovalRule|Reduce your time to merge."
+msgstr ""
msgid "ApprovalRule|Resolved"
msgstr "已解决"
@@ -4343,6 +4356,9 @@ msgstr "安全扫æ工具"
msgid "ApprovalRule|Select All"
msgstr "选择全部"
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr "选择扫æ工具"
@@ -4358,8 +4374,8 @@ msgstr "严é‡çº§åˆ«"
msgid "ApprovalRule|Target branch"
msgstr "目标分支"
-msgid "ApprovalRule|Try it for free"
-msgstr "å…费试用"
+msgid "ApprovalRule|Try for free"
+msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "å…许的æ¼æ´ž"
@@ -4370,23 +4386,29 @@ msgstr "æ¼æ´žçŠ¶æ€"
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "åˆå¹¶è¯·æ±‚审批设置已更新。"
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr "ç¦æ­¢ä½œè€…审批。"
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "ç¦æ­¢æ·»åŠ æ交的用户审批。"
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "ç¦æ­¢åœ¨åˆå¹¶è¯·æ±‚中编辑批准规则。"
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑批准规则。"
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "当æ交被添加到æºåˆ†æ”¯æ—¶åˆ é™¤æ‰€æœ‰å®¡æ‰¹ã€‚"
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
-msgstr "需è¦ç”¨æˆ·å¯†ç æ‰èƒ½æ‰¹å‡†ã€‚"
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr "加载åˆå¹¶è¯·æ±‚批准设置时出错。"
@@ -4499,6 +4521,9 @@ msgstr "确定è¦å–消归档此项目å—?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr "æ‚¨ç¡®å®šè¦ %{action} %{name}å—?"
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr "您确定è¦å°è¯•åˆå¹¶å—?"
@@ -4590,9 +4615,6 @@ msgstr "您确定è¦åˆ é™¤è¿™ä¸ªèº«ä»½æ ‡è¯†å—?"
msgid "Are you sure you want to remove this list?"
msgstr "您确定è¦åˆ é™¤æ­¤åˆ—表å—?"
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr "您确定è¦é‡ç½®SCIM令牌å—?在完æˆæ–°ä»¤ç‰Œæ›´æ–°ä¹‹å‰ï¼ŒSCIMé…置将åœæ­¢å·¥ä½œã€‚"
-
msgid "Are you sure you want to reset the health check token?"
msgstr "确定è¦é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥ä»¤ç‰Œå—?"
@@ -4677,8 +4699,8 @@ msgstr "ç¨åŽå†é—®"
msgid "Ask someone with write access to resolve it."
msgstr "请有写入æƒé™çš„人æ¥è§£å†³å®ƒã€‚"
-msgid "Ask your group maintainer to set up a group runner."
-msgstr "请è”系群组维护者设置一个群组级 Runner。"
+msgid "Ask your group owner to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "断言消费者æœåŠ¡ URL"
@@ -5117,6 +5139,9 @@ msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
msgid "Average per day: %{average}"
msgstr "å¹³å‡æ¯å¤©: %{average}"
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr "赞èµå·²æ·»åŠ "
@@ -5249,6 +5274,9 @@ msgstr "对 Bamboo æœåŠ¡å™¨å…·æœ‰ API 访问æƒé™çš„用户。"
msgid "Based on"
msgstr "基于"
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
@@ -5276,6 +5304,9 @@ msgstr "以下是%{link_to_gitlab_pages}的设置。"
msgid "Below you will find all the groups that are public."
msgstr "您将在下é¢æ‰¾åˆ°æ‰€æœ‰å…¬å¼€çš„群组。"
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "åŒå‘¨ä»£ç è¦†ç›–率"
@@ -5291,9 +5322,6 @@ msgstr "%{group_name} 正在使用 %{plan_name} 。"
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr "%{user_name},您正在使用%{plan_name}计划。"
-msgid "BillingPlans|Compare all plans"
-msgstr "比较所有计划"
-
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "æ­å–œï¼Œæ‚¨çš„试用计划已å¯ç”¨ã€‚"
@@ -5330,9 +5358,6 @@ 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 "å‡çº§åˆ° %{planNameForUpgrade}"
-
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 "虽然 GitLab å°†åœæ­¢ä½¿ç”¨ Bronze 方案,但您ä»ç„¶å¯ä»¥åœ¨ %{eoa_bronze_plan_end_date} 之å‰å†ç»­è®¢ä¸€æ¬¡ Bronze 订阅。 我们还æä¾›é™æ—¶å…è´¹å‡çº§åˆ°æˆ‘们的高级方案(最多 25 ä¸ªç”¨æˆ·ï¼‰ï¼ åœ¨æˆ‘ä»¬çš„ %{announcement_link} 中了解有关改å˜å’Œä¼˜æƒ çš„更多信æ¯ã€‚"
@@ -5391,10 +5416,10 @@ msgid "Billings|Shared runners cannot be enabled until a valid credit card is on
msgstr "Shared runners 无法å¯ç”¨ï¼Œç›´åˆ°æœ‰æ•ˆçš„信用å¡åœ¨æ¡£ã€‚"
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "è¦åœ¨ shared runners上使用å…è´¹ CI/CD 分钟,您需è¦ä½¿ç”¨ä¿¡ç”¨å¡éªŒè¯æ‚¨çš„å¸æˆ·ã€‚如果您ä¸æƒ³æ供,您å¯ä»¥é€šè¿‡ä¸ºæ‚¨çš„项目带æ¥è‡ªå·±çš„ runner 并ç¦ç”¨ shared runners æ¥è¿è¡Œæµæ°´çº¿ã€‚这是阻止和å‡å°‘对 GitLab 基础设施的滥用所必需的。 %{strongStart}GitLab ä¸ä¼šå¯¹æ‚¨çš„å¡å·æ‰£è´¹ï¼Œå®ƒåªä¼šç”¨äºŽéªŒè¯æ‚¨çš„身份。%{strongEnd} %{linkStart}了解更多%{linkEnd}"
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge your card, it will only be used for validation.%{strongEnd}"
-msgstr ""
+msgstr "è¦åœ¨å…±äº« runner 上使用å…费的 CI/CD 分钟,您需è¦ä½¿ç”¨ä¿¡ç”¨å¡éªŒè¯æ‚¨çš„å¸æˆ·ã€‚ 这样åšçš„目的是为了阻止和å‡å°‘ GitLab 基础设施的滥用。 %{strongStart}GitLab ä¸ä¼šå¯¹æ‚¨çš„å¡å·æ‰£è´¹ï¼Œå®ƒä»…用于验è¯ã€‚%{strongEnd}"
msgid "Billings|User validation required"
msgstr "需è¦ç”¨æˆ·éªŒè¯"
@@ -5406,14 +5431,20 @@ msgid "Billings|Validate user account"
msgstr "验è¯ç”¨æˆ·å¸æˆ·"
msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "您现在å¯ä»¥åˆ©ç”¨å…±äº« runner çš„å…è´¹ CI/CD 分钟。"
msgid "Billings|Your account has been validated"
+msgstr "您的å¸æˆ·å·²é€šè¿‡éªŒè¯"
+
+msgid "Billing|%{user} was successfully approved"
msgstr ""
msgid "Billing|An email address is only visible for users with public emails."
msgstr "åªæœ‰ç”¨æˆ·è®¾ç½®äº†å…¬å¼€ç”µå­é‚®ä»¶ï¼Œä»–们的邮件æ‰å¯¹å¤–å¯è§ã€‚"
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr "获å–计费会员详细信æ¯æ—¶å‘生错误"
@@ -5492,6 +5523,9 @@ msgstr "从 Bitbucket 导入"
msgid "Blame"
msgstr "Blame"
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr "å±è”½ç”¨æˆ·"
@@ -5801,18 +5835,12 @@ msgstr "删除已åˆå¹¶çš„分支"
msgid "Branches|Delete protected branch"
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 "删除 %{strongStart}%{branchName}%{strongEnd} 分支æ“作无法撤销。确定继续å—?"
-msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "删除 â€%{branch_name}†åŽå°†æ— æ³•æ¢å¤ï¼Œæ‚¨ç¡®å®šï¼Ÿ"
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "删除已åˆå¹¶çš„分支åŽå°†æ— æ³•æ¢å¤ï¼Œç¡®å®šç»§ç»­å—?"
@@ -5828,9 +5856,6 @@ msgstr "新建分支"
msgid "Branches|No branches to show"
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 "确认执行 %{strongStart}%{buttonText},%{strongEnd} åŽå°†æ— æ³•æ’¤é”€æˆ–æ¢å¤ã€‚"
@@ -5879,15 +5904,6 @@ msgstr "无法删除默认分支"
msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
msgstr "此分支尚未åˆå¹¶åˆ° %{defaultBranchName}。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œè¯·åœ¨åˆ é™¤ä¹‹å‰åˆå¹¶æ­¤åˆ†æ”¯ã€‚"
-msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr "此分支尚未åˆå¹¶åˆ° %{default_branch}。"
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "为é¿å…æ•°æ®ä¸¢å¤±ï¼Œè¯·åœ¨åˆ é™¤ä¹‹å‰åˆå¹¶æ­¤åˆ†æ”¯ã€‚"
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 "è¦æ”¾å¼ƒæœ¬åœ°æ›´æ”¹å¹¶è¦†ç›–上游版本的分支,请在此处将其删除,然åŽé€‰æ‹©ä¸Šé¢çš„“立å³æ›´æ–°â€ã€‚"
@@ -5906,9 +5922,6 @@ msgstr "您将è¦æ°¸ä¹…删除分支 %{strongStart}%{branchName}。%{strongEnd}"
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr "您将è¦æ°¸ä¹…删除å—ä¿æŠ¤çš„分支 %{strongStart}%{branchName}。%{strongEnd}"
-msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "å°†è¦æ°¸ä¹…删除å—ä¿æŠ¤çš„ %{branch_name} 分支。"
-
msgid "Branches|diverged from upstream"
msgstr "与上游存在差异"
@@ -6104,6 +6117,15 @@ msgstr "通过与ä¼ä¸šç”µå­é‚®ä»¶åœ°å€ç»‘定的账å·è¿›è¡Œèº«ä»½éªŒè¯ï¼Œè¯´
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "默认情况下,所有项目和群组将使用全局通知设置。"
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -6168,9 +6190,21 @@ msgstr "å‘布统计"
msgid "CICDAnalytics|Releases"
msgstr "å‘布"
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr "获å–å‘布统计信æ¯æ—¶å‡ºçŽ°é”™è¯¯"
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr "请将%{base_domain_link_start}基础域å%{link_end}添加到%{kubernetes_cluster_link_start}Kubernetes集群%{link_end},æ‰èƒ½ä½¿æ‚¨çš„部署策略正常工作。"
@@ -6405,6 +6439,9 @@ msgstr "无法将机密å²è¯—分é…ç»™éžæœºå¯†è®®é¢˜ã€‚请将此议题设置机
msgid "Cannot be merged automatically"
msgstr "无法自动åˆå¹¶"
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr "无法创建滥用报告。用户已被删除。"
@@ -6782,6 +6819,9 @@ msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
msgstr "(x%{quantity})"
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr "å¸å•åœ°å€"
@@ -6959,6 +6999,9 @@ msgstr "拣选此åˆå¹¶è¯·æ±‚"
msgid "Child"
msgstr "å­çº§"
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
@@ -7203,7 +7246,7 @@ msgid "Clear due date"
msgstr "清除截止日期"
msgid "Clear health status"
-msgstr ""
+msgstr "清除å¥åº·çŠ¶æ€"
msgid "Clear recent searches"
msgstr "清除最近的æœç´¢"
@@ -7224,13 +7267,13 @@ msgid "Clear weight"
msgstr "清除æƒé‡"
msgid "Cleared health status."
-msgstr ""
+msgstr "å¥åº·çŠ¶æ€å·²æ¸…除。"
msgid "Cleared weight."
msgstr "å·²é‡ç½®çš„æƒé‡"
msgid "Clears health status."
-msgstr ""
+msgstr "清除å¥åº·çŠ¶æ€ã€‚"
msgid "Clears weight."
msgstr "清除æƒé‡"
@@ -7259,15 +7302,6 @@ msgstr "点击éšè—"
msgid "Click to reveal"
msgstr "点击显示"
-msgid "Client authentication certificate"
-msgstr "客户端认è¯è¯ä¹¦"
-
-msgid "Client authentication key"
-msgstr "客户端认è¯å¯†é’¥"
-
-msgid "Client authentication key password"
-msgstr "客户端认è¯å¯†é’¥å¯†ç "
-
msgid "Client request timeout"
msgstr "客户端请求超时"
@@ -7364,6 +7398,12 @@ msgstr "关闭: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr "集群"
@@ -7386,10 +7426,10 @@ msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Stages::ClusterEndpointInserter需è¦é›†ç¾¤ç±»åž‹"
msgid "ClusterAgents|%{name} successfully deleted"
-msgstr ""
+msgstr "%{name} å·²æˆåŠŸåˆ é™¤"
-msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr "%{number} 个代ç†ï¼Œå…± %{total} 个"
+msgid "ClusterAgents|%{number} of %{total} Agents"
+msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
msgstr "%{total}个集群中的%{number}个通过集群è¯ä¹¦è¿žæŽ¥"
@@ -7433,8 +7473,8 @@ msgstr "代ç†ä»Žæœªè¿žæŽ¥åˆ° GitLab"
msgid "ClusterAgents|All"
msgstr "全部"
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr "加载您的GitLab Agentæ—¶å‘生错误"
+msgid "ClusterAgents|An error occurred while loading your Agents"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr "加载代ç†æ—¶å‡ºé”™"
@@ -7446,7 +7486,7 @@ msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "å‘生未知错误。请é‡è¯•ã€‚"
msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
-msgstr ""
+msgstr "确定è¦åˆ é™¤æ­¤ä»£ç†å—?您无法撤消此æ“作。"
msgid "ClusterAgents|Certificate"
msgstr "è¯ä¹¦"
@@ -7463,8 +7503,8 @@ msgstr "连接现有集群"
msgid "ClusterAgents|Connect with a certificate"
msgstr "使用è¯ä¹¦è¿žæŽ¥"
-msgid "ClusterAgents|Connect with the Agent"
-msgstr "与代ç†è¿žæŽ¥"
+msgid "ClusterAgents|Connect with agent"
+msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
msgstr "与 GitLab 代ç†è¿žæŽ¥"
@@ -7494,10 +7534,10 @@ msgid "ClusterAgents|Date created"
msgstr "创建日期"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "删除"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "删除代ç†"
msgid "ClusterAgents|Deprecated"
msgstr "已弃用"
@@ -7520,14 +7560,17 @@ msgstr "GitLab 代ç†"
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr "适用于 Kubernetes çš„ GitLab 代ç†"
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr "转到仓库文件"
msgid "ClusterAgents|How to register an agent?"
msgstr "如何注册代ç†ï¼Ÿ"
-msgid "ClusterAgents|Install a new agent"
-msgstr "安装新代ç†"
+msgid "ClusterAgents|Install new Agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "上次连接在 %{timeAgo}。"
@@ -7553,8 +7596,8 @@ msgstr "从ä¸"
msgid "ClusterAgents|Never connected"
msgstr "从未连接"
-msgid "ClusterAgents|No agents"
-msgstr "无代ç†"
+msgid "ClusterAgents|No Agents"
+msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr "没有通过集群è¯ä¹¦è¿žæŽ¥çš„集群"
@@ -7580,6 +7623,18 @@ msgstr "注册代ç†"
msgid "ClusterAgents|Registration token"
msgstr "注册令牌"
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr "安全"
@@ -7592,6 +7647,9 @@ msgstr "选择代ç†"
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr "选择è¦æ³¨å†Œåˆ° GitLab 的代ç†"
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr "当将 Kubernetes 集群连接到 GitLab 时,GitLab 代ç†æ供更高级别的安全性。 %{linkStart}了解有关 GitLab 代ç†çš„更多信æ¯ã€‚%{linkEnd}"
@@ -7612,10 +7670,10 @@ msgid "ClusterAgents|This agent has no tokens"
msgstr "此代ç†æ²¡æœ‰ä»¤ç‰Œ"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
-msgstr ""
+msgstr "è¦åˆ é™¤ä»£ç†ï¼Œè¯·è¾“å…¥ %{name} 进行确认:"
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
-msgstr "è¦å®‰è£…新代ç†ï¼Œé¦–先将代ç†çš„é…置文件添加到此仓库中。 %{linkStart}代ç†çš„é…置文件是什么?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
msgstr "由 %{userName} 创建的令牌"
@@ -7632,6 +7690,9 @@ msgstr "查看所有 %{number} 个代ç†"
msgid "ClusterAgents|View all %{number} clusters"
msgstr "查看所有 %{number} 个集群"
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr "什么是 GitLab 代ç†åŠ¨æ€ï¼Ÿ"
@@ -8581,6 +8642,9 @@ msgstr "æ交(编辑æ交消æ¯æ—¶ï¼‰"
msgid "Commit Message"
msgstr "æ交消æ¯"
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr "æ交更改"
@@ -8830,6 +8894,9 @@ msgstr "ç”±æ交者批准"
msgid "ComplianceReport|Less than 2 approvers"
msgstr "少于 2 个核准人"
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr "组件"
@@ -8860,6 +8927,12 @@ msgstr "在仓库上é…ç½® %{repository_checks_link_start}仓库检查%{link_end
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr "é…ç½® CAPTCHAã€IP 地å€é™åˆ¶å’Œå…¶ä»–å垃圾邮件措施。"
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr "使用 GitLab 托管模æ¿åœ¨ `.gitlab-ci.yml` 中é…ç½®ä¾èµ–扫æ。您å¯ä»¥[添加å˜é‡è¦†ç›–](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) æ¥è‡ªå®šä¹‰ä¾èµ–项扫æ设置。"
@@ -8905,12 +8978,15 @@ msgstr "é…置跟踪"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "在%{codeStart}.gitlab%{codeEnd}目录中é…ç½®%{codeStart}gitlab-webide.yml%{codeEnd}文件以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr "é…置高级æƒé™ã€å¤§æ–‡ä»¶å­˜å‚¨å’ŒåŒé‡èº«ä»½éªŒè¯è®¾ç½®ã€‚"
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
+msgstr ""
msgid "Configure existing installation"
msgstr "é…置现有安装"
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr "é…置仓库镜åƒã€‚"
@@ -8938,12 +9014,18 @@ msgstr "é…置默认的æ¯å‘¨ç¬¬ä¸€å¤©å’Œæ—¶é—´è·Ÿè¸ªå•ä½ã€‚"
msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "é…置显示给任何访问此看æ¿çš„人的列表"
msgid "Confirm"
msgstr "确认"
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr "确认新密ç "
@@ -9250,7 +9332,7 @@ msgid "ContainerRegistry|Note: Any policy update will result in a change to the
msgstr "注æ„:任何策略更新都会导致对预定è¿è¡Œæ—¥æœŸå’Œæ—¶é—´çš„更改"
msgid "ContainerRegistry|Please try different search criteria"
-msgstr ""
+msgstr "请å°è¯•ä¸åŒçš„æœç´¢æ¡ä»¶"
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "å‘布于%{timeInfo}"
@@ -9341,7 +9423,7 @@ msgid "ContainerRegistry|The cleanup policy timed out before it could delete all
msgstr "清ç†ç­–略在删除所有标签之å‰è¶…时。 管ç†å‘˜å¯ä»¥%{adminLinkStart}ç«‹å³æ‰§è¡Œæ‰‹åŠ¨æ¸…ç†%{adminLinkEnd}或者等待清ç†ç­–略下次自动è¿è¡Œã€‚%{docLinkStart}更多信æ¯%{docLinkEnd}"
msgid "ContainerRegistry|The filter returned no results"
-msgstr ""
+msgstr "过滤器没有返回结果"
msgid "ContainerRegistry|The image repository could not be found."
msgstr "找ä¸åˆ°é•œåƒä»“库。"
@@ -9499,8 +9581,8 @@ msgstr "控制与您å¸æˆ·å…³è”的电å­é‚®ä»¶"
msgid "Control how the GitLab Package Registry functions."
msgstr "控制 GitLab 软件包仓库是如何è¿ä½œçš„。"
-msgid "Control whether to display third-party offers in GitLab."
-msgstr "控制是å¦åœ¨ GitLab中显示第三方è¦çº¦ã€‚"
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
msgstr "控制使用此项目的 CI_JOB_TOKEN CI/CD å˜é‡è¿›è¡Œèº«ä»½éªŒè¯çš„ API 请求å¯ä»¥è®¿é—®å“ªäº›é¡¹ç›®ã€‚ç¦ç”¨æ­¤åŠŸèƒ½å­˜åœ¨å®‰å…¨é£Žé™©ï¼Œå› ä¸ºæœªç»æŽˆæƒçš„项目å¯èƒ½ä¼šå°è¯•æ£€ç´¢æ´»åŠ¨ä»¤ç‰Œå¹¶è®¿é—® API。"
@@ -9575,7 +9657,7 @@ msgid "Copy evidence SHA"
msgstr "å¤åˆ¶è¯æ®SHA"
msgid "Copy failed. Please manually copy the value."
-msgstr ""
+msgstr "å¤åˆ¶å¤±è´¥ã€‚请手动å¤åˆ¶å€¼ã€‚"
msgid "Copy file contents"
msgstr "å¤åˆ¶æ–‡ä»¶å†…容"
@@ -9640,9 +9722,24 @@ msgstr "动作"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr "语料库在模糊测试中用作å˜å¼‚æºä»¥æ”¹è¿›æœªæ¥çš„测试。"
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr "语料库å称"
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr "模糊测试语料库管ç†"
@@ -9655,9 +9752,6 @@ msgstr "最åŽä½¿ç”¨"
msgid "CorpusManagement|Latest Job:"
msgstr "最新作业:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr "新语料库需è¦ä¸Šä¼ *.zip æ ¼å¼ã€‚最大 5GB"
-
msgid "CorpusManagement|New upload"
msgstr "新上传"
@@ -9730,6 +9824,9 @@ msgstr "无法绘制代表作业关系的线"
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr "无法获å–策略,因为现有的策略 YAML 无效"
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr "未找到设计."
@@ -9757,14 +9854,17 @@ msgstr "无法删除触å‘器。"
msgid "Could not restore the group"
msgstr "无法还原群组"
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr "无法撤消身份模拟令牌 %{token_name}。"
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr "无法撤消个人访问令牌 %{personal_access_token_name}。"
-msgid "Could not revoke project access token %{project_access_token_name}."
-msgstr "无法撤消项目访问令牌%{project_access_token_name}。"
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
msgid "Could not save group ID"
msgstr "无法ä¿å­˜ç¾¤ç»„ID"
@@ -9907,6 +10007,9 @@ msgstr "创建议题æ¥è§£å†³æ‰€æœ‰ä¸»é¢˜"
msgid "Create iteration"
msgstr "创建迭代"
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr "创建列表"
@@ -9986,7 +10089,7 @@ msgid "Create user"
msgstr "创建用户"
msgid "Create via merge request"
-msgstr ""
+msgstr "通过åˆå¹¶è¯·æ±‚创建"
msgid "Create wildcard: %{searchTerm}"
msgstr "创建通é…符: %{searchTerm}"
@@ -10040,7 +10143,7 @@ msgid "CreateValueStreamForm|Create new Value Stream"
msgstr "创建新的价值æµ"
msgid "CreateValueStreamForm|Create value stream"
-msgstr ""
+msgstr "创建价值æµ"
msgid "CreateValueStreamForm|Default stages"
msgstr "默认阶段"
@@ -10049,7 +10152,7 @@ msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
msgstr "默认阶段åªèƒ½è¢«éšè—或é‡æ–°æŽ’åº"
msgid "CreateValueStreamForm|Edit value stream"
-msgstr ""
+msgstr "编辑价值æµ"
msgid "CreateValueStreamForm|Editing stage"
msgstr "编辑阶段"
@@ -10165,6 +10268,9 @@ msgstr "由我创建"
msgid "Created by:"
msgstr "创建人:"
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr "创建日期"
@@ -10399,6 +10505,9 @@ msgstr "客户关系è”系人"
msgid "Customer Relations Organizations"
msgstr "客户关系组织"
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr "客户关系"
@@ -10629,6 +10738,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "日期"
@@ -10638,11 +10750,11 @@ msgstr "从åˆå¹¶åˆ°éƒ¨ç½²çš„天数"
msgid "DORA4Metrics|Deployment frequency"
msgstr "部署频率"
-msgid "DORA4Metrics|Lead time"
-msgstr "交付时间"
+msgid "DORA4Metrics|Lead time for changes"
+msgstr ""
-msgid "DORA4Metrics|Median lead time"
-msgstr "中ä½äº¤ä»˜æ—¶é—´"
+msgid "DORA4Metrics|Median (last %{days}d)"
+msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
msgstr "在此期间没有部署åˆå¹¶è¯·æ±‚"
@@ -10731,12 +10843,6 @@ msgstr "无法创建扫æ工具é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr "无法创建站点é…置。请é‡è¯•ã€‚"
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr "无法删除ä¿å­˜çš„扫æ。请刷新页é¢ï¼Œæˆ–ç¨åŽé‡è¯•ã€‚"
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr "无法删除ä¿å­˜çš„扫æ:"
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr "无法删除扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
@@ -10749,9 +10855,6 @@ msgstr "无法删除站点é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "DastProfiles|Could not delete site profiles:"
msgstr "无法删除站点é…置:"
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr "无法获å–å·²ä¿å­˜çš„扫æ。请刷新页é¢ï¼Œæˆ–ç¨åŽé‡è¯•ã€‚"
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "无法获å–扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
@@ -10764,9 +10867,6 @@ msgstr "无法更新扫æ工具é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "无法更新站点é…置。请é‡è¯•ã€‚"
-msgid "DastProfiles|DAST Scan"
-msgstr "DAST 扫æ"
-
msgid "DastProfiles|Debug messages"
msgstr "调试消æ¯"
@@ -10839,9 +10939,6 @@ msgstr "新建站点é…ç½®"
msgid "DastProfiles|No scanner profiles created yet"
msgstr "尚未创建扫æ工具é…置文件"
-msgid "DastProfiles|No scans saved yet"
-msgstr "尚未ä¿å­˜æ‰«æ"
-
msgid "DastProfiles|No site profiles created yet"
msgstr "尚未创建站点é…置文件"
@@ -10869,9 +10966,6 @@ msgstr "请求报头"
msgid "DastProfiles|Rest API"
msgstr "Rest API"
-msgid "DastProfiles|Run scan"
-msgstr "è¿è¡Œæ‰«æ"
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr "除了传统的爬虫之外,å¯ä»¥è¿è¡ŒAJAX爬虫æ¥é历目标站点。"
@@ -10881,12 +10975,6 @@ msgstr "将目标站点和扫æ设置的常用设定ä¿å­˜ä¸ºé…置。使用这
msgid "DastProfiles|Save profile"
msgstr "ä¿å­˜é…ç½®"
-msgid "DastProfiles|Saved Scans"
-msgstr "ä¿å­˜çš„扫æ"
-
-msgid "DastProfiles|Scan"
-msgstr "扫æ"
-
msgid "DastProfiles|Scan mode"
msgstr "扫æ模å¼"
@@ -10899,9 +10987,6 @@ msgstr "扫æ工具é…ç½®"
msgid "DastProfiles|Scanner name"
msgstr "扫æ工具å称"
-msgid "DastProfiles|Schedule"
-msgstr "计划"
-
msgid "DastProfiles|Select branch"
msgstr "选择分支"
@@ -10923,9 +11008,6 @@ msgstr "站点类型"
msgid "DastProfiles|Spider timeout"
msgstr "爬虫超时"
-msgid "DastProfiles|Target"
-msgstr "目标"
-
msgid "DastProfiles|Target URL"
msgstr "目标URL"
@@ -11150,7 +11232,7 @@ msgid "Days to merge"
msgstr "åˆå¹¶æ‰€éœ€å¤©æ•°"
msgid "Deactivate dormant users after 90 days of inactivity"
-msgstr "闲置 90 天åŽåœç”¨ä¼‘眠用户"
+msgstr "闲置 90 天åŽå†»ç»“休眠用户"
msgid "Dear Administrator,"
msgstr "亲爱的管ç†å‘˜ï¼Œ"
@@ -11194,9 +11276,6 @@ msgstr "默认分支和å—ä¿æŠ¤çš„分支"
msgid "Default branch protection"
msgstr "默认分支ä¿æŠ¤"
-msgid "Default classification label"
-msgstr "默认分类标记"
-
msgid "Default delayed project deletion"
msgstr "默认延迟删除项目"
@@ -11617,6 +11696,9 @@ msgstr[0] "部署"
msgid "Deploy Keys"
msgstr "部署密钥"
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr "部署冻结"
@@ -11632,6 +11714,9 @@ msgstr "部署密钥授予对实例中所有仓库的读/写访问æƒé™"
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr "未找到部署进度。è¦æŸ¥çœ‹pod,请确ä¿æ‚¨çš„环境符åˆ%{linkStart}部署看æ¿æ¡ä»¶%{linkEnd}。"
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr "部署到 ..."
@@ -11843,9 +11928,39 @@ msgstr[0] "%{deployments} 环境å—到影å“。"
msgid "Deployment|API"
msgstr "API"
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr "此部署使用API创建"
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr "å·²å–消"
@@ -12402,9 +12517,6 @@ msgstr "安全能力,整åˆåˆ°æ‚¨çš„å¼€å‘生命周期中"
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr "查看 %{linkStart}旗舰版方案%{linkEnd} 的其它功能"
-msgid "Discover|Send feedback"
-msgstr "å‘é€å馈"
-
msgid "Discover|Start a free trial"
msgstr "开始å…费试用"
@@ -12469,8 +12581,8 @@ msgstr "显示æº"
msgid "Display time tracking in issues in total hours only."
msgstr "仅以总å°æ—¶æ•°æ˜¾ç¤ºè®®é¢˜ä¸­çš„时间跟踪。"
-msgid "Do not display offers from third parties"
-msgstr "ä¸æ˜¾ç¤ºæ¥è‡ªç¬¬ä¸‰æ–¹çš„优惠"
+msgid "Do not display content for customer experience improvement and offers from third parties"
+msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
msgstr "ä¸è¦å¼ºè¡ŒæŽ¨åŠ¨åˆ†æ­§çš„ref。创建镜åƒåŽï¼Œåªèƒ½ä½¿ç”¨ API 修改此设置。 %{mirroring_docs_link_start}了解有关此选项%{link_closing_tag} å’Œ %{mirroring_api_docs_link_start}API 的更多信æ¯ã€‚%{link_closing_tag}"
@@ -12664,8 +12776,8 @@ msgstr "编辑评论"
msgid "Edit Deploy Key"
msgstr "编辑部署密钥"
-msgid "Edit Geo Node"
-msgstr "编辑Geo节点"
+msgid "Edit Geo Site"
+msgstr ""
msgid "Edit Group Hook"
msgstr "编辑群组钩å­"
@@ -12722,7 +12834,7 @@ msgid "Edit environment"
msgstr "编辑环境"
msgid "Edit epics"
-msgstr ""
+msgstr "编辑å²è¯—"
msgid "Edit files in the editor and commit changes here"
msgstr "在编辑器中编辑文件并在这里​​æ交å˜æ›´å†…容"
@@ -12910,6 +13022,9 @@ msgstr "我们无法确定用户对应的电å­é‚®ä»¶ã€‚请通过WEB页é¢åˆ›å»º
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr "我们找ä¸åˆ°è¯¥é¡¹ç›®ã€‚请检查是å¦æœ‰æ‹¼å†™é”™è¯¯ã€‚"
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "ä¸å…许您执行此æ“作。如果您认为这是错误的,请è”系系统管ç†å‘˜ã€‚"
@@ -13054,9 +13169,6 @@ msgstr "å¯ç”¨èº«ä»½éªŒè¯"
msgid "Enable automatic repository housekeeping"
msgstr "å¯ç”¨è‡ªåŠ¨ä»“库例行维护"
-msgid "Enable classification control using an external service"
-msgstr "使用外部æœåŠ¡å¯ç”¨åˆ†ç±»æŽ§åˆ¶"
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr "为创建于早于GitLab 12.7版本的项目å¯ç”¨å®¹å™¨è¿‡æœŸå’Œä¿ç•™ç­–略。"
@@ -13099,6 +13211,9 @@ msgstr "å¯ç”¨kuromoji自定义分æžå™¨ï¼šç´¢å¼•"
msgid "Enable kuromoji custom analyzer: Search"
msgstr "å¯ç”¨kuromoji自定义分æžå™¨ï¼šæœç´¢"
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr "å¯ç”¨ç»´æŠ¤æ¨¡å¼"
@@ -13126,6 +13241,12 @@ msgstr "å¯ç”¨ reCAPTCHA 进行登录。"
msgid "Enable repository checks"
msgstr "å¯ç”¨ä»“库检查"
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr "为该组中的所有项目和å­ç»„å¯ç”¨å…±äº«Runner。"
@@ -13204,9 +13325,6 @@ msgstr "结æŸäºŽ"
msgid "Ends: %{endsAt}"
msgstr "结æŸäºŽï¼š%{endsAt}"
-msgid "Enforce DNS rebinding attack protection"
-msgstr "强制DNSé‡æ–°ç»‘定攻击ä¿æŠ¤"
-
msgid "Enforce SSH key expiration"
msgstr "强制使用 SSH 密钥过期"
@@ -13255,6 +13373,9 @@ msgstr "输入您的BitbucketæœåŠ¡å™¨URL和个人访问令牌"
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr "在下é¢è¾“入您的Phabricator Server URL和个人访问令牌"
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr "输入åˆå¹¶è¯·æ±‚网å€"
@@ -13529,6 +13650,9 @@ msgstr "终止环境"
msgid "Environments|Stopping %{environmentName}"
msgstr "终止%{environmentName}"
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "获å–日志时出错。请é‡è¯•ã€‚"
@@ -13556,6 +13680,9 @@ msgstr "ç”± %{avatar} æä¾›"
msgid "Environments|protected"
msgstr "å—ä¿æŠ¤çš„"
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr "å²è¯—"
@@ -13665,7 +13792,7 @@ msgid "Epics|Something went wrong while removing issue from epic."
msgstr "从å²è¯—中删除议题时出错。"
msgid "Epics|Something went wrong while updating epics."
-msgstr ""
+msgstr "æ›´æ–°å²è¯—时出错。"
msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
msgstr "这个å²è¯—和任何包å«å­å²è¯—çš„ä¿¡æ¯å‡ä¸ºç§å¯†ï¼Œåªèƒ½å¯¹æ‹¥æœ‰è‡³å°‘报告者访问æƒé™çš„团队æˆå‘˜å¯è§ã€‚"
@@ -14340,9 +14467,6 @@ msgstr "仅导出å˜é‡åˆ°ä¿æŠ¤åˆ†æ”¯å’Œæ ‡ç­¾ä¸Šè¿è¡Œçš„æµæ°´çº¿ã€‚"
msgid "Exported requirements"
msgstr "导出的è¦æ±‚"
-msgid "External Classification Policy Authorization"
-msgstr "外部分类政策授æƒ"
-
msgid "External ID"
msgstr "外部ID"
@@ -14352,15 +14476,9 @@ msgstr "外部URL"
msgid "External User:"
msgstr "外部用户:"
-msgid "External authentication"
-msgstr "外部身份验è¯"
-
msgid "External authorization denied access to this project"
msgstr "外部授æƒæ‹’ç»è®¿é—®æ­¤é¡¹ç›®"
-msgid "External authorization request timeout"
-msgstr "外部授æƒè¯·æ±‚超时"
-
msgid "External storage URL"
msgstr "外部存储网å€"
@@ -14376,6 +14494,54 @@ msgstr "分类标签"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "未设置分类标签的时候,将使用默认的分类标签`%{default_label}`。"
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr "此处å¯èƒ½ä¸ä¼šæ˜¾ç¤ºæ‰€æœ‰æ•°æ®ï¼Œè¦æŸ¥çœ‹æ›´å¤šè¯¦ç»†ä¿¡æ¯æˆ–对此议题进行更改,请转到 %{linkStart}%{trackerName}%{linkEnd}。"
@@ -14455,11 +14621,8 @@ msgstr "创建框架失败"
msgid "Failed to create import label for jira import."
msgstr "为jira导入创建导入标签失败。"
-msgid "Failed to create merge request. Please try again."
-msgstr "创建åˆå¹¶è¯·æ±‚失败。请é‡è¯•ã€‚"
-
-msgid "Failed to create new project access token: %{token_response_message}"
-msgstr "创建新项目访问令牌失败: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
+msgstr ""
msgid "Failed to create repository"
msgstr "创建仓库失败"
@@ -14897,13 +15060,6 @@ msgstr "用户ID"
msgid "FeatureFlag|User List"
msgstr "用户列表"
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] "剩余%{daysRemaining}天å¯ä»¥ä½¿ç”¨%{featureName}"
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr "享å—您的%{planNameForTrial}试用å—?è¦åœ¨è¯•ç”¨ç»“æŸåŽç»§ç»­ä½¿ç”¨ %{featureName} ,请å‡çº§åˆ°%{planNameForUpgrade}。"
-
msgid "Feb"
msgstr "2月"
@@ -14991,12 +15147,6 @@ msgstr "筛选器"
msgid "Filter by"
msgstr "筛选方å¼"
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr "筛选器%{issuable_type}当å‰å…³é—­ã€‚"
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr "筛选当å‰å¼€æ”¾çš„ %{issuable_type}"
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr "筛选当å‰å¼€æ”¾çš„ %{page_context_word}"
@@ -15321,6 +15471,9 @@ msgstr "在您的 %{gitlab_ci_yml} 中找到错误:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在.gitlab-ci.yml中å‘现错误:"
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr "框架删除æˆåŠŸ"
@@ -15364,7 +15517,7 @@ msgid "Full"
msgstr "全部"
msgid "Full log"
-msgstr ""
+msgstr "完整日志"
msgid "Full name"
msgstr "å…¨å"
@@ -15396,6 +15549,9 @@ msgstr "通用设置"
msgid "Generate a default set of labels"
msgstr "生æˆä¸€ç»„默认的标记"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr "生æˆå¯†é’¥"
@@ -15432,18 +15588,21 @@ msgstr "差异"
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr "Geo 节点"
-
msgid "Geo Replication"
msgstr "Geoå¤åˆ¶"
msgid "Geo Settings"
msgstr "Geo设置"
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr "Geo站点"
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr "%{component} å·²åŒæ­¥"
@@ -15480,6 +15639,9 @@ msgstr "添加站点"
msgid "Geo|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 Troubleshow%{linkEnd} 文档以获å–更多信æ¯ã€‚"
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr "所有%{replicable_name}"
@@ -15534,6 +15696,9 @@ msgstr "探索GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
msgstr "与主存储é…ç½®ä¸ä¸€è‡´"
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失败"
@@ -15609,12 +15774,6 @@ msgstr "下一次åŒæ­¥å®‰æŽ’在"
msgid "Geo|No available replication slots"
msgstr "没有å¯ç”¨çš„å¤åˆ¶æ§½"
-msgid "Geo|Node name can't be blank"
-msgstr "节点å称ä¸èƒ½ä¸ºç©º"
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr "节点å称应该介于1到255个字符之间"
-
msgid "Geo|Not synced yet"
msgstr "尚未åŒæ­¥"
@@ -15630,6 +15789,9 @@ msgstr "无需验è¯"
msgid "Geo|Offline"
msgstr "离线"
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "å¾…åŒæ­¥"
@@ -15663,17 +15825,20 @@ msgstr "é‡æ–°ä¸‹è½½"
msgid "Geo|Remove"
msgstr "删除"
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr "移除æ¡ç›®"
-msgid "Geo|Remove node"
-msgstr "删除节点"
+msgid "Geo|Remove site"
+msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr "移除跟踪数æ®åº“æ¡ç›®"
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
-msgstr "删除一个 Geo 节点会åœæ­¢ä¸Žè¯¥èŠ‚点的åŒæ­¥ï¼Œä½ ç¡®å®šå—?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
+msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
msgstr "å¤åˆ¶çš„æ•°æ®ç”±ä½¿ç”¨æ ¡éªŒå’Œçš„次è¦ç«™ç‚¹éªŒè¯"
@@ -15684,9 +15849,6 @@ msgstr "å¤åˆ¶çš„æ•°æ®ç”±ä½¿ç”¨æ ¡éªŒå’Œçš„次è¦ç«™ç‚¹éªŒè¯ã€‚"
msgid "Geo|Replication Details"
msgstr "å¤åˆ¶è¯¦æƒ…"
-msgid "Geo|Replication details"
-msgstr "å¤åˆ¶è¯¦æƒ…"
-
msgid "Geo|Replication slot WAL"
msgstr "å¤åˆ¶æ§½WAL"
@@ -15735,6 +15897,12 @@ msgstr "次è¦ç«™ç‚¹"
msgid "Geo|Selective (%{syncLabel})"
msgstr "选择性 (%{syncLabel})"
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr "站点状æ€æ›´æ–°äºŽ%{timeAgo}。"
@@ -15771,11 +15939,11 @@ msgstr "站点当å‰ä½äºŽä¸»ç«™ç‚¹åŽé¢ %{minutes_behind}。"
msgid "Geo|There are no %{replicable_type} to show"
msgstr "没有%{replicable_type}å¯æ˜¾ç¤º"
-msgid "Geo|There was an error deleting the Geo Node"
-msgstr "删除Geo节点时出现错误"
+msgid "Geo|There was an error deleting the Geo Site"
+msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
-msgstr "获å–Geo节点时出现错误"
+msgid "Geo|There was an error fetching the Geo Sites"
+msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "å°†è¦é‡æ–°åŒæ­¥æ‰€æœ‰%{replicableType}。å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´å®Œæˆã€‚确定继续å—?"
@@ -15796,7 +15964,7 @@ msgid "Geo|URL can't be blank"
msgstr "URLä¸èƒ½ä¸ºç©º"
msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
-msgstr "URL必须是有效的url(例如:https://gitlab.com)"
+msgstr "URL必须是有效的url"
msgid "Geo|Undefined"
msgstr "未定义"
@@ -15852,6 +16020,9 @@ msgstr "次è¦èŠ‚点"
msgid "Get a free instance review"
msgstr "获得å…费的实例评估"
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr "获å–支æŒè®¢é˜…"
@@ -15975,9 +16146,6 @@ msgstr "GitLab äº‹ä»¶è§¦å‘ webhook。使用 webhook 请求的详细信æ¯æ¥å¸®
msgid "GitLab export"
msgstr "GitLab导出"
-msgid "GitLab for Slack"
-msgstr "GitLab for Slack"
-
msgid "GitLab group: %{source_link}"
msgstr "GitLab 群组:%{source_link}"
@@ -16002,6 +16170,9 @@ msgstr "GitLab 是用于代ç å作的开æºè½¯ä»¶ã€‚"
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr "GitLab 正在进行维护并以åªè¯»æ¨¡å¼è¿è¡Œã€‚"
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr "GitLabæˆå‘˜æˆ–电å­é‚®ä»¶åœ°å€"
@@ -16182,6 +16353,9 @@ msgstr "Gitpod网å€"
msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
msgstr "é…ç½®ä¸ºè¯»å– GitLab 项目的 Gitpod 实例的 URL,例如 https://gitpod.example.com。"
+msgid "Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 "è¦ä½¿ç”¨é›†æˆï¼Œæ¯ä¸ªç”¨æˆ·è¿˜å¿…须在其 GitLab è´¦å·ä¸Šå¯ç”¨ Gitpod。 %{link_start}如何å¯ç”¨å®ƒï¼Ÿ%{link_end} "
@@ -16320,6 +16494,9 @@ msgstr "å‰å¾€ %{page} 页"
msgid "Go to parent"
msgstr "转到上一级"
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr "转到上一页"
@@ -16488,6 +16665,9 @@ msgstr "群组%{group_name}已安排删除。"
msgid "Group %{group_name} was successfully created."
msgstr "群组 %{group_name} å·²æˆåŠŸåˆ›å»ºã€‚"
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr "群组Git LFS状æ€ï¼š"
@@ -16506,6 +16686,9 @@ msgstr "å¿…é¡»å¯ç”¨ç¾¤ç»„SAMLæ‰èƒ½è¿›è¡Œæµ‹è¯•"
msgid "Group URL"
msgstr "群组URL"
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr "群组应用程åºï¼š%{name}"
@@ -16569,9 +16752,6 @@ msgstr "cluster_type为:group时群组为必需"
msgid "Group jobs by"
msgstr "分组作业按"
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr "群组维护者å¯ä»¥åœ¨é€šè¿‡ %{link} 注册群组级 Runner"
-
msgid "Group members"
msgstr "群组æˆå‘˜"
@@ -16596,6 +16776,9 @@ msgstr "群组导航"
msgid "Group overview content"
msgstr "群组概述内容"
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr "群组路径已被å ç”¨ï¼Œæˆ‘们已ç»æŽ¨è了一个å¯ç”¨çš„。"
@@ -16608,9 +16791,6 @@ msgstr "群组æµæ°´çº¿åˆ†é’Ÿæ•°å·²æˆåŠŸé‡ç½®ã€‚"
msgid "Group project URLs are prefixed with the group namespace"
msgstr "群组项目的URL以群组命å空间为å‰ç¼€"
-msgid "Group projects"
-msgstr "群组项目"
-
msgid "Group requires separate account"
msgstr "群组需è¦å•ç‹¬è´¦æˆ·"
@@ -16851,18 +17031,12 @@ msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr "SAML群组链接已æˆåŠŸåˆ é™¤ã€‚"
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr "SCIM API 端点 URL"
-
msgid "GroupSAML|SCIM Token"
msgstr "SCIM 令牌"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML令牌签åè¯ä¹¦çš„SHA1指纹。请从身份验è¯æ供商处获å–(也å¯ä»¥è¢«ç§°ä¸ºâ€œæ‹‡æŒ‡çº¹â€ï¼‰ã€‚"
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr "SCIM 令牌现在已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„å€¼ï¼Œæ‚¨éœ€è¦ "
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr "SCIM 令牌现已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„值,您需è¦%{linkStart}将其é‡ç½®%{linkEnd}。"
@@ -16887,9 +17061,6 @@ msgstr "有效的SAMLå“应"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr "在ç¦æ­¢å¤–部派生标志å¯ç”¨åŽï¼Œç¾¤ç»„æˆå‘˜å°†åªèƒ½åœ¨æ‚¨çš„群组内派生项目。"
-msgid "GroupSAML|Your SCIM token"
-msgstr "您的 SCIM 令牌"
-
msgid "GroupSAML|as %{access_level}"
msgstr "以%{access_level}身份"
@@ -16920,8 +17091,11 @@ msgstr "æœç´¢ç¾¤ç»„"
msgid "GroupSelect|Select a group"
msgstr "选择一个群组"
-msgid "GroupSettings|Allow project access token creation"
-msgstr "å…许创建项目访问令牌"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
+msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
msgstr "应用到所有å­ç¾¤ç»„,除éžè¢«ç¾¤ç»„所有者覆盖。已添加到项目的群组将失去访问æƒé™ã€‚"
@@ -16968,6 +17142,9 @@ msgstr "ç¦ç”¨ç”µå­é‚®ä»¶é€šçŸ¥"
msgid "GroupSettings|Disable group mentions"
msgstr "ç¦ç”¨ç¾¤ç»„æåŠ"
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr "å¯ç”¨å»¶è¿Ÿé¡¹ç›®åˆ é™¤"
@@ -16986,9 +17163,6 @@ msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr "覆盖群组ã€å­ç»„和项目所有æˆå‘˜çš„用户通知å好设置。"
-msgid "GroupSettings|Parent Group"
-msgstr "父组"
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "群组æµæ°´çº¿è®¾ç½®å·²æ›´æ–°"
@@ -17016,9 +17190,6 @@ msgstr "项目将在 %{waiting_period}天延迟åŽæ°¸ä¹…删除,由å­ç»„继承
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr "项目将在%{waiting_period}天延迟åŽæ°¸ä¹…删除,此延迟在实例设置中%{link_start}å¯ä»¥ç”±ç®¡ç†å‘˜å®šä¹‰%{link_end} ,由å­ç¾¤ç»„继承。"
-msgid "GroupSettings|Search groups"
-msgstr "æœç´¢ç¾¤ç»„"
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr "选择 %{code_start}.gitlab/insights.yml%{code_end} 文件的项目"
@@ -17061,8 +17232,8 @@ msgstr "此设置已应用于 %{ancestor_group}。 您å¯ä»¥è¦†ç›–此设置或 %
msgid "GroupSettings|Transfer group"
msgstr "转移群组"
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
-msgstr "用户å¯ä»¥ä¸ºè¯¥ç¾¤ç»„中的项目创建 %{link_start}项目访问令牌%{link_end}。"
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
+msgstr ""
msgid "GroupSettings|What are badges?"
msgstr "什么是徽章?"
@@ -17142,9 +17313,6 @@ 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."
msgstr "%{linkStart}群组%{linkEnd}å…许您在多个项目之间进行管ç†ä¸Žå作。群组的æˆå‘˜æ‹¥æœ‰è®¿é—®å…¶ä¸­æ‰€æœ‰é¡¹ç›®çš„æƒé™ã€‚"
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr "询问您的管ç†å‘˜ %{enable_link_start}å¯ç”¨%{enable_link_end} 群组è¿ç§»ã€‚"
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr "将相关项目组åˆåœ¨ä¸€èµ·å¹¶ä¸€æ¬¡æŽˆäºˆæˆå‘˜è®¿é—®å¤šä¸ªé¡¹ç›®çš„æƒé™ã€‚"
@@ -17199,8 +17367,8 @@ msgstr "请填写个人访问令牌。"
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr "为å¦ä¸€ä¸ª GitLab 实例æ供凭æ®ä»¥ç›´æŽ¥å¯¼å…¥æ‚¨çš„群组。"
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
-msgstr "此功能已弃用并由%{docs_link_start}群组è¿ç§»%{docs_link_end}å–代。"
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
+msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
msgstr "è¦å¯¼å…¥ç¾¤ç»„,请导航到 GitLab æºå®žä¾‹çš„群组设置, %{link_start}生æˆå¯¼å‡ºæ–‡ä»¶%{link_end},然åŽåœ¨æ­¤å¤„上传。"
@@ -17426,6 +17594,33 @@ msgstr[0] "éšè—值"
msgid "Hide values"
msgstr "éšè—值"
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr "存在高å±æˆ–未知æ¼æ´ž"
@@ -17486,9 +17681,6 @@ msgstr "例行维护"
msgid "Housekeeping successfully started"
msgstr "已开始维护"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr "管家,导出,路径,转移,删除,存档。"
-
msgid "How do I configure Akismet?"
msgstr "如何é…ç½® Akismet ?"
@@ -17525,9 +17717,6 @@ msgstr "如何使用 web 终端?"
msgid "How do I use file templates?"
msgstr "如何使用文件模æ¿ï¼Ÿ"
-msgid "How it works"
-msgstr "工作原ç†"
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr "对象标记被删除和实际被删除之间的天数。"
@@ -17543,6 +17732,9 @@ msgstr "æˆ‘æŽ¥å— %{terms_link}"
msgid "I forgot my password"
msgstr "我忘记了密ç "
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr "我想探索 GitLab,看看是å¦å€¼å¾—切æ¢åˆ°è¿™é‡Œ"
@@ -17642,6 +17834,18 @@ msgstr "标识符"
msgid "Identities"
msgstr "身份标识"
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr "如果任何索引字段超过此é™åˆ¶ï¼Œåˆ™å°†å…¶æˆªæ–­ä¸ºæ­¤å­—符数。其余内容既ä¸ç¼–入索引也ä¸å¯æœç´¢ã€‚è¿™ä¸é€‚用于仓库和 wiki 索引。对于无é™å­—符,将此设置为 0。"
@@ -17666,9 +17870,6 @@ msgstr "如果ç¦ç”¨ï¼Œåˆ™åªæœ‰ç®¡ç†å‘˜å¯ä»¥é…置仓库镜åƒã€‚"
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr "如果å¯ç”¨ï¼ŒGitLab 将使用 Geo 处ç†å¯¹è±¡å­˜å‚¨å¤åˆ¶ã€‚ %{linkStart}了解更多%{linkEnd}"
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr "如果å¯ç”¨ï¼Œåˆ™ä½¿ç”¨å¤–部æœåŠ¡ä¸Šçš„分类标签æ¥éªŒè¯å¯¹é¡¹ç›®çš„访问æƒé™ã€‚"
-
msgid "If enabled, only protected branches will be mirrored."
msgstr "如果å¯ç”¨ï¼Œåˆ™åªä¼šé•œåƒå—ä¿æŠ¤çš„分支。"
@@ -18266,6 +18467,9 @@ msgstr "在 GitLab 中å¯åŠ¨è‡ªåŠ¨ç¼©æ”¾Runner"
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr "ç«‹å³åœ¨ä¸åˆ°ä¸€åˆ†é’Ÿçš„时间内开始 GitLab Ultimate 试用,无需信用å¡ã€‚"
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr "开始å…费试用旗舰版 - 无需信用å¡"
@@ -18368,6 +18572,9 @@ msgstr "éžå¸¸å›°éš¾"
msgid "InProductMarketing|Very easy"
msgstr "éžå¸¸å®¹æ˜“"
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 "我们知é“一些关于效率的事情,我们想分享给大家。注册GitLab Ultimateçš„å…费试用版,您的团队将从第一天开始使用它。"
@@ -18402,7 +18609,7 @@ msgid "InProductMarketing|from Bitbucket"
msgstr "从 Bitbucket"
msgid "InProductMarketing|go to about.gitlab.com"
-msgstr "转到about.gitlab.com"
+msgstr "转到about.gitlab.cn"
msgid "InProductMarketing|how easy it is to get started"
msgstr "如何轻æ¾åœ°å¼€å§‹"
@@ -18443,6 +18650,9 @@ msgstr "事件"
msgid "Incident Management Limits"
msgstr "事件管ç†é™åˆ¶"
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr "事件模æ¿ï¼ˆå¯é€‰ï¼‰ã€‚"
@@ -18864,9 +19074,6 @@ msgstr "添加集æˆ"
msgid "Integrations|Add namespace"
msgstr "添加命å空间"
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr "添加命å空间仅适用于å…许跨站点 cookie çš„æµè§ˆå™¨ã€‚添加命å空间时,请使用 %{firefox_link_start}Firefox%{link_end} %{chrome_link_start}Google Chrome%{link_end},或在æµè§ˆå™¨ä¸­å¯ç”¨è·¨ç«™ç‚¹ cookie。"
-
msgid "Integrations|All details"
msgstr "所有详细信æ¯"
@@ -18879,9 +19086,6 @@ msgstr "使用自定义设置加载项目时å‘生错误。"
msgid "Integrations|Branches for which notifications are to be sent"
msgstr "è¦å‘é€é€šçŸ¥çš„分支"
-msgid "Integrations|Browser limitations"
-msgstr "æµè§ˆå™¨é™åˆ¶"
-
msgid "Integrations|Comment detail:"
msgstr "评论细节:"
@@ -18951,6 +19155,9 @@ msgstr "当议题在Jira中设定的项目中创建åŽï¼ŒJira中创建的议题ä
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr "在 Packagist 上更新您的 PHP ä¾èµ–项。"
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr "链接命å空间"
@@ -18969,9 +19176,6 @@ msgstr "没有å¯ç”¨çš„命å空间。"
msgid "Integrations|No linked namespaces"
msgstr "没有链接的命å空间"
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr "注æ„:此集æˆä»…适用于 GitLab.com (SaaS) 上的账å·ã€‚"
-
msgid "Integrations|Projects using custom settings"
msgstr "使用自定义设置的项目"
@@ -19008,6 +19212,9 @@ msgstr "将有关项目事件的通知å‘é€åˆ° Unify Circuit。"
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr "将有关项目事件的通知å‘é€åˆ° Unify Circuit 对è¯ã€‚ %{docs_link}"
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr "登录以添加命å空间"
@@ -19017,6 +19224,9 @@ msgstr "标准"
msgid "Integrations|There are no projects using custom settings"
msgstr "没有使用自定义设置的项目"
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr "此集æˆå’Œç»§æ‰¿é¡¹ç›®å·²è¢«é‡ç½®ã€‚"
@@ -19045,7 +19255,7 @@ msgid "Integrations|You must have owner or maintainer permissions to link namesp
msgstr "您必须拥有所有者或维护者æƒé™æ‰èƒ½é“¾æŽ¥å‘½å空间。"
msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
-msgstr "您现在应该在 Jira Cloud 议题中看到 GitLab.com 活动。 %{linkStart}了解更多%{linkEnd}"
+msgstr "您现在应该在 Jira Cloud 议题中看到动æ€ã€‚%{linkStart}了解更多%{linkEnd}"
msgid "Integrations|You've activated every integration 🎉"
msgstr "æ‚¨å·²æ¿€æ´»æ‰€æœ‰é›†æˆ ðŸŽ‰"
@@ -19077,8 +19287,8 @@ msgstr "除外部用户外,任何登录用户å‡å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Internal URL (optional)"
msgstr "内部URL(å¯é€‰)"
-msgid "Internal error occured while delivering this webhook."
-msgstr "ä¼ é€æ­¤ webhook æ—¶å‘生内部错误。"
+msgid "Internal error occurred while delivering this webhook."
+msgstr ""
msgid "Internal users"
msgstr "内部用户"
@@ -19591,7 +19801,7 @@ msgid "IssueBoards|Switch board"
msgstr "切æ¢çœ‹æ¿"
msgid "IssueList|created %{timeAgoString} by %{user}"
-msgstr "ç”± %{user} 创建于 %{timeAgoString} å‰"
+msgstr "由 %{user} 创建于 %{timeAgoString}"
msgid "IssueTracker|Custom issue tracker"
msgstr "自定义议题跟踪器"
@@ -20077,7 +20287,7 @@ msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart
msgstr "ä½¿ç”¨è½¬æ¢ ID 设置自定义最终状æ€ã€‚ %{linkStart}äº†è§£è½¬æ¢ ID%{linkEnd}"
msgid "JiraService|Sign in to GitLab.com to get started."
-msgstr "登录 GitLab.com 以开始使用。"
+msgstr "登录并开始使用。"
msgid "JiraService|This feature requires a Premium plan."
msgstr "此功能需è¦é«˜çº§è®¡åˆ’。"
@@ -20666,10 +20876,10 @@ msgid "Launch a ready-to-code development environment for your project."
msgstr "为您的项目å¯åŠ¨ä¸€ä¸ªçŽ°æˆçš„代ç å¼€å‘环境。"
msgid "Layout|Fixed"
-msgstr ""
+msgstr "固定"
msgid "Layout|Fluid"
-msgstr ""
+msgstr "æµåŠ¨"
msgid "Lead Time"
msgstr "交付时间"
@@ -20896,6 +21106,9 @@ msgstr "许å¯è¯åˆè§„"
msgid "License file"
msgstr "许å¯è¯æ–‡ä»¶"
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr "许å¯è¯æ¦‚览"
@@ -21212,9 +21425,6 @@ msgstr "正在加载..."
msgid "Loading…"
msgstr "正在加载..."
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr "é’©å­å’ŒæœåŠ¡å¯ä»¥è®¿é—®çš„本地IP地å€å’ŒåŸŸå。"
-
msgid "Localization"
msgstr "本地化"
@@ -21230,6 +21440,9 @@ msgstr "é”定"
msgid "Lock %{issuableDisplayName}"
msgstr "é”定 %{issuableDisplayName}"
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr "é”定æˆå‘˜èº«ä»½åˆ°LDAPåŒæ­¥"
@@ -21266,6 +21479,39 @@ msgstr "加é”å¯ä»¥é”定特定的文件或文件夹。"
msgid "Locks the discussion."
msgstr "é”定讨论."
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "使用智能å¡ç™»å½•"
@@ -22040,6 +22286,12 @@ msgstr "åˆå¹¶è¯·æ±‚ä¾èµ–"
msgid "Merge request events"
msgstr "åˆå¹¶è¯·æ±‚事件"
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr "åˆå¹¶è¯·æ±‚报告"
@@ -22058,9 +22310,18 @@ msgstr "åˆå¹¶åˆ†æ”¯å¹¶è§£å†³å‡ºçŽ°çš„任何冲çª"
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr "åˆå¹¶ä¸å¯ç”¨ï¼šåˆå¹¶è¯·æ±‚åœ¨æ¬¡è¦ Geo 节点中是åªè¯»çš„。"
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "当æµæ°´çº¿æˆåŠŸæ—¶åˆå¹¶"
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr "æ交到æºåˆ†æ”¯"
@@ -22182,10 +22443,10 @@ msgid "MergeRequest|Can't show this merge request because the fork project was d
msgstr "无法显示此åˆå¹¶è¯·æ±‚,因为派生项目已被删除。"
msgid "MergeRequest|Can't show this merge request because the source branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch."
-msgstr ""
+msgstr "无法显示此åˆå¹¶è¯·æ±‚,因为æºåˆ†æ”¯ %{branch_badge} 缺少项目 %{path_badge}。关闭此åˆå¹¶è¯·æ±‚或更新æºåˆ†æ”¯ã€‚"
msgid "MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch."
-msgstr ""
+msgstr "无法显示此åˆå¹¶è¯·æ±‚,因为项目 %{branch_badge} 中缺少目标分支 %{path_badge}。关闭此åˆå¹¶è¯·æ±‚或更新目标分支。"
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr "比较%{target}和%{source}"
@@ -22879,9 +23140,6 @@ msgstr "月"
msgid "More Information"
msgstr "更多信æ¯"
-msgid "More Slack commands"
-msgstr "更多Slack命令"
-
msgid "More actions"
msgstr "更多æ“作"
@@ -22903,9 +23161,6 @@ msgstr "这里"
msgid "More information."
msgstr "更多信æ¯ã€‚"
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "è¶…å‰ %{number_commits_distance} 个æ交与 %{default_branch} ä¸åŒ"
@@ -23081,11 +23336,11 @@ msgstr "您已ç»è¾¾åˆ°äº†ä¸€ä¸ªæˆ–多个项目的 %{free_size_limit} çš„å…è´¹å
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr "推é€åˆ°æ‚¨çš„仓库,创建æµæ°´çº¿ï¼Œåˆ›å»ºè®®é¢˜æˆ–添加评论。如需å‡å°‘存储使用,请删除未使用的仓库,产物,wiki,议题和æµæ°´çº¿ã€‚"
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
-msgstr "待定用户必须ç»è¿‡ç¾¤ç»„所有者的审查和批准。了解有关 %{user_caps_link_start}用户上é™%{link_end} å’Œ %{users_pending_approval_link_start}用户等待批准%{link_end}。"
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
+msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
-msgstr "查看待处ç†çš„用户批准"
+msgid "NamespaceUserCap|View pending approvals"
+msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
msgstr "您的群组已达到å¯è®¡è´¹æˆå‘˜ä¸Šé™"
@@ -23109,37 +23364,37 @@ msgid "Navigation bar"
msgstr "导航æ "
msgid "NavigationTheme|Blue"
-msgstr ""
+msgstr "è“色"
msgid "NavigationTheme|Dark"
-msgstr ""
+msgstr "深色"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "深色模å¼ï¼ˆalpha)"
msgid "NavigationTheme|Green"
-msgstr ""
+msgstr "绿色"
msgid "NavigationTheme|Indigo"
-msgstr ""
+msgstr "é›è“"
msgid "NavigationTheme|Light"
-msgstr ""
+msgstr "浅色"
msgid "NavigationTheme|Light Blue"
-msgstr ""
+msgstr "æµ…è“"
msgid "NavigationTheme|Light Green"
-msgstr ""
+msgstr "浅绿"
msgid "NavigationTheme|Light Indigo"
-msgstr ""
+msgstr "æµ…é›è“"
msgid "NavigationTheme|Light Red"
-msgstr ""
+msgstr "浅红"
msgid "NavigationTheme|Red"
-msgstr ""
+msgstr "红色"
msgid "Nav|Help"
msgstr "帮助"
@@ -23189,9 +23444,6 @@ msgstr "%{strongOpen}所有%{strongClose}pod"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr "%{strongOpen}任何%{strongClose}端å£"
-msgid "NetworkPolicies|.yaml"
-msgstr ".yaml"
-
msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml模å¼"
@@ -23270,9 +23522,6 @@ msgstr "å·²æˆåŠŸæ›´æ”¹ç­–ç•¥%{policyName}"
msgid "NetworkPolicies|Policy definition"
msgstr "策略定义"
-msgid "NetworkPolicies|Rule"
-msgstr "规则"
-
msgid "NetworkPolicies|Rule mode"
msgstr "规则模å¼"
@@ -23291,9 +23540,6 @@ msgstr "出现错误,无法获å–ç­–ç•¥"
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr "è¦å¯ç”¨è­¦æŠ¥ï¼Œè¯·å…ˆ%{installLinkStart}安装代ç†%{installLinkEnd}。"
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr "ä¸åŒ¹é…任何规则的æµé‡å°†è¢«é˜»æ­¢ã€‚"
-
msgid "NetworkPolicies|all DNS names"
msgstr "所有DNS域å"
@@ -23355,7 +23601,7 @@ msgid "New %{issueType}"
msgstr "新建%{issueType}"
msgid "New %{type} in %{project}"
-msgstr ""
+msgstr "在 %{project} 中新建 %{type}"
msgid "New Application"
msgstr "新建应用"
@@ -23808,6 +24054,9 @@ msgstr "无里程碑"
msgid "No milestones to show"
msgstr "没有è¦æ˜¾ç¤ºçš„里程碑"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "没有其他具有此类å称或æ述的标记"
@@ -23835,6 +24084,9 @@ msgstr "没有此å称或æ述的优先标记"
msgid "No profiles found"
msgstr "未找到é…置文件"
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr "未找到项目"
@@ -23901,8 +24153,8 @@ msgstr "æ— æ¼æ´ž"
msgid "No webhook events"
msgstr "没有 webhook 事件"
-msgid "No webhooks found, add one in the form above."
-msgstr "没有找到Webhook,请通过上é¢è¡¨å•æ·»åŠ ã€‚"
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
@@ -24002,7 +24254,7 @@ msgid "Note: Consider asking your GitLab administrator to configure %{github_int
msgstr "æ示:如GitLab管ç†å‘˜é…ç½® %{github_integration_link},将å…许通过GitHub登录并å…许导入Github代ç ä»“库而ä¸éœ€è¦ä¸ªäººè®¿é—®ä»¤ç‰Œã€‚"
msgid "Note: current forks will keep their visibility level."
-msgstr ""
+msgstr "注æ„:当å‰æ´¾ç”Ÿï¼ˆfork)将ä¿æŒå…¶å¯è§ç­‰çº§ã€‚"
msgid "NoteForm|Note"
msgstr "注æ„"
@@ -24420,10 +24672,10 @@ msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{lear
msgstr "%{learnMoreLinkStart}了解有关按需扫æ的更多信æ¯%{learnMoreLinkEnd}。"
msgid "OnDemandScans|Are you sure you want to delete this scan?"
-msgstr ""
+msgstr "您确定è¦åˆ é™¤æ­¤æ‰«æå—?"
msgid "OnDemandScans|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法删除ä¿å­˜çš„扫æ。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
msgstr "无法获å–按需扫æ。请刷新页é¢ï¼Œæˆ–ç¨åŽé‡è¯•ã€‚"
@@ -24444,7 +24696,7 @@ msgid "OnDemandScans|Create new site profile"
msgstr "创建新的站点é…置文件"
msgid "OnDemandScans|Delete profile"
-msgstr ""
+msgstr "删除é…置文件"
msgid "OnDemandScans|Description (optional)"
msgstr "æè¿° (å¯é€‰)"
@@ -24453,7 +24705,7 @@ msgid "OnDemandScans|Edit on-demand DAST scan"
msgstr "编辑按需扫æDAST"
msgid "OnDemandScans|Edit profile"
-msgstr ""
+msgstr "编辑é…置文件"
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr "例如:测试SQL注入的登录页é¢"
@@ -24498,7 +24750,7 @@ msgid "OnDemandScans|Repeats"
msgstr "é‡å¤"
msgid "OnDemandScans|Run scan"
-msgstr ""
+msgstr "è¿è¡Œæ‰«æ"
msgid "OnDemandScans|Save and run scan"
msgstr "ä¿å­˜å¹¶è¿è¡Œæ‰«æ"
@@ -24507,7 +24759,7 @@ msgid "OnDemandScans|Save scan"
msgstr "ä¿å­˜æ‰«æ"
msgid "OnDemandScans|Scan library"
-msgstr ""
+msgstr "扫æ库"
msgid "OnDemandScans|Scan name"
msgstr "扫æå称"
@@ -24546,7 +24798,7 @@ msgid "OnDemandScans|There are no running scans."
msgstr "没有è¿è¡Œä¸­çš„扫æ。"
msgid "OnDemandScans|There are no saved scans."
-msgstr ""
+msgstr "没有ä¿å­˜çš„扫æ。"
msgid "OnDemandScans|There are no scheduled scans."
msgstr "没有计划中的扫æ。"
@@ -24727,7 +24979,7 @@ msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "æ“作超时。请检查 Pod 日志 %{pod_name} 了解更多信æ¯ã€‚"
msgid "Operations"
-msgstr ""
+msgstr "è¿ç»´"
msgid "Operations Dashboard"
msgstr "è¿ç»´ä»ªè¡¨æ¿"
@@ -24804,8 +25056,29 @@ msgstr "我们的团队已收到通知,请é‡è¯•ã€‚"
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr "ä¸ç¬¦åˆè¯¥é¡¹ç›®æ”¿ç­–,应予以删除"
-msgid "Outbound requests"
-msgstr "外å‘请求"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr "GitLabå¯èƒ½æ— æ³•æ­£å¸¸å·¥ä½œï¼Œå› ä¸ºæ‚¨æ­£åœ¨ä½¿ç”¨è¿‡æ—¶çš„æµè§ˆå™¨ã€‚"
@@ -25420,9 +25693,6 @@ msgstr "粘贴项目路径(å³gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
msgstr "将此DSN粘贴到您的Sentry SDK"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr "粘贴您的SSH 公钥,通常包å«åœ¨æ–‡ä»¶ '~/.ssh/id_ed25519.pub' 或 '~/.ssh/id_rsa.pub' 中,并以“ssh-ed25519â€æˆ–“ssh-rsaâ€å¼€å¤´ã€‚ä¸è¦ç²˜è´´æ‚¨çš„SSHç§é’¥ï¼Œå› ä¸ºè¿™ä¼šæ³„露您的身份信æ¯ã€‚"
-
msgid "Patch to apply"
msgstr "è¦åº”用的补ä¸"
@@ -25561,11 +25831,14 @@ msgstr "对象"
msgid "PerformanceBar|wall"
msgstr "墙"
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr "周期(秒)"
msgid "Permalink"
-msgstr ""
+msgstr "永久链接"
msgid "Permanently delete project"
msgstr "永久删除项目"
@@ -25579,8 +25852,8 @@ msgstr "æƒé™"
msgid "Permissions Help"
msgstr "æƒé™å¸®åŠ©"
-msgid "Permissions, LFS, 2FA"
-msgstr "æƒé™ï¼ŒLFS,2FA"
+msgid "Permissions and group features"
+msgstr ""
msgid "Personal Access Token"
msgstr "个人访问凭è¯"
@@ -25846,9 +26119,6 @@ msgstr "æµæ°´çº¿"
msgid "Pipelines charts"
msgstr "æµæ°´çº¿ç»Ÿè®¡å›¾"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr "åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿å·²é…置。游离的æµæ°´çº¿è¿è¡ŒäºŽåˆå¹¶è¯·æ±‚环境,而éžåˆå¹¶ç»“果。更多内容请å‚阅关于åˆå¹¶ç»“果的æµæ°´çº¿æ–‡æ¡£ã€‚"
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "“%{project_name}â€çš„æµæ°´çº¿è®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚"
@@ -25861,6 +26131,9 @@ msgstr "添加代ç è´¨é‡ä½œä¸š"
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "您确定è¦è¿è¡Œè¿™æ¡æµæ°´çº¿å—?"
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr "自信地构建"
@@ -25873,14 +26146,14 @@ msgstr "CI lint"
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr "用于测试和部署您的 %{name} 项目的 CI/CD 模æ¿ã€‚"
-msgid "Pipelines|Child pipeline"
-msgstr "å­æµæ°´çº¿"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
msgid "Pipelines|Clear runner caches"
msgstr "清除Runner缓存"
msgid "Pipelines|Configuration validation currently not available."
-msgstr ""
+msgstr "é…置验è¯ç›®å‰ä¸å¯ç”¨ã€‚"
msgid "Pipelines|Copy trigger token"
msgstr "å¤åˆ¶è§¦å‘令牌"
@@ -26038,11 +26311,29 @@ msgstr "查看åˆå¹¶çš„ YAML"
msgid "Pipelines|Visualize"
msgstr "å¯è§†åŒ–"
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr "无效"
-msgid "Pipelines|parent"
-msgstr "父级"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
msgid "Pipeline|Actions"
msgstr "æ“作"
@@ -26224,6 +26515,9 @@ msgstr "方案"
msgid "Plan:"
msgstr "计划:"
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr "PlantUML"
@@ -26239,6 +26533,12 @@ msgstr "è¿è¡Œæ‰€æœ‰æ‰‹åŠ¨ä½œä¸š"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "想è¦è¯„论请 %{link_to_register} 或 %{link_to_sign_in}"
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr "请%{startTagRegister}注册%{endRegisterTag}或%{startTagSignIn}登录%{endSignInTag}å†å›žå¤"
@@ -26396,7 +26696,7 @@ msgid "Please select a file"
msgstr "请选择一个文件"
msgid "Please select a group"
-msgstr ""
+msgstr "请选择一个群组"
msgid "Please select a group."
msgstr "请选择一个群组。"
@@ -26593,6 +26893,9 @@ msgstr "时间å好"
msgid "Preferences|Use relative times"
msgstr "使用相对时间"
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr "上一页"
@@ -26818,6 +27121,9 @@ msgstr "头åƒè£å‰ª"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr "自我介ç»"
@@ -26842,9 +27148,6 @@ msgstr "城市,国家"
msgid "Profiles|Clear status"
msgstr "清除状æ€"
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "å•å‡»å›¾æ ‡ä»¥ä½¿ç”¨ä»¥ä¸‹æœåŠ¡ä¹‹ä¸€æ¿€æ´»ç™»å½•"
-
msgid "Profiles|Commit email"
msgstr "æ交邮件"
@@ -26945,7 +27248,7 @@ msgid "Profiles|Invalid username"
msgstr "用户å无效"
msgid "Profiles|Job title"
-msgstr ""
+msgstr "èŒä½"
msgid "Profiles|Key"
msgstr "密钥"
@@ -27005,10 +27308,10 @@ msgid "Profiles|Profile was successfully updated"
msgstr "个人资料已æˆåŠŸæ›´æ–°"
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "称呼"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "读音"
msgid "Profiles|Public avatar"
msgstr "公开头åƒ"
@@ -27022,6 +27325,9 @@ msgstr "公开å¯è§çš„ç§æœ‰SSH密钥å¯èƒ½ä¼šæŸå®³æ‚¨çš„系统。"
msgid "Profiles|Remove avatar"
msgstr "删除头åƒ"
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr "设置新个人资料图片"
@@ -27067,9 +27373,6 @@ msgstr "åŒé‡è®¤è¯"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "键入您的 %{confirmationValue} 以确认:"
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr "通常以“ssh-ed25519 …â€æˆ–“ssh-rsa …â€å¼€å¤´"
-
msgid "Profiles|Update profile settings"
msgstr "更新个人资料设置"
@@ -27095,7 +27398,7 @@ msgid "Profiles|Using emojis in names seems fun, but please try to set a status
msgstr "姓å中使用表情符å·è™½ç„¶æœ‰è¶£ï¼Œä½†è¯·è½¬åˆ°çŠ¶æ€ä¿¡æ¯é‡Œä½¿ç”¨å®ƒ"
msgid "Profiles|Website url"
-msgstr ""
+msgstr "网站 URL"
msgid "Profiles|What's your status?"
msgstr "您当å‰çš„状æ€ï¼Ÿ"
@@ -27560,7 +27863,7 @@ msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr "%{link_start}什么是æ述模æ¿ï¼Ÿ%{link_end}"
msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
-msgstr ""
+msgstr "%{link_start}我å¯ä»¥ä½¿ç”¨å“ªäº›å˜é‡ï¼Ÿ%{link_end}"
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr "å½±å“åˆå¹¶å®Œæˆçš„æ–¹å¼å’Œæ—¶é—´çš„其他设置。"
@@ -27592,11 +27895,14 @@ msgstr "默认情况下,å¤é€‰æ¡†æ˜¯å¯è§å’Œé€‰ä¸­çš„。"
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr "默认情况下,å¤é€‰æ¡†æ˜¯å¯è§å’Œæœªé€‰ä¸­çš„。"
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "选择åˆå¹¶æ–¹æ³•ã€åˆå¹¶é€‰é¡¹ï¼Œåˆå¹¶æ£€æŸ¥ä»¥åŠåˆå¹¶å»ºè®®"
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
-msgstr "选择åˆå¹¶æ–¹æ³•ã€åˆå¹¶é€‰é¡¹ã€åˆå¹¶æ£€æŸ¥ã€åˆå¹¶å»ºè®®ä»¥åŠè®¾ç½®é»˜è®¤åˆå¹¶è¯·æ±‚æ述模æ¿"
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "é…置您的项目资æºå¹¶ç›‘控它们的è¿è¡ŒçŠ¶å†µã€‚"
@@ -27673,6 +27979,12 @@ msgstr "全局"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr "çªå‡ºæ˜¾ç¤ºéšè—çš„ unicode 字符的用法。这些对从å³åˆ°å·¦çš„语言无害,但也å¯ç”¨äºŽæ½œåœ¨çš„æ¼æ´žåˆ©ç”¨ã€‚"
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -27718,6 +28030,9 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr "已批准的åˆå¹¶è¯·æ±‚已排队,æµæ°´çº¿åœ¨åˆå¹¶å‰éªŒè¯æºå’Œç›®æ ‡åˆ†æ”¯çš„åˆå¹¶ç»“果。 %{link_start}什么是åˆå¹¶é˜Ÿåˆ—?%{link_end}"
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "åˆå¹¶å»ºè®®"
@@ -27818,13 +28133,13 @@ msgid "ProjectSettings|Target project"
msgstr "目标项目"
msgid "ProjectSettings|The commit message used when applying merge request suggestions."
-msgstr ""
+msgstr "应用åˆå¹¶è¯·æ±‚建议时使用的æ交消æ¯ã€‚"
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
-msgstr ""
+msgstr "åˆå¹¶æ—¶ä½¿ç”¨çš„æ交消æ¯ï¼Œå¦‚æžœåˆå¹¶æ–¹æ³•åˆ›å»ºäº†åˆå¹¶æ交。"
msgid "ProjectSettings|The commit message used when squashing commits."
-msgstr ""
+msgstr "压缩æ交时使用的æ交消æ¯ã€‚"
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr "在此派生项目中创建的åˆå¹¶è¯·æ±‚的默认目标项目。"
@@ -27844,9 +28159,6 @@ msgstr "此设置应用于æœåŠ¡å™¨çº§åˆ«ï¼Œä½†å·²è¢«è¯¥é¡¹ç›®è¦†ç›–。"
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "此设置将应用于所有项目,除éžè¢«ç®¡ç†å‘˜è¦†ç›–。"
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr "è¦å¯ç”¨æ­¤åŠŸèƒ½ï¼Œè¯·é…ç½®æµæ°´çº¿ã€‚ %{link_start}如何为åˆå¹¶è¯·æ±‚é…ç½®æµæ°´çº¿ï¼Ÿ%{link_end}"
-
msgid "ProjectSettings|Transfer project"
msgstr "转移项目"
@@ -27868,8 +28180,8 @@ msgstr "用户å¯ä»¥è¯·æ±‚访问"
msgid "ProjectSettings|View and edit files in this project."
msgstr "查看和编辑此项目中的文件。"
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
-msgstr "查看和编辑此项目中的文件。éžé¡¹ç›®æˆå‘˜å°†åªæœ‰è¯»å–æƒé™ã€‚"
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
+msgstr ""
msgid "ProjectSettings|View project analytics."
msgstr "查看项目分æžã€‚"
@@ -27886,8 +28198,8 @@ msgstr "关于潜在的ä¸éœ€è¦çš„字符的警告"
msgid "ProjectSettings|What are badges?"
msgstr "什么是徽章?"
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr "在 CI/CD é…置文件中å¯ç”¨åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æ—¶ï¼Œæµæ°´çº¿ä¼šéªŒè¯æºåˆ†æ”¯å’Œç›®æ ‡åˆ†æ”¯çš„组åˆç»“果。 %{link_start}如何为åˆå¹¶è¯·æ±‚é…ç½®æµæ°´çº¿ï¼Ÿ%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
+msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr "当出现åˆå¹¶å†²çªæ—¶ï¼Œç”¨æˆ·å¯ä»¥é€‰æ‹©å˜åŸºï¼ˆrebase)。"
@@ -27980,13 +28292,13 @@ msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
msgid "ProjectView|Activity"
-msgstr ""
+msgstr "动æ€"
msgid "ProjectView|Files and Readme (default)"
-msgstr ""
+msgstr "文件和 Readme(默认)"
msgid "ProjectView|Readme"
-msgstr ""
+msgstr "Readme"
msgid "Projects"
msgstr "项目"
@@ -28490,7 +28802,7 @@ msgid "ProtectedBranch|Branch"
msgstr "分支"
msgid "ProtectedBranch|Branch will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "分支对开å‘人员是å¯å†™çš„。您确定å—?"
msgid "ProtectedBranch|Branch:"
msgstr "分支:"
@@ -28538,7 +28850,7 @@ msgid "ProtectedBranch|Toggle code owner approval"
msgstr "切æ¢ä»£ç æ‰€æœ‰è€…的批准"
msgid "ProtectedBranch|Unprotect"
-msgstr ""
+msgstr "å–消ä¿æŠ¤"
msgid "ProtectedBranch|What are protected branches?"
msgstr "什么是å—ä¿æŠ¤çš„分支?"
@@ -28648,9 +28960,6 @@ msgstr "公开访问帮助"
msgid "Public deploy keys"
msgstr "公共部署密钥"
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr "公共部署密钥(%{deploy_keys_count})"
-
msgid "Public pipelines"
msgstr "公开æµæ°´çº¿"
@@ -28684,8 +28993,8 @@ msgstr "购买更多时间"
msgid "Purchase more storage"
msgstr "购买更多存储"
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
-msgstr "购买步骤中å‘生错误。如果问题ä»ç„¶å­˜åœ¨ï¼Œè¯·è”ç³» support@gitlab.com。"
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
+msgstr ""
msgid "Push"
msgstr "推é€"
@@ -28838,10 +29147,10 @@ msgid "Quickly and easily edit multiple files in your project."
msgstr "快速轻æ¾åœ°ç¼–辑您项目中的多个文件。"
msgid "Quota of CI/CD minutes"
-msgstr ""
+msgstr "CI/CD 分钟数é…é¢"
msgid "Quota of CI/CD minutes:"
-msgstr ""
+msgstr "CI/CD 分钟数é…é¢ï¼š"
msgid "README"
msgstr "自述文件"
@@ -28930,6 +29239,12 @@ msgstr "Rebaseæºåˆ†æ”¯"
msgid "Rebase source branch on the target branch."
msgstr "在目标分支上Rebaseæºåˆ†æ”¯ã€‚"
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr "é‡æ–°éªŒè¯ï¼Ÿ"
@@ -28999,6 +29314,9 @@ msgstr "å‡å°‘事件管ç†è­¦æŠ¥é‡ï¼ˆä¾‹å¦‚,如果创建的议题过多)。
msgid "Reduce project visibility"
msgstr "é™ä½Žé¡¹ç›®å¯è§æ€§"
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr "é™ä½Žæ­¤é¡¹ç›®å¯è§æ€§å—?"
@@ -29072,20 +29390,20 @@ msgstr "注册功能包括:"
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr "å¯ç”¨æœåŠ¡ Ping 并注册此功能。"
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
-msgstr ""
+msgstr "Registration Features Program"
msgid "RegistrationFeatures|Want to %{feature_title} for free?"
-msgstr ""
+msgstr "想è¦å…费使用 %{feature_title} å—?"
msgid "RegistrationFeatures|send emails to users"
-msgstr ""
+msgstr "å‘用户å‘é€ç”µå­é‚®ä»¶"
msgid "RegistrationFeatures|use this feature"
-msgstr ""
+msgstr "使用此功能"
msgid "RegistrationVerification|Are you sure you want to skip this step?"
msgstr "您确定è¦è·³è¿‡è¿™ä¸€æ­¥å—?"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] "æ— éšœç¢æ€§æ‰«æ检测到%d个仅存在于æºåˆ†æ”¯çš„问题"
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr "æ— éšœç¢æ€§æ‰«æ没有检测到仅存在于æºåˆ†æ”¯çš„问题"
@@ -29833,6 +30155,9 @@ msgstr "仓库必须包å«è‡³å°‘1个文件。"
msgid "Repository size is above the limit."
msgstr "仓库大å°è¶…过é™åˆ¶ã€‚"
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr "仓库存储"
@@ -29908,9 +30233,6 @@ msgstr "%{code_start}%{help_text_url}%{code_end} 页é¢çš„请求é‡å®šå‘到 URL
msgid "Requests per period"
msgstr "æ¯ä¸ªå‘¨æœŸçš„请求"
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr "当ä¸å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„本地请求时,将å…许对本地网络上这些域/地å€çš„请求。å¯æ”¯æŒIP范围,例如1:0:0:0:0:0:0:0/124或127.0.0.0/28。当å‰ä¸æ”¯æŒåŸŸé€šé…符。多个æ¡ç›®éœ€ä½¿ç”¨é€—å·ï¼Œåˆ†å·æˆ–æ¢è¡Œç¬¦åˆ†éš”。å…许åå•æœ€å¤šå¯å®¹çº³1000个æ¡ç›®ã€‚域应使用IDNAç¼–ç ã€‚例如:example.com,192.168.1.1ã€127.0.0.0/28, xn--itlab-j1a.com。"
-
msgid "Require additional authentication for administrative tasks."
msgstr "需è¦å¯¹ç®¡ç†ä»»åŠ¡è¿›è¡Œé¢å¤–的身份验è¯ã€‚"
@@ -29929,6 +30251,9 @@ msgstr "在此项目为必须。"
msgid "Required only if you are not using role instance credentials."
msgstr "仅当您没有使用角色实例凭æ®æ—¶æ‰éœ€è¦ã€‚"
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "需求%{reference}已添加"
@@ -30054,9 +30379,6 @@ msgstr "解决者"
msgid "Resolved by %{name}"
msgstr "由%{name}解决"
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr "解æžä¸€æ¬¡IP地å€å¹¶ä½¿ç”¨å®ƒä»¬æ交请求"
-
msgid "Response"
msgstr "å“应"
@@ -30123,8 +30445,8 @@ msgstr "æ¢å¤"
msgid "Resync"
msgstr "é‡æ–°åŒæ­¥"
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
-msgstr "检索åˆè§„性报告失败。请刷新页é¢å¹¶é‡è¯•ã€‚"
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
+msgstr ""
msgid "Retry"
msgstr "é‡è¯•"
@@ -30221,15 +30543,15 @@ msgstr "撤销"
msgid "Revoked"
msgstr "已撤销"
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
msgid "Revoked impersonation token %{token_name}!"
msgstr "撤销身份模拟令牌 %{token_name}ï¼"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "撤销个人访问令牌 %{personal_access_token_name}ï¼"
-msgid "Revoked project access token %{project_access_token_name}!"
-msgstr "撤销项目访问令牌%{project_access_token_name}ï¼"
-
msgid "RightSidebar|Copy email address"
msgstr "å¤åˆ¶ç”µå­é‚®ä»¶åœ°å€"
@@ -30248,6 +30570,9 @@ msgstr "没看到您è¦å¯»æ‰¾çš„?%{linkStart}点击此处%{linkEnd}查看完æ•
msgid "Roadmap"
msgstr "路线图"
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr "角色"
@@ -30335,6 +30660,9 @@ msgstr "获å–指令时å‘生错误"
msgid "Runners|Architecture"
msgstr "架构"
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr "与一个或多个项目关è”"
@@ -30347,9 +30675,15 @@ msgstr "适用于群组中的所有项目和å­ç»„"
msgid "Runners|Can run untagged jobs"
msgstr "å¯ä»¥è¿è¡Œæœªæ ‡è®°çš„作业"
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr "注册runner的命令"
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr "å¤åˆ¶è¯´æ˜Ž"
@@ -30368,6 +30702,9 @@ msgstr "在 AWS 中部署 GitLab Runner"
msgid "Runners|Description"
msgstr "æè¿°"
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr "下载并安装二进制文件"
@@ -30383,9 +30720,6 @@ msgstr "对于æ¯ä¸ªè§£å†³æ–¹æ¡ˆï¼Œæ‚¨å°†é€‰æ‹©ä¸€ä¸ªå®¹é‡ã€‚ 1 通过自动扩
msgid "Runners|Group"
msgstr "群组"
-msgid "Runners|Group Runners"
-msgstr "群组Runner"
-
msgid "Runners|IP Address"
msgstr "IP地å€"
@@ -30414,13 +30748,13 @@ msgid "Runners|Name"
msgstr "å称"
msgid "Runners|Never contacted"
-msgstr ""
+msgstr "未连接过"
msgid "Runners|New registration token generated!"
msgstr "已生æˆæ–°çš„注册令牌ï¼"
msgid "Runners|New runner, has not contacted yet"
-msgstr ""
+msgstr "新的 runner,尚未连接"
msgid "Runners|No contact from this runner in over 3 months"
msgstr "超过 3 个月没有è”系此 runner"
@@ -30434,11 +30768,14 @@ msgstr "ä¸å¯ç”¨äºŽè¿è¡Œä½œä¸š"
msgid "Runners|Offline"
msgstr "离线"
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr "在线"
-msgid "Runners|Online Runners"
-msgstr "在线 runner"
+msgid "Runners|Online runners"
+msgstr ""
msgid "Runners|Paused"
msgstr "已暂åœ"
@@ -30473,6 +30810,9 @@ msgstr "注册令牌"
msgid "Runners|Registration token copied!"
msgstr "注册令牌已å¤åˆ¶ï¼"
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "版本"
@@ -30512,18 +30852,18 @@ msgstr "å–消分é…到项目的runner。"
msgid "Runners|Runners"
msgstr "Runner"
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
-msgstr "本群组的è¿è¡Œå™¨ï¼š%{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
+msgstr ""
msgid "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."
msgstr "共享Runnerå¯ç”¨äºŽ GitLab 实例中的æ¯ä¸ªé¡¹ç›®ã€‚如果您希望Runner仅构建特定项目,请é™åˆ¶ä¸‹è¡¨ä¸­çš„项目。当é™åˆ¶Runner的特定项目åŽï¼Œæ‚¨æ— æ³•å°†å…¶æ”¹å›žå…±äº«Runner。"
-msgid "Runners|Show Runner installation instructions"
-msgstr "显示Runner安装说明"
-
msgid "Runners|Show runner installation and registration instructions"
msgstr "显示runner安装和注册说明"
+msgid "Runners|Show runner installation instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr "获å–Runneræ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -30533,6 +30873,9 @@ msgstr "获å–标签建议时出现问题"
msgid "Runners|Stale"
msgstr "Stale"
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr "状æ€"
@@ -30546,10 +30889,7 @@ msgid "Runners|The runner will be permanently deleted and no longer available fo
msgstr "Runner 将被永久删除,ä¸å†é€‚用于项目或群组。您确定è¦ç»§ç»­å—?"
msgid "Runners|This runner has never contacted this instance"
-msgstr ""
-
-msgid "Runners|This runner is associated with one or more projects."
-msgstr "æ­¤Runner与一个或多个项目相关è”。"
+msgstr "此 runner 从未连接到此实例"
msgid "Runners|This runner is associated with specific projects."
msgstr "æ­¤Runner与特定项目相关è”。"
@@ -30615,7 +30955,7 @@ msgid "Runners|locked"
msgstr "å·²é”定"
msgid "Runners|never contacted"
-msgstr ""
+msgstr "从未连接过"
msgid "Runners|offline"
msgstr "离线"
@@ -30704,9 +31044,6 @@ msgstr "SSL验è¯ï¼š"
msgid "SSL verification"
msgstr "SSL 验è¯"
-msgid "SVG illustration"
-msgstr "SVG图形"
-
msgid "Satisfied"
msgstr "满足"
@@ -30833,9 +31170,6 @@ msgstr "æœç´¢"
msgid "Search GitLab"
msgstr "æœç´¢ GitLab"
-msgid "Search Jira issues"
-msgstr "æœç´¢Jira议题"
-
msgid "Search a group"
msgstr "æœç´¢ç¾¤ç»„"
@@ -30897,7 +31231,7 @@ msgid "Search forks"
msgstr "æœç´¢æ´¾ç”Ÿ"
msgid "Search groups"
-msgstr ""
+msgstr "æœç´¢ç¾¤ç»„"
msgid "Search iterations"
msgstr "æœç´¢è¿­ä»£"
@@ -31126,8 +31460,8 @@ msgstr "了解更多关于æ¼æ´žæ£€æŸ¥çš„ä¿¡æ¯"
msgid "SecurityApprovals|License-Check"
msgstr "许å¯è¯æ£€æŸ¥"
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
-msgstr "当结果中包å«æ‹’ç»çš„许å¯è¯æ—¶æ ¸å‡†ä¸ºå¿…须。%{linkStart}更多信æ¯%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
msgstr "测试覆盖率é™ä½Žï¼Œéœ€æ‰¹å‡†ã€‚%{linkStart}了解更多。%{linkEnd}"
@@ -31190,7 +31524,7 @@ msgid "SecurityConfiguration|Enable Auto DevOps"
msgstr "å¯ç”¨Auto DevOps"
msgid "SecurityConfiguration|Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
-msgstr ""
+msgstr "å¯ç”¨å®‰å…¨åŸ¹è®­ï¼Œå¸®åŠ©æ‚¨çš„å¼€å‘人员学习如何修å¤æ¼æ´žã€‚å¼€å‘者å¯ä»¥æŸ¥çœ‹é€‰å®šçš„教育æ供者æ供的与å‘现的脆弱性相关的安全培训。"
msgid "SecurityConfiguration|Enabled"
msgstr "å¯ç”¨"
@@ -31258,6 +31592,9 @@ msgstr "æ¼æ´žç®¡ç†"
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "åˆå¹¶è¯·æ±‚中的æ¼æ´žè¯¦ç»†ä¿¡æ¯å’Œç»Ÿè®¡"
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr "%{branches} %{plural}"
@@ -31312,6 +31649,9 @@ msgstr "执行 %{scanType} 扫æ"
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr "如果您正在使用Auto DevOps,如果您改å˜äº†æ­¤éƒ¨åˆ†çš„策略,您的 %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} 文件将ä¸ä¼šè¢«æ›´æ–° Auto DevOps 用户应按照 %{linkStart}容器网络策略文档%{linkEnd}进行更改。"
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr "最新扫æ"
@@ -31330,21 +31670,30 @@ msgstr "åªæœ‰æ‰€æœ‰è€…å¯ä»¥æ›´æ–°å®‰å…¨ç­–略项目"
msgid "SecurityOrchestration|Policies"
msgstr "ç­–ç•¥"
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr "ç­–ç•¥æè¿°"
msgid "SecurityOrchestration|Policy editor"
msgstr "策略编辑器"
-msgid "SecurityOrchestration|Policy preview"
-msgstr "策略预览"
-
msgid "SecurityOrchestration|Policy status"
msgstr "策略状æ€"
+msgid "SecurityOrchestration|Policy summary"
+msgstr ""
+
msgid "SecurityOrchestration|Policy type"
msgstr "策略类型"
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr "规则"
@@ -31354,12 +31703,21 @@ msgstr "规则"
msgid "SecurityOrchestration|Scan Execution"
msgstr "扫æ执行"
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr "扫æ执行"
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr "扫æ执行策略åªèƒ½ç”±é¡¹ç›®æ‰€æœ‰è€…创建。"
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr "è¦æ‰§è¡Œçš„扫æ %{cadence}"
@@ -31387,6 +31745,12 @@ msgstr "对ä¸èµ·ï¼Œæ‚¨çš„过滤器没有产生任何结果。"
msgid "SecurityOrchestration|Status"
msgstr "状æ€"
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr "创建新的安全策略时出现问题"
@@ -31402,12 +31766,60 @@ msgstr "å–消项目关è”"
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr "å–消链接安全项目会移除在链接的安全项目中存储的所有策略。ä¿å­˜ä»¥ç¡®è®¤æ­¤æ“作。"
-msgid "SecurityOrchestration|Update scan execution policies"
-msgstr "更新扫æ执行策略"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
+msgstr ""
msgid "SecurityOrchestration|view results"
msgstr "查看结果"
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr "+%{count} 更多"
@@ -31417,6 +31829,9 @@ msgstr "环境"
msgid "SecurityPolicies|Policy type"
msgstr "策略类型"
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject}和%{secondProject}"
@@ -31607,7 +32022,7 @@ msgid "SecurityReports|Severity"
msgstr "严é‡ç¨‹åº¦"
msgid "SecurityReports|Software and container dependency survey"
-msgstr ""
+msgstr "软件和容器ä¾èµ–性调查"
msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
msgstr "有时扫æ工具无法确定调查结果的严é‡æ€§ï¼Œè¿™äº›ç»“æžœå¯èƒ½ä»ç„¶æ˜¯æ½œåœ¨çš„风险æ¥æºï¼Œè¯·æ‰‹åŠ¨æŸ¥çœ‹"
@@ -31738,9 +32153,6 @@ msgstr "选择下载格å¼"
msgid "Select Git revision"
msgstr "选择Git版本"
-msgid "Select GitLab project to link with your Slack team"
-msgstr "选择GitLab项目连接你的Slack团队"
-
msgid "Select Page"
msgstr "选择页é¢"
@@ -31856,7 +32268,7 @@ msgid "Select project to choose zone"
msgstr "按项目选择地域"
msgid "Select project to create %{type}"
-msgstr ""
+msgstr "选择è¦åˆ›å»º %{type} 的项目"
msgid "Select project to create issue"
msgstr "选择è¦åˆ›å»ºè®®é¢˜çš„项目"
@@ -32128,8 +32540,8 @@ msgstr "æœåŠ¡å°"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr "æœåŠ¡å°å…许人们在没有自己的用户账å·çš„情况下在您的 GitLab 实例中创建议题。它为最终用户在项目中创建议题æ供了一个唯一的电å­é‚®ä»¶åœ°å€ã€‚回å¤å¯ä»¥é€šè¿‡ GitLab ç•Œé¢æˆ–通过电å­é‚®ä»¶å‘é€ã€‚最终用户åªèƒ½é€šè¿‡ç”µå­é‚®ä»¶æŸ¥çœ‹ä¸»é¢˜ã€‚"
-msgid "Service URL"
-msgstr "æœåŠ¡ URL"
+msgid "Service Usage Data"
+msgstr ""
msgid "Service account generated successfully"
msgstr "æœåŠ¡å¸æˆ·ç”ŸæˆæˆåŠŸ"
@@ -32137,6 +32549,9 @@ msgstr "æœåŠ¡å¸æˆ·ç”ŸæˆæˆåŠŸ"
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr "æœåŠ¡ ping 在您的é…置文件中被ç¦ç”¨ï¼Œå¹¶ä¸”无法通过此表å•å¯ç”¨ã€‚"
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
@@ -32146,18 +32561,12 @@ msgstr "有关为您的实例设置æœåŠ¡å°çš„帮助,请è”系管ç†å‘˜ã€‚"
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "从æœåŠ¡å°ç”µå­é‚®ä»¶åˆ›å»ºçš„议题将显示在此处,æ¯æ¡è¯„论都æˆä¸ºç”µå­é‚®ä»¶å¯¹è¯çš„一部分。"
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr "æœåŠ¡å°å·²å¯ç”¨ä½†å°šæœªæ¿€æ´»"
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr "æœåŠ¡å°æœªå¯ç”¨"
msgid "ServiceDesk|Service Desk is not supported"
msgstr "ä¸æ”¯æŒService Desk"
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr "è¦åœ¨æ­¤å®žä¾‹ä¸Šæ¿€æ´»æœåŠ¡å°ï¼Œå®žä¾‹ç®¡ç†å‘˜å¿…须首先设置接收电å­é‚®ä»¶åœ°å€ã€‚"
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr "è¦åœ¨æ­¤å®žä¾‹ä¸Šå¯ç”¨æœåŠ¡å°ï¼Œå®žä¾‹ç®¡ç†å‘˜å¿…须首先设置接收电å­é‚®ä»¶åœ°å€ã€‚"
@@ -32210,10 +32619,10 @@ msgid "Set due date"
msgstr "设置截止日期"
msgid "Set health status"
-msgstr ""
+msgstr "设置å¥åº·çŠ¶æ€"
msgid "Set health status to %{health_status}."
-msgstr ""
+msgstr "å°†å¥åº·çŠ¶æ€è®¾ç½®ä¸º %{health_status}。"
msgid "Set iteration"
msgstr "设置迭代"
@@ -32296,8 +32705,8 @@ msgstr "é…ç½® CI/CD"
msgid "Set up Jira Integration"
msgstr "设置Jira集æˆ"
-msgid "Set up a %{type} Runner for a project"
-msgstr "为项目设置一个 %{type}的Runner"
+msgid "Set up a %{type} runner for a project"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr "设置一个硬件设备作为登录的第二个因素。"
@@ -32372,7 +32781,7 @@ msgid "Sets %{epic_ref} as parent epic."
msgstr "å°†%{epic_ref}设置为父å²è¯—。"
msgid "Sets health status to %{health_status}."
-msgstr ""
+msgstr "å°†å¥åº·çŠ¶æ€è®¾ç½®ä¸º %{health_status}。"
msgid "Sets target branch to %{branch_name}."
msgstr "设置目标分支为%{branch_name}。"
@@ -32468,9 +32877,6 @@ msgstr "é‡ç½®æµæ°´çº¿åˆ†é’Ÿæ•°"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "é‡ç½®å·²ç”¨æµæ°´çº¿åˆ†é’Ÿæ•°"
-msgid "Sherlock Transactions"
-msgstr "Sherlock事务"
-
msgid "Shimo|Go to Shimo Workspace"
msgstr "转到石墨工作区"
@@ -32510,6 +32916,9 @@ msgstr "显示所有活动"
msgid "Show all breadcrumbs"
msgstr "显示所有é¢åŒ…屑导航"
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr "显示所有议题。"
@@ -32522,6 +32931,9 @@ msgstr "显示已归档的项目"
msgid "Show archived projects only"
msgstr "仅显示已归档项目"
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr "显示相关命令"
@@ -32534,9 +32946,6 @@ msgstr "显示对此文件的评论"
msgid "Show comments only"
msgstr "仅显示评论"
-msgid "Show commit description"
-msgstr "显示æ交æè¿°"
-
msgid "Show complete raw log"
msgstr "显示完整的原始日志"
@@ -32561,6 +32970,9 @@ msgstr "显示列表"
msgid "Show one file at a time"
msgstr "一次显示一个文件"
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr "显示已关闭列表"
@@ -32599,8 +33011,8 @@ msgstr "已显示全部议题"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr "显示群组 “%{group_name}†从 2019 å¹´ 11 月 1 日到 2019 å¹´ 12 月 31 日的数æ®"
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
-msgstr "显示在此日期范围内创建的工作æµé¡¹ç›®çš„æ•°æ®ã€‚日期范围ä¸èƒ½è¶…过 %{maxDateRange} 天。"
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
+msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
msgstr "显示基于最近%{timerange}天的事件的图表。"
@@ -32692,6 +33104,9 @@ msgstr "退出并注册"
msgid "Sign up"
msgstr "注册"
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr "注册æˆåŠŸï¼è¯·ç¡®è®¤æ‚¨çš„电å­é‚®ä»¶ä»¥ç™»å½•ã€‚"
@@ -32794,9 +33209,33 @@ msgstr "Slack应用"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr "Slack集æˆå…许您通过èŠå¤©çª—å£ä¸­çš„shash命令与GitLab交互。"
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr "å‘ Slack 频é“å‘é€æœ‰å…³é¡¹ç›®äº‹ä»¶çš„通知。"
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr "1. %{slash_command_link_start}在您的Slack团队中使用此信æ¯æ·»åŠ ä¸€ä¸ªæ–œæ å‘½ä»¤%{slash_command_link_end}:"
@@ -33103,9 +33542,6 @@ msgstr "出现错误。请é‡è¯•ã€‚"
msgid "Something went wrong. Try again later."
msgstr "出现错误。请ç¨åŽå†è¯•ã€‚"
-msgid "Sorry, no epics matched your search"
-msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—"
-
msgid "Sorry, no projects matched your search"
msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„项目"
@@ -33169,9 +33605,6 @@ msgstr "最åŽè”ç³»"
msgid "SortOptions|Last created"
msgstr "最近创建"
-msgid "SortOptions|Last updated"
-msgstr "最近更新"
-
msgid "SortOptions|Least popular"
msgstr "最ä¸å—欢迎"
@@ -33505,6 +33938,9 @@ msgstr "å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
msgid "Start merge train when pipeline succeeds"
msgstr "æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr "开始æœç´¢"
@@ -33547,6 +33983,9 @@ msgstr "开始于: %{startsAt}"
msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr "å·ž/çœ/市"
@@ -33889,6 +34328,9 @@ msgstr "已订阅"
msgid "Subscribed to this %{quick_action_target}."
msgstr "已订阅 %{quick_action_target}。"
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr "订阅%{quick_action_target}。"
@@ -33919,6 +34361,27 @@ msgstr "导出许å¯è¯ä½¿ç”¨æ–‡ä»¶"
msgid "SubscriptionBanner|Upload new license"
msgstr "上传新许å¯è¯"
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr "添加席ä½"
@@ -33977,13 +34440,13 @@ msgid "SubscriptionTable|Subscription start date"
msgstr "订阅开始日期"
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
-msgstr "这是 GitLab.com 团队最近一次与您è”系的时间,关于您的欠款。"
+msgstr "这是我们最近一次与您è”系的时间,关于您的欠款。"
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
msgstr "这是自订阅开始以æ¥åŒæ—¶å­˜åœ¨çš„最大用户数é‡ã€‚"
msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
-msgstr "这是 GitLab.com 团队下一次与您è”系的时间,关于您的欠款。"
+msgstr "这是我们下一次与您è”系的时间,关于您的欠款。"
msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
msgstr "这是您更新到付费方案时需è¦è´­ä¹°çš„最大用户数é‡ã€‚"
@@ -33997,9 +34460,6 @@ msgstr "试用结æŸæ—¥æœŸ"
msgid "SubscriptionTable|Trial start date"
msgstr "试用开始日期"
-msgid "SubscriptionTable|Upgrade"
-msgstr "å‡çº§"
-
msgid "SubscriptionTable|Usage"
msgstr "使用情况"
@@ -34168,9 +34628,6 @@ msgstr "摘è¦/注释"
msgid "Sunday"
msgstr "星期日"
-msgid "SuperSonics|Activate cloud license"
-msgstr "激活云端许å¯è¯"
-
msgid "SuperSonics|Activate subscription"
msgstr "激活订阅"
@@ -34195,6 +34652,9 @@ msgstr "云授æƒ"
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr "Cloud 许å¯çŽ°å·²æŽ¨å‡ºã€‚这是激活实例和管ç†è®¢é˜…的更简å•æ–¹æ³•ã€‚阅读 %{blogPostLinkStart}åšå®¢æ–‡ç« %{blogPostLinkEnd}中的更多相关信æ¯ã€‚激活ç åœ¨ %{portalLinkStart}客户门户%{portalLinkEnd}中å¯ç”¨ã€‚"
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr "导出许å¯è¯ä½¿ç”¨æ–‡ä»¶"
@@ -34234,6 +34694,9 @@ msgstr "开始å…费试用"
msgid "SuperSonics|Subscription details"
msgstr "订阅详情"
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr "åŒæ­¥è®¢é˜…详情"
@@ -34288,6 +34751,9 @@ msgstr "您已æˆåŠŸæ·»åŠ åœ¨ %{date} 激活的许å¯è¯ã€‚有关更多详细信
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 "æ ¹æ®æ‚¨çš„åè®®æ¡æ¬¾ï¼Œæ‚¨å°†æŒ‰å­£åº¦æˆ–æ¯å¹´ä¸º %{trueUpLinkStart}超过许å¯è¯çš„用户%{trueUpLinkEnd}付费。"
+msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr "您的未æ¥æ—¥æœŸè®¸å¯è¯å·²æˆåŠŸæ·»åŠ "
@@ -34300,6 +34766,15 @@ msgstr "您的订阅信æ¯å°†å¾ˆå¿«åŒæ­¥"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr "您的订阅已æˆåŠŸæ¿€æ´»ã€‚您å¯ä»¥åœ¨ä¸‹é¢æŸ¥çœ‹è¯¦ç»†ä¿¡æ¯ã€‚"
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr "支æŒ"
@@ -34355,22 +34830,22 @@ msgid "Syntax is incorrect."
msgstr "语法ä¸æ­£ç¡®ã€‚"
msgid "SynthaxHighlightingTheme|Dark"
-msgstr ""
+msgstr "深色"
msgid "SynthaxHighlightingTheme|Light"
-msgstr ""
+msgstr "浅色"
msgid "SynthaxHighlightingTheme|Monokai"
-msgstr ""
+msgstr "Monokai"
msgid "SynthaxHighlightingTheme|None"
-msgstr ""
+msgstr "æ— "
msgid "SynthaxHighlightingTheme|Solarized Dark"
-msgstr ""
+msgstr "Solarized Dark"
msgid "SynthaxHighlightingTheme|Solarized Light"
-msgstr ""
+msgstr "Solarized Light"
msgid "System"
msgstr "系统"
@@ -34543,6 +35018,9 @@ msgstr "目标分支"
msgid "Target-Branch"
msgstr "目标分支"
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr "任务ID: %{elastic_task}"
@@ -34615,6 +35093,9 @@ msgstr "æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–"
msgid "Terms of Service and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–"
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr "Terraform"
@@ -34640,20 +35121,20 @@ msgstr[0] "您的æµæ°´çº¿ç”Ÿæˆäº†%{number}个Terraform报告"
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
-msgstr[0] ""
+msgstr[0] "%{strong_start}%{number}%{strong_end} 个 Terraform 报告生æˆå¤±è´¥"
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report was generated in your pipelines"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports were generated in your pipelines"
-msgstr[0] ""
+msgstr[0] "您的æµæ°´çº¿ç”Ÿæˆäº† %{strong_start}%{number}%{strong_end} 个 Terraform 报告"
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr "%{user}更新于%{timeAgo}"
msgid "Terraform|A Terraform report failed to generate."
-msgstr ""
+msgstr "Terraform 报告生æˆå¤±è´¥ã€‚"
msgid "Terraform|A Terraform report was generated in your pipelines."
-msgstr ""
+msgstr "在您的æµæ°´çº¿ä¸­ç”Ÿæˆäº†ä¸€ä¸ª Terraform 报告。"
msgid "Terraform|A report failed to generate."
msgstr "无法生æˆæŠ¥å‘Šã€‚"
@@ -34686,7 +35167,7 @@ msgid "Terraform|Download JSON"
msgstr "下载JSON"
msgid "Terraform|Failed to load Terraform reports"
-msgstr ""
+msgstr "加载 Terraform 报告失败"
msgid "Terraform|Generating the report caused an error."
msgstr "生æˆæŠ¥å‘Šæ—¶å‘生错误。"
@@ -34701,7 +35182,7 @@ msgid "Terraform|Job status"
msgstr "作业状æ€"
msgid "Terraform|Loading Terraform reports..."
-msgstr ""
+msgstr "正在加载 Terraform 报告..."
msgid "Terraform|Lock"
msgstr "é”定"
@@ -34740,7 +35221,7 @@ msgid "Terraform|Terraform init command"
msgstr "Terraform init 命令"
msgid "Terraform|Terraform reports"
-msgstr ""
+msgstr "Terraform 报告"
msgid "Terraform|The job %{name} failed to generate a report."
msgstr "作业 %{name} 生æˆæŠ¥å‘Šå¤±è´¥ã€‚"
@@ -34749,10 +35230,10 @@ msgid "Terraform|The job %{name} generated a report."
msgstr "作业 %{name} 生æˆäº†ä¸€ä¸ªæŠ¥å‘Šã€‚"
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
-msgstr ""
+msgstr "作业 %{strong_start}%{name}%{strong_end} 生æˆæŠ¥å‘Šå¤±è´¥ã€‚"
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} generated a report."
-msgstr ""
+msgstr "作业 %{strong_start}%{name}%{strong_end} 生æˆäº†ä¸€ä¸ªæŠ¥å‘Šã€‚"
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
msgstr "è¦ä»Žæœ¬åœ°è®¡ç®—机访问此 terraform state,请在命令行中è¿è¡Œä»¥ä¸‹å‘½ä»¤ã€‚第一行需è¦å…·æœ‰ API 读写访问æƒé™çš„个人访问令牌。 %{linkStart}如何创建个人访问令牌?%{linkEnd}."
@@ -34781,6 +35262,9 @@ msgstr "测试"
msgid "Test Cases"
msgstr "测试用例"
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -34951,9 +35435,6 @@ msgstr "就是这样,åšå¾—好ï¼"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "群组“%{group_path}â€å…许您使用SSO以登录å¸æˆ·"
-msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
-msgstr "%{featureName} 功能是 GitLab 旗舰版 试用版的一部分。"
-
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}å…许有é¢å¤–用户,这些é¢å¤–用户在更新订阅时将会产生追溯费用。"
@@ -34991,12 +35472,6 @@ msgstr "PrometheusæœåŠ¡å™¨ä»¥â€œé”™è¯¯è¯·æ±‚â€å“应。请检查您的查询æ˜
msgid "The Snowplow cookie domain."
msgstr "Snowplow cookie 域å。"
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr "在主节点上定义的URL,次è¦èŠ‚点应使用该URL与其è”系。"
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr "在主节点上定义的URL,次è¦èŠ‚点将用此网å€æ¥è”络主节点。%{linkStart}更多信æ¯%{linkEnd}"
-
msgid "The URL of the Jenkins server."
msgstr "Jenkins æœåŠ¡å™¨çš„ URL。"
@@ -35006,9 +35481,6 @@ msgstr "URL 应该以 http:// 或 https:// 开头"
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr "连接到Elasticsearchçš„URL。对于集群,请添加用逗å·åˆ†éš”çš„URL。"
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr "在需è¦ç›¸äº’ TLS 与外部授æƒæœåŠ¡é€šä¿¡æ—¶ä½¿ç”¨çš„ X509 è¯ä¹¦ã€‚如果ä¿ç•™ä¸ºç©º, 则在访问 HTTPS æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr "应用程åºå¯ç”¨äºŽå®¢æˆ·ç«¯å¯†é’¥å¯ä»¥ä¿æŒä¿å¯†çš„地方。原生移动应用和å•é¡µåº”用被视为为éžä¿å¯†ã€‚"
@@ -35042,8 +35514,8 @@ msgstr "åˆè§„报告显示åˆå¹¶è¯·æ±‚在å—ä¿æŠ¤çš„环境中åˆå¹¶ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
-msgid "The contact does not belong to the same group as the issue"
-msgstr "è”系人ä¸å±žäºŽè®®é¢˜æ‰€åœ¨çš„相åŒç¾¤ç»„"
+msgid "The contact does not belong to the issue group or an ancestor"
+msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr "内容编辑器å¯èƒ½ä¼šæ›´æ”¹æ–‡æ¡£çš„ Markdown æ ¼å¼æ ·å¼ï¼Œè¿™å¯èƒ½ä¸Žæ‚¨åŽŸæ¥çš„ Markdown æ ·å¼ä¸åŒ¹é…。"
@@ -35208,6 +35680,9 @@ msgstr "将存储由最近æˆåŠŸæµæ°´çº¿ä¸­çš„作业创建的最新产物。"
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr "æ­¤åˆå¹¶è¯·æ±‚的最新æµæ°´çº¿æœªæˆåŠŸå®Œæˆã€‚"
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr "æ­¤åˆå¹¶è¯·æ±‚的最新æµæ°´çº¿å·²å¤±è´¥ã€‚"
@@ -35242,7 +35717,7 @@ msgid "The maximum file size is %{size}."
msgstr "最大文件大å°ä¸º %{size}。"
msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
-msgstr ""
+msgstr "一个群组æ¯æœˆå¯ä»¥ä½¿ç”¨çš„共享è¿è¡Œå™¨çš„ CI/CD 时长上é™ï¼ˆåˆ†é’Ÿï¼‰ã€‚0表示无é™åˆ¶ã€‚"
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 "å•ä¸ªworker接å—清ç†çš„最大标签数。如果标签数é‡è¶…过此é™åˆ¶ï¼Œåˆ™è¦åˆ é™¤çš„标签列表将被截断为该数é‡ã€‚è¦å–消此é™åˆ¶ï¼Œè¯·å°†å…¶è®¾ç½®ä¸º 0。"
@@ -35283,9 +35758,6 @@ msgstr "页é¢å·²è¶…时,无法显示。"
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr "父å²è¯—是ç§å¯†çš„,åªèƒ½åŒ…å«ç§å¯†å²è¯—和议题"
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
-
msgid "The password for the Jenkins server."
msgstr "Jenkins æœåŠ¡å™¨çš„密ç ã€‚"
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "æ供客户端è¯ä¹¦æ—¶ä½¿ç”¨çš„ç§é’¥ã€‚该值被加密存储。"
-
msgid "The project can be accessed by any logged in user except external users."
msgstr "除外部用户外,任何登录用户å‡å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
@@ -35673,8 +36142,8 @@ msgstr "获å–%{replicableType}时出错"
msgid "There was an error fetching the Geo Settings"
msgstr "获å–Geo设置时出错"
-msgid "There was an error fetching the Node's Groups"
-msgstr "获å–节点上的群组时出错"
+msgid "There was an error fetching the Sites's Groups"
+msgstr ""
msgid "There was an error fetching the deploy freezes."
msgstr "获å–部署冻结时出错。"
@@ -35724,8 +36193,8 @@ msgstr "é‡ç½®ç”¨æˆ·æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
msgid "There was an error retrieving the Jira users."
msgstr "获å–Jira用户时出错。"
-msgid "There was an error saving this Geo Node."
-msgstr "ä¿å­˜æ­¤Geo节点时出错。"
+msgid "There was an error saving this Geo Site"
+msgstr ""
msgid "There was an error saving your changes."
msgstr "ä¿å­˜å˜æ›´æ—¶å‡ºé”™ã€‚"
@@ -35808,9 +36277,6 @@ msgstr "这些将在附件完æˆåŽå‘é€è‡³ %{email}。"
msgid "Third Party Advisory Link"
msgstr "第三方建议链接"
-msgid "Third-party offers"
-msgstr "第三方优惠"
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "æ­¤%{issuableDisplayName}被é”定。åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥è¯„论。"
@@ -35934,6 +36400,9 @@ msgstr "æ­¤æ交使用%{strong_open}未ç»éªŒè¯çš„%{strong_close}ç­¾å进行ç
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr "由于%{reason},无法显示此内容。您å¯ä»¥%{options}以代替。"
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr "此凭è¯å·²è¿‡æœŸ"
@@ -35973,9 +36442,6 @@ msgstr "æ­¤å²è¯—çš„å­å²è¯—数目已达最大值。"
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "æ­¤å²è¯—ä¸å­˜åœ¨æˆ–者您没有足够的æƒé™ã€‚"
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr "此功能是旗舰版试用的一部分。"
-
msgid "This feature requires local storage to be enabled"
msgstr "此功能需è¦æœ¬åœ°å­˜å‚¨ä»¥å¯ç”¨"
@@ -35998,7 +36464,7 @@ msgid "This group"
msgstr "当å‰ç¾¤ç»„"
msgid "This group and its subgroups and projects will be placed in a 'pending deletion' state for %{deletion_adjourned_period} days, then permanently deleted on %{date}. The group can be fully restored before that date."
-msgstr ""
+msgstr "该组åŠå…¶å­ç»„和项目将在 %{deletion_adjourned_period} 天内处于“待删除â€çŠ¶æ€ï¼Œç„¶åŽåœ¨ %{date} 被永久删除。该群组å¯ä»¥åœ¨è¯¥æ—¥æœŸä¹‹å‰å®Œå…¨æ¢å¤ã€‚"
msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
msgstr "此群组ä¸èƒ½è¢«åˆ é™¤ï¼Œå› ä¸ºå®ƒå·²é“¾æŽ¥åˆ°ä¸€ä¸ªè®¢é˜…,è¦åˆ é™¤æ­¤ç¾¤ç»„, %{linkStart}将订阅%{linkEnd} 链接到å¦ä¸€ä¸ªç¾¤ç»„。"
@@ -36015,9 +36481,15 @@ msgstr "此群组尚无任何群组Runner。"
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr "此群组已安排在%{date}永久删除"
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr "此群组已链接到订阅"
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目已安排在%{date}移除。"
@@ -36237,6 +36709,9 @@ msgstr "æ­¤æµæ°´çº¿æ˜¯ç”±å®šæ—¶è®¡åˆ’触å‘çš„."
msgid "This project"
msgstr "当å‰é¡¹ç›®"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr "此项目ä¸å±žäºŽç¾¤ç»„,ä¸èƒ½ä½¿ç”¨ç¾¤ç»„Runner。"
@@ -36258,6 +36733,9 @@ msgstr "此项目已存档,无法添加评论。"
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "该项目在 %{strong_start}%{license_name}%{strong_end}下获得许å¯ã€‚"
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr "此项目使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾èµ–关系"
@@ -36297,6 +36775,9 @@ msgstr "æ­¤æœåŠ¡å…许用户通过在Slack输入 slash command æ¥æ‰§è¡Œæ­¤é¡¹ç
msgid "This setting can be overridden in each project."
msgstr "当å‰è®¾ç½®å¯åœ¨æ¯ä¸ªé¡¹ç›®ä¸­è¿›è¡Œæ›´æ”¹è¦†ç›–。"
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr "此订阅适用于"
@@ -36525,9 +37006,6 @@ msgstr "最åŽä¸€æ¬¡æ交到åˆå¹¶çš„时间"
msgid "Time in seconds"
msgstr "时间(秒)"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr "GitLab等待外部æœåŠ¡çš„å“应时间(秒)。当æœåŠ¡æ²¡æœ‰åŠæ—¶å“应时,访问将被拒ç»ã€‚"
-
msgid "Time of import: %{importTime}"
msgstr "导入时间: %{importTime}"
@@ -36773,9 +37251,6 @@ msgstr "è¦è®¿é—®æ­¤åŸŸï¼Œè¯·åˆ›å»ºæ–°çš„DNS记录"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr "è¦æ·»åŠ è‡ªå®šä¹‰åŽç¼€ï¼Œè¯·è®¾ç½®æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€ã€‚%{linkStart}了解更多。%{linkEnd}"
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "è¦æ·»åŠ ä¸€ä¸ªSSH密钥, 您需è¦%{generate_link_start}生æˆä¸€ä¸ª%{link_end}或使用一个%{existing_link_start}现有的密钥%{link_end}。"
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "如需手动添加æ¡ç›®ï¼Œè¯·åœ¨æ‰‹æœºåº”用中æ供以下信æ¯ã€‚"
@@ -36879,7 +37354,7 @@ msgid "To receive alerts from manually configured Prometheus services, add the f
msgstr "è¦ä»Žæ‰‹åŠ¨é…置的PrometheusæœåŠ¡æŽ¥æ”¶è­¦æŠ¥ï¼Œè¯·å°†ä»¥ä¸‹URL和授æƒå¯†é’¥æ·»åŠ åˆ°Prometheus webhooké…置文件中。了解更多关于 %{linkStart}é…ç½®Prometheus%{linkEnd} 将警报å‘é€åˆ°GitLab。"
msgid "To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
-msgstr ""
+msgstr "è‹¥è¦æ›´æ–°ï¼Œè¯·å°†æ‚¨çš„许å¯è¯ä½¿ç”¨æ–‡ä»¶å¯¼å‡ºå¹¶å‘é€ç”µå­é‚®ä»¶è‡³ %{renewal_service_email}。新的许å¯è¯å°†ä¼šè¢«å‘é€åˆ°åœ¨ %{customers_dot} 注册的电å­é‚®ä»¶åœ°å€ã€‚ 您å¯ä»¥å°†æ­¤è®¸å¯è¯ä¸Šä¼ åˆ°æ‚¨çš„实例。"
msgid "To resolve this, try to:"
msgstr "è¦è§£å†³æ­¤é—®é¢˜ï¼Œè¯·å°è¯•ï¼š"
@@ -36917,9 +37392,6 @@ msgstr "è‹¥è¦é€€è®¢æ­¤é—®é¢˜ï¼Œè¯·å°†ä»¥ä¸‹é“¾æŽ¥ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ï¼š"
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr "è¦ä½¿ç”¨å¤šä¸ªæ–‡ä»¶æ›´æ–°ä»£ç ç‰‡æ®µï¼Œæ‚¨å¿…须使用 `files` å‚æ•°"
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr "è¦ä½¿ç”¨Gitpod,您必须首先在 %{user_prefs}的“集æˆâ€éƒ¨åˆ†ä¸­å¯ç”¨è¯¥åŠŸèƒ½ã€‚"
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr "è¦ä½¿ç”¨å…¶å®ƒæ ¼å¼ï¼Œæ‚¨å¿…é¡»å¯åŠ¨æ‰€éœ€çš„ %{container_link_start}ä¼´éšå®¹å™¨%{container_link_end}。"
@@ -36935,9 +37407,6 @@ msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器"
msgid "To widen your search, change or remove filters above."
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
-msgid "To widen your search, change or remove filters."
-msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除筛选æ¡ä»¶ã€‚"
-
msgid "To-Do List"
msgstr "待办事项列表"
@@ -36948,37 +37417,37 @@ msgid "Today"
msgstr "今日"
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
-msgstr ""
+msgstr "您正在寻找è¦åšçš„事情å—? 查看 %{strongStart}%{openIssuesLinkStart}打开的议题%{openIssuesLinkEnd}%{strongEnd},贡献给 %{strongStart}%{mergeRequestLinkStart}åˆå¹¶è¯·æ±‚%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd},或在评论中æåŠæŸäººï¼Œè‡ªåŠ¨åˆ†é…新的待办事项。"
msgid "Todos|Filter by author"
-msgstr ""
+msgstr "按作者筛选"
msgid "Todos|Filter by group"
-msgstr ""
+msgstr "按群组筛选"
msgid "Todos|Filter by project"
-msgstr ""
+msgstr "按项目筛选"
msgid "Todos|It's how you always know what to work on next."
-msgstr ""
+msgstr "这是您始终知é“下一步该åšä»€ä¹ˆçš„æ–¹å¼ã€‚"
msgid "Todos|Mark all as done"
-msgstr ""
+msgstr "标记全部完æˆ"
msgid "Todos|Nothing is on your to-do list. Nice work!"
-msgstr ""
+msgstr "您的待办事项列表中没有任何事项。"
msgid "Todos|Undo mark all as done"
-msgstr ""
+msgstr "撤销标记全部完æˆ"
msgid "Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List."
-msgstr ""
+msgstr "当一个议题或åˆå¹¶è¯·æ±‚分é…给您,或者当您收到评论中的 %{strongStart}@mention%{strongEnd} 时,会自动触å‘您的待办事项列表中的一个新事项。"
msgid "Todos|You're all done!"
-msgstr ""
+msgstr "å·²ç»å…¨éƒ¨å®Œæˆäº†ï¼"
msgid "Todos|Your To-Do List shows what to work on next"
-msgstr ""
+msgstr "您的待办事项列表显示下一步è¦åšä»€ä¹ˆ"
msgid "Toggle GitLab Next"
msgstr "切æ¢GitLab Next"
@@ -37145,9 +37614,6 @@ msgstr "跟踪您的项目中的é‡è¦äº‹ä»¶ã€‚"
msgid "Track time with quick actions"
msgstr "使用快æ·æ“作æ¥ç»Ÿè®¡å·¥æ—¶"
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr "使用GitLab for Slack跟踪您的GitLab项目。"
-
msgid "Training mode"
msgstr "训练模å¼"
@@ -37257,6 +37723,9 @@ msgstr "您现在无法获得å…费试用,但您å¯ä»¥éšæ—¶é€šè¿‡é€‰æ‹©æ‚¨çš„
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr "您的试用版在 %{boldStart}%{trialEndDate}%{boldEnd}结æŸï¼Œæˆ‘们希望您能享å—GitLab %{planName}的功能,为了在试用结æŸåŽä¿ç•™è¿™äº›åŠŸèƒ½ï¼Œæ‚¨éœ€è¦è´­ä¹°è®¢é˜…。(如果您满足您的需è¦ï¼Œæ‚¨ä¹Ÿå¯ä»¥é€‰æ‹©ä¸“业版。)"
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr "å…¬å¸å称"
@@ -37272,15 +37741,9 @@ msgstr "国家"
msgid "Trial|Dismiss"
msgstr "驳回"
-msgid "Trial|First name"
-msgstr "åå­—"
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr "GitLab Ultimate 试用版(å¯é€‰ï¼‰"
-msgid "Trial|Last name"
-msgstr "姓æ°"
-
msgid "Trial|Number of employees"
msgstr "员工人数"
@@ -37347,6 +37810,12 @@ msgstr "触å‘器已æˆåŠŸæ›´æ–°ã€‚"
msgid "Triggerer"
msgstr "触å‘者"
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr "使用跟踪对应用程åºè¿›è¡Œæ•…障排除与监控"
@@ -37866,6 +38335,9 @@ msgstr "更新于"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "由%{updated_by}更新于%{updated_at}"
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr "æ›´æ–°"
@@ -37887,6 +38359,9 @@ msgstr "å‡çº§ä½ çš„计划"
msgid "Upload"
msgstr "上传"
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "上传CSV文件"
@@ -38322,6 +38797,9 @@ msgstr "用户和 IP 速率é™åˆ¶"
msgid "User cap"
msgstr "用户上é™"
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr "用户创建于"
@@ -38821,16 +39299,16 @@ msgid "Verification status"
msgstr "验è¯çŠ¶æ€"
msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity."
-msgstr ""
+msgstr "æµæ°´çº¿å¤±è´¥ï¼Ÿä¸ºäº†é˜²æ­¢ GitLab 垃圾邮件和滥用,我们è¦æ±‚您使用有效的付款方å¼éªŒè¯æ‚¨çš„身份。"
msgid "VerificationReminder|Until then, shared runners will be unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
-msgstr ""
+msgstr "在此之å‰ï¼Œå…±äº« runner ä¸å¯ç”¨ã€‚%{validateLinkStart}验è¯æ‚¨çš„å¸æˆ·%{validateLinkEnd} 或 %{docsLinkStart}使用您自己的 runner%{docsLinkEnd}。"
msgid "VerificationReminder|Your account has been validated"
-msgstr ""
+msgstr "您的å¸æˆ·å·²é€šè¿‡éªŒè¯ã€‚"
msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "您现在å¯ä»¥åˆ©ç”¨å…±äº« runner çš„å…è´¹ CI/CD 分钟。"
msgid "Verified"
msgstr "已验è¯"
@@ -38853,6 +39331,18 @@ msgstr "版本 %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
msgstr "版本 %{versionNumber} (最新)"
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr "查看文档"
@@ -38997,6 +39487,9 @@ msgstr[0] "查看公共 GPG 密钥"
msgid "View replaced file @ "
msgstr "查看替æ¢æ–‡ä»¶ @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr "查看设置"
@@ -39109,7 +39602,7 @@ msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by
msgstr "由%{user}于%{timeago}%{statusStart}解决%{statusEnd}"
msgid "VulnerabilityManagement|(optional) Include the solution to the vulnerability if available."
-msgstr ""
+msgstr "(å¯é€‰ï¼‰åŒ…括æ¼æ´žçš„解决方案(如果有)。"
msgid "VulnerabilityManagement|A removed or remediated vulnerability"
msgstr "已删除或已补救的æ¼æ´ž"
@@ -39222,6 +39715,9 @@ msgstr "实际å“应"
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr "实际收到的å“应是检测到此故障时收到的å“应"
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr "其它信æ¯"
@@ -39264,6 +39760,9 @@ msgstr "检测方法"
msgid "Vulnerability|Download"
msgstr "下载"
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "è¯æ®"
@@ -39282,6 +39781,12 @@ msgstr "GitLab 安全报告"
msgid "Vulnerability|Identifier"
msgstr "标识"
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr "标识"
@@ -39291,6 +39796,9 @@ msgstr "é•œåƒ"
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr "关于如何å‘现æ¼æ´žåŠå…¶å¯¹ç³»ç»Ÿçš„å½±å“çš„ä¿¡æ¯ã€‚"
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr "链接"
@@ -39303,6 +39811,9 @@ msgstr "命å空间"
msgid "Vulnerability|Project"
msgstr "项目"
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr "å†ç”Ÿèµ„产"
@@ -39315,6 +39826,9 @@ msgstr "请求/å“应"
msgid "Vulnerability|Scanner Provider"
msgstr "扫æ工具æ供者"
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr "安全审计"
@@ -39339,9 +39853,18 @@ msgstr "未修改的å“应是原始å“应没有对请求进行çªå˜çš„å“应"
msgid "Vulnerability|Tool"
msgstr "工具"
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr "未修改的å“应"
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr "警告:"
@@ -39448,7 +39971,7 @@ msgid "We'll use this to help surface the right features and information to you.
msgstr "我们将使用它æ¥å¸®åŠ©å‘您展示正确的功能和信æ¯ã€‚"
msgid "We're experiencing difficulties and this tab content is currently unavailable."
-msgstr ""
+msgstr "我们é‡åˆ°äº†å›°éš¾ï¼Œæ­¤æ ‡ç­¾å†…容目å‰ä¸å¯ç”¨ã€‚"
msgid "We've found no vulnerabilities"
msgstr "未å‘现安全æ¼æ´ž"
@@ -39522,6 +40045,48 @@ msgstr "Webhooks"
msgid "Webhooks Help"
msgstr "Webhooks帮助"
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
msgid "Webhooks|Comments"
msgstr "评论"
@@ -39564,6 +40129,9 @@ msgstr "æµæ°´çº¿äº‹ä»¶"
msgid "Webhooks|Push events"
msgstr "推é€äº‹ä»¶"
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
msgid "Webhooks|Releases events"
msgstr "å‘布事件"
@@ -39594,56 +40162,11 @@ msgstr "触å‘æ¥æº"
msgid "Webhooks|URL"
msgstr "网å€"
-msgid "Webhooks|URL is triggered by a push to the repository"
-msgstr "推é€åˆ°ä»“åº“æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr "在创建ã€æ›´æ–°ã€å…³é—­æˆ–é‡æ–°æ‰“å¼€ç§å¯†è®®é¢˜æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr "在部署开始ã€å®Œæˆã€å¤±è´¥æˆ–å–æ¶ˆæ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr "åœ¨æ‰“å¼€æˆ–å…³é—­åŠŸèƒ½æ ‡å¿—æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr "在创建ã€æ›´æ–°æˆ–删除群组æˆå‘˜æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr "在创建ã€æ›´æ–°æˆ–åˆå¹¶åˆå¹¶è¯·æ±‚æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr "在新标签被推é€åˆ°ä»“åº“æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr "URL 在创建或更新版本时触å‘"
-
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr "在创建或删除å­ç¾¤ç»„æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr "在创建或更新 wiki 页é¢æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr "在创建ã€æ›´æ–°ã€å…³é—­æˆ–é‡æ–°æ‰“å¼€è®®é¢˜æ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr "åœ¨æœ‰äººæ·»åŠ è¯„è®ºæ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr "在有人对ç§å¯†è®®é¢˜æ·»åŠ è¯„è®ºæ—¶è§¦å‘ URL"
-
-msgid "Webhooks|URL is triggered when the job status changes"
-msgstr "作业状æ€æ”¹å˜æ—¶è§¦å‘URL"
-
-msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr "当æµæ°´çº¿çŠ¶æ€æ”¹å˜æ—¶è§¦å‘URL"
-
-msgid "Webhooks|URL must be percent-encoded if neccessary."
-msgstr "如有必è¦ï¼ŒURL 必须进行百分比编ç ã€‚"
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
+msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
-msgstr "使用此令牌æ¥éªŒè¯æ”¶åˆ°çš„有效负载。它与 X-Gitlab-Token HTTP 标头中的请求一起å‘é€ã€‚"
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
+msgstr ""
msgid "Webhooks|Webhook failed to connect"
msgstr "Webhook 连接失败"
@@ -39691,7 +40214,7 @@ msgid "Welcome, %{name}!"
msgstr "欢迎, %{name}ï¼"
msgid "What are CI/CD minutes?"
-msgstr ""
+msgstr "什么是 CI/CD 分钟数?"
msgid "What are group audit events?"
msgstr "什么是群组审计事件?"
@@ -39750,12 +40273,12 @@ msgstr "如果å¯ç”¨ï¼Œåˆ™ä¸å†æŽ¥å—无过期日期或无效过期日期的 SS
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr "å¯ç”¨åŽï¼ŒçŽ°æœ‰çš„个人访问令牌å¯èƒ½ä¼šè¢«æ’¤é”€ã€‚留空表示没有é™åˆ¶ã€‚"
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
+msgstr ""
+
msgid "When inactive, an external authentication provider must be used."
msgstr "当未激活时,必须使用外部身份验è¯æ供程åºã€‚"
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨é¡¹ç›®åŠŸèƒ½æˆ–执行外部授æƒæ£€æŸ¥ã€‚"
-
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "当默认分支中的åˆå¹¶è¯·æ±‚å’Œæ交关闭时,它们引用的任何议题也会关闭。"
@@ -40060,8 +40583,14 @@ msgstr "正在进行中(开放和未分é…)"
msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
-msgid "Work in progress- click here to find out more"
-msgstr "正在进行中 - å•å‡»æ­¤å¤„了解更多信æ¯"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
+msgstr ""
msgid "WorkItem|Work Items"
msgstr "工作事项"
@@ -40162,6 +40691,9 @@ msgstr "您将删除 %{group_name}。这也将删除其所有å­ç»„和项目。å
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›®%{project_full_name}的派生关系。确定继续å—?"
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr "您将è¦å°† %{project_full_name} 转移到å¦ä¸€ä¸ªå称空间。您完全确定å—?"
@@ -40195,6 +40727,9 @@ msgstr "您无æƒåˆ é™¤æ­¤ç«™ç‚¹é…置文件"
msgid "You are not authorized to perform this action"
msgstr "您无æƒæ‰§è¡Œæ­¤æ“作"
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr "您无æƒæ›´æ–°æ­¤é…置文件"
@@ -40243,6 +40778,9 @@ msgstr "您å¯ä»¥åœ¨ %{lint_link_start}CI Lint%{lint_link_end} 中测试 %{gitla
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "您还å¯ä»¥æŒ‰ç…§ä»¥ä¸‹è¯´æ˜Žä»Žè®¡ç®—机中上传现有文件。"
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr "您还å¯ä»¥å°†é¡¹ç›®è®¿é—®ä»¤ç‰Œä¸Ž Git 结åˆä½¿ç”¨ä»¥é€šè¿‡ HTTP(S) 进行身份验è¯ã€‚ %{link_start}了解更多。%{link_end}"
@@ -40288,6 +40826,9 @@ msgstr "您å¯ä»¥è¯·æ±‚加入这些群组,以便为群组项目åšå‡ºè´¡çŒ®ã€‚
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr "您å¯ä»¥å¯ç”¨æ³¨å†ŒåŠŸèƒ½ï¼Œå› ä¸ºæœåŠ¡ Ping å·²å¯ç”¨ã€‚è¦åœ¨æœªæ¥ç»§ç»­ä½¿ç”¨æ³¨å†ŒåŠŸèƒ½ï¼Œæ‚¨è¿˜éœ€è¦é€šè¿‡æ–°çš„云许å¯æœåŠ¡å‘ GitLab 注册。"
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr "您å¯ä»¥åœ¨ %{link_start}群组设置%{link_end} 中å¯ç”¨é¡¹ç›®è®¿é—®ä»¤ç‰Œåˆ›å»ºã€‚"
@@ -40423,6 +40964,9 @@ msgstr "您没有æƒé™æ‰¹å‡†æˆå‘˜"
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "您没有æƒé™é€€å‡º%{namespaceType}。"
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "您无æƒè¿è¡ŒWeb终端。请è”系项目管ç†å‘˜ã€‚"
@@ -40514,6 +41058,9 @@ msgstr "您没有足够的æƒé™ä¸ºæ­¤é¡¹ç›®åˆ›å»ºHTTP集æˆ"
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr "您没有足够的æƒé™æ¥åˆ›å»ºæ­¤é¡¹ç›®çš„待命计划"
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr "您的æƒé™ä¸è¶³ï¼Œæ— æ³•ä»Žæ­¤é¡¹ç›®ä¸­åˆ é™¤on-callè½®æ¢"
@@ -40553,8 +41100,8 @@ msgstr "您已达到项目数é‡é™åˆ¶"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr "您已ç»ä¸ºæ‚¨çš„å¸æˆ·è®¾ç½®äº†ä¸¤æ­¥éªŒè¯ï¼ 如果您无法访问您的2FA 设备,您å¯ä»¥ä½¿ç”¨æ¢å¤ç è®¿é—®æ‚¨çš„å¸æˆ·ã€‚ 或者,如果您上传一个 SSH 密钥,您å¯ä»¥ä½¿ç”¨ %{anchorOpen}使用该密钥生æˆé¢å¤–çš„æ¢å¤ç %{anchorClose}。"
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
-msgstr "您已æˆåŠŸè´­ä¹° %{product}。您将通过邮件收到收æ®ã€‚"
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "您已æˆåŠŸè´­ä¹°äº†%{seats}用户的%{plan}计划订阅。收æ®å°†é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™æ‚¨ã€‚"
@@ -40568,6 +41115,9 @@ msgstr "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
msgid "You may close the milestone now."
msgstr "你现在å¯ä»¥å…³é—­è¿™ä¸ªé‡Œç¨‹ç¢‘。"
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr "您必须登录æ‰èƒ½åœ¨æ•´ä¸ªGitLab中进行æœç´¢"
@@ -40949,8 +41499,8 @@ msgstr "您的åå­—"
msgid "Your new %{type}"
msgstr "您的新%{type}"
-msgid "Your new SCIM token"
-msgstr "您的新 SCIM 令牌"
+msgid "Your new access token has been created."
+msgstr ""
msgid "Your new comment"
msgstr "您的新评论"
@@ -40958,9 +41508,6 @@ msgstr "您的新评论"
msgid "Your new personal access token has been created."
msgstr "您的新个人访问令牌已创建。"
-msgid "Your new project access token has been created."
-msgstr "您的新项目访问令牌已创建。"
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr "查看此页é¢ä¸éœ€è¦å¯†ç ã€‚如果è¦æ±‚输入密ç æˆ–其他任何个人详细信æ¯ï¼Œè¯·ä¸Žç®¡ç†å‘˜è”系以举报滥用行为。"
@@ -41027,6 +41574,9 @@ msgstr "您的代ç ç‰‡æ®µ"
msgid "Your subscription expired!"
msgstr "您的订阅已过期ï¼"
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr "您的订阅现在已过期。若è¦æ›´æ–°ï¼Œè¯·å°†æ‚¨çš„许å¯è¯ä½¿ç”¨æ–‡ä»¶å¯¼å‡ºå¹¶å‘é€ç”µå­é‚®ä»¶è‡³ %{renewal_service_email}。新的许å¯è¯å°†å‘é€ç”µå­é‚®ä»¶åˆ°åœ¨ %{customers_dot} 注册的电å­é‚®ä»¶åœ°å€ã€‚ 您å¯ä»¥ä¸Šä¼ æ­¤è®¸å¯è¯åˆ°æ‚¨çš„实例。è¦ä½¿ç”¨æ ‡å‡†ç‰ˆï¼Œè¯·åˆ é™¤æ‚¨å½“å‰çš„许å¯è¯ã€‚"
@@ -41155,6 +41705,10 @@ msgstr "åˆå¹¶è¯·æ±‚已有任æ„核准人(any-approver)"
msgid "any-approver for the project already exists"
msgstr "项目已有任æ„核准人(any-approver)"
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr "已核准人: "
@@ -41237,6 +41791,9 @@ msgstr "如果个人项目具有容器镜åƒåº“标签,则无法更改。"
msgid "cannot be changed if shared runners are enabled"
msgstr "如果å¯ç”¨å…±äº«Runner,则无法更改"
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr "无法å¯ç”¨ï¼Œå› ä¸ºçˆ¶ç¾¤ç»„ä¸å…许"
@@ -41606,6 +42163,9 @@ msgstr "å·²æ交"
msgid "compliance violation has already been recorded"
msgstr "è¿è§„行为已被记录"
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "container_nameåªèƒ½åŒ…å«å°å†™å­—æ¯ï¼Œæ•°å­—,'-'å’Œ'.',并且必须以字æ¯å’Œæ•°å­—字符开头和结尾"
@@ -41633,17 +42193,11 @@ msgstr "%{issuable_created}由%{author}创建"
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr "由 %{user} 通过 %{email} 创建于 %{timeAgoString}"
-msgid "created %{timeAgoString} by %{user}"
-msgstr "于 %{timeAgoString} å‰ç”±%{user}创建"
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "在 Jira 中,由%{user}于%{timeAgoString}å‰åˆ›å»º"
-
msgid "created %{timeAgo}"
msgstr "创建于%{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr "ç”± %{author} 在 %{timeAgo} 之å‰åˆ›å»º"
+msgstr "由 %{author} 创建于 %{timeAgo}"
msgid "created by"
msgstr "创建人:"
@@ -41764,6 +42318,9 @@ msgstr "已失败"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr "无法忽略关è”çš„å‘现(id=%{finding_id}): %{message}"
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr "无法将关è”çš„å‘现(id=%{finding_id})æ¢å¤åˆ°ä¸ºæ£€æµ‹åˆ°"
@@ -41808,6 +42365,12 @@ msgstr "frontmatter"
msgid "group"
msgstr "群组"
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr "群组æˆå‘˜"
@@ -41923,6 +42486,9 @@ msgstr "在此项目中ä¸è¢«å…许。"
msgid "is not allowed since the group is not top-level group."
msgstr "ä¸å…许,因为该群组ä¸æ˜¯é¡¶çº§ç¾¤ç»„。"
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr "ä¸è¢«å…许。我们目å‰ä¸æ”¯æŒé¡¹ç›®çº§è¿­ä»£"
@@ -42019,9 +42585,6 @@ msgstr "加载中"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "被 %{path_lock_user_name} 在 %{created_at} é”定"
-msgid "log in"
-msgstr "登录"
-
msgid "manual"
msgstr "手动"
@@ -42062,9 +42625,6 @@ msgstr "æ­¤åˆå¹¶è¯·æ±‚ä¸åŒ…å«ä»»ä½•æ›´æ”¹ã€‚"
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr "使用åˆå¹¶è¯·æ±‚å‘您的项目æ出更改建议并与您的团队讨论。è¦è¿›è¡Œæ›´æ”¹ï¼Œè¯·æŽ¨é€æ交或编辑此åˆå¹¶è¯·æ±‚以使用ä¸åŒçš„分支。使用 %{linkStart}CI/CD%{linkEnd},在åˆå¹¶ä¹‹å‰è‡ªåŠ¨æµ‹è¯•æ‚¨çš„更改。"
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr "%{boldHeaderStart}此处没有æµæ°´çº¿ã€‚%{boldHeaderEnd}"
@@ -42186,8 +42746,8 @@ msgstr "GitLab %{linkStart}CI/CD å¯ä»¥è‡ªåŠ¨æž„建ã€æµ‹è¯•å’Œéƒ¨ç½²æ‚¨çš„应ç”
msgid "mrWidget|Hide %{widget} details"
msgstr "éšè— %{widget} 的详细信æ¯"
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr "如果 %{missingBranchName} 分支存在于本地仓库中,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤è¡Œæ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr "如果最åŽä¸€ä¸ªæµæ°´çº¿è¿è¡Œåœ¨æ´¾ç”Ÿé¡¹ç›®ä¸­ï¼Œå®ƒå¯èƒ½ä¸å‡†ç¡®ã€‚åˆå¹¶å‰ï¼Œæˆ‘们建议在这个项目中è¿è¡Œä¸€æ¡æµæ°´çº¿ã€‚"
@@ -42232,6 +42792,9 @@ msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šæµæ°´çº¿å¿…é¡»æˆåŠŸã€‚等待手动完æˆæ“作。"
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šå¿…须批准此åˆå¹¶è¯·æ±‚。"
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "åˆå¹¶å¤±è´¥ã€‚"
@@ -42286,6 +42849,9 @@ msgstr "在Web IDE中打开"
msgid "mrWidget|Plain diff"
msgstr "文本差异"
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "å·²å¯è‡ªåŠ¨åˆå¹¶ã€‚ 请具有仓库写入æƒé™çš„用户æ¥åˆå¹¶æ­¤è¯·æ±‚"
@@ -42331,6 +42897,9 @@ msgstr "ç”±%{merge_author}设置为在æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
msgid "mrWidget|Show %{widget} details"
msgstr "显示 %{widget} 详情"
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr "更改已åˆå¹¶åˆ°"
@@ -42340,9 +42909,6 @@ msgstr "更改未åˆå¹¶åˆ°"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æœªå®Œæˆã€‚推é€æ–°çš„æ交以修å¤å¤±è´¥ï¼Œæˆ–检查 %{linkStart}故障排查文档%{linkEnd} 以查看其它å¯èƒ½çš„æ“作。"
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æœªå®Œæˆã€‚推é€æ–°çš„æ交以修å¤å¤±è´¥ã€‚"
-
msgid "mrWidget|The source branch has been deleted"
msgstr "æºåˆ†æ”¯å·²åˆ é™¤"
@@ -42379,9 +42945,6 @@ msgstr "什么是åˆå¹¶é˜Ÿåˆ—?"
msgid "mrWidget|Your password"
msgstr "您的密ç "
-msgid "mrWidget|branch does not exist."
-msgstr "分支ä¸å­˜åœ¨"
-
msgid "mrWidget|into"
msgstr "å…¥"
@@ -42657,9 +43220,6 @@ msgstr "仓库:"
msgid "required"
msgstr "å¿…å¡«"
-msgid "reset it."
-msgstr "é‡ç½®å®ƒã€‚"
-
msgid "satisfied"
msgstr "满足"
@@ -42840,9 +43400,6 @@ msgstr "用户头åƒ"
msgid "user namespace cannot be the parent of another namespace"
msgstr "用户命å空间ä¸èƒ½æ˜¯å¦ä¸€ä¸ªå‘½å空间的父级"
-msgid "user preferences"
-msgstr "用户首选项"
-
msgid "username"
msgstr "用户å"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 426e6cb5463..968aec37689 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: 2022-01-06 17:25\n"
+"PO-Revision-Date: 2022-02-02 15:49\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -645,6 +670,9 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr ""
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr ""
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr "新增 CHANGELOG"
msgid "Add CONTRIBUTING"
msgstr "新增 CONTRIBUTING"
-msgid "Add GitLab to Slack"
-msgstr ""
-
msgid "Add Jaeger URL"
msgstr ""
@@ -1875,7 +1891,7 @@ msgstr "增加 Kubernetes å¢é›†"
msgid "Add LICENSE"
msgstr ""
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr ""
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr ""
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†å“¡"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr ""
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr "容許本項目採用 Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "å…許來自鉤å­å’Œæœå‹™çš„å°æœ¬åœ°ç¶²çµ¡çš„請求。"
-
-msgid "Allow requests to the local network from system hooks"
-msgstr ""
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr ""
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr ""
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3693,16 +3715,13 @@ msgstr ""
msgid "An error occurred while fetching the latest pipeline."
msgstr ""
-msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
-
-msgid "An error occurred while fetching this tab."
+msgid "An error occurred while fetching the pipelines jobs."
msgstr ""
-msgid "An error occurred while generating a username. Please try again."
+msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgid "An error occurred while fetching this tab."
msgstr ""
msgid "An error occurred while getting files for - %{branchId}"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr ""
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr "確定è¦é‡ç½®å¥åº·æª¢æŸ¥ä»¤ç‰Œå—Žï¼Ÿ"
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr "移除已經åˆä½µçš„分支"
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr "新增分支"
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr "優é¸æ­¤åˆä½µè«‹æ±‚"
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] "部署"
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "二月"
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "產生é è¨­çš„標籤"
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr ""
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "已開始維護"
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr "鎖定"
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr "月"
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr "沒有è¦é¡¯ç¤ºçš„里程碑"
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr "æµæ°´ç·š"
msgid "Pipelines charts"
msgstr "æµæ°´ç·šåœ–表"
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr "顯示所有活動"
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr "åªé¡¯ç¤ºç•™è¨€"
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr "最後更新"
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr "星期日"
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr "目標分支"
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr "這個專案"
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr "檢視已å–代檔案 @ "
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr "您已é”到項目數é‡é™åˆ¶"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr "您的åå­—"
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr "åœ¨ç¶²é  IDE 中開啟"
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr "進入"
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index b8ad0cdb67d..0a9cbc35a42 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: 2022-01-06 17:20\n"
+"PO-Revision-Date: 2022-02-02 15:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -108,6 +108,22 @@ msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -390,6 +406,12 @@ msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
+msgid "%{codeStart}type%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stage%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
+msgid "%{codeStart}types%{codeEnd} is deprecated and will be removed in 15.0. Use %{codeStart}stages%{codeEnd} instead. %{linkStart}Learn More %{linkEnd}"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -549,6 +571,9 @@ msgstr ""
msgid "%{group_name} group members"
msgstr ""
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} 使用群組管ç†å¸³æˆ¶ã€‚您需è¦å»ºç«‹ä¸€å€‹æ–°çš„ GitLab 帳戶,該帳戶將由 %{group_name} 群組管ç†ã€‚"
@@ -645,6 +670,9 @@ msgstr "%{group_level_name} 群組ä¸å…許 %{level_name} 。"
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "由於分å‰çš„æºé …ç›®å¯è¦‹æ€§è¼ƒä½Žï¼Œå› æ­¤ä¸å…許使用 %{level_name}。"
+msgid "%{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
@@ -654,6 +682,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
+msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -763,9 +794,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
-msgid "%{primary} (%{secondary})"
-msgstr "%{primary} (%{secondary})"
-
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
@@ -797,6 +825,9 @@ 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 "%{runner} created %{timeago}"
+msgstr ""
+
msgid "%{scope} results for term '%{term}'"
msgstr ""
@@ -1716,21 +1747,12 @@ msgstr "無法用於存å–其它資料。"
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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 has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
msgstr ""
-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"
msgstr "個人存å–權æ–"
@@ -1755,9 +1777,6 @@ msgstr ""
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 this token"
-msgstr ""
-
msgid "AccessibilityReport|Learn more"
msgstr ""
@@ -1863,9 +1882,6 @@ msgstr "加入變更記錄"
msgid "Add CONTRIBUTING"
msgstr "加入貢ç»è³‡è¨Š"
-msgid "Add GitLab to Slack"
-msgstr "將 GitLab 加入到 Slack"
-
msgid "Add Jaeger URL"
msgstr "加入 Jaeger 網å€"
@@ -1875,7 +1891,7 @@ msgstr "加入 Kubernetes å¢é›†"
msgid "Add LICENSE"
msgstr "加入授權æ¢æ¬¾"
-msgid "Add New Node"
+msgid "Add New Site"
msgstr ""
msgid "Add README"
@@ -1890,6 +1906,9 @@ msgstr ""
msgid "Add a GPG key"
msgstr "加入 GPG 金鑰"
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@@ -1956,6 +1975,9 @@ msgstr ""
msgid "Add an SSH key"
msgstr "加入 SSH 金鑰"
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "Add an existing issue"
msgstr ""
@@ -2073,9 +2095,6 @@ msgstr "加入系統掛鉤"
msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
-msgid "Add to Slack"
-msgstr "加到 Slack"
-
msgid "Add to board"
msgstr ""
@@ -2373,6 +2392,12 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "載入統計資料時發生錯誤。請å†è©¦ä¸€æ¬¡"
+msgid "AdminGeo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "AdminGeo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
msgid "AdminLabels|Define your default set of project labels"
msgstr ""
@@ -2529,6 +2554,9 @@ msgstr ""
msgid "AdminUsers|(Internal)"
msgstr ""
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
msgid "AdminUsers|(Pending approval)"
msgstr ""
@@ -2565,7 +2593,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†å“¡"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2691,6 +2719,9 @@ msgstr "這就是你ï¼"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
+msgid "AdminUsers|Locked"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2754,6 +2785,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr "此使用者將會登出"
@@ -2856,7 +2890,7 @@ 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."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
@@ -3417,22 +3451,13 @@ msgstr "å…許該群組內的專案使用 Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
-msgid "Allow requests to the local network from hooks and services."
-msgstr "å…許掛鉤åŠæœå‹™å‘本機網路請求。"
-
-msgid "Allow requests to the local network from system hooks"
-msgstr "å…許系統掛鉤å‘本機網路請求"
-
-msgid "Allow requests to the local network from web hooks and services"
-msgstr "å…許 Webhook åŠæœå‹™å‘本機網路請求"
-
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
-msgid "Allow this secondary node to replicate content on Object Storage"
+msgid "Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
@@ -3543,9 +3568,6 @@ msgstr "發生錯誤"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
msgstr ""
-msgid "An error occured while fetching the pipelines jobs."
-msgstr ""
-
msgid "An error occurred adding a draft to the thread."
msgstr "å‘話題加入è‰ç¨¿æ™‚發生錯誤。"
@@ -3693,18 +3715,15 @@ msgstr "抓å–作業時發生錯誤。"
msgid "An error occurred while fetching the latest pipeline."
msgstr "抓å–最後一個æµæ°´ç·šæ™‚發生錯誤。"
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred while fetching the releases. Please try again."
msgstr "抓å–發行版本時發生錯誤。請é‡è©¦ã€‚"
msgid "An error occurred while fetching this tab."
msgstr "抓å–此分é æ™‚發生錯誤。"
-msgid "An error occurred while generating a username. Please try again."
-msgstr "產生使用者å稱時發生錯誤。請é‡è©¦ã€‚"
-
-msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
-
msgid "An error occurred while getting files for - %{branchId}"
msgstr "å–å¾— %{branchId} 的檔案時發生錯誤"
@@ -4250,9 +4269,6 @@ msgstr ""
msgid "ApprovalRule|Add approvers"
msgstr ""
-msgid "ApprovalRule|Add required approvers to improve your code review process"
-msgstr ""
-
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4283,9 +4299,6 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|Assign approvers by area of expertise."
-msgstr ""
-
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4295,13 +4308,13 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
-msgid "ApprovalRule|Increase your organization’s code quality."
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
-msgid "ApprovalRule|Learn more about merge request approval."
+msgid "ApprovalRule|Increase quality and maintain standards."
msgstr ""
-msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
msgid "ApprovalRule|Name"
@@ -4328,7 +4341,7 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
-msgid "ApprovalRule|Reduce the overall time to merge."
+msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
@@ -4343,6 +4356,9 @@ msgstr ""
msgid "ApprovalRule|Select All"
msgstr ""
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
msgid "ApprovalRule|Select scanners"
msgstr ""
@@ -4358,7 +4374,7 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Try it for free"
+msgid "ApprovalRule|Try for free"
msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
@@ -4370,22 +4386,28 @@ msgstr ""
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approval by author."
msgstr ""
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
+msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
msgstr ""
-msgid "ApprovalSettings|Require user password to approve."
+msgid "ApprovalSettings|Require user password to approve"
msgstr ""
msgid "ApprovalSettings|There was an error loading merge request approval settings."
@@ -4499,6 +4521,9 @@ msgstr "確定è¦å–消歸檔此專案嗎?"
msgid "Are you sure you want to %{action} %{name}?"
msgstr ""
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
msgid "Are you sure you want to attempt to merge?"
msgstr ""
@@ -4590,9 +4615,6 @@ msgstr "您確定è¦ç§»é™¤é€™å€‹èº«ä»½è­˜åˆ¥å—Žï¼Ÿ"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
-
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -4677,7 +4699,7 @@ msgstr ""
msgid "Ask someone with write access to resolve it."
msgstr ""
-msgid "Ask your group maintainer to set up a group runner."
+msgid "Ask your group owner to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -5117,6 +5139,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Awaiting user signup"
+msgstr ""
+
msgid "Award added"
msgstr ""
@@ -5249,6 +5274,9 @@ msgstr ""
msgid "Based on"
msgstr ""
+msgid "Basic information"
+msgstr ""
+
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -5276,6 +5304,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5291,9 +5322,6 @@ 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 ""
@@ -5330,9 +5358,6 @@ 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 ""
@@ -5411,9 +5436,15 @@ msgstr ""
msgid "Billings|Your account has been validated"
msgstr ""
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
msgid "Billing|An error occurred while getting a billable member details"
msgstr ""
@@ -5492,6 +5523,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
msgid "Block user"
msgstr ""
@@ -5801,18 +5835,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
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 ""
-
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
@@ -5828,9 +5856,6 @@ msgstr ""
msgid "Branches|No branches to show"
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 ""
@@ -5879,15 +5904,6 @@ 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 ""
-
-msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
-
-msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-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 ""
@@ -5906,9 +5922,6 @@ 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 ""
-
msgid "Branches|diverged from upstream"
msgstr ""
@@ -6104,6 +6117,15 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -6168,9 +6190,21 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
+msgid "CICDAnalytics|Shared Runners Usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
+msgid "CICDAnalytics|What is shared runner usage?"
+msgstr ""
+
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
msgstr ""
@@ -6405,6 +6439,9 @@ msgstr ""
msgid "Cannot be merged automatically"
msgstr ""
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
msgid "Cannot create the abuse report. The user has been deleted."
msgstr ""
@@ -6782,6 +6819,9 @@ msgstr ""
msgid "Checkout|(x%{quantity})"
msgstr ""
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
msgid "Checkout|Billing address"
msgstr ""
@@ -6959,6 +6999,9 @@ msgstr ""
msgid "Child"
msgstr ""
+msgid "Child epic"
+msgstr ""
+
msgid "Child epic does not exist."
msgstr ""
@@ -7259,15 +7302,6 @@ msgstr ""
msgid "Click to reveal"
msgstr ""
-msgid "Client authentication certificate"
-msgstr ""
-
-msgid "Client authentication key"
-msgstr ""
-
-msgid "Client authentication key password"
-msgstr ""
-
msgid "Client request timeout"
msgstr ""
@@ -7364,6 +7398,12 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -7388,7 +7428,7 @@ msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} agents"
+msgid "ClusterAgents|%{number} of %{total} Agents"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
@@ -7433,7 +7473,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
@@ -7463,7 +7503,7 @@ msgstr ""
msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with the Agent"
+msgid "ClusterAgents|Connect with agent"
msgstr ""
msgid "ClusterAgents|Connect with the GitLab Agent"
@@ -7520,13 +7560,16 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
msgid "ClusterAgents|Go to the repository files"
msgstr ""
msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install a new agent"
+msgid "ClusterAgents|Install new Agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7553,7 +7596,7 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No Agents"
msgstr ""
msgid "ClusterAgents|No clusters connected through cluster certificates"
@@ -7580,6 +7623,18 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to install new agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a maintainer or greater role to connect existing clusters"
+msgstr ""
+
msgid "ClusterAgents|Security"
msgstr ""
@@ -7592,6 +7647,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
@@ -7614,7 +7672,7 @@ msgstr ""
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
msgstr ""
-msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}Learn more about installing GitLab Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Token created by %{userName}"
@@ -7632,6 +7690,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
@@ -8581,6 +8642,9 @@ msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit SHA"
+msgstr ""
+
msgid "Commit changes"
msgstr ""
@@ -8830,6 +8894,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -8860,6 +8927,12 @@ msgstr ""
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
msgstr ""
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr ""
@@ -8905,12 +8978,15 @@ msgstr ""
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
-msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
msgid "Configure existing installation"
msgstr ""
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
msgid "Configure repository mirroring."
msgstr ""
@@ -8938,12 +9014,18 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
+msgid "Configure via Merge Request"
+msgstr ""
+
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm approval"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -9499,7 +9581,7 @@ msgstr ""
msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "Control whether to display third-party offers in GitLab."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API."
@@ -9640,9 +9722,24 @@ msgstr ""
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
msgstr ""
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
msgid "CorpusManagement|Corpus name"
msgstr ""
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9655,9 +9752,6 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
-msgstr ""
-
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9730,6 +9824,9 @@ msgstr ""
msgid "Could not fetch policy because existing policy YAML is invalid"
msgstr ""
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -9757,13 +9854,16 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
-msgid "Could not revoke project access token %{project_access_token_name}."
+msgid "Could not save configuration. Please refresh the page, or try again later."
msgstr ""
msgid "Could not save group ID"
@@ -9907,6 +10007,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create label"
+msgstr ""
+
msgid "Create list"
msgstr ""
@@ -10165,6 +10268,9 @@ msgstr ""
msgid "Created by:"
msgstr ""
+msgid "Created compliance violations if any were found"
+msgstr ""
+
msgid "Created date"
msgstr ""
@@ -10399,6 +10505,9 @@ msgstr ""
msgid "Customer Relations Organizations"
msgstr ""
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
msgid "Customer relations"
msgstr ""
@@ -10629,6 +10738,9 @@ msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr ""
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -10638,10 +10750,10 @@ msgstr ""
msgid "DORA4Metrics|Deployment frequency"
msgstr ""
-msgid "DORA4Metrics|Lead time"
+msgid "DORA4Metrics|Lead time for changes"
msgstr ""
-msgid "DORA4Metrics|Median lead time"
+msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
@@ -10731,12 +10843,6 @@ msgstr ""
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
-
-msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
-
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
msgstr ""
@@ -10749,9 +10855,6 @@ msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
-msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
-
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -10764,9 +10867,6 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
-msgid "DastProfiles|DAST Scan"
-msgstr ""
-
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10839,9 +10939,6 @@ msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
-msgid "DastProfiles|No scans saved yet"
-msgstr ""
-
msgid "DastProfiles|No site profiles created yet"
msgstr ""
@@ -10869,9 +10966,6 @@ msgstr ""
msgid "DastProfiles|Rest API"
msgstr ""
-msgid "DastProfiles|Run scan"
-msgstr ""
-
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -10881,12 +10975,6 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
-msgid "DastProfiles|Saved Scans"
-msgstr ""
-
-msgid "DastProfiles|Scan"
-msgstr ""
-
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -10899,9 +10987,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
-msgid "DastProfiles|Schedule"
-msgstr ""
-
msgid "DastProfiles|Select branch"
msgstr ""
@@ -10923,9 +11008,6 @@ msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
-msgid "DastProfiles|Target"
-msgstr ""
-
msgid "DastProfiles|Target URL"
msgstr ""
@@ -11194,9 +11276,6 @@ msgstr ""
msgid "Default branch protection"
msgstr ""
-msgid "Default classification label"
-msgstr ""
-
msgid "Default delayed project deletion"
msgstr ""
@@ -11617,6 +11696,9 @@ msgstr[0] ""
msgid "Deploy Keys"
msgstr ""
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
msgid "Deploy freezes"
msgstr ""
@@ -11632,6 +11714,9 @@ msgstr ""
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
msgid "Deploy to..."
msgstr ""
@@ -11843,9 +11928,39 @@ msgstr[0] ""
msgid "Deployment|API"
msgstr ""
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
msgid "Deployment|This deployment was created using the API"
msgstr ""
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
msgid "Deployment|canceled"
msgstr ""
@@ -12402,9 +12517,6 @@ msgstr ""
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
msgstr ""
-msgid "Discover|Send feedback"
-msgstr ""
-
msgid "Discover|Start a free trial"
msgstr ""
@@ -12469,7 +12581,7 @@ msgstr ""
msgid "Display time tracking in issues in total hours only."
msgstr ""
-msgid "Do not display offers from third parties"
+msgid "Do not display content for customer experience improvement and offers from third parties"
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
@@ -12664,7 +12776,7 @@ msgstr ""
msgid "Edit Deploy Key"
msgstr ""
-msgid "Edit Geo Node"
+msgid "Edit Geo Site"
msgstr ""
msgid "Edit Group Hook"
@@ -12910,6 +13022,9 @@ msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
msgstr ""
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -13054,9 +13169,6 @@ msgstr ""
msgid "Enable automatic repository housekeeping"
msgstr ""
-msgid "Enable classification control using an external service"
-msgstr ""
-
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
@@ -13099,6 +13211,9 @@ msgstr ""
msgid "Enable kuromoji custom analyzer: Search"
msgstr ""
+msgid "Enable logs collection"
+msgstr ""
+
msgid "Enable maintenance mode"
msgstr ""
@@ -13126,6 +13241,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13204,9 +13325,6 @@ msgstr ""
msgid "Ends: %{endsAt}"
msgstr ""
-msgid "Enforce DNS rebinding attack protection"
-msgstr ""
-
msgid "Enforce SSH key expiration"
msgstr ""
@@ -13255,6 +13373,9 @@ msgstr ""
msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter license key"
+msgstr ""
+
msgid "Enter merge request URLs"
msgstr ""
@@ -13529,6 +13650,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13556,6 +13680,9 @@ msgstr ""
msgid "Environments|protected"
msgstr ""
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
msgid "Epic"
msgstr ""
@@ -14340,9 +14467,6 @@ msgstr ""
msgid "Exported requirements"
msgstr ""
-msgid "External Classification Policy Authorization"
-msgstr ""
-
msgid "External ID"
msgstr ""
@@ -14352,15 +14476,9 @@ msgstr ""
msgid "External User:"
msgstr ""
-msgid "External authentication"
-msgstr ""
-
msgid "External authorization denied access to this project"
msgstr ""
-msgid "External authorization request timeout"
-msgstr ""
-
msgid "External storage URL"
msgstr ""
@@ -14376,6 +14494,54 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
msgstr ""
@@ -14455,10 +14621,7 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create merge request. Please try again."
-msgstr ""
-
-msgid "Failed to create new project access token: %{token_response_message}"
+msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
msgid "Failed to create repository"
@@ -14897,13 +15060,6 @@ msgstr ""
msgid "FeatureFlag|User List"
msgstr ""
-msgid "FeatureHighlight|%{daysRemaining} day remaining to enjoy %{featureName}"
-msgid_plural "FeatureHighlight|%{daysRemaining} days remaining to enjoy %{featureName}"
-msgstr[0] ""
-
-msgid "FeatureHighlight|Enjoying your GitLab %{planNameForTrial} trial? To continue using %{featureName} after your trial ends, upgrade to GitLab %{planNameForUpgrade}."
-msgstr ""
-
msgid "Feb"
msgstr "2月"
@@ -14991,12 +15147,6 @@ msgstr ""
msgid "Filter by"
msgstr ""
-msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
-
-msgid "Filter by %{issuable_type} that are currently open."
-msgstr ""
-
msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
@@ -15321,6 +15471,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Found warning in your .gitlab-ci.yml"
+msgstr ""
+
msgid "Framework successfully deleted"
msgstr ""
@@ -15396,6 +15549,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
msgid "Generate key"
msgstr ""
@@ -15432,18 +15588,21 @@ msgstr ""
msgid "Geo"
msgstr "Geo"
-msgid "Geo Nodes"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
+msgid "Geo Sites"
+msgstr ""
+
msgid "Geo sites"
msgstr ""
+msgid "Geo|%{boldStart}N/A%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
msgid "Geo|%{component} synced"
msgstr ""
@@ -15480,6 +15639,9 @@ msgstr ""
msgid "Geo|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 "Geo|All"
+msgstr ""
+
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -15534,6 +15696,9 @@ msgstr ""
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -15609,12 +15774,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Node name can't be blank"
-msgstr ""
-
-msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
-
msgid "Geo|Not synced yet"
msgstr ""
@@ -15630,6 +15789,9 @@ msgstr ""
msgid "Geo|Offline"
msgstr ""
+msgid "Geo|Open replications"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -15663,16 +15825,19 @@ msgstr ""
msgid "Geo|Remove"
msgstr ""
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
msgid "Geo|Remove entry"
msgstr ""
-msgid "Geo|Remove node"
+msgid "Geo|Remove site"
msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
-msgid "Geo|Removing a Geo node stops the synchronization to and from that node. Are you sure?"
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
msgstr ""
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
@@ -15684,9 +15849,6 @@ msgstr ""
msgid "Geo|Replication Details"
msgstr ""
-msgid "Geo|Replication details"
-msgstr ""
-
msgid "Geo|Replication slot WAL"
msgstr ""
@@ -15735,6 +15897,12 @@ msgstr ""
msgid "Geo|Selective (%{syncLabel})"
msgstr ""
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15771,10 +15939,10 @@ msgstr ""
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
-msgid "Geo|There was an error deleting the Geo Node"
+msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
-msgid "Geo|There was an error fetching the Geo Nodes"
+msgid "Geo|There was an error fetching the Geo Sites"
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
@@ -15852,6 +16020,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -15975,9 +16146,6 @@ msgstr ""
msgid "GitLab export"
msgstr ""
-msgid "GitLab for Slack"
-msgstr ""
-
msgid "GitLab group: %{source_link}"
msgstr ""
@@ -16002,6 +16170,9 @@ msgstr ""
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "GitLab logo"
+msgstr ""
+
msgid "GitLab member or Email address"
msgstr ""
@@ -16182,6 +16353,9 @@ msgstr ""
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 Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+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 ""
@@ -16320,6 +16494,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
+msgid "Go to parent directory"
+msgstr ""
+
msgid "Go to previous page"
msgstr ""
@@ -16488,6 +16665,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
+msgid "Group Access Tokens"
+msgstr ""
+
msgid "Group Git LFS status:"
msgstr ""
@@ -16506,6 +16686,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "Group application: %{name}"
msgstr ""
@@ -16569,9 +16752,6 @@ msgstr ""
msgid "Group jobs by"
msgstr ""
-msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
-
msgid "Group members"
msgstr ""
@@ -16596,6 +16776,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group owners can register group runners in the %{link}"
+msgstr ""
+
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -16608,9 +16791,6 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group projects"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -16851,18 +17031,12 @@ msgstr ""
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
-msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
-
msgid "GroupSAML|SCIM Token"
msgstr ""
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
-msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
-
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
msgstr ""
@@ -16887,9 +17061,6 @@ msgstr ""
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
msgstr ""
-msgid "GroupSAML|Your SCIM token"
-msgstr ""
-
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16920,7 +17091,10 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Allow project access token creation"
+msgid "GroupSettings|Allow project and group access token creation"
+msgstr ""
+
+msgid "GroupSettings|Allows creating organizations and contacts and associating them with issues."
msgstr ""
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
@@ -16968,6 +17142,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Enable customer relations"
+msgstr ""
+
msgid "GroupSettings|Enable delayed project deletion"
msgstr ""
@@ -16986,9 +17163,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17016,9 +17190,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -17061,7 +17232,7 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
-msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group."
msgstr ""
msgid "GroupSettings|What are badges?"
@@ -17142,9 +17313,6 @@ 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."
msgstr ""
-msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
-msgstr ""
-
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -17199,7 +17367,7 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
-msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
msgstr ""
msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
@@ -17426,6 +17594,33 @@ msgstr[0] ""
msgid "Hide values"
msgstr ""
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -17486,9 +17681,6 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
-msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
-
msgid "How do I configure Akismet?"
msgstr ""
@@ -17525,9 +17717,6 @@ msgstr ""
msgid "How do I use file templates?"
msgstr ""
-msgid "How it works"
-msgstr ""
-
msgid "How many days need to pass between marking entity for deletion and actual removing it."
msgstr ""
@@ -17543,6 +17732,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -17642,6 +17834,18 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
@@ -17666,9 +17870,6 @@ msgstr ""
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}Learn more%{linkEnd}"
msgstr ""
-msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
-
msgid "If enabled, only protected branches will be mirrored."
msgstr ""
@@ -18266,6 +18467,9 @@ msgstr ""
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
msgstr ""
@@ -18368,6 +18572,9 @@ msgstr ""
msgid "InProductMarketing|Very easy"
msgstr ""
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+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 ""
@@ -18443,6 +18650,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident details"
+msgstr ""
+
msgid "Incident template (optional)."
msgstr ""
@@ -18864,9 +19074,6 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{link_end}, %{chrome_link_start}Google Chrome%{link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
-msgstr ""
-
msgid "Integrations|All details"
msgstr ""
@@ -18879,9 +19086,6 @@ msgstr ""
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
-msgid "Integrations|Browser limitations"
-msgstr ""
-
msgid "Integrations|Comment detail:"
msgstr ""
@@ -18951,6 +19155,9 @@ msgstr ""
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
msgstr ""
+msgid "Integrations|Known limitations"
+msgstr ""
+
msgid "Integrations|Link namespaces"
msgstr ""
@@ -18969,9 +19176,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
-msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
-msgstr ""
-
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -19008,6 +19212,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -19017,6 +19224,9 @@ msgstr ""
msgid "Integrations|There are no projects using custom settings"
msgstr ""
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
@@ -19077,7 +19287,7 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
-msgid "Internal error occured while delivering this webhook."
+msgid "Internal error occurred while delivering this webhook."
msgstr ""
msgid "Internal users"
@@ -20896,6 +21106,9 @@ msgstr ""
msgid "License file"
msgstr ""
+msgid "License key"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -21212,9 +21425,6 @@ msgstr ""
msgid "Loading…"
msgstr ""
-msgid "Local IP addresses and domain names that hooks and services may access."
-msgstr ""
-
msgid "Localization"
msgstr ""
@@ -21230,6 +21440,9 @@ msgstr "鎖定"
msgid "Lock %{issuableDisplayName}"
msgstr ""
+msgid "Lock File?"
+msgstr ""
+
msgid "Lock memberships to LDAP synchronization"
msgstr ""
@@ -21266,6 +21479,39 @@ msgstr ""
msgid "Locks the discussion."
msgstr ""
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -22040,6 +22286,12 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request pipelines are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for merge request pipelines."
+msgstr ""
+
msgid "Merge request reports"
msgstr ""
@@ -22058,9 +22310,18 @@ msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "Merge..."
+msgstr ""
+
msgid "MergeConflict|Commit to source branch"
msgstr ""
@@ -22879,9 +23140,6 @@ msgstr ""
msgid "More Information"
msgstr ""
-msgid "More Slack commands"
-msgstr ""
-
msgid "More actions"
msgstr ""
@@ -22903,9 +23161,6 @@ msgstr ""
msgid "More information."
msgstr ""
-msgid "More options"
-msgstr ""
-
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -23081,10 +23336,10 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
+msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}user caps%{link_end} and %{users_pending_approval_link_start}users pending approval%{link_end}."
msgstr ""
-msgid "NamespaceUserCap|View pending user approvals"
+msgid "NamespaceUserCap|View pending approvals"
msgstr ""
msgid "NamespaceUserCap|Your group has reached its billable member limit"
@@ -23189,9 +23444,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
-msgid "NetworkPolicies|.yaml"
-msgstr ""
-
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@@ -23270,9 +23522,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
-msgid "NetworkPolicies|Rule"
-msgstr ""
-
msgid "NetworkPolicies|Rule mode"
msgstr ""
@@ -23291,9 +23540,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr ""
-msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -23808,6 +24054,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -23835,6 +24084,9 @@ msgstr ""
msgid "No profiles found"
msgstr ""
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
msgid "No projects found"
msgstr ""
@@ -23901,7 +24153,7 @@ msgstr ""
msgid "No webhook events"
msgstr ""
-msgid "No webhooks found, add one in the form above."
+msgid "No webhooks enabled. Select trigger events above."
msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
@@ -24804,7 +25056,28 @@ msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "Outbound requests"
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -25420,9 +25693,6 @@ msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
-msgstr ""
-
msgid "Patch to apply"
msgstr ""
@@ -25561,6 +25831,9 @@ msgstr ""
msgid "PerformanceBar|wall"
msgstr ""
+msgid "Performs a rebase but skips triggering a new pipeline"
+msgstr ""
+
msgid "Period in seconds"
msgstr ""
@@ -25579,7 +25852,7 @@ msgstr ""
msgid "Permissions Help"
msgstr ""
-msgid "Permissions, LFS, 2FA"
+msgid "Permissions and group features"
msgstr ""
msgid "Personal Access Token"
@@ -25846,9 +26119,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
@@ -25861,6 +26131,9 @@ msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -25873,7 +26146,7 @@ msgstr ""
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
-msgid "Pipelines|Child pipeline"
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
msgstr ""
msgid "Pipelines|Clear runner caches"
@@ -26038,10 +26311,28 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|detached"
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
msgid "Pipelines|invalid"
msgstr ""
-msgid "Pipelines|parent"
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|train"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
msgstr ""
msgid "Pipeline|Actions"
@@ -26224,6 +26515,9 @@ msgstr ""
msgid "Plan:"
msgstr ""
+msgid "Planning hierarchy"
+msgstr ""
+
msgid "PlantUML"
msgstr ""
@@ -26239,6 +26533,12 @@ msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -26593,6 +26893,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
msgid "Prev"
msgstr ""
@@ -26818,6 +27121,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
msgid "Profiles|Bio"
msgstr ""
@@ -26842,9 +27148,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27022,6 +27325,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
@@ -27067,9 +27373,6 @@ msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
-msgstr ""
-
msgid "Profiles|Update profile settings"
msgstr ""
@@ -27592,10 +27895,13 @@ msgstr ""
msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
-msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
@@ -27673,6 +27979,12 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27718,6 +28030,9 @@ msgstr ""
msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
msgstr ""
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
@@ -27844,9 +28159,6 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
-
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27868,7 +28180,7 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
msgstr ""
msgid "ProjectSettings|View project analytics."
@@ -27886,7 +28198,7 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
@@ -28648,9 +28960,6 @@ msgstr ""
msgid "Public deploy keys"
msgstr ""
-msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
-
msgid "Public pipelines"
msgstr ""
@@ -28684,7 +28993,7 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
-msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
msgstr ""
msgid "Push"
@@ -28930,6 +29239,12 @@ msgstr ""
msgid "Rebase source branch on the target branch."
msgstr ""
+msgid "Rebase without CI"
+msgstr ""
+
+msgid "Rebases and triggers a pipeline"
+msgstr ""
+
msgid "Recaptcha verified?"
msgstr ""
@@ -28999,6 +29314,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
msgid "Reduce this project’s visibility?"
msgstr ""
@@ -29072,7 +29390,7 @@ msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
-msgid "RegistrationFeatures|Read more about the %{linkStart}%{label}%{linkEnd}."
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
msgstr ""
msgid "RegistrationFeatures|Registration Features Program"
@@ -29609,6 +29927,10 @@ msgid "Reports|Accessibility scanning detected %d issue for the source branch on
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
@@ -29833,6 +30155,9 @@ msgstr ""
msgid "Repository size is above the limit."
msgstr ""
+msgid "Repository size limit (MB)"
+msgstr ""
+
msgid "Repository storage"
msgstr ""
@@ -29908,9 +30233,6 @@ msgstr ""
msgid "Requests per period"
msgstr ""
-msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
-msgstr ""
-
msgid "Require additional authentication for administrative tasks."
msgstr ""
@@ -29929,6 +30251,9 @@ msgstr ""
msgid "Required only if you are not using role instance credentials."
msgstr ""
+msgid "Requirement"
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -30054,9 +30379,6 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
-msgid "Resolves IP addresses once and uses them to submit requests"
-msgstr ""
-
msgid "Response"
msgstr ""
@@ -30123,7 +30445,7 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
msgstr ""
msgid "Retry"
@@ -30221,13 +30543,13 @@ msgstr ""
msgid "Revoked"
msgstr ""
-msgid "Revoked impersonation token %{token_name}!"
+msgid "Revoked access token %{access_token_name}!"
msgstr ""
-msgid "Revoked personal access token %{personal_access_token_name}!"
+msgid "Revoked impersonation token %{token_name}!"
msgstr ""
-msgid "Revoked project access token %{project_access_token_name}!"
+msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
msgid "RightSidebar|Copy email address"
@@ -30248,6 +30570,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
+msgid "Roadmap settings"
+msgstr ""
+
msgid "Role"
msgstr ""
@@ -30335,6 +30660,9 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Assigned Group"
+msgstr ""
+
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -30347,9 +30675,15 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Change to project runner"
+msgstr ""
+
msgid "Runners|Command to register runner"
msgstr ""
+msgid "Runners|Configuration"
+msgstr ""
+
msgid "Runners|Copy instructions"
msgstr ""
@@ -30368,6 +30702,9 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Details"
+msgstr ""
+
msgid "Runners|Download and install binary"
msgstr ""
@@ -30383,9 +30720,6 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
-msgid "Runners|Group Runners"
-msgstr ""
-
msgid "Runners|IP Address"
msgstr ""
@@ -30434,10 +30768,13 @@ msgstr ""
msgid "Runners|Offline"
msgstr ""
+msgid "Runners|Offline runners"
+msgstr ""
+
msgid "Runners|Online"
msgstr ""
-msgid "Runners|Online Runners"
+msgid "Runners|Online runners"
msgstr ""
msgid "Runners|Paused"
@@ -30473,6 +30810,9 @@ msgstr ""
msgid "Runners|Registration token copied!"
msgstr ""
+msgid "Runners|Reset token"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30512,16 +30852,16 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners in this group: %{groupRunnersCount}"
+msgid "Runners|Runs untagged jobs"
msgstr ""
msgid "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."
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Show runner installation and registration instructions"
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while fetching runner data."
@@ -30533,6 +30873,9 @@ msgstr ""
msgid "Runners|Stale"
msgstr ""
+msgid "Runners|Stale runners"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -30548,9 +30891,6 @@ msgstr ""
msgid "Runners|This runner has never contacted this instance"
msgstr ""
-msgid "Runners|This runner is associated with one or more projects."
-msgstr ""
-
msgid "Runners|This runner is associated with specific projects."
msgstr ""
@@ -30704,9 +31044,6 @@ msgstr ""
msgid "SSL verification"
msgstr ""
-msgid "SVG illustration"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30833,9 +31170,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
-msgid "Search Jira issues"
-msgstr ""
-
msgid "Search a group"
msgstr ""
@@ -31126,7 +31460,7 @@ msgstr ""
msgid "SecurityApprovals|License-Check"
msgstr ""
-msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
@@ -31258,6 +31592,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
+msgid "SecurityOrchestration| or "
+msgstr ""
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -31312,6 +31649,9 @@ msgstr ""
msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
msgid "SecurityOrchestration|Latest scan"
msgstr ""
@@ -31330,21 +31670,30 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
msgid "SecurityOrchestration|Policy description"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
msgstr ""
-msgid "SecurityOrchestration|Policy preview"
+msgid "SecurityOrchestration|Policy status"
msgstr ""
-msgid "SecurityOrchestration|Policy status"
+msgid "SecurityOrchestration|Policy summary"
msgstr ""
msgid "SecurityOrchestration|Policy type"
msgstr ""
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
msgid "SecurityOrchestration|Rule"
msgstr ""
@@ -31354,12 +31703,21 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
@@ -31387,6 +31745,12 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31402,12 +31766,60 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Update scan policies"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups"
+msgstr ""
+
+msgid "SecurityOrchestration|members of groups with ids"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group"
+msgstr ""
+
+msgid "SecurityOrchestration|members of the group with id"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|user with id"
+msgstr ""
+
+msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
msgid "SecurityPolicies|+%{count} more"
msgstr ""
@@ -31417,6 +31829,9 @@ msgstr ""
msgid "SecurityPolicies|Policy type"
msgstr ""
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -31738,9 +32153,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select GitLab project to link with your Slack team"
-msgstr ""
-
msgid "Select Page"
msgstr ""
@@ -32128,7 +32540,7 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service URL"
+msgid "Service Usage Data"
msgstr ""
msgid "Service account generated successfully"
@@ -32137,6 +32549,9 @@ msgstr ""
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
+msgid "Service usage data"
+msgstr ""
+
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -32146,18 +32561,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "ServiceDesk|Service Desk is enabled but not yet active"
-msgstr ""
-
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
-msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
-
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
@@ -32296,7 +32705,7 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner for a project"
+msgid "Set up a %{type} runner for a project"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -32468,9 +32877,6 @@ msgstr ""
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
-msgid "Sherlock Transactions"
-msgstr ""
-
msgid "Shimo|Go to Shimo Workspace"
msgstr ""
@@ -32510,6 +32916,9 @@ msgstr ""
msgid "Show all breadcrumbs"
msgstr ""
+msgid "Show all epics"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32522,6 +32931,9 @@ msgstr ""
msgid "Show archived projects only"
msgstr ""
+msgid "Show closed epics"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -32534,9 +32946,6 @@ msgstr ""
msgid "Show comments only"
msgstr ""
-msgid "Show commit description"
-msgstr ""
-
msgid "Show complete raw log"
msgstr ""
@@ -32561,6 +32970,9 @@ msgstr ""
msgid "Show one file at a time"
msgstr ""
+msgid "Show open epics"
+msgstr ""
+
msgid "Show the Closed list"
msgstr ""
@@ -32599,7 +33011,7 @@ msgstr ""
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
-msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
msgstr ""
msgid "Showing graphs based on events of the last %{timerange} days."
@@ -32692,6 +33104,9 @@ msgstr ""
msgid "Sign up"
msgstr ""
+msgid "Sign up now"
+msgstr ""
+
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
@@ -32794,9 +33209,33 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|To set up this integration press \"Add to Slack\""
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -33103,9 +33542,6 @@ msgstr ""
msgid "Something went wrong. Try again later."
msgstr ""
-msgid "Sorry, no epics matched your search"
-msgstr ""
-
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -33169,9 +33605,6 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
-msgid "SortOptions|Last updated"
-msgstr ""
-
msgid "SortOptions|Least popular"
msgstr ""
@@ -33505,6 +33938,9 @@ msgstr ""
msgid "Start merge train when pipeline succeeds"
msgstr ""
+msgid "Start merge train..."
+msgstr ""
+
msgid "Start search"
msgstr ""
@@ -33547,6 +33983,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province"
+msgstr ""
+
msgid "State/Province/City"
msgstr ""
@@ -33889,6 +34328,9 @@ msgstr ""
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
+msgid "Subscribed to this project"
+msgstr ""
+
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -33919,6 +34361,27 @@ msgstr ""
msgid "SubscriptionBanner|Upload new license"
msgstr ""
+msgid "SubscriptionEmail|%{doc_link_start}Please reach out if you have questions%{doc_link_end}, and we'll be happy to assist."
+msgstr ""
+
+msgid "SubscriptionEmail|Additional charges for your GitLab subscription"
+msgstr ""
+
+msgid "SubscriptionEmail|Dear %{customer_name},"
+msgstr ""
+
+msgid "SubscriptionEmail|GitLab Billing Team"
+msgstr ""
+
+msgid "SubscriptionEmail|Thank you for your business!"
+msgstr ""
+
+msgid "SubscriptionEmail|You can find more information about the quarterly reconciliation process in %{doc_link_start}our documentation%{doc_link_end}."
+msgstr ""
+
+msgid "SubscriptionEmail|You have exceeded the number of seats in your GitLab subscription %{subscription_name} by %{seat_quantity}. Even if you've exceeded the seats in your subscription, you can continue to add users, and GitLab will bill you a prorated amount for any seat overages on a quarterly basis."
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -33997,9 +34460,6 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
-msgid "SubscriptionTable|Upgrade"
-msgstr ""
-
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -34168,9 +34628,6 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate cloud license"
-msgstr ""
-
msgid "SuperSonics|Activate subscription"
msgstr ""
@@ -34195,6 +34652,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -34234,6 +34694,9 @@ msgstr ""
msgid "SuperSonics|Subscription details"
msgstr ""
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
msgid "SuperSonics|Sync subscription details"
msgstr ""
@@ -34288,6 +34751,9 @@ 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 %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
@@ -34300,6 +34766,15 @@ msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -34543,6 +35018,9 @@ msgstr ""
msgid "Target-Branch"
msgstr ""
+msgid "Task"
+msgstr ""
+
msgid "Task ID: %{elastic_task}"
msgstr ""
@@ -34615,6 +35093,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Terms of service"
+msgstr ""
+
msgid "Terraform"
msgstr ""
@@ -34781,6 +35262,9 @@ msgstr ""
msgid "Test Cases"
msgstr ""
+msgid "Test case"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -34951,9 +35435,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-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 ""
@@ -34991,12 +35472,6 @@ msgstr ""
msgid "The Snowplow cookie domain."
msgstr ""
-msgid "The URL defined on the primary node that secondary nodes should use to contact it."
-msgstr ""
-
-msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
-
msgid "The URL of the Jenkins server."
msgstr ""
@@ -35006,9 +35481,6 @@ msgstr ""
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
-msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
-
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
@@ -35042,7 +35514,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue"
+msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
@@ -35208,6 +35680,9 @@ msgstr ""
msgid "The latest pipeline for this merge request did not complete successfully."
msgstr ""
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
msgid "The latest pipeline for this merge request has failed."
msgstr ""
@@ -35283,9 +35758,6 @@ msgstr ""
msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
-
msgid "The password for the Jenkins server."
msgstr ""
@@ -35301,9 +35773,6 @@ 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 private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
-
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
@@ -35673,7 +36142,7 @@ msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
-msgid "There was an error fetching the Node's Groups"
+msgid "There was an error fetching the Sites's Groups"
msgstr ""
msgid "There was an error fetching the deploy freezes."
@@ -35724,7 +36193,7 @@ msgstr ""
msgid "There was an error retrieving the Jira users."
msgstr ""
-msgid "There was an error saving this Geo Node."
+msgid "There was an error saving this Geo Site"
msgstr ""
msgid "There was an error saving your changes."
@@ -35808,9 +36277,6 @@ msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
-msgid "Third-party offers"
-msgstr ""
-
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
@@ -35934,6 +36400,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
msgid "This credential has expired"
msgstr ""
@@ -35973,9 +36442,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This feature is part of your GitLab Ultimate trial."
-msgstr ""
-
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -36015,9 +36481,15 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group has no active access tokens."
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
@@ -36237,6 +36709,9 @@ msgstr ""
msgid "This project"
msgstr ""
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
msgid "This project does not belong to a group and cannot make use of group runners."
msgstr ""
@@ -36258,6 +36733,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr ""
@@ -36297,6 +36775,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
msgid "This subscription is for"
msgstr ""
@@ -36525,9 +37006,6 @@ msgstr ""
msgid "Time in seconds"
msgstr ""
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
-
msgid "Time of import: %{importTime}"
msgstr ""
@@ -36773,9 +37251,6 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
-
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -36917,9 +37392,6 @@ msgstr ""
msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
-msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
-
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
@@ -36935,9 +37407,6 @@ msgstr ""
msgid "To widen your search, change or remove filters above."
msgstr ""
-msgid "To widen your search, change or remove filters."
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -37145,9 +37614,6 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Track your GitLab projects with GitLab for Slack."
-msgstr ""
-
msgid "Training mode"
msgstr ""
@@ -37257,6 +37723,9 @@ msgstr ""
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Trial|Company name"
msgstr ""
@@ -37272,15 +37741,9 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|First name"
-msgstr ""
-
msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
-msgid "Trial|Last name"
-msgstr ""
-
msgid "Trial|Number of employees"
msgstr ""
@@ -37347,6 +37810,12 @@ msgstr ""
msgid "Triggerer"
msgstr ""
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -37866,6 +38335,9 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
+msgid "Updated date"
+msgstr ""
+
msgid "Updates"
msgstr ""
@@ -37887,6 +38359,9 @@ msgstr ""
msgid "Upload"
msgstr ""
+msgid "Upload %{file_name} file"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -38322,6 +38797,9 @@ msgstr ""
msgid "User cap"
msgstr ""
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -38853,6 +39331,18 @@ msgstr ""
msgid "Version %{versionNumber} (latest)"
msgstr ""
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -38997,6 +39487,9 @@ msgstr[0] ""
msgid "View replaced file @ "
msgstr ""
+msgid "View seat usage"
+msgstr ""
+
msgid "View setting"
msgstr ""
@@ -39222,6 +39715,9 @@ msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
msgid "Vulnerability|Additional Info"
msgstr ""
@@ -39264,6 +39760,9 @@ msgstr ""
msgid "Vulnerability|Download"
msgstr ""
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -39282,6 +39781,12 @@ msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
msgid "Vulnerability|Identifiers"
msgstr ""
@@ -39291,6 +39796,9 @@ msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
+msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -39303,6 +39811,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -39315,6 +39826,9 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Secure Code Warrior"
+msgstr ""
+
msgid "Vulnerability|Security Audit"
msgstr ""
@@ -39339,9 +39853,18 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
msgid "Vulnerability|Unmodified Response"
msgstr ""
+msgid "Vulnerability|View training"
+msgstr ""
+
msgid "WARNING:"
msgstr ""
@@ -39522,127 +40045,127 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "Webhooks|Comments"
+msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
-msgid "Webhooks|Confidential comments"
+msgid "Webhooks|A comment is added to an issue."
msgstr ""
-msgid "Webhooks|Confidential issues events"
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Deployment events"
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr ""
-msgid "Webhooks|Enable SSL verification"
+msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
-msgid "Webhooks|Failed to connect"
+msgid "Webhooks|A group member is created, updated, or removed."
msgstr ""
-msgid "Webhooks|Fails to connect"
+msgid "Webhooks|A job's status changes."
msgstr ""
-msgid "Webhooks|Feature flag events"
+msgid "Webhooks|A merge request is created, updated, or merged."
msgstr ""
-msgid "Webhooks|Issues events"
+msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
-msgid "Webhooks|Job events"
+msgid "Webhooks|A pipeline's status changes."
msgstr ""
-msgid "Webhooks|Member events"
+msgid "Webhooks|A release is created or updated."
msgstr ""
-msgid "Webhooks|Merge request events"
+msgid "Webhooks|A subgroup is created or removed."
msgstr ""
-msgid "Webhooks|Pipeline events"
+msgid "Webhooks|A wiki page is created or updated."
msgstr ""
-msgid "Webhooks|Push events"
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr ""
-msgid "Webhooks|Releases events"
+msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|SSL verification"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Secret token"
+msgid "Webhooks|Confidential issues events"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Deployment events"
msgstr ""
-msgid "Webhooks|Tag push events"
+msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Failed to connect"
msgstr ""
-msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgid "Webhooks|Fails to connect"
msgstr ""
-msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgid "Webhooks|Feature flag events"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|Issues events"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|Job events"
msgstr ""
-msgid "Webhooks|URL is triggered by a push to the repository"
+msgid "Webhooks|Member events"
msgstr ""
-msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
+msgid "Webhooks|Merge request events"
msgstr ""
-msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Pipeline events"
msgstr ""
-msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|Push events"
msgstr ""
-msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgid "Webhooks|Push to the repository."
msgstr ""
-msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgid "Webhooks|Releases events"
msgstr ""
-msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|URL is triggered when a release is created or updated"
+msgid "Webhooks|Secret token"
msgstr ""
-msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgid "Webhooks|Subgroup events"
msgstr ""
-msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment"
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr ""
-msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr ""
-msgid "Webhooks|URL is triggered when the job status changes"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
msgid "Webhooks|Webhook failed to connect"
@@ -39750,10 +40273,10 @@ msgstr ""
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
-msgid "When inactive, an external authentication provider must be used."
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
msgstr ""
-msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgid "When inactive, an external authentication provider must be used."
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
@@ -40060,7 +40583,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "Work in progress- click here to find out more"
+msgid "WorkItem|Convert to work item"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|New Task"
msgstr ""
msgid "WorkItem|Work Items"
@@ -40162,6 +40691,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -40195,6 +40727,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
msgid "You are not authorized to update this profile"
msgstr ""
@@ -40243,6 +40778,9 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -40288,6 +40826,9 @@ msgstr ""
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
msgstr ""
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
msgstr ""
@@ -40423,6 +40964,9 @@ msgstr ""
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
@@ -40514,6 +41058,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -40553,7 +41100,7 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
-msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
@@ -40568,6 +41115,9 @@ msgstr ""
msgid "You may close the milestone now."
msgstr ""
+msgid "You must be authenticated to access this path."
+msgstr ""
+
msgid "You must be logged in to search across all of GitLab"
msgstr ""
@@ -40949,7 +41499,7 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new SCIM token"
+msgid "Your new access token has been created."
msgstr ""
msgid "Your new comment"
@@ -40958,9 +41508,6 @@ msgstr ""
msgid "Your new personal access token has been created."
msgstr ""
-msgid "Your new project access token has been created."
-msgstr ""
-
msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
msgstr ""
@@ -41027,6 +41574,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription has %{remaining_seats_count} out of %{total_seats_count} seats remaining. Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
msgstr ""
@@ -41155,6 +41705,10 @@ msgstr ""
msgid "any-approver for the project already exists"
msgstr ""
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+
msgid "approved by: "
msgstr ""
@@ -41237,6 +41791,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled"
msgstr ""
+msgid "cannot be enabled"
+msgstr ""
+
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -41606,6 +42163,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "contact with same email already exists in group hierarchy"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41633,12 +42193,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
-msgid "created %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "created %{timeAgo}"
msgstr ""
@@ -41764,6 +42318,9 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -41808,6 +42365,12 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
msgid "group members"
msgstr ""
@@ -41923,6 +42486,9 @@ msgstr ""
msgid "is not allowed since the group is not top-level group."
msgstr ""
+msgid "is not allowed."
+msgstr ""
+
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -42019,9 +42585,6 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "log in"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -42062,9 +42625,6 @@ msgstr ""
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
-msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
-
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -42186,7 +42746,7 @@ msgstr ""
msgid "mrWidget|Hide %{widget} details"
msgstr ""
-msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
msgstr ""
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
@@ -42232,6 +42792,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr ""
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -42286,6 +42849,9 @@ msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -42331,6 +42897,9 @@ msgstr ""
msgid "mrWidget|Show %{widget} details"
msgstr ""
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -42340,9 +42909,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
-msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
-
msgid "mrWidget|The source branch has been deleted"
msgstr ""
@@ -42379,9 +42945,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|branch does not exist."
-msgstr ""
-
msgid "mrWidget|into"
msgstr ""
@@ -42657,9 +43220,6 @@ msgstr ""
msgid "required"
msgstr ""
-msgid "reset it."
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -42840,9 +43400,6 @@ msgstr ""
msgid "user namespace cannot be the parent of another namespace"
msgstr ""
-msgid "user preferences"
-msgstr ""
-
msgid "username"
msgstr ""
diff --git a/metrics_server/dependencies.rb b/metrics_server/dependencies.rb
index 5615cef42ce..02cec1173e0 100644
--- a/metrics_server/dependencies.rb
+++ b/metrics_server/dependencies.rb
@@ -23,6 +23,7 @@ require_relative '../lib/gitlab/metrics/system'
require_relative '../lib/gitlab/metrics/samplers/base_sampler'
require_relative '../lib/gitlab/metrics/samplers/ruby_sampler'
require_relative '../lib/gitlab/metrics/exporter/base_exporter'
+require_relative '../lib/gitlab/metrics/exporter/web_exporter'
require_relative '../lib/gitlab/metrics/exporter/sidekiq_exporter'
require_relative '../lib/gitlab/metrics/exporter/metrics_middleware'
require_relative '../lib/gitlab/metrics/exporter/health_checks_middleware'
diff --git a/metrics_server/metrics_server.rb b/metrics_server/metrics_server.rb
index 122a4e4fc1e..70769459019 100644
--- a/metrics_server/metrics_server.rb
+++ b/metrics_server/metrics_server.rb
@@ -6,8 +6,23 @@ require_relative 'dependencies'
class MetricsServer # rubocop:disable Gitlab/NamespacedClass
class << self
- def spawn(target, metrics_dir:, wipe_metrics_dir: false, trapped_signals: [])
- raise "The only valid target is 'sidekiq' currently" unless target == 'sidekiq'
+ def spawn(target, metrics_dir:, gitlab_config: nil, wipe_metrics_dir: false)
+ ensure_valid_target!(target)
+
+ cmd = "#{Rails.root}/bin/metrics-server"
+ env = {
+ 'METRICS_SERVER_TARGET' => target,
+ 'WIPE_METRICS_DIR' => wipe_metrics_dir ? '1' : '0'
+ }
+ env['GITLAB_CONFIG'] = gitlab_config if gitlab_config
+
+ Process.spawn(env, cmd, err: $stderr, out: $stdout, pgroup: true).tap do |pid|
+ Process.detach(pid)
+ end
+ end
+
+ def fork(target, metrics_dir:, wipe_metrics_dir: false, reset_signals: [])
+ ensure_valid_target!(target)
pid = Process.fork
@@ -15,7 +30,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
# Remove any custom signal handlers the parent process had registered, since we do
# not want to inherit them, and Ruby forks with a `clone` that has the `CLONE_SIGHAND`
# flag set.
- Gitlab::ProcessManagement.modify_signals(trapped_signals, 'DEFAULT')
+ Gitlab::ProcessManagement.modify_signals(reset_signals, 'DEFAULT')
server = MetricsServer.new(target, metrics_dir, wipe_metrics_dir)
# This rewrites /proc/cmdline, since otherwise tools like `top` will show the
@@ -29,6 +44,12 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
pid
end
+
+ private
+
+ def ensure_valid_target!(target)
+ raise "Target must be one of [puma,sidekiq]" unless %w(puma sidekiq).include?(target)
+ end
end
def initialize(target, metrics_dir, wipe_metrics_dir)
@@ -40,7 +61,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
def start
::Prometheus::Client.configure do |config|
config.multiprocess_files_dir = @metrics_dir
- config.pid_provider = proc { "#{@target}_exporter" }
+ config.pid_provider = proc { name }
end
FileUtils.mkdir_p(@metrics_dir, mode: 0700)
@@ -50,16 +71,25 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
# a race where not all Prometheus db files will be visible to the exporter, resulting
# in missing metrics.
# Warming up ensures that these files exist prior to the exporter starting up.
- Gitlab::Metrics::Samplers::RubySampler.initialize_instance(warmup: true).start
+ Gitlab::Metrics::Samplers::RubySampler.initialize_instance(prefix: name, warmup: true).start
- exporter_class = "Gitlab::Metrics::Exporter::#{@target.camelize}Exporter".constantize
- settings = Settings.new(Settings.monitoring[name])
- server = exporter_class.instance(settings, gc_requests: true, synchronous: true)
+ default_opts = { gc_requests: true, synchronous: true }
+ exporter =
+ case @target
+ when 'puma'
+ Gitlab::Metrics::Exporter::WebExporter.instance(**default_opts)
+ when 'sidekiq'
+ settings = Settings.new(Settings.monitoring[name])
+ Gitlab::Metrics::Exporter::SidekiqExporter.instance(settings, **default_opts)
+ end
- server.start
+ exporter.start
end
def name
- "#{@target}_exporter"
+ case @target
+ when 'puma' then 'web_exporter'
+ when 'sidekiq' then 'sidekiq_exporter'
+ end
end
end
diff --git a/package.json b/package.json
index d1630b6a64d..582d86454b8 100644
--- a/package.json
+++ b/package.json
@@ -44,10 +44,10 @@
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
"webpack-vendor": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.vendor.config.js",
- "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js",
- "webpack-prod-node-latest": "NODE_OPTIONS=\"--max-old-space-size=3584 --openssl-legacy-provider\" NODE_ENV=production webpack --config config/webpack.config.js"
+ "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js"
},
"dependencies": {
+ "@apollo/client": "^3.3.11",
"@babel/core": "^7.10.1",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-json-strings": "^7.10.1",
@@ -56,53 +56,46 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "2.2.0",
- "@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "32.68.0",
+ "@gitlab/svgs": "2.5.0",
+ "@gitlab/ui": "36.6.0",
"@gitlab/visual-review-tools": "1.6.1",
- "@rails/actioncable": "6.1.4-1",
- "@rails/ujs": "6.1.4-1",
+ "@rails/actioncable": "6.1.4-6",
+ "@rails/ujs": "6.1.4-6",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
- "@tiptap/core": "^2.0.0-beta.160",
+ "@tiptap/core": "^2.0.0-beta.171",
"@tiptap/extension-blockquote": "^2.0.0-beta.26",
"@tiptap/extension-bold": "^2.0.0-beta.25",
"@tiptap/extension-bullet-list": "^2.0.0-beta.26",
"@tiptap/extension-code": "^2.0.0-beta.26",
- "@tiptap/extension-code-block-lowlight": "2.0.0-beta.63",
+ "@tiptap/extension-code-block-lowlight": "2.0.0-beta.68",
"@tiptap/extension-document": "^2.0.0-beta.15",
"@tiptap/extension-dropcursor": "^2.0.0-beta.25",
"@tiptap/extension-gapcursor": "^2.0.0-beta.34",
"@tiptap/extension-hard-break": "^2.0.0-beta.30",
- "@tiptap/extension-heading": "^2.0.0-beta.24",
+ "@tiptap/extension-heading": "^2.0.0-beta.26",
"@tiptap/extension-history": "^2.0.0-beta.21",
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.30",
- "@tiptap/extension-image": "^2.0.0-beta.24",
+ "@tiptap/extension-horizontal-rule": "^2.0.0-beta.31",
+ "@tiptap/extension-image": "^2.0.0-beta.25",
"@tiptap/extension-italic": "^2.0.0-beta.25",
- "@tiptap/extension-link": "^2.0.0-beta.34",
+ "@tiptap/extension-link": "^2.0.0-beta.36",
"@tiptap/extension-list-item": "^2.0.0-beta.20",
"@tiptap/extension-ordered-list": "^2.0.0-beta.27",
"@tiptap/extension-paragraph": "^2.0.0-beta.23",
"@tiptap/extension-strike": "^2.0.0-beta.27",
"@tiptap/extension-subscript": "^2.0.0-beta.10",
"@tiptap/extension-superscript": "^2.0.0-beta.10",
- "@tiptap/extension-table": "^2.0.0-beta.46",
+ "@tiptap/extension-table": "^2.0.0-beta.48",
"@tiptap/extension-table-cell": "^2.0.0-beta.20",
"@tiptap/extension-table-header": "^2.0.0-beta.22",
"@tiptap/extension-table-row": "^2.0.0-beta.19",
- "@tiptap/extension-task-item": "^2.0.0-beta.30",
+ "@tiptap/extension-task-item": "^2.0.0-beta.31",
"@tiptap/extension-task-list": "^2.0.0-beta.26",
"@tiptap/extension-text": "^2.0.0-beta.15",
- "@tiptap/vue-2": "^2.0.0-beta.74",
+ "@tiptap/vue-2": "^2.0.0-beta.77",
"@toast-ui/editor": "^2.5.2",
"@toast-ui/vue-editor": "^2.5.2",
- "apollo-cache-inmemory": "^1.6.6",
- "apollo-client": "^2.6.10",
- "apollo-link": "^1.2.14",
- "apollo-link-batch-http": "^1.2.14",
- "apollo-link-error": "^1.1.13",
- "apollo-link-http": "^1.5.17",
- "apollo-upload-client": "^13.0.0",
+ "apollo-upload-client": "^14.1.3",
"autosize": "^5.0.1",
"aws-sdk": "^2.637.0",
"axios": "^0.24.0",
@@ -116,7 +109,7 @@
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.20.2",
+ "core-js": "^3.21.1",
"cron-validator": "^1.1.1",
"cronstrue": "^1.122.0",
"cropper": "^2.3.0",
@@ -127,7 +120,7 @@
"dateformat": "^5.0.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "dompurify": "^2.3.4",
+ "dompurify": "^2.3.5",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^10.0.0",
@@ -167,7 +160,7 @@
"prosemirror-model": "^1.16.1",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
- "prosemirror-view": "^1.23.5",
+ "prosemirror-view": "^1.23.6",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"scrollparent": "^2.0.1",
@@ -188,7 +181,7 @@
"uuid": "8.1.0",
"visibilityjs": "^1.2.4",
"vue": "^2.6.12",
- "vue-apollo": "^3.0.3",
+ "vue-apollo": "^3.0.7",
"vue-loader": "^15.9.6",
"vue-observe-visibility": "^1.0.0",
"vue-resize": "^1.0.1",
@@ -200,16 +193,16 @@
"web-vitals": "^0.2.4",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^4.4.2",
- "webpack-cli": "^3.3.12",
+ "webpack-cli": "^4.9.2",
"webpack-stats-plugin": "^0.3.1",
"worker-loader": "^2.0.0",
"xterm": "3.14.5",
- "yaml": "^2.0.0-8"
+ "yaml": "^2.0.0-10"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
"@gitlab/eslint-plugin": "10.0.0",
- "@gitlab/stylelint-config": "2.6.0",
+ "@gitlab/stylelint-config": "4.0.0",
"@graphql-eslint/eslint-plugin": "3.0.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.3.0",
@@ -243,12 +236,12 @@
"jest-util": "^26.5.2",
"jsdoc": "^3.5.5",
"jsdoc-vue": "^1.0.0",
- "markdownlint-cli": "0.26.0",
+ "markdownlint-cli": "0.31.0",
"md5": "^2.2.1",
"miragejs": "^0.1.40",
- "mock-apollo-client": "^0.7.0",
+ "mock-apollo-client": "1.2.0",
"nodemon": "^2.0.4",
- "postcss": "^7.0.14",
+ "postcss": "^8.4.5",
"prettier": "2.2.1",
"prosemirror-schema-basic": "^1.1.2",
"prosemirror-schema-list": "^1.1.6",
@@ -256,9 +249,10 @@
"purgecss": "^4.0.3",
"purgecss-from-html": "^4.0.3",
"sass": "^1.32.12",
+ "stylelint": "^14.3.0",
"timezone-mock": "^1.0.8",
"vue-jest": "4.0.1",
- "webpack-dev-server": "^3.11.3",
+ "webpack-dev-server": "4.7.4",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
"yarn-deduplicate": "^3.1.0"
@@ -267,6 +261,7 @@
"bootstrap-vue": "https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#bootstrapvue"
},
"resolutions": {
+ "@apollo/client/subscriptions-transport-ws": "0.11.0",
"chokidar": "^3.4.0",
"@types/node": "14.17.5"
},
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 54de6509518..fa666daa927 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -63,6 +63,7 @@ WORKDIR /home/gitlab/qa
# Install qa dependencies or fetch from cache if unchanged
COPY ./qa/Gemfile* /home/gitlab/qa/
+RUN gem install bundler --no-document --conservative --version 2.3.6
RUN bundle install --jobs=$(nproc) --retry=3 --without=development --quiet
##
diff --git a/qa/Gemfile b/qa/Gemfile
index c07f9dc96a7..1eaf9c7cec0 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -3,7 +3,7 @@
source 'https://rubygems.org'
gem 'gitlab-qa', require: 'gitlab/qa'
-gem 'activesupport', '~> 6.1.4.1' # This should stay in sync with the root's Gemfile
+gem 'activesupport', '~> 6.1.4.6' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.15.0'
gem 'capybara', '~> 3.35.0'
gem 'capybara-screenshot', '~> 1.0.23'
@@ -20,6 +20,7 @@ gem 'parallel_tests', '~> 2.29'
gem 'rotp', '~> 3.1.0'
gem 'timecop', '~> 0.9.1'
gem 'parallel', '~> 1.19'
+gem 'rainbow', '~> 3.0.0'
gem 'rspec-parameterized', '~> 0.4.2'
gem 'octokit', '~> 4.21'
gem 'webdrivers', '~> 5.0'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 3e85a33f2a2..6afd205a6e1 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
abstract_type (0.0.7)
- activesupport (6.1.4.1)
+ activesupport (6.1.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@@ -226,6 +226,7 @@ GEM
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
+ rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
representable (3.1.1)
@@ -321,7 +322,7 @@ PLATFORMS
ruby
DEPENDENCIES
- activesupport (~> 6.1.4.1)
+ activesupport (~> 6.1.4.6)
airborne (~> 0.3.4)
allure-rspec (~> 2.15.0)
capybara (~> 3.35.0)
@@ -339,6 +340,7 @@ DEPENDENCIES
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
+ rainbow (~> 3.0.0)
rake (~> 13)
rest-client (~> 2.1.0)
rotp (~> 3.1.0)
@@ -355,4 +357,4 @@ DEPENDENCIES
zeitwerk (~> 2.4)
BUNDLED WITH
- 2.2.33
+ 2.3.6
diff --git a/qa/lib/gitlab/page/admin/subscription.rb b/qa/lib/gitlab/page/admin/subscription.rb
index cdd9bb20b42..b90a49abf4b 100644
--- a/qa/lib/gitlab/page/admin/subscription.rb
+++ b/qa/lib/gitlab/page/admin/subscription.rb
@@ -6,6 +6,10 @@ module Gitlab
class Subscription < Chemlab::Page
path '/admin/subscription'
+ div :subscription_details
+ text_field :activation_code
+ button :activate
+ label :terms_of_services, text: /I agree that/
p :plan
p :started
p :name
@@ -16,6 +20,33 @@ module Gitlab
h2 :users_in_subscription
h2 :users_over_subscription
table :subscription_history
+
+ def accept_terms
+ terms_of_services_element.click # workaround for hidden checkbox
+ end
+
+ # Checks if a subscription record exists in subscription history table
+ #
+ # @param plan [Hash] Name of the plan
+ # @option plan [Hash] Support::Helpers::FREE
+ # @option plan [Hash] Support::Helpers::PREMIUM
+ # @option plan [Hash] Support::Helpers::PREMIUM_SELF_MANAGED
+ # @option plan [Hash] Support::Helpers::ULTIMATE
+ # @option plan [Hash] Support::Helpers::ULTIMATE_SELF_MANAGED
+ # @option plan [Hash] Support::Helpers::CI_MINUTES
+ # @option plan [Hash] Support::Helpers::STORAGE
+ # @param users_in_license [Integer] Number of users in license
+ # @param license_type [Hash] Type of the license
+ # @option license_type [String] 'license file'
+ # @option license_type [String] 'cloud license'
+ # @return [Boolean] True if record exsists, false if not
+ def has_subscription_record?(plan, users_in_license, license_type)
+ # find any records that have a matching plan and seats and type
+ subscription_history_element.hashes.any? do |record|
+ record['Plan'] == plan[:name].capitalize && record['Seats'] == users_in_license.to_s && \
+ record['Type'].strip.downcase == license_type
+ end
+ end
end
end
end
diff --git a/qa/lib/gitlab/page/admin/subscription.stub.rb b/qa/lib/gitlab/page/admin/subscription.stub.rb
index 89d7bfb95d9..56a063e8978 100644
--- a/qa/lib/gitlab/page/admin/subscription.stub.rb
+++ b/qa/lib/gitlab/page/admin/subscription.stub.rb
@@ -4,6 +4,112 @@ module Gitlab
module Page
module Admin
module Subscription
+ # @note Defined as +h6 :subscription_details+
+ # @return [String] The text content or value of +subscription_details+
+ def subscription_details
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.subscription_details_element).to exist
+ # end
+ # @return [Watir::H6] The raw +H6+ element
+ def subscription_details_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_subscription_details
+ # end
+ # @return [Boolean] true if the +subscription_details+ element is present on the page
+ def subscription_details?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +text_field :activation_code+
+ # @return [String] The text content or value of +activation_code+
+ def activation_code
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # Set the value of activation_code
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # subscription.activation_code = 'value'
+ # end
+ # @param value [String] The value to set.
+ def activation_code=(value)
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.activation_code_element).to exist
+ # end
+ # @return [Watir::TextField] The raw +TextField+ element
+ def activation_code_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_activation_code
+ # end
+ # @return [Boolean] true if the +activation_code+ element is present on the page
+ def activation_code?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +label :terms_of_services+
+ # @return [String] The text content or value of +terms_of_services+
+ def terms_of_services
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.terms_of_services_element).to exist
+ # end
+ # @return [Watir::Label] The raw +Label+ element
+ def terms_of_services_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_terms_of_services
+ # end
+ # @return [Boolean] true if the +terms_of_services+ element is present on the page
+ def terms_of_services?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +button :activate+
+ # Clicks +activate+
+ def activate
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.activate_element).to exist
+ # end
+ # @return [Watir::Button] The raw +Button+ element
+ def activate_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_activate
+ # end
+ # @return [Boolean] true if the +activate+ element is present on the page
+ def activate?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
# @note Defined as +p :plan+
# @return [String] The text content or value of +plan+
def plan
diff --git a/qa/qa.rb b/qa/qa.rb
index 703ed4ffe1d..442f6c578cf 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -51,7 +51,9 @@ module QA
"smtp" => "SMTP",
"otp" => "OTP",
"jira_api" => "JiraAPI",
- "registry_tls" => "RegistryTLS"
+ "registry_tls" => "RegistryTLS",
+ "jetbrains" => "JetBrains",
+ "vscode" => "VSCode"
)
loader.setup
diff --git a/qa/qa/fixtures/package_managers/composer/composer.json.erb b/qa/qa/fixtures/package_managers/composer/composer.json.erb
new file mode 100644
index 00000000000..a1e31e2599f
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/composer/composer.json.erb
@@ -0,0 +1,13 @@
+{
+ "name": "<%= project.path_with_namespace %>/<%= package.name %>",
+ "description": "Library XY",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "authors": [
+ {
+ "name": "John Doe",
+ "email": "john@example.com"
+ }
+ ],
+ "require": {}
+} \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/composer/composer_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/composer/composer_upload_package.yaml.erb
new file mode 100644
index 00000000000..b6bcfafffee
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/composer/composer_upload_package.yaml.erb
@@ -0,0 +1,13 @@
+publish:
+ image: curlimages/curl:latest
+ stage: build
+ variables:
+ URL: "$CI_SERVER_PROTOCOL://$CI_SERVER_HOST:$CI_SERVER_PORT/api/v4/projects/$CI_PROJECT_ID/packages/composer?job_token=$CI_JOB_TOKEN"
+ script:
+ - version=$([[ -z "$CI_COMMIT_TAG" ]] && echo "branch=$CI_COMMIT_REF_NAME" || echo "tag=$CI_COMMIT_TAG")
+ - insecure=$([ "$CI_SERVER_PROTOCOL" = "http" ] && echo "--insecure" || echo "")
+ - response=$(curl -s -w "%{http_code}" $insecure --data $version $URL)
+ - code=$(echo "$response" | tail -n 1)
+ - body=$(echo "$response" | head -n 1)
+ tags:
+ - "runner-for-<%= project.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/conan/conan_upload_install_package.yaml.erb b/qa/qa/fixtures/package_managers/conan/conan_upload_install_package.yaml.erb
new file mode 100644
index 00000000000..39c04f6511b
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/conan/conan_upload_install_package.yaml.erb
@@ -0,0 +1,12 @@
+image: conanio/gcc7
+
+test_package:
+ stage: deploy
+ script:
+ - conan remote add gitlab <%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/conan
+ - conan new <%= package.name %>/0.1 -t
+ - conan create . mycompany/stable
+ - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload <%= package.name %>/0.1@mycompany/stable --all --remote=gitlab"
+ - conan install <%= package.name %>/0.1@mycompany/stable --remote=gitlab
+ tags:
+ - runner-for-<%= project.name %> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/generic/generic_upload_install_package.yaml.erb b/qa/qa/fixtures/package_managers/generic/generic_upload_install_package.yaml.erb
new file mode 100644
index 00000000000..13fe3e2c62e
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/generic/generic_upload_install_package.yaml.erb
@@ -0,0 +1,18 @@
+image: curlimages/curl:latest
+
+stages:
+ - upload
+ - download
+
+upload:
+ stage: upload
+ script:
+ - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/<%= package.name %>/0.0.1/file.txt'
+ tags:
+ - runner-for-<%= project.name %>
+download:
+ stage: download
+ script:
+ - 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/<%= package.name %>/0.0.1/file.txt -O file_downloaded.txt'
+ tags:
+ - runner-for-<%= project.name %> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/helm/Chart.yaml.erb b/qa/qa/fixtures/package_managers/helm/Chart.yaml.erb
new file mode 100644
index 00000000000..5a56533c65d
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/helm/Chart.yaml.erb
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: <%= package_name %>
+description: GitLab QA helm package
+type: application
+version: <%= package_version %>
+appVersion: "1.16.0" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/helm/helm_install_package.yaml.erb b/qa/qa/fixtures/package_managers/helm/helm_install_package.yaml.erb
new file mode 100644
index 00000000000..786b0592153
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/helm/helm_install_package.yaml.erb
@@ -0,0 +1,11 @@
+pull:
+ image: alpine:3
+ script:
+ - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
+ - helm repo add --username <%= username %> --password <%= access_token %> gitlab_qa ${CI_API_V4_URL}/projects/<%= package_project.id %>/packages/helm/stable
+ - helm repo update
+ - helm pull gitlab_qa/<%= package_name %>
+ only:
+ - <%= client_project.default_branch %>
+ tags:
+ - runner-for-<%=client_project.group.name %> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/helm/helm_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/helm/helm_upload_package.yaml.erb
new file mode 100644
index 00000000000..b3e907b50f4
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/helm/helm_upload_package.yaml.erb
@@ -0,0 +1,14 @@
+deploy:
+ image: alpine:3
+ script:
+ - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
+ - apk add curl
+ - helm create <%= package_name %>
+ - cp ./Chart.yaml <%= package_name %>
+ - helm package <%= package_name %>
+ - http_code=$(curl --write-out "%{http_code}" --request POST --form 'chart=@<%= package_name %>-<%= package_version %>.tgz' --user <%= username %>:<%= access_token %> ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts --output /dev/null --silent)
+ - '[ $http_code = "201" ]'
+ only:
+ - <%= package_project.default_branch %>
+ tags:
+ - runner-for-<%= package_project.group.name %> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/build_install.gradle.erb b/qa/qa/fixtures/package_managers/maven/build_install.gradle.erb
new file mode 100644
index 00000000000..303a64ad233
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/build_install.gradle.erb
@@ -0,0 +1,28 @@
+plugins {
+ id 'java'
+ id 'application'
+}
+
+repositories {
+ jcenter()
+ maven {
+ url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven"
+ name "GitLab"
+ credentials(HttpHeaderCredentials) {
+ name = '<%= maven_header_name %>'
+ value = <%= token %>
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+}
+
+dependencies {
+ implementation group: '<%= group_id %>', name: '<%= artifact_id %>', version: '<%= package_version %>'
+ testImplementation 'junit:junit:4.12'
+}
+
+application {
+ mainClassName = 'gradle_maven_app.App'
+} \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb b/qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb
new file mode 100644
index 00000000000..c14e63e11df
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb
@@ -0,0 +1,27 @@
+plugins {
+ id 'java'
+ id 'maven-publish'
+}
+
+publishing {
+ publications {
+ library(MavenPublication) {
+ groupId '<%= group_id %>'
+ artifactId '<%= artifact_id %>'
+ version '<%= package_version %>'
+ from components.java
+ }
+ }
+ repositories {
+ maven {
+ url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven"
+ credentials(HttpHeaderCredentials) {
+ name = "Private-Token"
+ value = "<%= personal_access_token %>"
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb b/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb
new file mode 100644
index 00000000000..20bb5f3964e
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb
@@ -0,0 +1,19 @@
+<project>
+ <groupId><%= group_id %></groupId>
+ <artifactId>maven_client</artifactId>
+ <version>1.0</version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/groups/<%= package_project.group.id %>/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <dependencies>
+ <dependency>
+ <groupId><%= group_id %></groupId>
+ <artifactId><%= artifact_id %></artifactId>
+ <version><%= package_version %></version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb
new file mode 100644
index 00000000000..49873f124cc
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb
@@ -0,0 +1,8 @@
+ build:
+ image: gradle:6.5-jdk11
+ script:
+ - 'gradle build'
+ only:
+ - "<%= client_project.default_branch %>"
+ tags:
+ - "runner-for-<%= client_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb
new file mode 100644
index 00000000000..3f3c7dce03c
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb
@@ -0,0 +1,8 @@
+deploy:
+ image: gradle:6.5-jdk11
+ script:
+ - 'gradle publish'
+ only:
+ - "<%= package_project.default_branch %>"
+ tags:
+ - "runner-for-<%= package_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb
new file mode 100644
index 00000000000..78d6255e9a9
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb
@@ -0,0 +1,8 @@
+install:
+ image: maven:3.6-jdk-11
+ script:
+ - "mvn install -s settings.xml"
+ only:
+ - "<%= client_project.default_branch %>"
+ tags:
+ - "runner-for-<%= client_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb
new file mode 100644
index 00000000000..64a63bf0bd8
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb
@@ -0,0 +1,8 @@
+ deploy:
+ image: maven:3.6-jdk-11
+ script:
+ - 'mvn deploy -s settings.xml'
+ only:
+ - "<%= package_project.default_branch %>"
+ tags:
+ - "runner-for-<%= package_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/package_pom.xml.erb b/qa/qa/fixtures/package_managers/maven/package_pom.xml.erb
new file mode 100644
index 00000000000..5159172a170
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/package_pom.xml.erb
@@ -0,0 +1,22 @@
+ <project>
+ <groupId><%= group_id %></groupId>
+ <artifactId><%= artifact_id %></artifactId>
+ <version><%= package_version %></version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/groups/<%= package_project.group.id %>/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/settings.xml.erb
new file mode 100644
index 00000000000..b670b83cf85
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/settings.xml.erb
@@ -0,0 +1,16 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+<servers>
+ <server>
+ <id><%= package_project.name %></id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name><%= maven_header_name %></name>
+ <value><%= token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+</servers>
+</settings> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb b/qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb
new file mode 100644
index 00000000000..611c232819f
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb
@@ -0,0 +1,16 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id><%= package_project.name %></id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value><%= personal_access_token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb
new file mode 100644
index 00000000000..a396fc98e95
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb
@@ -0,0 +1,21 @@
+image: node:latest
+
+stages:
+ - install
+
+install:
+ stage: install
+ script:
+ - "npm config set @<%= registry_scope %>:registry <%= gitlab_address_with_port %>/api/v4/packages/npm/"
+ - "npm install <%= package.name %>"
+ cache:
+ key: ${CI_BUILD_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "<%= another_project.default_branch %>"
+ tags:
+ - "runner-for-<%= another_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb
new file mode 100644
index 00000000000..8d94d03ef9b
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb
@@ -0,0 +1,31 @@
+image: node:latest
+
+stages:
+ - deploy
+ - install
+
+deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=<%= auth_token %>">.npmrc
+ - npm publish
+ only:
+ - "<%= project.default_branch %>"
+ tags:
+ - "runner-for-<%= project.name %>"
+install:
+ stage: install
+ script:
+ - "npm config set @<%= registry_scope %>:registry <%= gitlab_address_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
+ - "npm install <%= package.name %>"
+ cache:
+ key: ${CI_BUILD_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "<%= project.default_branch %>"
+ tags:
+ - "runner-for-<%= project.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/npm_upload_package_instance.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_upload_package_instance.yaml.erb
new file mode 100644
index 00000000000..13c00cd17c4
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/npm_upload_package_instance.yaml.erb
@@ -0,0 +1,14 @@
+image: node:latest
+
+stages:
+ - deploy
+
+deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=<%= auth_token %>">.npmrc
+ - npm publish
+ only:
+ - "<%= project.default_branch %>"
+ tags:
+ - "runner-for-<%= project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/package_instance.json.erb b/qa/qa/fixtures/package_managers/npm/package_instance.json.erb
new file mode 100644
index 00000000000..46fecf97e2c
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/package_instance.json.erb
@@ -0,0 +1,8 @@
+{
+ "name": "<%= package.name %>",
+ "version": "1.0.0",
+ "description": "Example package for GitLab npm registry",
+ "publishConfig": {
+ "@<%= registry_scope %>:registry": "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/npm/"
+ }
+} \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/package_project.json.erb b/qa/qa/fixtures/package_managers/npm/package_project.json.erb
new file mode 100644
index 00000000000..46fecf97e2c
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/package_project.json.erb
@@ -0,0 +1,8 @@
+{
+ "name": "<%= package.name %>",
+ "version": "1.0.0",
+ "description": "Example package for GitLab npm registry",
+ "publishConfig": {
+ "@<%= registry_scope %>:registry": "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/npm/"
+ }
+} \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/nuget/nuget_install_package.yaml.erb b/qa/qa/fixtures/package_managers/nuget/nuget_install_package.yaml.erb
new file mode 100644
index 00000000000..39b65a55884
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/nuget/nuget_install_package.yaml.erb
@@ -0,0 +1,15 @@
+image: mcr.microsoft.com/dotnet/sdk:5.0
+
+stages:
+ - install
+
+install:
+ stage: install
+ script:
+ - dotnet nuget locals all --clear
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/<%= another_project.group.id %>/-/packages/nuget/index.json" --name gitlab --username <%= auth_token_username %> --password <%= auth_token_password %> --store-password-in-clear-text
+ - "dotnet add otherdotnet.csproj package <%= package.name %> --version 1.0.0"
+ only:
+ - "<%= another_project.default_branch %>"
+ tags:
+ - "runner-for-<%= project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/nuget/nuget_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/nuget/nuget_upload_package.yaml.erb
new file mode 100644
index 00000000000..7c88eb49be0
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/nuget/nuget_upload_package.yaml.erb
@@ -0,0 +1,17 @@
+image: mcr.microsoft.com/dotnet/sdk:5.0
+
+stages:
+ - deploy
+
+deploy:
+ stage: deploy
+ script:
+ - dotnet restore -p:Configuration=Release
+ - dotnet build -c Release
+ - dotnet pack -c Release -p:PackageID=<%= package.name %>
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username <%= auth_token_username %> --password <%= auth_token_password %> --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "<%= project.default_branch %>"'
+ tags:
+ - "runner-for-<%= project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb b/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb
new file mode 100644
index 00000000000..3ea71152801
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb
@@ -0,0 +1,19 @@
+image: python:latest
+stages:
+ - run
+ - install
+
+run:
+ stage: 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 <%= gitlab_address_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
+ tags:
+ - runner-for-<%= project.name %>
+install:
+ stage: install
+ script:
+ - "pip install <%= package.name %> --no-deps --index-url <%= uri.scheme %>://<%= personal_access_token %>:<%= personal_access_token %>@<%= gitlab_host_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host <%= gitlab_host_with_port %>"
+ tags:
+ - runner-for-<%= project.name %> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/pypi/setup.py.erb b/qa/qa/fixtures/package_managers/pypi/setup.py.erb
new file mode 100644
index 00000000000..d365f93cb5e
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/pypi/setup.py.erb
@@ -0,0 +1,16 @@
+import setuptools
+
+setuptools.setup(
+ name="<%= package.name %>",
+ version="0.0.1",
+ author="Example Author",
+ author_email="author@example.com",
+ description="A small example package",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+) \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/rubygems/package.gemspec.erb b/qa/qa/fixtures/package_managers/rubygems/package.gemspec.erb
new file mode 100644
index 00000000000..915deb0335d
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/rubygems/package.gemspec.erb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |s|
+ s.name = '<%= package.name %>'
+ s.authors = ['Tanuki Steve', 'Hal 9000']
+ s.author = 'Tanuki Steve'
+ s.version = '0.0.1'
+ s.date = '2011-09-29'
+ s.summary = 'this is a test package'
+ s.files = ['lib/hello_gem.rb']
+ s.require_paths = ['lib']
+
+ s.description = 'A test package for GitLab.'
+ s.email = 'tanuki@not_real.com'
+ s.homepage = 'https://gitlab.com/ruby-co/my-package'
+ s.license = 'MIT'
+
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
+ 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
+ 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
+ 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
+ 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
+ }
+
+ s.bindir = 'bin'
+ s.platform = Gem::Platform::RUBY
+ s.post_install_message = 'Installed, thank you!'
+ s.rdoc_options = ['--main']
+ s.required_ruby_version = '>= 2.7.0'
+ s.required_rubygems_version = '>= 1.8.11'
+ s.requirements = 'A high powered server or calculator'
+ s.rubygems_version = '1.8.09'
+
+ s.add_dependency 'dependency_1', '~> 1.2.3'
+ s.add_dependency 'dependency_2', '3.0.0'
+ s.add_dependency 'dependency_3', '>= 1.0.0'
+ s.add_dependency 'dependency_4'
+end \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/rubygems/rubygems_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/rubygems/rubygems_upload_package.yaml.erb
new file mode 100644
index 00000000000..29038130f1b
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/rubygems/rubygems_upload_package.yaml.erb
@@ -0,0 +1,15 @@
+image: ruby
+
+test_package:
+ stage: deploy
+ before_script:
+ - mkdir ~/.gem
+ - echo "---" > ~/.gem/credentials
+ - |
+ echo "<%= gitlab_address_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
+ - chmod 0600 ~/.gem/credentials
+ script:
+ - gem build <%= package.name %>
+ - gem push <%= package.name %>-0.0.1.gem --host <%= gitlab_address_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
+ tags:
+ - runner-for-<%= project.name %> \ No newline at end of file
diff --git a/qa/qa/page/component/badges.rb b/qa/qa/page/component/badges.rb
new file mode 100644
index 00000000000..f2c5f809d8d
--- /dev/null
+++ b/qa/qa/page/component/badges.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ class Badges < Page::Base
+ view 'app/assets/javascripts/badges/components/badge_form.vue' do
+ element :badge_name_field
+ element :badge_link_url_field
+ element :badge_image_url_field
+ element :add_badge_button
+ end
+
+ view 'app/assets/javascripts/badges/components/badge_list.vue' do
+ element :badge_list_content
+ element :badge_list_row
+ end
+
+ view 'app/assets/javascripts/badges/components/badge.vue' do
+ element :badge_image_link
+ end
+
+ def fill_name(name)
+ fill_element :badge_name_field, name
+ end
+
+ def fill_link_url(url)
+ fill_element :badge_link_url_field, url
+ end
+
+ def fill_image_url(url)
+ fill_element :badge_image_url_field, url
+ end
+
+ def click_add_badge_button
+ click_element :add_badge_button
+ end
+
+ def has_badge?(badge_name)
+ within_element(:badge_list_content) do
+ has_element?(:badge_list_row, badge_name: badge_name)
+ end
+ end
+
+ def has_visible_badge_image_link?(link_url)
+ within_element(:badge_list_content) do
+ has_element?(:badge_image_link, link_url: link_url)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/blob_content.rb b/qa/qa/page/component/blob_content.rb
index 4d36a6dcefe..ce743b24dda 100644
--- a/qa/qa/page/component/blob_content.rb
+++ b/qa/qa/page/component/blob_content.rb
@@ -22,6 +22,10 @@ module QA
element :copy_contents_button
end
+ base.view 'app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue' do
+ element :blob_viewer_file_content
+ end
+
base.view 'app/views/projects/blob/_header_content.html.haml' do
element :file_name_content
end
diff --git a/qa/qa/page/component/design_management.rb b/qa/qa/page/component/design_management.rb
index 1f5620e30c7..73ba5713bda 100644
--- a/qa/qa/page/component/design_management.rb
+++ b/qa/qa/page/component/design_management.rb
@@ -55,7 +55,7 @@ module QA
# wait for the "Save comment" button to disappear
saved = has_no_element?(:save_comment_button)
- raise ExpectationNotMet, %q(There was a problem while adding the annotation) unless saved
+ raise RSpec::Expectations::ExpectationNotMetError, %q(There was a problem while adding the annotation) unless saved
end
def add_design(design_file_path)
diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb
index ca6862ccb02..7c536ff651b 100644
--- a/qa/qa/page/component/invite_members_modal.rb
+++ b/qa/qa/page/component/invite_members_modal.rb
@@ -9,7 +9,7 @@ module QA
def self.included(base)
super
- base.view 'app/assets/javascripts/invite_members/components/invite_members_modal.vue' do
+ base.view 'app/assets/javascripts/invite_members/components/invite_modal_base.vue' do
element :invite_button
element :access_level_dropdown
element :invite_members_modal_content
@@ -44,9 +44,9 @@ module QA
open_invite_members_modal
within_element(:invite_members_modal_content) do
- fill_element :members_token_select_input, username
+ fill_element(:members_token_select_input, username)
Support::WaitForRequests.wait_for_requests
- click_button username
+ click_button(username, match: :prefer_exact)
set_access_level(access_level)
end
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 4a81230499c..921647eb4cc 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -40,7 +40,7 @@ module QA
end
base.view 'app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue' do
- element :milestone_link, 'data-qa-selector="`${issuableAttribute}_link`"' # rubocop:disable QA/ElementWithPattern
+ element :milestone_link, 'data-qa-selector="`${formatIssuableAttribute.snake}_link`"' # rubocop:disable QA/ElementWithPattern
end
base.view 'app/assets/javascripts/sidebar/components/sidebar_editable_item.vue' do
diff --git a/qa/qa/page/component/members_filter.rb b/qa/qa/page/component/members_filter.rb
new file mode 100644
index 00000000000..ac07fe7e9fa
--- /dev/null
+++ b/qa/qa/page/component/members_filter.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module MembersFilter
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view 'app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue' do
+ element :members_filtered_search_bar_content
+ end
+ end
+
+ def search_member(username)
+ # TODO: Update the two actions below to use direct qa selectors once this is implemented:
+ # https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1688
+ find_element(:members_filtered_search_bar_content).find('input').set(username)
+ find('.gl-search-box-by-click-search-button').click
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/namespace_select.rb b/qa/qa/page/component/namespace_select.rb
new file mode 100644
index 00000000000..924e1af876c
--- /dev/null
+++ b/qa/qa/page/component/namespace_select.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module NamespaceSelect
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
+ element :namespaces_list
+ element :namespaces_list_groups
+ element :namespaces_list_item
+ end
+ end
+
+ def select_namespace(item)
+ click_element :namespaces_list
+
+ within_element(:namespaces_list) do
+ find_element(:namespaces_list_item, text: item).click
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index bc73fe0c3ab..8f504b784b2 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -38,7 +38,7 @@ module QA
def click_submit
click_element(:wiki_submit_button)
- wait_until(reload: false) do
+ QA::Support::Retrier.retry_on_exception do
has_no_element?(:wiki_title_textbox)
end
end
@@ -48,15 +48,8 @@ module QA
Page::Modal::DeleteWiki.perform(&:confirm_deletion)
end
- def use_new_editor(toggle)
- # Update once the feature is released, see https://gitlab.com/gitlab-org/gitlab/-/issues/345398
- if toggle
- click_element(:editing_mode_button, mode: 'Edit rich text')
- else
- within_element(:try_new_editor_container) do
- click_button('Use the new editor')
- end
- end
+ def use_new_editor
+ click_element(:editing_mode_button, mode: 'Edit rich text')
wait_until(reload: false) do
has_element?(:content_editor_container)
diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb
index ccc901932f4..c80bdadb11f 100644
--- a/qa/qa/page/group/members.rb
+++ b/qa/qa/page/group/members.rb
@@ -6,6 +6,7 @@ module QA
class Members < Page::Base
include Page::Component::InviteMembersModal
include Page::Component::UsersSelect
+ include Page::Component::MembersFilter
view 'app/assets/javascripts/members/components/modals/remove_member_modal.vue' do
element :remove_member_modal_content
@@ -31,6 +32,8 @@ module QA
end
def update_access_level(username, access_level)
+ search_member(username)
+
within_element(:member_row, text: username) do
click_element :access_level_dropdown
click_element :access_level_link, text: access_level
diff --git a/qa/qa/page/group/settings/general.rb b/qa/qa/page/group/settings/general.rb
index 2e7ab131225..1877065f478 100644
--- a/qa/qa/page/group/settings/general.rb
+++ b/qa/qa/page/group/settings/general.rb
@@ -7,6 +7,8 @@ module QA
class General < QA::Page::Base
include ::QA::Page::Settings::Common
include Page::Component::VisibilitySetting
+ include Page::Component::ConfirmModal
+ include Page::Component::NamespaceSelect
view 'app/views/groups/edit.html.haml' do
element :permission_lfs_2fa_content
@@ -38,16 +40,6 @@ module QA
element :project_creation_level_dropdown
end
- view 'app/views/groups/settings/_transfer.html.haml' do
- element :select_group_dropdown
- element :transfer_group_button
- end
-
- view 'app/helpers/dropdowns_helper.rb' do
- element :dropdown_input_field
- element :dropdown_list_content
- end
-
def set_group_name(name)
find_element(:group_name_field).send_keys([:command, 'a'], :backspace)
find_element(:group_name_field).set name
@@ -111,17 +103,14 @@ module QA
click_element(:save_permissions_changes_button)
end
- def transfer_group(target_group)
+ def transfer_group(target_group, source_group)
expand_content :advanced_settings_content
- click_element :select_group_dropdown
- fill_element(:dropdown_input_field, target_group)
-
- within_element(:dropdown_list_content) do
- click_on target_group
- end
+ select_namespace(target_group)
+ click_element(:transfer_button)
- click_element :transfer_group_button
+ fill_confirmation_text(source_group)
+ confirm_transfer
end
end
end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index f004107d7bd..a5bd37be287 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -157,6 +157,7 @@ module QA
end
def redirect_to_login_page(address)
+ Menu.perform(&:sign_out_if_signed_in)
desired_host = URI(Runtime::Scenario.send("#{address}_address")).host
Runtime::Browser.visit(address, Page::Main::Login) if desired_host != current_host
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index f8d063ac6bd..d76dfb295a0 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -83,10 +83,18 @@ module QA
element :merge_immediately_menu_item
end
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue' do
+ element :head_mismatch_content
+ end
+
view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
element :squash_checkbox
end
+ view 'app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue' do
+ element :mr_widget_content
+ end
+
view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do
element :apply_suggestion_dropdown
element :commit_message_field
@@ -255,7 +263,8 @@ module QA
# status as unmerged, the test will fail.
# Revisit after merge page re-architect is done https://gitlab.com/groups/gitlab-org/-/epics/5598
# To remove page refresh logic if possible
- retry_until(max_attempts: 3, reload: true) do
+ # We don't raise on failure because this method is used as a predicate matcher
+ retry_until(max_attempts: 3, reload: true, raise_on_failure: false) do
has_element?(:merged_status_content, text: 'The changes were merged into', wait: 20)
end
end
@@ -269,13 +278,29 @@ module QA
has_element?(:merge_button, disabled: false)
end
- # Waits up 60 seconds and raises an error if unable to merge
- def wait_until_ready_to_merge
- has_element?(:merge_button)
+ # Waits up 60 seconds and raises an error if unable to merge.
+ #
+ # If a state is encountered in which a user would typically refresh the page, this will refresh the page and
+ # then check again if it's ready to merge. For example, it will refresh if a new change was pushed and the page
+ # needs to be refreshed to show the change.
+ #
+ # @param [Boolean] transient_test true if the current test is a transient test (default: false)
+ def wait_until_ready_to_merge(transient_test: false)
+ wait_until do
+ has_element?(:merge_button)
- # The merge button is enabled via JS
- wait_until(reload: false) do
- !find_element(:merge_button).disabled?
+ break true unless find_element(:merge_button).disabled?
+
+ # If the widget shows "Merge blocked: new changes were just added" we can refresh the page and check again
+ next false if has_element?(:head_mismatch_content)
+
+ # Stop waiting if we're in a transient test. By this point we're in an unexpected state and should let the
+ # test fail so we can investigate. If we're not in a transient test we keep trying until we reach timeout.
+ next true unless transient_test
+
+ QA::Runtime::Logger.debug("MR widget text: #{mr_widget_text}")
+
+ false
end
end
@@ -385,6 +410,10 @@ module QA
def cancel_auto_merge!
click_element(:cancel_auto_merge_button)
end
+
+ def mr_widget_text
+ find_element(:mr_widget_content).text
+ end
end
end
end
diff --git a/qa/qa/page/project/members.rb b/qa/qa/page/project/members.rb
index 1102abd6646..30748ed920b 100644
--- a/qa/qa/page/project/members.rb
+++ b/qa/qa/page/project/members.rb
@@ -5,6 +5,7 @@ module QA
module Project
class Members < Page::Base
include QA::Page::Component::InviteMembersModal
+ include QA::Page::Component::MembersFilter
view 'app/assets/javascripts/members/components/members_tabs.vue' do
element :groups_list_tab
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 42baf1f3f87..e061bc52abc 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -13,7 +13,6 @@ module QA
view 'app/views/projects/_new_project_fields.html.haml' do
element :initialize_with_readme_checkbox
- element :initialize_with_sast_checkbox
element :project_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
element :project_path, 'text_field :path' # rubocop:disable QA/ElementWithPattern
element :project_description, 'text_area :description' # rubocop:disable QA/ElementWithPattern
@@ -21,6 +20,10 @@ module QA
element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/projects/_new_project_initialize_with_sast.html.haml' do
+ element :initialize_with_sast_checkbox
+ end
+
view 'app/views/projects/project_templates/_template.html.haml' do
element :use_template_button
element :template_option_row
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index f7c5d149593..d088ba76bc0 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -26,11 +26,15 @@ module QA
end
def wait_for_latest_pipeline_succeeded
- wait_for_latest_pipeline_status { has_text?('passed') }
+ wait_for_latest_pipeline_status { has_selector?(".ci-status-icon-success") }
end
def wait_for_latest_pipeline_completed
- wait_for_latest_pipeline_status { has_text?('passed') || has_text?('failed') }
+ wait_for_latest_pipeline_status { has_selector?(".ci-status-icon-success") || has_selector?(".ci-status-icon-failed") }
+ end
+
+ def wait_for_latest_pipeline_skipped
+ wait_for_latest_pipeline_status { has_text?('skipped') }
end
def wait_for_latest_pipeline_status
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 83a49ae6361..6f4757a34e8 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -18,7 +18,7 @@ module QA
view 'app/assets/javascripts/pipelines/components/graph/job_item.vue' do
element :job_item_container
element :job_link
- element :action_button
+ element :job_action_button
end
view 'app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue' do
@@ -38,6 +38,11 @@ module QA
element :pipeline_badges
end
+ view 'app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue' do
+ element :job_dropdown_container
+ element :jobs_dropdown_menu
+ end
+
def running?(wait: 0)
within_element(:pipeline_header) do
page.has_content?('running', wait: wait)
@@ -47,7 +52,7 @@ module QA
def has_build?(name, status: :success, wait: nil)
if status
within_element(:job_item_container, text: name) do
- has_selector?(".ci-status-icon-#{status}", { wait: wait }.compact)
+ has_selector?(".ci-status-icon-#{status}", **{ wait: wait }.compact)
end
else
has_element?(:job_item_container, text: name)
@@ -110,8 +115,22 @@ module QA
end
def click_job_action(job_name)
+ wait_for_requests
+
within_element(:job_item_container, text: job_name) do
- click_element(:action_button)
+ click_element(:job_action_button)
+ end
+ end
+
+ def click_job_dropdown(job_dropdown_name)
+ click_element(:job_dropdown_container, text: job_dropdown_name)
+ end
+
+ def has_skipped_job_in_group?
+ within_element(:jobs_dropdown_menu) do
+ all_elements(:job_item_container, minimum: 1).all? do
+ has_selector?('.ci-status-icon-skipped')
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index da1f16f4cfc..525210a08f6 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -6,18 +6,13 @@ module QA
module Settings
class Advanced < Page::Base
include Component::ConfirmModal
+ include Component::NamespaceSelect
view 'app/views/projects/edit.html.haml' do
element :project_path_field
element :change_path_button
end
- view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
- element :namespaces_list
- element :namespaces_list_groups
- element :namespaces_list_item
- end
-
view 'app/views/projects/settings/_archive.html.haml' do
element :archive_project_link
element :unarchive_project_link
@@ -43,14 +38,6 @@ module QA
click_element :change_path_button
end
- def select_namespace(item)
- click_element :namespaces_list
-
- within_element(:namespaces_list) do
- find_element(:namespaces_list_item, text: item).click
- end
- end
-
def transfer_project!(project_name, namespace)
QA::Runtime::Logger.info "Transferring project: #{project_name} to namespace: #{namespace}"
diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb
index 5efcb7bf23c..52ed630ac66 100644
--- a/qa/qa/page/project/settings/main.rb
+++ b/qa/qa/page/project/settings/main.rb
@@ -9,11 +9,13 @@ module QA
include Component::Select2
include SubMenus::Project
include Component::Breadcrumbs
+ include Layout::Flash
view 'app/views/projects/edit.html.haml' do
element :advanced_settings_content
element :merge_request_settings_content
element :visibility_features_permissions_content
+ element :badges_settings_content
end
view 'app/views/projects/settings/_general.html.haml' do
@@ -51,6 +53,12 @@ module QA
VisibilityFeaturesPermissions.perform(&block)
end
end
+
+ def expand_badges_settings(&block)
+ expand_content(:badges_settings_content) do
+ Component::Badges.perform(&block)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 8074b6f833b..4c9df2716e2 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -39,6 +39,8 @@ module QA
element :forked_from_link
element :project_name_content
element :project_id_content
+ element :project_badges_content
+ element :badge_image_link
end
view 'app/views/projects/_files.html.haml' do
@@ -179,6 +181,12 @@ module QA
has_css?('.tree-holder')
end
end
+
+ def has_visible_badge_image_link?(link_url)
+ within_element(:project_badges_content) do
+ has_element?(:badge_image_link, link_url: link_url)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index 9c0a3ab691c..403c919c6e5 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -68,7 +68,7 @@ module QA
element :delete_button
end
- view 'app/views/shared/_confirm_fork_modal.html.haml' do
+ view 'app/assets/javascripts/vue_shared/components/confirm_fork_modal.vue' do
element :fork_project_button
element :confirm_fork_modal
end
diff --git a/qa/qa/page/trials/new.rb b/qa/qa/page/trials/new.rb
index 6e9d7fce688..cd3b145a89e 100644
--- a/qa/qa/page/trials/new.rb
+++ b/qa/qa/page/trials/new.rb
@@ -12,6 +12,7 @@ module QA
select :number_of_employees
text_field :telephone_number
select :country
+ select :state, id: 'state'
button :continue
end
end
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index 4c77c515cfd..1958884916c 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -7,11 +7,11 @@ module QA
module Resource
module ApiFabricator
include Capybara::DSL
+ include Support::API
include Errors
- attr_reader :api_resource, :api_response
attr_writer :api_client
- attr_accessor :api_user
+ attr_accessor :api_user, :api_resource, :api_response
def api_support?
respond_to?(:api_get_path) &&
@@ -48,9 +48,6 @@ module QA
end
end
- include Support::API
- attr_writer :api_resource, :api_response
-
def api_put(body = api_put_body)
response = put(
Runtime::API::Request.new(api_client, api_put_path).url,
@@ -67,6 +64,16 @@ module QA
@api_fabrication_http_method ||= :post
end
+ # Checks if a resource already exists
+ #
+ # @return [Boolean] true if the resource returns HTTP status code 200
+ def exists?
+ request = Runtime::API::Request.new(api_client, api_get_path)
+ response = get(request.url)
+
+ response.code == HTTP_STATUS_OK
+ end
+
private
def resource_web_url(resource)
diff --git a/qa/qa/resource/badge_base.rb b/qa/qa/resource/badge_base.rb
new file mode 100644
index 00000000000..5bb7eb98d4e
--- /dev/null
+++ b/qa/qa/resource/badge_base.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class BadgeBase < Base
+ attributes :id,
+ :name,
+ :link_url,
+ :image_url
+
+ def initialize
+ @name = "qa-badge-#{SecureRandom.hex(8)}"
+ end
+
+ def fabricate!
+ Page::Component::Badges.perform do |badges|
+ badges.fill_name(name)
+ badges.fill_link_url(link_url)
+ badges.fill_image_url(image_url)
+ badges.click_add_badge_button
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index 0112e766cf0..fc7f8445d4e 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -8,6 +8,7 @@ module QA
class Base
include ApiFabricator
extend Capybara::DSL
+ using Rainbow
NoValueError = Class.new(RuntimeError)
@@ -31,7 +32,7 @@ module QA
parents = options.fetch(:parents) { [] }
do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
- log_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
+ log_and_record_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
current_url
end
@@ -47,7 +48,7 @@ module QA
resource.eager_load_api_client!
do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
- log_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
+ log_and_record_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
end
end
@@ -59,7 +60,7 @@ module QA
resource.eager_load_api_client!
do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
- log_fabrication(:api, resource, parents, args) { resource.remove_via_api! }
+ log_and_record_fabrication(:api, resource, parents, args) { resource.remove_via_api! }
end
end
@@ -71,36 +72,17 @@ module QA
resource_web_url = yield
resource.web_url = resource_web_url
- QA::Tools::TestResourceDataProcessor.collect(resource, resource_identifier(resource))
-
resource
end
- def resource_identifier(resource)
- if resource.respond_to?(:username) && resource.username
- "with username '#{resource.username}'"
- elsif resource.respond_to?(:full_path) && resource.full_path
- "with full_path '#{resource.full_path}'"
- elsif resource.respond_to?(:name) && resource.name
- "with name '#{resource.name}'"
- elsif resource.respond_to?(:id) && resource.id
- "with id '#{resource.id}'"
- elsif resource.respond_to?(:iid) && resource.iid
- "with iid '#{resource.iid}'"
- end
- rescue QA::Resource::Base::NoValueError
- nil
- end
-
- def log_fabrication(method, resource, parents, args)
+ def log_and_record_fabrication(fabrication_method, resource, parents, args)
start = Time.now
Support::FabricationTracker.start_fabrication
result = yield.tap do
fabrication_time = Time.now - start
-
fabrication_http_method = if resource.api_fabrication_http_method == :get
- if self.include?(Reusable)
+ if include?(Reusable)
"Retrieved for reuse"
else
"Retrieved"
@@ -109,16 +91,23 @@ module QA
"Built"
end
- Support::FabricationTracker.save_fabrication(:"#{method}_fabrication", fabrication_time)
+ Support::FabricationTracker.save_fabrication(:"#{fabrication_method}_fabrication", fabrication_time)
+ Tools::TestResourceDataProcessor.collect(
+ resource: resource,
+ info: resource.identifier,
+ fabrication_method: fabrication_method,
+ fabrication_time: fabrication_time
+ )
+
Runtime::Logger.debug do
msg = ["==#{'=' * parents.size}>"]
- msg << "#{fabrication_http_method} a #{name}"
- msg << resource_identifier(resource) if resource_identifier(resource)
+ msg << "#{fabrication_http_method} a #{Rainbow(name).black.bg(:white)}"
+ msg << resource.identifier
msg << "as a dependency of #{parents.last}" if parents.any?
- msg << "via #{method}"
+ msg << "via #{fabrication_method}"
msg << "in #{fabrication_time} seconds"
- msg.join(' ')
+ msg.compact.join(' ')
end
end
Support::FabricationTracker.finish_fabrication
@@ -172,7 +161,7 @@ module QA
end
def visit!(skip_resp_code_check: false)
- Runtime::Logger.debug(%(Visiting #{self.class.name} at "#{web_url}"))
+ Runtime::Logger.debug("Visiting #{Rainbow(self.class.name).black.bg(:white)} at #{web_url}")
# Just in case an async action is not yet complete
Support::WaitForRequests.wait_for_requests(skip_resp_code_check: skip_resp_code_check)
@@ -209,6 +198,35 @@ module QA
JSON.pretty_generate(comparable)
end
+ def diff(other)
+ return if self == other
+
+ diff_values = self.comparable.to_a - other.comparable.to_a
+ diff_values.to_h
+ end
+
+ def identifier
+ if respond_to?(:username) && username
+ "with username '#{username}'"
+ elsif respond_to?(:full_path) && full_path
+ "with full_path '#{full_path}'"
+ elsif respond_to?(:name) && name
+ "with name '#{name}'"
+ elsif respond_to?(:id) && id
+ "with id '#{id}'"
+ elsif respond_to?(:iid) && iid
+ "with iid '#{iid}'"
+ end
+ rescue QA::Resource::Base::NoValueError
+ nil
+ end
+
+ def remove_via_api!
+ super
+
+ Runtime::Logger.debug(["Removed a #{self.class.name}", identifier].compact.join(' '))
+ end
+
protected
# Custom resource comparison logic using resource attributes from api_resource
diff --git a/qa/qa/resource/clusters/agent.rb b/qa/qa/resource/clusters/agent.rb
index ee5a292b9b3..b190634f357 100644
--- a/qa/qa/resource/clusters/agent.rb
+++ b/qa/qa/resource/clusters/agent.rb
@@ -17,7 +17,6 @@ module QA
end
def fabricate!
- puts 'TODO: FABRICATE VIA UI'
end
def resource_web_url(resource)
diff --git a/qa/qa/resource/clusters/agent_token.rb b/qa/qa/resource/clusters/agent_token.rb
index 6d803b94564..c1cf5c2f37b 100644
--- a/qa/qa/resource/clusters/agent_token.rb
+++ b/qa/qa/resource/clusters/agent_token.rb
@@ -11,7 +11,6 @@ module QA
end
def fabricate!
- puts 'TODO: FABRICATE VIA UI'
end
def resource_web_url(resource)
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index d0313670e8b..d60b90b534f 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -31,6 +31,8 @@ module QA
end
end
+ delegate :path_with_namespace, to: :project
+
def fabricate!
populate(:upstream, :user)
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index a325d96ccc2..dee63f9699c 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -3,12 +3,16 @@
module QA
module Resource
class Group < GroupBase
- attributes :require_two_factor_authentication, :description
+ attributes :require_two_factor_authentication, :description, :path
attribute :full_path do
determine_full_path
end
+ attribute :name do
+ @name || path
+ end
+
attribute :sandbox do
Sandbox.fabricate_via_api! do |sandbox|
sandbox.api_client = api_client
@@ -50,12 +54,6 @@ 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
@@ -66,7 +64,7 @@ module QA
{
parent_id: sandbox.id,
path: path,
- name: path,
+ name: name || path,
visibility: 'public',
require_two_factor_authentication: @require_two_factor_authentication,
avatar: avatar
diff --git a/qa/qa/resource/group_badge.rb b/qa/qa/resource/group_badge.rb
index 3719b502b93..0c176bd5fbc 100644
--- a/qa/qa/resource/group_badge.rb
+++ b/qa/qa/resource/group_badge.rb
@@ -2,12 +2,8 @@
module QA
module Resource
- class GroupBadge < Base
- attributes :id,
- :name,
- :link_url,
- :image_url,
- :group
+ class GroupBadge < BadgeBase
+ attribute :group
# API get path
#
diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb
index 9f492a046db..05b41a4b4f6 100644
--- a/qa/qa/resource/group_base.rb
+++ b/qa/qa/resource/group_base.rb
@@ -7,6 +7,8 @@ module QA
class GroupBase < Base
include Members
+ MAX_NAME_LENGTH = 255
+
attr_accessor :path, :avatar
attributes :id,
diff --git a/qa/qa/resource/group_milestone.rb b/qa/qa/resource/group_milestone.rb
index b9ec53e929c..c208270658e 100644
--- a/qa/qa/resource/group_milestone.rb
+++ b/qa/qa/resource/group_milestone.rb
@@ -14,7 +14,7 @@ module QA
attribute :group do
Group.fabricate_via_api! do |resource|
- resource.name = 'group-with-milestone'
+ resource.name = "group-with-milestone-#{SecureRandom.hex(4)}"
end
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 0750ea49224..c5b72eebe03 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -17,6 +17,7 @@ module QA
attributes :id,
:name,
+ :path,
:add_name_uuid,
:description,
:runners_token,
diff --git a/qa/qa/resource/project_badge.rb b/qa/qa/resource/project_badge.rb
new file mode 100644
index 00000000000..e036999117e
--- /dev/null
+++ b/qa/qa/resource/project_badge.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ProjectBadge < BadgeBase
+ def initialize
+ super
+
+ @link_url = "#{Runtime::Scenario.gitlab_address}/%{project_path}"
+ @image_url = "#{Runtime::Scenario.gitlab_address}/%{project_path}/badges/%{default_branch}/pipeline.svg"
+ end
+
+ def fabricate!
+ Page::Project::Menu.perform(&:go_to_general_settings)
+ Page::Project::Settings::Main.perform(&:expand_badges_settings)
+
+ super
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project_web_hook.rb b/qa/qa/resource/project_web_hook.rb
new file mode 100644
index 00000000000..8b806c42030
--- /dev/null
+++ b/qa/qa/resource/project_web_hook.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ProjectWebHook < Base
+ EVENT_TRIGGERS = %i[
+ issues
+ job
+ merge_requests
+ note
+ pipeline
+ push
+ tag_push
+ wiki_page
+ confidential_issues
+ confidential_note
+ ].freeze
+
+ attr_accessor :url, :enable_ssl, :id
+
+ attribute :project do
+ Project.fabricate_via_api! do |resource|
+ resource.name = 'project-with-webhooks'
+ end
+ end
+
+ EVENT_TRIGGERS.each do |trigger|
+ attribute "#{trigger}_events".to_sym do
+ false
+ end
+ end
+
+ def initialize
+ @id = nil
+ @enable_ssl = false
+ @url = nil
+ end
+
+ def resource_web_url(resource)
+ "/project/#{project.name}/~/hooks/##{resource[:id]}/edit"
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/hooks"
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def api_post_body
+ body = {
+ id: project.id,
+ url: url,
+ enable_ssl_verification: enable_ssl
+ }
+ EVENT_TRIGGERS.each_with_object(body) do |trigger, memo|
+ attr = "#{trigger}_events"
+ memo[attr.to_sym] = send(attr)
+ memo
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb
index 7db6450acf8..062d4e9f3d8 100644
--- a/qa/qa/resource/protected_branch.rb
+++ b/qa/qa/resource/protected_branch.rb
@@ -61,6 +61,8 @@ module QA
end
def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
populate_new_branch_if_required
super
@@ -75,7 +77,11 @@ module QA
end
def api_delete_path
- "/projects/#{project.id}/protected_branches/#{branch_name}"
+ api_get_path
+ end
+
+ def api_put_path
+ api_get_path
end
def api_post_path
@@ -107,6 +113,16 @@ module QA
# this particular resource does not expose a web_url property
end
+ def set_require_code_owner_approval(require = true)
+ response = patch(Runtime::API::Request.new(api_client, api_put_path).url, { code_owner_approval_required: require })
+ return if response.code == HTTP_STATUS_OK
+
+ raise(
+ ResourceUpdateFailedError,
+ "Could not update code_owner_approval_required to #{require}. Request returned (#{response.code}): `#{response}`."
+ )
+ end
+
class Roles
NO_ONE = { description: 'No one', access_level: 0 }.freeze
DEVS_AND_MAINTAINERS = { description: 'Developers + Maintainers', access_level: 30 }.freeze
diff --git a/qa/qa/resource/reusable.rb b/qa/qa/resource/reusable.rb
index 24b0a1f6bce..6a9d0392ba2 100644
--- a/qa/qa/resource/reusable.rb
+++ b/qa/qa/resource/reusable.rb
@@ -4,8 +4,13 @@ module QA
module Resource
#
# This module includes methods that allow resource classes to be reused safely. It should be prepended to a new
- # reusable version of an existing resource class. See Resource::Project and ReusableResource::Project for an example
+ # reusable version of an existing resource class. See Resource::Project and ReusableResource::Project for an example.
+ # Reusable resource classes must also be registered with a resource collection that will manage cleanup.
#
+ # @example Register a resource class with a collection
+ # QA::Resource::ReusableCollection.register_resource_classes do |collection|
+ # QA::Resource::ReusableProject.register(collection)
+ # end
module Reusable
attr_accessor :reuse,
:reuse_as
@@ -16,7 +21,7 @@ module QA
base.extend(ClassMethods)
end
- # Gets an existing resource if it exists and the parameters of the new specification of the resource are valid.
+ # Gets an existing resource if it exists and the specified attributes of the resource are valid.
# Creates a new instance of the resource if it does not exist.
#
# @return [String] The URL of the resource.
@@ -27,33 +32,128 @@ module QA
rescue Errors::ResourceNotFoundError
super
ensure
- self.class.resources[reuse_as] = self
+ self.class.resources[reuse_as] ||= {
+ tests: Set.new,
+ resource: self
+ }
+
+ self.class.resources[reuse_as][:attributes] ||= all_attributes.each_with_object({}) do |attribute_name, attributes|
+ attributes[attribute_name] = instance_variable_get("@#{attribute_name}")
+ end
+ self.class.resources[reuse_as][:tests] << Runtime::Example.location
end
- # Including classes must confirm that the resource can be reused as defined. For example, a project can't be
- # fabricated with a unique name.
+ # Overrides remove_via_api! to log a debug message stating that removal will happen after the suite completes.
#
# @return [nil]
+ def remove_via_api!
+ QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite")
+ end
+
+ # Object comparison
+ #
+ # @param [QA::Resource::Base] other
+ # @return [Boolean]
+ def ==(other)
+ self.class <= other.class && comparable == other.comparable
+ end
+
+ # Confirms that reuse of the resource did not change it in a way that breaks later reuse.
+ # For example, this should fail if a reusable resource should have a specific name, but the name has been changed.
+ def validate_reuse
+ QA::Runtime::Logger.debug(["Validating a #{self.class.name} that was reused as #{reuse_as}", identifier].compact.join(' '))
+
+ fresh_resource = reference_resource
+ diff = reuse_validation_diff(fresh_resource)
+
+ if diff.present?
+ raise ResourceReuseError, <<~ERROR
+ The reused #{self.class.name} resource does not have the attributes expected.
+ The following change was found: #{diff}"
+ The resource's web_url is #{web_url}.
+ It was used in these tests: #{self.class.resources[reuse_as][:tests].to_a.join(', ')}
+ ERROR
+ end
+
+ ensure
+ fresh_resource.remove_via_api!
+ end
+
+ private
+
+ # Creates a new resource that can be compared to a reused resource, using the post body of the original.
+ # Must be implemented by classes that include this module.
+ def reference_resource
+ return super if defined?(super)
+
+ raise NotImplementedError
+ end
+
+ # Confirms that the resource attributes specified in its fabricate_via_api! block will allow it to be reused.
+ #
+ # @return [nil] returns nil unless an error is raised
def validate_reuse_preconditions
+ return unless self.class.resources.key?(reuse_as)
+
+ attributes = unique_identifiers.each_with_object({ proposed: {}, existing: {} }) do |id, attrs|
+ proposed = public_send(id)
+ existing = self.class.resources[reuse_as][:resource].public_send(id)
+
+ next if proposed == existing
+
+ attrs[:proposed][id] = proposed
+ attrs[:existing][id] = existing
+ end
+
+ unless attributes[:proposed].empty? && attributes[:existing].empty?
+ raise ResourceReuseError, "Reusable resources must use the same unique identifier(s). " \
+ "The #{self.class.name} to be reused as :#{reuse_as} has the identifier(s) #{attributes[:proposed]} " \
+ "but it should have #{attributes[:existing]}"
+ end
+ end
+
+ # Compares the attributes of the current reused resource with a reference instance.
+ #
+ # @return [Hash] any differences between the resources.
+ def reuse_validation_diff(other)
+ original, reference = prepare_reuse_validation_diff(other)
+
+ return if original == reference
+
+ diff_values = original.to_a - reference.to_a
+ diff_values.to_h
+ end
+
+ # Compares the current reusable resource to a reference instance, ignoring identifying unique attributes that
+ # had to be changed.
+ #
+ # @return [Hash, Hash] the current and reference resource attributes, respectively.
+ def prepare_reuse_validation_diff(other)
+ original = self.reload!.comparable
+ reference = other.reload!.comparable
+ unique_identifiers.each { |id| reference[id] = original[id] }
+ [original, reference]
+ end
+
+ # The attributes of the resource that should be the same whenever a test wants to reuse a resource. Must be
+ # implemented by classes that include this module.
+ #
+ # @return [Array<Symbol>] the attribute names.
+ def unique_identifiers
return super if defined?(super)
raise NotImplementedError
end
module ClassMethods
- # Removes all created resources of this type.
- #
- # @return [Hash<Symbol, QA::Resource>] the resources that were to be removed.
- def remove_all_via_api!
- resources.each do |reuse_as, resource|
- QA::Runtime::Logger.debug("#{self.name} - removing #{reuse_as}")
- resource.method(:remove_via_api!).super_method.call
- end
+ # Includes the resources created/reused by this class in the specified collection
+ def register(collection)
+ collection[self.name] = resources
end
- # The resources created by this resource class.
+ # The resources created/reused by this resource class.
#
- # @return [Hash<Symbol, QA::Resource>] the resources created by this resource class.
+ # @return [Hash<Symbol, Hash>] the resources created/reused by this resource class.
def resources
@resources ||= {}
end
diff --git a/qa/qa/resource/reusable_collection.rb b/qa/qa/resource/reusable_collection.rb
new file mode 100644
index 00000000000..1168b0091fc
--- /dev/null
+++ b/qa/qa/resource/reusable_collection.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'singleton'
+
+module QA
+ module Resource
+ #
+ # This singleton class collects all reusable resources used by tests and allows operations to be performed on them
+ # all. For example, verifying their state after tests have run and might have changed them.
+ #
+ class ReusableCollection
+ include Singleton
+
+ attr_accessor :resource_classes
+
+ def initialize
+ @resource_classes = {}
+ end
+
+ # Yields each resource in the collection.
+ #
+ # @yieldparam [Symbol] reuse_as the name that identifies the resource instance.
+ # @yieldparam [QA::Resource] reuse_instance the resource.
+ def each_resource
+ resource_classes.each_value do |reuse_instances|
+ reuse_instances.each do |reuse_as, reuse_instance|
+ yield reuse_as, reuse_instance[:resource]
+ end
+ end
+ end
+
+ class << self
+ # Removes all created resources that are included in the collection.
+ def remove_all_via_api!
+ instance.each_resource do |reuse_as, resource|
+ next QA::Runtime::Logger.debug("#{resource.class.name} reused as :#{reuse_as} has already been removed.") unless resource.exists?
+
+ resource.method(:remove_via_api!).super_method.call
+ end
+ end
+
+ # Validates the reuse of each resource as defined by the resource class of each resource in the collection.
+ def validate_resource_reuse
+ instance.each_resource { |_, resource| resource.validate_reuse }
+ end
+
+ # Yields the collection of resources to allow resource classes to register themselves with the collection.
+ #
+ # @yieldparam [Hash] resource_classes the resource classes in the collection.
+ def register_resource_classes
+ yield instance.resource_classes
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/reusable_group.rb b/qa/qa/resource/reusable_group.rb
index a4bd799e85c..b75cb0517bf 100644
--- a/qa/qa/resource/reusable_group.rb
+++ b/qa/qa/resource/reusable_group.rb
@@ -8,46 +8,35 @@ module QA
def initialize
super
- @path = "reusable_group"
+ @name = @path = 'reusable_group'
@description = "QA reusable group"
@reuse_as = :default_group
end
- # Confirms that the group can be reused
- #
- # @return [nil] returns nil unless an error is raised
- def validate_reuse_preconditions
- unless reused_path_unique?
- raise ResourceReuseError,
- "Reusable groups must have the same name. The group reused as #{reuse_as} has the path '#{path}' but it should be '#{self.class.resources[reuse_as].path}'"
- end
- end
+ private
- # Confirms that reuse of the resource did not change it in a way that breaks later reuse. This raises an error if
- # the current group path doesn't match the original path.
- def validate_reuse
- reload!
-
- if api_resource[:path] != @path
- raise ResourceReuseError, "The group now has the path '#{api_resource[:path]}' but it should be '#{path}'"
- end
- end
-
- # Checks if the group is being reused with the same path.
+ # Creates a new group that can be compared to a reused group, using the attributes of the original. Attributes that
+ # must be unique (path and name) are replaced with new unique values.
#
- # @return [Boolean] true if the group's path is different from another group with the same reuse symbol (reuse_as)
- def reused_path_unique?
- return true unless self.class.resources.key?(reuse_as)
-
- self.class.resources[reuse_as].path == path
+ # @return [QA::Resource] a new instance of Resource::ReusableGroup that should be a copy of the original resource
+ def reference_resource
+ attributes = self.class.resources[reuse_as][:attributes]
+ name = "ref#{SecureRandom.hex(8)}_#{attributes.delete(:path)}"[0...MAX_NAME_LENGTH]
+
+ Group.fabricate_via_api! do |resource|
+ self.class.resources[reuse_as][:attributes].each do |attribute_name, attribute_value|
+ resource.instance_variable_set("@#{attribute_name}", attribute_value) if attribute_value
+ end
+ resource.path = name
+ resource.name = name
+ end
end
- # Overrides QA::Resource::Group#remove_via_api! to log a debug message stating that removal will happen after
- # the suite completes rather than now.
+ # The attributes of the resource that should be the same whenever a test wants to reuse a group.
#
- # @return [nil]
- def remove_via_api!
- QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite")
+ # @return [Array<Symbol>] the attribute names.
+ def unique_identifiers
+ [:name, :path]
end
end
end
diff --git a/qa/qa/resource/reusable_project.rb b/qa/qa/resource/reusable_project.rb
index d2dfff8ad56..b9fca314122 100644
--- a/qa/qa/resource/reusable_project.rb
+++ b/qa/qa/resource/reusable_project.rb
@@ -15,36 +15,36 @@ module QA
super
@add_name_uuid = false
- @name = "reusable_project"
+ @name = @path = 'reusable_project'
@reuse_as = :default_project
@initialize_with_readme = true
end
- # Confirms that the project can be reused
- #
- # @return [nil] returns nil unless an error is raised
- def validate_reuse_preconditions
- unless reused_name_unique?
- raise ResourceReuseError,
- "Reusable projects must have the same name. The project reused as #{reuse_as} has the name '#{name}' but it should be '#{self.class.resources[reuse_as].name}'"
- end
- end
+ private
- # Checks if the project is being reused with the same name.
+ # Creates a new project that can be compared to a reused project, using the attributes of the original. Attributes
+ # that must be unique (path and name) are replaced with new unique values.
#
- # @return [Boolean] true if the project's name is different from another project with the same reuse symbol (reuse_as)
- def reused_name_unique?
- return true unless self.class.resources.key?(reuse_as)
-
- self.class.resources[reuse_as].name == name
+ # @return [QA::Resource] a new instance of Resource::ReusableProject that should be a copy of the original resource
+ def reference_resource
+ attributes = self.class.resources[reuse_as][:attributes]
+ name = "reference_resource_#{SecureRandom.hex(8)}_for_#{attributes.delete(:name)}"
+
+ Project.fabricate_via_api! do |project|
+ self.class.resources[reuse_as][:attributes].each do |attribute_name, attribute_value|
+ project.instance_variable_set("@#{attribute_name}", attribute_value) if attribute_value
+ end
+ project.name = name
+ project.path = name
+ project.path_with_namespace = "#{project.group.full_path}/#{project.name}"
+ end
end
- # Overrides QA::Resource::Project#remove_via_api! to log a debug message stating that removal will happen after
- # the suite completes rather than now.
+ # The attributes of the resource that should be the same whenever a test wants to reuse a project.
#
- # @return [nil]
- def remove_via_api!
- QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite")
+ # @return [Array<Symbol>] the attribute names.
+ def unique_identifiers
+ [:name, :path]
end
end
end
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 555bfb1abc9..8e7527bccd4 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -51,14 +51,6 @@ module QA
resource_web_url(api_get)
rescue ResourceNotFoundError
super
-
- # If the group was just created the runners token might not be
- # available via the API immediately.
- 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
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 1679698a9c0..088822cc2ca 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -65,6 +65,10 @@ module QA
ENV['QA_LOG_PATH'] || $stdout
end
+ def colorized_logs?
+ enabled?(ENV['COLORIZED_LOGS'], default: false)
+ end
+
# set to 'false' to have the browser run visibly instead of headless
def webdriver_headless?
if ENV.key?('CHROME_HEADLESS')
@@ -291,6 +295,14 @@ module QA
ENV['JIRA_HOSTNAME']
end
+ # this is set by the integrations job
+ # which will allow bidirectional communication
+ # between the app and the specs container
+ # should the specs container spin up a server
+ def qa_hostname
+ ENV['QA_HOSTNAME']
+ end
+
def cache_namespace_name?
enabled?(ENV['CACHE_NAMESPACE_NAME'], default: true)
end
@@ -434,6 +446,18 @@ module QA
ENV.fetch('QA_TEST_RESOURCES_CREATED_FILEPATH', File.join(Path.qa_root, 'tmp', file_name))
end
+ def ee_activation_code
+ ENV['QA_EE_ACTIVATION_CODE']
+ end
+
+ def quarantine_disabled?
+ enabled?(ENV['DISABLE_QUARANTINE'], default: false)
+ end
+
+ def validate_resource_reuse?
+ enabled?(ENV['QA_VALIDATE_RESOURCE_REUSE'], default: false)
+ end
+
private
def remote_grid_credentials
diff --git a/qa/qa/runtime/example.rb b/qa/qa/runtime/example.rb
new file mode 100644
index 00000000000..cd2119762f5
--- /dev/null
+++ b/qa/qa/runtime/example.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module QA
+ module Runtime
+ module Example
+ extend self
+
+ attr_accessor :current
+
+ def location
+ current.respond_to?(:location) ? current.location : 'unknown'
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/fixtures.rb b/qa/qa/runtime/fixtures.rb
index 05dee4bfce5..41d7ce5d178 100644
--- a/qa/qa/runtime/fixtures.rb
+++ b/qa/qa/runtime/fixtures.rb
@@ -33,6 +33,14 @@ module QA
FileUtils.remove_entry(dir, true)
end
+ def read_fixture(fixture_path, file_name)
+ file_path = Pathname
+ .new(__dir__)
+ .join("../fixtures/#{fixture_path}/#{file_name}")
+
+ File.read(file_path)
+ end
+
private
def api_client
diff --git a/qa/qa/runtime/logger.rb b/qa/qa/runtime/logger.rb
index a70c8faf7d2..81c41000033 100644
--- a/qa/qa/runtime/logger.rb
+++ b/qa/qa/runtime/logger.rb
@@ -2,11 +2,13 @@
require 'logger'
require 'forwardable'
+require 'rainbow/refinement'
module QA
module Runtime
module Logger
extend SingleForwardable
+ using Rainbow
def_delegators :logger, :debug, :info, :warn, :error, :fatal, :unknown
@@ -14,8 +16,16 @@ module QA
attr_writer :logger
def logger
+ Rainbow.enabled = Runtime::Env.colorized_logs?
+
@logger ||= ::Logger.new(Runtime::Env.log_destination).tap do |logger|
logger.level = Runtime::Env.debug? ? ::Logger::DEBUG : ::Logger::ERROR
+
+ logger.formatter = proc do |severity, datetime, progname, msg|
+ date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
+
+ "[date=#{date_format} from=QA Tests] #{severity.ljust(5)} -- ".yellow + "#{msg}\n"
+ end
end
end
end
diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb
index ef634d3ccda..8cf1fa0705f 100644
--- a/qa/qa/scenario/template.rb
+++ b/qa/qa/scenario/template.rb
@@ -32,6 +32,9 @@ module QA
# Given *gitlab_address* = 'http://gitlab-abc123.test/' #=> http://about.gitlab-abc123.test/
Runtime::Scenario.define(:about_address, URI(-> { gitlab_address.host = "about.#{gitlab_address.host}"; gitlab_address }.call).to_s) # rubocop:disable Style/Semicolon
+ # Save the scenario class name
+ Runtime::Scenario.define(:klass, self.class.name)
+
##
# Setup knapsack and download latest report
#
diff --git a/qa/qa/service/cluster_provider/gcloud.rb b/qa/qa/service/cluster_provider/gcloud.rb
index c6d1f6cfe88..77677745f7a 100644
--- a/qa/qa/service/cluster_provider/gcloud.rb
+++ b/qa/qa/service/cluster_provider/gcloud.rb
@@ -49,7 +49,7 @@ module QA
if account.empty?
raise "Failed to login to gcloud. No credentials provided in environment and no credentials found locally."
else
- puts "gcloud account found. Using: #{account} for creating K8s cluster."
+ QA::Runtime::Logger.debug("gcloud account found. Using: #{account} for creating K8s cluster.")
end
end
end
diff --git a/qa/qa/service/docker_run/smocker.rb b/qa/qa/service/docker_run/smocker.rb
new file mode 100644
index 00000000000..83ab58887da
--- /dev/null
+++ b/qa/qa/service/docker_run/smocker.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module QA
+ module Service
+ module DockerRun
+ class Smocker < Base
+ def initialize
+ @image = 'thiht/smocker:0.17.1'
+ @name = 'smocker-server'
+ @public_port = '8080'
+ @admin_port = '8081'
+ super
+ @network_cache = network
+ end
+
+ def host_name
+ return '127.0.0.1' unless QA::Runtime::Env.running_in_ci? || QA::Runtime::Env.qa_hostname
+
+ "#{@name}.#{@network_cache}"
+ end
+
+ def base_url
+ "http://#{host_name}:#{@public_port}"
+ end
+
+ def admin_url
+ "http://#{host_name}:#{@admin_port}"
+ end
+
+ def wait_for_running
+ Support::Waiter.wait_until(raise_on_failure: false, reload_page: false) do
+ running?
+ end
+ end
+
+ def register!
+ command = <<~CMD.tr("\n", ' ')
+ docker run -d --rm
+ --network #{@network_cache}
+ --hostname #{host_name}
+ --name #{@name}
+ --publish #{@public_port}:8080
+ --publish #{@admin_port}:8081
+ #{@image}
+ CMD
+
+ unless QA::Runtime::Env.running_in_ci? || QA::Runtime::Env.qa_hostname
+ command.gsub!("--network #{@network_cache} ", '')
+ end
+
+ shell command
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 7e47049d446..8ffb7c47652 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'digest'
+
module QA
module Service
class PraefectManager
@@ -50,6 +52,7 @@ module QA
def stop_primary_node
stop_node(@primary_node)
+ wait_until_node_is_removed_from_healthy_storages(@primary_node)
end
def start_primary_node
@@ -67,6 +70,7 @@ module QA
def stop_secondary_node
stop_node(@secondary_node)
+ wait_until_node_is_removed_from_healthy_storages(@secondary_node)
end
def start_secondary_node
@@ -75,6 +79,7 @@ module QA
def stop_tertiary_node
stop_node(@tertiary_node)
+ wait_until_node_is_removed_from_healthy_storages(@tertiary_node)
end
def start_tertiary_node
@@ -82,20 +87,41 @@ module QA
end
def start_node(name)
- shell "docker start #{name}"
- end
+ state = node_state(name)
+ return if state == "running"
+
+ if state == "paused"
+ shell "docker unpause #{name}"
+ end
+
+ if state == "stopped"
+ shell "docker start #{name}"
+ end
- def stop_node(name)
- shell "docker stop #{name}"
wait_until_shell_command_matches(
"docker inspect -f {{.State.Running}} #{name}",
- /false/,
+ /true/,
sleep_interval: 3,
max_duration: 180,
retry_on_exception: true
)
end
+ def stop_node(name)
+ return if node_state(name) == 'paused'
+
+ shell "docker pause #{name}"
+ end
+
+ def node_state(name)
+ state = "stopped"
+ wait_until_shell_command("docker inspect -f {{.State.Status}} #{name}") do |line|
+ QA::Runtime::Logger.debug(line)
+ break state = "running" if line.include?("running")
+ break state = "paused" if line.include?("paused")
+ end
+ end
+
def clear_replication_queue
QA::Runtime::Logger.info("Clearing the replication queue")
shell sql_to_docker_exec_cmd(
@@ -174,15 +200,25 @@ module QA
end
def start_all_nodes
- start_node(@postgres)
+ start_postgres
start_node(@primary_node)
start_node(@secondary_node)
start_node(@tertiary_node)
- start_node(@praefect)
+ start_praefect
wait_for_health_check_all_nodes
end
+ def start_postgres
+ start_node(@postgres)
+
+ Support::Waiter.repeat_until(max_attempts: 60, sleep_interval: 1) do
+ shell(sql_to_docker_exec_cmd("SELECT 1 as healthy_database"), fail_on_exception: false) do |line|
+ break true if line.include?("healthy_database")
+ end
+ end
+ end
+
def verify_storage_move(source_storage, destination_storage, repo_type: :project)
return if Specs::Helpers::ContextSelector.dot_com?
@@ -194,9 +230,8 @@ module QA
def wait_for_praefect
QA::Runtime::Logger.info("Waiting for health check on praefect")
Support::Waiter.wait_until(max_duration: 120, sleep_interval: 1, raise_on_failure: true) do
- # praefect runs a grpc server on port 2305, which will return an error 'Connection refused' until such time it is ready
- wait_until_shell_command("docker exec #{@gitaly_cluster} bash -c 'curl #{@praefect}:2305'") do |line|
- break if line.include?('curl: (1) Received HTTP/0.9 when not allowed')
+ wait_until_shell_command("docker exec #{@praefect} gitlab-ctl status praefect") do |line|
+ break true if line.include?('run: praefect: ')
QA::Runtime::Logger.debug(line.chomp)
end
@@ -250,6 +285,48 @@ module QA
end
end
+ def praefect_dataloss_information(project_id)
+ dataloss_info = []
+ cmd = "docker exec #{@praefect} praefect -config /var/opt/gitlab/praefect/config.toml dataloss --partially-unavailable=true"
+ shell(cmd) { |line| dataloss_info << line.strip }
+
+ # Expected will have a record for each repository in the storage, in the following format
+ # @hashed/bc/52/bc52dd634277c4a34a2d6210994a9a5e2ab6d33bb4a3a8963410e00ca6c15a02.git:
+ # Primary: gitaly1
+ # In-Sync Storages:
+ # gitaly1, assigned host
+ # gitaly3, assigned host
+ # Outdated Storages:
+ # gitaly2 is behind by 1 change or less, assigned host
+ #
+ # Alternatively, if all repositories are in sync, a concise message is returned
+ # Virtual storage: default
+ # All repositories are fully available on all assigned storages!
+
+ # extract the relevant project under test info if it is identified
+ start_index = dataloss_info.index { |line| line.include?("#{Digest::SHA256.hexdigest(project_id.to_s)}.git") }
+ unless start_index.nil?
+ dataloss_info = dataloss_info[start_index, 7]
+ end
+
+ dataloss_info&.each { |info| QA::Runtime::Logger.debug(info) }
+ dataloss_info
+ end
+
+ def praefect_dataloss_info_for_project(project_id)
+ dataloss_info = []
+ Support::Retrier.retry_until(max_duration: 60) do
+ dataloss_info = praefect_dataloss_information(project_id)
+ dataloss_info.include?("#{Digest::SHA256.hexdigest(project_id.to_s)}.git")
+ end
+ end
+
+ def wait_for_project_synced_across_all_storages(project_id)
+ Support::Retrier.retry_until(max_duration: 60) do
+ praefect_dataloss_information(project_id).include?('All repositories are fully available on all assigned storages!')
+ end
+ end
+
def wait_for_health_check_all_nodes
wait_for_gitaly_health_check(@primary_node)
wait_for_gitaly_health_check(@secondary_node)
@@ -259,9 +336,8 @@ module QA
def wait_for_gitaly_health_check(node)
QA::Runtime::Logger.info("Waiting for health check on #{node}")
Support::Waiter.wait_until(max_duration: 120, sleep_interval: 1, raise_on_failure: true) do
- # gitaly runs a grpc server on port 8075, which will return an error 'Connection refused' until such time it is ready
- wait_until_shell_command("docker exec #{@praefect} bash -c 'curl #{node}:8075'") do |line|
- break if line.include?('curl: (1) Received HTTP/0.9 when not allowed')
+ wait_until_shell_command("docker exec #{node} gitlab-ctl status gitaly") do |line|
+ break true if line.include?('run: gitaly: ')
QA::Runtime::Logger.debug(line.chomp)
end
diff --git a/qa/qa/service/shellout.rb b/qa/qa/service/shellout.rb
index 5a35d8c251e..33d1d10b515 100644
--- a/qa/qa/service/shellout.rb
+++ b/qa/qa/service/shellout.rb
@@ -5,6 +5,7 @@ require 'open3'
module QA
module Service
module Shellout
+ using Rainbow
CommandError = Class.new(StandardError)
module_function
@@ -13,23 +14,25 @@ module QA
# TODO, make it possible to use generic QA framework classes
# as a library - gitlab-org/gitlab-qa#94
#
- def shell(command, stdin_data: nil)
- puts "Executing `#{command}`"
+ def shell(command, stdin_data: nil, fail_on_exception: true)
+ QA::Runtime::Logger.info("Executing `#{command}`".cyan)
Open3.popen2e(*command) do |stdin, out, wait|
stdin.puts(stdin_data) if stdin_data
stdin.close if stdin_data
+ cmd_output = ''
if block_given?
out.each do |line|
+ cmd_output += line
yield line
end
end
out.each_char { |char| print char }
- if wait.value.exited? && wait.value.exitstatus.nonzero?
- raise CommandError, "Command `#{command}` failed!"
+ if wait.value.exited? && wait.value.exitstatus.nonzero? && fail_on_exception
+ raise CommandError, "Command failed: #{command} \nCommand Output: #{cmd_output}"
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
index 4bc95395f25..a51d733d484 100644
--- a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :github, :requires_admin do
+ RSpec.describe 'Manage', :github, :requires_admin, :reliable 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 } }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
index 8a2a382ac45..bb4b0472398 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
@@ -3,12 +3,8 @@
require_relative 'gitlab_project_migration_common'
module QA
- RSpec.describe 'Manage', :requires_admin do
- describe 'Gitlab migration', quarantine: {
- only: { job: 'praefect' },
- type: :investigating,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348999'
- } do
+ RSpec.describe 'Manage' do
+ describe 'Gitlab migration' do
include_context 'with gitlab project migration'
context 'with project issues' do
@@ -40,13 +36,13 @@ module QA
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347608'
) do
expect_import_finished
+ expect(imported_issues.count).to eq(1)
aggregate_failures do
- expect(imported_issues.count).to eq(1)
expect(imported_issue).to eq(source_issue.reload!)
expect(imported_comments.count).to eq(1)
- expect(imported_comments.first[:body]).to include(source_comment[:body])
+ expect(imported_comments.first&.fetch(:body)).to include(source_comment[:body])
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
index 9dce9bff3c1..d656ea4dea5 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
@@ -3,12 +3,8 @@
require_relative 'gitlab_project_migration_common'
module QA
- RSpec.describe 'Manage', :requires_admin do
- describe 'Gitlab migration', quarantine: {
- only: { job: 'praefect' },
- type: :investigating,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348999'
- } do
+ RSpec.describe 'Manage' do
+ describe 'Gitlab migration' do
include_context 'with gitlab project migration'
context 'with merge request' do
@@ -33,7 +29,8 @@ module QA
let!(:source_comment) { source_mr.add_comment('This is a test comment!') }
let(:imported_mrs) { imported_project.merge_requests }
- let(:imported_mr_comments) { imported_mr.comments }
+ let(:imported_mr_comments) { imported_mr.comments.map { |note| note.except(:id, :noteable_id) } }
+ let(:source_mr_comments) { source_mr.comments.map { |note| note.except(:id, :noteable_id) } }
let(:imported_mr) do
Resource::MergeRequest.init do |mr|
@@ -52,17 +49,12 @@ module QA
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348478'
) do
expect_import_finished
+ expect(imported_mrs.count).to eq(1)
aggregate_failures do
- expect(imported_mrs.count).to eq(1)
- # TODO: remove custom comparison after member migration is implemented
- # https://gitlab.com/gitlab-org/gitlab/-/issues/341886
- expect(imported_mr.comparable.except(:author)).to eq(source_mr.reload!.comparable.except(:author))
+ expect(imported_mr).to eq(source_mr.reload!)
- expect(imported_mr_comments.count).to eq(1)
- expect(imported_mr_comments.first[:body]).to include(source_comment[:body])
- # Comment will have mention of original user since members are not migrated yet
- expect(imported_mr_comments.first[:body]).to include(other_user.name)
+ expect(imported_mr_comments).to eq(source_mr_comments)
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
index a0c758c99e6..421dbe56a99 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
@@ -3,12 +3,8 @@
require_relative 'gitlab_project_migration_common'
module QA
- RSpec.describe 'Manage', :requires_admin do
- describe 'Gitlab migration', quarantine: {
- only: { job: 'praefect' },
- type: :investigating,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348999'
- } do
+ RSpec.describe 'Manage' do
+ describe 'Gitlab migration' do
include_context 'with gitlab project migration'
context 'with uninitialized project' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
index 827ebc1f5e2..b7f0a10c525 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
@@ -1,7 +1,13 @@
# frozen_string_literal: true
module QA
- RSpec.shared_context 'with gitlab project migration' do
+ # Disable on staging until bulk_import_projects toggle is on by default
+ # Otherwise tests running in parallel can disable feature in the middle of other test
+ RSpec.shared_context 'with gitlab project migration', :requires_admin, except: { subdomain: :staging }, quarantine: {
+ only: { job: 'praefect' },
+ type: :investigating,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348999'
+ } do
let(:source_project_with_readme) { false }
let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
let(:admin_api_client) { Runtime::API::Client.as_admin }
diff --git a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
index 13a795ca976..6480b880400 100644
--- a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
@@ -78,11 +78,6 @@ module QA
@different_project.remove_via_api!
end
end
-
- after(:all) do
- @project_access_token.remove_via_api!
- @project_access_token.project.remove_via_api!
- end
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
index 6a31d173440..fe6c89f4ee4 100644
--- a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
@@ -31,44 +31,50 @@ module QA
end
it 'is not allowed to push code via the CLI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347863' do
- expect do
- Resource::Repository::Push.fabricate! do |push|
- push.repository_http_uri = @project.repository_http_location.uri
- push.file_name = 'test.txt'
- push.file_content = "# This is a test project named #{@project.name}"
- push.commit_message = 'Add test.txt'
- push.branch_name = "new_branch_#{SecureRandom.hex(8)}"
- push.user = @user
- end
- end.to raise_error(QA::Support::Run::CommandError, /You are not allowed to push code to this project/)
+ QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 2) do
+ expect do
+ Resource::Repository::Push.fabricate! do |push|
+ push.repository_http_uri = @project.repository_http_location.uri
+ push.file_name = 'test.txt'
+ push.file_content = "# This is a test project named #{@project.name}"
+ push.commit_message = 'Add test.txt'
+ push.branch_name = "new_branch_#{SecureRandom.hex(8)}"
+ push.user = @user
+ end
+ end.to raise_error(QA::Support::Run::CommandError, /You are not allowed to push code to this project/)
+ end
end
it 'is not allowed to create a file via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347864' do
- expect do
- Resource::File.fabricate_via_api! do |file|
- file.api_client = @user_api_client
- file.project = @project
- file.branch = "new_branch_#{SecureRandom.hex(8)}"
- file.commit_message = 'Add new file'
- file.name = 'test.txt'
- file.content = "New file"
- end
- end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden/)
+ QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 2) do
+ expect do
+ Resource::File.fabricate_via_api! do |file|
+ file.api_client = @user_api_client
+ file.project = @project
+ file.branch = "new_branch_#{SecureRandom.hex(8)}"
+ file.commit_message = 'Add new file'
+ file.name = 'test.txt'
+ file.content = "New file"
+ end
+ end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden/)
+ end
end
it 'is not allowed to commit via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347865' do
- expect do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.api_client = @user_api_client
- commit.project = @project
- commit.branch = "new_branch_#{SecureRandom.hex(8)}"
- commit.start_branch = @project.default_branch
- commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
- end
- end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
+ QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 2) do
+ expect do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = @user_api_client
+ commit.project = @project
+ commit.branch = "new_branch_#{SecureRandom.hex(8)}"
+ commit.start_branch = @project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([
+ { file_path: 'test.txt', content: 'new file' }
+ ])
+ end
+ end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
+ end
end
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
index 6a9be19efdd..55ae0d215cf 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
@@ -9,37 +9,30 @@ module QA
project = nil
let(:intial_commit_message) { 'Initial commit' }
- let(:first_added_commit_message) { 'pushed to primary gitaly node' }
- let(:second_added_commit_message) { 'commit to failover node' }
+ let(:first_added_commit_message) { 'first_added_commit_message to primary gitaly node' }
+ let(:second_added_commit_message) { 'second_added_commit_message to failover node' }
before(:context) do
- # Reset the cluster in case previous tests left it in a bad state
praefect_manager.start_all_nodes
project = Resource::Project.fabricate! do |project|
project.name = "gitaly_cluster"
project.initialize_with_readme = true
end
- end
-
- after do
- praefect_manager.start_all_nodes
+ # We need to ensure that the the project is replicated to all nodes before proceeding with this test
+ praefect_manager.wait_for_replication(project.id)
end
it 'automatically fails over', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347830' do
- # Create a new project with a commit and wait for it to replicate
-
- # make sure that our project is published to the 'primary' node
+ # stop other nodes, so we can control which node the commit is sent to
praefect_manager.stop_secondary_node
praefect_manager.stop_tertiary_node
- praefect_manager.wait_for_secondary_node_health_check_failure
- praefect_manager.wait_for_tertiary_node_health_check_failure
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.commit_message = first_added_commit_message
push.new_branch = false
- push.file_content = "This should exist on all nodes"
+ push.file_content = 'This file created on gitaly1 while gitaly2/gitaly3 not running'
end
praefect_manager.start_all_nodes
@@ -56,7 +49,7 @@ module QA
commit.add_files([
{
file_path: "file-#{SecureRandom.hex(8)}",
- content: 'This should exist on one node before reconciliation'
+ content: 'This is created on gitaly2/gitaly3 while gitaly1 is unavailable'
}
])
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb
new file mode 100644
index 00000000000..6e2a34afb3e
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Praefect dataloss commands', :orchestrated, :gitaly_cluster do
+ let(:praefect_manager) { Service::PraefectManager.new }
+
+ let(:project) do
+ Resource::Project.fabricate! do |project|
+ project.name = 'gitaly_cluster-dataloss-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ praefect_manager.start_all_nodes
+ end
+
+ it 'confirms that changes are synced across all storages', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352691' do
+ expect { praefect_manager.praefect_dataloss_information(project.id) }
+ .to(eventually_include('All repositories are fully available on all assigned storages!')
+ .within(max_duration: 60))
+ end
+
+ it 'identifies how many changes are not in sync across storages', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352692' do
+ # Ensure our test repository is replicated and in a consistent state prior to test
+ praefect_manager.wait_for_project_synced_across_all_storages(project.id)
+
+ # testing for gitaly2 'out of sync'
+ praefect_manager.stop_secondary_node
+
+ number_of_changes = 3
+ 1.upto(number_of_changes) do |i|
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.branch = "newbranch-#{SecureRandom.hex(8)}"
+ commit.start_branch = project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([
+ { file_path: "new_file-#{SecureRandom.hex(8)}.txt", content: 'new file' }
+ ])
+ end
+ end
+
+ # testing for gitaly3 'in sync' but marked unhealthy
+ praefect_manager.stop_tertiary_node
+
+ project_data_loss = praefect_manager.praefect_dataloss_information(project.id)
+ aggregate_failures "validate dataloss identified" do
+ expect(project_data_loss).to include('gitaly1, assigned host')
+ expect(project_data_loss).to include("gitaly2 is behind by #{number_of_changes} changes or less, assigned host, unhealthy")
+ expect(project_data_loss).to include('gitaly3, assigned host, unhealthy')
+ end
+ end
+ end
+ end
+end
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 e7e23124312..d066953d12e 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, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/346453', type: :flaky } do
+ context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env do
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
Resource::Project.fabricate! do |project|
@@ -15,12 +15,10 @@ module QA
before do
praefect_manager.start_all_nodes
- praefect_manager.start_praefect
end
after do
praefect_manager.start_all_nodes
- praefect_manager.start_praefect
praefect_manager.clear_replication_queue
end
diff --git a/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb b/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb
new file mode 100644
index 00000000000..7a277d754c9
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'WebHooks integration', :requires_admin, :integrations, :orchestrated do
+ before(:context) do
+ toggle_local_requests(true)
+ end
+
+ after(:context) do
+ Vendor::Smocker::SmockerApi.teardown!
+ end
+
+ let(:session) { SecureRandom.hex(5) }
+
+ it 'sends a push event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348945' do
+ setup_webhook(push: true) do |webhook, smocker|
+ Resource::Repository::ProjectPush.fabricate! do |project_push|
+ project_push.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].push?).to be(true), "Not push event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a merge request event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349720' do
+ setup_webhook(merge_requests: true) do |webhook, smocker|
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].mr?).to be(true), "Not MR event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a wiki page event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349722' do
+ setup_webhook(wiki_page: true) do |webhook, smocker|
+ Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
+ page.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].wiki?).to be(true), "Not wiki event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends an issues and note event', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
+ setup_webhook(issues: true, note: true) do |webhook, smocker|
+ issue = Resource::Issue.fabricate_via_api! do |issue_init|
+ issue_init.project = webhook.project
+ end
+
+ Resource::ProjectIssueNote.fabricate_via_api! do |note|
+ note.project = issue.project
+ note.issue = issue
+ end
+
+ wait_until do
+ smocker.history(session).size > 1
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ issue_event = events.find(&:issue?)
+ note_event = events.find(&:note?)
+
+ expect(events.size).to be(2), "Should have 2 events: \n#{events.map(&:raw).join("\n")}"
+ expect(issue_event).not_to be(nil), "Not issue event: \n#{events[0].raw}"
+ expect(note_event).not_to be(nil), "Not note event: \n#{events[1].raw}"
+ end
+ end
+ end
+
+ private
+
+ def setup_webhook(**event_args)
+ Vendor::Smocker::SmockerApi.init(wait: 10) do |smocker|
+ smocker.register(session: session)
+
+ webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
+ hook.url = smocker.url
+
+ event_args.each do |event, bool|
+ hook.send("#{event}_events=", bool)
+ end
+ end
+
+ yield(webhook, smocker)
+
+ smocker.reset
+ end
+ end
+
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
+ end
+
+ def wait_until(timeout = 120, &block)
+ Support::Waiter.wait_until(max_duration: timeout, reload_page: false, raise_on_failure: false, &block)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
index 83dcb163d56..6eb3060fb59 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
@@ -68,9 +68,10 @@ module QA
mr.iid = merge_request[:iid]
end
- expect(merge_request.state).to eq('opened')
- expect(merge_request.merge_status).to eq('checking')
- expect(merge_request.merge_when_pipeline_succeeds).to be true
+ aggregate_failures do
+ expect(merge_request.state).to eq('opened')
+ expect(merge_request.merge_when_pipeline_succeeds).to be true
+ end
end
it 'merges when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347842' do
diff --git a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb
index ecc59aa7cc8..bb4e0d71710 100644
--- a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb
+++ b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Service ping default enabled' do
- context 'When using default enabled from gitlab.yml config', :requires_admin do
+ context 'When using default enabled from gitlab.yml config', :requires_admin, except: { job: 'review-qa-*' } do
before do
Flow::Login.sign_in_as_admin
@@ -10,7 +10,7 @@ module QA
Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
end
- it 'has service ping toggle enabled' do
+ it 'has service ping toggle enabled', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348335' do
Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
setting.expand_usage_statistics do |page|
expect(page).not_to have_disabled_usage_data_checkbox
diff --git a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb
index 309369265c9..cab8bd367f5 100644
--- a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb
+++ b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb
@@ -10,7 +10,7 @@ module QA
Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
end
- it 'has service ping toggle is disabled' do
+ it 'has service ping toggle is disabled', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348340' do
Page::Admin::Settings::MetricsAndProfiling.perform do |settings|
settings.expand_usage_statistics do |usage_statistics|
expect(usage_statistics).to have_disabled_usage_data_checkbox
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
index a18e22f52f1..a1b9e232e3d 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- describe 'Manage', :requires_admin do
+ describe 'Manage', :requires_admin, :reliable do
describe 'Gitlab migration' do
let!(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:user) do
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 881bc5bc7c3..2db93ac60ea 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
@@ -31,7 +31,7 @@ module QA
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform do |general|
- general.transfer_group(target_group.path)
+ general.transfer_group(target_group.path, sub_group_for_transfer.path)
sub_group_for_transfer.sandbox = target_group
sub_group_for_transfer.reload!
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
index 098c0b3ba63..5487ecff028 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
@@ -64,7 +64,9 @@ module QA
Page::Profile::Accounts::Show.perform do |show|
show.delete_account(user.password)
end
- Support::Waiter.wait_until { !user.exists? }
+
+ # TODO: Remove retry_on_exception once https://gitlab.com/gitlab-org/gitlab/-/issues/24294 is resolved
+ Support::Waiter.wait_until(retry_on_exception: true, sleep_interval: 3) { !user.exists? }
end
it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
index 895027a588d..bfb810b5c2b 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :requires_admin, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/350598',
- type: :needs_update,
- only: { subdomain: :staging }
- } do
+ RSpec.describe 'Manage', :requires_admin do
describe 'Add project member' do
before do
Runtime::Feature.enable(:invite_members_group_modal)
@@ -25,7 +21,7 @@ module QA
Page::Project::Menu.perform(&:click_members)
Page::Project::Members.perform do |members|
members.add_member(user.username)
-
+ members.search_member(user.username)
expect(members).to have_content("@#{user.username}")
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
new file mode 100644
index 00000000000..2933d580957
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Create project badge' do
+ let(:badge_name) { "project-badge-#{SecureRandom.hex(8)}" }
+ let(:expected_badge_link_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}" }
+ let(:expected_badge_image_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg" }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'badge-test-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ end
+
+ it 'creates project badge successfully', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/350065' do
+ Resource::ProjectBadge.fabricate! do |badge|
+ badge.name = badge_name
+ end
+
+ Page::Project::Settings::Main.perform do |project_settings|
+ expect(project_settings).to have_notice('New badge added.')
+ end
+
+ Page::Component::Badges.perform do |badges|
+ aggregate_failures do
+ expect(badges).to have_badge(badge_name)
+ expect(badges).to have_visible_badge_image_link(expected_badge_link_url)
+ expect(badges.asset_exists?(expected_badge_image_url)).to be_truthy
+ end
+ end
+
+ project.visit!
+
+ Page::Project::Show.perform do |project|
+ expect(project).to have_visible_badge_image_link(expected_badge_link_url)
+ expect(project.asset_exists?(expected_badge_image_url)).to be_truthy
+ end
+ end
+
+ after do
+ project&.remove_via_api!
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb
index 714c4a2da67..4f9ba579730 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb
@@ -21,8 +21,8 @@ module QA
let(:tag_message) { 'Version 0.0.1' }
let(:tag_release_notes) { 'Release It!' }
- shared_examples 'successful tag creation' do |user|
- it "can be created by #{user}" do
+ shared_examples 'successful tag creation' do |user, testcase|
+ it "can be created by #{user}", testcase: testcase do
Flow::Login.sign_in(as: send(user))
create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
@@ -36,8 +36,8 @@ module QA
end
end
- shared_examples 'unsuccessful tag creation' do |user|
- it "cannot be created by an unauthorized #{user}" do
+ shared_examples 'unsuccessful tag creation' do |user, testcase|
+ it "cannot be created by an unauthorized #{user}", testcase: testcase do
Flow::Login.sign_in(as: send(user))
create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
@@ -54,8 +54,8 @@ module QA
add_members_to_project(project)
end
- it_behaves_like 'successful tag creation', :developer_user
- it_behaves_like 'successful tag creation', :maintainer_user
+ it_behaves_like 'successful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347930'
+ it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347929'
end
context 'when protected' do
@@ -69,8 +69,8 @@ module QA
Page::Main::Menu.perform(&:sign_out)
end
- it_behaves_like 'unsuccessful tag creation', :developer_user
- it_behaves_like 'successful tag creation', :maintainer_user
+ it_behaves_like 'unsuccessful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347927'
+ it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347928'
end
def create_tag_for_project(project, name, message, release_notes)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
index 87b51edef08..11cf4f60a80 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
@@ -5,21 +5,27 @@ module QA
describe 'User', :requires_admin do
let(:admin_api_client) { Runtime::API::Client.as_admin }
- let(:user) do
+ let(:followed_user_api_client) { Runtime::API::Client.new(:gitlab, user: followed_user) }
+
+ let(:followed_user) do
Resource::User.fabricate_via_api! do |user|
+ user.name = "followed_user_#{SecureRandom.hex(8)}"
user.api_client = admin_api_client
end
end
- let(:user_api_client) do
- Runtime::API::Client.new(:gitlab, user: user)
+ let(:following_user) do
+ Resource::User.fabricate_via_api! do |user|
+ user.name = "following_user_#{SecureRandom.hex(8)}"
+ user.api_client = admin_api_client
+ end
end
let(:group) do
group = QA::Resource::Group.fabricate_via_api! do |group|
group.path = "group_for_follow_user_activity_#{SecureRandom.hex(8)}"
end
- group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
+ group.add_member(followed_user, Resource::Members::AccessLevel::MAINTAINER)
group
end
@@ -27,7 +33,7 @@ module QA
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-for-tags'
project.initialize_with_readme = true
- project.api_client = user_api_client
+ project.api_client = followed_user_api_client
project.group = group
end
end
@@ -35,14 +41,14 @@ module QA
let(:merge_request) do
Resource::MergeRequest.fabricate_via_api! do |mr|
mr.project = project
- mr.api_client = user_api_client
+ mr.api_client = followed_user_api_client
end
end
let(:issue) do
Resource::Issue.fabricate_via_api! do |issue|
issue.project = project
- issue.api_client = user_api_client
+ issue.api_client = followed_user_api_client
end
end
@@ -51,19 +57,19 @@ module QA
project_issue_note.project = project
project_issue_note.issue = issue
project_issue_note.body = 'This is a comment'
- project_issue_note.api_client = user_api_client
+ project_issue_note.api_client = followed_user_api_client
end
end
before do
# Create both tokens before logging in the first time so that we don't need to log out in the middle of the test
admin_api_client.personal_access_token
- user_api_client.personal_access_token
+ followed_user_api_client.personal_access_token
end
it 'can be followed and their activity seen', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347678' do
- Flow::Login.sign_in
- page.visit Runtime::Scenario.gitlab_address + "/#{user.username}"
+ Flow::Login.sign_in(as: following_user)
+ page.visit Runtime::Scenario.gitlab_address + "/#{followed_user.username}"
Page::User::Show.perform(&:click_follow_user_link)
expect(page).to have_text("No activities found")
@@ -76,7 +82,7 @@ module QA
Page::Main::Menu.perform(&:click_user_profile_link)
Page::User::Show.perform do |show|
show.click_following_link
- show.click_user_link(user.username)
+ show.click_user_link(followed_user.username)
aggregate_failures do
expect(show).to have_activity('created project')
@@ -88,9 +94,10 @@ module QA
end
after do
- project.api_client = admin_api_client
- project.remove_via_api!
- user.remove_via_api!
+ project&.api_client = admin_api_client
+ project&.remove_via_api!
+ followed_user&.remove_via_api!
+ following_user&.remove_via_api!
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
index c908b1c46a1..d3662884952 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
@@ -31,8 +31,8 @@ module QA
Flow::Login.sign_in
end
- shared_examples 'milestone assigned to existing issue' do
- it 'is assigned to an existing issue' do
+ shared_examples 'milestone assigned to existing issue' do |testcase|
+ it 'is assigned to an existing issue', testcase: testcase do
issue.visit!
Page::Project::Issue::Show.perform do |existing_issue|
@@ -43,8 +43,8 @@ module QA
end
end
- shared_examples 'milestone assigned to new issue' do
- it 'is assigned to a new issue' do
+ shared_examples 'milestone assigned to new issue' do |testcase|
+ it 'is assigned to a new issue', testcase: testcase do
Resource::Issue.fabricate_via_browser_ui! do |new_issue|
new_issue.project = project
new_issue.milestone = milestone
@@ -65,8 +65,8 @@ module QA
end
end
- it_behaves_like 'milestone assigned to existing issue'
- it_behaves_like 'milestone assigned to new issue'
+ it_behaves_like 'milestone assigned to existing issue', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347964'
+ it_behaves_like 'milestone assigned to new issue', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347965'
end
context 'Project milestone' do
@@ -78,8 +78,8 @@ module QA
end
end
- it_behaves_like 'milestone assigned to existing issue'
- it_behaves_like 'milestone assigned to new issue'
+ it_behaves_like 'milestone assigned to existing issue', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347962'
+ it_behaves_like 'milestone assigned to new issue', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347963'
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
index 5f896c7bf10..b7284f972ef 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
@@ -12,7 +12,7 @@ module QA
Flow::Login.sign_in
end
- it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347822' do
+ it 'user adds a design and annotates it', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/352746', type: :investigating }, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347822' do
issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
index 9a771919c11..85270791f0f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
@@ -20,6 +20,18 @@ module QA
end
before do
+ Flow::Login.sign_in
+ end
+
+ after do
+ runner&.remove_via_api!
+ project&.remove_via_api!
+ end
+
+ it 'merges after pipeline succeeds' do
+ transient_test = repeat > 1
+
+ # Push a new pipeline config file
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -30,7 +42,7 @@ module QA
content: <<~EOF
test:
tags: ["runner-for-#{project.name}"]
- script: sleep 20
+ script: sleep 30
only:
- merge_requests
EOF
@@ -39,17 +51,8 @@ module QA
)
end
- Flow::Login.sign_in
- end
-
- after do
- runner&.remove_via_api!
- project&.remove_via_api!
- end
-
- it 'merges after pipeline succeeds' do
repeat.times do |i|
- QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if repeat > 1
+ QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if transient_test
branch_name = "mr-test-#{SecureRandom.hex(6)}-#{i}"
@@ -68,19 +71,54 @@ module QA
merge_request.no_preparation = true
end
+ # Load the page so that the browser is as prepared as possible to display the pipeline in progress when we
+ # start it.
merge_request.visit!
+ # Push a new file to trigger a new pipeline
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add new file'
+ commit.branch = branch_name
+ commit.add_files(
+ [
+ {
+ file_path: "#{branch_name}-file.md",
+ content: "file content"
+ }
+ ]
+ )
+ end
+
Page::MergeRequest::Show.perform do |mr|
- mr.merge_when_pipeline_succeeds!
+ mr.refresh
+
+ # Part of the challenge with this test is that the MR widget has many components that could be displayed
+ # and many errors states that those components could encounter. Most of the time few of those
+ # possible components will be relevant, so it would be inefficient for this test to check for each of
+ # them. Instead, we fail on anything but the expected state.
+ #
+ # The following method allows us to handle and ignore states (as we find them) that users could safely ignore.
+ mr.wait_until_ready_to_merge(transient_test: transient_test)
+
+ mr.retry_until(reload: true, message: 'Wait until ready to click MWPS') do
+ merge_request.reload!
+
+ # Click the MWPS button if we can
+ break mr.merge_when_pipeline_succeeds! if mr.has_element?(:merge_button, text: 'Merge when pipeline succeeds')
+
+ # But fail if the button is missing because the pipeline is complete
+ raise "The pipeline already finished before we could click MWPS" if mr.wait_until { project.pipelines.first }[:status] == 'success'
- Support::Waiter.wait_until(sleep_interval: 5) do
- merge_request = merge_request.reload!
- merge_request.state == 'merged'
+ # Otherwise, if this is not a transient test reload the page and retry
+ next false unless transient_test
end
aggregate_failures do
- expect(merge_request.merge_when_pipeline_succeeds).to be_truthy
- expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear."
+ expect { mr.merged? }.to eventually_be_truthy.within(max_duration: 60), "Expected content 'The changes were merged' but it did not appear."
+ expect(merge_request.reload!.merge_when_pipeline_succeeds).to be_truthy
+ expect(merge_request.state).to eq('merged')
+ expect(project.pipelines.last[:status]).to eq('success')
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
index 3da73c8fa72..107d72a9724 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
@@ -18,30 +18,34 @@ module QA
file_name: '.gitignore',
name: 'Android',
api_path: 'gitignores',
- api_key: 'Android'
+ api_key: 'Android',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347659'
},
{
file_name: '.gitlab-ci.yml',
name: 'Julia',
api_path: 'gitlab_ci_ymls',
- api_key: 'Julia'
+ api_key: 'Julia',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347658'
},
{
file_name: 'Dockerfile',
name: 'Python',
api_path: 'dockerfiles',
- api_key: 'Python'
+ api_key: 'Python',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347660'
},
{
file_name: 'LICENSE',
name: 'Mozilla Public License 2.0',
api_path: 'licenses',
- api_key: 'mpl-2.0'
+ api_key: 'mpl-2.0',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347657'
}
]
templates.each do |template|
- it "user adds #{template[:file_name]} via file template #{template[:name]}" do
+ it "user adds #{template[:file_name]} via file template #{template[:name]}", testcase: template[:testcase] do
content = fetch_template_from_api(template[:api_path], template[:api_key])
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb
new file mode 100644
index 00000000000..78abdb94dfe
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create', only: { subdomain: %i[staging staging-canary] } do
+ describe 'Git push to canary Gitaly node over HTTP' do
+ it 'pushes to a project using a canary specific Gitaly repository storage', :smoke, :requires_admin, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/351116' do
+ Flow::Login.sign_in_as_admin
+
+ project = Resource::Project.fabricate_via_api! do |storage_project|
+ storage_project.name = 'canary-specific-repository-storage'
+ storage_project.repository_storage = 'nfs-file-cny01' # TODO: move to ENV var
+ end
+
+ Resource::Repository::Push.fabricate! do |push|
+ push.repository_http_uri = project.repository_http_location.uri
+ push.file_name = 'README.md'
+ push.file_content = "# This is a test project named #{project.name}"
+ push.commit_message = 'Add README.md'
+ push.new_branch = true
+ end
+
+ project.visit!
+
+ Page::Project::Show.perform do |project_page|
+ expect(project_page).to have_file('README.md')
+ expect(project_page).to have_readme_content("This is a test project named #{project.name}")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
index 6ab50ba56f2..1a7c64a363f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
@@ -28,8 +28,8 @@ module QA
project_snippet&.remove_via_api!
end
- shared_examples 'comments on snippets' do |snippet_type|
- it "adds, edits, and deletes a comment on a #{snippet_type}" do
+ shared_examples 'comments on snippets' do |snippet_type, testcase|
+ it "adds, edits, and deletes a comment on a #{snippet_type}", testcase: testcase do
send(snippet_type)
Page::Main::Menu.perform(&:sign_out)
@@ -49,8 +49,8 @@ module QA
end
end
- it_behaves_like 'comments on snippets', :personal_snippet
- it_behaves_like 'comments on snippets', :project_snippet
+ it_behaves_like 'comments on snippets', :personal_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347816'
+ it_behaves_like 'comments on snippets', :project_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347817'
def create_comment
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
index 72d83eadde9..8f05446ff70 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
@@ -28,8 +28,8 @@ module QA
project_snippet&.remove_via_api!
end
- shared_examples 'adding file to snippet' do |snippet_type|
- it "adds second file to an existing #{snippet_type} to make it multi-file" do
+ shared_examples 'adding file to snippet' do |snippet_type, testcase|
+ it "adds second file to an existing #{snippet_type} to make it multi-file", testcase: testcase do
send(snippet_type).visit!
Page::Dashboard::Snippet::Show.perform(&:click_edit_button)
@@ -52,8 +52,8 @@ module QA
end
end
- it_behaves_like 'adding file to snippet', :personal_snippet
- it_behaves_like 'adding file to snippet', :project_snippet
+ it_behaves_like 'adding file to snippet', :personal_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347845'
+ it_behaves_like 'adding file to snippet', :project_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347846'
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
index 29ddbb22a01..0b63d9a1edb 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
@@ -59,8 +59,8 @@ module QA
project_snippet&.remove_via_api!
end
- shared_examples 'copying snippet file contents' do |snippet_type|
- it "copies file contents of a multi-file #{snippet_type} to a comment and verifies them" do
+ shared_examples 'copying snippet file contents' do |snippet_type, testcase|
+ it "copies file contents of a multi-file #{snippet_type} to a comment and verifies them", testcase: testcase do
send(snippet_type).visit!
files.each do |files|
@@ -73,8 +73,8 @@ module QA
end
end
- it_behaves_like 'copying snippet file contents', :personal_snippet
- it_behaves_like 'copying snippet file contents', :project_snippet
+ it_behaves_like 'copying snippet file contents', :personal_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347849'
+ it_behaves_like 'copying snippet file contents', :project_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347848'
end
end
end
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 dc66e0c5a9f..e04f580dc15 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do # convert back to a smoke test once proved to be stable
+ RSpec.describe 'Create', :smoke do
describe 'Personal snippet creation' do
let(:snippet) do
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
index 014c0ca4d48..b6092ef0c4c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
@@ -36,8 +36,8 @@ module QA
project_snippet&.remove_via_api!
end
- shared_examples 'deleting file from snippet' do |snippet_type|
- it "deletes second file from an existing #{snippet_type} to make it single-file" do
+ shared_examples 'deleting file from snippet' do |snippet_type, testcase|
+ it "deletes second file from an existing #{snippet_type} to make it single-file", testcase: testcase do
send(snippet_type).visit!
Page::Dashboard::Snippet::Show.perform(&:click_edit_button)
@@ -58,8 +58,8 @@ module QA
end
end
- it_behaves_like 'deleting file from snippet', :personal_snippet
- it_behaves_like 'deleting file from snippet', :project_snippet
+ it_behaves_like 'deleting file from snippet', :personal_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347728'
+ it_behaves_like 'deleting file from snippet', :project_snippet, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347727'
end
end
end
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 d922950335f..97e42edfd01 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
@@ -56,8 +56,8 @@ module QA
project_snippet_with_multiple_files.remove_via_api!
end
- shared_examples 'displaying details on index page' do |snippet_type|
- it "shows correct details of #{snippet_type} including file number" do
+ shared_examples 'displaying details on index page' do |snippet_type, testcase|
+ it "shows correct details of #{snippet_type} including file number", testcase: testcase do
send(snippet_type)
Page::Main::Menu.perform do |menu|
menu.go_to_menu_dropdown_option(:snippets_link)
@@ -73,10 +73,10 @@ module QA
end
end
- it_behaves_like 'displaying details on index page', :personal_snippet_with_single_file
- it_behaves_like 'displaying details on index page', :personal_snippet_with_multiple_files
- it_behaves_like 'displaying details on index page', :project_snippet_with_single_file
- it_behaves_like 'displaying details on index page', :project_snippet_with_multiple_files
+ it_behaves_like 'displaying details on index page', :personal_snippet_with_single_file, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347717'
+ it_behaves_like 'displaying details on index page', :personal_snippet_with_multiple_files, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347720'
+ it_behaves_like 'displaying details on index page', :project_snippet_with_single_file, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347718'
+ it_behaves_like 'displaying details on index page', :project_snippet_with_multiple_files, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347719'
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
index 70c9c9beeb8..19dd868744f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
@@ -18,30 +18,34 @@ module QA
file_name: '.gitignore',
name: 'Android',
api_path: 'gitignores',
- api_key: 'Android'
+ api_key: 'Android',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347752'
},
{
file_name: '.gitlab-ci.yml',
name: 'Julia',
api_path: 'gitlab_ci_ymls',
- api_key: 'Julia'
+ api_key: 'Julia',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347753'
},
{
file_name: 'Dockerfile',
name: 'Python',
api_path: 'dockerfiles',
- api_key: 'Python'
+ api_key: 'Python',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347750'
},
{
file_name: 'LICENSE',
name: 'Mozilla Public License 2.0',
api_path: 'licenses',
- api_key: 'mpl-2.0'
+ api_key: 'mpl-2.0',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347751'
}
]
templates.each do |template|
- it "user adds #{template[:file_name]} via file template #{template[:name]}" do
+ it "user adds #{template[:file_name]} via file template #{template[:name]}", testcase: template[:testcase] do
content = fetch_template_from_api(template[:api_path], template[:api_key])
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
index 758aae9f729..96e85139e78 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
@@ -11,7 +11,7 @@ module QA
end
context 'when a user does not have permissions to commit to the project' do
- let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
+ let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) }
context 'when no fork is present' do
it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347823' do
@@ -45,6 +45,10 @@ module QA
submit_merge_request_upstream
end
+
+ after do
+ fork_project.project.remove_via_api!
+ end
end
def submit_merge_request_upstream
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
index 67eee66b3d6..b45624381c8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/350220', type: :investigating } do # remove :requires_admin once the ff is enabled by default in https://gitlab.com/gitlab-org/gitlab/-/issues/345398
+ RSpec.describe 'Create' do
context 'Content Editor' do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
let(:page_title) { 'Content Editor Page' }
let(:heading_text) { 'My New Heading' }
let(:image_file_name) { 'testfile.png' }
- let!(:toggle) { Runtime::Feature.enabled?(:wiki_switch_between_content_editor_raw_markdown) }
before do
Flow::Login.sign_in
@@ -24,7 +23,7 @@ module QA
Page::Project::Wiki::Edit.perform do |edit|
edit.set_title(page_title)
- edit.use_new_editor(toggle)
+ edit.use_new_editor
edit.add_heading('Heading 1', heading_text)
edit.upload_image(File.absolute_path(File.join('qa', 'fixtures', 'designs', image_file_name)))
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
index 22bb5fed84c..0bc3fb7b829 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
@@ -25,7 +25,7 @@ module QA
Resource::Runner.fabricate! do |runner|
runner.name = executor
runner.tags = [executor]
- runner.token = group.sandbox.runners_token
+ runner.token = group.reload!.runners_token
end
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb
new file mode 100644
index 00000000000..7a2c2b4ae90
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :runner, quarantine: {
+ type: :flaky,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/351994'
+ } do
+ describe 'Run pipeline with manual jobs' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pipeline-with-manual-job'
+ project.description = 'Project for pipeline with manual job'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = "qa-runner-#{SecureRandom.hex(3)}"
+ end
+ end
+
+ let!(:ci_file) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ stages:
+ - Stage1
+ - Stage2
+ - Stage3
+
+ Prep:
+ stage: Stage1
+ script: exit 0
+ when: manual
+
+ Build:
+ stage: Stage2
+ needs: ['Prep']
+ script: exit 0
+ parallel: 6
+
+ Test:
+ stage: Stage3
+ needs: ['Build']
+ script: exit 0
+
+ Deploy:
+ stage: Stage3
+ needs: ['Test']
+ script: exit 0
+ parallel: 6
+ YAML
+ }
+ ]
+ )
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'skipped')
+ end
+
+ after do
+ runner&.remove_via_api!
+ project&.remove_via_api!
+ end
+
+ it 'does not leave any job in skipped state', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349158' do
+ Page::Project::Pipeline::Show.perform do |show|
+ show.click_job_action('Prep') # Trigger pipeline manually
+
+ show.wait_until(max_duration: 300, sleep_interval: 2, reload: false) do
+ project.pipelines.last[:status] == 'success'
+ end
+
+ aggregate_failures do
+ expect(show).to have_build('Test', status: :success)
+
+ show.click_job_dropdown('Build')
+ expect(show).not_to have_skipped_job_in_group
+
+ show.click_job_dropdown('Build') # Close Build dropdown
+ show.click_job_dropdown('Deploy')
+ expect(show).not_to have_skipped_job_in_group
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
index 5e0f1911811..9a5a5416d5c 100644
--- a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
@@ -3,6 +3,8 @@
module QA
RSpec.describe 'Package', :orchestrated, :registry, only: { pipeline: :main } do
describe 'Dependency Proxy' do
+ using RSpec::Parameterized::TableSyntax
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'dependency-proxy-project'
@@ -40,12 +42,13 @@ module QA
runner.remove_via_api!
end
- where(:docker_client_version) do
- %w[docker:19.03.12 docker:20.10]
+ where(:case_name, :docker_client_version, :testcase) do
+ 'using docker:19.03.12' | 'docker:19.03.12' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347605'
+ 'using docker:20.10' | 'docker:20.10' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347604'
end
with_them do
- it "pulls an image using the dependency proxy" do
+ it "pulls an image using the dependency proxy", testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
@@ -58,7 +61,7 @@ module QA
image: "#{docker_client_version}"
services:
- name: "#{docker_client_version}-dind"
- command: ["--insecure-registry=gitlab.test:80"]
+ command: ["--insecure-registry=gitlab.test:80"]
before_script:
- apk add curl jq grep
- echo $CI_DEPENDENCY_PROXY_SERVER
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
index 92e4d64fee4..2da0f6a0cf8 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
@@ -32,55 +32,22 @@ module QA
"#{uri.scheme}://#{uri.host}:#{uri.port}"
end
- let(:composer_json_file) do
- <<~EOF
- {
- "name": "#{project.path_with_namespace}/#{package.name}",
- "description": "Library XY",
- "type": "library",
- "license": "GPL-3.0-only",
- "authors": [
- {
- "name": "John Doe",
- "email": "john@example.com"
- }
- ],
- "require": {}
- }
- EOF
- end
-
- let(:gitlab_ci_yaml) do
- <<~YAML
- publish:
- image: curlimages/curl:latest
- stage: build
- variables:
- URL: "$CI_SERVER_PROTOCOL://$CI_SERVER_HOST:$CI_SERVER_PORT/api/v4/projects/$CI_PROJECT_ID/packages/composer?job_token=$CI_JOB_TOKEN"
- script:
- - version=$([[ -z "$CI_COMMIT_TAG" ]] && echo "branch=$CI_COMMIT_REF_NAME" || echo "tag=$CI_COMMIT_TAG")
- - insecure=$([ "$CI_SERVER_PROTOCOL" = "http" ] && echo "--insecure" || echo "")
- - response=$(curl -s -w "%{http_code}" $insecure --data $version $URL)
- - code=$(echo "$response" | tail -n 1)
- - body=$(echo "$response" | head -n 1)
- tags:
- - "runner-for-#{project.name}"
- YAML
- end
-
before do
Flow::Login.sign_in
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ composer_yaml = ERB.new(read_fixture('package_managers/composer', 'composer_upload_package.yaml.erb')).result(binding)
+ composer_json = ERB.new(read_fixture('package_managers/composer', 'composer.json.erb')).result(binding)
+
commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([{
file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
+ content: composer_yaml
},
{
file_path: 'composer.json',
- content: composer_json_file
+ content: composer_json
}]
)
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
index 15578cd5e6b..22495796605 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
@@ -46,25 +46,13 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ conan_yaml = ERB.new(read_fixture('package_managers/conan', 'conan_upload_install_package.yaml.erb')).result(binding)
+
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([{
file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: conanio/gcc7
-
- test_package:
- stage: deploy
- script:
- - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
- - "conan new #{package.name}/0.1 -t"
- - "conan create . mycompany/stable"
- - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
- - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
- tags:
- - "runner-for-#{project.name}"
- YAML
+ content: conan_yaml
}])
end
end
@@ -90,8 +78,10 @@ module QA
Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
+ aggregate_failures 'package deletion' do
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
index ded90607d67..71acc3a8f92 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
@@ -3,6 +3,8 @@
module QA
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
describe 'Generic Repository' do
+ include Runtime::Fixtures
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'generic-package-project'
@@ -25,29 +27,6 @@ module QA
end
end
- let(:gitlab_ci_yaml) do
- <<~YAML
- image: curlimages/curl:latest
-
- stages:
- - upload
- - download
-
- upload:
- stage: upload
- script:
- - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt'
- tags:
- - "runner-for-#{project.name}"
- download:
- stage: download
- script:
- - 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt -O file_downloaded.txt'
- tags:
- - "runner-for-#{project.name}"
- YAML
- end
-
let(:file_txt) do
<<~EOF
Hello, world!
@@ -59,11 +38,13 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ generic_packages_yaml = ERB.new(read_fixture('package_managers/generic', 'generic_upload_install_package.yaml.erb')).result(binding)
+
commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([{
file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
+ content: generic_packages_yaml
},
{
file_path: 'file.txt',
@@ -100,21 +81,11 @@ module QA
package.remove_via_api!
end
- it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348017' do
+ it 'uploads a generic package and downloads it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348017' do
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- aggregate_failures 'package deletion' do
- expect(index).to have_content("Package deleted successfully")
- expect(index).to have_no_package(package.name)
- end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
index 92d0f547764..d2e816f9bf9 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
@@ -3,6 +3,7 @@
module QA
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
describe 'Helm Registry' do
+ using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
include_context 'packages registry qa scenario'
@@ -10,140 +11,105 @@ module QA
let(:package_version) { '1.3.7' }
let(:package_type) { 'helm' }
- let(:package_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: alpine:3
- script:
- - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
- - apk add curl
- - helm create #{package_name}
- - cp ./Chart.yaml #{package_name}
- - helm package #{package_name}
- - http_code=$(curl --write-out "%{http_code}" --request POST --form 'chart=@#{package_name}-#{package_version}.tgz' --user #{username}:#{access_token} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts --output /dev/null --silent)
- - '[ $http_code = "201" ]'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.group.name}"
- YAML
- }
+ where(:case_name, :authentication_token_type, :testcase) do
+ 'using personal access token' | :personal_access_token | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347586'
+ 'using ci job token' | :ci_job_token | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347587'
+ 'using project deploy token' | :project_deploy_token | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347588'
end
- let(:package_chart_yaml_file) do
- {
- file_path: "Chart.yaml",
- content:
- <<~EOF
- apiVersion: v2
- name: #{package_name}
- description: GitLab QA helm package
- type: application
- version: #{package_version}
- appVersion: "1.16.0"
- EOF
- }
- end
-
- let(:client_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- pull:
- image: alpine:3
- script:
- - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
- - helm repo add --username #{username} --password #{access_token} gitlab_qa ${CI_API_V4_URL}/projects/#{package_project.id}/packages/helm/stable
- - helm repo update
- - helm pull gitlab_qa/#{package_name}
- only:
- - "#{client_project.default_branch}"
- tags:
- - "runner-for-#{client_project.group.name}"
- YAML
- }
- end
-
- %i[personal_access_token ci_job_token project_deploy_token].each do |authentication_token_type|
- context "using a #{authentication_token_type}" do
- let(:username) do
- case authentication_token_type
- when :personal_access_token
- Runtime::User.username
- when :ci_job_token
- 'gitlab-ci-token'
- when :project_deploy_token
- project_deploy_token.username
- end
+ with_them do
+ let(:username) do
+ case authentication_token_type
+ when :personal_access_token
+ Runtime::User.username
+ when :ci_job_token
+ 'gitlab-ci-token'
+ when :project_deploy_token
+ project_deploy_token.username
end
+ end
- let(:access_token) do
- case authentication_token_type
- when :personal_access_token
- personal_access_token
- when :ci_job_token
- '${CI_JOB_TOKEN}'
- when :project_deploy_token
- project_deploy_token.token
- end
+ let(:access_token) do
+ case authentication_token_type
+ when :personal_access_token
+ personal_access_token
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ project_deploy_token.token
end
+ end
- it "pushes and pulls a helm chart" do
- Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_chart_yaml_file])
- end
+ it "pushes and pulls a helm chart", testcase: params[:testcase] do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ helm_upload_yaml = ERB.new(read_fixture('package_managers/helm', 'helm_upload_package.yaml.erb')).result(binding)
+ helm_chart_yaml = ERB.new(read_fixture('package_managers/helm', 'Chart.yaml.erb')).result(binding)
+
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: helm_upload_yaml
+ },
+ {
+ file_path: 'Chart.yaml',
+ content: helm_chart_yaml
+ }
+ ])
end
+ end
- package_project.visit!
+ package_project.visit!
- Flow::Pipeline.visit_latest_pipeline
+ Flow::Pipeline.visit_latest_pipeline
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:click_packages_link)
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
- index.click_package(package_name)
- end
+ index.click_package(package_name)
+ end
- Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package_name, package_version)
- end
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package_name, package_version)
+ end
- Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file])
- end
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ helm_install_yaml = ERB.new(read_fixture('package_managers/helm', 'helm_install_package.yaml.erb')).result(binding)
+
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: helm_install_yaml
+ }
+ ])
end
+ end
- client_project.visit!
+ client_project.visit!
- Flow::Pipeline.visit_latest_pipeline
+ Flow::Pipeline.visit_latest_pipeline
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('pull')
- end
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('pull')
+ end
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
index 57e1aa6a087..45693ecee41 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
@@ -13,80 +13,10 @@ module QA
let(:package_version) { '1.3.7' }
let(:package_type) { 'maven_gradle' }
- let(:package_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: gradle:6.5-jdk11
- script:
- - 'gradle publish'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.group.name}"
- YAML
- }
- end
-
- let(:package_build_gradle_file) do
- {
- file_path: 'build.gradle',
- content:
- <<~EOF
- plugins {
- id 'java'
- id 'maven-publish'
- }
-
- publishing {
- publications {
- library(MavenPublication) {
- groupId '#{group_id}'
- artifactId '#{artifact_id}'
- version '#{package_version}'
- from components.java
- }
- }
- repositories {
- maven {
- url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
- credentials(HttpHeaderCredentials) {
- name = "Private-Token"
- value = "#{personal_access_token}"
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
- }
- }
- EOF
- }
- end
-
- let(:client_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- build:
- image: gradle:6.5-jdk11
- script:
- - 'gradle build'
- only:
- - "#{client_project.default_branch}"
- tags:
- - "runner-for-#{client_project.group.name}"
- YAML
- }
- end
-
- where(:authentication_token_type, :maven_header_name) do
- :personal_access_token | 'Private-Token'
- :ci_job_token | 'Job-Token'
- :project_deploy_token | 'Deploy-Token'
+ where(:case_name, :authentication_token_type, :maven_header_name, :testcase) do
+ 'using personal access token' | :personal_access_token | 'Private-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347601'
+ 'using ci job token' | :ci_job_token | 'Job-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347603'
+ 'using project deploy token' | :project_deploy_token | 'Deploy-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347602'
end
with_them do
@@ -101,49 +31,24 @@ module QA
end
end
- let(:client_build_gradle_file) do
- {
- file_path: 'build.gradle',
- content:
- <<~EOF
- plugins {
- id 'java'
- id 'application'
- }
-
- repositories {
- jcenter()
- maven {
- url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
- name "GitLab"
- credentials(HttpHeaderCredentials) {
- name = '#{maven_header_name}'
- value = #{token}
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
- }
-
- dependencies {
- implementation group: '#{group_id}', name: '#{artifact_id}', version: '#{package_version}'
- testImplementation 'junit:junit:4.12'
- }
-
- application {
- mainClassName = 'gradle_maven_app.App'
- }
- EOF
- }
- end
-
- it "pushes and pulls a maven package via gradle using #{params[:authentication_token_type]}" do
+ it 'pushes and pulls a maven package via gradle', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven', 'gradle_upload_package.yaml.erb')).result(binding)
+ build_upload_gradle = ERB.new(read_fixture('package_managers/maven', 'build_upload.gradle.erb')).result(binding)
+
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_build_gradle_file])
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: gradle_upload_yaml
+ },
+ {
+ file_path: 'build.gradle',
+ content: build_upload_gradle
+ }
+ ])
end
end
@@ -173,9 +78,21 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ gradle_install_yaml = ERB.new(read_fixture('package_managers/maven', 'gradle_install_package.yaml.erb')).result(binding)
+ build_install_gradle = ERB.new(read_fixture('package_managers/maven', 'build_install.gradle.erb')).result(binding)
+
commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file, client_build_gradle_file])
+ commit.commit_message = 'Add files'
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: gradle_install_yaml
+ },
+ {
+ file_path: 'build.gradle',
+ content: build_install_gradle
+ }
+ ])
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
index e6591b6adb9..b4ebb9dd475 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
@@ -13,121 +13,6 @@ module QA
let(:package_version) { '1.3.7' }
let(:package_type) { 'maven' }
- let(:package_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: maven:3.6-jdk-11
- script:
- - 'mvn deploy -s settings.xml'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.group.name}"
- YAML
- }
- end
-
- let(:package_pom_file) do
- {
- file_path: 'pom.xml',
- content: <<~XML
- <project>
- <groupId>#{group_id}</groupId>
- <artifactId>#{artifact_id}</artifactId>
- <version>#{package_version}</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/groups/#{package_project.group.id}/-/packages/maven</url>
- </repository>
- </repositories>
- <distributionManagement>
- <repository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
- </snapshotRepository>
- </distributionManagement>
- </project>
- XML
- }
- end
-
- let(:client_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- install:
- image: maven:3.6-jdk-11
- script:
- - "mvn install -s settings.xml"
- only:
- - "#{client_project.default_branch}"
- tags:
- - "runner-for-#{client_project.group.name}"
- YAML
- }
- end
-
- let(:client_pom_file) do
- {
- file_path: 'pom.xml',
- content: <<~XML
- <project>
- <groupId>#{group_id}</groupId>
- <artifactId>maven_client</artifactId>
- <version>1.0</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/groups/#{package_project.group.id}/-/packages/maven</url>
- </repository>
- </repositories>
- <dependencies>
- <dependency>
- <groupId>#{group_id}</groupId>
- <artifactId>#{artifact_id}</artifactId>
- <version>#{package_version}</version>
- </dependency>
- </dependencies>
- </project>
- XML
- }
- end
-
- let(:settings_xml_with_pat) do
- {
- file_path: 'settings.xml',
- content: <<~XML
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>#{package_project.name}</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Private-Token</name>
- <value>#{personal_access_token}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
- XML
- }
- end
-
where(:authentication_token_type, :maven_header_name) do
:personal_access_token | 'Private-Token'
:ci_job_token | 'Job-Token'
@@ -146,39 +31,28 @@ module QA
end
end
- let(:settings_xml) do
- {
- file_path: 'settings.xml',
- content: <<~XML
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>#{package_project.name}</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>#{maven_header_name}</name>
- <value>#{token}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
- XML
- }
- end
-
it "pushes and pulls a maven package via maven using #{params[:authentication_token_type]}" do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ maven_upload_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_upload_package.yaml.erb')).result(binding)
+ package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+
commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([
- package_gitlab_ci_file,
- package_pom_file,
- settings_xml
+ {
+ file_path: '.gitlab-ci.yml',
+ content: maven_upload_package_yaml
+ },
+ {
+ file_path: 'pom.xml',
+ content: package_pom_xml
+ },
+ {
+ file_path: 'settings.xml',
+ content: settings_xml
+ }
])
end
end
@@ -209,12 +83,25 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ maven_install_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_install_package.yaml.erb')).result(binding)
+ client_pom_xml = ERB.new(read_fixture('package_managers/maven', 'client_pom.xml.erb')).result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+
commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([
- client_gitlab_ci_file,
- client_pom_file,
- settings_xml
+ {
+ file_path: '.gitlab-ci.yml',
+ content: maven_install_package_yaml
+ },
+ {
+ file_path: 'pom.xml',
+ content: client_pom_xml
+ },
+ {
+ file_path: 'settings.xml',
+ content: settings_xml
+ }
])
end
end
@@ -278,7 +165,19 @@ module QA
end
def create_duplicated_package
- with_fixtures([package_pom_file, settings_xml_with_pat]) do |dir|
+ settings_xml_with_pat = ERB.new(read_fixture('package_managers/maven', 'settings_with_pat.xml.erb')).result(binding)
+ package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
+
+ with_fixtures([
+ {
+ file_path: 'pom.xml',
+ content: package_pom_xml
+ },
+ {
+ file_path: 'settings.xml',
+ content: settings_xml_with_pat
+ }
+ ]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
end
@@ -294,12 +193,25 @@ module QA
def push_duplicated_package
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ maven_upload_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_upload_package.yaml.erb')).result(binding)
+ package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+
commit.project = client_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
- package_gitlab_ci_file,
- package_pom_file,
- settings_xml
+ {
+ file_path: '.gitlab-ci.yml',
+ content: maven_upload_package_yaml
+ },
+ {
+ file_path: 'pom.xml',
+ content: package_pom_xml
+ },
+ {
+ file_path: 'settings.xml',
+ content: settings_xml
+ }
])
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
index 70b31c1beca..04aaefbaf5c 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package Registry', :orchestrated, :packages, :object_storage do
+ RSpec.describe 'Package Registry', :orchestrated, :reliable, :packages, :object_storage do
describe 'npm instance level endpoint' do
using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
@@ -50,79 +50,10 @@ module QA
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = ["runner-for-#{project.group.name}"]
runner.executor = :docker
- runner.token = project.group.runners_token
+ runner.token = project.group.reload!.runners_token
end
end
- let(:gitlab_ci_deploy_yaml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: node:latest
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
- - npm publish
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- end
-
- let(:gitlab_ci_install_yaml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: node:latest
-
- stages:
- - install
-
- install:
- stage: install
- script:
- - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/packages/npm/"
- - "npm install #{package.name}"
- cache:
- key: ${CI_BUILD_REF_NAME}
- paths:
- - node_modules/
- artifacts:
- paths:
- - node_modules/
- only:
- - "#{another_project.default_branch}"
- tags:
- - "runner-for-#{another_project.group.name}"
- YAML
- }
- end
-
- let(:package_json) do
- {
- file_path: 'package.json',
- content: <<~JSON
- {
- "name": "#{package.name}",
- "version": "1.0.0",
- "description": "Example package for GitLab npm registry",
- "publishConfig": {
- "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
- }
- }
- JSON
- }
- end
-
let(:package) do
Resource::Package.init do |package|
package.name = "@#{registry_scope}/#{project.name}-#{SecureRandom.hex(8)}"
@@ -137,10 +68,10 @@ module QA
another_project.remove_via_api!
end
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :ci_job_token | 'CI Job Token'
- :project_deploy_token | 'Deploy Token'
+ where(:case_name, :authentication_token_type, :token_name, :testcase) do
+ 'using personal access token' | :personal_access_token | 'Personal Access Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347600'
+ 'using ci job token' | :ci_job_token | 'CI Job Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347599'
+ 'using project deploy token' | :project_deploy_token | 'Deploy Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347598'
end
with_them do
@@ -155,14 +86,23 @@ module QA
end
end
- it "push and pull a npm package via CI using a #{params[:token_name]}" do
+ it 'push and pull a npm package via CI', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ npm_upload_yaml = ERB.new(read_fixture('package_managers/npm', 'npm_upload_package_instance.yaml.erb')).result(binding)
+ package_json = ERB.new(read_fixture('package_managers/npm', 'package_instance.json.erb')).result(binding)
+
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([
- gitlab_ci_deploy_yaml,
- package_json
+ {
+ file_path: '.gitlab-ci.yml',
+ content: npm_upload_yaml
+ },
+ {
+ file_path: 'package.json',
+ content: package_json
+ }
])
end
end
@@ -180,10 +120,15 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ npm_install_yaml = ERB.new(read_fixture('package_managers/npm', 'npm_install_package_instance.yaml.erb')).result(binding)
+
commit.project = another_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
- gitlab_ci_install_yaml
+ {
+ file_path: '.gitlab-ci.yml',
+ content: npm_install_yaml
+ }
])
end
end
@@ -217,13 +162,6 @@ module QA
Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package.name, "1.0.0")
-
- show.click_delete
- end
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
index e25a742493b..cad1802f3e9 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package Registry', :orchestrated, :packages, :object_storage do
+ RSpec.describe 'Package Registry', :orchestrated, :reliable, :packages, :object_storage do
describe 'npm project level endpoint' do
using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
@@ -46,62 +46,6 @@ module QA
end
end
- let(:gitlab_ci_yaml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: node:latest
-
- stages:
- - deploy
- - install
-
- deploy:
- stage: deploy
- script:
- - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
- - npm publish
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.name}"
- install:
- stage: install
- script:
- - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
- - "npm install #{package.name}"
- cache:
- key: ${CI_BUILD_REF_NAME}
- paths:
- - node_modules/
- artifacts:
- paths:
- - node_modules/
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.name}"
- YAML
- }
- end
-
- let(:package_json) do
- {
- file_path: 'package.json',
- content: <<~JSON
- {
- "name": "#{package.name}",
- "version": "1.0.0",
- "description": "Example package for GitLab npm registry",
- "publishConfig": {
- "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
- }
- }
- JSON
- }
- end
-
let(:package) do
Resource::Package.init do |package|
package.name = "@#{registry_scope}/mypackage-#{SecureRandom.hex(8)}"
@@ -115,10 +59,10 @@ module QA
project.remove_via_api!
end
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :ci_job_token | 'CI Job Token'
- :project_deploy_token | 'Deploy Token'
+ where(:case_name, :authentication_token_type, :token_name, :testcase) do
+ 'using personal access token' | :personal_access_token | 'Personal Access Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347592'
+ 'using ci job token' | :ci_job_token | 'CI Job Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347594'
+ 'using project deploy token' | :project_deploy_token | 'Deploy Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347593'
end
with_them do
@@ -133,13 +77,22 @@ module QA
end
end
- it "push and pull a npm package via CI using a #{params[:token_name]}" do
+ it 'push and pull a npm package via CI', testcase: params[:testcase] do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ npm_upload_install_yaml = ERB.new(read_fixture('package_managers/npm', 'npm_upload_install_package_project.yaml.erb')).result(binding)
+ package_json = ERB.new(read_fixture('package_managers/npm', 'package_project.json.erb')).result(binding)
+
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
- gitlab_ci_yaml,
- package_json
+ {
+ file_path: '.gitlab-ci.yml',
+ content: npm_upload_install_yaml
+ },
+ {
+ file_path: 'package.json',
+ content: package_json
+ }
])
end
@@ -182,13 +135,6 @@ module QA
Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package.name, "1.0.0")
-
- show.click_delete
- end
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
index d63bf486f11..24f83bc19fb 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
@@ -5,6 +5,7 @@ module QA
describe 'NuGet Repository' do
using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-project'
@@ -53,7 +54,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.runners_token
+ runner.token = project.group.reload!.runners_token
end
end
@@ -62,10 +63,10 @@ module QA
package.remove_via_api!
end
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :ci_job_token | 'CI Job Token'
- :group_deploy_token | 'Deploy Token'
+ where(:case_name, :authentication_token_type, :token_name, :testcase) do
+ 'using personal access token' | :personal_access_token | 'Personal Access Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347597'
+ 'using ci job token' | :ci_job_token | 'CI Job Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347595'
+ 'using group deploy token' | :group_deploy_token | 'Deploy Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347596'
end
with_them do
@@ -91,36 +92,19 @@ module QA
end
end
- it "publishes a nuget package at the project level, installs and deletes it at the group level using a #{params[:token_name]}" do
+ it 'publishes a nuget package at the project endpoint and installs it from the group endpoint', testcase: params[:testcase] do
Flow::Login.sign_in
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ nuget_upload_yaml = ERB.new(read_fixture('package_managers/nuget', 'nuget_upload_package.yaml.erb')).result(binding)
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.update_files(
[
{
file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - dotnet restore -p:Configuration=Release
- - dotnet build -c Release
- - dotnet pack -c Release -p:PackageID=#{package.name}
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
- rules:
- - if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
- tags:
- - "runner-for-#{project.group.name}"
- YAML
+ content: nuget_upload_yaml
}
]
)
@@ -142,6 +126,8 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ nuget_install_yaml = ERB.new(read_fixture('package_managers/nuget', 'nuget_install_package.yaml.erb')).result(binding)
+
commit.project = another_project
commit.commit_message = 'Add new csproj file'
commit.add_files(
@@ -165,23 +151,7 @@ module QA
[
{
file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - install
-
- install:
- stage: install
- script:
- - dotnet nuget locals all --clear
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
- only:
- - "#{another_project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
+ content: nuget_install_yaml
}
]
)
@@ -204,14 +174,6 @@ module QA
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content('Package deleted successfully')
- expect(index).not_to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
index 2e7bd8fc5d7..a0c2eca5bd2 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
@@ -4,6 +4,7 @@ module QA
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
describe 'PyPI Repository' do
include Runtime::Fixtures
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'pypi-package-project'
@@ -36,56 +37,18 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ pypi_yaml = ERB.new(read_fixture('package_managers/pypi', 'pypi_upload_install_package.yaml.erb')).result(binding)
+ pypi_setup_file = ERB.new(read_fixture('package_managers/pypi', 'setup.py.erb')).result(binding)
+
commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.commit_message = 'Add files'
commit.add_files([{
file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: python:latest
- stages:
- - run
- - install
-
- run:
- stage: 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 #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
- tags:
- - "runner-for-#{project.name}"
- install:
- stage: install
- script:
- - "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
- tags:
- - "runner-for-#{project.name}"
-
- YAML
+ content: pypi_yaml
},
{
file_path: 'setup.py',
- content:
- <<~EOF
- import setuptools
-
- setuptools.setup(
- name="#{package.name}",
- version="0.0.1",
- author="Example Author",
- author_email="author@example.com",
- description="A small example package",
- packages=setuptools.find_packages(),
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
- python_requires='>=3.6',
- )
- EOF
-
+ content: pypi_setup_file
}])
end
end
@@ -119,21 +82,11 @@ module QA
end
context 'when at the project level' do
- it 'publishes and installs a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348015' do
+ it 'publishes and installs a pypi package', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348015' do
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- aggregate_failures do
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
- end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
index 062d2b49deb..b2208dc644c 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
@@ -43,35 +43,21 @@ module QA
project.remove_via_api!
end
- it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347649' do
+ it 'publishes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347649' do
Flow::Login.sign_in
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ rubygem_upload_yaml = ERB.new(read_fixture('package_managers/rubygems', 'rubygems_upload_package.yaml.erb')).result(binding)
+ rubygem_package_gemspec = ERB.new(read_fixture('package_managers/rubygems', 'package.gemspec.erb')).result(binding)
+
commit.project = project
commit.commit_message = 'Add package files'
commit.add_files(
[
{
file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: ruby
-
- test_package:
- stage: deploy
- before_script:
- - mkdir ~/.gem
- - echo "---" > ~/.gem/credentials
- - |
- echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
- - chmod 0600 ~/.gem/credentials
- script:
- - gem build #{package.name}
- - gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
- tags:
- - "runner-for-#{project.name}"
- YAML
+ content: rubygem_upload_yaml
},
{
file_path: 'lib/hello_gem.rb',
@@ -86,49 +72,7 @@ module QA
},
{
file_path: "#{package.name}.gemspec",
- content:
- <<~RUBY
- # frozen_string_literal: true
-
- Gem::Specification.new do |s|
- s.name = '#{package.name}'
- s.authors = ['Tanuki Steve', 'Hal 9000']
- s.author = 'Tanuki Steve'
- s.version = '0.0.1'
- s.date = '2011-09-29'
- s.summary = 'this is a test package'
- s.files = ['lib/hello_gem.rb']
- s.require_paths = ['lib']
-
- s.description = 'A test package for GitLab.'
- s.email = 'tanuki@not_real.com'
- s.homepage = 'https://gitlab.com/ruby-co/my-package'
- s.license = 'MIT'
-
- s.metadata = {
- 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
- 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
- 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
- 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
- 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
- }
-
- s.bindir = 'bin'
- s.platform = Gem::Platform::RUBY
- s.post_install_message = 'Installed, thank you!'
- s.rdoc_options = ['--main']
- s.required_ruby_version = '>= 2.7.0'
- s.required_rubygems_version = '>= 1.8.11'
- s.requirements = 'A high powered server or calculator'
- s.rubygems_version = '1.8.09'
-
- s.add_dependency 'dependency_1', '~> 1.2.3'
- s.add_dependency 'dependency_2', '3.0.0'
- s.add_dependency 'dependency_3', '>= 1.0.0'
- s.add_dependency 'dependency_4'
- end
-
- RUBY
+ content: rubygem_package_gemspec
}
]
)
@@ -150,14 +94,6 @@ module QA
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index f4a5c715684..c86f75e0b16 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -33,13 +33,13 @@ module QA
end
keys = [
- [Runtime::Key::RSA, 8192],
- [Runtime::Key::ECDSA, 521],
- [Runtime::Key::ED25519]
+ ['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348022', Runtime::Key::RSA, 8192],
+ ['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348021', Runtime::Key::ECDSA, 521],
+ ['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348020', Runtime::Key::ED25519]
]
- keys.each do |(key_class, bits)|
- it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do
+ keys.each do |(testcase, key_class, bits)|
+ it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines", testcase: testcase do
key = key_class.new(*bits)
Resource::DeployKey.fabricate_via_browser_ui! do |resource|
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 2538f249010..718dc9860fb 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
@@ -3,6 +3,8 @@
module QA
RSpec.describe 'Configure' do
describe 'AutoDevOps Templates', only: { subdomain: :staging } do
+ using RSpec::Parameterized::TableSyntax
+
# specify jobs to be disabled in the pipeline.
# CANARY_ENABLED will allow the pipeline to be
# blocked by a manual job, rather than fail
@@ -17,8 +19,8 @@ module QA
]
end
- where(:template) do
- %w[express]
+ where(:case_name, :template, :testcase) do
+ 'using express template' | 'express' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348075'
end
with_them do
@@ -45,7 +47,7 @@ module QA
Flow::Login.sign_in
end
- it 'works with Auto DevOps' do
+ it 'works with Auto DevOps', testcase: params[:testcase] do
%w[build code_quality test].each do |job|
pipeline.visit!
diff --git a/qa/qa/specs/helpers/quarantine.rb b/qa/qa/specs/helpers/quarantine.rb
index 738c99efb28..e58d70fdfb5 100644
--- a/qa/qa/specs/helpers/quarantine.rb
+++ b/qa/qa/specs/helpers/quarantine.rb
@@ -10,8 +10,10 @@ module QA
extend self
- # Skip tests in quarantine unless we explicitly focus on them.
+ # Skip tests in quarantine unless we explicitly focus on them or quarantine disabled
def skip_or_run_quarantined_tests_or_contexts(example)
+ return if Runtime::Env.quarantine_disabled?
+
if filters.key?(:quarantine)
included_filters = filters_other_than_quarantine
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index 2c9e302fc56..a861c13a44c 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -7,6 +7,7 @@ module QA
module Specs
class Runner < Scenario::Template
attr_accessor :tty, :tags, :options
+ RegexMismatchError = Class.new(StandardError)
DEFAULT_TEST_PATH_ARGS = ['--', File.expand_path('./features', __dir__)].freeze
DEFAULT_STD_ARGS = [$stderr, $stdout].freeze
@@ -72,16 +73,48 @@ module QA
elsif Runtime::Scenario.attributes[:count_examples_only]
args.unshift('--dry-run')
out = StringIO.new
+
RSpec::Core::Runner.run(args.flatten, $stderr, out).tap do |status|
abort if status.nonzero?
end
- $stdout.puts out.string.match(/(\d+) examples,/)[1]
+
+ begin
+ total_examples = out.string.match(/(\d+) examples?,/)[1]
+ rescue StandardError
+ raise RegexMismatchError, 'Rspec output did not match regex'
+ end
+
+ filename = build_filename
+
+ File.open(filename, 'w') { |f| f.write(total_examples) } if total_examples.to_i > 0
+
+ $stdout.puts "Total examples in #{Runtime::Scenario.klass}: #{total_examples}#{total_examples.to_i > 0 ? ". Saved to file: #{filename}" : ''}"
else
RSpec::Core::Runner.run(args.flatten, *DEFAULT_STD_ARGS).tap do |status|
abort if status.nonzero?
end
end
end
+
+ private
+
+ def build_filename
+ filename = Runtime::Scenario.klass.split('::').last(3).join('_').downcase
+
+ tags = []
+ options.reduce do |before, after|
+ tags << after if %w[--tag -t].include?(before)
+ after
+ end
+ tags = tags.compact.join('_')
+
+ filename.concat("_#{tags}") unless tags.empty?
+
+ filename.concat('.txt')
+
+ FileUtils.mkdir_p('no_of_examples')
+ File.join('no_of_examples', filename)
+ end
end
end
end
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 663761805ee..976188e45c6 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -44,6 +44,18 @@ module QA
end
end
+ def patch(url, payload = nil)
+ with_retry_on_too_many_requests do
+ RestClient::Request.execute(
+ method: :patch,
+ url: url,
+ payload: payload,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ return_response_or_raise(e)
+ end
+ end
+
def put(url, payload = nil)
with_retry_on_too_many_requests do
RestClient::Request.execute(
diff --git a/qa/qa/support/formatters/allure_metadata_formatter.rb b/qa/qa/support/formatters/allure_metadata_formatter.rb
index 10769ba5c57..da35ffde1ae 100644
--- a/qa/qa/support/formatters/allure_metadata_formatter.rb
+++ b/qa/qa/support/formatters/allure_metadata_formatter.rb
@@ -15,14 +15,42 @@ module QA
def example_started(example_notification)
example = example_notification.example
- quarantine_issue = example.metadata.dig(:quarantine, :issue)
- example.issue('Quarantine issue', quarantine_issue) if quarantine_issue
+ add_quarantine_issue_link(example)
+ add_failure_issues_link(example)
+ add_ci_job_link(example)
+ end
+
+ private
+
+ # Add quarantine issue links
+ #
+ # @param [RSpec::Core::Example] example
+ # @return [void]
+ def add_quarantine_issue_link(example)
+ issue_link = example.metadata.dig(:quarantine, :issue)
+
+ return unless issue_link
+ return example.issue('Quarantine issue', issue_link) if issue_link.is_a?(String)
+ return issue_link.each { |link| example.issue('Quarantine issue', link) } if issue_link.is_a?(Array)
+ end
+ # Add failure issues link
+ #
+ # @param [RSpec::Core::Example] example
+ # @return [void]
+ def add_failure_issues_link(example)
spec_file = example.file_path.split('/').last
example.issue(
'Failure issues',
"https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&state=opened&search=#{spec_file}"
)
+ end
+
+ # Add ci job link
+ #
+ # @param [RSpec::Core::Example] example
+ # @return [void]
+ def add_ci_job_link(example)
return unless Runtime::Env.running_in_ci?
example.add_link(name: "Job(#{Runtime::Env.ci_job_name})", url: Runtime::Env.ci_job_url)
diff --git a/qa/qa/support/formatters/test_stats_formatter.rb b/qa/qa/support/formatters/test_stats_formatter.rb
index 7678cb8406c..430294b0bb6 100644
--- a/qa/qa/support/formatters/test_stats_formatter.rb
+++ b/qa/qa/support/formatters/test_stats_formatter.rb
@@ -14,40 +14,38 @@ module QA
return log(:warn, 'Missing QA_INFLUXDB_URL, skipping metrics export!') unless influxdb_url
return log(:warn, 'Missing QA_INFLUXDB_TOKEN, skipping metrics export!') unless influxdb_token
- data = notification.examples.map { |example| test_stats(example) }.compact
- influx_client.create_write_api.write(data: data)
- log(:info, "Pushed #{data.length} entries to influxdb")
- rescue StandardError => e
- log(:error, "Failed to push data to influxdb, error: #{e}")
+ push_test_stats(notification.examples)
+ push_fabrication_stats
end
private
- # InfluxDb client
+ # Push test execution stats to influxdb
#
- # @return [InfluxDB2::Client]
- def influx_client
- @influx_client ||= InfluxDB2::Client.new(
- influxdb_url,
- influxdb_token,
- bucket: 'e2e-test-stats',
- org: 'gitlab-qa',
- precision: InfluxDB2::WritePrecision::NANOSECOND
- )
- end
+ # @param [Array<RSpec::Core::Example>] examples
+ # @return [void]
+ def push_test_stats(examples)
+ data = examples.map { |example| test_stats(example) }.compact
- # InfluxDb instance url
- #
- # @return [String]
- def influxdb_url
- @influxdb_url ||= env('QA_INFLUXDB_URL')
+ influx_client.write(data: data)
+ log(:debug, "Pushed #{data.length} test execution entries to influxdb")
+ rescue StandardError => e
+ log(:error, "Failed to push test execution stats to influxdb, error: #{e}")
end
- # Influxdb token
+ # Push resource fabrication stats to influxdb
#
- # @return [String]
- def influxdb_token
- @influxdb_token ||= env('QA_INFLUXDB_TOKEN')
+ # @return [void]
+ def push_fabrication_stats
+ data = Tools::TestResourceDataProcessor.resources.flat_map do |resource, values|
+ values.map { |v| fabrication_stats(resource: resource, **v) }
+ end
+ return if data.empty?
+
+ influx_client.write(data: data)
+ log(:debug, "Pushed #{data.length} resource fabrication entries to influxdb")
+ rescue StandardError => e
+ log(:error, "Failed to push fabrication stats to influxdb, error: #{e}")
end
# Transform example to influxdb compatible metrics data
@@ -73,7 +71,8 @@ module QA
job_name: job_name,
merge_request: merge_request,
run_type: env('QA_RUN_TYPE') || run_type,
- stage: devops_stage(file_path)
+ stage: devops_stage(file_path),
+ testcase: example.metadata[:testcase]
},
fields: {
id: example.id,
@@ -84,8 +83,7 @@ module QA
retry_attempts: example.metadata[:retry_attempts] || 0,
job_url: QA::Runtime::Env.ci_job_url,
pipeline_url: env('CI_PIPELINE_URL'),
- pipeline_id: env('CI_PIPELINE_ID'),
- testcase: example.metadata[:testcase]
+ pipeline_id: env('CI_PIPELINE_ID')
}
}
rescue StandardError => e
@@ -93,6 +91,34 @@ module QA
nil
end
+ # Resource fabrication data point
+ #
+ # @param [String] resource
+ # @param [String] info
+ # @param [Symbol] fabrication_method
+ # @param [Symbol] http_method
+ # @param [Integer] fabrication_time
+ # @return [Hash]
+ def fabrication_stats(resource:, info:, fabrication_method:, http_method:, fabrication_time:, timestamp:, **)
+ {
+ name: 'fabrication-stats',
+ time: time,
+ tags: {
+ resource: resource,
+ fabrication_method: fabrication_method,
+ http_method: http_method,
+ run_type: env('QA_RUN_TYPE') || run_type,
+ merge_request: merge_request
+ },
+ fields: {
+ fabrication_time: fabrication_time,
+ info: info,
+ job_url: QA::Runtime::Env.ci_job_url,
+ timestamp: timestamp
+ }
+ }
+ end
+
# Project name
#
# @return [String]
@@ -150,7 +176,7 @@ module QA
# @param [String] message
# @return [void]
def log(level, message)
- QA::Runtime::Logger.public_send(level, "influxdb exporter: #{message}")
+ QA::Runtime::Logger.public_send(level, "[influxdb exporter]: #{message}")
end
# Return non empty environment variable value
@@ -170,6 +196,33 @@ module QA
def devops_stage(file_path)
file_path.match(%r{\d{1,2}_(\w+)/})&.captures&.first
end
+
+ # InfluxDb client
+ #
+ # @return [InfluxDB2::WriteApi]
+ def influx_client
+ @influx_client ||= InfluxDB2::Client.new(
+ influxdb_url,
+ influxdb_token,
+ bucket: 'e2e-test-stats',
+ org: 'gitlab-qa',
+ precision: InfluxDB2::WritePrecision::NANOSECOND
+ ).create_write_api
+ end
+
+ # InfluxDb instance url
+ #
+ # @return [String]
+ def influxdb_url
+ @influxdb_url ||= env('QA_INFLUXDB_URL')
+ end
+
+ # Influxdb token
+ #
+ # @return [String]
+ def influxdb_token
+ @influxdb_token ||= env('QA_INFLUXDB_TOKEN')
+ end
end
end
end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index f5299ed840d..b402639b843 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -4,6 +4,8 @@ module QA
module Support
module Page
module Logging
+ using Rainbow
+
def assert_no_element(name)
log("asserting no element :#{name}")
@@ -17,7 +19,7 @@ module QA
end
def scroll_to(selector, text: nil)
- msg = "scrolling to :#{selector}"
+ msg = "scrolling to :#{Rainbow(selector).underline.bright}"
msg += " with text: #{text}" if text
log(msg)
@@ -37,7 +39,7 @@ module QA
element = super
- log("found :#{name}") if element
+ log("found :#{Rainbow(name).underline.bright}")
element
end
@@ -47,7 +49,7 @@ module QA
elements = super
- log("found #{elements.size} :#{name}") if elements
+ log("found #{elements.size} :#{Rainbow(name).underline.bright}") if elements
elements
end
@@ -71,7 +73,7 @@ module QA
end
def click_element(name, page = nil, **kwargs)
- msg = ["clicking :#{name}"]
+ msg = ["clicking :#{Rainbow(name).underline.bright}"]
msg << ", expecting to be at #{page.class}" if page
msg << "with args #{kwargs}"
@@ -170,7 +172,7 @@ module QA
end
def log_has_element_or_not(method, name, found, **kwargs)
- msg = ["#{method} :#{name}"]
+ msg = ["#{method} :#{Rainbow(name).underline.bright}"]
msg << %Q(with text "#{kwargs[:text]}") if kwargs[:text]
msg << "class: #{kwargs[:class]}" if kwargs[:class]
msg << "(wait: #{kwargs[:wait] || Capybara.default_max_wait_time})"
diff --git a/qa/qa/support/repeater.rb b/qa/qa/support/repeater.rb
index a4e8035f964..1b9aa809051 100644
--- a/qa/qa/support/repeater.rb
+++ b/qa/qa/support/repeater.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: true
-
require 'active_support/inflector'
+require 'rainbow/refinement'
module QA
module Support
module Repeater
+ using Rainbow
DEFAULT_MAX_WAIT_TIME = 60
RepeaterConditionExceededError = Class.new(RuntimeError)
@@ -39,7 +40,7 @@ module QA
QA::Runtime::Logger.debug(msg.join(' '))
end
- QA::Runtime::Logger.debug("Attempt number #{attempts + 1}") if log && max_attempts && attempts > 0
+ QA::Runtime::Logger.debug("Attempt number #{attempts + 1}".bg(:yellow).black) if log && max_attempts && attempts > 0
result = yield
if result
diff --git a/qa/qa/tools/delete_test_resources.rb b/qa/qa/tools/delete_test_resources.rb
index 917cb2fa992..6f63c56f736 100644
--- a/qa/qa/tools/delete_test_resources.rb
+++ b/qa/qa/tools/delete_test_resources.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-# This script reads from test_resources.txt file to collect data about resources to delete
-# Deletes all deletable resources that E2E tests created
-# Resource type: Sandbox, User, Fork and RSpec::Mocks::Double are not included
+# This script reads from test-resources JSON file to collect data about resources to delete
+# Filter out resources that cannot be deleted
+# Then deletes all deletable resources that E2E tests created
#
# Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
# When in CI also requires: QA_TEST_RESOURCES_FILE_PATTERN
@@ -13,7 +13,15 @@ module QA
class DeleteTestResources
include Support::API
- def initialize(file_pattern = nil)
+ IGNORED_RESOURCES = [
+ 'QA::Resource::PersonalAccessToken',
+ 'QA::Resource::CiVariable',
+ 'QA::Resource::Repository::Commit',
+ 'QA::EE::Resource::GroupIteration',
+ 'QA::EE::Resource::Settings::Elasticsearch'
+ ].freeze
+
+ def initialize(file_pattern = Runtime::Env.test_resources_created_filepath)
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN" unless ENV['GITLAB_QA_ACCESS_TOKEN']
@@ -22,45 +30,58 @@ module QA
end
def run
- puts 'Deleting test created resources...'
-
- if Runtime::Env.running_in_ci?
- raise ArgumentError, 'Please provide QA_TEST_RESOURCES_FILE_PATTERN' unless ENV['QA_TEST_RESOURCES_FILE_PATTERN']
-
- Dir.glob(@file_pattern).each do |file|
- delete_resources(load_file(file))
- end
- else
- file = Runtime::Env.test_resources_created_filepath
- raise ArgumentError, "'#{file}' either does not exist or empty." if !File.exist?(file) || File.zero?(file)
-
- delete_resources(load_file(file))
+ failures = files.flat_map do |file|
+ resources = read_file(file)
+ filtered_resources = filter_resources(resources)
+ delete_resources(filtered_resources)
end
- puts "\nDone"
+ return puts "\nDone" if failures.empty?
+
+ puts "\nFailed to delete #{failures.size} resources:\n"
+ puts failures
end
private
- def load_file(json)
- JSON.parse(File.read(json))
+ def files
+ puts "Gathering JSON files...\n"
+ files = Dir.glob(@file_pattern)
+ abort("There is no file with this pattern #{@file_pattern}") if files.empty?
+
+ files.reject { |file| File.zero?(file) }
+
+ files
end
- def delete_resources(resources)
- failures = []
+ def read_file(file)
+ JSON.parse(File.read(file))
+ end
- resources.each_key do |type|
- next if resources[type].empty?
+ def filter_resources(resources)
+ puts "Filtering resources - Only keep deletable resources...\n"
- resources[type].each do |resource|
- next if resource_not_found?(resource['api_path'])
+ transformed_values = resources.transform_values! do |v|
+ v.reject do |attributes|
+ attributes['info'] == "with full_path 'gitlab-qa-sandbox-group'" ||
+ attributes['http_method'] == 'get' && !attributes['info']&.include?("with username 'qa-") ||
+ attributes['api_path'] == 'Cannot find resource API path'
+ end
+ end
+
+ transformed_values.reject! { |k, v| v.empty? || IGNORED_RESOURCES.include?(k) }
+ end
- msg = resource['info'] ? "#{type} - #{resource['info']}" : "#{type} at #{resource['api_path']}"
+ def delete_resources(resources)
+ resources.each_with_object([]) do |(key, value), failures|
+ value.each do |resource|
+ next if resource_not_found?(resource['api_path'])
+ msg = resource['info'] ? "#{key} - #{resource['info']}" : "#{key} at #{resource['api_path']}"
puts "\nDeleting #{msg}..."
delete_response = delete(Runtime::API::Request.new(@api_client, resource['api_path']).url)
- if delete_response.code == 202
+ if delete_response.code == 202 || delete_response.code == 204
print "\e[32m.\e[0m"
else
print "\e[31mF\e[0m"
@@ -68,17 +89,11 @@ module QA
end
end
end
-
- unless failures.empty?
- puts "\nFailed to delete #{failures.length} resources:\n"
- puts failures
- end
end
def resource_not_found?(api_path)
- get_response = get Runtime::API::Request.new(@api_client, api_path).url
-
- get_response.code.eql? 404
+ # if api path contains param "?hard_delete=<boolean>", remove it
+ get(Runtime::API::Request.new(@api_client, api_path.split('?').first).url).code.eql? 404
end
end
end
diff --git a/qa/qa/tools/initialize_gitlab_auth.rb b/qa/qa/tools/initialize_gitlab_auth.rb
index 86791f1f624..18e90f0d739 100644
--- a/qa/qa/tools/initialize_gitlab_auth.rb
+++ b/qa/qa/tools/initialize_gitlab_auth.rb
@@ -16,7 +16,7 @@ module QA
def run
Runtime::Scenario.define(:gitlab_address, address)
- puts "Signing in and creating the default password for the root user if it's not set already..."
+ QA::Runtime::Logger.info("Signing in and creating the default password for the root user if it's not set already...")
QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login)
Flow::Login.sign_in
diff --git a/qa/qa/tools/reliable_report.rb b/qa/qa/tools/reliable_report.rb
index b99b97c1ea6..27e54c2d8bf 100644
--- a/qa/qa/tools/reliable_report.rb
+++ b/qa/qa/tools/reliable_report.rb
@@ -58,7 +58,7 @@ module QA
{
title: "Reliable e2e test report",
description: report_issue_body,
- labels: "Quality,test,type::maintenance,reliable test report"
+ labels: "Quality,test,type::maintenance,reliable test report,automation:devops-mapping-disable"
},
headers: { "PRIVATE-TOKEN" => gitlab_access_token }
)
diff --git a/qa/qa/tools/test_resource_data_processor.rb b/qa/qa/tools/test_resource_data_processor.rb
index 78fb6ef6cd0..965919dc516 100644
--- a/qa/qa/tools/test_resource_data_processor.rb
+++ b/qa/qa/tools/test_resource_data_processor.rb
@@ -6,60 +6,81 @@
module QA
module Tools
class TestResourceDataProcessor
- @resources ||= Hash.new { |hsh, key| hsh[key] = [] }
+ include Singleton
+
+ def initialize
+ @resources = Hash.new { |hsh, key| hsh[key] = [] }
+ end
class << self
- # Ignoring rspec-mocks, sandbox, user and fork resources
- # TODO: Will need to figure out which user resources can be collected, ignore for now
- #
- # Collecting resources created in E2E tests
- # Data is a Hash of resources with keys as resource type (group, project, issue, etc.)
- # Each type contains an array of resource object (hash) of the same type
- # E.g: { "QA::Resource::Project": [ { info: 'foo', api_path: '/foo'}, {...} ] }
- def collect(resource, info)
- return if resource.api_response.nil? ||
- resource.is_a?(RSpec::Mocks::Double) ||
- resource.is_a?(Resource::Sandbox) ||
- resource.is_a?(Resource::User) ||
- resource.is_a?(Resource::Fork)
+ delegate :collect, :write_to_file, :resources, to: :instance
+ end
- api_path = if resource.respond_to?(:api_delete_path)
- resource.api_delete_path.gsub('%2F', '/')
- elsif resource.respond_to?(:api_get_path)
- resource.api_get_path.gsub('%2F', '/')
- else
- 'Cannot find resource API path'
- end
+ # @return [Hash<String, Array>]
+ attr_reader :resources
- type = resource.class.name
+ # Collecting resources created in E2E tests
+ # Data is a Hash of resources with keys as resource type (group, project, issue, etc.)
+ # Each type contains an array of resource object (hash) of the same type
+ # E.g: { "QA::Resource::Project": [ { info: 'foo', api_path: '/foo'}, {...} ] }
+ #
+ # @param [QA::Resource::Base] resource fabricated resource
+ # @param [String] info resource info
+ # @param [Symbol] method fabrication method, api or browser_ui
+ # @param [Integer] time fabrication time
+ # @return [Hash]
+ def collect(resource:, info:, fabrication_method:, fabrication_time:)
+ api_path = resource_api_path(resource)
+ type = resource.class.name
- @resources[type] << { info: info, api_path: api_path }
- end
+ resources[type] << {
+ info: info,
+ api_path: api_path,
+ fabrication_method: fabrication_method,
+ fabrication_time: fabrication_time,
+ http_method: resource.api_fabrication_http_method,
+ timestamp: Time.now.to_s
+ }
+ end
+
+ # If JSON file exists and not empty, read and load file content
+ # Merge what is saved in @resources into the content from file
+ # Overwrite file content with the new data hash
+ # Otherwise create file and write data hash to file for the first time
+ #
+ # @return [void]
+ def write_to_file
+ return if resources.empty?
- # If JSON file exists and not empty, read and load file content
- # Merge what is saved in @resources into the content from file
- # Overwrite file content with the new data hash
- # Otherwise create file and write data hash to file for the first time
- def write_to_file
- return if @resources.empty?
+ file = Pathname.new(Runtime::Env.test_resources_created_filepath)
+ FileUtils.mkdir_p(file.dirname)
- file = Runtime::Env.test_resources_created_filepath
- FileUtils.mkdir_p('tmp/')
- FileUtils.touch(file)
- data = nil
+ data = resources.deep_dup
+ # merge existing json if present
+ JSON.parse(File.read(file)).deep_merge!(data) { |key, val, other_val| val + other_val } if file.exist?
+
+ File.write(file, JSON.pretty_generate(data))
+ end
- if File.zero?(file)
- data = @resources
- else
- data = JSON.parse(File.read(file))
+ private
- @resources.each_pair do |key, val|
- data[key].nil? ? data[key] = val : val.each { |item| data[key] << item }
- end
- end
+ # Determine resource api path or return default value
+ # Some resources fabricated via UI can raise no attribute error
+ #
+ # @param [QA::Resource::Base] resource
+ # @return [String]
+ def resource_api_path(resource)
+ default = 'Cannot find resource API path'
- File.open(file, 'w') { |f| f.write(JSON.pretty_generate(data.each_value(&:uniq!))) }
+ if resource.respond_to?(:api_delete_path)
+ resource.api_delete_path.gsub('%2F', '/')
+ elsif resource.respond_to?(:api_get_path)
+ resource.api_get_path.gsub('%2F', '/')
+ else
+ default
end
+ rescue QA::Resource::Base::NoValueError
+ default
end
end
end
diff --git a/qa/qa/vendor/smocker/event_payload.rb b/qa/qa/vendor/smocker/event_payload.rb
new file mode 100644
index 00000000000..4bf154b76c2
--- /dev/null
+++ b/qa/qa/vendor/smocker/event_payload.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Smocker
+ class EventPayload
+ def initialize(hook_data)
+ @hook_data = hook_data
+ end
+
+ def raw
+ @hook_data
+ end
+
+ def event
+ raw[:object_kind]&.to_sym
+ end
+
+ def project_name
+ raw.dig(:project, :name)
+ end
+
+ def mr?
+ event == :merge_request
+ end
+
+ def issue?
+ event == :issue
+ end
+
+ def note?
+ event == :note
+ end
+
+ def push?
+ event == :push
+ end
+
+ def tag?
+ event == :tag
+ end
+
+ def wiki?
+ event == :wiki_page
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/smocker/history_response.rb b/qa/qa/vendor/smocker/history_response.rb
new file mode 100644
index 00000000000..53d5759ef8b
--- /dev/null
+++ b/qa/qa/vendor/smocker/history_response.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require_relative './event_payload'
+require 'time'
+
+module QA
+ module Vendor
+ module Smocker
+ class HistoryResponse
+ attr_reader :payload
+
+ def initialize(payload)
+ @payload = payload
+ end
+
+ # Smocker context including call counter
+ def context
+ payload[:context]
+ end
+
+ # Smocker request data
+ def request
+ payload[:request]
+ end
+
+ # @return [EventPayload] the request body as a webhook event
+ def as_hook_event
+ body = request&.dig(:body)
+ EventPayload.new body if body
+ end
+
+ # @return [Time] Time request was recieved
+ def received
+ date = request&.dig(:date)
+ Time.parse date if date
+ end
+
+ # Find time elapsed since <target>
+ #
+ # @param target [Time] target time
+ # @return [Integer] seconds elapsed since <target>
+ def elapsed(target)
+ (received.to_f - target.to_f).round if received
+ end
+
+ def response
+ payload[:response]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/smocker/smocker_api.rb b/qa/qa/vendor/smocker/smocker_api.rb
new file mode 100644
index 00000000000..3f595b58886
--- /dev/null
+++ b/qa/qa/vendor/smocker/smocker_api.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Smocker
+ class SmockerApi
+ include Scenario::Actable
+ include Support::API
+
+ DEFAULT_MOCK = <<~YAML
+ - request:
+ method: POST
+ path: /default
+ response:
+ headers:
+ Content-Type: application/json
+ body: '{}'
+ YAML
+
+ # @param wait [Integer] seconds to wait for server
+ # @yieldparam [SmockerApi] the api object ready for interaction
+ def self.init(**wait_args)
+ if @container.nil?
+ @container = Service::DockerRun::Smocker.new
+ @container.register!
+ @container.wait_for_running
+ end
+
+ yield new(@container, **wait_args)
+ end
+
+ def self.teardown!
+ @container&.remove!
+ end
+
+ def initialize(container, **wait_args)
+ @container = container
+ wait_for_ready(**wait_args)
+ end
+
+ # @return [String] Base url of mock endpoint
+ def base_url
+ @container.base_url
+ end
+
+ # @return [String] Url of admin endpoint
+ def admin_url
+ @container.admin_url
+ end
+
+ # @param endpoint [String] path for mock endpoint
+ # @return [String] url for mock endpoint
+ def url(endpoint = 'default')
+ "#{base_url}/#{endpoint}"
+ end
+
+ # Waits for the smocker server to be ready
+ #
+ # @param wait [Integer] wait duration for smocker readiness
+ def wait_for_ready(wait: 10)
+ Support::Waiter.wait_until(max_duration: wait, reload_page: false, raise_on_failure: true) do
+ ready?
+ end
+ end
+
+ # Is smocker server ready for interaction?
+ #
+ # @return [Boolean]
+ def ready?
+ QA::Runtime::Logger.debug 'Checking Smocker readiness'
+ get("#{admin_url}/version")
+ true
+ # rescuing StandardError because RestClient::ExceptionWithResponse isn't propagating
+ rescue StandardError => e
+ QA::Runtime::Logger.debug "Smocker not ready yet \n #{e}"
+ false
+ end
+
+ # Clears mocks and history
+ #
+ # @param force [Boolean] remove locked mocks?
+ # @return [Boolean] reset was successful?
+ def reset(force: true)
+ response = post("#{admin_url}/reset?force=#{force}", {}.to_json)
+ parse_body(response)['message'] == 'Reset successful'
+ end
+
+ # Fetches an active session id from a name
+ #
+ # @param name [String] the name of the session
+ # @return [String] the unique session id
+ def get_session_id(name)
+ sessions = parse_body get("#{admin_url}/sessions/summary")
+ current = sessions.find do |session|
+ session[:name] == name
+ end
+ current&.dig(:id)
+ end
+
+ # Registers a mock to Smocker
+ # If a session name is provided, the mock will register to that session
+ # https://smocker.dev/technical-documentation/mock-definition.html
+ #
+ # @param yaml [String] the yaml representing the mock
+ # @param session [String] the session name for the mock
+ def register(yaml = DEFAULT_MOCK, session: nil)
+ query_params = build_params(session: session)
+ url = "#{admin_url}/mocks?#{query_params}"
+ headers = { 'Content-Type' => 'application/x-yaml' }
+ response = post(url, yaml, headers: headers)
+ parse_body(response)
+ end
+
+ # Fetches call history for a mock
+ #
+ # @param session_name [String] the session name for the mock
+ # @return [Array<HistoryResponse>]
+ def history(session_name = nil)
+ query_params = session_name ? build_params(session: get_session_id(session_name)) : ''
+ response = get("#{admin_url}/history?#{query_params}")
+ body = parse_body(response)
+
+ raise body[:message] unless body.is_a?(Array)
+
+ body.map do |entry|
+ HistoryResponse.new(entry)
+ end
+ end
+
+ private
+
+ def build_params(**args)
+ args.each_with_object([]) do |(k, v), memo|
+ memo << "#{k}=#{v}" if v
+ end.join("&")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb
index 2dd25f983bf..eab205ec5d1 100644
--- a/qa/spec/resource/base_spec.rb
+++ b/qa/spec/resource/base_spec.rb
@@ -3,10 +3,45 @@
RSpec.describe QA::Resource::Base do
include QA::Support::Helpers::StubEnv
- let(:resource) { spy('resource', username: 'qa') }
+ let(:resource) { spy('resource') }
let(:location) { 'http://location' }
let(:log_regex) { %r{==> Built a MyResource with username 'qa' via #{method} in [\d.\-e]+ seconds+} }
+ before do
+ allow(QA::Tools::TestResourceDataProcessor).to receive(:collect)
+ allow(QA::Tools::TestResourceDataProcessor).to receive(:write_to_file)
+ end
+
+ shared_context 'with simple resource' do
+ subject do
+ Class.new(QA::Resource::Base) do
+ def self.name
+ 'MyResource'
+ end
+
+ attribute :test do
+ 'block'
+ end
+
+ attribute :username do
+ 'qa'
+ end
+
+ attribute :no_block
+
+ def fabricate!(*args)
+ 'any'
+ end
+
+ def self.current_url
+ 'http://stub'
+ end
+ end
+ end
+
+ let(:resource) { subject.new }
+ end
+
shared_context 'with fabrication context' do
subject do
Class.new(described_class) do
@@ -56,23 +91,29 @@ RSpec.describe QA::Resource::Base do
end
describe '.fabricate_via_api!' do
- include_context 'with fabrication context'
+ context 'when fabricating' do
+ include_context 'with fabrication context'
- it_behaves_like 'fabrication method', :fabricate_via_api!
+ it_behaves_like 'fabrication method', :fabricate_via_api!
- it 'instantiates the resource, calls resource method returns the resource' do
- expect(resource).to receive(:fabricate_via_api!).and_return(location)
+ it 'instantiates the resource, calls resource method returns the resource' do
+ expect(resource).to receive(:fabricate_via_api!).and_return(location)
- result = subject.fabricate_via_api!(resource: resource, parents: [])
+ result = subject.fabricate_via_api!(resource: resource, parents: [])
- expect(result).to eq(resource)
+ expect(result).to eq(resource)
+ end
end
context "with debug log level" do
+ include_context 'with simple resource'
+
let(:method) { 'api' }
before do
allow(QA::Runtime::Logger).to receive(:debug)
+ allow(resource).to receive(:api_support?).and_return(true)
+ allow(resource).to receive(:fabricate_via_api!)
end
it 'logs the resource and build method' do
@@ -88,27 +129,32 @@ RSpec.describe QA::Resource::Base do
end
describe '.fabricate_via_browser_ui!' do
- include_context 'with fabrication context'
+ context 'when fabricating' do
+ include_context 'with fabrication context'
- it_behaves_like 'fabrication method', :fabricate_via_browser_ui!, :fabricate!
+ it_behaves_like 'fabrication method', :fabricate_via_browser_ui!, :fabricate!
- it 'instantiates the resource and calls resource method' do
- subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+ it 'instantiates the resource and calls resource method' do
+ subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
- expect(resource).to have_received(:fabricate!).with('something')
- end
+ expect(resource).to have_received(:fabricate!).with('something')
+ end
- it 'returns fabrication resource' do
- result = subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+ it 'returns fabrication resource' do
+ result = subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
- expect(result).to eq(resource)
+ expect(result).to eq(resource)
+ end
end
context "with debug log level" do
+ include_context 'with simple resource'
+
let(:method) { 'browser_ui' }
before do
allow(QA::Runtime::Logger).to receive(:debug)
+ # allow(resource).to receive(:fabricate!)
end
it 'logs the resource and build method' do
@@ -123,28 +169,6 @@ RSpec.describe QA::Resource::Base do
end
end
- shared_context 'with simple resource' do
- subject do
- Class.new(QA::Resource::Base) do
- attribute :test do
- 'block'
- end
-
- attribute :no_block
-
- def fabricate!
- 'any'
- end
-
- def self.current_url
- 'http://stub'
- end
- end
- end
-
- let(:resource) { subject.new }
- end
-
describe '.attribute' do
include_context 'with simple resource'
diff --git a/qa/spec/resource/reusable_collection_spec.rb b/qa/spec/resource/reusable_collection_spec.rb
new file mode 100644
index 00000000000..9116462b396
--- /dev/null
+++ b/qa/spec/resource/reusable_collection_spec.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+RSpec.describe QA::Resource::ReusableCollection do
+ let(:reusable_resource_class) do
+ Class.new do
+ prepend QA::Resource::Reusable
+
+ attr_reader :removed
+
+ def self.name
+ 'FooReusableResource'
+ end
+
+ def comparable
+ self.class.name
+ end
+
+ def remove_via_api!
+ @removed = true
+ end
+
+ def exists?() end
+ end
+ end
+
+ let(:another_reusable_resource_class) do
+ Class.new(reusable_resource_class) do
+ def self.name
+ 'BarReusableResource'
+ end
+ end
+ end
+
+ let(:a_resource_instance) { reusable_resource_class.new }
+ let(:another_resource_instance) { another_reusable_resource_class.new }
+
+ it 'is a singleton class' do
+ expect { described_class.new }.to raise_error(NoMethodError)
+ end
+
+ subject(:collection) do
+ described_class.instance
+ end
+
+ before do
+ described_class.register_resource_classes do |c|
+ reusable_resource_class.register(c)
+ another_reusable_resource_class.register(c)
+ end
+
+ collection.resource_classes = {
+ 'FooReusableResource' => {
+ reuse_as_identifier: {
+ resource: a_resource_instance
+ }
+ },
+ 'BarReusableResource' => {
+ another_reuse_as_identifier: {
+ resource: another_resource_instance
+ }
+ }
+ }
+
+ allow(a_resource_instance).to receive(:validate_reuse)
+ allow(another_resource_instance).to receive(:validate_reuse)
+ end
+
+ after do
+ collection.resource_classes = {}
+ end
+
+ describe '#each_resource' do
+ it 'yields each resource and reuse_as identifier in the collection' do
+ expect { |blk| collection.each_resource(&blk) }
+ .to yield_successive_args(
+ [:reuse_as_identifier, a_resource_instance],
+ [:another_reuse_as_identifier, another_resource_instance]
+ )
+ end
+ end
+
+ describe '.remove_all_via_api!' do
+ before do
+ allow(a_resource_instance).to receive(:exists?).and_return(true)
+ allow(another_resource_instance).to receive(:exists?).and_return(true)
+ end
+
+ it 'removes each instance of each resource class' do
+ described_class.remove_all_via_api!
+
+ expect(a_resource_instance.removed).to be true
+ expect(another_resource_instance.removed).to be true
+ end
+ end
+
+ describe '.validate_resource_reuse' do
+ it 'validates each instance of each resource class' do
+ expect(a_resource_instance).to receive(:validate_reuse)
+ expect(another_resource_instance).to receive(:validate_reuse)
+
+ described_class.validate_resource_reuse
+ end
+ end
+
+ describe '.register_resource_classes' do
+ it 'yields the hash of resource classes in the collection' do
+ expect { |blk| described_class.register_resource_classes(&blk) }.to yield_with_args(collection.resource_classes)
+ end
+ end
+end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 47791f76970..2a6acd6d014 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -6,6 +6,7 @@ require 'securerandom'
require 'pathname'
require 'active_support/core_ext/hash'
require 'active_support/core_ext/object/blank'
+require 'rainbow/refinement'
require_relative 'qa_deprecation_toolkit_env'
QaDeprecationToolkitEnv.configure!
@@ -27,8 +28,16 @@ RSpec.configure do |config|
config.add_formatter QA::Support::Formatters::QuarantineFormatter
config.add_formatter QA::Support::Formatters::TestStatsFormatter if QA::Runtime::Env.export_metrics?
+ config.before(:suite) do |suite|
+ QA::Resource::ReusableCollection.register_resource_classes do |collection|
+ QA::Resource::ReusableProject.register(collection)
+ QA::Resource::ReusableGroup.register(collection)
+ end
+ end
+
config.prepend_before do |example|
QA::Runtime::Logger.debug("\nStarting test: #{example.full_description}\n")
+ QA::Runtime::Example.current = example
# Reset fabrication counters tracked in resource base
Thread.current[:api_fabrication] = 0
@@ -65,11 +74,15 @@ RSpec.configure do |config|
end
config.after(:suite) do |suite|
- # If any tests failed, leave the resources behind to help troubleshoot
- QA::Resource::ReusableProject.remove_all_via_api! unless suite.reporter.failed_examples.present?
-
# Write all test created resources to JSON file
QA::Tools::TestResourceDataProcessor.write_to_file
+
+ # If requested, confirm that resources were used appropriately (e.g., not left with changes that interfere with
+ # further reuse)
+ QA::Resource::ReusableCollection.validate_resource_reuse if QA::Runtime::Env.validate_resource_reuse?
+
+ # If any tests failed, leave the resources behind to help troubleshoot, otherwise remove them.
+ QA::Resource::ReusableCollection.remove_all_via_api! unless suite.reporter.failed_examples.present?
end
config.append_after(:suite) do
diff --git a/qa/spec/specs/helpers/quarantine_spec.rb b/qa/spec/specs/helpers/quarantine_spec.rb
index 8ea375cdb05..0f2d592d771 100644
--- a/qa/spec/specs/helpers/quarantine_spec.rb
+++ b/qa/spec/specs/helpers/quarantine_spec.rb
@@ -104,6 +104,20 @@ RSpec.describe QA::Specs::Helpers::Quarantine do
end
describe '.skip_or_run_quarantined_tests_or_contexts' do
+ context 'with explicitly disabled quarantine' do
+ before do
+ stub_env('DISABLE_QUARANTINE', 'true')
+ end
+
+ it 'runs quarantined test' do
+ group = describe_successfully do
+ it('is pending', :quarantine) {}
+ end
+
+ expect(group.examples.first.execution_result.status).to eq(:passed)
+ end
+ end
+
context 'with no tag focused' do
it 'skips quarantined tests' do
group = describe_successfully do
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
index 5cc9ff403cd..e52ca1fb17c 100644
--- a/qa/spec/specs/runner_spec.rb
+++ b/qa/spec/specs/runner_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe QA::Specs::Runner do
allow(QA::Runtime::Browser).to receive(:configure!)
QA::Runtime::Scenario.define(:gitlab_address, "http://gitlab.test")
+ QA::Runtime::Scenario.define(:klass, "QA::Scenario::Test::Instance::All")
end
it_behaves_like 'excludes orchestrated, transient, and geo'
@@ -43,6 +44,43 @@ RSpec.describe QA::Specs::Runner do
subject.perform
end
+ it 'writes to file when examples are more than zero' do
+ allow(RSpec::Core::Runner).to receive(:run).and_return(0)
+
+ expect(File).to receive(:open).with('no_of_examples/test_instance_all.txt', 'w') { '22' }
+
+ subject.perform
+ end
+
+ it 'does not write to file when zero examples' do
+ out.string = '0 examples,'
+ allow(RSpec::Core::Runner).to receive(:run).and_return(0)
+
+ expect(File).not_to receive(:open)
+
+ subject.perform
+ end
+
+ it 'raises error when Rspec output does not match regex' do
+ out.string = '0'
+ allow(RSpec::Core::Runner).to receive(:run).and_return(0)
+
+ expect { subject.perform }
+ .to raise_error(QA::Specs::Runner::RegexMismatchError, 'Rspec output did not match regex')
+ end
+
+ context 'when --tag is specified as an option' do
+ subject { described_class.new.tap { |runner| runner.options = %w[--tag actioncable] } }
+
+ it 'includes the option value in the file name' do
+ expect_rspec_runner_arguments(['--dry-run', '--tag', '~geo', '--tag', 'actioncable', *described_class::DEFAULT_TEST_PATH_ARGS], [$stderr, anything])
+
+ expect(File).to receive(:open).with('no_of_examples/test_instance_all_actioncable.txt', 'w') { '22' }
+
+ subject.perform
+ end
+ end
+
after do
QA::Runtime::Scenario.attributes.delete(:count_examples_only)
end
diff --git a/qa/spec/support/formatters/test_stats_formatter_spec.rb b/qa/spec/support/formatters/test_stats_formatter_spec.rb
index 2bfd7863653..84fc3b83185 100644
--- a/qa/spec/support/formatters/test_stats_formatter_spec.rb
+++ b/qa/spec/support/formatters/test_stats_formatter_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
require 'rspec/core/sandbox'
+require 'active_support/testing/time_helpers'
describe QA::Support::Formatters::TestStatsFormatter do
include QA::Support::Helpers::StubEnv
include QA::Specs::Helpers::RSpec
+ include ActiveSupport::Testing::TimeHelpers
let(:url) { "http://influxdb.net" }
let(:token) { "token" }
@@ -22,6 +24,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
let(:file_path) { "./qa/specs/features/#{stage}/subfolder/some_spec.rb" }
let(:ui_fabrication) { 0 }
let(:api_fabrication) { 0 }
+ let(:fabrication_resources) { {} }
let(:influx_client_args) do
{
@@ -45,7 +48,8 @@ describe QA::Support::Formatters::TestStatsFormatter do
job_name: "test-job",
merge_request: "false",
run_type: run_type,
- stage: stage.match(%r{\d{1,2}_(\w+)}).captures.first
+ stage: stage.match(%r{\d{1,2}_(\w+)}).captures.first,
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/1234'
},
fields: {
id: './spec/support/formatters/test_stats_formatter_spec.rb[1:1]',
@@ -56,8 +60,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
retry_attempts: 0,
job_url: ci_job_url,
pipeline_url: ci_pipeline_url,
- pipeline_id: ci_pipeline_id,
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/1234'
+ pipeline_id: ci_pipeline_id
}
}
end
@@ -88,6 +91,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
before do
allow(InfluxDB2::Client).to receive(:new).with(url, token, **influx_client_args) { influx_client }
+ allow(QA::Tools::TestResourceDataProcessor).to receive(:resources) { fabrication_resources }
end
context "without influxdb variables configured" do
@@ -135,6 +139,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
it('spec', :reliable, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/1234') {}
end
+ expect(influx_write_api).to have_received(:write).once
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
@@ -147,6 +152,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
it('spec', :quarantine, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/1234') {}
end
+ expect(influx_write_api).to have_received(:write).once
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
@@ -162,6 +168,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
it 'exports data to influxdb with correct run type' do
run_spec
+ expect(influx_write_api).to have_received(:write).once
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
@@ -179,6 +186,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
it 'exports data to influxdb with correct run type' do
run_spec
+ expect(influx_write_api).to have_received(:write).once
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
@@ -195,8 +203,54 @@ describe QA::Support::Formatters::TestStatsFormatter do
it 'exports data to influxdb with fabrication times' do
run_spec
+ expect(influx_write_api).to have_received(:write).once
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
+
+ context 'with fabrication resources' do
+ let(:fabrication_resources) do
+ {
+ 'QA::Resource::Project' => [{
+ info: "with id '1'",
+ api_path: '/project',
+ fabrication_method: :api,
+ fabrication_time: 1,
+ http_method: :post,
+ timestamp: Time.now.to_s
+ }]
+ }
+ end
+
+ let(:fabrication_data) do
+ {
+ name: 'fabrication-stats',
+ time: DateTime.strptime(ci_timestamp).to_time,
+ tags: {
+ resource: 'QA::Resource::Project',
+ fabrication_method: :api,
+ http_method: :post,
+ run_type: run_type,
+ merge_request: "false"
+ },
+ fields: {
+ fabrication_time: 1,
+ info: "with id '1'",
+ job_url: ci_job_url,
+ timestamp: Time.now.to_s
+ }
+ }
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ it 'exports fabrication stats data to influxdb' do
+ run_spec
+
+ expect(influx_write_api).to have_received(:write).with(data: [fabrication_data])
+ end
+ end
end
end
diff --git a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
index 348176d264b..73a6c2bd99e 100644
--- a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
+++ b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
@@ -32,7 +32,7 @@ module QA
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = ["runner-for-#{package_project.group.name}"]
runner.executor = :docker
- runner.token = package_project.group.runners_token
+ runner.token = package_project.group.reload!.runners_token
end
end
diff --git a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
index 40a8be8202a..4bbad9bf3e5 100644
--- a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
+++ b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
@@ -31,19 +31,13 @@ module QA
end
# Require approval from code owners on the default branch
- # The default branch is already protected, and we can't update a protected branch via the API (yet)
- # so we unprotect it first and then protect it again with the desired parameters
- Resource::ProtectedBranch.unprotect_via_api! do |protected_branch|
- protected_branch.project = project
- protected_branch.branch_name = project.default_branch
- end
-
- Resource::ProtectedBranch.fabricate_via_api! do |protected_branch|
- protected_branch.project = project
- protected_branch.branch_name = project.default_branch
- protected_branch.new_branch = false
- protected_branch.require_code_owner_approval = true
+ protected_branch = Resource::ProtectedBranch.fabricate_via_api! do |branch|
+ branch.project = project
+ branch.branch_name = project.default_branch
+ branch.new_branch = false
+ branch.require_code_owner_approval = true
end
+ protected_branch.set_require_code_owner_approval
# Push a change to the file with a CODEOWNERS rule
Resource::Repository::Push.fabricate! do |push|
diff --git a/qa/spec/tools/reliable_report_spec.rb b/qa/spec/tools/reliable_report_spec.rb
index 1ff62df34e0..85b2590d3aa 100644
--- a/qa/spec/tools/reliable_report_spec.rb
+++ b/qa/spec/tools/reliable_report_spec.rb
@@ -167,7 +167,7 @@ describe QA::Tools::ReliableReport do
payload: {
title: "Reliable e2e test report",
description: issue_body,
- labels: "Quality,test,type::maintenance,reliable test report"
+ labels: "Quality,test,type::maintenance,reliable test report,automation:devops-mapping-disable"
}
)
expect(slack_notifier).to have_received(:post).with(
diff --git a/qa/spec/tools/test_resources_data_processor_spec.rb b/qa/spec/tools/test_resources_data_processor_spec.rb
index 6a8c0fd06a4..5117d1d367f 100644
--- a/qa/spec/tools/test_resources_data_processor_spec.rb
+++ b/qa/spec/tools/test_resources_data_processor_spec.rb
@@ -1,33 +1,60 @@
# frozen_string_literal: true
+require 'active_support/testing/time_helpers'
+
RSpec.describe QA::Tools::TestResourceDataProcessor do
+ include QA::Support::Helpers::StubEnv
+ include ActiveSupport::Testing::TimeHelpers
+
+ subject(:processor) { Class.new(described_class).instance }
+
let(:info) { 'information' }
- let(:api_path) { '/foo' }
- let(:result) { [{ info: info, api_path: api_path }] }
+ let(:api_response) { {} }
+ let(:method) { :api }
+ let(:time) { 2 }
+ let(:api_path) { resource.api_delete_path }
+ let(:resource) { QA::Resource::Project.init { |project| project.id = 1 } }
- describe '.collect' do
- context 'when resource is not restricted' do
- let(:resource) { instance_double(QA::Resource::Project, api_delete_path: '/foo', api_response: 'foo') }
+ let(:result) do
+ {
+ 'QA::Resource::Project' => [{
+ info: info,
+ api_path: api_path,
+ fabrication_method: method,
+ fabrication_time: time,
+ http_method: :post,
+ timestamp: Time.now.to_s
+ }]
+ }
+ end
+
+ before do
+ processor.collect(resource: resource, info: info, fabrication_method: method, fabrication_time: time)
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
- it 'collects resource' do
- expect(described_class.collect(resource, info)).to eq(result)
- end
+ describe '.collect' do
+ it 'collects and stores resource' do
+ expect(processor.resources).to eq(result)
end
+ end
+
+ describe '.write_to_file' do
+ let(:resources_file) { Pathname.new(Faker::File.file_name(dir: 'tmp', ext: 'json')) }
- context 'when resource api response is nil' do
- let(:resource) { double(QA::Resource::Project, api_delete_path: '/foo', api_response: nil) }
+ before do
+ stub_env('QA_TEST_RESOURCES_CREATED_FILEPATH', resources_file)
- it 'does not collect resource' do
- expect(described_class.collect(resource, info)).to eq(nil)
- end
+ allow(File).to receive(:write)
end
- context 'when resource is restricted' do
- let(:resource) { double(QA::Resource::Sandbox, api_delete_path: '/foo', api_response: 'foo') }
+ it 'writes applicable resources to file' do
+ processor.write_to_file
- it 'does not collect resource' do
- expect(described_class.collect(resource, info)).to eq(nil)
- end
+ expect(File).to have_received(:write).with(resources_file, JSON.pretty_generate(result))
end
end
end
diff --git a/rubocop/cop/file_decompression.rb b/rubocop/cop/file_decompression.rb
new file mode 100644
index 00000000000..44813244028
--- /dev/null
+++ b/rubocop/cop/file_decompression.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ # Check for symlinks when extracting files to avoid arbitrary file reading.
+ class FileDecompression < RuboCop::Cop::Cop
+ MSG = <<~EOF
+ While extracting files check for symlink to avoid arbitrary file reading.
+ https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6132
+ EOF
+
+ def_node_matcher :system?, <<~PATTERN
+ (send {nil? | const} {:system | :exec | :spawn | :popen}
+ (str $_))
+ PATTERN
+
+ def_node_matcher :subshell?, <<~PATTERN
+ (xstr
+ (str $_))
+ PATTERN
+
+ FORBIDDEN_COMMANDS = %w[gunzip gzip zip tar].freeze
+
+ def on_xstr(node)
+ subshell?(node) do |match|
+ add_offense(node, message: MSG) if forbidden_command?(match)
+ end
+ end
+
+ def on_send(node)
+ system?(node) do |match|
+ add_offense(node, location: :expression, message: MSG) if forbidden_command?(match)
+ end
+ end
+
+ private
+
+ def forbidden_command?(cmd)
+ FORBIDDEN_COMMANDS.any? do |forbidden|
+ cmd.match?(forbidden)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/event_store_subscriber.rb b/rubocop/cop/gitlab/event_store_subscriber.rb
new file mode 100644
index 00000000000..0b2dd94bc42
--- /dev/null
+++ b/rubocop/cop/gitlab/event_store_subscriber.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that checks the implementation of Gitlab::EventStore::Subscriber
+ #
+ # A worker that implements Gitlab::EventStore::Subscriber
+ # must implement the method #handle_event(event) and
+ # must not override the method #perform(*args)
+ #
+ # # bad
+ # class MySubscriber
+ # include Gitlab::EventStore::Subscriber
+ #
+ # def perform(*args)
+ # end
+ # end
+ #
+ # # bad
+ # class MySubscriber
+ # include Gitlab::EventStore::Subscriber
+ # end
+ #
+ # # good
+ # class MySubscriber
+ # include Gitlab::EventStore::Subscriber
+ #
+ # def handle_event(event)
+ # end
+ # end
+ #
+ class EventStoreSubscriber < RuboCop::Cop::Cop
+ SUBSCRIBER_MODULE_NAME = 'Gitlab::EventStore::Subscriber'
+ FORBID_PERFORM_OVERRIDE = "Do not override `perform` in a `#{SUBSCRIBER_MODULE_NAME}`."
+ REQUIRE_HANDLE_EVENT = "A `#{SUBSCRIBER_MODULE_NAME}` must implement `#handle_event(event)`."
+
+ def_node_matcher :includes_subscriber?, <<~PATTERN
+ (send nil? :include (const (const (const nil? :Gitlab) :EventStore) :Subscriber))
+ PATTERN
+
+ def on_send(node)
+ return unless includes_subscriber?(node)
+
+ self.is_subscriber ||= true
+ self.include_subscriber_node ||= node
+ end
+
+ def on_def(node)
+ if is_subscriber && node.method_name == :perform
+ add_offense(node, message: FORBID_PERFORM_OVERRIDE)
+ end
+
+ self.implements_handle_event ||= true if node.method_name == :handle_event
+ end
+
+ def on_investigation_end
+ super
+
+ if is_subscriber && !implements_handle_event
+ add_offense(include_subscriber_node, message: REQUIRE_HANDLE_EVENT)
+ end
+ end
+
+ private
+
+ attr_accessor :is_subscriber, :include_subscriber_node, :implements_handle_event
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index 4d9fc6148fa..7e01c2765c9 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -44,7 +44,9 @@ module RuboCop
DYNAMIC_FEATURE_FLAGS = [
:usage_data_static_site_editor_commits, # https://gitlab.com/gitlab-org/gitlab/-/issues/284082
- :usage_data_static_site_editor_merge_requests # https://gitlab.com/gitlab-org/gitlab/-/issues/284083
+ :usage_data_static_site_editor_merge_requests, # https://gitlab.com/gitlab-org/gitlab/-/issues/284083
+ :usage_data_users_clicking_license_testing_visiting_external_website, # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77866
+ :usage_data_users_visiting_testing_license_compliance_full_report # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77866
].freeze
class << self
diff --git a/rubocop/cop/migration/schedule_async.rb b/rubocop/cop/migration/schedule_async.rb
index f31bfa46aa7..4fdedecdf64 100644
--- a/rubocop/cop/migration/schedule_async.rb
+++ b/rubocop/cop/migration/schedule_async.rb
@@ -16,14 +16,23 @@ module RuboCop
MSG
def_node_matcher :calls_background_migration_worker?, <<~PATTERN
- (send (const nil? :BackgroundMigrationWorker) {:perform_async :perform_in :bulk_perform_async :bulk_perform_in} ... )
+ (send (const {cbase nil?} :BackgroundMigrationWorker) #perform_method? ...)
+ PATTERN
+
+ def_node_matcher :calls_ci_database_worker?, <<~PATTERN
+ (send (const {(const {cbase nil?} :BackgroundMigration) nil?} :CiDatabaseWorker) #perform_method? ...)
+ PATTERN
+
+ def_node_matcher :perform_method?, <<~PATTERN
+ {:perform_async :bulk_perform_async :perform_in :bulk_perform_in}
PATTERN
def on_send(node)
return unless in_migration?(node)
return if version(node) < ENFORCED_SINCE
+ return unless calls_background_migration_worker?(node) || calls_ci_database_worker?(node)
- add_offense(node, location: :expression) if calls_background_migration_worker?(node)
+ add_offense(node, location: :expression)
end
end
end
diff --git a/rubocop/cop/scalability/bulk_perform_with_context.rb b/rubocop/cop/scalability/bulk_perform_with_context.rb
index 3c5d7f39680..b96aa35bfee 100644
--- a/rubocop/cop/scalability/bulk_perform_with_context.rb
+++ b/rubocop/cop/scalability/bulk_perform_with_context.rb
@@ -23,6 +23,8 @@ module RuboCop
Read more about it https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#worker-context
MSG
+ BACKGROUND_MIGRATION_WORKER_NAMES = %w[BackgroundMigrationWorker CiDatabaseWorker].freeze
+
def_node_matcher :schedules_in_batch_without_context?, <<~PATTERN
(send (...) {:bulk_perform_async :bulk_perform_in} _*)
PATTERN
@@ -30,7 +32,7 @@ module RuboCop
def on_send(node)
return if in_migration?(node) || in_spec?(node)
return unless schedules_in_batch_without_context?(node)
- return if name_of_receiver(node) == "BackgroundMigrationWorker"
+ return if scheduled_for_background_migration?(node)
add_offense(node, location: :expression)
end
@@ -40,6 +42,10 @@ module RuboCop
def in_spec?(node)
file_path_for_node(node).end_with?("_spec.rb")
end
+
+ def scheduled_for_background_migration?(node)
+ BACKGROUND_MIGRATION_WORKER_NAMES.include?(name_of_receiver(node))
+ end
end
end
end
diff --git a/rubocop/cop/scalability/cron_worker_context.rb b/rubocop/cop/scalability/cron_worker_context.rb
index 8e754af4dcf..3cc0d42d7bc 100644
--- a/rubocop/cop/scalability/cron_worker_context.rb
+++ b/rubocop/cop/scalability/cron_worker_context.rb
@@ -11,7 +11,7 @@ module RuboCop
If there is no relevant metadata, please disable the cop with a comment
explaining this.
- Read more about it https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#worker-context
+ Read more about it https://docs.gitlab.com/ee/development/sidekiq/logging.html#worker-context
MSG
def_node_matcher :includes_cronjob_queue?, <<~PATTERN
diff --git a/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication.rb b/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication.rb
deleted file mode 100644
index e8b4b513a23..00000000000
--- a/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../code_reuse_helpers'
-
-module RuboCop
- module Cop
- module SidekiqLoadBalancing
- # This cop checks for including_scheduled: true option in idempotent Sidekiq workers that utilize load balancing capabilities.
- #
- # @example
- #
- # # bad
- # class BadWorker
- # include ApplicationWorker
- #
- # data_consistency :delayed
- # idempotent!
- #
- # def perform
- # end
- # end
- #
- # # bad
- # class BadWorker
- # include ApplicationWorker
- #
- # data_consistency :delayed
- #
- # deduplicate :until_executing
- # idempotent!
- #
- # def perform
- # end
- # end
- #
- # # good
- # class GoodWorker
- # include ApplicationWorker
- #
- # data_consistency :delayed
- #
- # deduplicate :until_executing, including_scheduled: true
- # idempotent!
- #
- # def perform
- # end
- # end
- #
- class WorkerDataConsistencyWithDeduplication < RuboCop::Cop::Base
- include CodeReuseHelpers
- extend AutoCorrector
-
- HELP_LINK = 'https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#scheduling-jobs-in-the-future'
- REPLACEMENT = ', including_scheduled: true'
- DEFAULT_STRATEGY = ':until_executing'
-
- MSG = <<~MSG
- Workers that declare either `:sticky` or `:delayed` data consistency become eligible for database load-balancing.
- In both cases, jobs are enqueued with a short delay.
-
- If you do want to deduplicate jobs that utilize load-balancing, you need to specify including_scheduled: true
- argument when defining deduplication strategy.
-
- See #{HELP_LINK} for a more detailed explanation of these settings.
- MSG
-
- def_node_search :application_worker?, <<~PATTERN
- `(send nil? :include (const nil? :ApplicationWorker))
- PATTERN
-
- def_node_search :idempotent_worker?, <<~PATTERN
- `(send nil? :idempotent!)
- PATTERN
-
- def_node_search :data_consistency_defined?, <<~PATTERN
- `(send nil? :data_consistency (sym {:sticky :delayed }))
- PATTERN
-
- def_node_matcher :including_scheduled?, <<~PATTERN
- `(hash <(pair (sym :including_scheduled) (%1)) ...>)
- PATTERN
-
- def_node_matcher :deduplicate_strategy?, <<~PATTERN
- `(send nil? :deduplicate (sym $_) $(...)?)
- PATTERN
-
- def on_class(node)
- return unless in_worker?(node)
- return unless application_worker?(node)
- return unless idempotent_worker?(node)
- return unless data_consistency_defined?(node)
-
- @strategy, options = deduplicate_strategy?(node)
- including_scheduled = false
- if options
- @deduplicate_options = options[0]
- including_scheduled = including_scheduled?(@deduplicate_options, :true) # rubocop:disable Lint/BooleanSymbol
- end
-
- @offense = !(including_scheduled || @strategy == :none)
- end
-
- def on_send(node)
- return unless offense
-
- if node.children[1] == :deduplicate
- add_offense(node.loc.expression) do |corrector|
- autocorrect_deduplicate_strategy(node, corrector)
- end
- elsif node.children[1] == :idempotent! && !strategy
- add_offense(node.loc.expression) do |corrector|
- autocorrect_missing_deduplicate_strategy(node, corrector)
- end
- end
- end
-
- private
-
- attr_reader :offense, :deduplicate_options, :strategy
-
- def autocorrect_deduplicate_with_options(corrector)
- if including_scheduled?(deduplicate_options, :false) # rubocop:disable Lint/BooleanSymbol
- replacement = deduplicate_options.source.sub("including_scheduled: false", "including_scheduled: true")
- corrector.replace(deduplicate_options.loc.expression, replacement)
- else
- corrector.insert_after(deduplicate_options.loc.expression, REPLACEMENT)
- end
- end
-
- def autocorrect_deduplicate_without_options(node, corrector)
- corrector.insert_after(node.loc.expression, REPLACEMENT)
- end
-
- def autocorrect_missing_deduplicate_strategy(node, corrector)
- indent_found = node.source_range.source_line =~ /^( +)/
- # Get indentation size
- whitespaces = Regexp.last_match(1).size if indent_found
- replacement = "deduplicate #{DEFAULT_STRATEGY}#{REPLACEMENT}\n"
- # Add indentation in the end since we are inserting a whole line before idempotent!
- replacement += ' ' * whitespaces.to_i
- corrector.insert_before(node.source_range, replacement)
- end
-
- def autocorrect_deduplicate_strategy(node, corrector)
- if deduplicate_options
- autocorrect_deduplicate_with_options(corrector)
- else
- autocorrect_deduplicate_without_options(node, corrector)
- end
- end
- end
- end
- end
-end
diff --git a/scripts/decomposition/generate-loose-foreign-key b/scripts/decomposition/generate-loose-foreign-key
new file mode 100755
index 00000000000..35f84c64ce1
--- /dev/null
+++ b/scripts/decomposition/generate-loose-foreign-key
@@ -0,0 +1,405 @@
+#!/usr/bin/env -S ENABLE_SPRING=0 bin/rails runner -e test
+
+# This is helper script to swap foreign key to loose foreign key
+# using DB schema
+
+require 'optparse'
+
+$options = {
+ milestone: "#{Gitlab.version_info.major}.#{Gitlab.version_info.minor}",
+ cross_schema: false,
+ dry_run: false,
+ branch: true,
+ rspec: true
+}
+
+OptionParser.new do |opts|
+ opts.banner = "Usage: #{$0} [options] <filters...>"
+
+ opts.on("-c", "--cross-schema", "Show only cross-schema foreign keys") do |v|
+ $options[:cross_schema] = v
+ end
+
+ opts.on("-n", "--dry-run", "Do not execute any commands (dry run)") do |v|
+ $options[:dry_run] = v
+ end
+
+ opts.on("-b", "--[no-]branch", "Create or not a new branch") do |v|
+ $options[:branch] = v
+ end
+
+ opts.on("-r", "--[no-]rspec", "Create or not a rspecs automatically") do |v|
+ $options[:rspec] = v
+ end
+
+ opts.on("-m", "--milestone MILESTONE", "Specify custom milestone (current: #{$options[:milestone]})") do |v|
+ $options[:milestone] = v
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+end.parse!
+
+unless system("git diff --quiet db/structure.sql")
+ raise "The db/structure.sql is changed. Reset branch or commit changes."
+end
+
+unless system("git diff --quiet")
+ raise "There are uncommitted changes. Commit to continue."
+end
+
+if Gitlab::Database.database_base_models.many?
+ raise 'Cannot run in multiple-databases mode. Use only `main:` in `config/database.yml`.'
+end
+
+puts "Re-creating current test database"
+ActiveRecord::Tasks::DatabaseTasks.drop_current
+ActiveRecord::Tasks::DatabaseTasks.create_current
+ActiveRecord::Tasks::DatabaseTasks.load_schema_current
+ActiveRecord::Tasks::DatabaseTasks.migrate
+ActiveRecord::Migration.check_pending!
+ActiveRecord::Base.connection_pool.disconnect!
+puts
+
+def exec_cmd(*args, fail: nil)
+ # output full command
+ if $options[:dry_run]
+ puts ">> #{args.shelljoin}"
+ return true
+ end
+
+ # truncate up-to 60 chars or first line
+ command = args.shelljoin
+ truncated_command = command.truncate([command.lines.first.length+3, 120].min)
+
+ puts ">> #{truncated_command}"
+ return true if system(*args)
+
+ raise fail if fail
+
+ puts "--------------------------------------------------"
+ puts "This command failed:"
+ puts ">> #{command}"
+ puts "--------------------------------------------------"
+ false
+end
+
+def has_lfk?(definition)
+ Gitlab::Database::LooseForeignKeys.definitions.any? do |lfk_definition|
+ lfk_definition.from_table == definition.from_table &&
+ lfk_definition.to_table == definition.to_table &&
+ lfk_definition.column == definition.column
+ end
+end
+
+def matching_filter?(definition, filters)
+ filters.all? do |filter|
+ definition.from_table.include?(filter) ||
+ definition.to_table.include?(filter) ||
+ definition.column.include?(filter)
+ end
+end
+
+def columns(*args)
+ puts("%5s | %7s | %40s | %20s | %30s | %15s " % args)
+end
+
+def add_definition_to_yaml(definition)
+ content = YAML.load_file(Rails.root.join('config/gitlab_loose_foreign_keys.yml'))
+ table_definitions = content[definition.from_table]
+
+ # insert new entry at random place to avoid conflicts
+ unless table_definitions
+ table_definitions = []
+ insert_idx = rand(content.count+1)
+
+ # insert at a given index in ordered hash
+ content = content.to_a
+ content.insert(insert_idx, [definition.from_table, table_definitions])
+ content = content.to_h
+ end
+
+ on_delete =
+ case definition.on_delete
+ when :cascade
+ 'async_delete'
+ when :nullify
+ 'async_nullify'
+ else
+ raise "Unsupported on_delete behavior: #{definition.on_delete}"
+ end
+
+ yaml_definition = {
+ "table" => definition.to_table,
+ "column" => definition.column,
+ "on_delete" => on_delete
+ }
+
+ # match and update by "table", "column"
+ if existing = table_definitions.pluck("table", "column").index([definition.to_table, definition.column])
+ puts "Updated existing definition from #{table_definitions[existing]} to #{yaml_definition}."
+ table_definitions[existing] = yaml_definition
+ else
+ puts "Add new definition for #{yaml_definition}."
+ table_definitions.append(yaml_definition)
+ end
+
+ # emulate existing formatting
+ File.write(
+ Rails.root.join('config/gitlab_loose_foreign_keys.yml'),
+ content.to_yaml.gsub(/^([- ] )/, ' \1')
+ )
+
+ exec_cmd("git", "add", "config/gitlab_loose_foreign_keys.yml")
+end
+
+def generate_migration(definition)
+ timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
+
+ # db/post_migrate/20220111221516_remove_projects_ci_pending_builds_fk.rb
+
+ migration_name = "db/post_migrate/#{timestamp}_remove_#{definition.to_table}_#{definition.from_table}_#{definition.column}_fk.rb"
+ puts "Writing #{migration_name}"
+
+ content = <<-EOF.strip_heredoc
+ # frozen_string_literal: true
+
+ class Remove#{definition.to_table.camelcase}#{definition.from_table.camelcase}#{definition.column.camelcase}Fk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ return unless foreign_key_exists?(:#{definition.from_table}, :#{definition.to_table}, name: "#{definition.name}")
+
+ with_lock_retries do
+ execute('LOCK #{definition.to_table}, #{definition.from_table} IN ACCESS EXCLUSIVE MODE') if transaction_open?
+
+ remove_foreign_key_if_exists(:#{definition.from_table}, :#{definition.to_table}, name: "#{definition.name}")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:#{definition.from_table}, :#{definition.to_table}, name: "#{definition.name}", column: :#{definition.column}, target_column: :#{definition.primary_key}, on_delete: :#{definition.on_delete})
+ end
+ end
+ EOF
+
+ File.write(migration_name, content)
+
+ exec_cmd("git", "add", migration_name, fail: "Failed to add migration file.")
+ exec_cmd("bin/rails", "db:migrate", fail: "Failed to run db:migrate.")
+ exec_cmd("git", "add", "db/schema_migrations/#{timestamp}", "db/structure.sql", fail: "There are uncommitted changes. We should not have any.")
+ exec_cmd("git diff --exit-code --name-only", fail: "There are uncommitted changes. We should not have any.")
+end
+
+def class_by_table_name
+ @index_by_table_name ||= ActiveRecord::Base
+ .descendants
+ .reject(&:abstract_class)
+ .map(&:base_class)
+ .index_by(&:table_name)
+end
+
+def spec_from_clazz(clazz, definition)
+ %w[spec/models ee/spec/models].each do |specs_path|
+ path = File.join(specs_path, clazz.underscore + "_spec.rb")
+ return path if File.exist?(path)
+ end
+
+ raise "Cannot find specs for #{clazz} (#{definition.from_table})"
+end
+
+def add_test_to_specs(definition)
+ return unless $options[:rspec]
+
+ clazz = class_by_table_name[definition.from_table]
+ raise "Cannot map #{definition.from_table} to clazz" unless clazz
+
+ spec_path = spec_from_clazz(clazz, definition)
+ puts "Adding test to #{spec_path}..."
+
+ spec_test = <<-EOF.strip_heredoc.indent(2)
+ context 'loose foreign key on #{definition.from_table}.#{definition.column}' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:#{definition.to_table.singularize}) }
+ let!(:model) { create(:#{definition.from_table.singularize}, #{definition.column.delete_suffix("_id").singularize}: parent) }
+ end
+ end
+ EOF
+
+ # append to end of file with empty line before
+ lines = File.readlines(spec_path)
+ insert_line = lines.count - 1
+ lines.insert(insert_line, "\n", *spec_test.lines)
+ File.write(spec_path, lines.join(""))
+
+ # find a matching line
+ test_lines = (1..lines.count).select do |line|
+ lines[line-1].include?("it_behaves_like 'cleanup by a loose foreign key' do")
+ end.join(":")
+
+ loop do
+ if system("bin/rspec", "#{spec_path}:#{test_lines}")
+ puts "Test seems fine?"
+ break
+ end
+
+ puts "--------------------------------------------------"
+ puts "Test failed:"
+ puts "Edit: vim #{spec_path} (lines #{test_lines})"
+ puts "Re-run: bin/rspec #{spec_path}:#{test_lines}"
+ puts "--------------------------------------------------"
+ puts "Running bash. To exit do 'Ctrl-D' to re-run, or do 'Ctrl-C' to break (and ignore failure)."
+ puts
+
+ unless exec_cmd("bash")
+ break
+ end
+ end
+
+ exec_cmd("git", "add", spec_path, fail: "There are uncommitted changes. We should not have any.")
+end
+
+def update_no_cross_db_foreign_keys_spec(definition)
+ from_column = "#{definition.from_table}.#{definition.column}"
+ spec_path = "spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb"
+
+ puts "Updating #{spec_path}..."
+ lines = File.readlines(spec_path)
+ updated = lines.reject { |line| line.strip == from_column }
+
+ if lines.count == updated.count
+ puts "Nothing changed."
+ return
+ end
+
+ File.write(spec_path, updated.join(""))
+ exec_cmd("git", "add", spec_path, fail: "Failed to add changes from #{spec_path}")
+end
+
+def commit_changes(definition)
+ branch_name = "remove-#{definition.to_table}_#{definition.from_table}_#{definition.column}-fk"
+ commit_title = "Swap FK #{definition.from_table} to #{definition.to_table} for LFK"
+ mr_title = "Swap FK #{definition.from_table}.#{definition.column} to #{definition.to_table} for LFK"
+ description = <<-EOF.strip_heredoc
+ Swaps FK for #{definition.from_table}.#{definition.column} to #{definition.to_table}
+
+ Changelog: changed
+ EOF
+
+ commit_message = "#{commit_title}\n\n#{description}"
+
+ existing_branch = %x[git rev-parse --abbrev-ref HEAD].strip
+
+ if $options[:branch]
+ unless exec_cmd("git", "checkout", "-b", branch_name)
+ raise "Failed to create branch: #{branch_name}"
+ end
+ end
+
+ unless exec_cmd("git", "commit", "-m", commit_message)
+ raise "Failed to commit changes."
+ end
+
+ if $options[:branch]
+ exec_cmd("git", "push", "origin", "-u", "HEAD",
+ "-o", "merge_request.create",
+ "-o", "merge_request.target=#{existing_branch}",
+ "-o", "merge_request.milestone=#{$options[:milestone]}",
+ "-o", "merge_request.title=#{mr_title}"
+ )
+
+ puts
+ puts "--------------------------------------------------"
+ puts "Put this as MR description:"
+ puts "--------------------------------------------------"
+ puts <<-EOF.strip_heredoc
+ ## What does this MR do and why?
+
+ Per https://gitlab.com/groups/gitlab-org/-/epics/7249
+
+ As part of our CI "decomposition" efforts we need to remove all foreign keys that are cross-database (ie. between the planned \`main\` and \`ci\` databases). We are going to replace them all with ["loose foreign keys"](https://docs.gitlab.com/ee/development/database/loose_foreign_keys.html).
+
+ Related: <DETAIL>
+
+ ## Validations
+
+ - **Best team to review (check off when reviewed):** TBD
+ - [ ] No way for user to access once parent is deleted. Please explain: <DETAIL>
+ - [ ] Possible to access once parent deleted but low user impact. Please explain: <DETAIL>
+ - [ ] Possible Sidekiq workers that may load directly and possibly lead to exceptions. Please explain: <DETAIL>
+ - [ ] Possible user impact to be evaluated or mitigated. Please explain: <DETAIL>
+ - [ ] Is this FK safe to be removed to avoid LOCKing problems? (Explanation: https://gitlab.com/groups/gitlab-org/-/epics/7249#note_819662046). Please explain: <DETAIL>
+
+ ## MR acceptance checklist
+
+ This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
+
+ * [ ] I have evaluated the [MR acceptance checklist](https://docs.gitlab.com/ee/development/code_review.html#acceptance-checklist) for this MR.
+
+ /label ~"ci-decomposition::phase4" ~"database::review pending" ~"devops::enablement" ~"group::sharding" ~"section::enablement" ~"sharding::active" ~"type::feature" ~"workflow::in dev" ~backend ~"ci-decomposition" ~database ~"Category:Sharding"
+ /milestone %"#{$options[:milestone]}"
+ /assign_reviewer @ahegyi
+ EOF
+ puts "--------------------------------------------------"
+ end
+end
+
+all_foreign_keys = ActiveRecord::Base.connection.tables.flat_map do |table|
+ ActiveRecord::Base.connection.foreign_keys(table)
+end
+
+# Show only cross-schema foreign keys
+if $options[:cross_schema]
+ all_foreign_keys.select! do |definition|
+ Gitlab::Database::GitlabSchema.table_schema(definition.from_table) != Gitlab::Database::GitlabSchema.table_schema(definition.to_table)
+ end
+end
+
+if $options[:cross_schema]
+ puts "Showing cross-schema foreign keys (#{all_foreign_keys.count}):"
+else
+ puts "Showing all foreign keys (#{all_foreign_keys.count}):"
+ puts "Did you meant `#{$0} --cross-schema ...`?"
+end
+
+columns("ID", "HAS_LFK", "FROM", "TO", "COLUMN", "ON_DELETE")
+all_foreign_keys.each_with_index do |definition, idx|
+ columns(idx, has_lfk?(definition) ? 'Y' : 'N', definition.from_table, definition.to_table, definition.column, definition.on_delete)
+end
+puts
+
+puts "To match FK write one or many filters to match against FROM/TO/COLUMN:"
+puts "- #{$0} <filter(s)...>"
+puts "- #{$0} ci_job_artifacts project_id"
+puts "- #{$0} dast_site_profiles_pipelines"
+puts
+
+return if ARGV.empty?
+
+puts "Loading all models..."
+# Fix bug with loading `app/models/identity/uniqueness_scopes.rb`
+require_relative Rails.root.join('app/models/identity.rb')
+
+%w[app/models/**/*.rb ee/app/models/**/*.rb].each do |filter|
+ Dir.glob(filter).each do |path|
+ require_relative Rails.root.join(path)
+ end
+end
+puts
+
+puts "Generating Loose Foreign Key for given filters: #{ARGV}"
+
+all_foreign_keys.each_with_index do |definition, idx|
+ next unless matching_filter?(definition, ARGV)
+
+ puts "Matched: #{idx} (#{definition.from_table}, #{definition.to_table}, #{definition.column})"
+
+ add_definition_to_yaml(definition)
+ generate_migration(definition)
+ add_test_to_specs(definition)
+ update_no_cross_db_foreign_keys_spec(definition)
+ commit_changes(definition)
+end
+puts
diff --git a/scripts/gather-test-memory-data b/scripts/gather-test-memory-data
deleted file mode 100755
index 3156365ac19..00000000000
--- a/scripts/gather-test-memory-data
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-require 'csv'
-
-def join_csv_files(output_path, input_paths)
- return if input_paths.empty?
-
- input_csvs = input_paths.map do |input_path|
- CSV.read(input_path, headers: true)
- end
-
- CSV.open(output_path, "w", headers: input_csvs.first.headers, write_headers: true) do |output_csv|
- input_csvs.each do |input_csv|
- input_csv.each do |line|
- output_csv << line
- end
- end
- end
-end
-
-join_csv_files('tmp/memory_test/report.csv', Dir['tmp/memory_test/*.csv'].sort)
diff --git a/scripts/generate-gems-memory-metrics-static b/scripts/generate-gems-memory-metrics-static
deleted file mode 100755
index 42191f078f1..00000000000
--- a/scripts/generate-gems-memory-metrics-static
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-abort "usage: #{__FILE__} <memory_bundle_objects_file_name>" unless ARGV.length == 1
-memory_bundle_objects_file_name = ARGV.first
-
-full_report = File.readlines(memory_bundle_objects_file_name)
-
-allocated_str = full_report[1]
-retained_str = full_report[2]
-allocated_stats = /Total allocated: (?<bytes>.*) bytes \((?<objects>.*) objects\)/.match(allocated_str)
-retained_stats = /Total retained: (?<bytes>.*) bytes \((?<objects>.*) objects\)/.match(retained_str)
-
-abort 'failed to process the benchmark output' unless allocated_stats && retained_stats
-
-puts "memory_static_objects_allocated_mb #{(allocated_stats[:bytes].to_f / (1024 * 1024)).round(1)}"
-puts "memory_static_objects_retained_mb #{(retained_stats[:bytes].to_f / (1024 * 1024)).round(1)}"
-puts "memory_static_objects_allocated_items #{allocated_stats[:objects]}"
-puts "memory_static_objects_retained_items #{retained_stats[:objects]}"
diff --git a/scripts/generate-gems-size-metrics-static b/scripts/generate-gems-size-metrics-static
deleted file mode 100755
index 2406e720916..00000000000
--- a/scripts/generate-gems-size-metrics-static
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-abort "usage: #{__FILE__} <memory_bundle_mem_file_name>" unless ARGV.length == 1
-memory_bundle_mem_file_name = ARGV.first
-
-full_report = File.readlines(memory_bundle_mem_file_name)
-
-def total_size(memory_bundle_mem_report)
- stats = /TOP: (?<total_mibs_str>.*) MiB/.match(memory_bundle_mem_report.first)
- abort 'failed to process the benchmark output' unless stats
- "gem_total_size_mb #{stats[:total_mibs_str].to_f.round(1)}"
-end
-
-TOP_LEVEL_GEM_LOG_FORMAT = /^ (?<gem_name>\S.*):\s*(?<gem_size>\d[.\d]*)\s*MiB/.freeze
-def all_gems(memory_bundle_mem_report)
- memory_bundle_mem_report.map do |line|
- TOP_LEVEL_GEM_LOG_FORMAT.match(line)
- end.compact
-end
-
-def gems_as_metrics(gems_match_data)
- gems_match_data.map do |gem|
- gem_name = gem[:gem_name]
- gem_size_mb = gem[:gem_size].to_f.round(1)
- "gem_size_mb{name=\"#{gem_name}\"} #{gem_size_mb}"
- end
-end
-
-puts total_size(full_report)
-puts gems_as_metrics(all_gems(full_report)).sort(&:casecmp)
diff --git a/scripts/insert-rspec-profiling-data b/scripts/insert-rspec-profiling-data
index be25972644c..996ad78ba5f 100755
--- a/scripts/insert-rspec-profiling-data
+++ b/scripts/insert-rspec-profiling-data
@@ -43,4 +43,4 @@ def insert_data(path)
end
end
-insert_data('rspec_profiling') if ENV['RSPEC_PROFILING_POSTGRES_URL'].present?
+insert_data(ENV['RSPEC_PROFILING_FOLDER_PATH']) if ENV['RSPEC_PROFILING_POSTGRES_URL'].present?
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index a036b3f7342..aba815cdf28 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -128,7 +128,7 @@ function run_locally_or_in_docker() {
$cmd $args
elif hash docker 2>/dev/null
then
- docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.14.0-markdownlint-0.30.0 ${cmd} ${args}
+ docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.15.0-markdownlint-0.31.0 ${cmd} ${args}
else
echo
echo " ✖ ERROR: '${cmd}' not found. Install '${cmd}' or Docker to proceed." >&2
diff --git a/scripts/rspec_bisect_flaky b/scripts/rspec_bisect_flaky
index efeb9bcb5a0..2ef6dedb4c2 100755
--- a/scripts/rspec_bisect_flaky
+++ b/scripts/rspec_bisect_flaky
@@ -10,20 +10,20 @@ if [ $# -eq 0 ]; then
exit
fi
-files=( $@ )
+files=( "$@" )
len=${#files[@]}
target=${files[$len-1]}
# Trap interrupts and exit instead of continuing the loop
trap "echo Exited!; exit 2;" SIGINT SIGTERM
-# Show which set of specs are running
-set -x
+# Show which set of specs are running and exit immediately if they fail.
+set -xe
# Do the speedy case first, run each spec with our failing spec
for file in "${files[@]}"; do
- bin/rspec $file $target
+ bin/rspec "$file" "$target"
done
# Do a full bisect given we did not find candidates with speedy cases
-bin/rspec --bisect=verbose $@
+bin/rspec --bisect=verbose "$@"
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 2a6eb91a1f3..af09d6d0edd 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -1,15 +1,18 @@
#!/usr/bin/env bash
function retrieve_tests_metadata() {
- mkdir -p $(dirname "$KNAPSACK_RSPEC_SUITE_REPORT_PATH") $(dirname "$FLAKY_RSPEC_SUITE_REPORT_PATH") rspec_profiling/
+ mkdir -p $(dirname "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}") $(dirname "${FLAKY_RSPEC_SUITE_REPORT_PATH}") "${RSPEC_PROFILING_FOLDER_PATH}"
if [[ -n "${RETRIEVE_TESTS_METADATA_FROM_PAGES}" ]]; then
if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
- curl --location -o "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "https://gitlab-org.gitlab.io/gitlab/${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
+ curl --location -o "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "https://gitlab-org.gitlab.io/gitlab/${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ||
+ echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
fi
if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
- curl --location -o "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "https://gitlab-org.gitlab.io/gitlab/${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ curl --location -o "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "https://gitlab-org.gitlab.io/gitlab/${FLAKY_RSPEC_SUITE_REPORT_PATH}" ||
+ curl --location -o "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "https://gitlab-org.gitlab.io/gitlab/rspec_flaky/report-suite.json" || # temporary back-compat
+ echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
else
# ${CI_DEFAULT_BRANCH} might not be master in other forks but we want to
@@ -31,7 +34,14 @@ function retrieve_tests_metadata() {
fi
if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
- scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ||
+ scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "rspec_flaky/report-suite.json" || # temporary back-compat
+ echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+
+ # temporary back-compat
+ if [[ -f "rspec_flaky/report-suite.json" ]]; then
+ mv "rspec_flaky/report-suite.json" "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ fi
fi
else
echo "test_metadata_job_id couldn't be found!"
@@ -42,21 +52,24 @@ function retrieve_tests_metadata() {
}
function update_tests_metadata() {
+ local rspec_flaky_folder_path="$(dirname "${FLAKY_RSPEC_SUITE_REPORT_PATH}")/"
+ local knapsack_folder_path="$(dirname "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}")/"
+
echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
- scripts/merge-reports "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" knapsack/rspec*.json
- rm -f knapsack/rspec*.json
+ scripts/merge-reports "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ${knapsack_folder_path}rspec*.json
export FLAKY_RSPEC_GENERATE_REPORT="true"
- scripts/merge-reports "${FLAKY_RSPEC_SUITE_REPORT_PATH}" rspec_flaky/all_*.json
+ scripts/merge-reports "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ${rspec_flaky_folder_path}all_*.json
scripts/flaky_examples/prune-old-flaky-examples "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
- rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json
if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then
scripts/insert-rspec-profiling-data
else
echo "Not inserting profiling data as the pipeline is not a scheduled one."
fi
+
+ cleanup_individual_job_reports
}
function retrieve_tests_mapping() {
@@ -158,12 +171,20 @@ function retrieve_previous_failed_tests() {
scripts/failed_tests.rb --previous-tests-report-path "${pipeline_report_path}" --output-directory "${directory_for_output_reports}" --rspec-pg-regex "${rspec_pg_regex}" --rspec-ee-pg-regex "${rspec_ee_pg_regex}"
}
-function rspec_simple_job() {
+function rspec_args() {
local rspec_opts="${1}"
+ local junit_report_file="${2:-${JUNIT_RESULT_FILE}}"
+
+ echo "-Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out ${junit_report_file} ${rspec_opts}"
+}
+function rspec_simple_job() {
export NO_KNAPSACK="1"
- eval "bin/rspec -Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
+ local rspec_cmd="bin/rspec $(rspec_args "${1}" "${2}")"
+ echoinfo "Running RSpec command: ${rspec_cmd}"
+
+ eval "${rspec_cmd}"
}
function rspec_db_library_code() {
@@ -172,6 +193,26 @@ function rspec_db_library_code() {
rspec_simple_job "-- ${db_files}"
}
+function debug_rspec_variables() {
+ echoinfo "SKIP_FLAKY_TESTS_AUTOMATICALLY: ${SKIP_FLAKY_TESTS_AUTOMATICALLY}"
+ echoinfo "RETRY_FAILED_TESTS_IN_NEW_PROCESS: ${RETRY_FAILED_TESTS_IN_NEW_PROCESS}"
+
+ echoinfo "KNAPSACK_GENERATE_REPORT: ${KNAPSACK_GENERATE_REPORT}"
+ echoinfo "FLAKY_RSPEC_GENERATE_REPORT: ${FLAKY_RSPEC_GENERATE_REPORT}"
+
+ echoinfo "KNAPSACK_TEST_FILE_PATTERN: ${KNAPSACK_TEST_FILE_PATTERN}"
+ echoinfo "KNAPSACK_LOG_LEVEL: ${KNAPSACK_LOG_LEVEL}"
+ echoinfo "KNAPSACK_REPORT_PATH: ${KNAPSACK_REPORT_PATH}"
+
+ echoinfo "FLAKY_RSPEC_SUITE_REPORT_PATH: ${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ echoinfo "FLAKY_RSPEC_REPORT_PATH: ${FLAKY_RSPEC_REPORT_PATH}"
+ echoinfo "NEW_FLAKY_RSPEC_REPORT_PATH: ${NEW_FLAKY_RSPEC_REPORT_PATH}"
+ echoinfo "SKIPPED_FLAKY_TESTS_REPORT_PATH: ${SKIPPED_FLAKY_TESTS_REPORT_PATH}"
+ echoinfo "RETRIED_TESTS_REPORT_PATH: ${RETRIED_TESTS_REPORT_PATH}"
+
+ echoinfo "CRYSTALBALL: ${CRYSTALBALL}"
+}
+
function rspec_paralellized_job() {
read -ra job_name <<< "${CI_JOB_NAME}"
local test_tool="${job_name[0]}"
@@ -179,6 +220,9 @@ function rspec_paralellized_job() {
local report_name=$(echo "${CI_JOB_NAME}" | sed -E 's|[/ ]|_|g') # e.g. 'rspec unit pg12 1/24' would become 'rspec_unit_pg12_1_24'
local rspec_opts="${1}"
local spec_folder_prefixes=""
+ local rspec_flaky_folder_path="$(dirname "${FLAKY_RSPEC_SUITE_REPORT_PATH}")/"
+ local knapsack_folder_path="$(dirname "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}")/"
+ local rspec_run_status=0
if [[ "${test_tool}" =~ "-ee" ]]; then
spec_folder_prefixes="'ee/'"
@@ -193,7 +237,7 @@ function rspec_paralellized_job() {
fi
export KNAPSACK_LOG_LEVEL="debug"
- export KNAPSACK_REPORT_PATH="knapsack/${report_name}_report.json"
+ export KNAPSACK_REPORT_PATH="${knapsack_folder_path}${report_name}_report.json"
# There's a bug where artifacts are sometimes not downloaded. Since specs can run without the Knapsack report, we can
# handle the missing artifact gracefully here. See https://gitlab.com/gitlab-org/gitlab/-/issues/212349.
@@ -203,21 +247,15 @@ function rspec_paralellized_job() {
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
- if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
- pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
- export KNAPSACK_TEST_FILE_PATTERN="${pattern}"
- fi
-
- echo "KNAPSACK_TEST_FILE_PATTERN: ${KNAPSACK_TEST_FILE_PATTERN}"
- echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: ${SKIP_FLAKY_TESTS_AUTOMATICALLY}"
+ export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
+ export FLAKY_RSPEC_REPORT_PATH="${rspec_flaky_folder_path}all_${report_name}_report.json"
+ export NEW_FLAKY_RSPEC_REPORT_PATH="${rspec_flaky_folder_path}new_${report_name}_report.json"
+ export SKIPPED_FLAKY_TESTS_REPORT_PATH="${rspec_flaky_folder_path}skipped_flaky_tests_${report_name}_report.txt"
+ export RETRIED_TESTS_REPORT_PATH="${rspec_flaky_folder_path}retried_tests_${report_name}_report.txt"
if [[ -d "ee/" ]]; then
export KNAPSACK_GENERATE_REPORT="true"
export FLAKY_RSPEC_GENERATE_REPORT="true"
- export SUITE_FLAKY_RSPEC_REPORT_PATH="${FLAKY_RSPEC_SUITE_REPORT_PATH}"
- export FLAKY_RSPEC_REPORT_PATH="rspec_flaky/all_${report_name}_report.json"
- export NEW_FLAKY_RSPEC_REPORT_PATH="rspec_flaky/new_${report_name}_report.json"
- export SKIPPED_FLAKY_TESTS_REPORT_PATH="rspec_flaky/skipped_flaky_tests_${report_name}_report.txt"
if [[ ! -f $FLAKY_RSPEC_REPORT_PATH ]]; then
echo "{}" > "${FLAKY_RSPEC_REPORT_PATH}"
@@ -228,19 +266,52 @@ function rspec_paralellized_job() {
fi
fi
- mkdir -p tmp/memory_test
+ debug_rspec_variables
- export MEMORY_TEST_PATH="tmp/memory_test/${report_name}_memory.csv"
+ if [[ -n $RSPEC_TESTS_MAPPING_ENABLED ]]; then
+ tooling/bin/parallel_rspec --rspec_args "$(rspec_args "${rspec_opts}")" --filter "tmp/matching_tests.txt" || rspec_run_status=$?
+ else
+ tooling/bin/parallel_rspec --rspec_args "$(rspec_args "${rspec_opts}")" || rspec_run_status=$?
+ fi
- local rspec_args="-Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
+ echoinfo "RSpec exited with ${rspec_run_status}."
- if [[ -n $RSPEC_TESTS_MAPPING_ENABLED ]]; then
- tooling/bin/parallel_rspec --rspec_args "${rspec_args}" --filter "tmp/matching_tests.txt"
+ # Experiment to retry failed examples in a new RSpec process: https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1148
+ if [[ $rspec_run_status -ne 0 ]]; then
+ if [[ "${RETRY_FAILED_TESTS_IN_NEW_PROCESS}" == "true" ]]; then
+ retry_failed_rspec_examples
+ rspec_run_status=$?
+ fi
else
- tooling/bin/parallel_rspec --rspec_args "${rspec_args}"
+ echosuccess "No examples to retry, congrats!"
fi
- date
+ exit $rspec_run_status
+}
+
+function retry_failed_rspec_examples() {
+ local rspec_run_status=0
+
+ # Keep track of the tests that are retried, later consolidated in a single file by the `rspec:flaky-tests-report` job
+ local failed_examples=$(grep " failed" ${RSPEC_LAST_RUN_RESULTS_FILE})
+ echo "${CI_JOB_URL}" > "${RETRIED_TESTS_REPORT_PATH}"
+ echo $failed_examples >> "${RETRIED_TESTS_REPORT_PATH}"
+
+ echoinfo "Retrying the failing examples in a new RSpec process..."
+
+ install_junit_merge_gem
+
+ # Disable Crystalball on retry to not overwrite the existing report
+ export CRYSTALBALL="false"
+
+ # Retry only the tests that failed on first try
+ rspec_simple_job "--only-failures --pattern \"${KNAPSACK_TEST_FILE_PATTERN}\"" "${JUNIT_RETRY_FILE}"
+ rspec_run_status=$?
+
+ # Merge the JUnit report from retry into the first-try report
+ junit_merge "${JUNIT_RETRY_FILE}" "${JUNIT_RESULT_FILE}"
+
+ exit $rspec_run_status
}
function rspec_rerun_previous_failed_tests() {
@@ -330,3 +401,30 @@ function generate_frontend_fixtures_mapping() {
rspec_simple_job "--pattern \"${pattern}\""
}
+
+function cleanup_individual_job_reports() {
+ local rspec_flaky_folder_path="$(dirname "${FLAKY_RSPEC_SUITE_REPORT_PATH}")/"
+ local knapsack_folder_path="$(dirname "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}")/"
+
+ rm -rf ${knapsack_folder_path}rspec*.json \
+ ${rspec_flaky_folder_path}all_*.json \
+ ${rspec_flaky_folder_path}new_*.json \
+ ${rspec_flaky_folder_path}skipped_flaky_tests_*_report.txt \
+ ${rspec_flaky_folder_path}retried_tests_*_report.txt \
+ ${RSPEC_LAST_RUN_RESULTS_FILE} \
+ ${RSPEC_PROFILING_FOLDER_PATH}/**/*
+ rmdir ${RSPEC_PROFILING_FOLDER_PATH} || true
+}
+
+function generate_flaky_tests_reports() {
+ local rspec_flaky_folder_path="$(dirname "${FLAKY_RSPEC_SUITE_REPORT_PATH}")/"
+
+ debug_rspec_variables
+
+ mkdir -p ${rspec_flaky_folder_path}
+
+ find ${rspec_flaky_folder_path} -type f -name 'skipped_flaky_tests_*_report.txt' -exec cat {} + >> "${SKIPPED_FLAKY_TESTS_REPORT_PATH}"
+ find ${rspec_flaky_folder_path} -type f -name 'retried_tests_*_report.txt' -exec cat {} + >> "${RETRIED_TESTS_REPORT_PATH}"
+
+ cleanup_individual_job_reports
+}
diff --git a/scripts/setup/find-jh-branch.rb b/scripts/setup/find-jh-branch.rb
index 812e1c210f4..89aa1492939 100755
--- a/scripts/setup/find-jh-branch.rb
+++ b/scripts/setup/find-jh-branch.rb
@@ -8,7 +8,7 @@ require_relative '../api/default_options'
class FindJhBranch
JH_DEFAULT_BRANCH = 'main-jh'
- JH_PROJECT_PATH = 'gitlab-jh/gitlab'
+ JH_PROJECT_PATH = 'gitlab-org/gitlab-jh/gitlab'
BranchNotFound = Class.new(RuntimeError)
def run
diff --git a/scripts/trigger-build b/scripts/trigger-build.rb
index d40e8de5a1f..17cbd91a8ee 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build.rb
@@ -21,6 +21,12 @@ module Trigger
variable_value
end
+ def self.variables_for_env_file(variables)
+ variables.map do |key, value|
+ %Q(#{key}=#{value})
+ end.join("\n")
+ end
+
class Base
# Can be overridden
def self.access_token
@@ -57,6 +63,21 @@ module Trigger
end
end
+ def variables
+ simple_forwarded_variables.merge(base_variables, extra_variables, version_file_variables)
+ end
+
+ def simple_forwarded_variables
+ {
+ 'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
+ 'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
+ 'TOP_UPSTREAM_SOURCE_REF' => ENV['CI_COMMIT_REF_NAME'],
+ 'TOP_UPSTREAM_SOURCE_JOB' => ENV['CI_JOB_URL'],
+ 'TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID' => ENV['CI_MERGE_REQUEST_PROJECT_ID'],
+ 'TOP_UPSTREAM_MERGE_REQUEST_IID' => ENV['CI_MERGE_REQUEST_IID']
+ }
+ end
+
private
# Override to trigger and work with pipeline on different GitLab instance
@@ -95,23 +116,13 @@ module Trigger
ENV[version_file]&.strip || File.read(version_file).strip
end
- def variables
- base_variables.merge(extra_variables).merge(version_file_variables)
- end
-
def base_variables
# Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results,
# and fallback to CI_COMMIT_SHA for the `detached` pipelines.
{
'GITLAB_REF_SLUG' => ENV['CI_COMMIT_TAG'] ? ENV['CI_COMMIT_REF_NAME'] : ENV['CI_COMMIT_REF_SLUG'],
'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'],
- 'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
- 'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
- 'TOP_UPSTREAM_SOURCE_JOB' => ENV['CI_JOB_URL'],
- 'TOP_UPSTREAM_SOURCE_SHA' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'],
- 'TOP_UPSTREAM_SOURCE_REF' => ENV['CI_COMMIT_REF_NAME'],
- 'TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID' => ENV['CI_MERGE_REQUEST_PROJECT_ID'],
- 'TOP_UPSTREAM_MERGE_REQUEST_IID' => ENV['CI_MERGE_REQUEST_IID']
+ 'TOP_UPSTREAM_SOURCE_SHA' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA']
}
end
@@ -163,17 +174,16 @@ module Trigger
end
class CNG < Base
- def self.access_token
- # Default to "Multi-pipeline (from 'gitlab-org/gitlab' 'cloud-native-image' job)" at https://gitlab.com/gitlab-org/build/CNG/-/settings/access_tokens
- ENV['CNG_PROJECT_ACCESS_TOKEN'] || super
+ def variables
+ # Delete variables that aren't useful when using native triggers.
+ super.tap do |hash|
+ hash.delete('TRIGGER_SOURCE')
+ hash.delete('TRIGGERED_USER')
+ end
end
private
- def downstream_project_path
- ENV.fetch('CNG_PROJECT_PATH', 'gitlab-org/build/CNG')
- end
-
def ref
return ENV['CI_COMMIT_REF_NAME'] if ENV['CI_COMMIT_REF_NAME'] =~ /^[\d-]+-stable(-ee)?$/
@@ -181,17 +191,17 @@ module Trigger
end
def extra_variables
- edition = Trigger.ee? ? 'EE' : 'CE'
# Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA (MR HEAD commit) so that the image is in sync with the assets and QA images.
source_sha = Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA']
{
- "ee" => Trigger.ee? ? "true" : "false",
+ "TRIGGER_BRANCH" => ref,
"GITLAB_VERSION" => source_sha,
- "GITLAB_TAG" => ENV['CI_COMMIT_TAG'],
+ "GITLAB_TAG" => ENV['CI_COMMIT_TAG'], # Always set a value, even an empty string, so that the downstream pipeline can correctly check it.
"GITLAB_ASSETS_TAG" => ENV['CI_COMMIT_TAG'] ? ENV['CI_COMMIT_REF_NAME'] : source_sha,
"FORCE_RAILS_IMAGE_BUILDS" => 'true',
- "#{edition}_PIPELINE" => 'true'
+ "CE_PIPELINE" => Trigger.ee? ? nil : "true", # Always set a value, even an empty string, so that the downstream pipeline can correctly check it.
+ "EE_PIPELINE" => Trigger.ee? ? "true" : nil # Always set a value, even an empty string, so that the downstream pipeline can correctly check it.
}
end
@@ -445,28 +455,30 @@ module Trigger
Job = Class.new(Pipeline)
end
-case ARGV[0]
-when 'omnibus'
- Trigger::Omnibus.new.invoke!(post_comment: true, downstream_job_name: 'Trigger:qa-test').wait!
-when 'cng'
- Trigger::CNG.new.invoke!.wait!
-when 'gitlab-com-database-testing'
- Trigger::DatabaseTesting.new.invoke!
-when 'docs'
- docs_trigger = Trigger::Docs.new
-
- case ARGV[1]
- when 'deploy'
- docs_trigger.deploy!
- when 'cleanup'
- docs_trigger.cleanup!
+if $0 == __FILE__
+ case ARGV[0]
+ when 'omnibus'
+ Trigger::Omnibus.new.invoke!(post_comment: true, downstream_job_name: 'Trigger:qa-test').wait!
+ when 'cng'
+ Trigger::CNG.new.invoke!.wait!
+ when 'gitlab-com-database-testing'
+ Trigger::DatabaseTesting.new.invoke!
+ when 'docs'
+ docs_trigger = Trigger::Docs.new
+
+ case ARGV[1]
+ when 'deploy'
+ docs_trigger.deploy!
+ when 'cleanup'
+ docs_trigger.cleanup!
+ else
+ puts 'usage: trigger-build docs <deploy|cleanup>'
+ exit 1
+ end
else
- puts 'usage: trigger-build docs <deploy|cleanup>'
- exit 1
+ puts "Please provide a valid option:
+ omnibus - Triggers a pipeline that builds the omnibus-gitlab package
+ cng - Triggers a pipeline that builds images used by the GitLab helm chart
+ gitlab-com-database-testing - Triggers a pipeline that tests database changes on GitLab.com data"
end
-else
- puts "Please provide a valid option:
- omnibus - Triggers a pipeline that builds the omnibus-gitlab package
- cng - Triggers a pipeline that builds images used by the GitLab helm chart
- gitlab-com-database-testing - Triggers a pipeline that tests database changes on GitLab.com data"
end
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 15047d35fc3..c20508617b8 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -36,6 +36,7 @@ function bundle_install_script() {
exit 1;
fi;
+ gem install bundler --no-document --conservative --version 2.3.6
bundle --version
bundle config set path "$(pwd)/vendor"
bundle config set clean 'true'
@@ -64,16 +65,20 @@ function setup_db() {
}
function install_api_client_dependencies_with_apk() {
- apk add --update openssl curl jq
+ run_timed_command "apk add --update openssl curl jq"
}
function install_gitlab_gem() {
- gem install httparty --no-document --version 0.18.1
- gem install gitlab --no-document --version 4.17.0
+ run_timed_command "gem install httparty --no-document --version 0.18.1"
+ run_timed_command "gem install gitlab --no-document --version 4.17.0"
}
function install_tff_gem() {
- gem install test_file_finder --version 0.1.1
+ run_timed_command "gem install test_file_finder --no-document --version 0.1.1"
+}
+
+function install_junit_merge_gem() {
+ run_timed_command "gem install junit_merge --no-document --version 0.1.2"
}
function run_timed_command() {
diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb
index bbe95788a35..2feb77601b8 100644
--- a/sidekiq_cluster/cli.rb
+++ b/sidekiq_cluster/cli.rb
@@ -191,11 +191,11 @@ module Gitlab
return unless metrics_server_enabled?
@logger.info("Starting metrics server on port #{sidekiq_exporter_port}")
- @metrics_server_pid = MetricsServer.spawn(
+ @metrics_server_pid = MetricsServer.fork(
'sidekiq',
metrics_dir: @metrics_dir,
wipe_metrics_dir: wipe_metrics_dir,
- trapped_signals: TERMINATE_SIGNALS + FORWARD_SIGNALS
+ reset_signals: TERMINATE_SIGNALS + FORWARD_SIGNALS
)
end
diff --git a/spec/bin/feature_flag_spec.rb b/spec/bin/feature_flag_spec.rb
index a85cafcb4a3..03f5ac135f7 100644
--- a/spec/bin/feature_flag_spec.rb
+++ b/spec/bin/feature_flag_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'bin/feature-flag' do
allow(File).to receive(:write).and_return(true)
# ignore stdin
- allow($stdin).to receive(:gets).and_raise('EOF')
+ allow(Readline).to receive(:readline).and_raise('EOF')
end
subject { creator.execute }
@@ -135,8 +135,8 @@ RSpec.describe 'bin/feature-flag' do
let(:type) { 'deprecated' }
it 'shows error message and retries' do
- expect($stdin).to receive(:gets).and_return(type)
- expect($stdin).to receive(:gets).and_raise('EOF')
+ expect(Readline).to receive(:readline).and_return(type)
+ expect(Readline).to receive(:readline).and_raise('EOF')
expect do
expect { described_class.read_type }.to raise_error(/EOF/)
@@ -154,8 +154,8 @@ RSpec.describe 'bin/feature-flag' do
)
end
- it 'reads type from $stdin' do
- expect($stdin).to receive(:gets).and_return(type)
+ it 'reads type from stdin' do
+ expect(Readline).to receive(:readline).and_return(type)
expect do
expect(described_class.read_type).to eq(:development)
end.to output(/Specify the feature flag type/).to_stdout
@@ -165,8 +165,8 @@ RSpec.describe 'bin/feature-flag' do
let(:type) { 'invalid' }
it 'shows error message and retries' do
- expect($stdin).to receive(:gets).and_return(type)
- expect($stdin).to receive(:gets).and_raise('EOF')
+ expect(Readline).to receive(:readline).and_return(type)
+ expect(Readline).to receive(:readline).and_raise('EOF')
expect do
expect { described_class.read_type }.to raise_error(/EOF/)
@@ -180,8 +180,8 @@ RSpec.describe 'bin/feature-flag' do
describe '.read_group' do
let(:group) { 'group::memory' }
- it 'reads type from $stdin' do
- expect($stdin).to receive(:gets).and_return(group)
+ it 'reads type from stdin' do
+ expect(Readline).to receive(:readline).and_return(group)
expect do
expect(described_class.read_group).to eq('group::memory')
end.to output(/Specify the group introducing the feature flag/).to_stdout
@@ -191,8 +191,8 @@ RSpec.describe 'bin/feature-flag' do
let(:type) { 'invalid' }
it 'shows error message and retries' do
- expect($stdin).to receive(:gets).and_return(type)
- expect($stdin).to receive(:gets).and_raise('EOF')
+ expect(Readline).to receive(:readline).and_return(type)
+ expect(Readline).to receive(:readline).and_raise('EOF')
expect do
expect { described_class.read_group }.to raise_error(/EOF/)
@@ -205,8 +205,8 @@ RSpec.describe 'bin/feature-flag' do
describe '.read_introduced_by_url' do
let(:url) { 'https://merge-request' }
- it 'reads type from $stdin' do
- expect($stdin).to receive(:gets).and_return(url)
+ it 'reads type from stdin' do
+ expect(Readline).to receive(:readline).and_return(url)
expect do
expect(described_class.read_introduced_by_url).to eq('https://merge-request')
end.to output(/URL of the MR introducing the feature flag/).to_stdout
@@ -216,7 +216,7 @@ RSpec.describe 'bin/feature-flag' do
let(:url) { '' }
it 'skips entry' do
- expect($stdin).to receive(:gets).and_return(url)
+ expect(Readline).to receive(:readline).and_return(url)
expect do
expect(described_class.read_introduced_by_url).to be_nil
end.to output(/URL of the MR introducing the feature flag/).to_stdout
@@ -227,8 +227,8 @@ RSpec.describe 'bin/feature-flag' do
let(:url) { 'invalid' }
it 'shows error message and retries' do
- expect($stdin).to receive(:gets).and_return(url)
- expect($stdin).to receive(:gets).and_raise('EOF')
+ expect(Readline).to receive(:readline).and_return(url)
+ expect(Readline).to receive(:readline).and_raise('EOF')
expect do
expect { described_class.read_introduced_by_url }.to raise_error(/EOF/)
@@ -242,8 +242,8 @@ RSpec.describe 'bin/feature-flag' do
let(:options) { double('options', name: 'foo', type: :development) }
let(:url) { 'https://issue' }
- it 'reads type from $stdin' do
- expect($stdin).to receive(:gets).and_return(url)
+ it 'reads type from stdin' do
+ expect(Readline).to receive(:readline).and_return(url)
expect do
expect(described_class.read_rollout_issue_url(options)).to eq('https://issue')
end.to output(/URL of the rollout issue/).to_stdout
@@ -253,8 +253,8 @@ RSpec.describe 'bin/feature-flag' do
let(:type) { 'invalid' }
it 'shows error message and retries' do
- expect($stdin).to receive(:gets).and_return(type)
- expect($stdin).to receive(:gets).and_raise('EOF')
+ expect(Readline).to receive(:readline).and_return(type)
+ expect(Readline).to receive(:readline).and_raise('EOF')
expect do
expect { described_class.read_rollout_issue_url(options) }.to raise_error(/EOF/)
diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb
index c10e0c0cab4..affde0095cf 100644
--- a/spec/channels/application_cable/connection_spec.rb
+++ b/spec/channels/application_cable/connection_spec.rb
@@ -3,15 +3,11 @@
require 'spec_helper'
RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do
- let(:session_id) { Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') }
+ include SessionHelpers
context 'when session cookie is set' do
before do
- Gitlab::Redis::Sessions.with do |redis|
- redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
- end
-
- cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+ stub_session(session_hash)
end
context 'when user is logged in' do
diff --git a/spec/commands/metrics_server/metrics_server_spec.rb b/spec/commands/metrics_server/metrics_server_spec.rb
index b755801bb65..217aa185767 100644
--- a/spec/commands/metrics_server/metrics_server_spec.rb
+++ b/spec/commands/metrics_server/metrics_server_spec.rb
@@ -12,6 +12,11 @@ RSpec.describe 'bin/metrics-server', :aggregate_failures do
{
'test' => {
'monitoring' => {
+ 'web_exporter' => {
+ 'address' => 'localhost',
+ 'enabled' => true,
+ 'port' => 3807
+ },
'sidekiq_exporter' => {
'address' => 'localhost',
'enabled' => true,
@@ -22,56 +27,52 @@ RSpec.describe 'bin/metrics-server', :aggregate_failures do
}
end
- context 'with a running server' do
- let(:metrics_dir) { Dir.mktmpdir }
+ %w(puma sidekiq).each do |target|
+ context "with a running server targeting #{target}" do
+ let(:metrics_dir) { Dir.mktmpdir }
- before do
- # We need to send a request to localhost
- WebMock.allow_net_connect!
+ before do
+ # We need to send a request to localhost
+ WebMock.allow_net_connect!
- config_file.write(YAML.dump(config))
- config_file.close
+ config_file.write(YAML.dump(config))
+ config_file.close
- env = {
- 'GITLAB_CONFIG' => config_file.path,
- 'METRICS_SERVER_TARGET' => 'sidekiq',
- 'WIPE_METRICS_DIR' => '1',
- 'prometheus_multiproc_dir' => metrics_dir
- }
- @pid = Process.spawn(env, 'bin/metrics-server', pgroup: true)
- end
+ @pid = MetricsServer.spawn(target, metrics_dir: metrics_dir, gitlab_config: config_file.path, wipe_metrics_dir: true)
+ end
- after do
- webmock_enable!
+ after do
+ webmock_enable!
- if @pid
- pgrp = Process.getpgid(@pid)
+ if @pid
+ pgrp = Process.getpgid(@pid)
- Timeout.timeout(5) do
- Process.kill('TERM', -pgrp)
- Process.waitpid(@pid)
- end
+ Timeout.timeout(10) do
+ Process.kill('TERM', -pgrp)
+ Process.waitpid(@pid)
+ end
- expect(Gitlab::ProcessManagement.process_alive?(@pid)).to be(false)
+ expect(Gitlab::ProcessManagement.process_alive?(@pid)).to be(false)
+ end
+ rescue Errno::ESRCH => _
+ # 'No such process' means the process died before
+ ensure
+ config_file.unlink
+ FileUtils.rm_rf(metrics_dir, secure: true)
end
- rescue Errno::ESRCH => _
- # 'No such process' means the process died before
- ensure
- config_file.unlink
- FileUtils.rm_rf(metrics_dir, secure: true)
- end
- it 'serves /metrics endpoint' do
- expect do
- Timeout.timeout(5) do
- http_ok = false
- until http_ok
- sleep 1
- response = Gitlab::HTTP.try_get("http://localhost:3807/metrics", allow_local_requests: true)
- http_ok = response&.success?
+ it 'serves /metrics endpoint' do
+ expect do
+ Timeout.timeout(10) do
+ http_ok = false
+ until http_ok
+ sleep 1
+ response = Gitlab::HTTP.try_get("http://localhost:3807/metrics", allow_local_requests: true)
+ http_ok = response&.success?
+ end
end
- end
- end.not_to raise_error
+ end.not_to raise_error
+ end
end
end
end
diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb
index d7488e8d965..15b738cacd1 100644
--- a/spec/commands/sidekiq_cluster/cli_spec.rb
+++ b/spec/commands/sidekiq_cluster/cli_spec.rb
@@ -3,9 +3,10 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
+require_relative '../../support/stub_settings_source'
require_relative '../../../sidekiq_cluster/cli'
-RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do # rubocop:disable RSpec/FilePath
+RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubocop:disable RSpec/FilePath
let(:cli) { described_class.new('/dev/null') }
let(:timeout) { Gitlab::SidekiqCluster::DEFAULT_SOFT_TIMEOUT_SECONDS }
let(:default_options) do
@@ -302,7 +303,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
end
it 'does not start a sidekiq metrics server' do
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@@ -319,7 +320,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
end
it 'does not start a sidekiq metrics server' do
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@@ -349,7 +350,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
end
it 'does not start a sidekiq metrics server' do
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@@ -375,7 +376,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
end
it 'does not start a sidekiq metrics server' do
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@@ -405,9 +406,9 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
specify do
if start_metrics_server
- expect(MetricsServer).to receive(:spawn).with('sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: true, trapped_signals: trapped_signals)
+ expect(MetricsServer).to receive(:fork).with('sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: true, reset_signals: trapped_signals)
else
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
end
cli.run(%w(foo))
@@ -420,7 +421,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
let(:sidekiq_exporter_enabled) { true }
it 'does not start the server' do
- expect(MetricsServer).not_to receive(:spawn)
+ expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo --dryrun))
end
@@ -433,7 +434,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
before do
allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
- allow(MetricsServer).to receive(:spawn).and_return(99)
+ allow(MetricsServer).to receive(:fork).and_return(99)
cli.start_metrics_server
end
@@ -452,8 +453,8 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do #
allow(Gitlab::ProcessManagement).to receive(:all_alive?).with(an_instance_of(Array)).and_return(false)
allow(cli).to receive(:stop_metrics_server)
- expect(MetricsServer).to receive(:spawn).with(
- 'sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: false, trapped_signals: trapped_signals
+ expect(MetricsServer).to receive(:fork).with(
+ 'sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: false, reset_signals: trapped_signals
)
cli.start_loop
diff --git a/spec/controllers/admin/instance_review_controller_spec.rb b/spec/controllers/admin/instance_review_controller_spec.rb
index 2169be4e70c..342562618b2 100644
--- a/spec/controllers/admin/instance_review_controller_spec.rb
+++ b/spec/controllers/admin/instance_review_controller_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Admin::InstanceReviewController do
stub_application_setting(usage_ping_enabled: true)
stub_usage_data_connections
stub_database_flavor_check
- ::Gitlab::UsageData.data(force_refresh: true)
+ ::Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)
subject
end
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index 08fb12c375e..74f352e8ec2 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -4,9 +4,10 @@ require 'spec_helper'
RSpec.describe Admin::RunnersController do
let_it_be(:runner) { create(:ci_runner) }
+ let_it_be(:user) { create(:admin) }
before do
- sign_in(create(:admin))
+ sign_in(user)
end
describe '#index' do
@@ -104,6 +105,10 @@ RSpec.describe Admin::RunnersController do
describe '#destroy' do
it 'destroys the runner' do
+ expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
delete :destroy, params: { id: runner.id }
expect(response).to have_gitlab_http_status(:found)
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 6ccba866ebb..533d3896ee6 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe AutocompleteController do
let(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
context 'GET users' do
let!(:user2) { create(:user) }
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
index 743759d5023..b4a4ac56fce 100644
--- a/spec/controllers/dashboard/projects_controller_spec.rb
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -97,14 +97,18 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
subject { get :starred, format: :json }
let(:projects) { create_list(:project, 2, creator: user) }
+ let(:aimed_for_deletion_project) { create_list(:project, 2, :archived, creator: user, marked_for_deletion_at: 3.days.ago) }
before do
- allow(Kaminari.config).to receive(:default_per_page).and_return(1)
-
projects.each do |project|
project.add_developer(user)
create(:users_star_project, project_id: project.id, user_id: user.id)
end
+
+ aimed_for_deletion_project.each do |project|
+ project.add_developer(user)
+ create(:users_star_project, project_id: project.id, user_id: user.id)
+ end
end
it 'returns success' do
@@ -113,10 +117,22 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok)
end
- it 'paginates the records' do
+ context "pagination" do
+ before do
+ allow(Kaminari.config).to receive(:default_per_page).and_return(1)
+ end
+
+ it 'paginates the records' do
+ subject
+
+ expect(assigns(:projects).count).to eq(1)
+ end
+ end
+
+ it 'does not include projects aimed for deletion' do
subject
- expect(assigns(:projects).count).to eq(1)
+ expect(assigns(:projects).count).to eq(2)
end
end
end
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index f2328303102..c3f6c653376 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -73,6 +73,24 @@ RSpec.describe Explore::ProjectsController do
expect(assigns(:projects)).to eq [project1, project2]
end
end
+
+ context 'projects aimed for deletion' do
+ let(:project1) { create(:project, :public, updated_at: 3.days.ago) }
+ let(:project2) { create(:project, :public, updated_at: 1.day.ago) }
+ let(:aimed_for_deletion_project) { create(:project, :public, :archived, updated_at: 2.days.ago, marked_for_deletion_at: 2.days.ago) }
+
+ before do
+ create(:trending_project, project: project1)
+ create(:trending_project, project: project2)
+ create(:trending_project, project: aimed_for_deletion_project)
+ end
+
+ it 'does not list projects aimed for deletion' do
+ get :trending
+
+ expect(assigns(:projects)).to eq [project2, project1]
+ end
+ end
end
describe 'GET #topic' do
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index 578ce04721c..95f60156c40 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -124,6 +124,16 @@ RSpec.describe GraphqlController do
post :execute
end
+
+ it 'calls the track jetbrains api when trackable method' do
+ agent = 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1'
+ request.env['HTTP_USER_AGENT'] = agent
+
+ expect(Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter)
+ .to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
+
+ post :execute
+ end
end
context 'when user uses an API token' do
@@ -151,6 +161,16 @@ RSpec.describe GraphqlController do
subject
end
+
+ it 'calls the track jetbrains api when trackable method' do
+ agent = 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1'
+ request.env['HTTP_USER_AGENT'] = agent
+
+ expect(Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter)
+ .to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
+
+ subject
+ end
end
context 'when user is not logged in' do
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 93c560b4753..710e983dfbd 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe Groups::ClustersController do
it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(group) }
it { expect { go }.to be_allowed_for(:maintainer).of(group) }
- it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_allowed_for(:developer).of(group) }
it { expect { go }.to be_denied_for(:reporter).of(group) }
it { expect { go }.to be_denied_for(:guest).of(group) }
it { expect { go }.to be_denied_for(:user) }
@@ -309,7 +309,8 @@ RSpec.describe Groups::ClustersController do
.to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
+ double(
+ 'instance',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
@@ -673,7 +674,7 @@ RSpec.describe Groups::ClustersController do
it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(group) }
it { expect { go }.to be_allowed_for(:maintainer).of(group) }
- it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_allowed_for(:developer).of(group) }
it { expect { go }.to be_denied_for(:reporter).of(group) }
it { expect { go }.to be_denied_for(:guest).of(group) }
it { expect { go }.to be_denied_for(:user) }
diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
index f438be534fa..57a83da3425 100644
--- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
@@ -47,6 +47,24 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
end
+ shared_examples 'with invalid path' do
+ context 'with invalid image' do
+ let(:image) { '../path_traversal' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Utils::PathTraversalAttackError, 'Invalid path')
+ end
+ end
+
+ context 'with invalid tag' do
+ let(:tag) { 'latest%2f..%2f..%2fpath_traversal' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Utils::PathTraversalAttackError, 'Invalid path')
+ end
+ end
+ end
+
shared_examples 'without permission' do
context 'with invalid user' do
before do
@@ -164,8 +182,10 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
describe 'GET #manifest' do
+ let_it_be(:image) { 'alpine' }
let_it_be(:tag) { 'latest' }
- let_it_be(:manifest) { create(:dependency_proxy_manifest, file_name: "alpine:#{tag}.json", group: group) }
+ let_it_be(:file_name) { "#{image}:#{tag}.json" }
+ let_it_be(:manifest) { create(:dependency_proxy_manifest, file_name: file_name, group: group) }
let(:pull_response) { { status: :success, manifest: manifest, from_cache: false } }
@@ -235,6 +255,8 @@ RSpec.describe Groups::DependencyProxyForContainersController do
context 'with workhorse response' do
let(:pull_response) { { status: :success, manifest: nil, from_cache: false } }
+ it_behaves_like 'with invalid path'
+
it 'returns Workhorse send-dependency instructions', :aggregate_failures do
subject
@@ -246,7 +268,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
"Authorization" => ["Bearer abcd1234"],
"Accept" => ::ContainerRegistry::Client::ACCEPTED_TYPES
)
- expect(url).to eq(DependencyProxy::Registry.manifest_url('alpine', tag))
+ expect(url).to eq(DependencyProxy::Registry.manifest_url(image, tag))
expect(response.headers['Content-Type']).to eq('application/gzip')
expect(response.headers['Content-Disposition']).to eq(
ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: manifest.file_name)
@@ -277,7 +299,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
it_behaves_like 'not found when disabled'
def get_manifest(tag)
- get :manifest, params: { group_id: group.to_param, image: 'alpine', tag: tag }
+ get :manifest, params: { group_id: group.to_param, image: image, tag: tag }
end
end
@@ -440,6 +462,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
it_behaves_like 'a package tracking event', described_class.name, 'pull_manifest'
+ it_behaves_like 'with invalid path'
context 'with no existing manifest' do
it 'creates a manifest' do
diff --git a/spec/controllers/groups/releases_controller_spec.rb b/spec/controllers/groups/releases_controller_spec.rb
index 50701382945..582a77b1c50 100644
--- a/spec/controllers/groups/releases_controller_spec.rb
+++ b/spec/controllers/groups/releases_controller_spec.rb
@@ -6,14 +6,14 @@ RSpec.describe Groups::ReleasesController do
let(:group) { create(:group) }
let!(:project) { create(:project, :repository, :public, namespace: group) }
let!(:private_project) { create(:project, :repository, :private, namespace: group) }
- let(:developer) { create(:user) }
+ let(:guest) { create(:user) }
let!(:release_1) { create(:release, project: project, tag: 'v1', released_at: Time.zone.parse('2020-02-15')) }
let!(:release_2) { create(:release, project: project, tag: 'v2', released_at: Time.zone.parse('2020-02-20')) }
let!(:private_release_1) { create(:release, project: private_project, tag: 'p1', released_at: Time.zone.parse('2020-03-01')) }
let!(:private_release_2) { create(:release, project: private_project, tag: 'p2', released_at: Time.zone.parse('2020-03-05')) }
before do
- private_project.add_developer(developer)
+ group.add_guest(guest)
end
describe 'GET #index' do
@@ -42,7 +42,7 @@ RSpec.describe Groups::ReleasesController do
end
it 'does not return any releases' do
- expect(json_response.map {|r| r['tag'] } ).to match_array(%w(v2 v1))
+ expect(json_response.map {|r| r['tag'] } ).to be_empty
end
it 'returns OK' do
@@ -52,7 +52,7 @@ RSpec.describe Groups::ReleasesController do
context 'the user is authorized' do
it "returns all group's public and private project's releases as JSON, ordered by released_at" do
- sign_in(developer)
+ sign_in(guest)
subject
diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
index a8830efe653..9f0615a96ae 100644
--- a/spec/controllers/groups/runners_controller_spec.rb
+++ b/spec/controllers/groups/runners_controller_spec.rb
@@ -190,6 +190,10 @@ RSpec.describe Groups::RunnersController do
end
it 'destroys the runner and redirects' do
+ expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
delete :destroy, params: params
expect(response).to have_gitlab_http_status(:found)
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 62171528695..a82c5681911 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -132,6 +132,29 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
end
+
+ describe 'require_verification_for_namespace_creation experiment', :experiment do
+ before do
+ sign_in(owner)
+ stub_experiments(require_verification_for_namespace_creation: :candidate)
+ end
+
+ it 'tracks a "start_create_group" event' do
+ expect(experiment(:require_verification_for_namespace_creation)).to track(
+ :start_create_group
+ ).on_next_instance.with_context(user: owner)
+
+ get :new
+ end
+
+ context 'when creating a sub-group' do
+ it 'does not track a "start_create_group" event' do
+ expect(experiment(:require_verification_for_namespace_creation)).not_to track(:start_create_group)
+
+ get :new, params: { parent_id: group.id }
+ end
+ end
+ end
end
describe 'GET #activity' do
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index 4f74af295c6..9fa90dde997 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -67,12 +67,6 @@ RSpec.describe MetricsController, :request_store do
expect(response.body).to match(/^prometheus_counter 1$/)
end
- it 'initializes the rails request SLIs' do
- expect(Gitlab::Metrics::RailsSlis).to receive(:initialize_request_slis_if_needed!).and_call_original
-
- get :index
- end
-
context 'prometheus metrics are disabled' do
before do
allow(Gitlab::Metrics).to receive(:prometheus_metrics_enabled?).and_return(false)
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
index 98cc8d83e0c..e6553c027d6 100644
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ b/spec/controllers/oauth/authorizations_controller_spec.rb
@@ -4,7 +4,13 @@ require 'spec_helper'
RSpec.describe Oauth::AuthorizationsController do
let(:user) { create(:user) }
- let!(:application) { create(:oauth_application, scopes: 'api read_user', redirect_uri: 'http://example.com') }
+ let(:application_scopes) { 'api read_user' }
+
+ let!(:application) do
+ create(:oauth_application, scopes: application_scopes,
+ redirect_uri: 'http://example.com')
+ end
+
let(:params) do
{
response_type: "code",
@@ -119,6 +125,92 @@ RSpec.describe Oauth::AuthorizationsController do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template('doorkeeper/authorizations/redirect')
end
+
+ context 'with gl_auth_type=login' do
+ let(:minimal_scope) { Gitlab::Auth::READ_USER_SCOPE.to_s }
+
+ before do
+ params[:gl_auth_type] = 'login'
+ end
+
+ shared_examples 'downgrades scopes' do
+ it 'downgrades the scopes' do
+ subject
+
+ pre_auth = controller.send(:pre_auth)
+
+ expect(pre_auth.scopes).to contain_exactly(minimal_scope)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('doorkeeper/authorizations/new')
+ # See: config/locales/doorkeeper.en.yml
+ expect(response.body).to include("Read the authenticated user&#39;s personal information")
+ expect(response.body).not_to include("Access the authenticated user&#39;s API")
+ end
+ end
+
+ shared_examples 'adds read_user scope' do
+ it 'modifies the client.application.scopes' do
+ expect { subject }
+ .to change { application.reload.scopes }.to include(minimal_scope)
+ end
+
+ it 'does not remove pre-existing scopes' do
+ subject
+
+ expect(application.scopes).to include(*application_scopes.split(/ /))
+ end
+ end
+
+ context 'the application has all scopes' do
+ let(:application_scopes) { 'api read_api read_user' }
+
+ include_examples 'downgrades scopes'
+ end
+
+ context 'the application has api and read_user scopes' do
+ let(:application_scopes) { 'api read_user' }
+
+ include_examples 'downgrades scopes'
+ end
+
+ context 'the application has read_api and read_user scopes' do
+ let(:application_scopes) { 'read_api read_user' }
+
+ include_examples 'downgrades scopes'
+ end
+
+ context 'the application has only api scopes' do
+ let(:application_scopes) { 'api' }
+
+ include_examples 'downgrades scopes'
+ include_examples 'adds read_user scope'
+ end
+
+ context 'the application has only read_api scopes' do
+ let(:application_scopes) { 'read_api' }
+
+ include_examples 'downgrades scopes'
+ include_examples 'adds read_user scope'
+ end
+
+ context 'the application has scopes we do not handle' do
+ let(:application_scopes) { Gitlab::Auth::PROFILE_SCOPE.to_s }
+
+ before do
+ params[:scope] = application_scopes
+ end
+
+ it 'does not modify the scopes' do
+ subject
+
+ pre_auth = controller.send(:pre_auth)
+
+ expect(pre_auth.scopes).to contain_exactly(application_scopes)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('doorkeeper/authorizations/new')
+ end
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 754b0ddfb94..f410c16b30b 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::ArtifactsController do
include RepoHelpers
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:pipeline, reload: true) do
diff --git a/spec/controllers/projects/autocomplete_sources_controller_spec.rb b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
index 865b31a28d7..79edc261809 100644
--- a/spec/controllers/projects/autocomplete_sources_controller_spec.rb
+++ b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Projects::AutocompleteSourcesController do
- let_it_be(:group) { create(:group) }
+ let_it_be(:group, reload: true) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
@@ -69,4 +69,62 @@ RSpec.describe Projects::AutocompleteSourcesController do
end
end
end
+
+ describe 'GET contacts' do
+ let_it_be(:contact_1) { create(:contact, group: group) }
+ let_it_be(:contact_2) { create(:contact, group: group) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when feature flag is enabled' do
+ context 'when a group has contact relations enabled' do
+ before do
+ create(:crm_settings, group: group, enabled: true)
+ end
+
+ context 'when a user can read contacts' do
+ it 'lists contacts' do
+ group.add_developer(user)
+
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ emails = json_response.map { |contact_data| contact_data["email"] }
+ expect(emails).to match_array([contact_1.email, contact_2.email])
+ end
+ end
+
+ context 'when a user can not read contacts' do
+ it 'renders 404' do
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when a group has contact relations disabled' do
+ it 'renders 404' do
+ group.add_developer(user)
+
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it 'renders 404' do
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb
index 35878fe4c2d..39a373ed6b6 100644
--- a/spec/controllers/projects/avatars_controller_spec.rb
+++ b/spec/controllers/projects/avatars_controller_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Projects::AvatarsController do
end
it 'sets appropriate caching headers' do
- sign_in(project.owner)
+ sign_in(project.first_owner)
subject
expect(response.cache_control[:public]).to eq(true)
@@ -63,7 +63,7 @@ RSpec.describe Projects::AvatarsController do
let(:project) { create(:project, :repository, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
it 'removes avatar from DB by calling destroy' do
diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb
index 242b2fd3ec6..d41e8d6169f 100644
--- a/spec/controllers/projects/badges_controller_spec.rb
+++ b/spec/controllers/projects/badges_controller_spec.rb
@@ -7,39 +7,100 @@ RSpec.describe Projects::BadgesController do
let_it_be(:pipeline, reload: true) { create(:ci_empty_pipeline, project: project) }
let_it_be(:user) { create(:user) }
- shared_examples 'a badge resource' do |badge_type|
- context 'when pipelines are public' do
+ shared_context 'renders badge irrespective of project access levels' do |badge_type|
+ context 'when project is public' do
before do
- project.update!(public_builds: true)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
- context 'when project is public' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- end
+ it "returns the #{badge_type} badge to unauthenticated users" do
+ get_badge(badge_type)
- it "returns the #{badge_type} badge to unauthenticated users" do
- get_badge(badge_type)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- end
+ context 'when project is restricted' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ project.add_guest(user)
+ sign_in(user)
end
- context 'when project is restricted' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- project.add_guest(user)
- sign_in(user)
- end
+ it "returns the #{badge_type} badge to guest users" do
+ get_badge(badge_type)
- it "returns the #{badge_type} badge to guest users" do
- get_badge(badge_type)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- end
+ shared_context 'when pipelines are public' do |badge_type|
+ before do
+ project.update!(public_builds: true)
+ end
+
+ it_behaves_like 'renders badge irrespective of project access levels', badge_type
+ end
+
+ shared_context 'when pipelines are not public' do |badge_type|
+ before do
+ project.update!(public_builds: false)
+ end
+
+ context 'when project is public' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it 'returns 404 to unauthenticated users' do
+ get_badge(badge_type)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when project is restricted to the user' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ project.add_guest(user)
+ sign_in(user)
+ end
+
+ it 'defaults to project permissions' do
+ get_badge(badge_type)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ shared_context 'customization' do |badge_type|
+ render_views
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'when key_text param is used' do
+ it 'sets custom key text' do
+ get_badge(badge_type, key_text: 'custom key text')
+
+ expect(response.body).to include('custom key text')
+ end
+ end
+
+ context 'when key_width param is used' do
+ it 'sets custom key width' do
+ get_badge(badge_type, key_width: '123')
+
+ expect(response.body).to include('123')
end
end
+ end
+ shared_examples 'a badge resource' do |badge_type|
context 'format' do
before do
project.add_maintainer(user)
@@ -77,61 +138,11 @@ RSpec.describe Projects::BadgesController do
end
end
- context 'when pipelines are not public' do
- before do
- project.update!(public_builds: false)
- end
-
- context 'when project is public' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'returns 404 to unauthenticated users' do
- get_badge(badge_type)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when project is restricted to the user' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- project.add_guest(user)
- sign_in(user)
- end
-
- it 'defaults to project permissions' do
- get_badge(badge_type)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'customization' do
- render_views
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- context 'when key_text param is used' do
- it 'sets custom key text' do
- get_badge(badge_type, key_text: 'custom key text')
-
- expect(response.body).to include('custom key text')
- end
- end
-
- context 'when key_width param is used' do
- it 'sets custom key width' do
- get_badge(badge_type, key_width: '123')
+ it_behaves_like 'customization', badge_type
- expect(response.body).to include('123')
- end
- end
+ if [:pipeline, :coverage].include?(badge_type)
+ it_behaves_like 'when pipelines are public', badge_type
+ it_behaves_like 'when pipelines are not public', badge_type
end
end
@@ -163,6 +174,13 @@ RSpec.describe Projects::BadgesController do
it_behaves_like 'a badge resource', :coverage
end
+ describe '#release' do
+ action = :release
+
+ it_behaves_like 'a badge resource', action
+ it_behaves_like 'renders badge irrespective of project access levels', action
+ end
+
def get_badge(badge, args = {})
params = {
namespace_id: project.namespace.to_param,
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index d9dedb04b0d..ea22e6b6f10 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -657,6 +657,36 @@ RSpec.describe Projects::BranchesController do
end
end
+ context 'sorting', :aggregate_failures do
+ let(:sort) { 'name_asc' }
+
+ before do
+ get :index, format: :html, params: {
+ namespace_id: project.namespace, project_id: project, state: 'all', sort: sort
+ }
+ end
+
+ it { expect(assigns[:sort]).to eq('name_asc') }
+
+ context 'when sort is not provided' do
+ let(:sort) { nil }
+
+ it 'uses a default sort without an error message' do
+ expect(assigns[:sort]).to eq('updated_desc')
+ expect(controller).not_to set_flash.now[:alert]
+ end
+ end
+
+ context 'when sort is not supported' do
+ let(:sort) { 'unknown' }
+
+ it 'uses a default sort and shows an error message' do
+ expect(assigns[:sort]).to eq('updated_desc')
+ expect(controller).to set_flash.now[:alert].to(/Unsupported sort/)
+ end
+ end
+ end
+
context 'when gitaly is not available' do
before do
allow_next_instance_of(Gitlab::GitalyClient::RefService) do |ref_service|
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 2a8feb09780..d0bef810ec8 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe Projects::ClustersController do
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_allowed_for(:developer).of(project) }
it { expect { go }.to be_denied_for(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).of(project) }
it { expect { go }.to be_denied_for(:user) }
@@ -315,7 +315,8 @@ RSpec.describe Projects::ClustersController do
.to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
+ double(
+ 'secure',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
@@ -711,7 +712,7 @@ RSpec.describe Projects::ClustersController do
end
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_allowed_for(:developer).of(project) }
it { expect { go }.to be_denied_for(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).of(project) }
it { expect { go }.to be_denied_for(:user) }
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index 16bb33e95c8..72fee40a6e9 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -183,6 +183,18 @@ RSpec.describe Projects::CommitController do
expect(assigns(:tags)).to eq([])
expect(assigns(:tags_limit_exceeded)).to be_truthy
end
+
+ context 'when commit is not found' do
+ it 'responds with 404' do
+ get(:branches, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: '11111111111111111111111111111111111111'
+ })
+
+ expect(response).to be_not_found
+ end
+ end
end
describe 'POST revert' do
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb
index fd840fafa61..c7f98406201 100644
--- a/spec/controllers/projects/commits_controller_spec.rb
+++ b/spec/controllers/projects/commits_controller_spec.rb
@@ -88,6 +88,26 @@ RSpec.describe Projects::CommitsController do
expect(response).to be_successful
end
+
+ context 'when limit is a hash' do
+ it 'uses the default limit' do
+ expect_any_instance_of(Repository).to receive(:commits).with(
+ "master",
+ path: "README.md",
+ limit: described_class::COMMITS_DEFAULT_LIMIT,
+ offset: 0
+ ).and_call_original
+
+ get(:show, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: id,
+ limit: { 'broken' => 'value' }
+ })
+
+ expect(response).to be_successful
+ end
+ end
end
context "when the ref name ends in .atom" do
@@ -131,6 +151,20 @@ RSpec.describe Projects::CommitsController do
expect(response.media_type).to eq('text/html')
end
end
+
+ context 'when the ref does not exist' do
+ before do
+ get(:show, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'unknown.atom'
+ })
+ end
+
+ it 'returns 404 page' do
+ expect(response).to be_not_found
+ end
+ end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 48afd42e8ff..62b93a2728b 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -25,15 +25,25 @@ RSpec.describe Projects::CompareController do
end
describe 'GET index' do
+ let(:params) { { namespace_id: project.namespace, project_id: project } }
+
render_views
before do
- get :index, params: { namespace_id: project.namespace, project_id: project }
+ get :index, params: params
end
it 'returns successfully' do
expect(response).to be_successful
end
+
+ context 'with incorrect parameters' do
+ let(:params) { super().merge(from: { invalid: :param }, to: { also: :invalid }) }
+
+ it 'returns successfully' do
+ expect(response).to be_successful
+ end
+ end
end
describe 'GET show' do
@@ -340,12 +350,13 @@ RSpec.describe Projects::CompareController do
context 'when sending invalid params' do
where(:from_ref, :to_ref, :from_project_id, :expected_redirect_params) do
- '' | '' | '' | {}
- 'main' | '' | '' | { from: 'main' }
- '' | 'main' | '' | { to: 'main' }
- '' | '' | '1' | { from_project_id: 1 }
- 'main' | '' | '1' | { from: 'main', from_project_id: 1 }
- '' | 'main' | '1' | { to: 'main', from_project_id: 1 }
+ '' | '' | '' | {}
+ 'main' | '' | '' | { from: 'main' }
+ '' | 'main' | '' | { to: 'main' }
+ '' | '' | '1' | { from_project_id: 1 }
+ 'main' | '' | '1' | { from: 'main', from_project_id: 1 }
+ '' | 'main' | '1' | { to: 'main', from_project_id: 1 }
+ ['a'] | ['b'] | ['c'] | {}
end
with_them do
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index e53e53980b5..0f8f3b49e02 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -67,6 +67,18 @@ RSpec.describe Projects::ForksController do
expect(assigns[:private_forks_count]).to eq(0)
end
end
+
+ context 'when unsupported keys are provided' do
+ it 'ignores them' do
+ get :index, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ user: 'unsupported'
+ }
+
+ expect(assigns[:forks]).to be_present
+ end
+ end
end
context 'when fork is internal' do
diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb
index d514c486f60..ea15d483c90 100644
--- a/spec/controllers/projects/group_links_controller_spec.rb
+++ b/spec/controllers/projects/group_links_controller_spec.rb
@@ -178,7 +178,7 @@ RSpec.describe Projects::GroupLinksController do
context 'when `expires_at` is set' do
it 'returns correct json response' do
- expect(json_response).to eq({ "expires_in" => "about 1 month", "expires_soon" => false })
+ expect(json_response).to eq({ "expires_in" => controller.helpers.time_ago_with_tooltip(expiry_date), "expires_soon" => false })
end
end
diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb
index 2ab18ccddbf..ebcf35a7ecd 100644
--- a/spec/controllers/projects/hooks_controller_spec.rb
+++ b/spec/controllers/projects/hooks_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::HooksController do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index d91c1b0d29a..bf0b833b311 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -502,10 +502,7 @@ RSpec.describe Projects::IssuesController do
context 'with valid params' do
it 'reorders issues and returns a successful 200 response' do
- reorder_issue(issue1,
- move_after_id: issue2.id,
- move_before_id: issue3.id,
- group_full_path: group.full_path)
+ reorder_issue(issue1, move_after_id: issue2.id, move_before_id: issue3.id)
[issue1, issue2, issue3].map(&:reload)
@@ -531,12 +528,10 @@ RSpec.describe Projects::IssuesController do
end
it 'returns a unprocessable entity 422 response for issues not in group' do
- another_group = create(:group)
+ other_group_project = create(:project, group: create(:group))
+ other_group_issue = create(:issue, project: other_group_project)
- reorder_issue(issue1,
- move_after_id: issue2.id,
- move_before_id: issue3.id,
- group_full_path: another_group.full_path)
+ reorder_issue(issue1, move_after_id: issue2.id, move_before_id: other_group_issue.id)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -555,15 +550,14 @@ RSpec.describe Projects::IssuesController do
end
end
- def reorder_issue(issue, move_after_id: nil, move_before_id: nil, group_full_path: nil)
+ def reorder_issue(issue, move_after_id: nil, move_before_id: nil)
put :reorder,
params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: issue.iid,
move_after_id: move_after_id,
- move_before_id: move_before_id,
- group_full_path: group_full_path
+ move_before_id: move_before_id
},
format: :json
end
diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
index e07b7e4586a..366a1e587ab 100644
--- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::MergeRequests::ConflictsController do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
let(:merge_request_with_conflicts) do
create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project, merge_status: :unchecked) do |mr|
diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
index df2023b7356..3c650988b4f 100644
--- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::MergeRequests::CreationsController do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:fork_project) { create(:forked_project_with_submodules) }
let(:get_diff_params) do
{
diff --git a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
index 580211893dc..222bb977beb 100644
--- a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Projects::MergeRequests::DraftsController do
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:user2) { create(:user) }
let(:params) do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 36b6df59ef5..2390687c3ea 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Projects::MergeRequestsController do
let_it_be_with_refind(:project) { create(:project, :repository) }
let_it_be_with_reload(:project_public_with_private_builds) { create(:project, :repository, :public, :builds_private) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: merge_request_source_project, allow_collaboration: false) }
let(:merge_request_source_project) { project }
@@ -57,19 +57,13 @@ RSpec.describe Projects::MergeRequestsController do
merge_request.mark_as_unchecked!
end
- context 'check_mergeability_async_in_widget feature flag is disabled' do
- before do
- stub_feature_flags(check_mergeability_async_in_widget: false)
+ it 'checks mergeability asynchronously' do
+ expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
+ expect(service).not_to receive(:execute)
+ expect(service).to receive(:async_execute)
end
- it 'checks mergeability asynchronously' do
- expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
- expect(service).not_to receive(:execute)
- expect(service).to receive(:async_execute)
- end
-
- go
- end
+ go
end
end
@@ -449,7 +443,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when the merge request is not mergeable' do
before do
- merge_request.update!(title: "WIP: #{merge_request.title}")
+ merge_request.update!(title: "Draft: #{merge_request.title}")
post :merge, params: base_params
end
@@ -2084,6 +2078,20 @@ RSpec.describe Projects::MergeRequestsController do
end
end
+ context 'when source branch is protected from force push' do
+ before do
+ create(:protected_branch, project: project, name: merge_request.source_branch, allow_force_push: false)
+ end
+
+ it 'returns 404' do
+ expect_rebase_worker_for(user).never
+
+ post_rebase
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
context 'with a forked project' do
let(:forked_project) { fork_project(project, fork_owner, repository: true) }
let(:fork_owner) { create(:user) }
diff --git a/spec/controllers/projects/mirrors_controller_spec.rb b/spec/controllers/projects/mirrors_controller_spec.rb
index 7c5d14d3a22..7bc86d7c583 100644
--- a/spec/controllers/projects/mirrors_controller_spec.rb
+++ b/spec/controllers/projects/mirrors_controller_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::MirrorsController do
shared_examples 'only admin is allowed when mirroring is disabled' do
let(:subject_action) { raise 'subject_action is required' }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:project_settings_path) { project_settings_repository_path(project, anchor: 'js-push-remote-settings') }
context 'when project mirroring is enabled' do
@@ -88,7 +88,7 @@ RSpec.describe Projects::MirrorsController do
context 'when the current project is not a mirror' do
it 'allows to create a remote mirror' do
- sign_in(project.owner)
+ sign_in(project.first_owner)
expect do
do_put(project, remote_mirrors_attributes: { '0' => { 'enabled' => 1, 'url' => 'http://foo.com' } })
@@ -106,7 +106,7 @@ RSpec.describe Projects::MirrorsController do
end
it 'processes a successful update' do
- sign_in(project.owner)
+ sign_in(project.first_owner)
do_put(project, remote_mirrors_attributes: { '0' => ssh_mirror_attributes })
expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-push-remote-settings'))
@@ -126,7 +126,7 @@ RSpec.describe Projects::MirrorsController do
let(:project) { create(:project, :repository, :remote_mirror) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
context 'With valid URL for a push' do
@@ -169,7 +169,7 @@ RSpec.describe Projects::MirrorsController do
let(:cache) { SshHostKey.new(project: project, url: "ssh://example.com:22") }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
context 'invalid URLs' do
diff --git a/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
index 707edeaeee3..a655c742973 100644
--- a/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
+++ b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
@@ -52,18 +52,6 @@ RSpec.describe Projects::Packages::InfrastructureRegistryController do
expect(assigns(:package_files)).to contain_exactly(terraform_module_package_file)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- subject
-
- expect(assigns(:package_files)).to contain_exactly(package_file_pending_destruction, terraform_module_package_file)
- end
- end
end
end
end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 3fe709a0d44..4a51e2ed5a0 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -1169,7 +1169,7 @@ RSpec.describe Projects::PipelinesController do
context 'when user has ability to delete pipeline' do
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
it 'deletes pipeline and redirects' do
diff --git a/spec/controllers/projects/refs_controller_spec.rb b/spec/controllers/projects/refs_controller_spec.rb
index b625ce35d61..56415663109 100644
--- a/spec/controllers/projects/refs_controller_spec.rb
+++ b/spec/controllers/projects/refs_controller_spec.rb
@@ -47,6 +47,23 @@ RSpec.describe Projects::RefsController do
expect(response).to be_not_found
end
+ context 'when ref is incorrect' do
+ it 'returns 404 page' do
+ xhr_get(:json, id: '.')
+
+ expect(response).to be_not_found
+ end
+ end
+
+ context 'when offset has an invalid format' do
+ it 'renders JSON' do
+ xhr_get(:json, offset: { wrong: :format })
+
+ expect(response).to be_successful
+ expect(json_response).to be_kind_of(Array)
+ end
+ end
+
context 'when json is requested' do
it 'renders JSON' do
expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index 1370ec9cc0b..928428b5caf 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -3,7 +3,37 @@
require "spec_helper"
RSpec.describe Projects::RepositoriesController do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ describe 'POST create' do
+ let_it_be(:user) { create(:user) }
+
+ let(:request) { post :create, params: { namespace_id: project.namespace, project_id: project } }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'when repository does not exist' do
+ let!(:project) { create(:project) }
+
+ it 'creates the repository' do
+ expect { request }.to change { project.repository.raw_repository.exists? }.from(false).to(true)
+
+ expect(response).to be_redirect
+ end
+ end
+
+ context 'when repository already exists' do
+ it 'does not raise an exception' do
+ expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
+ request
+
+ expect(response).to be_redirect
+ end
+ end
+ end
describe "GET archive" do
before do
diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb
index 70ff77d7ff0..246a37129d7 100644
--- a/spec/controllers/projects/runners_controller_spec.rb
+++ b/spec/controllers/projects/runners_controller_spec.rb
@@ -37,6 +37,10 @@ RSpec.describe Projects::RunnersController do
describe '#destroy' do
it 'destroys the runner' do
+ expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
delete :destroy, params: params
expect(response).to have_gitlab_http_status(:found)
diff --git a/spec/controllers/projects/service_ping_controller_spec.rb b/spec/controllers/projects/service_ping_controller_spec.rb
index e6afaadc75f..13b34290962 100644
--- a/spec/controllers/projects/service_ping_controller_spec.rb
+++ b/spec/controllers/projects/service_ping_controller_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Projects::ServicePingController do
shared_examples 'counter is increased' do |counter|
context 'when the authenticated user has access to the project' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it 'increments the usage counter' do
expect do
@@ -55,6 +55,33 @@ RSpec.describe Projects::ServicePingController do
end
context 'when web ide clientside preview is not enabled' do
+ let(:user) { project.first_owner }
+
+ before do
+ stub_application_setting(web_ide_clientside_preview_enabled: false)
+ end
+
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'POST #web_ide_clientside_preview_success' do
+ subject { post :web_ide_clientside_preview_success, params: { namespace_id: project.namespace, project_id: project } }
+
+ context 'when web ide clientside preview is enabled' do
+ before do
+ stub_application_setting(web_ide_clientside_preview_enabled: true)
+ end
+
+ it_behaves_like 'counter is not increased'
+ it_behaves_like 'counter is increased', 'WEB_IDE_PREVIEWS_SUCCESS_COUNT'
+ end
+
+ context 'when web ide clientside preview is not enabled' do
let(:user) { project.owner }
before do
diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb
index 2bb93990c58..22287fea82c 100644
--- a/spec/controllers/projects/settings/repository_controller_spec.rb
+++ b/spec/controllers/projects/settings/repository_controller_spec.rb
@@ -33,6 +33,20 @@ RSpec.describe Projects::Settings::RepositoryController do
expect(response).to redirect_to project_settings_repository_path(project)
end
+
+ context 'when project cleanup returns an error', :aggregate_failures do
+ it 'shows an error' do
+ expect(Projects::CleanupService)
+ .to receive(:enqueue)
+ .with(project, user, anything)
+ .and_return(status: :error, message: 'error message')
+
+ put :cleanup, params: { namespace_id: project.namespace, project_id: project, project: { bfg_object_map: object_map } }
+
+ expect(controller).to set_flash[:alert].to('error message')
+ expect(response).to redirect_to project_settings_repository_path(project)
+ end
+ end
end
describe 'POST create_deploy_token' do
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index 9823c36cb86..f955f9d0248 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -17,6 +17,14 @@ RSpec.describe Projects::TagsController do
expect(assigns(:tags).map(&:name)).to include('v1.1.0', 'v1.0.0')
end
+ context 'default sort for tags' do
+ it 'sorts tags by recently updated' do
+ subject
+
+ expect(assigns(:sort)).to eq('updated_desc')
+ end
+ end
+
context 'when Gitaly is unavailable' do
where(:format) do
[:html, :atom]
@@ -31,6 +39,7 @@ RSpec.describe Projects::TagsController do
get :index, params: { namespace_id: project.namespace.to_param, project_id: project }, format: format
expect(assigns(:tags)).to eq([])
+ expect(assigns(:releases)).to eq([])
expect(response).to have_gitlab_http_status(:service_unavailable)
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 7ebd86640ad..08d1d88fcda 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -1202,6 +1202,26 @@ RSpec.describe ProjectsController do
end
end
end
+
+ context 'when input params are invalid' do
+ let(:request) { get :refs, params: { namespace_id: project.namespace, id: project, ref: { invalid: :format } } }
+
+ it 'does not break' do
+ request
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+
+ context 'when "strong_parameters_for_project_controller" FF is disabled' do
+ before do
+ stub_feature_flags(strong_parameters_for_project_controller: false)
+ end
+
+ it 'raises an exception' do
+ expect { request }.to raise_error(TypeError)
+ end
+ end
+ end
end
describe 'POST #preview_markdown' do
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index d5fe32ac094..af34ae2f69b 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -456,6 +456,28 @@ RSpec.describe RegistrationsController do
subject
end
+
+ describe 'logged_out_marketing_header experiment', :experiment do
+ before do
+ stub_experiments(logged_out_marketing_header: :candidate)
+ end
+
+ it 'tracks signed_up event' do
+ expect(experiment(:logged_out_marketing_header)).to track(:signed_up).on_next_instance
+
+ subject
+ end
+
+ context 'when registration fails' do
+ let_it_be(:user_params) { { user: base_user_params.merge({ username: '' }) } }
+
+ it 'does not track signed_up event' do
+ expect(experiment(:logged_out_marketing_header)).not_to track(:signed_up)
+
+ subject
+ end
+ end
+ end
end
describe '#destroy' do
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index 4a6e745cd63..fb2637238ec 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Repositories::GitHttpController do
context 'when repository container is a project' do
it_behaves_like Repositories::GitHttpController do
let(:container) { project }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:access_checker_class) { Gitlab::GitAccess }
it_behaves_like 'handles unavailable Gitaly'
@@ -103,7 +103,7 @@ RSpec.describe Repositories::GitHttpController do
context 'when repository container is a project wiki' do
it_behaves_like Repositories::GitHttpController do
let(:container) { create(:project_wiki, :empty_repo, project: project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:access_checker_class) { Gitlab::GitAccessWiki }
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 58d34a5e5c1..0f1501d4c3c 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -397,9 +397,10 @@ RSpec.describe SearchController do
expect(payload[:metadata]['meta.search.filters.confidential']).to eq('true')
expect(payload[:metadata]['meta.search.filters.state']).to eq('true')
expect(payload[:metadata]['meta.search.project_ids']).to eq(%w(456 789))
+ expect(payload[:metadata]['meta.search.search_level']).to eq('multi-project')
end
- get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', project_ids: %w(456 789), confidential: true, state: true, force_search_results: true }
+ get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', project_ids: %w(456 789), search_level: 'multi-project', confidential: true, state: true, force_search_results: true }
end
it 'appends the default scope in meta.search.scope' do
diff --git a/spec/crystalball_env.rb b/spec/crystalball_env.rb
index d606fe69cdf..cd609dfb3f9 100644
--- a/spec/crystalball_env.rb
+++ b/spec/crystalball_env.rb
@@ -6,7 +6,7 @@ module CrystalballEnv
extend self
def start!
- return unless ENV['CRYSTALBALL']
+ return unless ENV['CRYSTALBALL'] == 'true'
require 'crystalball'
require_relative '../tooling/lib/tooling/crystalball/coverage_lines_execution_detector'
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 9bd6691bdb2..2608a13a399 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'Database schema' do
boards: %w[milestone_id iteration_id],
chat_names: %w[chat_id team_id user_id],
chat_teams: %w[team_id],
- ci_builds: %w[erased_by_id runner_id trigger_request_id],
+ ci_builds: %w[erased_by_id trigger_request_id],
ci_namespace_monthly_usages: %w[namespace_id],
ci_runner_projects: %w[runner_id],
ci_trigger_requests: %w[commit_id],
diff --git a/spec/events/projects/project_deleted_event_spec.rb b/spec/events/projects/project_deleted_event_spec.rb
new file mode 100644
index 00000000000..fd8cec7271b
--- /dev/null
+++ b/spec/events/projects/project_deleted_event_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ProjectDeletedEvent do
+ where(:data, :valid) do
+ [
+ [{ project_id: 1, namespace_id: 2 }, true],
+ [{ project_id: 1 }, false],
+ [{ namespace_id: 1 }, false],
+ [{ project_id: 'foo', namespace_id: 2 }, false],
+ [{ project_id: 1, namespace_id: 'foo' }, false],
+ [{ project_id: [], namespace_id: 2 }, false],
+ [{ project_id: 1, namespace_id: [] }, false],
+ [{ project_id: {}, namespace_id: 2 }, false],
+ [{ project_id: 1, namespace_id: {} }, false],
+ ['foo', false],
+ [123, false],
+ [[], false]
+ ]
+ end
+
+ with_them do
+ it 'validates data' do
+ constructor = -> { described_class.new(data: data) }
+
+ if valid
+ expect { constructor.call }.not_to raise_error
+ else
+ expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
+ end
+ end
+ end
+end
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb
index 5146fe3e752..70ee4bd3c5a 100644
--- a/spec/experiments/application_experiment_spec.rb
+++ b/spec/experiments/application_experiment_spec.rb
@@ -24,38 +24,6 @@ RSpec.describe ApplicationExperiment, :experiment do
expect { experiment('namespaced/stub') { } }.not_to raise_error
end
- describe "#enabled?" do
- before do
- allow(application_experiment).to receive(:enabled?).and_call_original
-
- allow(Feature::Definition).to receive(:get).and_return('_instance_')
- allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
- allow(Feature).to receive(:get).and_return(double(state: :on))
- end
-
- it "is enabled when all criteria are met" do
- expect(application_experiment).to be_enabled
- end
-
- it "isn't enabled if the feature definition doesn't exist" do
- expect(Feature::Definition).to receive(:get).with('namespaced_stub').and_return(nil)
-
- expect(application_experiment).not_to be_enabled
- end
-
- it "isn't enabled if we're not in dev or dotcom environments" do
- expect(Gitlab).to receive(:dev_env_or_com?).and_return(false)
-
- expect(application_experiment).not_to be_enabled
- end
-
- it "isn't enabled if the feature flag state is :off" do
- expect(Feature).to receive(:get).with('namespaced_stub').and_return(double(state: :off))
-
- expect(application_experiment).not_to be_enabled
- end
- end
-
describe "#publish" do
let(:should_track) { true }
@@ -117,7 +85,7 @@ RSpec.describe ApplicationExperiment, :experiment do
describe '#publish_to_database' do
using RSpec::Parameterized::TableSyntax
- let(:publish_to_database) { application_experiment.publish_to_database }
+ let(:publish_to_database) { ActiveSupport::Deprecation.silence { application_experiment.publish_to_database } }
shared_examples 'does not record to the database' do
it 'does not create an experiment record' do
@@ -214,26 +182,6 @@ RSpec.describe ApplicationExperiment, :experiment do
)
end
- it "tracks the event correctly even when using the base class" do
- subject = Gitlab::Experiment.new(:unnamed)
- subject.track(:action, context: [fake_context])
-
- expect_snowplow_event(
- category: 'unnamed',
- action: 'action',
- context: [
- {
- schema: 'iglu:com.gitlab/fake/jsonschema/0-0-0',
- data: { data: '_data_' }
- },
- {
- schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0',
- data: { experiment: 'unnamed', key: subject.context.key, variant: 'control' }
- }
- ]
- )
- end
-
context "when using known context resources" do
let(:user) { build(:user, id: non_existing_record_id) }
let(:project) { build(:project, id: non_existing_record_id) }
@@ -347,23 +295,15 @@ RSpec.describe ApplicationExperiment, :experiment do
end
context "when resolving variants" do
- it "uses the default value as specified in the yaml" do
- expect(Feature).to receive(:enabled?).with('namespaced_stub', application_experiment, type: :experiment, default_enabled: :yaml)
-
- expect(application_experiment.variant.name).to eq('control')
+ before do
+ stub_feature_flags(namespaced_stub: true)
end
- context "when rolled out to 100%" do
- before do
- stub_feature_flags(namespaced_stub: true)
- end
-
- it "returns the first variant name" do
- application_experiment.try(:variant1) {}
- application_experiment.try(:variant2) {}
+ it "returns an assigned name" do
+ application_experiment.variant(:variant1) {}
+ application_experiment.variant(:variant2) {}
- expect(application_experiment.variant.name).to eq('variant1')
- end
+ expect(application_experiment.assigned.name).to eq('variant2')
end
end
@@ -395,8 +335,8 @@ RSpec.describe ApplicationExperiment, :experiment do
cache.clear(key: application_experiment.name)
- application_experiment.use { } # setup the control
- application_experiment.try { } # setup the candidate
+ application_experiment.control { }
+ application_experiment.candidate { }
end
it "caches the variant determined by the variant resolver" do
@@ -451,4 +391,29 @@ RSpec.describe ApplicationExperiment, :experiment do
end
end
end
+
+ context "with deprecation warnings" do
+ before do
+ Gitlab::Experiment::Configuration.instance_variable_set(:@__dep_versions, nil) # clear the internal memoization
+
+ allow(ActiveSupport::Deprecation).to receive(:new).and_call_original
+ end
+
+ it "doesn't warn on non dev/test environments" do
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(false)
+
+ expect { experiment(:example) { |e| e.use { } } }.not_to raise_error
+ expect(ActiveSupport::Deprecation).not_to have_received(:new).with(anything, 'Gitlab::Experiment')
+ end
+
+ it "warns on dev and test environments" do
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(true)
+
+ # This will eventually raise an ActiveSupport::Deprecation exception,
+ # it's ok to change it when that happens.
+ expect { experiment(:example) { |e| e.use { } } }.not_to raise_error
+
+ expect(ActiveSupport::Deprecation).to have_received(:new).with(anything, 'Gitlab::Experiment')
+ end
+ end
end
diff --git a/spec/experiments/new_project_readme_content_experiment_spec.rb b/spec/experiments/new_project_readme_content_experiment_spec.rb
deleted file mode 100644
index a6a81580a29..00000000000
--- a/spec/experiments/new_project_readme_content_experiment_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe NewProjectReadmeContentExperiment, :experiment do
- subject { described_class.new(namespace: project.namespace) }
-
- let(:project) { create(:project, name: 'Experimental', description: 'An experiment project') }
-
- it "renders the basic README" do
- expect(subject.run_with(project)).to eq(<<~MARKDOWN.strip)
- # Experimental
-
- An experiment project
- MARKDOWN
- end
-
- describe "the advanced variant" do
- let(:markdown) { subject.run_with(project, variant: :advanced) }
- let(:initial_url) { 'https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file' }
-
- it "renders the project details" do
- expect(markdown).to include(<<~MARKDOWN.strip)
- # Experimental
-
- An experiment project
-
- ## Getting started
- MARKDOWN
- end
-
- it "renders redirect URLs" do
- url = Rails.application.routes.url_helpers.experiment_redirect_url(subject, url: initial_url)
- expect(url).to include("/-/experiment/#{subject.to_param}?")
- expect(markdown).to include(url)
- end
- end
-end
diff --git a/spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb b/spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb
index 87417fe1637..269b6222020 100644
--- a/spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb
+++ b/spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe RequireVerificationForNamespaceCreationExperiment, :experiment do
subject(:experiment) { described_class.new(user: user) }
- let_it_be(:user) { create(:user) }
+ let(:user_created_at) { RequireVerificationForNamespaceCreationExperiment::EXPERIMENT_START_DATE + 1.hour }
+ let(:user) { create(:user, created_at: user_created_at) }
describe '#candidate?' do
context 'when experiment subject is candidate' do
@@ -56,4 +57,21 @@ RSpec.describe RequireVerificationForNamespaceCreationExperiment, :experiment do
end
end
end
+
+ describe 'exclusions' do
+ context 'when user is new' do
+ it 'is not excluded' do
+ expect(subject).not_to exclude(user: user)
+ end
+ end
+
+ context 'when user is NOT new' do
+ let(:user_created_at) { RequireVerificationForNamespaceCreationExperiment::EXPERIMENT_START_DATE - 1.day }
+ let(:user) { create(:user, created_at: user_created_at) }
+
+ it 'is excluded' do
+ expect(subject).to exclude(user: user)
+ end
+ end
+ end
end
diff --git a/spec/factories/ci/build_metadata.rb b/spec/factories/ci/build_metadata.rb
new file mode 100644
index 00000000000..cfc86c4ef4b
--- /dev/null
+++ b/spec/factories/ci/build_metadata.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_build_metadata, class: 'Ci::BuildMetadata' do
+ build { association(:ci_build, strategy: :build, metadata: instance) }
+ end
+end
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index 6665b7b76a0..18026412261 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -13,6 +13,7 @@ FactoryBot.define do
transient do
groups { [] }
projects { [] }
+ token_expires_at { nil }
end
after(:build) do |runner, evaluator|
@@ -25,6 +26,10 @@ FactoryBot.define do
end
end
+ after(:create) do |runner, evaluator|
+ runner.update!(token_expires_at: evaluator.token_expires_at) if evaluator.token_expires_at
+ end
+
trait :online do
contacted_at { Time.now }
end
diff --git a/spec/factories/container_repositories.rb b/spec/factories/container_repositories.rb
index 86bb129067f..ce83e9e8006 100644
--- a/spec/factories/container_repositories.rb
+++ b/spec/factories/container_repositories.rb
@@ -33,6 +33,52 @@ FactoryBot.define do
expiration_policy_cleanup_status { :cleanup_ongoing }
end
+ trait :default do
+ migration_state { 'default' }
+ end
+
+ trait :pre_importing do
+ migration_state { 'pre_importing' }
+ migration_pre_import_started_at { Time.zone.now }
+ end
+
+ trait :pre_import_done do
+ migration_state { 'pre_import_done' }
+ migration_pre_import_started_at { Time.zone.now }
+ migration_pre_import_done_at { Time.zone.now }
+ end
+
+ trait :importing do
+ migration_state { 'importing' }
+ migration_pre_import_started_at { Time.zone.now }
+ migration_pre_import_done_at { Time.zone.now }
+ migration_import_started_at { Time.zone.now }
+ end
+
+ trait :import_done do
+ migration_state { 'import_done' }
+ migration_pre_import_started_at { Time.zone.now }
+ migration_pre_import_done_at { Time.zone.now }
+ migration_import_started_at { Time.zone.now }
+ migration_import_done_at { Time.zone.now }
+ end
+
+ trait :import_aborted do
+ migration_state { 'import_aborted' }
+ migration_pre_import_started_at { Time.zone.now }
+ migration_pre_import_done_at { Time.zone.now }
+ migration_import_started_at { Time.zone.now }
+ migration_aborted_at { Time.zone.now }
+ migration_aborted_in_state { 'importing' }
+ migration_retries_count { 1 }
+ end
+
+ trait :import_skipped do
+ migration_state { 'import_skipped' }
+ migration_skipped_at { Time.zone.now }
+ migration_skipped_reason { :too_many_tags }
+ end
+
after(:build) do |repository, evaluator|
next if evaluator.tags.to_a.none?
diff --git a/spec/factories/gitlab/database/background_migration/batched_jobs.rb b/spec/factories/gitlab/database/background_migration/batched_jobs.rb
index cec20616f7f..3c7dcd03701 100644
--- a/spec/factories/gitlab/database/background_migration/batched_jobs.rb
+++ b/spec/factories/gitlab/database/background_migration/batched_jobs.rb
@@ -9,5 +9,21 @@ FactoryBot.define do
batch_size { 5 }
sub_batch_size { 1 }
pause_ms { 100 }
+
+ trait(:pending) do
+ status { 0 }
+ end
+
+ trait(:running) do
+ status { 1 }
+ end
+
+ trait(:failed) do
+ status { 2 }
+ end
+
+ trait(:succeeded) do
+ status { 3 }
+ end
end
end
diff --git a/spec/factories/go_module_commits.rb b/spec/factories/go_module_commits.rb
index 514a5559344..4f86d38954c 100644
--- a/spec/factories/go_module_commits.rb
+++ b/spec/factories/go_module_commits.rb
@@ -17,7 +17,7 @@ FactoryBot.define do
service do
Files::MultiService.new(
project,
- project.owner,
+ project.first_owner,
commit_message: message,
start_branch: project.repository.root_ref || 'master',
branch_name: project.repository.root_ref || 'master',
@@ -38,7 +38,7 @@ FactoryBot.define do
commit = project.repository.commit_by(oid: r[:result])
if tag
- r = Tags::CreateService.new(project, project.owner).execute(tag, commit.sha, tag_message)
+ r = Tags::CreateService.new(project, project.first_owner).execute(tag, commit.sha, tag_message)
raise "operation failed: #{r}" unless r[:status] == :success
end
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index ab2321c81c4..4b1bf9a7d11 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -35,6 +35,18 @@ FactoryBot.define do
access_level { GroupMember::MINIMAL_ACCESS }
end
+ trait :awaiting do
+ after(:create) do |member|
+ member.update!(state: ::Member::STATE_AWAITING)
+ end
+ end
+
+ trait :active do
+ after(:create) do |member|
+ member.update!(state: ::Member::STATE_ACTIVE)
+ end
+ end
+
transient do
tasks_to_be_done { [] }
end
diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb
index 8b53732a3c1..26c858665a8 100644
--- a/spec/factories/issues.rb
+++ b/spec/factories/issues.rb
@@ -61,6 +61,15 @@ FactoryBot.define do
factory :incident do
issue_type { :incident }
association :work_item_type, :default, :incident
+
+ # An escalation status record is created for all incidents
+ # in app code. This is a trait to avoid creating escalation
+ # status records in specs which do not need them.
+ trait :with_escalation_status do
+ after(:create) do |incident|
+ create(:incident_management_issuable_escalation_status, issue: incident)
+ end
+ end
end
end
end
diff --git a/spec/factories/keys.rb b/spec/factories/keys.rb
index cf52e772ae0..2af1c6cc62d 100644
--- a/spec/factories/keys.rb
+++ b/spec/factories/keys.rb
@@ -1,14 +1,12 @@
# frozen_string_literal: true
-require_relative '../support/helpers/key_generator_helper'
-
FactoryBot.define do
factory :key do
title
- key { Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate + ' dummy@gitlab.com' }
+ key { SSHData::PrivateKey::RSA.generate(1024, unsafe_allow_small_key: true).public_key.openssh(comment: 'dummy@gitlab.com') }
factory :key_without_comment do
- key { Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate }
+ key { SSHData::PrivateKey::RSA.generate(1024, unsafe_allow_small_key: true).public_key.openssh }
end
factory :deploy_key, class: 'DeployKey'
@@ -148,5 +146,24 @@ FactoryBot.define do
KEY
end
end
+
+ factory :ecdsa_sk_key_256 do
+ key do
+ <<~KEY.delete("\n")
+ sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyN
+ TZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBDZ+f5tSRhlB7EN39f93SscTN5PUv
+ bD3UQsNrlE1ZdbwPMMRul2zlPiUvwAvnJitW0jlD/vwZOW2YN+q+iZ5c0MAAAAEc3NoOg== dummy@gitlab.com
+ KEY
+ end
+ end
+
+ factory :ed25519_sk_key_256 do
+ key do
+ <<~KEY.delete("\n")
+ sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tA
+ AAAIEX/dQ0v4127bEo8eeG1EV0ApO2lWbSnN6RWusn/NjqIAAAABHNzaDo= dummy@gitlab.com
+ KEY
+ end
+ end
end
end
diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb
index f0cef41db69..250c92c0038 100644
--- a/spec/factories/labels.rb
+++ b/spec/factories/labels.rb
@@ -18,13 +18,6 @@ FactoryBot.define do
title { "#{prefix}::#{generate(:label_title)}" }
end
- trait :incident do
- properties = IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES
- title { properties.fetch(:title) }
- description { properties.fetch(:description) }
- color { properties.fetch(:color) }
- end
-
factory :label, traits: [:base_label], class: 'ProjectLabel' do
project
diff --git a/spec/factories/namespace_statistics.rb b/spec/factories/namespace_statistics.rb
new file mode 100644
index 00000000000..49e2c8957c5
--- /dev/null
+++ b/spec/factories/namespace_statistics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :namespace_statistics do
+ namespace factory: :namespace
+ end
+end
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index f2dedc178c7..c38257b06b6 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -24,6 +24,18 @@ FactoryBot.define do
after(:build) { |project_member, _| project_member.user.block! }
end
+ trait :awaiting do
+ after(:create) do |member|
+ member.update!(state: ::Member::STATE_AWAITING)
+ end
+ end
+
+ trait :active do
+ after(:create) do |member|
+ member.update!(state: ::Member::STATE_ACTIVE)
+ end
+ end
+
transient do
tasks_to_be_done { [] }
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index c345fa0c8b4..8a406f95f58 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -82,7 +82,7 @@ FactoryBot.define do
# user have access to the project. Our specs don't use said service class,
# thus we must manually refresh things here.
unless project.group || project.pending_delete
- project.add_maintainer(project.owner)
+ project.add_maintainer(project.first_owner)
end
project.group&.refresh_members_authorized_projects
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index f00d1f8b808..86799af1719 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -58,14 +58,6 @@ FactoryBot.define do
# Tracing
create(:project_tracing_setting, project: projects[0])
- # Incident Labeled Issues
- incident_label = create(:label, :incident, project: projects[0])
- create(:labeled_issue, project: projects[0], labels: [incident_label])
- incident_label_scoped_to_project = create(:label, :incident, project: projects[1])
- incident_label_scoped_to_group = create(:group_label, :incident, group: group)
- create(:labeled_issue, project: projects[1], labels: [incident_label_scoped_to_project])
- create(:labeled_issue, project: projects[1], labels: [incident_label_scoped_to_group])
-
# Alert Issues
create(:alert_management_alert, issue: issues[0], project: projects[0])
create(:alert_management_alert, issue: alert_bot_issues[0], project: projects[0])
diff --git a/spec/factories/work_items.rb b/spec/factories/work_items.rb
new file mode 100644
index 00000000000..6d9dcac6165
--- /dev/null
+++ b/spec/factories/work_items.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :work_item, traits: [:has_internal_id] do
+ title { generate(:title) }
+ project
+ author { project.creator }
+ updated_by { author }
+ relative_position { RelativePositioning::START_POSITION }
+ issue_type { :issue }
+ association :work_item_type, :default
+ end
+end
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 8d4e7a7442c..a0a41061d64 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Admin Groups' do
include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Spec::Support::Helpers::ModalHelpers
let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
@@ -250,26 +251,26 @@ RSpec.describe 'Admin Groups' do
end
end
- describe 'admin remove themself from a group', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222342' do
+ describe 'admin removes themself from a group', :js do
it 'removes admin from the group' do
- stub_feature_flags(bootstrap_confirmation_modals: false)
group.add_user(current_user, Gitlab::Access::DEVELOPER)
visit group_group_members_path(group)
- page.within '[data-qa-selector="members_list"]' do # rubocop:disable QA/SelectorUsage
+ page.within members_table do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
- accept_confirm { find(:css, 'li', text: current_user.name).find(:css, 'a.btn-danger').click }
+ find_member_row(current_user).click_button(title: 'Leave')
+
+ accept_gl_confirm(button_text: 'Leave')
+
+ wait_for_all_requests
visit group_group_members_path(group)
- page.within '[data-qa-selector="members_list"]' do # rubocop:disable QA/SelectorUsage
- expect(page).not_to have_content(current_user.name)
- expect(page).not_to have_content('Developer')
- end
+ expect(members_table).not_to have_content(current_user.name)
end
end
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index 58bea5c4b5f..f2f6e26fbee 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Admin Mode Logout', :js do
it 'disable shows flash notice' do
gitlab_disable_admin_mode
- expect(page).to have_selector('.flash-notice')
+ expect(page).to have_selector('[data-testid="alert-info"]')
end
context 'on a read-only instance' do
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index ceb91b86876..25ff4022454 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -254,6 +254,18 @@ RSpec.describe "Admin Runners" do
expect(page).not_to have_content 'runner-group'
end
+ it 'show the same counts after selecting another tab' do
+ visit admin_runners_path
+
+ page.within('[data-testid="runner-type-tabs"]') do
+ click_on('Project')
+
+ expect(page).to have_link('All 2')
+ expect(page).to have_link('Group 1')
+ expect(page).to have_link('Project 1')
+ end
+ end
+
it 'shows no runner when type does not match' do
visit admin_runners_path
@@ -460,7 +472,7 @@ RSpec.describe "Admin Runners" do
click_on 'Reset registration token'
within_modal do
- click_button('OK', match: :first)
+ click_button('Reset token', match: :first)
end
wait_for_requests
@@ -476,6 +488,42 @@ RSpec.describe "Admin Runners" do
end
end
+ describe "Runner show page", :js do
+ let(:runner) do
+ create(
+ :ci_runner,
+ description: 'runner-foo',
+ version: '14.0',
+ ip_address: '127.0.0.1',
+ tag_list: ['tag1']
+ )
+ end
+
+ before do
+ visit admin_runner_path(runner)
+ end
+
+ describe 'runner show page breadcrumbs' do
+ it 'contains the current runner id and token' do
+ page.within '[data-testid="breadcrumb-links"]' do
+ expect(page.find('h2')).to have_link("##{runner.id} (#{runner.short_sha})")
+ end
+ end
+ end
+
+ it 'shows runner details' do
+ aggregate_failures do
+ expect(page).to have_content 'Description runner-foo'
+ expect(page).to have_content 'Last contact Never contacted'
+ expect(page).to have_content 'Version 14.0'
+ expect(page).to have_content 'IP Address 127.0.0.1'
+ expect(page).to have_content 'Configuration Runs untagged jobs'
+ expect(page).to have_content 'Maximum job timeout None'
+ expect(page).to have_content 'Tags tag1'
+ end
+ end
+ end
+
describe "Runner edit page" do
let(:runner) { create(:ci_runner) }
@@ -487,7 +535,7 @@ RSpec.describe "Admin Runners" do
wait_for_requests
end
- describe 'runner page breadcrumbs' do
+ describe 'runner edit page breadcrumbs' do
it 'contains the current runner id and token' do
page.within '[data-testid="breadcrumb-links"]' do
expect(page).to have_link("##{runner.id} (#{runner.short_sha})")
diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb
index 94fb3a0314f..a3d0c7bdd4d 100644
--- a/spec/features/admin/admin_sees_background_migrations_spec.rb
+++ b/spec/features/admin/admin_sees_background_migrations_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "Admin > Admin sees background migrations" do
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: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3)
+ create(:batched_background_migration_job, :failed, batched_migration: failed_migration, batch_size: 10, min_value: 6, max_value: 15, attempts: 3)
end
before do
@@ -68,7 +68,7 @@ RSpec.describe "Admin > Admin sees background migrations" do
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(tab[:class]).to include('gl-tab-nav-item-active')
expect(page).to have_selector('tbody tr', count: 1)
@@ -93,7 +93,7 @@ RSpec.describe "Admin > Admin sees background migrations" do
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(tab[:class]).to include('gl-tab-nav-item-active')
expect(page).to have_selector('tbody tr', count: 1)
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index e136ab41966..ca452264c02 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -85,6 +85,8 @@ RSpec.describe 'Admin updates settings' do
select 'Are allowed', from: 'DSA SSH keys'
select 'Must be at least 384 bits', from: 'ECDSA SSH keys'
select 'Are forbidden', from: 'ED25519 SSH keys'
+ select 'Are forbidden', from: 'ECDSA_SK SSH keys'
+ select 'Are forbidden', from: 'ED25519_SK SSH keys'
click_on 'Save changes'
end
@@ -95,6 +97,8 @@ RSpec.describe 'Admin updates settings' do
expect(find_field('DSA SSH keys').value).to eq('0')
expect(find_field('ECDSA SSH keys').value).to eq('384')
expect(find_field('ED25519 SSH keys').value).to eq(forbidden)
+ expect(find_field('ECDSA_SK SSH keys').value).to eq(forbidden)
+ expect(find_field('ED25519_SK SSH keys').value).to eq(forbidden)
end
it 'change Account and Limit Settings' do
@@ -528,7 +532,7 @@ RSpec.describe 'Admin updates settings' do
expect(find_field('Allow access to members of the following group').value).to be_nil
end
- it 'loads usage ping payload on click', :js do
+ it 'loads togglable usage ping payload on click', :js do
stub_usage_data_connections
stub_database_flavor_check
@@ -544,6 +548,10 @@ RSpec.describe 'Admin updates settings' do
expect(page).to have_selector '.js-service-ping-payload'
expect(page).to have_button 'Hide payload'
expect(page).to have_content expected_payload_content
+
+ click_button('Hide payload')
+
+ expect(page).not_to have_content expected_payload_content
end
end
end
@@ -623,6 +631,20 @@ RSpec.describe 'Admin updates settings' do
expect(current_settings.issues_create_limit).to eq(0)
end
+ it 'changes Users API rate limits settings' do
+ visit network_admin_application_settings_path
+
+ page.within('.as-users-api-limits') do
+ fill_in 'Maximum requests per 10 minutes per user', with: 0
+ fill_in 'Users to exclude from the rate limit', with: 'someone, someone_else'
+ click_button 'Save changes'
+ end
+
+ expect(page).to have_content "Application settings saved successfully"
+ expect(current_settings.users_get_by_id_limit).to eq(0)
+ expect(current_settings.users_get_by_id_limit_allowlist).to eq(%w[someone someone_else])
+ end
+
shared_examples 'regular throttle rate limit settings' do
it 'changes rate limit settings' do
visit network_admin_application_settings_path
@@ -771,6 +793,38 @@ RSpec.describe 'Admin updates settings' do
end
end
end
+
+ context 'Service usage data page' do
+ before do
+ stub_usage_data_connections
+ stub_database_flavor_check
+
+ visit service_usage_data_admin_application_settings_path
+ end
+
+ it 'loads usage ping payload on click', :js do
+ expected_payload_content = /(?=.*"uuid")(?=.*"hostname")/m
+
+ expect(page).not_to have_content expected_payload_content
+
+ click_button('Preview payload')
+
+ wait_for_requests
+
+ expect(page).to have_button 'Hide payload'
+ expect(page).to have_content expected_payload_content
+ end
+
+ it 'generates usage ping payload on button click', :js do
+ expect_next_instance_of(Admin::ApplicationSettingsController) do |instance|
+ expect(instance).to receive(:usage_data).and_call_original
+ end
+
+ click_button('Download payload')
+
+ wait_for_requests
+ end
+ end
end
context 'application setting :admin_mode is disabled' do
diff --git a/spec/features/admin/integrations/instance_integrations_spec.rb b/spec/features/admin/integrations/instance_integrations_spec.rb
new file mode 100644
index 00000000000..7b326ec161c
--- /dev/null
+++ b/spec/features/admin/integrations/instance_integrations_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Instance integrations', :js do
+ include_context 'instance integration activation'
+
+ it_behaves_like 'integration settings form' do
+ let(:integrations) { Integration.find_or_initialize_all_non_project_specific(Integration.for_instance) }
+
+ def navigate_to_integration(integration)
+ visit_instance_integration(integration.title)
+ 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
index 793a5bced00..22a27b33671 100644
--- a/spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb
@@ -19,19 +19,4 @@ RSpec.describe 'User activates the instance-level Mattermost Slash Command integ
expect(page).to have_link('Settings', href: edit_path)
expect(page).to have_link('Projects using custom settings', href: overrides_path)
end
-
- it 'does not render integration form element' do
- expect(page).not_to have_selector('[data-testid="integration-form"]')
- end
-
- context 'when `vue_integration_form` feature flag is disabled' do
- before do
- stub_feature_flags(vue_integration_form: false)
- visit_instance_integration('Mattermost slash commands')
- end
-
- it 'renders integration form element' do
- expect(page).to have_selector('[data-testid="integration-form"]')
- end
- end
end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index 473f51370b3..5b0b6e085c9 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin::Users' do
include Spec::Support::Helpers::Features::AdminUsersHelpers
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user, reload: true) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
let_it_be(:current_user) { create(:admin) }
@@ -294,6 +295,22 @@ RSpec.describe 'Admin::Users' do
end
end
+ context 'when a user is locked', time_travel_to: '2020-02-25 10:30:45 -0700' do
+ let_it_be(:locked_user) { create(:user, locked_at: DateTime.parse('2020-02-25 10:30:00 -0700')) }
+
+ it "displays `Locked` badge next to user" do
+ expect(page).to have_content("#{locked_user.name} Locked")
+ end
+
+ it 'allows a user to be unlocked from the `User administration dropdown', :js do
+ accept_gl_confirm("Unlock user #{locked_user.name}?", button_text: 'Unlock') do
+ click_action_in_user_dropdown(locked_user.id, 'Unlock')
+ end
+
+ expect(page).not_to have_content("#{locked_user.name} (Locked)")
+ end
+ end
+
describe 'internal users' do
context 'when showing a `Ghost User`' do
let_it_be(:ghost_user) { create(:user, :ghost) }
diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb
index 49375e4b37b..e37bf515088 100644
--- a/spec/features/boards/board_filters_spec.rb
+++ b/spec/features/boards/board_filters_spec.rb
@@ -7,15 +7,15 @@ RSpec.describe 'Issue board filters', :js do
let_it_be(:user) { create(:user) }
let_it_be(:board) { create(:board, project: project) }
let_it_be(:project_label) { create(:label, project: project, title: 'Label') }
- let_it_be(:milestone_1) { create(:milestone, project: project) }
- let_it_be(:milestone_2) { create(:milestone, project: project) }
+ let_it_be(:milestone_1) { create(:milestone, project: project, due_date: 3.days.from_now ) }
+ let_it_be(:milestone_2) { create(:milestone, project: project, due_date: Date.tomorrow ) }
let_it_be(:release) { create(:release, tag: 'v1.0', project: project, milestones: [milestone_1]) }
let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project, milestones: [milestone_2]) }
let_it_be(:issue_1) { create(:issue, project: project, milestone: milestone_1, author: user) }
let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label], confidential: true) }
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
- let(:filtered_search) { find('[data-testid="issue_1-board-filtered-search"]') }
+ let(:filtered_search) { find('[data-testid="issue-board-filtered-search"]') }
let(:filter_input) { find('.gl-filtered-search-term-input')}
let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
@@ -134,8 +134,11 @@ RSpec.describe 'Issue board filters', :js do
expect(filter_dropdown).to have_content('Any')
expect(filter_dropdown).to have_content('Started')
expect(filter_dropdown).to have_content('Upcoming')
- expect(filter_dropdown).to have_content(milestone_1.title)
- expect(filter_dropdown).to have_content(milestone_2.title)
+
+ dropdown_nodes = page.find_all('.gl-filtered-search-suggestion-list > .gl-filtered-search-suggestion')
+
+ expect(dropdown_nodes[4]).to have_content(milestone_2.title)
+ expect(dropdown_nodes.last).to have_content(milestone_1.title)
click_on milestone_1.title
filter_submit.click
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index d25cddea902..2ca4ff94911 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -583,7 +583,11 @@ RSpec.describe 'Project issue boards', :js do
end
page.within(find('.js-board-settings-sidebar')) do
- accept_confirm { find('[data-testid="remove-list"]').click }
+ click_button 'Remove list'
+ end
+
+ page.within('.modal') do
+ click_button 'Remove list'
end
end
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index f88d31bda88..5f4517d47ee 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -3,12 +3,13 @@
require 'spec_helper'
RSpec.describe 'Issue Boards new issue', :js do
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:board) { create(:board, project: project) }
- let_it_be(:backlog_list) { create(:backlog_list, board: board) }
- let_it_be(:label) { create(:label, project: project, name: 'Label 1') }
- let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
- let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:backlog_list) { create(:backlog_list, board: board) }
+ let_it_be(:label) { create(:label, project: project, name: 'Label 1') }
+ let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:existing_issue) { create(:issue, project: project, title: 'other issue', relative_position: 50) }
let(:board_list_header) { first('[data-testid="board-list-header"]') }
let(:project_select_dropdown) { find('[data-testid="project-select-dropdown"]') }
@@ -56,7 +57,7 @@ RSpec.describe 'Issue Boards new issue', :js do
end
end
- it 'creates new issue and opens sidebar' do
+ it 'creates new issue, places it on top of the list, and opens sidebar' do
page.within(first('.board')) do
click_button 'New issue'
end
@@ -69,12 +70,14 @@ RSpec.describe 'Issue Boards new issue', :js do
wait_for_requests
page.within(first('.board [data-testid="issue-count-badge"]')) do
- expect(page).to have_content('1')
+ expect(page).to have_content('2')
end
page.within(first('.board-card')) do
issue = project.issues.find_by_title('bug')
+ expect(issue.relative_position).to be < existing_issue.relative_position
+
expect(page).to have_content(issue.to_reference)
expect(page).to have_link(issue.title, href: /#{issue_path(issue)}/)
end
diff --git a/spec/features/breadcrumbs_schema_markup_spec.rb b/spec/features/breadcrumbs_schema_markup_spec.rb
index a87a3d284de..f86ad5cd2ae 100644
--- a/spec/features/breadcrumbs_schema_markup_spec.rb
+++ b/spec/features/breadcrumbs_schema_markup_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Breadcrumbs schema markup', :aggregate_failures do
expect(item_list.size).to eq 2
expect(item_list[0]['name']).to eq project.namespace.name
- expect(item_list[0]['item']).to eq user_url(project.owner)
+ expect(item_list[0]['item']).to eq user_url(project.first_owner)
expect(item_list[1]['name']).to eq project.name
expect(item_list[1]['item']).to eq project_url(project)
@@ -59,7 +59,7 @@ RSpec.describe 'Breadcrumbs schema markup', :aggregate_failures do
expect(item_list.size).to eq 3
expect(item_list[0]['name']).to eq project.namespace.name
- expect(item_list[0]['item']).to eq user_url(project.owner)
+ expect(item_list[0]['item']).to eq user_url(project.first_owner)
expect(item_list[1]['name']).to eq project.name
expect(item_list[1]['item']).to eq project_url(project)
@@ -75,7 +75,7 @@ RSpec.describe 'Breadcrumbs schema markup', :aggregate_failures do
expect(item_list.size).to eq 4
expect(item_list[0]['name']).to eq project.namespace.name
- expect(item_list[0]['item']).to eq user_url(project.owner)
+ expect(item_list[0]['item']).to eq user_url(project.first_owner)
expect(item_list[1]['name']).to eq project.name
expect(item_list[1]['item']).to eq project_url(project)
diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb
index 7ed31a8c549..e03126d344e 100644
--- a/spec/features/clusters/create_agent_spec.rb
+++ b/spec/features/clusters/create_agent_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'Cluster agent registration', :js do
double(agent_name: 'example-agent-1', path: '.gitlab/agents/example-agent-1/config.yaml'),
double(agent_name: 'example-agent-2', path: '.gitlab/agents/example-agent-2/config.yaml')
])
+ allow(client).to receive(:get_connected_agents).and_return([])
end
allow(Devise).to receive(:friendly_token).and_return('example-agent-token')
diff --git a/spec/features/contextual_sidebar_spec.rb b/spec/features/contextual_sidebar_spec.rb
index 29c7e0ddd21..cc4a0471d4e 100644
--- a/spec/features/contextual_sidebar_spec.rb
+++ b/spec/features/contextual_sidebar_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Contextual sidebar', :js do
context 'when context is a project' do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 69361f66a71..03d61020ff0 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Value Stream Analytics', :js do
let_it_be(:stage_table_event_title_selector) { '[data-testid="vsa-stage-event-title"]' }
let_it_be(:stage_table_pagination_selector) { '[data-testid="vsa-stage-pagination"]' }
let_it_be(:stage_table_duration_column_header_selector) { '[data-testid="vsa-stage-header-duration"]' }
- let_it_be(:metrics_selector) { "[data-testid='vsa-time-metrics']" }
+ let_it_be(:metrics_selector) { "[data-testid='vsa-metrics']" }
let_it_be(:metric_value_selector) { "[data-testid='displayValue']" }
let(:stage_table) { find(stage_table_selector) }
@@ -134,7 +134,7 @@ RSpec.describe 'Value Stream Analytics', :js do
end
it 'can filter the metrics by date' do
- expect(metrics_values).to match_array(["21.0", "2.0", "1.0", "0.0"])
+ expect(metrics_values).to match_array(%w[21 2 1 0])
set_daterange(from, to)
diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb
index 8c941b27cd2..3a4296836bd 100644
--- a/spec/features/dashboard/groups_list_spec.rb
+++ b/spec/features/dashboard/groups_list_spec.rb
@@ -15,6 +15,10 @@ RSpec.describe 'Dashboard Groups page', :js do
wait_for_requests
end
+ def click_options_menu(group)
+ page.find("[data-testid='group-#{group.id}-dropdown-button'").click
+ end
+
it 'shows groups user is member of' do
group.add_owner(user)
nested_group.add_owner(user)
@@ -112,6 +116,67 @@ RSpec.describe 'Dashboard Groups page', :js do
end
end
+ context 'group actions dropdown' do
+ let!(:subgroup) { create(:group, :public, parent: group) }
+
+ context 'user with subgroup ownership' do
+ before do
+ subgroup.add_owner(user)
+ sign_in(user)
+
+ visit dashboard_groups_path
+ end
+
+ it 'cannot remove parent group' do
+ expect(page).not_to have_selector("[data-testid='group-#{group.id}-dropdown-button'")
+ end
+ end
+
+ context 'user with parent group ownership' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+
+ visit dashboard_groups_path
+ end
+
+ it 'can remove parent group' do
+ click_options_menu(group)
+
+ expect(page).to have_selector("[data-testid='remove-group-#{group.id}-btn']")
+ end
+
+ it 'can remove subgroups' do
+ click_group_caret(group)
+ click_options_menu(subgroup)
+
+ expect(page).to have_selector("[data-testid='remove-group-#{subgroup.id}-btn']")
+ end
+ end
+
+ context 'user is a maintainer' do
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+
+ visit dashboard_groups_path
+ click_options_menu(group)
+ end
+
+ it 'cannot remove the group' do
+ expect(page).not_to have_selector("[data-testid='remove-group-#{group.id}-btn']")
+ end
+
+ it 'cannot edit the group' do
+ expect(page).not_to have_selector("[data-testid='edit-group-#{group.id}-btn']")
+ end
+
+ it 'can leave the group' do
+ expect(page).to have_selector("[data-testid='leave-group-#{group.id}-btn']")
+ end
+ end
+ end
+
context 'when using pagination' do
let(:group) { create(:group, created_at: 5.days.ago) }
let(:group2) { create(:group, created_at: 2.days.ago) }
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index 8e938fef155..6700ec07765 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
it 'reflects dashboard issues count' do
visit issues_path
- expect_counters('issues', '1')
+ expect_counters('issues', '1', n_("%d assigned issue", "%d assigned issues", 1) % 1)
issue.assignees = []
@@ -26,14 +26,14 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
travel_to(3.minutes.from_now) do
visit issues_path
- expect_counters('issues', '0')
+ expect_counters('issues', '0', n_("%d assigned issue", "%d assigned issues", 0) % 0)
end
end
it 'reflects dashboard merge requests count' do
visit merge_requests_path
- expect_counters('merge_requests', '1')
+ expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
merge_request.update!(assignees: [])
@@ -42,7 +42,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
travel_to(3.minutes.from_now) do
visit merge_requests_path
- expect_counters('merge_requests', '0')
+ expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
end
end
@@ -54,13 +54,14 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
merge_requests_dashboard_path(assignee_username: user.username)
end
- def expect_counters(issuable_type, count)
+ def expect_counters(issuable_type, count, badge_label)
dashboard_count = find('.gl-tabs-nav li a.active')
nav_count = find(".dashboard-shortcuts-#{issuable_type}")
- header_count = find(".header-content .#{issuable_type.tr('_', '-')}-count")
expect(dashboard_count).to have_content(count)
expect(nav_count).to have_content(count)
- expect(header_count).to have_content(count)
+ within("span[aria-label='#{badge_label}']") do
+ expect(page).to have_content(count)
+ end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 6239702edde..7507ef4e453 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -112,7 +112,9 @@ RSpec.describe 'Dashboard Merge Requests' do
end
it 'includes assigned and reviewers in badge' do
- expect(find('.merge-requests-count')).to have_content('3')
+ within("span[aria-label='#{n_("%d merge request", "%d merge requests", 3) % 3}']") do
+ expect(page).to have_content('3')
+ end
expect(find('.js-assigned-mr-count')).to have_content('2')
expect(find('.js-reviewer-mr-count')).to have_content('1')
end
diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb
index 224f2111014..f891950eeb8 100644
--- a/spec/features/dashboard/snippets_spec.rb
+++ b/spec/features/dashboard/snippets_spec.rb
@@ -7,11 +7,11 @@ RSpec.describe 'Dashboard snippets' do
context 'when the project has snippets' do
let(:project) { create(:project, :public, creator: user) }
- let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) }
+ let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.first_owner, project: project) }
before do
allow(Snippet).to receive(:default_per_page).and_return(1)
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit dashboard_snippets_path
end
@@ -27,7 +27,7 @@ RSpec.describe 'Dashboard snippets' do
let(:project) { create(:project, :public, creator: user) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit dashboard_snippets_path
end
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index 6846d8f6ade..d5dbe259159 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
end
it 'displays the results' do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_error_tracking_index_path(project)
page.within(find('.gl-table')) do
results = page.all('.table-row')
diff --git a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
index c16c9d3fb1f..89bf79ebb81 100644
--- a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
+++ b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'When a user searches for Sentry errors', :js, :use_clean_rails_m
end
it 'displays the results' do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_error_tracking_index_path(project)
page.within(find('.gl-table')) do
diff --git a/spec/features/error_tracking/user_sees_error_details_spec.rb b/spec/features/error_tracking/user_sees_error_details_spec.rb
index e4a09d04ca1..ecbb3fe0412 100644
--- a/spec/features/error_tracking/user_sees_error_details_spec.rb
+++ b/spec/features/error_tracking/user_sees_error_details_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'View error details page', :js, :use_clean_rails_memory_store_cac
context 'with current user as project owner' do
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit details_project_error_tracking_index_path(project, issue_id: issue_id)
end
diff --git a/spec/features/error_tracking/user_sees_error_index_spec.rb b/spec/features/error_tracking/user_sees_error_index_spec.rb
index bc6709c659d..21f9e688e3f 100644
--- a/spec/features/error_tracking/user_sees_error_index_spec.rb
+++ b/spec/features/error_tracking/user_sees_error_index_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
context 'with current user as project owner' do
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_error_tracking_index_path(project)
end
@@ -43,7 +43,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
context 'with error tracking settings disabled' do
before do
project_error_tracking_settings.update!(enabled: false)
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_error_tracking_index_path(project)
end
diff --git a/spec/features/file_uploads/attachment_spec.rb b/spec/features/file_uploads/attachment_spec.rb
index 9ad404ce869..41da0e9fbe0 100644
--- a/spec/features/file_uploads/attachment_spec.rb
+++ b/spec/features/file_uploads/attachment_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload an attachment', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:api_path) { "/projects/#{project_id}/uploads" }
diff --git a/spec/features/file_uploads/git_lfs_spec.rb b/spec/features/file_uploads/git_lfs_spec.rb
index 239afb1a1bb..8d15c5c33f7 100644
--- a/spec/features/file_uploads/git_lfs_spec.rb
+++ b/spec/features/file_uploads/git_lfs_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a git lfs object', :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
diff --git a/spec/features/file_uploads/maven_package_spec.rb b/spec/features/file_uploads/maven_package_spec.rb
index ab9f023bd8f..70302142fa2 100644
--- a/spec/features/file_uploads/maven_package_spec.rb
+++ b/spec/features/file_uploads/maven_package_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a maven package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:project_id) { project.id }
diff --git a/spec/features/file_uploads/nuget_package_spec.rb b/spec/features/file_uploads/nuget_package_spec.rb
index 871c0274445..cbffd34d4ab 100644
--- a/spec/features/file_uploads/nuget_package_spec.rb
+++ b/spec/features/file_uploads/nuget_package_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a nuget package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:api_path) { "/projects/#{project.id}/packages/nuget/" }
diff --git a/spec/features/file_uploads/rubygem_package_spec.rb b/spec/features/file_uploads/rubygem_package_spec.rb
index 4a5891fdfed..f91fb407b28 100644
--- a/spec/features/file_uploads/rubygem_package_spec.rb
+++ b/spec/features/file_uploads/rubygem_package_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a RubyGems package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:api_path) { "/projects/#{project_id}/packages/rubygems/api/v1/gems" }
diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb
index ca772680ff6..af14b6e2e95 100644
--- a/spec/features/gitlab_experiments_spec.rb
+++ b/spec/features/gitlab_experiments_spec.rb
@@ -21,8 +21,8 @@ RSpec.describe "Gitlab::Experiment", :js do
allow_next_instance_of(Admin::AbuseReportsController) do |instance|
allow(instance).to receive(:index).and_wrap_original do |original|
instance.experiment(:null_hypothesis, user: instance.current_user) do |e|
- e.use { original.call }
- e.try { original.call }
+ e.control { original.call }
+ e.candidate { original.call }
end
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 161a8a7a203..30a81333547 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -138,6 +138,51 @@ RSpec.describe 'Edit group settings' do
end
end
+ describe 'transfer group', :js do
+ let(:namespace_select) { page.find('[data-testid="transfer-group-namespace-select"]') }
+ let(:confirm_modal) { page.find('[data-testid="confirm-danger-modal"]') }
+
+ shared_examples 'can transfer the group' do
+ before do
+ selected_group.add_owner(user)
+ end
+
+ it 'can successfully transfer the group' do
+ visit edit_group_path(selected_group)
+
+ page.within('.js-group-transfer-form') do
+ namespace_select.find('button').click
+ namespace_select.find('.dropdown-menu p', text: target_group_name, match: :first).click
+
+ click_button "Transfer group"
+ end
+
+ page.within(confirm_modal) do
+ expect(page).to have_text "You are going to transfer #{selected_group.name} to another namespace. Are you ABSOLUTELY sure? "
+
+ fill_in "confirm_name_input", with: selected_group.name
+ click_button "Confirm"
+ end
+
+ expect(page).to have_text "Group '#{selected_group.name}' was successfully transferred."
+ end
+ end
+
+ context 'with a sub group' do
+ let(:selected_group) { create(:group, path: 'foo-subgroup', parent: group) }
+ let(:target_group_name) { "No parent group" }
+
+ it_behaves_like 'can transfer the group'
+ end
+
+ context 'with a root group' do
+ let(:selected_group) { create(:group, path: 'foo-rootgroup') }
+ let(:target_group_name) { group.name }
+
+ it_behaves_like 'can transfer the group'
+ end
+ end
+
context 'disable email notifications' do
it 'is visible' do
visit edit_group_path(group)
diff --git a/spec/features/groups/integrations/group_integrations_spec.rb b/spec/features/groups/integrations/group_integrations_spec.rb
new file mode 100644
index 00000000000..0d65fa5964b
--- /dev/null
+++ b/spec/features/groups/integrations/group_integrations_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Group integrations', :js do
+ include_context 'group integration activation'
+
+ it_behaves_like 'integration settings form' do
+ let(:integrations) { Integration.find_or_initialize_all_non_project_specific(Integration.for_group(group)) }
+
+ def navigate_to_integration(integration)
+ visit_group_integration(integration.title)
+ end
+ end
+end
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index e6bf1ffc2f7..9612c6625f6 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe 'Groups > Members > Leave group' do
visit group_path(group, leave: 1)
- expect(find('.flash-alert')).to have_content 'You do not have permission to leave this group'
+ expect(find('[data-testid="alert-danger"]')).to have_content 'You do not have permission to leave this group'
end
def left_group_message(group)
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index 2beecda23b5..61c6709f9cc 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -156,6 +156,26 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
group_outside_hierarchy.add_owner(user)
end
+ context 'when the invite members group modal is enabled' do
+ it 'does not show self or ancestors', :aggregate_failures do
+ group_sibbling = create(:group, parent: group)
+ group_sibbling.add_owner(user)
+
+ visit group_group_members_path(group_within_hierarchy)
+
+ click_on 'Invite a group'
+ click_on 'Select a group'
+ wait_for_requests
+
+ page.within('[data-testid="group-select-dropdown"]') do
+ expect(page).to have_selector("[entity-id='#{group_outside_hierarchy.id}']")
+ expect(page).to have_selector("[entity-id='#{group_sibbling.id}']")
+ expect(page).not_to have_selector("[entity-id='#{group.id}']")
+ expect(page).not_to have_selector("[entity-id='#{group_within_hierarchy.id}']")
+ end
+ end
+ end
+
context 'when sharing with groups outside the hierarchy is enabled' do
context 'when the invite members group modal is disabled' do
before do
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 19f60ce55d3..925bbc47cf6 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe 'Group' do
click_button 'Create group'
expect(current_path).to eq(new_group_path)
- expect(page).to have_text('Please choose a group URL with no special characters or spaces.')
+ expect(page).to have_text('Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores.')
end
end
@@ -90,7 +90,7 @@ RSpec.describe 'Group' do
fill_in 'group_path', with: user.username
wait_for_requests
- expect(page).to have_content("Group path is already taken. We've suggested one that is available.")
+ expect(page).to have_content("Group path is unavailable. Path has been replaced with a suggested available path.")
end
it 'does not break after an invalid form submit' do
@@ -279,7 +279,7 @@ RSpec.describe 'Group' do
fill_in 'Group URL', with: subgroup.path
wait_for_requests
- expect(page).to have_content("Group path is already taken. We've suggested one that is available.")
+ expect(page).to have_content("Group path is unavailable. Path has been replaced with a suggested available path.")
end
end
end
diff --git a/spec/features/ide/user_commits_changes_spec.rb b/spec/features/ide/user_commits_changes_spec.rb
index 1b1e71e2862..e1e586a4f18 100644
--- a/spec/features/ide/user_commits_changes_spec.rb
+++ b/spec/features/ide/user_commits_changes_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'IDE user commits changes', :js do
include WebIdeSpecHelpers
let(:project) { create(:project, :public, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/ide/user_opens_merge_request_spec.rb b/spec/features/ide/user_opens_merge_request_spec.rb
index 7ae43f35901..72fe6eb6ca8 100644
--- a/spec/features/ide/user_opens_merge_request_spec.rb
+++ b/spec/features/ide/user_opens_merge_request_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'IDE merge request', :js do
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:project) { create(:project, :public, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb
index 2dcabb38b8f..ab7c0ce2891 100644
--- a/spec/features/issuables/markdown_references/internal_references_spec.rb
+++ b/spec/features/issuables/markdown_references/internal_references_spec.rb
@@ -5,11 +5,11 @@ require 'spec_helper'
RSpec.describe "Internal references", :js do
include Spec::Support::Helpers::Features::NotesHelpers
- let(:private_project_user) { private_project.owner }
+ let(:private_project_user) { private_project.first_owner }
let(:private_project) { create(:project, :private, :repository) }
let(:private_project_issue) { create(:issue, project: private_project) }
let(:private_project_merge_request) { create(:merge_request, source_project: private_project) }
- let(:public_project_user) { public_project.owner }
+ let(:public_project_user) { public_project.first_owner }
let(:public_project) { create(:project, :public, :repository) }
let(:public_project_issue) { create(:issue, project: public_project) }
let(:public_project_merge_request) { create(:merge_request, source_project: public_project) }
diff --git a/spec/features/issues/filtered_search/dropdown_base_spec.rb b/spec/features/issues/filtered_search/dropdown_base_spec.rb
index 3a304515cab..b8fb807dd78 100644
--- a/spec/features/issues/filtered_search/dropdown_base_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_base_spec.rb
@@ -24,23 +24,6 @@ RSpec.describe 'Dropdown base', :js do
visit project_issues_path(project)
end
- describe 'behavior' do
- it 'shows loading indicator when opened' do
- slow_requests do
- # We aren't using `input_filtered_search` because we want to see the loading indicator
- filtered_search.set('assignee:=')
-
- expect(page).to have_css("#{js_dropdown_assignee} .filter-dropdown-loading", visible: true)
- end
- end
-
- it 'hides loading indicator when loaded' do
- input_filtered_search('assignee:=', submit: false, extra_space: false)
-
- expect(find(js_dropdown_assignee)).not_to have_css('.filter-dropdown-loading')
- end
- end
-
describe 'caching requests' do
it 'caches requests after the first load' do
input_filtered_search('assignee:=', submit: false, extra_space: false)
diff --git a/spec/features/issues/filtered_search/recent_searches_spec.rb b/spec/features/issues/filtered_search/recent_searches_spec.rb
index 3ddcbf1bd01..3929d3694ff 100644
--- a/spec/features/issues/filtered_search/recent_searches_spec.rb
+++ b/spec/features/issues/filtered_search/recent_searches_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe 'Recent searches', :js do
set_recent_searches(project_1_local_storage_key, 'fail')
visit project_issues_path(project_1)
- expect(find('.flash-alert')).to have_text('An error occurred while parsing recent searches')
+ expect(find('[data-testid="alert-danger"]')).to have_text('An error occurred while parsing recent searches')
end
context 'on tablet/mobile screen' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index b0e4729db8b..b4d1b0aeab9 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -6,10 +6,8 @@ RSpec.describe 'GFM autocomplete', :js do
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:user2) { create(:user, name: 'Marge Simpson', username: 'msimpson') }
- let_it_be(:group) { create(:group, name: 'Ancestor') }
- let_it_be(:child_group) { create(:group, parent: group, name: 'My group') }
- let_it_be(:project) { create(:project, group: child_group) }
-
+ let_it_be(:group) { create(:group, :crm_enabled) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:issue) { create(:issue, project: project, assignees: [user]) }
let_it_be(:label) { create(:label, project: project, title: 'special+') }
let_it_be(:label_scoped) { create(:label, project: project, title: 'scoped::label') }
@@ -22,675 +20,390 @@ RSpec.describe 'GFM autocomplete', :js do
let_it_be(:label_xss) { create(:label, project: project, title: label_xss_title) }
before_all do
- project.add_maintainer(user)
- project.add_maintainer(user_xss)
- project.add_maintainer(user2)
+ group.add_maintainer(user)
+ group.add_maintainer(user_xss)
+ group.add_maintainer(user2)
end
- describe 'when tribute_autocomplete feature flag is off' do
- describe 'new issue page' do
- before do
- stub_feature_flags(tribute_autocomplete: false)
-
- sign_in(user)
- visit new_project_issue_path(project)
+ describe 'new issue page' do
+ before do
+ sign_in(user)
+ visit new_project_issue_path(project)
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'allows quick actions' do
- fill_in 'Description', with: '/'
+ it 'allows quick actions' do
+ fill_in 'Description', with: '/'
- expect(find_autocomplete_menu).to be_visible
- end
+ expect(find_autocomplete_menu).to be_visible
end
+ end
- describe 'issue description' do
- let(:issue_to_edit) { create(:issue, project: project) }
-
- before do
- stub_feature_flags(tribute_autocomplete: false)
+ describe 'issue description' do
+ let(:issue_to_edit) { create(:issue, project: project) }
- sign_in(user)
- visit project_issue_path(project, issue_to_edit)
+ before do
+ sign_in(user)
+ visit project_issue_path(project, issue_to_edit)
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'updates with GFM reference' do
- click_button 'Edit title and description'
+ it 'updates with GFM reference' do
+ click_button 'Edit title and description'
- wait_for_requests
+ wait_for_requests
- fill_in 'Description', with: "@#{user.name[0...3]}"
+ fill_in 'Description', with: "@#{user.name[0...3]}"
- wait_for_requests
+ wait_for_requests
- find_highlighted_autocomplete_item.click
+ find_highlighted_autocomplete_item.click
- click_button 'Save changes'
+ click_button 'Save changes'
- wait_for_requests
+ wait_for_requests
- expect(find('.description')).to have_text(user.to_reference)
- end
+ expect(find('.description')).to have_text(user.to_reference)
+ end
- it 'allows quick actions' do
- click_button 'Edit title and description'
+ it 'allows quick actions' do
+ click_button 'Edit title and description'
- fill_in 'Description', with: '/'
+ fill_in 'Description', with: '/'
- expect(find_autocomplete_menu).to be_visible
- end
+ expect(find_autocomplete_menu).to be_visible
end
+ end
- describe 'issue comment' do
- before do
- stub_feature_flags(tribute_autocomplete: false)
-
- sign_in(user)
- visit project_issue_path(project, issue)
+ describe 'issue comment' do
+ before do
+ sign_in(user)
+ visit project_issue_path(project, issue)
- wait_for_requests
- end
+ wait_for_requests
+ end
- describe 'triggering autocomplete' do
- it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
- fill_in 'Comment', with: 'testing@'
- expect(page).not_to have_css('.atwho-view')
+ describe 'triggering autocomplete' do
+ it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
+ fill_in 'Comment', with: 'testing@'
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: '@@'
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: '@@'
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: "@#{user.username[0..2]}!"
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: "@#{user.username[0..2]}!"
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: '7:'
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: 'w:'
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: 'Ð:'
- expect(page).not_to have_css('.atwho-view')
+ fill_in 'Comment', with: 'Ð:'
+ expect(page).not_to have_css('.atwho-view')
- fill_in 'Comment', with: "test\n\n@"
- expect(find_autocomplete_menu).to be_visible
- end
+ fill_in 'Comment', with: "test\n\n@"
+ expect(find_autocomplete_menu).to be_visible
end
+ end
- context 'xss checks' do
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
-
- fill_in 'Comment', with: '#'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text(issue_xss_title)
- end
-
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
-
- wait_for_requests
-
- expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
- end
-
- it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
- milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:milestone, project: project, title: milestone_xss_title)
-
- fill_in 'Comment', with: '%'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text('alert milestone')
- end
+ context 'xss checks' do
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: issue_xss_title)
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '~'
+ fill_in 'Comment', with: '#'
- wait_for_requests
+ wait_for_requests
- expect(find_autocomplete_menu).to have_text('alert label')
- end
+ expect(find_autocomplete_menu).to have_text(issue_xss_title)
end
- describe 'autocomplete highlighting' do
- it 'auto-selects the first item when there is a query, and only for assignees with no query', :aggregate_failures do
- fill_in 'Comment', with: ':'
- wait_for_requests
- expect(find_autocomplete_menu).not_to have_css('.cur')
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '@ev'
- fill_in 'Comment', with: ':1'
- wait_for_requests
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ wait_for_requests
- fill_in 'Comment', with: '@'
- wait_for_requests
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
end
- describe 'assignees' do
- it 'does not wrap with quotes for assignee values' do
- fill_in 'Comment', with: "@#{user.username}"
-
- find_highlighted_autocomplete_item.click
-
- expect(find_field('Comment').value).to have_text("@#{user.username}")
- end
-
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text(user.name)
- end
-
- it 'searches across full name for assignees' do
- fill_in 'Comment', with: '@speciÄ…lsome'
-
- wait_for_requests
-
- expect(find_highlighted_autocomplete_item).to have_text(user.name)
- end
-
- it 'shows names that start with the query as the top result' do
- fill_in 'Comment', with: '@mar'
-
- wait_for_requests
-
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
-
- it 'shows usernames that start with the query as the top result' do
- fill_in 'Comment', with: '@msi'
-
- wait_for_requests
-
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
-
- # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
- it 'shows username when pasting then pressing Enter' do
- fill_in 'Comment', with: "@#{user.username}\n"
-
- expect(find_field('Comment').value).to have_text "@#{user.username}"
- end
-
- it 'does not show `@undefined` when pressing `@` then Enter' do
- fill_in 'Comment', with: "@\n"
-
- expect(find_field('Comment').value).to have_text '@'
- expect(find_field('Comment').value).not_to have_text '@undefined'
- end
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
+ create(:milestone, project: project, title: milestone_xss_title)
- context 'when /assign quick action is selected' do
- it 'triggers user autocomplete and lists users who are currently not assigned to the issue' do
- fill_in 'Comment', with: '/as'
+ fill_in 'Comment', with: '%'
- find_highlighted_autocomplete_item.click
+ wait_for_requests
- expect(find_autocomplete_menu).not_to have_text(user.username)
- expect(find_autocomplete_menu).to have_text(user2.username)
- end
- end
+ expect(find_autocomplete_menu).to have_text('alert milestone')
end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0..2]}"
-
- find_highlighted_autocomplete_item.click
-
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
- end
-
- it 'doesn\'t wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
-
- find_highlighted_autocomplete_item.click
-
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
- end
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '~'
- context 'quick actions' do
- it 'does not limit quick actions autocomplete list to 5' do
- fill_in 'Comment', with: '/'
+ wait_for_requests
- expect(find_autocomplete_menu).to have_css('li', minimum: 6)
- end
+ expect(find_autocomplete_menu).to have_text('alert label')
end
+ end
- context 'labels' do
- it 'allows colons when autocompleting scoped labels' do
- fill_in 'Comment', with: '~scoped:'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text('scoped::label')
- end
-
- it 'allows spaces when autocompleting multi-word labels' do
- fill_in 'Comment', with: '~Accepting merge'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text('Accepting merge requests')
- end
-
- it 'only autocompletes the last label' do
- fill_in 'Comment', with: '~scoped:: foo bar ~Accepting merge'
+ describe 'autocomplete highlighting' do
+ it 'auto-selects the first item when there is a query, and only for assignees with no query', :aggregate_failures do
+ fill_in 'Comment', with: ':'
+ wait_for_requests
+ expect(find_autocomplete_menu).not_to have_css('.cur')
- wait_for_requests
+ fill_in 'Comment', with: ':1'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- expect(find_autocomplete_menu).to have_text('Accepting merge requests')
- end
+ fill_in 'Comment', with: '@'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ end
+ end
- it 'does not autocomplete labels if no tilde is typed' do
- fill_in 'Comment', with: 'Accepting merge'
+ describe 'assignees' do
+ it 'does not wrap with quotes for assignee values' do
+ fill_in 'Comment', with: "@#{user.username}"
- wait_for_requests
+ find_highlighted_autocomplete_item.click
- expect(page).not_to have_css('.atwho-view')
- end
+ expect(find_field('Comment').value).to have_text("@#{user.username}")
end
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+ it 'includes items for assignee dropdowns with non-ASCII characters in name' do
+ fill_in 'Comment', with: "@#{user.name[0...8]}"
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- note = find_field('Comment')
+ wait_for_requests
- start_comment_with_emoji(note, '.atwho-view li')
+ expect(find_autocomplete_menu).to have_text(user.name)
+ end
- start_and_cancel_discussion
+ it 'searches across full name for assignees' do
+ fill_in 'Comment', with: '@speciÄ…lsome'
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.atwho-view li')
- note.native.send_keys(:enter)
+ wait_for_requests
- expect(note.value).to eql('Hello :100: ')
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user.name)
end
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
+ it 'shows names that start with the query as the top result' do
+ fill_in 'Comment', with: '@mar'
- find_autocomplete_menu.find('li').click
+ wait_for_requests
- expect(find_field('Comment').value).to have_text(expected_body)
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
end
- context 'issues' do
- let(:object) { issue }
- let(:expected_body) { object.to_reference }
+ it 'shows usernames that start with the query as the top result' do
+ fill_in 'Comment', with: '@msi'
- it_behaves_like 'autocomplete suggestions'
- end
-
- context 'merge requests' do
- let(:object) { create(:merge_request, source_project: project) }
- let(:expected_body) { object.to_reference }
+ wait_for_requests
- it_behaves_like 'autocomplete suggestions'
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
end
- context 'project snippets' do
- let!(:object) { snippet }
- let(:expected_body) { object.to_reference }
+ # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
+ it 'shows username when pasting then pressing Enter' do
+ fill_in 'Comment', with: "@#{user.username}\n"
- it_behaves_like 'autocomplete suggestions'
+ expect(find_field('Comment').value).to have_text "@#{user.username}"
end
- context 'milestone' do
- let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
- let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
- let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
- let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
- let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
-
- before do
- fill_in 'Comment', with: '/milestone %'
+ it 'does not show `@undefined` when pressing `@` then Enter' do
+ fill_in 'Comment', with: "@\n"
- wait_for_requests
- end
+ expect(find_field('Comment').value).to have_text '@'
+ expect(find_field('Comment').value).not_to have_text '@undefined'
+ end
- it 'shows milestons list in the autocomplete menu' do
- page.within(find_autocomplete_menu) do
- expect(page).to have_selector('li', count: 5)
- end
- end
+ context 'when /assign quick action is selected' do
+ it 'triggers user autocomplete and lists users who are currently not assigned to the issue' do
+ fill_in 'Comment', with: '/as'
- it 'shows expired milestone at the bottom of the list' do
- page.within(find_autocomplete_menu) do
- expect(page.find('li:last-child')).to have_content milestone_expired.title
- end
- end
+ find_highlighted_autocomplete_item.click
- it 'shows milestone due earliest at the top of the list' do
- page.within(find_autocomplete_menu) do
- aggregate_failures do
- expect(page.all('li')[0]).to have_content milestone3.title
- expect(page.all('li')[1]).to have_content milestone2.title
- expect(page.all('li')[2]).to have_content milestone1.title
- expect(page.all('li')[3]).to have_content milestone_no_duedate.title
- end
- end
+ expect(find_autocomplete_menu).not_to have_text(user.username)
+ expect(find_autocomplete_menu).to have_text(user2.username)
end
end
end
- end
- describe 'when tribute_autocomplete feature flag is on' do
- describe 'issue description' do
- let(:issue_to_edit) { create(:issue, project: project) }
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ fill_in 'Comment', with: "~#{label.title[0..2]}"
- before do
- stub_feature_flags(tribute_autocomplete: true)
-
- sign_in(user)
- visit project_issue_path(project, issue_to_edit)
+ find_highlighted_autocomplete_item.click
- wait_for_requests
+ expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
end
- it 'updates with GFM reference' do
- click_button 'Edit title and description'
-
- wait_for_requests
-
- fill_in 'Description', with: "@#{user.name[0...3]}"
+ it 'doesn\'t wrap for emoji values' do
+ fill_in 'Comment', with: ':cartwheel_'
- wait_for_requests
-
- find_highlighted_tribute_autocomplete_menu.click
-
- click_button 'Save changes'
-
- wait_for_requests
+ find_highlighted_autocomplete_item.click
- expect(find('.description')).to have_text(user.to_reference)
+ expect(find_field('Comment').value).to have_text('cartwheel_tone1')
end
end
- describe 'issue comment' do
- before do
- stub_feature_flags(tribute_autocomplete: true)
-
- sign_in(user)
- visit project_issue_path(project, issue)
+ context 'quick actions' do
+ it 'does not limit quick actions autocomplete list to 5' do
+ fill_in 'Comment', with: '/'
- wait_for_requests
+ expect(find_autocomplete_menu).to have_css('li', minimum: 6)
end
+ end
- describe 'triggering autocomplete' do
- it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
- fill_in 'Comment', with: 'testing@'
- expect(page).not_to have_css('.tribute-container')
-
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
- expect(page).not_to have_css('.tribute-container')
-
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.tribute-container')
-
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.tribute-container')
+ context 'labels' do
+ it 'allows colons when autocompleting scoped labels' do
+ fill_in 'Comment', with: '~scoped:'
- fill_in 'Comment', with: 'Ð:'
- expect(page).not_to have_css('.tribute-container')
+ wait_for_requests
- fill_in 'Comment', with: "test\n\n@"
- expect(find_tribute_autocomplete_menu).to be_visible
- end
+ expect(find_autocomplete_menu).to have_text('scoped::label')
end
- context 'xss checks' do
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
-
- fill_in 'Comment', with: '#'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text(issue_xss_title)
- end
-
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
-
- wait_for_requests
+ it 'allows spaces when autocompleting multi-word labels' do
+ fill_in 'Comment', with: '~Accepting merge'
- expect(find_tribute_autocomplete_menu).to have_text(user_xss.username)
- end
-
- it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
- milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:milestone, project: project, title: milestone_xss_title)
-
- fill_in 'Comment', with: '%'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text('alert milestone')
- end
-
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '~'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text('alert label')
- end
- end
-
- describe 'autocomplete highlighting' do
- it 'auto-selects the first item with query', :aggregate_failures do
- fill_in 'Comment', with: ':1'
- wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
+ wait_for_requests
- fill_in 'Comment', with: '@'
- wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- end
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
end
- describe 'assignees' do
- it 'does not wrap with quotes for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0..2]}"
+ it 'only autocompletes the last label' do
+ fill_in 'Comment', with: '~scoped:: foo bar ~Accepting merge'
- find_highlighted_tribute_autocomplete_menu.click
-
- expect(find_field('Comment').value).to have_text("@#{user.username}")
- end
-
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text(user.name)
- end
-
- context 'when autocompleting for groups' do
- it 'shows the group when searching for the name of the group' do
- fill_in 'Comment', with: '@mygroup'
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text('My group')
- end
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- it 'does not show the group when searching for the name of the parent of the group' do
- fill_in 'Comment', with: '@ancestor'
+ it 'does not autocomplete labels if no tilde is typed' do
+ fill_in 'Comment', with: 'Accepting merge'
- expect(find_tribute_autocomplete_menu).not_to have_text('My group')
- end
- end
-
- context 'when /assign quick action is selected' do
- it 'lists users who are currently not assigned to the issue' do
- note = find_field('Comment')
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(user2.username)
- end
+ wait_for_requests
- it 'lists users who are currently not assigned to the issue when using /assign on the second line' do
- note = find_field('Comment')
- note.native.send_keys('/assign @user2')
- note.native.send_keys(:enter)
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(user2.username)
- end
- end
+ expect(page).not_to have_css('.atwho-view')
end
+ end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0..2]}"
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
- find_highlighted_tribute_autocomplete_menu.click
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ note = find_field('Comment')
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
- end
+ start_comment_with_emoji(note, '.atwho-view li')
- it 'does not wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
+ start_and_cancel_discussion
- find_highlighted_tribute_autocomplete_menu.click
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.atwho-view li')
+ note.native.send_keys(:enter)
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
+ expect(note.value).to eql('Hello :100: ')
end
+ end
- context 'quick actions' do
- it 'autocompletes for quick actions' do
- fill_in 'Comment', with: '/as'
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ fill_in 'Comment', with: object.class.reference_prefix
- find_highlighted_tribute_autocomplete_menu.click
+ find_autocomplete_menu.find('li').click
- expect(find_field('Comment').value).to have_text('/assign')
- end
+ expect(find_field('Comment').value).to have_text(expected_body)
end
+ end
- context 'labels' do
- it 'allows colons when autocompleting scoped labels' do
- fill_in 'Comment', with: '~scoped:'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text('scoped::label')
- end
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
- it 'autocompletes multi-word labels' do
- fill_in 'Comment', with: '~Acceptingmerge'
+ it_behaves_like 'autocomplete suggestions'
+ end
- wait_for_requests
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
- expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- it 'only autocompletes the last label' do
- fill_in 'Comment', with: '~scoped:: foo bar ~Acceptingmerge'
- # Invoke autocompletion
- find_field('Comment').native.send_keys(:right)
+ context 'project snippets' do
+ let!(:object) { snippet }
+ let(:expected_body) { object.to_reference }
- wait_for_requests
+ it_behaves_like 'autocomplete suggestions'
+ end
- expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
- end
+ context 'milestone' do
+ let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
+ let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
+ let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
+ let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
+ let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
- it 'does not autocomplete labels if no tilde is typed' do
- fill_in 'Comment', with: 'Accepting'
+ before do
+ fill_in 'Comment', with: '/milestone %'
- wait_for_requests
+ wait_for_requests
+ end
- expect(page).not_to have_css('.tribute-container')
+ it 'shows milestons list in the autocomplete menu' do
+ page.within(find_autocomplete_menu) do
+ expect(page).to have_selector('li', count: 5)
end
end
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
-
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- note = find_field('Comment')
-
- start_comment_with_emoji(note, '.tribute-container li')
-
- start_and_cancel_discussion
-
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.tribute-container li')
- note.native.send_keys(:enter)
-
- expect(note.value).to eql('Hello :100: ')
+ it 'shows expired milestone at the bottom of the list' do
+ page.within(find_autocomplete_menu) do
+ expect(page.find('li:last-child')).to have_content milestone_expired.title
end
end
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
-
- find_tribute_autocomplete_menu.find('li').click
-
- expect(find_field('Comment').value).to have_text(expected_body)
+ it 'shows milestone due earliest at the top of the list' do
+ page.within(find_autocomplete_menu) do
+ aggregate_failures do
+ expect(page.all('li')[0]).to have_content milestone3.title
+ expect(page.all('li')[1]).to have_content milestone2.title
+ expect(page.all('li')[2]).to have_content milestone1.title
+ expect(page.all('li')[3]).to have_content milestone_no_duedate.title
+ end
end
end
+ end
- context 'issues' do
- let(:object) { issue }
- let(:expected_body) { object.to_reference }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ context 'contact' do
+ let_it_be(:contacts) { create_list(:contact, 2, group: group) }
- context 'merge requests' do
- let(:object) { create(:merge_request, source_project: project) }
- let(:expected_body) { object.to_reference }
+ before do
+ fill_in 'Comment', with: '/add_contacts [contact:'
- it_behaves_like 'autocomplete suggestions'
+ wait_for_requests
end
- context 'project snippets' do
- let!(:object) { snippet }
- let(:expected_body) { object.to_reference }
-
- it_behaves_like 'autocomplete suggestions'
+ it 'shows contacts list in the autocomplete menu' do
+ page.within(find_autocomplete_menu) do
+ expect(page).to have_selector('li', count: 2)
+ end
end
- context 'milestone' do
- let!(:object) { create(:milestone, project: project) }
- let(:expected_body) { object.to_reference }
+ it 'shows all contacts' do
+ page.within(find_autocomplete_menu) do
+ expected_data = contacts.map { |c| "#{c.first_name} #{c.last_name} #{c.email}"}
- it_behaves_like 'autocomplete suggestions'
+ expect(page.all('li').map(&:text)).to match_array(expected_data)
+ end
end
end
end
@@ -707,9 +420,10 @@ RSpec.describe 'GFM autocomplete', :js do
def start_and_cancel_discussion
fill_in('Reply to comment', with: 'Whoops!')
+ click_button('Cancel')
- page.accept_alert 'Are you sure you want to cancel creating this comment?' do
- click_button('Cancel')
+ page.within('.modal') do
+ click_button('OK', match: :first)
end
wait_for_requests
@@ -722,12 +436,4 @@ RSpec.describe 'GFM autocomplete', :js do
def find_highlighted_autocomplete_item
find('.atwho-view li.cur', visible: true)
end
-
- def find_tribute_autocomplete_menu
- find('.tribute-container ul', visible: true)
- end
-
- def find_highlighted_tribute_autocomplete_menu
- find('.tribute-container li.highlight', visible: true)
- end
end
diff --git a/spec/features/issues/keyboard_shortcut_spec.rb b/spec/features/issues/keyboard_shortcut_spec.rb
index 502412bab5d..4dbc5d8e01c 100644
--- a/spec/features/issues/keyboard_shortcut_spec.rb
+++ b/spec/features/issues/keyboard_shortcut_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Issues shortcut', :js do
let(:project) { create(:project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
@@ -23,7 +23,7 @@ RSpec.describe 'Issues shortcut', :js do
let(:project) { create(:project, :issues_disabled) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
diff --git a/spec/features/issues/todo_spec.rb b/spec/features/issues/todo_spec.rb
index 315d1c911a2..d63d21353e5 100644
--- a/spec/features/issues/todo_spec.rb
+++ b/spec/features/issues/todo_spec.rb
@@ -19,13 +19,13 @@ RSpec.describe 'Manually create a todo item from issue', :js do
expect(page).to have_content 'Mark as done'
end
- page.within '.header-content .todos-count' do
+ page.within ".header-content span[aria-label='#{_('Todos count')}']" do
expect(page).to have_content '1'
end
visit project_issue_path(project, issue)
- page.within '.header-content .todos-count' do
+ page.within ".header-content span[aria-label='#{_('Todos count')}']" do
expect(page).to have_content '1'
end
end
@@ -36,10 +36,10 @@ RSpec.describe 'Manually create a todo item from issue', :js do
click_button 'Mark as done'
end
- expect(page).to have_selector('.todos-count', visible: false)
+ expect(page).to have_selector(".header-content span[aria-label='#{_('Todos count')}']", visible: false)
visit project_issue_path(project, issue)
- expect(page).to have_selector('.todos-count', visible: false)
+ expect(page).to have_selector(".header-content span[aria-label='#{_('Todos count')}']", visible: false)
end
end
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 5d03aa1fc2b..a719263f092 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe "User comments on issue", :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(tribute_autocomplete: false)
stub_feature_flags(sandboxed_mermaid: false)
project.add_guest(user)
sign_in(user)
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index 875b0a60634..167521134b1 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -71,16 +71,10 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
perform_enqueued_jobs do
select_dropdown_option('create-mr')
- expect(page).to have_content('Draft: Resolve "Cherry-Coloured Funk"')
- expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
-
- wait_for_requests
+ expect(page).to have_content('New merge request')
+ expect(page).to have_content("From #{issue.to_branch_name} into #{project.default_branch}")
+ expect(page).to have_current_path(project_new_merge_request_path(project, merge_request: { source_branch: issue.to_branch_name, target_branch: project.default_branch }))
end
-
- visit project_issue_path(project, issue)
-
- expect(page).to have_content("created merge request !1 to address this issue")
- expect(page).to have_content('mentioned in merge request !1')
end
it 'creates a branch' do
@@ -100,17 +94,10 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
perform_enqueued_jobs do
select_dropdown_option('create-mr', branch_name)
- expect(page).to have_content('Draft: Resolve "Cherry-Coloured Funk"')
- expect(page).to have_content('Request to merge custom-branch-name into')
- expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
-
- wait_for_requests
+ expect(page).to have_content('New merge request')
+ expect(page).to have_content("From #{branch_name} into #{project.default_branch}")
+ expect(page).to have_current_path(project_new_merge_request_path(project, merge_request: { source_branch: branch_name, target_branch: project.default_branch }))
end
-
- visit project_issue_path(project, issue)
-
- expect(page).to have_content("created merge request !1 to address this issue")
- expect(page).to have_content('mentioned in merge request !1')
end
it 'creates a branch' do
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index a036a9a5bbc..8c906e6a27c 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -145,7 +145,7 @@ RSpec.describe "Issues > User edits issue", :js do
fill_in 'Comment', with: '/label ~syzygy'
click_button 'Comment'
- expect(page).to have_text('added syzygy label just now', wait: 300)
+ expect(page).to have_text('added syzygy label just now')
page.within '.block.labels' do
# Remove `verisimilitude` label
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 2e52a8d862e..892b57bac5c 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -65,9 +65,10 @@ RSpec.describe 'User interacts with awards' do
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 reacted with :8ball:"]')
+ wait_for_requests
+
expect do
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
end
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 48297e9049e..f3eaff379a1 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -119,89 +119,6 @@ RSpec.describe "User sorts issues" do
end
end
- describe 'filtering by due date', :js do
- before do
- issue1.update!(due_date: 1.day.from_now)
- issue2.update!(due_date: 6.days.from_now)
- end
-
- it 'filters by none' do
- visit project_issues_path(project, due_date: Issue::NoDueDate.name)
-
- page.within '.issues-list' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by any' do
- visit project_issues_path(project, due_date: Issue::AnyDueDate.name)
-
- page.within '.issues-list' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by due this week' do
- issue1.update!(due_date: Date.today.beginning_of_week + 2.days)
- issue2.update!(due_date: Date.today.end_of_week)
- issue3.update!(due_date: Date.today - 8.days)
-
- visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
-
- page.within '.issues-list' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
- end
- end
-
- it 'filters by due this month' do
- issue1.update!(due_date: Date.today.beginning_of_month + 2.days)
- issue2.update!(due_date: Date.today.end_of_month)
- issue3.update!(due_date: Date.today - 50.days)
-
- visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
-
- page.within '.issues-list' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
- end
- end
-
- it 'filters by overdue' do
- issue1.update!(due_date: Date.today + 2.days)
- issue2.update!(due_date: Date.today + 20.days)
- issue3.update!(due_date: Date.yesterday)
-
- visit project_issues_path(project, due_date: Issue::Overdue.name)
-
- page.within '.issues-list' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by due next month and previous two weeks' do
- issue1.update!(due_date: Date.today - 4.weeks)
- issue2.update!(due_date: (Date.today + 2.months).beginning_of_month)
- issue3.update!(due_date: Date.yesterday)
-
- visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
-
- page.within '.issues-list' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
- end
-
describe 'sorting by milestone', :js do
before do
issue1.milestone = newer_due_milestone
diff --git a/spec/features/jira_connect/branches_spec.rb b/spec/features/jira_connect/branches_spec.rb
index 6fa600c6906..c334a425849 100644
--- a/spec/features/jira_connect/branches_spec.rb
+++ b/spec/features/jira_connect/branches_spec.rb
@@ -25,8 +25,9 @@ RSpec.describe 'Create GitLab branches from Jira', :js do
it 'select project and branch and submit the form' do
visit new_jira_connect_branch_path(issue_key: 'ACME-123', issue_summary: 'My issue !@#$% title')
- expect(page).to have_field('Branch name', with: 'ACME-123-my-issue-title')
expect(page).to have_button('Create branch', disabled: true)
+ # initially, branch field should be hidden.
+ expect(page).not_to have_field('Branch name')
# Select project1
@@ -44,6 +45,7 @@ RSpec.describe 'Create GitLab branches from Jira', :js do
click_on 'Alice / foo'
end
+ expect(page).to have_field('Branch name', with: 'ACME-123-my-issue-title')
expect(page).to have_button('Create branch', disabled: false)
click_on 'master'
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index 0e5a20fe24a..6951d8298e5 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -663,7 +663,7 @@ RSpec.describe 'Copy as GFM', :js do
let(:project) { create(:project, :repository) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
context 'from a diff' do
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index f695b225915..eb98c7d5061 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
expect(page).to have_selector('[data-testid="review_bar_component"]')
- expect(find('.review-bar-content .btn-confirm')).to have_content('1')
+ expect(find('[data-testid="review_bar_component"] .btn-confirm')).to have_content('1')
end
it 'publishes review' do
@@ -64,7 +64,11 @@ RSpec.describe 'Merge request > Batch comments', :js do
it 'deletes draft note' do
write_diff_comment
- accept_alert { find('.js-note-delete').click }
+ find('.js-note-delete').click
+
+ page.within('.modal') do
+ click_button('Delete Comment', match: :first)
+ end
wait_for_requests
@@ -146,10 +150,6 @@ RSpec.describe 'Merge request > Batch comments', :js do
it 'adds draft comments to both sides' do
write_parallel_comment('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9')
-
- # make sure line 9 is in the view
- execute_script("window.scrollBy(0, -200)")
-
write_parallel_comment('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9', button_text: 'Add to review', text: 'Another wrong line')
expect(find('.new .draft-note-component')).to have_content('Line is wrong')
@@ -251,13 +251,15 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
def write_diff_comment(**params)
- click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']"))
write_comment(**params)
end
def write_parallel_comment(line, **params)
- find("div[id='#{line}']").hover
+ line_element = find_by_scrolling("[id='#{line}']")
+ scroll_to_elements_bottom(line_element)
+ line_element.hover
find(".js-add-diff-note-button").click
write_comment(selector: "form[data-line-code='#{line}']", **params)
diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb
index 240b8f996c8..35eadb34799 100644
--- a/spec/features/merge_request/user_awards_emoji_spec.rb
+++ b/spec/features/merge_request/user_awards_emoji_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe 'Merge request > User awards emoji', :js do
it 'removes award from merge request' do
first('[data-testid="award-button"]').click
+ expect(first('[data-testid="award-button"]')).to have_content '1'
find('[data-testid="award-button"].selected').click
expect(first('[data-testid="award-button"]')).to have_content '0'
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index f9b554c5ed2..c06019f6b77 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -25,14 +25,15 @@ RSpec.describe 'User comments on a diff', :js do
context 'when toggling inline comments' do
context 'in a single file' do
it 'hides a comment' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ line_element = find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']").find(:xpath, "..")
+ click_diff_line(line_element)
page.within('.js-discussion-note-form') do
fill_in('note_note', with: 'Line is wrong')
click_button('Add comment now')
end
- page.within('.diff-files-holder > div:nth-child(6)') do
+ page.within(line_element.ancestor('[data-path]')) do
expect(page).to have_content('Line is wrong')
find('.js-diff-more-actions').click
@@ -45,7 +46,9 @@ RSpec.describe 'User comments on a diff', :js do
context 'in multiple files' do
it 'toggles comments' do
- click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
+ first_line_element = find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']").find(:xpath, "..")
+ first_root_element = first_line_element.ancestor('[data-path]')
+ click_diff_line(first_line_element)
page.within('.js-discussion-note-form') do
fill_in('note_note', with: 'Line is correct')
@@ -54,11 +57,14 @@ RSpec.describe 'User comments on a diff', :js do
wait_for_requests
- page.within('.diff-files-holder > div:nth-child(5) .note-body > .note-text') do
+ page.within(first_root_element) do
expect(page).to have_content('Line is correct')
end
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ second_line_element = find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']")
+ second_root_element = second_line_element.ancestor('[data-path]')
+
+ click_diff_line(second_line_element)
page.within('.js-discussion-note-form') do
fill_in('note_note', with: 'Line is wrong')
@@ -68,7 +74,7 @@ RSpec.describe 'User comments on a diff', :js do
wait_for_requests
# Hide the comment.
- page.within('.diff-files-holder > div:nth-child(6)') do
+ page.within(second_root_element) do
find('.js-diff-more-actions').click
click_button 'Hide comments on this file'
@@ -77,37 +83,36 @@ RSpec.describe 'User comments on a diff', :js do
# At this moment a user should see only one comment.
# The other one should be hidden.
- page.within('.diff-files-holder > div:nth-child(5) .note-body > .note-text') do
+ page.within(first_root_element) do
expect(page).to have_content('Line is correct')
end
# Show the comment.
- page.within('.diff-files-holder > div:nth-child(6)') do
+ page.within(second_root_element) do
find('.js-diff-more-actions').click
click_button 'Show comments on this file'
end
# Now both the comments should be shown.
- page.within('.diff-files-holder > div:nth-child(6) .note-body > .note-text') do
+ page.within(second_root_element) do
expect(page).to have_content('Line is wrong')
end
- page.within('.diff-files-holder > div:nth-child(5) .note-body > .note-text') do
+ page.within(first_root_element) do
expect(page).to have_content('Line is correct')
end
# Check the same comments in the side-by-side view.
- execute_script("window.scrollTo(0,0);")
find('.js-show-diff-settings').click
click_button 'Side-by-side'
wait_for_requests
- page.within('.diff-files-holder > div:nth-child(6) .parallel .note-body > .note-text') do
+ page.within(second_root_element) do
expect(page).to have_content('Line is wrong')
end
- page.within('.diff-files-holder > div:nth-child(5) .parallel .note-body > .note-text') do
+ page.within(first_root_element) do
expect(page).to have_content('Line is correct')
end
end
@@ -121,7 +126,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'when adding multiline comments' do
it 'saves a multiline comment' do
- click_diff_line(find("[id='#{sample_commit.line_code}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_commit.line_code}']").find(:xpath, '..'))
add_comment('-13', '+14')
end
@@ -133,13 +138,13 @@ RSpec.describe 'User comments on a diff', :js do
# In `files/ruby/popen.rb`
it 'allows comments for changes involving both sides' do
# click +15, select -13 add and verify comment
- click_diff_line(find('div[data-path="files/ruby/popen.rb"] .right-side a[data-linenumber="15"]').find(:xpath, '../../..'), 'right')
+ click_diff_line(find_by_scrolling('div[data-path="files/ruby/popen.rb"] .right-side a[data-linenumber="15"]').find(:xpath, '../../..'), 'right')
add_comment('-13', '+15')
end
it 'allows comments on previously hidden lines at the top of a file', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/285294' do
# Click -9, expand up, select 1 add and verify comment
- page.within('[data-path="files/ruby/popen.rb"]') do
+ page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do
all('.js-unfold-all')[0].click
end
click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="9"]').find(:xpath, '../..'), 'left')
@@ -148,7 +153,7 @@ RSpec.describe 'User comments on a diff', :js do
it 'allows comments on previously hidden lines the middle of a file' do
# Click 27, expand up, select 18, add and verify comment
- page.within('[data-path="files/ruby/popen.rb"]') do
+ page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do
all('.js-unfold-all')[1].click
end
click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="21"]').find(:xpath, '../..'), 'left')
@@ -157,8 +162,8 @@ RSpec.describe 'User comments on a diff', :js do
it 'allows comments on previously hidden lines at the bottom of a file' do
# Click +28, expand down, select 37 add and verify comment
- page.within('[data-path="files/ruby/popen.rb"]') do
- all('.js-unfold-down')[1].click
+ page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do
+ all('.js-unfold-down:not([disabled])')[1].click
end
click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="30"]').find(:xpath, '../..'), 'left')
add_comment('+28', '37')
@@ -198,7 +203,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'when editing comments' do
it 'edits a comment' do
- click_diff_line(find("[id='#{sample_commit.line_code}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_commit.line_code}']"))
page.within('.js-discussion-note-form') do
fill_in(:note_note, with: 'Line is wrong')
@@ -224,7 +229,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'when deleting comments' do
it 'deletes a comment' do
- click_diff_line(find("[id='#{sample_commit.line_code}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_commit.line_code}']"))
page.within('.js-discussion-note-form') do
fill_in(:note_note, with: 'Line is wrong')
@@ -238,8 +243,11 @@ RSpec.describe 'User comments on a diff', :js do
page.within('.diff-file:nth-of-type(1) .discussion .note') do
find('.more-actions').click
find('.more-actions .dropdown-menu li', match: :first)
+ find('.js-note-delete').click
+ end
- accept_confirm { find('.js-note-delete').click }
+ page.within('.modal') do
+ click_button('Delete Comment', match: :first)
end
page.within('.merge-request-tabs') do
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index cc0d7a279dd..15f186b649a 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Merge request > User creates image diff notes', :js do
it 'shows indicator and avatar badges, and allows collapsing/expanding the discussion notes' do
indicator = find('.js-image-badge')
- badge = find('.image-diff-avatar-link .badge')
+ badge = find('.image-diff-avatar-link .design-note-pin')
expect(indicator).to have_content('1')
expect(badge).to have_content('1')
@@ -127,7 +127,7 @@ RSpec.describe 'Merge request > User creates image diff notes', :js do
visit diffs_project_merge_request_path(project, merge_request, view: view)
wait_for_requests
- expect(page.all('.diff-file span.label-lfs', visible: :all)).not_to be_empty
+ expect(page.all('[data-testid="label-lfs"]', visible: :all)).not_to be_empty
end
it_behaves_like 'creates image diff note'
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 1087be3d8c6..5894ec923c2 100644
--- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
+++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do
before do
stub_const('Autocomplete::UsersFinder::LIMIT', users_find_limit)
- sign_in(project.owner)
+ sign_in(project.first_owner)
merge_request.assignees << assignee
diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb
index 52554f11d28..25c9584350d 100644
--- a/spec/features/merge_request/user_expands_diff_spec.rb
+++ b/spec/features/merge_request/user_expands_diff_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'User expands diff', :js do
let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) }
before do
- allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
+ allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.bytes)
visit(diffs_project_merge_request_path(project, merge_request))
@@ -15,7 +15,7 @@ RSpec.describe 'User expands diff', :js do
end
it 'allows user to expand diff' do
- page.within find('[id="19763941ab80e8c09871c0a425f0560d9053bcb3"]') do
+ page.within find("[id='4c76a1271e41072d7da9fe40bf0f79f7384d472a']") do
find('[data-testid="expand-button"]').click
wait_for_requests
diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
index 3665ad91dd6..7d67cde4bbb 100644
--- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
+++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
@@ -10,21 +10,19 @@ RSpec.describe 'Batch diffs', :js do
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit diffs_project_merge_request_path(merge_request.project, merge_request)
wait_for_requests
- # Add discussion to first line of first file
- click_diff_line(find('.diff-file.file-holder:first-of-type .line_holder .left-side:first-of-type'))
- page.within('.js-discussion-note-form') do
+ click_diff_line(get_first_diff.find('[data-testid="left-side"]', match: :first))
+ page.within get_first_diff.find('.js-discussion-note-form') do
fill_in('note_note', with: 'First Line Comment')
click_button('Add comment now')
end
- # Add discussion to first line of last file
- click_diff_line(find('.diff-file.file-holder:last-of-type .line_holder .left-side:first-of-type'))
- page.within('.js-discussion-note-form') do
+ click_diff_line(get_second_diff.find('[data-testid="left-side"]', match: :first))
+ page.within get_second_diff.find('.js-discussion-note-form') do
fill_in('note_note', with: 'Last Line Comment')
click_button('Add comment now')
end
@@ -36,17 +34,14 @@ RSpec.describe 'Batch diffs', :js do
# Reload so we know the discussions are persisting across batch loads
visit page.current_url
- # Wait for JS to settle
wait_for_requests
- expect(page).to have_selector('.diff-files-holder .file-holder', count: 39)
-
# Confirm discussions are applied to appropriate files (should be contained in multiple diff pages)
- page.within('.diff-file.file-holder:first-of-type .notes .timeline-entry .note .note-text') do
+ page.within get_first_diff.find('.notes .timeline-entry .note .note-text') do
expect(page).to have_content('First Line Comment')
end
- page.within('.diff-file.file-holder:last-of-type .notes .timeline-entry .note .note-text') do
+ page.within get_second_diff.find('.notes .timeline-entry .note .note-text') do
expect(page).to have_content('Last Line Comment')
end
end
@@ -54,7 +49,7 @@ RSpec.describe 'Batch diffs', :js do
context 'when user visits a URL with a link directly to to a discussion' do
context 'which is in the first batched page of diffs' do
it 'scrolls to the correct discussion' do
- page.within('.diff-file.file-holder:first-of-type') do
+ page.within get_first_diff do
click_link('just now')
end
@@ -63,15 +58,15 @@ RSpec.describe 'Batch diffs', :js do
wait_for_requests
# Confirm scrolled to correct UI element
- expect(page.find('.diff-file.file-holder:first-of-type .discussion-notes .timeline-entry li.note[id]').obscured?).to be_falsey
- expect(page.find('.diff-file.file-holder:last-of-type .discussion-notes .timeline-entry li.note[id]').obscured?).to be_truthy
+ expect(get_first_diff.find('.discussion-notes .timeline-entry li.note[id]').obscured?).to be_falsey
+ expect(get_second_diff.find('.discussion-notes .timeline-entry li.note[id]').obscured?).to be_truthy
end
end
context 'which is in at least page 2 of the batched pages of diffs' do
it 'scrolls to the correct discussion',
quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/293814' } do
- page.within('.diff-file.file-holder:last-of-type') do
+ page.within get_first_diff do
click_link('just now')
end
@@ -80,8 +75,8 @@ RSpec.describe 'Batch diffs', :js do
wait_for_requests
# Confirm scrolled to correct UI element
- expect(page.find('.diff-file.file-holder:first-of-type .discussion-notes .timeline-entry li.note[id]').obscured?).to be_truthy
- expect(page.find('.diff-file.file-holder:last-of-type .discussion-notes .timeline-entry li.note[id]').obscured?).to be_falsey
+ expect(get_first_diff.find('.discussion-notes .timeline-entry li.note[id]').obscured?).to be_truthy
+ expect(get_second_diff.find('.discussion-notes .timeline-entry li.note[id]').obscured?).to be_falsey
end
end
end
@@ -95,15 +90,21 @@ RSpec.describe 'Batch diffs', :js do
end
it 'has the correct discussions applied to files across batched pages' do
- expect(page).to have_selector('.diff-files-holder .file-holder', count: 39)
-
- page.within('.diff-file.file-holder:first-of-type .notes .timeline-entry .note .note-text') do
+ page.within get_first_diff.find('.notes .timeline-entry .note .note-text') do
expect(page).to have_content('First Line Comment')
end
- page.within('.diff-file.file-holder:last-of-type .notes .timeline-entry .note .note-text') do
+ page.within get_second_diff.find('.notes .timeline-entry .note .note-text') do
expect(page).to have_content('Last Line Comment')
end
end
end
+
+ def get_first_diff
+ find('#a9b6f940524f646951cc28d954aa41f814f95d4f')
+ end
+
+ def get_second_diff
+ find('#b285a86891571c7fdbf1f82e840816079de1cc8b')
+ end
end
diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb
index 7758fa8e666..d1be93cae02 100644
--- a/spec/features/merge_request/user_merges_merge_request_spec.rb
+++ b/spec/features/merge_request/user_merges_merge_request_spec.rb
@@ -3,7 +3,7 @@
require "spec_helper"
RSpec.describe "User merges a merge request", :js do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
index 8438c0af553..4d7ee11e366 100644
--- a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe 'Merge request > User merges only if pipeline succeeds', :js do
wait_for_requests
expect(page).to have_css('button[disabled="disabled"]', text: 'Merge')
- expect(page).to have_content('The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the troubleshooting documentation to see other possible actions.')
+ expect(page).to have_content('Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or learn about other solutions.')
end
end
@@ -70,7 +70,7 @@ RSpec.describe 'Merge request > User merges only if pipeline succeeds', :js do
wait_for_requests
expect(page).not_to have_button 'Merge'
- expect(page).to have_content('The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the troubleshooting documentation to see other possible actions.')
+ expect(page).to have_content('Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or learn about other solutions.')
end
end
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index 9e314e18563..d803aec5895 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -29,54 +29,54 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
context 'with an old line on the left and no line on the right' do
it 'allows commenting on the left side' do
- should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_23_22"]'), 'left')
+ should_allow_commenting(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_23_22"]'), 'left')
end
it 'does not allow commenting on the right side' do
- should_not_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_23_22"]').find(:xpath, '..'), 'right')
+ should_not_allow_commenting(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_23_22"]').find(:xpath, '..'), 'right')
end
end
context 'with no line on the left and a new line on the right' do
it 'does not allow commenting on the left side' do
- should_not_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15"]').find(:xpath, '..'), 'left')
+ should_not_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15"]').find(:xpath, '..'), 'left')
end
it 'allows commenting on the right side' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15"]').find(:xpath, '..'), 'right')
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15"]').find(:xpath, '..'), 'right')
end
end
context 'with an old line on the left and a new line on the right' do
it 'allows commenting on the left side', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/199050' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"]').find(:xpath, '..'), 'left')
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"]').find(:xpath, '..'), 'left')
end
it 'allows commenting on the right side' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"]').find(:xpath, '..'), 'right')
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"]').find(:xpath, '..'), 'right')
end
end
context 'with an unchanged line on the left and an unchanged line on the right' do
it 'allows commenting on the left side', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/196826' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]', match: :first).find(:xpath, '..'), 'left')
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]', match: :first).find(:xpath, '..'), 'left')
end
it 'allows commenting on the right side' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]', match: :first).find(:xpath, '..'), 'right')
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]', match: :first).find(:xpath, '..'), 'right')
end
end
context 'with a match line' do
it 'does not allow commenting' do
- line_holder = find('.match', match: :first)
+ line_holder = find_by_scrolling('.match', match: :first)
match_should_not_allow_commenting(line_holder)
end
end
context 'with an unfolded line' do
before do
- page.within('.file-holder[id="a5cc2925ca8258af241be7e5b0381edf30266302"]') do
+ page.within find_by_scrolling('.file-holder[id="a5cc2925ca8258af241be7e5b0381edf30266302"]') do
find('.js-unfold', match: :first).click
end
@@ -84,12 +84,12 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
end
it 'allows commenting on the left side' do
- should_allow_commenting(first('#a5cc2925ca8258af241be7e5b0381edf30266302 .line_holder [data-testid="left-side"]'))
+ should_allow_commenting(find_by_scrolling('#a5cc2925ca8258af241be7e5b0381edf30266302').first('.line_holder [data-testid="left-side"]'))
end
it 'allows commenting on the right side' do
# Automatically shifts comment box to left side.
- should_allow_commenting(first('#a5cc2925ca8258af241be7e5b0381edf30266302 .line_holder [data-testid="right-side"]'))
+ should_allow_commenting(find_by_scrolling('#a5cc2925ca8258af241be7e5b0381edf30266302').first('.line_holder [data-testid="right-side"]'))
end
end
end
@@ -101,44 +101,44 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
context 'after deleteing a note' do
it 'allows commenting' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
- accept_confirm do
+ accept_gl_confirm(button_text: 'Delete Comment') do
first('button.more-actions-toggle').click
first('.js-note-delete').click
end
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
end
end
context 'with a new line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
end
end
context 'with an old line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
+ should_allow_commenting(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
end
end
context 'with an unchanged line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
end
end
context 'with a match line' do
it 'does not allow commenting' do
- match_should_not_allow_commenting(find('.match', match: :first))
+ match_should_not_allow_commenting(find_by_scrolling('.match', match: :first))
end
end
context 'with an unfolded line' do
before do
- page.within('.file-holder[id="a5cc2925ca8258af241be7e5b0381edf30266302"]') do
+ page.within find_by_scrolling('.file-holder[id="a5cc2925ca8258af241be7e5b0381edf30266302"]') do
find('.js-unfold', match: :first).click
end
@@ -147,7 +147,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
# The first `.js-unfold` unfolds upwards, therefore the first
# `.line_holder` will be an unfolded line.
- let(:line_holder) { first('[id="a5cc2925ca8258af241be7e5b0381edf30266302_1_1"]') }
+ let(:line_holder) { find_by_scrolling('[id="a5cc2925ca8258af241be7e5b0381edf30266302_1_1"]') }
it 'allows commenting' do
should_allow_commenting line_holder
@@ -157,7 +157,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
context 'when hovering over a diff discussion' do
before do
visit diffs_project_merge_request_path(project, merge_request, view: 'inline')
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
visit project_merge_request_path(project, merge_request)
end
@@ -174,7 +174,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
context 'with a new line' do
it 'allows dismissing a comment' do
- should_allow_dismissing_a_comment(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ should_allow_dismissing_a_comment(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
end
end
end
@@ -182,13 +182,13 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
describe 'with multiple note forms' do
before do
visit diffs_project_merge_request_path(project, merge_request, view: 'inline')
- click_diff_line(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
- click_diff_line(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
+ click_diff_line(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ click_diff_line(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
end
describe 'posting a note' do
it 'adds as discussion' do
- should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'), asset_form_reset: false)
+ should_allow_commenting(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'), asset_form_reset: false)
expect(page).to have_css('.notes_holder .note.note-discussion', count: 1)
expect(page).to have_field('Reply…')
end
@@ -203,25 +203,25 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
context 'with a new line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
end
end
context 'with an old line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
+ should_allow_commenting(find_by_scrolling('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'))
end
end
context 'with an unchanged line' do
it 'allows commenting' do
- should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
+ should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]'))
end
end
context 'with a match line' do
it 'does not allow commenting' do
- match_should_not_allow_commenting(find('.match', match: :first))
+ match_should_not_allow_commenting(find_by_scrolling('.match', match: :first))
end
end
end
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 0416474218f..1779567624c 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -133,7 +133,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
describe 'when previewing a note' do
it 'shows the toolbar buttons when editing a note' do
page.within('.js-main-target-form') do
- expect(page).to have_css('.md-header-toolbar.active')
+ expect(page).to have_css('.md-header-toolbar')
end
end
@@ -141,7 +141,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
wait_for_requests
find('.js-md-preview-button').click
page.within('.js-main-target-form') do
- expect(page).not_to have_css('.md-header-toolbar.active')
+ expect(page).not_to have_css('.md-header-toolbar')
end
end
end
@@ -165,11 +165,13 @@ RSpec.describe 'Merge request > User posts notes', :js do
it 'resets the edit note form textarea with the original content of the note if cancelled' do
within('.current-note-edit-form') do
fill_in 'note[note]', with: 'Some new content'
+ find('[data-testid="cancel"]').click
+ end
- accept_confirm do
- find('[data-testid="cancel"]').click
- end
+ page.within('.modal') do
+ click_button('OK', match: :first)
end
+
expect(find('.js-note-text').text).to eq ''
end
diff --git a/spec/features/merge_request/user_rebases_merge_request_spec.rb b/spec/features/merge_request/user_rebases_merge_request_spec.rb
index a3f72a6266b..d42864200ec 100644
--- a/spec/features/merge_request/user_rebases_merge_request_spec.rb
+++ b/spec/features/merge_request/user_rebases_merge_request_spec.rb
@@ -4,7 +4,7 @@ require "spec_helper"
RSpec.describe "User rebases a merge request", :js do
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index fd405855cf8..92927b713f1 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
-RSpec.describe 'Merge request > User resolves Work in Progress', :js do
+RSpec.describe 'Merge request > User resolves Draft', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
let(:merge_request) do
create(:merge_request_with_diffs, source_project: project,
author: user,
- title: 'WIP: Bug NS-04',
+ title: 'Draft: Bug NS-04',
merge_params: { force_remove_source_branch: '1' })
end
diff --git a/spec/features/merge_request/user_reviews_image_spec.rb b/spec/features/merge_request/user_reviews_image_spec.rb
index 533f3c9c91a..bd490294829 100644
--- a/spec/features/merge_request/user_reviews_image_spec.rb
+++ b/spec/features/merge_request/user_reviews_image_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Merge request > image review', :js do
include MergeRequestDiffHelpers
include RepoHelpers
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project, author: user) }
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 64cd5aa2bb1..33c5a936b8d 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -1,9 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
+include Spec::Support::Helpers::ModalHelpers # rubocop:disable Style/MixinUsage
RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
include NoteInteractionHelpers
+ include Spec::Support::Helpers::ModalHelpers
+ include MergeRequestDiffHelpers
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
@@ -121,8 +124,8 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
it 'removes avatar when note is deleted' do
open_more_actions_dropdown(note)
- page.within find(".note-row-#{note.id}") do
- accept_confirm { find('.js-note-delete').click }
+ accept_gl_confirm(button_text: 'Delete Comment') do
+ find(".note-row-#{note.id} .js-note-delete").click
end
wait_for_requests
@@ -133,6 +136,7 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
end
it 'adds avatar when commenting' do
+ find_by_scrolling('[data-discussion-id]', match: :first)
find_field('Reply…', match: :first).click
page.within '.js-discussion-note-form' do
@@ -152,6 +156,7 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
it 'adds multiple comments' do
3.times do
+ find_by_scrolling('[data-discussion-id]', match: :first)
find_field('Reply…', match: :first).click
page.within '.js-discussion-note-form' do
@@ -190,7 +195,7 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
end
def find_line(line_code)
- line = find("[id='#{line_code}']")
+ line = find_by_scrolling("[id='#{line_code}']")
line = line.find(:xpath, 'preceding-sibling::*[1][self::td]/preceding-sibling::*[1][self::td]') if line.tag_name == 'td'
line
end
diff --git a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb
index 7c93952ee99..dc50c3bc8db 100644
--- a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb
+++ b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Merge request > User sees deleted target branch', :js do
end
it 'shows a message about missing target branch' do
- expect(page).to have_content('Target branch does not exist')
+ expect(page).to have_content('The target branch feature does not exist')
end
it 'does not show link to target branch' do
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 345404cc28f..01cc58777ba 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Merge request > User sees deployment widget', :js do
+ include Spec::Support::Helpers::ModalHelpers
+
describe 'when merge request has associated environments' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
@@ -118,7 +120,9 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
end
it 'does start build when stop button clicked' do
- accept_confirm { find('.js-stop-env').click }
+ accept_gl_confirm(button_text: 'Stop environment') do
+ find('.js-stop-env').click
+ end
expect(page).to have_content('close_app')
end
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index a7713ed9964..7cd9ef80874 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Merge request > User sees diff', :js do
include ProjectForksHelper
include RepoHelpers
+ include MergeRequestDiffHelpers
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
@@ -58,12 +59,12 @@ RSpec.describe 'Merge request > User sees diff', :js do
let(:changelog_id) { Digest::SHA1.hexdigest("CHANGELOG") }
context 'as author' do
- it 'shows direct edit link', :sidekiq_might_not_need_inline do
+ it 'contains direct edit link', :sidekiq_might_not_need_inline do
sign_in(author_user)
visit diffs_project_merge_request_path(project, merge_request)
# Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax
- expect(page).to have_selector("[id=\"#{changelog_id}\"] .js-edit-blob", visible: false)
+ expect(page).to have_selector(".js-edit-blob", visible: false)
end
end
@@ -72,6 +73,8 @@ RSpec.describe 'Merge request > User sees diff', :js do
sign_in(user)
visit diffs_project_merge_request_path(project, merge_request)
+ find_by_scrolling("[id=\"#{changelog_id}\"]")
+
# Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax
find("[id=\"#{changelog_id}\"] .js-diff-more-actions").click
find("[id=\"#{changelog_id}\"] .js-edit-blob").click
@@ -82,7 +85,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
end
context 'when file contains html' do
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:branch_name) {"test_branch"}
it 'escapes any HTML special characters in the diff chunk header' do
@@ -107,6 +110,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
CONTENT
file_name = 'xss_file.rs'
+ file_hash = Digest::SHA1.hexdigest(file_name)
create_file('master', file_name, file_content)
merge_request = create(:merge_request, source_project: project)
@@ -116,6 +120,8 @@ RSpec.describe 'Merge request > User sees diff', :js do
visit diffs_project_merge_request_path(project, merge_request)
+ find_by_scrolling("[id='#{file_hash}']")
+
expect(page).to have_text("function foo<input> {")
expect(page).to have_css(".line[lang='rust'] .k")
end
@@ -123,7 +129,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
context 'when file is stored in LFS' do
let(:merge_request) { create(:merge_request, source_project: project) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
context 'when LFS is enabled on the project' do
before do
@@ -136,7 +142,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
end
context 'when file is an image', :js do
- let(:file_name) { 'files/lfs/image.png' }
+ let(:file_name) { 'a/image.png' }
it 'shows an error message' do
expect(page).not_to have_content('could not be displayed because it is stored in LFS')
@@ -144,7 +150,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
end
context 'when file is not an image' do
- let(:file_name) { 'files/lfs/ruby.rb' }
+ let(:file_name) { 'a/ruby.rb' }
it 'shows an error message' do
expect(page).to have_content('This source diff could not be displayed because it is stored in LFS')
@@ -153,7 +159,14 @@ RSpec.describe 'Merge request > User sees diff', :js do
end
context 'when LFS is not enabled' do
+ let(:file_name) { 'a/lfs_object.iso' }
+
before do
+ allow(Gitlab.config.lfs).to receive(:disabled).and_return(true)
+ project.update_attribute(:lfs_enabled, false)
+
+ create_file('master', file_name, project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data)
+
visit diffs_project_merge_request_path(project, merge_request)
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 2a49109d360..b77b3d69fc1 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
@@ -64,7 +64,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-created', count: 2)
- expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -101,16 +101,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('[data-testid="pipeline-url-link"]')[0])
+ expect(all('[data-testid="pipeline-identifier"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('[data-testid="pipeline-url-link"]')[1])
+ expect(all('[data-testid="pipeline-identifier"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('[data-testid="pipeline-url-link"]')[2])
+ expect(all('[data-testid="pipeline-identifier"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('[data-testid="pipeline-url-link"]')[3])
+ expect(all('[data-testid="pipeline-identifier"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
@@ -201,7 +201,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees a branch pipeline in pipeline tab' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-created', count: 1)
- expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
+ expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{push_pipeline.id}")
end
end
@@ -252,7 +252,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 2)
- expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -295,16 +295,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('[data-testid="pipeline-url-link"]')[0])
+ expect(all('[data-testid="pipeline-identifier"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('[data-testid="pipeline-url-link"]')[1])
+ expect(all('[data-testid="pipeline-identifier"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('[data-testid="pipeline-url-link"]')[2])
+ expect(all('[data-testid="pipeline-identifier"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('[data-testid="pipeline-url-link"]')[3])
+ expect(all('[data-testid="pipeline-identifier"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
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 8761ee89463..872507c3b7a 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -104,10 +104,11 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
visit project_merge_request_path(project, merge_request)
end
- it 'has danger button while waiting for external CI status' do
+ it 'has merge button with confirm variant while waiting for external CI status' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- expect(page).to have_selector('.accept-merge-request.btn-danger')
+
+ expect(page).to have_selector('.accept-merge-request.btn-confirm')
end
end
@@ -125,10 +126,27 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
visit project_merge_request_path(project, merge_request)
end
- it 'has danger button when not succeeded' do
+ it 'has merge button that shows modal when pipeline does not succeeded' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- expect(page).to have_selector('.accept-merge-request.btn-danger')
+
+ click_button 'Merge...'
+
+ expect(page).to have_selector('[data-testid="merge-failed-pipeline-confirmation-dialog"]', visible: true)
+ end
+
+ it 'allows me to merge with a failed pipeline' do
+ modal_selector = '[data-testid="merge-failed-pipeline-confirmation-dialog"]'
+
+ wait_for_requests
+
+ click_button 'Merge...'
+
+ page.within(modal_selector) do
+ click_button 'Merge unverified changes'
+ end
+
+ expect(find('.media-body h4')).to have_content('Merging!')
end
end
diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
index e997fb3e853..39bba3f2f73 100644
--- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
+++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Merge request > User sees MR with deleted source branch', :js do
end
it 'shows a message about missing source branch' do
- expect(page).to have_content('Source branch does not exist.')
+ expect(page).to have_content('The source branch this-branch-does-not-exist does not exist.')
end
it 'still contains Discussion, Commits and Changes tabs' do
@@ -27,7 +27,7 @@ RSpec.describe 'Merge request > User sees MR with deleted source branch', :js do
expect(page).to have_content('Changes')
end
- expect(page).to have_content('Source branch does not exist.')
+ expect(page).to have_content('The source branch this-branch-does-not-exist does not exist.')
click_on 'Changes'
wait_for_requests
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 4967f58528e..a356dd50898 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -125,6 +125,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
before do
stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
+ stub_feature_flags(rearrange_pipelines_table: false)
end
it 'creates a pipeline in the parent project when user proceeds with the warning' do
@@ -133,7 +134,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
create_merge_request_pipeline
act_on_security_warning(action: 'Run pipeline')
- check_pipeline(expected_project: parent_project)
+ check_pipeline(expected_project: parent_project, link_selector: 'pipeline-url-link')
check_head_pipeline(expected_project: parent_project)
end
@@ -178,13 +179,13 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
click_button('Run pipeline')
end
- def check_pipeline(expected_project:)
+ def check_pipeline(expected_project:, link_selector: 'commit-title')
page.within('.ci-table') do
expect(page).to have_selector('.commit', count: 2)
page.within(first('.commit')) do
page.within('.pipeline-tags') do
- expect(page.find('[data-testid="pipeline-url-link"]')[:href]).to include(expected_project.full_path)
+ expect(page.find("[data-testid=#{link_selector}]")[:href]).to include(expected_project.full_path)
expect(page).to have_content('detached')
end
page.within('.pipeline-triggerer') do
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 5abf4e2f5ad..2b856811e02 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Merge request > User sees versions', :js do
+ include MergeRequestDiffHelpers
+
let(:merge_request) do
create(:merge_request).tap do |mr|
mr.merge_request_diff.destroy!
@@ -27,8 +29,12 @@ RSpec.describe 'Merge request > User sees versions', :js do
diff_file_selector = ".diff-file[id='#{file_id}']"
line_code = "#{file_id}_#{line_code}"
- page.within(diff_file_selector) do
- first("[id='#{line_code}']").hover
+ page.within find_by_scrolling(diff_file_selector) do
+ line_code_element = first("[id='#{line_code}']")
+ # scrolling to element's bottom is required in order for .hover action to work
+ # otherwise, the element could be hidden underneath a sticky header
+ scroll_to_elements_bottom(line_code_element)
+ line_code_element.hover
first("[id='#{line_code}'] [role='button']").click
page.within("form[data-line-code='#{line_code}']") do
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index 690a292937a..beb658bb7a0 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'single suggestion note' do
it 'hides suggestion popover' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
expect(page).to have_selector('.diff-suggest-popover')
@@ -46,7 +46,7 @@ RSpec.describe 'User comments on a diff', :js do
end
it 'suggestion is presented' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
fill_in('note_note', with: "```suggestion\n# change to a comment\n```")
@@ -74,7 +74,7 @@ RSpec.describe 'User comments on a diff', :js do
end
it 'allows suggestions in replies' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
fill_in('note_note', with: "```suggestion\n# change to a comment\n```")
@@ -91,7 +91,7 @@ RSpec.describe 'User comments on a diff', :js do
end
it 'suggestion is appliable' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
fill_in('note_note', with: "```suggestion\n# change to a comment\n```")
@@ -273,7 +273,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'multiple suggestions in a single note' do
it 'suggestions are presented', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/258989' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
fill_in('note_note', with: "```suggestion\n# change to a comment\n```\n```suggestion:-2\n# or that\n# heh\n```")
@@ -316,7 +316,7 @@ RSpec.describe 'User comments on a diff', :js do
context 'multi-line suggestions' do
before do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
fill_in('note_note', with: "```suggestion:-3+5\n# change to a\n# comment\n# with\n# broken\n# lines\n```")
diff --git a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
index 370341a43f9..e3272a6e280 100644
--- a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
+++ b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'User views merged merge request from deleted fork' do
let(:project) { create(:project, :repository) }
let(:source_project) { fork_project(project, nil, repository: true) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let!(:merge_request) { create(:merge_request, :merged, source_project: source_project, target_project: project) }
before do
diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb
index b5a973a53c0..a145bcb976b 100644
--- a/spec/features/merge_request/user_views_open_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb
@@ -128,4 +128,30 @@ RSpec.describe 'User views an open merge request' do
expect(find("[data-testid='ref-name']")[:title]).to eq(source_branch)
end
end
+
+ context 'when user preferred language has changed', :use_clean_rails_memory_store_fragment_caching do
+ let(:project) { create(:project, :public, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'renders edit button in preferred language' do
+ visit(merge_request_path(merge_request))
+
+ page.within('.detail-page-header-actions') do
+ expect(page).to have_link('Edit')
+ end
+
+ user.update!(preferred_language: 'de')
+
+ visit(merge_request_path(merge_request))
+
+ page.within('.detail-page-header-actions') do
+ expect(page).to have_link('Bearbeiten')
+ end
+ end
+ end
end
diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb
index 46c12784ea8..f781ba0827c 100644
--- a/spec/features/merge_requests/user_mass_updates_spec.rb
+++ b/spec/features/merge_requests/user_mass_updates_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Merge requests > User mass updates', :js do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
before do
+ stub_feature_flags(mr_attention_requests: false)
+
project.add_maintainer(user)
sign_in(user)
end
@@ -59,6 +61,18 @@ RSpec.describe 'Merge requests > User mass updates', :js do
expect(find('.merge-request')).to have_link "Assigned to #{user.name}"
end
+
+ describe 'with attention requests feature flag on' do
+ before do
+ stub_feature_flags(mr_attention_requests: true)
+ end
+
+ it 'updates merge request with assignee' do
+ change_assignee(user.name)
+
+ expect(find('.issuable-meta a.author-link')[:title]).to eq "Attention requested from assignee #{user.name}, go to their profile."
+ end
+ end
end
describe 'remove assignee' do
diff --git a/spec/features/monitor_sidebar_link_spec.rb b/spec/features/monitor_sidebar_link_spec.rb
index bb5e581a034..fcef0fa0eff 100644
--- a/spec/features/monitor_sidebar_link_spec.rb
+++ b/spec/features/monitor_sidebar_link_spec.rb
@@ -117,9 +117,8 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project))
expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project))
expect(page).to have_link('Logs', href: project_logs_path(project))
-
- expect(page).not_to have_link('Serverless', href: project_serverless_functions_path(project))
- expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project))
+ expect(page).to have_link('Serverless', href: project_serverless_functions_path(project))
+ expect(page).to have_link('Kubernetes', href: project_clusters_path(project))
end
it_behaves_like 'shows Monitor menu based on the access level'
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index cc805e7d369..b2739454b52 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -33,31 +33,12 @@ RSpec.describe 'Member autocomplete', :js do
let(:noteable) { create(:issue, author: author, project: project) }
before do
- stub_feature_flags(tribute_autocomplete: false)
visit project_issue_path(project, noteable)
end
include_examples "open suggestions when typing @", 'issue'
end
- describe 'when tribute_autocomplete feature flag is on' do
- context 'adding a new note on a Issue' do
- let(:noteable) { create(:issue, author: author, project: project) }
-
- before do
- stub_feature_flags(tribute_autocomplete: true)
- visit project_issue_path(project, noteable)
-
- fill_in 'Comment', with: '@'
- end
-
- it 'suggests noteable author and note author' do
- expect(find_tribute_autocomplete_menu).to have_content(author.username)
- expect(find_tribute_autocomplete_menu).to have_content(note.author.username)
- end
- end
- end
-
context 'adding a new note on a Merge Request' do
let(:noteable) do
create(:merge_request, source_project: project,
@@ -91,8 +72,4 @@ RSpec.describe 'Member autocomplete', :js do
def find_autocomplete_menu
find('.atwho-view ul', visible: true)
end
-
- def find_tribute_autocomplete_menu
- find('.tribute-container ul', visible: true)
- end
end
diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb
index b9e59a0239b..fde85a731a1 100644
--- a/spec/features/profiles/keys_spec.rb
+++ b/spec/features/profiles/keys_spec.rb
@@ -49,7 +49,12 @@ RSpec.describe 'Profile > SSH Keys' do
context 'when only DSA and ECDSA keys are allowed' do
before do
forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE
- stub_application_setting(rsa_key_restriction: forbidden, ed25519_key_restriction: forbidden)
+ stub_application_setting(
+ rsa_key_restriction: forbidden,
+ ed25519_key_restriction: forbidden,
+ ecdsa_sk_key_restriction: forbidden,
+ ed25519_sk_key_restriction: forbidden
+ )
end
it 'shows a validation error' do
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 25fe43617fd..898e2c2aa59 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'Profile > Password' do
it 'shows a success message' do
fill_passwords(Gitlab::Password.test_default, Gitlab::Password.test_default)
- page.within('.flash-notice') do
+ page.within('[data-testid="alert-info"]') do
expect(page).to have_content('Password was successfully updated. Please sign in again.')
end
end
diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb
index b8c928004ed..2601dcf55c9 100644
--- a/spec/features/projects/active_tabs_spec.rb
+++ b/spec/features/projects/active_tabs_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Project active tab' do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb
index 9012b335bf4..a3e511b5c22 100644
--- a/spec/features/projects/activity/rss_spec.rb
+++ b/spec/features/projects/activity/rss_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Project Activity RSS' do
let(:project) { create(:project, :public) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:path) { activity_project_path(project) }
before do
@@ -13,7 +13,7 @@ RSpec.describe 'Project Activity RSS' do
context 'when signed in' do
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit path
end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 62994d19fc0..77194fd6ca1 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -29,443 +29,421 @@ RSpec.describe 'File blob', :js do
).execute
end
- before do
- stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350455
- end
-
- context 'Ruby file' do
- before do
- visit_blob('files/ruby/popen.rb')
-
- wait_for_requests
- end
-
- it 'displays the blob' do
- aggregate_failures do
- # shows highlighted Ruby code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("require 'fileutils'")
-
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
-
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
-
- # shows a raw button
- expect(page).to have_link('Open raw')
- end
- end
-
- it 'displays file actions on all screen sizes' do
- file_actions_selector = '.file-actions'
-
- resize_screen_sm
- expect(page).to have_selector(file_actions_selector, visible: true)
-
- resize_screen_xs
- expect(page).to have_selector(file_actions_selector, visible: true)
- end
- end
-
- context 'Markdown file' do
- context 'visiting directly' do
+ context 'with refactor_blob_viewer feature flag enabled' do
+ context 'Ruby file' do
before do
- visit_blob('files/markdown/ruby-style-guide.md')
+ visit_blob('files/ruby/popen.rb')
wait_for_requests
end
- it 'displays the blob using the rich viewer' do
+ it 'displays the blob' do
aggregate_failures do
- # hides the simple viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
- expect(page).to have_selector('.blob-viewer[data-type="rich"]')
-
- # shows rendered Markdown
- expect(page).to have_link("PEP-8")
+ # shows highlighted Ruby code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("require 'fileutils'")
- # shows a viewer switcher
- expect(page).to have_selector('.js-blob-viewer-switcher')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # shows a disabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
end
end
- context 'switching to the simple viewer' do
+ it 'displays file actions on all screen sizes' do
+ file_actions_selector = '.file-actions'
+
+ resize_screen_sm
+ expect(page).to have_selector(file_actions_selector, visible: true)
+
+ resize_screen_xs
+ expect(page).to have_selector(file_actions_selector, visible: true)
+ end
+ end
+
+ context 'Markdown file' do
+ context 'visiting directly' do
before do
- find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+ visit_blob('files/markdown/ruby-style-guide.md')
wait_for_requests
end
- it 'displays the blob using the simple viewer' do
+ it 'displays the blob using the rich viewer' do
aggregate_failures do
- # hides the rich viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
- # shows highlighted Markdown code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
- context 'switching to the rich viewer again' do
+ context 'switching to the simple viewer' do
before do
- find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
wait_for_requests
end
- it 'displays the blob using the rich viewer' do
+ it 'displays the blob using the simple viewer' do
aggregate_failures do
- # hides the simple viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
- expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows highlighted Markdown code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
- end
- end
- end
- context 'when ref switch' do
- def switch_ref_to(ref_name)
- first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
-
- page.within '.project-refs-form' do
- click_link ref_name
- wait_for_requests
- end
- end
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
- it 'displays single highlighted line number of different ref' do
- visit_blob('files/js/application.js', anchor: 'L1')
+ wait_for_requests
+ end
- switch_ref_to('feature')
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
- page.within '.blob-content' do
- expect(find_by_id('LC1')[:class]).to include("hll")
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ end
+ end
+ end
end
end
- it 'displays multiple highlighted line numbers of different ref' do
- visit_blob('files/js/application.js', anchor: 'L1-3')
+ context 'when ref switch' do
+ def switch_ref_to(ref_name)
+ first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
- switch_ref_to('feature')
-
- page.within '.blob-content' do
- expect(find_by_id('LC1')[:class]).to include("hll")
- expect(find_by_id('LC2')[:class]).to include("hll")
- expect(find_by_id('LC3')[:class]).to include("hll")
+ page.within '.project-refs-form' do
+ click_link ref_name
+ wait_for_requests
+ end
end
- end
- it 'displays no highlighted number of different ref' do
- Files::UpdateService.new(
- project,
- project.owner,
- commit_message: 'Update',
- start_branch: 'feature',
- branch_name: 'feature',
- file_path: 'files/js/application.js',
- file_content: 'new content'
- ).execute
+ it 'displays no highlighted number of different ref' do
+ Files::UpdateService.new(
+ project,
+ project.first_owner,
+ commit_message: 'Update',
+ start_branch: 'feature',
+ branch_name: 'feature',
+ file_path: 'files/js/application.js',
+ file_content: 'new content'
+ ).execute
- project.commit('feature').diffs.diff_files.first
+ project.commit('feature').diffs.diff_files.first
- visit_blob('files/js/application.js', anchor: 'L3')
- switch_ref_to('feature')
+ visit_blob('files/js/application.js', anchor: 'L3')
+ switch_ref_to('feature')
- page.within '.blob-content' do
- expect(page).not_to have_css('.hll')
+ page.within '.blob-content' do
+ expect(page).not_to have_css('.hll')
+ end
end
- end
- context 'successfully change ref of similar name' do
- before do
- project.repository.create_branch('dev')
- project.repository.create_branch('development')
- end
+ context 'successfully change ref of similar name' do
+ before do
+ project.repository.create_branch('dev')
+ project.repository.create_branch('development')
+ end
- it 'switch ref from longer to shorter ref name' do
- visit_blob('files/js/application.js', ref: 'development')
- switch_ref_to('dev')
+ it 'switch ref from longer to shorter ref name' do
+ visit_blob('files/js/application.js', ref: 'development')
+ switch_ref_to('dev')
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
+ 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 'switch ref from shorter to longer ref name' do
- visit_blob('files/js/application.js', ref: 'dev')
- switch_ref_to('development')
+ 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')
+ 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
- end
- it 'successfully changes ref when the ref name matches the project name' do
- project.repository.create_branch(project.name)
+ 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')
+ 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')
+ 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
end
- context 'visiting with a line number anchor' do
+ context 'Markdown rendering' do
before do
- visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
- end
+ project.add_maintainer(project.creator)
- it 'displays the blob using the simple viewer' do
- aggregate_failures do
- # hides the rich viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add RedCarpet and CommonMark Markdown ",
+ file_path: 'files/commonmark/file.md',
+ file_content: "1. one\n - sublist\n"
+ ).execute
+ end
- # highlights the line in question
- expect(page).to have_selector('#LC1.hll')
+ context 'when rendering default markdown' do
+ before do
+ visit_blob('files/commonmark/file.md')
- # shows highlighted Markdown code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+ wait_for_requests
+ end
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ it 'renders using CommonMark' do
+ aggregate_failures do
+ expect(page).to have_content("sublist")
+ expect(page).not_to have_xpath("//ol//li//ul")
+ end
end
end
end
- end
-
- context 'Markdown rendering' do
- before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add RedCarpet and CommonMark Markdown ",
- file_path: 'files/commonmark/file.md',
- file_content: "1. one\n - sublist\n"
- ).execute
- end
- context 'when rendering default markdown' do
+ context 'Markdown file (stored in LFS)' do
before do
- visit_blob('files/commonmark/file.md')
-
- wait_for_requests
- end
+ project.add_maintainer(project.creator)
- it 'renders using CommonMark' do
- aggregate_failures do
- expect(page).to have_content("sublist")
- expect(page).not_to have_xpath("//ol//li//ul")
- end
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add Markdown in LFS",
+ file_path: 'files/lfs/file.md',
+ file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data
+ ).execute
end
- end
- end
- context 'Markdown file (stored in LFS)' do
- before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add Markdown in LFS",
- file_path: 'files/lfs/file.md',
- file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data
- ).execute
- end
-
- context 'when LFS is enabled on the project' do
- before do
- allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
- project.update_attribute(:lfs_enabled, true)
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
- visit_blob('files/lfs/file.md')
+ visit_blob('files/lfs/file.md')
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'displays an error' do
- aggregate_failures do
- # hides the simple viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
- expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+ it 'displays an error' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
- # shows an error message
- expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS. You can download it instead.')
+ # shows an error message
+ expect(page).to have_content('This content could not be displayed because it is stored in LFS. You can download it instead.')
- # shows a viewer switcher
- expect(page).to have_selector('.js-blob-viewer-switcher')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
- # shows a download button
- expect(page).to have_link('Download')
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
end
end
- context 'switching to the simple viewer' do
+ context 'when LFS is disabled on the project' do
before do
- find('.js-blob-viewer-switcher .js-blob-viewer-switch-btn[data-viewer=simple]').click
+ visit_blob('files/lfs/file.md')
wait_for_requests
end
- it 'displays an error' do
+ it 'displays the blob' do
aggregate_failures do
- # hides the rich viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+ # shows text
+ expect(page).to have_content('size 1575078')
- # shows an error message
- expect(page).to have_content('The source could not be displayed because it is stored in LFS. You can download it instead.')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
end
end
- context 'when LFS is disabled on the project' do
+ context 'PDF file' do
before do
- visit_blob('files/lfs/file.md')
+ project.add_maintainer(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add PDF",
+ file_path: 'files/test.pdf',
+ file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data
+ ).execute
+
+ visit_blob('files/test.pdf')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
- # shows text
- expect(page).to have_content('size 1575078')
+ # shows rendered PDF
+ expect(page).to have_selector('.js-pdf-viewer')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
- # shows a raw button
- expect(page).to have_link('Open raw')
+ # shows a download button
+ expect(page).to have_link('Download')
end
end
end
- end
- context 'PDF file' do
- before do
- project.add_maintainer(project.creator)
+ context 'Jupiter Notebook file' do
+ before do
+ project.add_maintainer(project.creator)
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add PDF",
- file_path: 'files/test.pdf',
- file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data
- ).execute
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add Jupiter Notebook",
+ file_path: 'files/basic.ipynb',
+ file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
+ ).execute
- visit_blob('files/test.pdf')
+ visit_blob('files/basic.ipynb')
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'displays the blob' do
- aggregate_failures do
- # shows rendered PDF
- expect(page).to have_selector('.js-pdf-viewer')
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows rendered notebook
+ expect(page).to have_selector('.js-notebook-viewer-mounted')
+
+ # does show a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # show a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ # shows a raw button
+ expect(page).to have_link('Open raw')
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ # shows a download button
+ expect(page).to have_link('Download')
- # shows a download button
- expect(page).to have_link('Download')
+ # shows the rendered notebook
+ expect(page).to have_content('test')
+ end
end
end
- end
- context 'Jupiter Notebook file' do
- before do
- project.add_maintainer(project.creator)
+ context 'ISO file (stored in LFS)' do
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add Jupiter Notebook",
- file_path: 'files/basic.ipynb',
- file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
- ).execute
+ visit_blob('files/lfs/lfs_object.iso')
- visit_blob('files/basic.ipynb')
+ wait_for_requests
+ end
- wait_for_requests
- end
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (1.50 MiB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
- it 'displays the blob' do
- aggregate_failures do
- # shows rendered notebook
- expect(page).to have_selector('.js-notebook-viewer-mounted')
+ context 'when LFS is disabled on the project' do
+ before do
+ visit_blob('files/lfs/lfs_object.iso')
- # does show a viewer switcher
- expect(page).to have_selector('.js-blob-viewer-switcher')
+ wait_for_requests
+ end
- # show a disabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows text
+ expect(page).to have_content('size 1575078')
- # shows a raw button
- expect(page).to have_link('Open raw')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # shows a download button
- expect(page).to have_link('Download')
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
- # shows the rendered notebook
- expect(page).to have_content('test')
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+ end
+ end
end
end
- end
- context 'ISO file (stored in LFS)' do
- context 'when LFS is enabled on the project' do
+ context 'ZIP file' do
before do
- allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
- project.update_attribute(:lfs_enabled, true)
-
- visit_blob('files/lfs/lfs_object.iso')
+ visit_blob('Gemfile.zip')
wait_for_requests
end
@@ -473,7 +451,7 @@ RSpec.describe 'File blob', :js do
it 'displays the blob' do
aggregate_failures do
# shows a download link
- expect(page).to have_link('Download (1.5 MB)')
+ expect(page).to have_link('Download (2.11 KiB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
@@ -487,578 +465,703 @@ RSpec.describe 'File blob', :js do
end
end
- context 'when LFS is disabled on the project' do
+ context 'empty file' do
before do
- visit_blob('files/lfs/lfs_object.iso')
+ project.add_maintainer(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add empty file",
+ file_path: 'files/empty.md',
+ file_content: ''
+ ).execute
+
+ visit_blob('files/empty.md')
wait_for_requests
end
- it 'displays the blob' do
+ it 'displays an error' do
aggregate_failures do
- # shows text
- expect(page).to have_content('size 1575078')
+ # shows an error message
+ expect(page).to have_content('Empty file')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
- # shows a raw button
- expect(page).to have_link('Open raw')
+ # does not show a download or raw button
+ expect(page).not_to have_link('Download')
+ expect(page).not_to have_link('Open raw')
end
end
end
- end
-
- context 'ZIP file' do
- before do
- visit_blob('Gemfile.zip')
- wait_for_requests
- end
+ context 'files with auxiliary viewers' do
+ describe '.gitlab-ci.yml' do
+ before do
+ project.add_maintainer(project.creator)
- it 'displays the blob' do
- aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (2.11 KB)')
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab-ci.yml",
+ file_path: '.gitlab-ci.yml',
+ file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ ).execute
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ visit_blob('.gitlab-ci.yml')
+ end
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that configuration is valid
+ expect(page).to have_content('This GitLab CI configuration is valid.')
- # shows a download button
- expect(page).to have_link('Download')
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
end
- end
- end
- context 'empty file' do
- before do
- project.add_maintainer(project.creator)
+ describe '.gitlab/route-map.yml' do
+ before do
+ project.add_maintainer(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab/route-map.yml",
+ file_path: '.gitlab/route-map.yml',
+ file_content: <<-MAP.strip_heredoc
+ # Team data
+ - source: 'data/team.yml'
+ public: 'team/'
+ MAP
+ ).execute
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add empty file",
- file_path: 'files/empty.md',
- file_content: ''
- ).execute
+ visit_blob('.gitlab/route-map.yml')
+ end
- visit_blob('files/empty.md')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that map is valid
+ expect(page).to have_content('This Route Map is valid.')
- wait_for_requests
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
- it 'displays an error' do
- aggregate_failures do
- # shows an error message
- expect(page).to have_content('Empty file')
+ describe '.gitlab/dashboards/custom-dashboard.yml' do
+ before do
+ project.add_maintainer(project.creator)
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
+ file_path: '.gitlab/dashboards/custom-dashboard.yml',
+ file_content: file_content
+ ).execute
+ end
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ context 'with metrics_dashboard_exhaustive_validations feature flag off' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ end
- # does not show a download or raw button
- expect(page).not_to have_link('Download')
- expect(page).not_to have_link('Open raw')
- end
- end
- end
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
- context 'binary file that appears to be text in the first 1024 bytes' do
- before do
- visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
- it 'displays the blob' do
- aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (23.8 KB)')
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
- # The specs below verify an arguably incorrect result, but since we only
- # learn that the file is not actually text once the text viewer content
- # is loaded asynchronously, there is no straightforward way to get these
- # synchronously loaded elements to display correctly.
- #
- # Clicking the copy button will result in nothing being copied.
- # Clicking the raw button will result in the binary file being downloaded,
- # as expected.
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
- # shows an enabled copy button, incorrectly
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
+ end
- # shows a raw button, incorrectly
- expect(page).to have_link('Open raw')
- end
- end
- end
+ context 'with metrics_dashboard_exhaustive_validations feature flag on' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ end
- context 'files with auxiliary viewers' do
- before do
- stub_feature_flags(refactor_blob_viewer: true)
- end
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
- describe '.gitlab-ci.yml' do
- before do
- project.add_maintainer(project.creator)
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab-ci.yml",
- file_path: '.gitlab-ci.yml',
- file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
- ).execute
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
- visit_blob('.gitlab-ci.yml')
- end
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that configuration is valid
- expect(page).to have_content('This GitLab CI configuration is valid.')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("root is missing required keys: panel_groups")
- # shows a learn more link
- expect(page).to have_link('Learn more')
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
end
end
- end
- describe '.gitlab/route-map.yml' do
- before do
- project.add_maintainer(project.creator)
+ context 'LICENSE' do
+ before do
+ visit_blob('LICENSE')
+ end
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab/route-map.yml",
- file_path: '.gitlab/route-map.yml',
- file_content: <<-MAP.strip_heredoc
- # Team data
- - source: 'data/team.yml'
- public: 'team/'
- MAP
- ).execute
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows license
+ expect(page).to have_content('This project is licensed under the MIT License.')
- visit_blob('.gitlab/route-map.yml')
+ # shows a learn more link
+ expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
+ end
+ end
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that map is valid
- expect(page).to have_content('This Route Map is valid.')
+ context '*.gemspec' do
+ before do
+ project.add_maintainer(project.creator)
- # shows a learn more link
- expect(page).to have_link('Learn more')
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add activerecord.gemspec",
+ file_path: 'activerecord.gemspec',
+ file_content: <<-SPEC.strip_heredoc
+ Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "activerecord"
+ end
+ SPEC
+ ).execute
+
+ visit_blob('activerecord.gemspec')
end
- end
- end
- describe '.gitlab/dashboards/custom-dashboard.yml' do
- before do
- project.add_maintainer(project.creator)
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows names of dependency manager and package
+ expect(page).to have_content('This project manages its dependencies using RubyGems.')
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
- file_path: '.gitlab/dashboards/custom-dashboard.yml',
- file_content: file_content
- ).execute
+ # shows a learn more link
+ expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
+ end
+ end
end
- context 'with metrics_dashboard_exhaustive_validations feature flag off' do
+ context 'CONTRIBUTING.md' do
before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ file_name = 'CONTRIBUTING.md'
+
+ create_file(file_name, '## Contribution guidelines')
+ visit_blob(file_name)
end
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
+ end
+ end
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+ context 'CHANGELOG.md' do
+ before do
+ file_name = 'CHANGELOG.md'
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ create_file(file_name, '## Changelog for v1.0.0')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
end
end
+ end
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
+ context 'Cargo.toml' do
+ before do
+ file_name = 'Cargo.toml'
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
+ create_file(file_name, '
+ [package]
+ name = "hello_world" # the name of the package
+ version = "0.1.0" # the current version, obeying semver
+ authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
+ ')
+ visit_blob(file_name)
+ end
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Cargo.")
end
end
end
- context 'with metrics_dashboard_exhaustive_validations feature flag on' do
+ context 'Cartfile' do
before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ file_name = 'Cartfile'
+
+ create_file(file_name, '
+ gitlab "Alamofire/Alamofire" == 4.9.0
+ gitlab "Alamofire/AlamofireImage" ~> 3.4
+ ')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Carthage.")
+ end
end
+ end
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+ context 'composer.json' do
+ before do
+ file_name = 'composer.json'
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+ create_file(file_name, '
+ {
+ "license": "MIT"
+ }
+ ')
+ visit_blob(file_name)
+ end
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Composer.")
end
end
+ end
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
+ context 'Gemfile' do
+ before do
+ file_name = 'Gemfile'
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("root is missing required keys: panel_groups")
+ create_file(file_name, '
+ source "https://rubygems.org"
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ # Gems here
+ ')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Bundler.")
end
end
end
- end
- context 'LICENSE' do
- before do
- visit_blob('LICENSE')
- end
+ context 'Godeps.json' do
+ before do
+ file_name = 'Godeps.json'
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows license
- expect(page).to have_content('This project is licensed under the MIT License.')
+ create_file(file_name, '
+ {
+ "GoVersion": "go1.6"
+ }
+ ')
+ visit_blob(file_name)
+ end
- # shows a learn more link
- expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using godep.")
+ end
end
end
- end
- context '*.gemspec' do
- before do
- project.add_maintainer(project.creator)
+ context 'go.mod' do
+ before do
+ file_name = 'go.mod'
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add activerecord.gemspec",
- file_path: 'activerecord.gemspec',
- file_content: <<-SPEC.strip_heredoc
- Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = "activerecord"
- end
- SPEC
- ).execute
+ create_file(file_name, '
+ module example.com/mymodule
+
+ go 1.14
+ ')
+ visit_blob(file_name)
+ end
- visit_blob('activerecord.gemspec')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Go Modules.")
+ end
+ end
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows names of dependency manager and package
- expect(page).to have_content('This project manages its dependencies using RubyGems.')
+ context 'package.json' do
+ before do
+ file_name = 'package.json'
- # shows a learn more link
- expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
+ create_file(file_name, '
+ {
+ "name": "my-awesome-package",
+ "version": "1.0.0"
+ }
+ ')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using npm.")
+ end
end
end
- end
- context 'CONTRIBUTING.md' do
- before do
- file_name = 'CONTRIBUTING.md'
+ context 'podfile' do
+ before do
+ file_name = 'podfile'
- create_file(file_name, '## Contribution guidelines')
- visit_blob(file_name)
- end
+ create_file(file_name, 'platform :ios, "8.0"')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ end
end
end
- end
- context 'CHANGELOG.md' do
- before do
- file_name = 'CHANGELOG.md'
+ context 'test.podspec' do
+ before do
+ file_name = 'test.podspec'
- create_file(file_name, '## Changelog for v1.0.0')
- visit_blob(file_name)
- end
+ create_file(file_name, '
+ Pod::Spec.new do |s|
+ s.name = "TensorFlowLiteC"
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ end
end
end
- end
- context 'Cargo.toml' do
- before do
- file_name = 'Cargo.toml'
+ context 'JSON.podspec.json' do
+ before do
+ file_name = 'JSON.podspec.json'
- create_file(file_name, '
- [package]
- name = "hello_world" # the name of the package
- version = "0.1.0" # the current version, obeying semver
- authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
- ')
- visit_blob(file_name)
- end
+ create_file(file_name, '
+ {
+ "name": "JSON"
+ }
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Cargo.")
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ end
end
end
- end
- context 'Cartfile' do
- before do
- file_name = 'Cartfile'
+ context 'requirements.txt' do
+ before do
+ file_name = 'requirements.txt'
- create_file(file_name, '
- gitlab "Alamofire/Alamofire" == 4.9.0
- gitlab "Alamofire/AlamofireImage" ~> 3.4
- ')
- visit_blob(file_name)
+ create_file(file_name, 'Project requirements')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using pip.")
+ end
+ end
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Carthage.")
+ context 'yarn.lock' do
+ before do
+ file_name = 'yarn.lock'
+
+ create_file(file_name, '
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+ # yarn lockfile v1
+ ')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Yarn.")
+ end
end
end
end
- context 'composer.json' do
+ context 'realtime pipelines' do
before do
- file_name = 'composer.json'
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'feature',
+ branch_name: 'feature',
+ commit_message: "Add ruby file",
+ file_path: 'files/ruby/test.rb',
+ file_content: "# Awesome content"
+ ).execute
- create_file(file_name, '
- {
- "license": "MIT"
- }
- ')
- visit_blob(file_name)
+ create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
+ visit_blob('files/ruby/test.rb', ref: 'feature')
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Composer.")
+ it 'shows the realtime pipeline status' do
+ page.within('.commit-actions') do
+ expect(page).to have_css('.ci-status-icon')
+ expect(page).to have_css('.ci-status-icon-running')
+ expect(page).to have_css('.js-ci-status-icon-running')
end
end
end
- context 'Gemfile' do
- before do
- file_name = 'Gemfile'
+ context 'for subgroups' do
+ let(:group) { create(:group) }
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project) { create(:project, :public, :repository, group: subgroup) }
- create_file(file_name, '
- source "https://rubygems.org"
+ it 'renders tree table without errors' do
+ visit_blob('README.md')
- # Gems here
- ')
- visit_blob(file_name)
+ expect(page).to have_selector('.file-content')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Bundler.")
- end
+ it 'displays a GPG badge' do
+ visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
+
+ expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
+ expect(page).to have_selector '.gpg-status-box.invalid'
end
end
- context 'Godeps.json' do
- before do
- file_name = 'Godeps.json'
+ context 'on signed merge commit' do
+ it 'displays a GPG badge' do
+ visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
- create_file(file_name, '
- {
- "GoVersion": "go1.6"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using godep.")
- end
+ expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
+ expect(page).to have_selector '.gpg-status-box.invalid'
end
end
- context 'go.mod' do
+ context 'when static objects external storage is enabled' do
before do
- file_name = 'go.mod'
+ stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
+ end
- create_file(file_name, '
- module example.com/mymodule
+ context 'public project' do
+ before do
+ visit_blob('README.md')
+ end
- go 1.14
- ')
- visit_blob(file_name)
- end
+ it 'shows open raw and download buttons with external storage URL prepended to their href' do
+ path = project_raw_path(project, 'master/README.md')
+ raw_uri = "https://cdn.gitlab.com#{path}"
+ download_uri = "https://cdn.gitlab.com#{path}?inline=false"
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Go Modules.")
+ aggregate_failures do
+ expect(page).to have_link 'Open raw', href: raw_uri
+ expect(page).to have_link 'Download', href: download_uri
+ end
end
end
end
+ end
- context 'package.json' do
- before do
- file_name = 'package.json'
+ context 'with refactor_blob_viewer feature flag disabled' do
+ before do
+ stub_feature_flags(refactor_blob_viewer: false)
+ end
- create_file(file_name, '
- {
- "name": "my-awesome-package",
- "version": "1.0.0"
- }
- ')
- visit_blob(file_name)
- end
+ context 'when ref switch' do
+ # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
+ # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using npm.")
+ def switch_ref_to(ref_name)
+ first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
+
+ page.within '.project-refs-form' do
+ click_link ref_name
+ wait_for_requests
end
end
- end
- context 'podfile' do
- before do
- file_name = 'podfile'
+ context 'when highlighting lines' do
+ it 'displays single highlighted line number of different ref' do
+ visit_blob('files/js/application.js', anchor: 'L1')
- create_file(file_name, 'platform :ios, "8.0"')
- visit_blob(file_name)
- end
+ switch_ref_to('feature')
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ page.within '.blob-content' do
+ expect(find_by_id('LC1')[:class]).to include("hll")
+ end
end
- end
- end
- context 'test.podspec' do
- before do
- file_name = 'test.podspec'
+ it 'displays multiple highlighted line numbers of different ref' do
+ visit_blob('files/js/application.js', anchor: 'L1-3')
- create_file(file_name, '
- Pod::Spec.new do |s|
- s.name = "TensorFlowLiteC"
- ')
- visit_blob(file_name)
- end
+ switch_ref_to('feature')
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ page.within '.blob-content' do
+ expect(find_by_id('LC1')[:class]).to include("hll")
+ expect(find_by_id('LC2')[:class]).to include("hll")
+ expect(find_by_id('LC3')[:class]).to include("hll")
+ end
end
end
end
- context 'JSON.podspec.json' do
- before do
- file_name = 'JSON.podspec.json'
+ context 'visiting with a line number anchor' do
+ # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
+ # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
- create_file(file_name, '
- {
- "name": "JSON"
- }
- ')
- visit_blob(file_name)
+ before do
+ visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
end
- it 'displays an auxiliary viewer' do
+ it 'displays the blob using the simple viewer' do
aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+
+ # highlights the line in question
+ expect(page).to have_selector('#LC1.hll')
+
+ # shows highlighted Markdown code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
end
- context 'requirements.txt' do
- before do
- file_name = 'requirements.txt'
+ context 'binary file that appears to be text in the first 1024 bytes' do
+ # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
+ # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559
- create_file(file_name, 'Project requirements')
- visit_blob(file_name)
+ before do
+ visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
end
-
- it 'displays an auxiliary viewer' do
+ it 'displays the blob' do
aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using pip.")
+ # shows a download link
+ expect(page).to have_link('Download (23.8 KB)')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ # The specs below verify an arguably incorrect result, but since we only
+ # learn that the file is not actually text once the text viewer content
+ # is loaded asynchronously, there is no straightforward way to get these
+ # synchronously loaded elements to display correctly.
+ #
+ # Clicking the copy button will result in nothing being copied.
+ # Clicking the raw button will result in the binary file being downloaded,
+ # as expected.
+ # shows an enabled copy button, incorrectly
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # shows a raw button, incorrectly
+ expect(page).to have_link('Open raw')
end
end
end
- context 'yarn.lock' do
- before do
- file_name = 'yarn.lock'
+ context 'when static objects external storage is enabled' do
+ # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
+ # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351555
- create_file(file_name, '
- # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
- # yarn lockfile v1
- ')
- visit_blob(file_name)
+ before do
+ stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Yarn.")
+ context 'private project' do
+ let_it_be(:project) { create(:project, :repository, :private) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+ visit_blob('README.md')
+ end
+
+ it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
+ path = project_raw_path(project, 'master/README.md')
+ raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
+ download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
+
+ aggregate_failures do
+ expect(page).to have_link 'Open raw', href: raw_uri
+ expect(page).to have_link 'Download', href: download_uri
+ end
end
end
end
- context 'when refactor_blob_viewer is disabled' do
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
+ context 'files with auxiliary viewers' do
+ # This context is the same as the other 'files with auxiliary viewers' in this file, we just ensure that the auxiliary viewers still work this the refactor_blob_viewer disabled
+ # It should be safe to remove once we rollout the refactored blob viewer
describe '.gitlab-ci.yml' do
before do
@@ -1554,104 +1657,4 @@ RSpec.describe 'File blob', :js do
end
end
end
-
- context 'realtime pipelines' do
- before do
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'feature',
- branch_name: 'feature',
- commit_message: "Add ruby file",
- file_path: 'files/ruby/test.rb',
- file_content: "# Awesome content"
- ).execute
-
- create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
- visit_blob('files/ruby/test.rb', ref: 'feature')
- end
-
- it 'shows the realtime pipeline status' do
- page.within('.commit-actions') do
- expect(page).to have_css('.ci-status-icon')
- expect(page).to have_css('.ci-status-icon-running')
- expect(page).to have_css('.js-ci-status-icon-running')
- end
- end
- end
-
- context 'for subgroups' do
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:project) { create(:project, :public, :repository, group: subgroup) }
-
- it 'renders tree table without errors' do
- visit_blob('README.md')
-
- expect(page).to have_selector('.file-content')
- expect(page).not_to have_selector('.flash-alert')
- end
-
- it 'displays a GPG badge' do
- visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
-
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
- end
-
- context 'on signed merge commit' do
- it 'displays a GPG badge' do
- visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
-
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
- end
-
- context 'when static objects external storage is enabled' do
- before do
- stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
- end
-
- context 'private project' do
- let_it_be(:project) { create(:project, :repository, :private) }
- let_it_be(:user) { create(:user) }
-
- before do
- project.add_developer(user)
-
- sign_in(user)
- visit_blob('README.md')
- end
-
- it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
- download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
-
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
- end
- end
-
- context 'public project' do
- before do
- visit_blob('README.md')
- end
-
- it 'shows open raw and download buttons with external storage URL prepended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}"
- download_uri = "https://cdn.gitlab.com#{path}?inline=false"
-
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
- end
- end
- end
end
diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
index 1c79b2ddc38..a2db5e11c7c 100644
--- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
+++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled
include CookieHelper
let(:project) { create(:project, :empty_repo) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
describe 'viewing the new blob page' do
before do
diff --git a/spec/features/projects/branches/user_views_branches_spec.rb b/spec/features/projects/branches/user_views_branches_spec.rb
index d0c0a0860d9..b6b6dcb5cf1 100644
--- a/spec/features/projects/branches/user_views_branches_spec.rb
+++ b/spec/features/projects/branches/user_views_branches_spec.rb
@@ -4,7 +4,7 @@ require "spec_helper"
RSpec.describe "User views branches", :js do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb
index 16cfa9f5f84..daf5ac61d73 100644
--- a/spec/features/projects/ci/editor_spec.rb
+++ b/spec/features/projects/ci/editor_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'Pipeline Editor', :js do
expect(page).to have_content('Pipeline Editor')
end
- context 'branch switcher' do
+ describe 'Branch switcher' do
def switch_to_branch(branch)
find('[data-testid="branch-selector"]').click
@@ -64,7 +64,64 @@ RSpec.describe 'Pipeline Editor', :js do
end
end
- context 'Editor content' do
+ describe 'Editor navigation' do
+ context 'when no change is made' do
+ it 'user can navigate away without a browser alert' do
+ expect(page).to have_content('Pipeline Editor')
+
+ click_link 'Pipelines'
+
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+ end
+
+ context 'when a change is made' do
+ before do
+ click_button 'Collapse'
+
+ page.within('#source-editor-') do
+ find('textarea').send_keys '123'
+ # It takes some time after sending keys for the vue
+ # component to update
+ sleep 1
+ end
+ end
+
+ it 'user who tries to navigate away can cancel the action and keep their changes' do
+ click_link 'Pipelines'
+
+ page.driver.browser.switch_to.alert.dismiss
+
+ expect(page).to have_content('Pipeline Editor')
+
+ page.within('#source-editor-') do
+ expect(page).to have_content('Default Content123')
+ end
+ end
+
+ it 'user who tries to navigate away can confirm the action and discard their change' do
+ click_link 'Pipelines'
+
+ page.driver.browser.switch_to.alert.accept
+
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+
+ it 'user who creates a MR is taken to the merge request page without warnings' do
+ expect(page).not_to have_content('New merge request')
+
+ find_field('Target Branch').set 'new_branch'
+ find_field('Start a new merge request with these changes').click
+
+ click_button 'Commit changes'
+
+ expect(page).not_to have_content('Pipeline Editor')
+ expect(page).to have_content('New merge request')
+ end
+ end
+ end
+
+ describe 'Editor content' do
it 'user can reset their CI configuration' do
click_button 'Collapse'
diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb
index 4018ef2abc9..d2b07bbc1de 100644
--- a/spec/features/projects/cluster_agents_spec.rb
+++ b/spec/features/projects/cluster_agents_spec.rb
@@ -10,6 +10,11 @@ RSpec.describe 'ClusterAgents', :js do
let(:user) { project.creator }
before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
+ allow_next_instance_of(Gitlab::Kas::Client) do |client|
+ allow(client).to receive(:get_connected_agents).and_return([])
+ end
+
gitlab_sign_in(user)
end
@@ -22,7 +27,7 @@ RSpec.describe 'ClusterAgents', :js do
end
it 'displays empty state', :aggregate_failures do
- expect(page).to have_content('Install a new agent')
+ expect(page).to have_content('Install new Agent')
expect(page).to have_selector('.empty-state')
end
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 6e45529c659..b0406e1f3c4 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -99,7 +99,8 @@ RSpec.describe 'Clusters', :js do
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
+ double(
+ 'cluster_control',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index d88ff5c1aa5..bfd54b9c6da 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -132,6 +132,29 @@ RSpec.describe 'Environment' do
end
end
+ context 'with upcoming deployments' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ let!(:runnind_deployment_1) { create(:deployment, environment: environment, deployable: build, status: :running) }
+ let!(:runnind_deployment_2) { create(:deployment, environment: environment, deployable: build, status: :running) }
+ # Success deployments must have present `finished_at`. We'll backfill in the future.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350618 for more information.
+ let!(:success_without_finished_at) { create(:deployment, environment: environment, deployable: build, status: :success, finished_at: nil) }
+
+ before do
+ visit_environment(environment)
+ end
+
+ # This ordering is unexpected and to be fixed.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350618 for more information.
+ it 'shows upcoming deployments in unordered way' do
+ displayed_ids = find_all('[data-testid="deployment-id"]').map { |e| e.text }
+ internal_ids = [runnind_deployment_1, runnind_deployment_2, success_without_finished_at].map { |d| "##{d.iid}" }
+ expect(displayed_ids).to match_array(internal_ids)
+ end
+ end
+
context 'with related deployable present' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb
index 7d31de2b418..531eae1d638 100644
--- a/spec/features/projects/environments_pod_logs_spec.rb
+++ b/spec/features/projects/environments_pod_logs_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do
stub_kubeclient_ingresses(environment.deployment_namespace)
stub_kubeclient_nodes_and_nodes_metrics(cluster.platform.api_url)
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
it "shows environments in dropdown" do
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index 11663158b33..3a0cc61d9c6 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do
before do
project = create(:project, :repository)
- sign_in project.owner
+ sign_in project.first_owner
visit project_new_blob_path(project, 'master', file_name: 'Dockerfile')
end
diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb
index fda024e893d..e08c53a67dd 100644
--- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb
+++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User uses soft wrap while editing file', :js do
before do
project = create(:project, :repository)
- user = project.owner
+ user = project.first_owner
sign_in user
visit project_new_blob_path(project, 'master', file_name: 'test_file-name')
diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb
index 819864b3def..e256bec2a1c 100644
--- a/spec/features/projects/files/editing_a_file_spec.rb
+++ b/spec/features/projects/files/editing_a_file_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to edit a file' do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:commit_params) do
{
start_branch: project.default_branch,
diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
index 94190889ace..a283f7d128c 100644
--- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
+++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User views files page' do
let(:project) { create(:forked_project_with_submodules) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in user
diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb
index 4293183fd9a..9ae3be4993b 100644
--- a/spec/features/projects/files/find_file_keyboard_spec.rb
+++ b/spec/features/projects/files/find_file_keyboard_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > Find file keyboard shortcuts', :js do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in user
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index d47eaee2e79..4a92216f46c 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do
before do
project = create(:project, :repository)
- sign_in project.owner
+ sign_in project.first_owner
visit project_new_blob_path(project, 'master', file_name: '.gitignore')
end
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index fc199f66490..cdf6c219ea5 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
let_it_be(:project) { create(:project, :repository) }
before do
- sign_in project.owner
+ sign_in project.first_owner
visit project_new_blob_path(project, 'master', file_name: filename, **params)
end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index ab62e8aabc0..4a0b1f4c548 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > Project owner creates a license file', :js do
let(:project) { create(:project, :repository) }
- let(:project_maintainer) { project.owner }
+ let(:project_maintainer) { project.first_owner }
before do
project.repository.delete_file(project_maintainer, 'LICENSE',
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 37583870cfd..ca384291c12 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
include WebIdeSpecHelpers
let(:project) { create(:project_empty_repo) }
- let(:project_maintainer) { project.owner }
+ let(:project_maintainer) { project.first_owner }
before do
sign_in(project_maintainer)
diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb
index ca9ce841a92..9cdb5eeb076 100644
--- a/spec/features/projects/files/template_type_dropdown_spec.rb
+++ b/spec/features/projects/files/template_type_dropdown_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > Template type dropdown selector', :js do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in user
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 560cb53ead2..0b2daf12063 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > Template Undo Button', :js do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in user
diff --git a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
index 4d9da783f98..220572c6a6d 100644
--- a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
+++ b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
# This is a regression test for https://gitlab.com/gitlab-org/gitlab-foss/issues/37569
RSpec.describe 'Projects > Files > User browses a tree with a folder containing only a folder', :js do
let(:project) { create(:project, :empty_repo) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
project.repository.create_dir(user, 'foo/bar', branch_name: 'master', message: 'Add the foo/bar folder')
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 508dec70db6..9b4d1502bc8 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
-RSpec.describe "User browses files" do
+RSpec.describe "User browses files", :js do
include RepoHelpers
let(:fork_message) do
@@ -13,7 +13,7 @@ RSpec.describe "User browses files" do
let(:project) { create(:project, :repository, name: "Shop") }
let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") }
let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
@@ -340,32 +340,37 @@ RSpec.describe "User browses files" do
let(:newrev) { project.repository.commit('master').sha }
before do
- stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350456
create_file_in_repo(project, 'master', 'master', filename, 'Test file')
path = File.join('master', filename)
visit(project_blob_path(project, path))
+ wait_for_requests
end
- it "shows a raw file content" do
- click_link("Open raw")
+ it "shows raw file content in a new tab" do
+ new_tab = window_opened_by {click_link 'Open raw'}
- expect(source).to eq("") # Body is filled in by gitlab-workhorse
+ within_window new_tab do
+ expect(page).to have_content("Test file")
+ end
end
end
context "when browsing a raw file" do
before do
- stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350456
- path = File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path)
+ visit(tree_path_root_ref)
+ wait_for_requests
- visit(project_blob_path(project, path))
+ click_link(".gitignore")
+ wait_for_requests
end
- it "shows a raw file content" do
- click_link("Open raw")
+ it "shows raw file content in a new tab" do
+ new_tab = window_opened_by {click_link 'Open raw'}
- expect(source).to eq("") # Body is filled in by gitlab-workhorse
+ within_window new_tab do
+ expect(page).to have_content("*.rbc")
+ end
end
end
end
diff --git a/spec/features/projects/files/user_browses_lfs_files_spec.rb b/spec/features/projects/files/user_browses_lfs_files_spec.rb
index 17699847704..3976df849fa 100644
--- a/spec/features/projects/files/user_browses_lfs_files_spec.rb
+++ b/spec/features/projects/files/user_browses_lfs_files_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User browses LFS files' do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/files/user_searches_for_files_spec.rb b/spec/features/projects/files/user_searches_for_files_spec.rb
index 7fd7dfff279..cce73d06f94 100644
--- a/spec/features/projects/files/user_searches_for_files_spec.rb
+++ b/spec/features/projects/files/user_searches_for_files_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User searches for files' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb
index f4cd65bcba1..a7d68b07dd3 100644
--- a/spec/features/projects/gfm_autocomplete_load_spec.rb
+++ b/spec/features/projects/gfm_autocomplete_load_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'GFM autocomplete loading', :js do
let(:project) { create(:project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 2fbec4e22f4..1e5c5d33ad9 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'Import/Export - project import integration test', :js do
project = Project.last
expect(project).not_to be_nil
- expect(page).to have_content("Project 'test-project-path' is being imported")
+ expect(page).to have_content("Project 'Test Project Name' is being imported")
end
it 'invalid project' do
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/integrations/disable_triggers_spec.rb
index c6413685f38..b039d610ecb 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/integrations/disable_triggers_spec.rb
@@ -3,16 +3,16 @@
require 'spec_helper'
RSpec.describe 'Disable individual triggers', :js do
- include_context 'project service activation'
+ include_context 'project integration activation'
let(:checkbox_selector) { 'input[name$="_events]"]' }
before do
- visit_project_integration(service_name)
+ visit_project_integration(integration_name)
end
- context 'service has multiple supported events' do
- let(:service_name) { 'Jenkins' }
+ context 'integration has multiple supported events' do
+ let(:integration_name) { 'Jenkins' }
it 'shows trigger checkboxes' do
event_count = Integrations::Jenkins.supported_events.count
@@ -22,8 +22,8 @@ RSpec.describe 'Disable individual triggers', :js do
end
end
- context 'services only has one supported event' do
- let(:service_name) { 'Asana' }
+ context 'integrations only has one supported event' do
+ let(:integration_name) { 'Asana' }
it "doesn't show unnecessary Trigger checkboxes" do
expect(page).not_to have_content "Trigger"
diff --git a/spec/features/projects/integrations/project_integrations_spec.rb b/spec/features/projects/integrations/project_integrations_spec.rb
new file mode 100644
index 00000000000..708a5bca8c1
--- /dev/null
+++ b/spec/features/projects/integrations/project_integrations_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project integrations', :js do
+ include_context 'project integration activation'
+
+ it_behaves_like 'integration settings form' do
+ let(:integrations) { project.find_or_initialize_integrations }
+
+ def navigate_to_integration(integration)
+ visit_project_integration(integration.title)
+ end
+ end
+end
diff --git a/spec/features/projects/services/prometheus_external_alerts_spec.rb b/spec/features/projects/integrations/prometheus_external_alerts_spec.rb
index c2ae72ddb5e..7e56ca13e23 100644
--- a/spec/features/projects/services/prometheus_external_alerts_spec.rb
+++ b/spec/features/projects/integrations/prometheus_external_alerts_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Prometheus external alerts', :js do
- include_context 'project service activation'
+ include_context 'project integration activation'
let(:alerts_section_selector) { '.js-prometheus-alerts' }
let(:alerts_section) { page.find(alerts_section_selector) }
diff --git a/spec/features/projects/integrations/user_activates_asana_spec.rb b/spec/features/projects/integrations/user_activates_asana_spec.rb
index cf2290383e8..9ec9f00529a 100644
--- a/spec/features/projects/integrations/user_activates_asana_spec.rb
+++ b/spec/features/projects/integrations/user_activates_asana_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'User activates Asana' do
- include_context 'project service activation'
+ include_context 'project integration activation'
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Asana')
fill_in('API key', with: 'verySecret')
fill_in('Restrict to branch', with: 'verySecret')
diff --git a/spec/features/projects/integrations/user_activates_assembla_spec.rb b/spec/features/projects/integrations/user_activates_assembla_spec.rb
index 63cc424a641..be9034ec5ba 100644
--- a/spec/features/projects/integrations/user_activates_assembla_spec.rb
+++ b/spec/features/projects/integrations/user_activates_assembla_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates Assembla' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:post, /.*atlas.assembla.com.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Assembla')
fill_in('Token', with: 'verySecret')
diff --git a/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb
index 91db375be3a..49f62a34bd2 100644
--- a/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb
+++ b/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates Atlassian Bamboo CI' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:get, /.*bamboo.example.com.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Atlassian Bamboo')
fill_in('Bamboo URL', with: 'http://bamboo.example.com')
fill_in('Build key', with: 'KEY')
diff --git a/spec/features/projects/services/user_activates_emails_on_push_spec.rb b/spec/features/projects/integrations/user_activates_emails_on_push_spec.rb
index 5a075fc61e8..168779aad07 100644
--- a/spec/features/projects/services/user_activates_emails_on_push_spec.rb
+++ b/spec/features/projects/integrations/user_activates_emails_on_push_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'User activates Emails on push' do
- include_context 'project service activation'
+ include_context 'project integration activation'
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Emails on push')
fill_in('Recipients', with: 'qa@company.name')
diff --git a/spec/features/projects/integrations/user_activates_flowdock_spec.rb b/spec/features/projects/integrations/user_activates_flowdock_spec.rb
index 4a4d7bbecfd..df1a4feddfb 100644
--- a/spec/features/projects/integrations/user_activates_flowdock_spec.rb
+++ b/spec/features/projects/integrations/user_activates_flowdock_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'User activates Flowdock' do
- include_context 'project service activation' do
+ include_context 'project integration activation' do
let(:project) { create(:project, :repository) }
end
@@ -11,7 +11,7 @@ RSpec.describe 'User activates Flowdock' do
stub_request(:post, /.*api.flowdock.com.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Flowdock')
fill_in('Token', with: 'verySecret')
diff --git a/spec/features/projects/services/user_activates_irker_spec.rb b/spec/features/projects/integrations/user_activates_irker_spec.rb
index 004aa116bb3..23b5f2a5c47 100644
--- a/spec/features/projects/services/user_activates_irker_spec.rb
+++ b/spec/features/projects/integrations/user_activates_irker_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'User activates irker (IRC gateway)' do
- include_context 'project service activation'
+ include_context 'project integration activation'
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('irker (IRC gateway)')
check('Colorize messages')
fill_in('Recipients', with: 'irc://chat.freenode.net/#commits')
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb
index 27c23e7beb5..b9c2c539899 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'User activates issue tracker', :js do
- include_context 'project service activation'
+ include_context 'project integration activation'
let(:url) { 'http://tracker.example.com' }
@@ -17,7 +17,7 @@ RSpec.describe 'User activates issue tracker', :js do
end
shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false, skip_test: false|
- describe 'user sets and activates the Service' do
+ describe 'user sets and activates the integration' do
context 'when the connection test succeeds' do
before do
stub_request(:head, url).to_return(headers: { 'Content-Type' => 'application/json' })
@@ -32,7 +32,7 @@ RSpec.describe 'User activates issue tracker', :js do
end
end
- it 'activates the service' do
+ it 'activates the integration' do
expect(page).to have_content("#{tracker} settings saved and active.")
expect(current_path).to eq(edit_project_integration_path(project, tracker.parameterize(separator: '_')))
end
@@ -45,7 +45,7 @@ RSpec.describe 'User activates issue tracker', :js do
end
context 'when the connection test fails' do
- it 'activates the service' do
+ it 'activates the integration' do
stub_request(:head, url).to_raise(Gitlab::HTTP::Error)
visit_project_integration(tracker)
@@ -63,7 +63,7 @@ RSpec.describe 'User activates issue tracker', :js do
end
end
- describe 'user disables the service' do
+ describe 'user disables the integration' do
before do
visit_project_integration(tracker)
fill_form(disable: true, skip_new_issue_url: skip_new_issue_url)
@@ -71,7 +71,7 @@ RSpec.describe 'User activates issue tracker', :js do
click_button('Save changes')
end
- it 'saves but does not activate the service' do
+ it 'saves but does not activate the integration' do
expect(page).to have_content("#{tracker} settings saved, but not active.")
expect(current_path).to eq(edit_project_integration_path(project, tracker.parameterize(separator: '_')))
end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/integrations/user_activates_jetbrains_teamcity_ci_spec.rb
index 17bfe8fc1e2..e6f2e462b8c 100644
--- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
+++ b/spec/features/projects/integrations/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates JetBrains TeamCity CI' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:post, /.*teamcity.example.com.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('JetBrains TeamCity')
check('Push')
check('Merge Request')
diff --git a/spec/features/projects/integrations/user_activates_jira_spec.rb b/spec/features/projects/integrations/user_activates_jira_spec.rb
index 50010950f0e..7562dc00092 100644
--- a/spec/features/projects/integrations/user_activates_jira_spec.rb
+++ b/spec/features/projects/integrations/user_activates_jira_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe 'User activates Jira', :js do
- include_context 'project service activation'
- include_context 'project service Jira context'
+ include_context 'project integration activation'
+ include_context 'project integration Jira context'
before do
stub_request(:get, test_url).to_return(body: { key: 'value' }.to_json)
end
- describe 'user tests Jira Service' do
+ describe 'user tests Jira integration' do
context 'when Jira connection test succeeds' do
before do
visit_project_integration('Jira')
@@ -18,7 +18,7 @@ RSpec.describe 'User activates Jira', :js do
click_test_then_save_integration(expect_test_to_fail: false)
end
- it 'activates the Jira service' do
+ it 'activates the Jira integration' do
expect(page).to have_content('Jira settings saved and active.')
expect(current_path).to eq(edit_project_integration_path(project, :jira))
end
@@ -46,7 +46,7 @@ RSpec.describe 'User activates Jira', :js do
end
end
- it 'activates the Jira service' do
+ it 'activates the Jira integration' do
stub_request(:get, test_url).with(basic_auth: %w(username password))
.to_raise(JIRA::HTTPError.new(double(message: 'message')))
@@ -60,7 +60,7 @@ RSpec.describe 'User activates Jira', :js do
end
end
- describe 'user disables the Jira Service' do
+ describe 'user disables the Jira integration' do
include JiraServiceHelper
before do
@@ -70,7 +70,7 @@ RSpec.describe 'User activates Jira', :js do
click_save_integration
end
- it 'saves but does not activate the Jira service' do
+ it 'saves but does not activate the Jira integration' do
expect(page).to have_content('Jira settings saved, but not active.')
expect(current_path).to eq(edit_project_integration_path(project, :jira))
end
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb
index 74919a99f04..ed0877ab0e9 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb
@@ -4,14 +4,14 @@ require 'spec_helper'
RSpec.describe 'Set up Mattermost slash commands', :js do
describe 'user visits the mattermost slash command config page' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_mattermost_setting(enabled: mattermost_enabled)
visit_project_integration('Mattermost slash commands')
end
- context 'mattermost service is enabled' do
+ context 'mattermost integration is enabled' do
let(:mattermost_enabled) { true }
describe 'activation' do
@@ -84,7 +84,9 @@ 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(Integrations::MattermostSlashCommands).to receive(:list_teams) { [[], 'test mattermost error message'] }
+ allow_next_instance_of(Integrations::MattermostSlashCommands) do |integration|
+ allow(integration).to receive(:list_teams).and_return([[], 'test mattermost error message'])
+ end
click_link 'Add to Mattermost'
@@ -113,7 +115,9 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
def stub_teams(count: 0)
teams = create_teams(count)
- allow_any_instance_of(Integrations::MattermostSlashCommands).to receive(:list_teams) { [teams, nil] }
+ allow_next_instance_of(Integrations::MattermostSlashCommands) do |integration|
+ allow(integration).to receive(:list_teams).and_return([teams, nil])
+ end
teams
end
@@ -129,7 +133,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
end
end
- context 'mattermost service is not enabled' do
+ context 'mattermost integration is not enabled' do
let(:mattermost_enabled) { false }
it 'shows the correct trigger url' do
diff --git a/spec/features/projects/services/user_activates_packagist_spec.rb b/spec/features/projects/integrations/user_activates_packagist_spec.rb
index 87303cf8fb4..0892843e840 100644
--- a/spec/features/projects/services/user_activates_packagist_spec.rb
+++ b/spec/features/projects/integrations/user_activates_packagist_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates Packagist' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:post, /.*packagist.org.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Packagist')
fill_in('Username', with: 'theUser')
fill_in('Token', with: 'verySecret')
diff --git a/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb
index ea34a766719..fe6ed786ace 100644
--- a/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb
+++ b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates PivotalTracker' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:post, /.*www.pivotaltracker.com.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Pivotal Tracker')
fill_in('Token', with: 'verySecret')
diff --git a/spec/features/projects/services/user_activates_prometheus_spec.rb b/spec/features/projects/integrations/user_activates_prometheus_spec.rb
index 73ad8088be2..80629af6fce 100644
--- a/spec/features/projects/services/user_activates_prometheus_spec.rb
+++ b/spec/features/projects/integrations/user_activates_prometheus_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates Prometheus' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:get, /.*prometheus.example.com.*/)
end
- it 'does not activate service and informs about deprecation', :js do
+ it 'does not activate integration and informs about deprecation', :js do
visit_project_integration('Prometheus')
check('Active')
fill_in('API URL', with: 'http://prometheus.example.com')
diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/integrations/user_activates_pushover_spec.rb
index d92f69e700a..616efdc836f 100644
--- a/spec/features/projects/services/user_activates_pushover_spec.rb
+++ b/spec/features/projects/integrations/user_activates_pushover_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe 'User activates Pushover' do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_request(:post, /.*api.pushover.net.*/)
end
- it 'activates service', :js do
+ it 'activates integration', :js do
visit_project_integration('Pushover')
fill_in('API key', with: 'verySecret')
fill_in('User key', with: 'verySecret')
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/integrations/user_activates_slack_notifications_spec.rb
index 38b6ad84c77..616469c5df8 100644
--- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb
+++ b/spec/features/projects/integrations/user_activates_slack_notifications_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe 'User activates Slack notifications', :js do
- include_context 'project service activation'
+ include_context 'project integration activation'
- context 'when service is not configured yet' do
+ context 'when integration is not configured yet' do
before do
visit_project_integration('Slack notifications')
end
- it 'activates service' do
+ it 'activates integration' do
fill_in('Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685')
click_test_then_save_integration
@@ -19,7 +19,7 @@ RSpec.describe 'User activates Slack notifications', :js do
end
end
- context 'when service is already configured' do
+ context 'when integration is already configured' do
let(:integration) { Integrations::Slack.new }
let(:project) { create(:project, slack_integration: integration) }
diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/integrations/user_activates_slack_slash_command_spec.rb
index d46d1f739b7..7ec469070ea 100644
--- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
+++ b/spec/features/projects/integrations/user_activates_slack_slash_command_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Slack slash commands', :js do
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
visit_project_integration('Slack slash commands')
diff --git a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
index d2c4418f0d6..fcb04c338a9 100644
--- a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
+++ b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'User uses inherited settings', :js do
include JiraServiceHelper
- include_context 'project service activation'
+ include_context 'project integration activation'
before do
stub_jira_integration_test
diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/integrations/user_views_services_spec.rb
index 201a58ba379..559461f911f 100644
--- a/spec/features/projects/services/user_views_services_spec.rb
+++ b/spec/features/projects/integrations/user_views_services_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
-RSpec.describe 'User views services', :js do
- include_context 'project service activation'
+RSpec.describe 'User views integrations', :js do
+ include_context 'project integration activation'
- it 'shows the list of available services' do
+ it 'shows the list of available integrations' do
visit_project_integrations
expect(page).to have_content('Integrations')
diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
index 211576a93f3..762f9c33510 100644
--- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
+++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'User uploads new design', :js do
include DesignManagementTestHelpers
let(:project) { create(:project_empty_repo, :public) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:issue) { create(:issue, project: project) }
before do
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 7ccd5c51493..a65d2d15c12 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -615,7 +615,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end
context 'when the user is not able to view the cluster' do
- let(:user_access_level) { :developer }
+ let(:user_access_level) { :reporter }
it 'includes only the name of the cluster without a link' do
expect(page).to have_content 'using cluster the-cluster'
diff --git a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
index c8a9f959188..c9fee9bee7a 100644
--- a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
+++ b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
@@ -21,6 +21,6 @@ RSpec.describe 'Projects > Members > Group member cannot leave group project' do
it 'renders a flash message if attempting to leave by url', :js do
visit project_path(project, leave: 1)
- expect(find('.flash-alert')).to have_content 'You do not have permission to leave this project'
+ expect(find('[data-testid="alert-danger"]')).to have_content 'You do not have permission to leave this project'
end
end
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index b674cad0312..066e0b0d20f 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
- let(:maintainer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
using RSpec::Parameterized::TableSyntax
@@ -190,17 +190,26 @@ RSpec.describe 'Project > Members > Invite group', :js do
end
describe 'the groups dropdown' do
- context 'with multiple groups to choose from' do
- let(:project) { create(:project) }
+ let_it_be(:parent_group) { create(:group, :public) }
+ let_it_be(:project_group) { create(:group, :public, parent: parent_group) }
+ let_it_be(:public_sub_subgroup) { create(:group, :public, parent: project_group) }
+ let_it_be(:public_sibbling_group) { create(:group, :public, parent: parent_group) }
+ let_it_be(:private_sibbling_group) { create(:group, :private, parent: parent_group) }
+ let_it_be(:private_membership_group) { create(:group, :private) }
+ let_it_be(:public_membership_group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, group: project_group) }
- it 'includes multiple groups' do
- project.add_maintainer(maintainer)
- sign_in(maintainer)
+ before do
+ private_membership_group.add_guest(maintainer)
+ public_membership_group.add_maintainer(maintainer)
+
+ sign_in(maintainer)
+ end
- group1 = create(:group)
- group1.add_owner(maintainer)
- group2 = create(:group)
- group2.add_owner(maintainer)
+ context 'for a project in a nested group' do
+ it 'does not show the groups inherited from projects' do
+ project.add_maintainer(maintainer)
+ public_sibbling_group.add_maintainer(maintainer)
visit project_project_members_path(project)
@@ -208,37 +217,90 @@ RSpec.describe 'Project > Members > Invite group', :js do
click_on 'Select a group'
wait_for_requests
- expect(page).to have_button(group1.name)
- expect(page).to have_button(group2.name)
- end
- end
-
- context 'for a project in a nested group' do
- let(:group) { create(:group) }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:group_to_share_with) { create(:group) }
- let!(:project) { create(:project, namespace: nested_group) }
+ page.within('[data-testid="group-select-dropdown"]') do
+ expect_to_have_group(public_membership_group)
+ expect_to_have_group(public_sibbling_group)
+ expect_to_have_group(private_membership_group)
- before do
- project.add_maintainer(maintainer)
- sign_in(maintainer)
- group.add_maintainer(maintainer)
- group_to_share_with.add_maintainer(maintainer)
+ expect_not_to_have_group(public_sub_subgroup)
+ expect_not_to_have_group(private_sibbling_group)
+ expect_not_to_have_group(parent_group)
+ expect_not_to_have_group(project_group)
+ end
end
- # This behavior should be changed to exclude the ancestor and project
- # group from the options once issue is fixed for the modal:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/329835
- it 'the groups dropdown does show ancestors and the project group' do
+ it 'does not show the ancestors or project group', :aggregate_failures do
+ parent_group.add_maintainer(maintainer)
+
visit project_project_members_path(project)
click_on 'Invite a group'
click_on 'Select a group'
wait_for_requests
- expect(page).to have_button(group_to_share_with.name)
- expect(page).to have_button(group.name)
- expect(page).to have_button(nested_group.name)
+ page.within('[data-testid="group-select-dropdown"]') do
+ expect_to_have_group(public_membership_group)
+ expect_to_have_group(public_sibbling_group)
+ expect_to_have_group(private_membership_group)
+ expect_to_have_group(public_sub_subgroup)
+ expect_to_have_group(private_sibbling_group)
+
+ expect_not_to_have_group(parent_group)
+ expect_not_to_have_group(project_group)
+ end
+ end
+
+ context 'when invite_members_group_modal feature disabled' do
+ let(:group_invite_dropdown) { find('#select2-results-2') }
+
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'does not show the groups inherited from projects', :aggregate_failures do
+ project.add_maintainer(maintainer)
+ public_sibbling_group.add_maintainer(maintainer)
+
+ visit project_project_members_path(project)
+
+ click_on 'Invite group'
+ click_on 'Search for a group'
+ wait_for_requests
+
+ expect(group_invite_dropdown).to have_text(public_membership_group.full_path)
+ expect(group_invite_dropdown).to have_text(public_sibbling_group.full_path)
+ expect(group_invite_dropdown).to have_text(private_membership_group.full_path)
+ expect(group_invite_dropdown).not_to have_text(public_sub_subgroup.full_path)
+ expect(group_invite_dropdown).not_to have_text(private_sibbling_group.full_path)
+ expect(group_invite_dropdown).not_to have_text(parent_group.full_path, exact: true)
+ expect(group_invite_dropdown).not_to have_text(project_group.full_path, exact: true)
+ end
+
+ it 'does not show the ancestors or project group', :aggregate_failures do
+ parent_group.add_maintainer(maintainer)
+
+ visit project_project_members_path(project)
+
+ click_on 'Invite group'
+ click_on 'Search for a group'
+ wait_for_requests
+
+ expect(group_invite_dropdown).to have_text(public_membership_group.full_path)
+ expect(group_invite_dropdown).to have_text(public_sub_subgroup.full_path)
+ expect(group_invite_dropdown).to have_text(public_sibbling_group.full_path)
+ expect(group_invite_dropdown).to have_text(private_sibbling_group.full_path)
+ expect(group_invite_dropdown).to have_text(private_membership_group.full_path)
+ expect(group_invite_dropdown).not_to have_text(parent_group.full_path, exact: true)
+ expect(group_invite_dropdown).not_to have_text(project_group.full_path, exact: true)
+ end
+ end
+
+ def expect_to_have_group(group)
+ expect(page).to have_selector("[entity-id='#{group.id}']")
+ end
+
+ def expect_not_to_have_group(group)
+ expect(page).not_to have_selector("[entity-id='#{group.id}']")
end
end
end
diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb
index 4881a7bdf1a..c38292f81bf 100644
--- a/spec/features/projects/members/member_leaves_project_spec.rb
+++ b/spec/features/projects/members/member_leaves_project_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Member leaves project' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
@@ -21,13 +23,18 @@ RSpec.describe 'Projects > Members > Member leaves project' do
expect(project.users.exists?(user.id)).to be_falsey
end
- it 'user leaves project by url param', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/35925' do
+ it 'user leaves project by url param', :js do
visit project_path(project, leave: 1)
page.accept_confirm
+ wait_for_all_requests
- expect(find('.flash-notice')).to have_content "You left the \"#{project.full_name}\" project"
expect(current_path).to eq(dashboard_projects_path)
- expect(project.users.exists?(user.id)).to be_falsey
+
+ sign_in(project.first_owner)
+
+ visit project_project_members_path(project)
+
+ expect(members_table).not_to have_content(user.name)
end
end
diff --git a/spec/features/projects/members/owner_cannot_leave_project_spec.rb b/spec/features/projects/members/owner_cannot_leave_project_spec.rb
index fbe8583b236..45a8f979b87 100644
--- a/spec/features/projects/members/owner_cannot_leave_project_spec.rb
+++ b/spec/features/projects/members/owner_cannot_leave_project_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > Owner cannot leave project' do
let(:project) { create(:project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
diff --git a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb
index 5e6e3d4d7f2..fad5d831c19 100644
--- a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb
+++ b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > Owner cannot request access to their own pr
let(:project) { create(:project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index dcaef5f4ef0..0b00656f87b 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > User requests access', :js do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
- let(:maintainer) { project.owner }
+ let(:maintainer) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index f61eaccf5b9..91e643ff258 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Project navbar' do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/network_graph_spec.rb b/spec/features/projects/network_graph_spec.rb
index 4ae809399b6..1ee0ea51e53 100644
--- a/spec/features/projects/network_graph_spec.rb
+++ b/spec/features/projects/network_graph_spec.rb
@@ -96,7 +96,7 @@ RSpec.describe 'Project Network Graph', :js do
find('button').click
end
- expect(page).to have_selector '.flash-alert', text: "Git revision ';' does not exist."
+ expect(page).to have_selector '[data-testid="alert-danger"]', text: "Git revision ';' does not exist."
end
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index f1786c1be40..b3fbf5d356e 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -306,10 +306,24 @@ RSpec.describe 'New project', :js do
expect(page).to have_text('There is not a valid Git repository at this URL')
end
+ it 'reports error if repo URL is not a valid Git repository and submit button is clicked immediately' do
+ stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return(status: 200, body: "not-a-git-repo")
+
+ fill_in 'project_import_url', with: 'http://foo/bar'
+ click_on 'Create project'
+
+ wait_for_requests
+
+ expect(page).to have_text('There is not a valid Git repository at this URL')
+ end
+
it 'keeps "Import project" tab open after form validation error' do
collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace)
+ stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200,
+ body: '001e# service=git-upload-pack',
+ headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } })
- fill_in 'project_import_url', with: collision_project.http_url_to_repo
+ fill_in 'project_import_url', with: 'http://foo/bar'
fill_in 'project_name', with: collision_project.name
click_on 'Create project'
@@ -319,6 +333,38 @@ RSpec.describe 'New project', :js do
end
end
+ context 'when import is initiated from project page' do
+ before do
+ project_without_repo = create(:project, name: 'project-without-repo', namespace: user.namespace)
+ visit project_path(project_without_repo)
+ click_on 'Import repository'
+ end
+
+ it 'reports error when invalid url is provided' do
+ stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return(status: 200, body: "not-a-git-repo")
+
+ fill_in 'project_import_url', with: 'http://foo/bar'
+
+ click_on 'Start import'
+ wait_for_requests
+
+ expect(page).to have_text('There is not a valid Git repository at this URL')
+ end
+
+ it 'initiates import when valid repo url is provided' do
+ stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200,
+ body: '001e# service=git-upload-pack',
+ headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } })
+
+ fill_in 'project_import_url', with: 'http://foo/bar'
+
+ click_on 'Start import'
+ wait_for_requests
+
+ expect(page).to have_text('Import in progress')
+ end
+ end
+
context 'from GitHub' do
before do
first('.js-import-github').click
@@ -358,4 +404,47 @@ RSpec.describe 'New project', :js do
end
end
end
+
+ context 'from Bitbucket', :js do
+ shared_examples 'has a link to bitbucket cloud' do
+ context 'when bitbucket is not configured' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:enabled?).and_call_original
+ allow(Gitlab::Auth::OAuth::Provider)
+ .to receive(:enabled?).with(:bitbucket)
+ .and_return(false)
+
+ visit new_project_path
+ click_link 'Import project'
+ click_link 'Bitbucket Cloud'
+ end
+
+ it 'shows import instructions' do
+ expect(find('.modal-body')).to have_content(bitbucket_link_content)
+ end
+ end
+ end
+
+ context 'as a user' do
+ let(:user) { create(:user) }
+ let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, ask your GitLab administrator to configure OAuth integration' }
+
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'has a link to bitbucket cloud'
+ end
+
+ context 'as an admin' do
+ let(:user) { create(:admin) }
+ let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, as administrator you need to configure OAuth integration' }
+
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'has a link to bitbucket cloud'
+ end
+ end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 5176a7ec5a1..01c942aec4c 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -715,7 +715,7 @@ RSpec.describe 'Pipeline', :js do
let(:schedule) do
create(:ci_pipeline_schedule,
project: project,
- owner: project.owner,
+ owner: project.first_owner,
description: 'blocked user schedule'
).tap do |schedule|
schedule.update_column(:next_run_at, 1.minute.ago)
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index fb45db213d0..d5b470194a2 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Pipelines', :js do
include ProjectForksHelper
+ include Spec::Support::Helpers::ModalHelpers
let(:project) { create(:project) }
@@ -159,7 +160,7 @@ RSpec.describe 'Pipelines', :js do
end
end
- context 'when pipeline is detached merge request pipeline' do
+ context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned off' do
let(:merge_request) do
create(:merge_request,
:with_detached_merge_request_pipeline,
@@ -172,6 +173,8 @@ RSpec.describe 'Pipelines', :js do
let(:target_project) { project }
before do
+ stub_feature_flags(rearrange_pipelines_table: false)
+
visit project_pipelines_path(source_project)
end
@@ -201,7 +204,47 @@ RSpec.describe 'Pipelines', :js do
end
end
- context 'when pipeline is merge request pipeline' do
+ context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned on' do
+ let(:merge_request) do
+ create(:merge_request,
+ :with_detached_merge_request_pipeline,
+ source_project: source_project,
+ target_project: target_project)
+ end
+
+ let!(:pipeline) { merge_request.all_pipelines.first }
+ let(:source_project) { project }
+ let(:target_project) { project }
+
+ before do
+ stub_feature_flags(rearrange_pipelines_table: true)
+
+ visit project_pipelines_path(source_project)
+ end
+
+ shared_examples_for 'detached merge request pipeline' do
+ it 'shows pipeline information without pipeline ref', :sidekiq_might_not_need_inline do
+ within '.pipeline-tags' do
+ expect(page).to have_content('detached')
+
+ expect(page).to have_link(merge_request.iid,
+ href: project_merge_request_path(project, merge_request))
+
+ expect(page).not_to have_link(pipeline.ref)
+ end
+ end
+ end
+
+ it_behaves_like 'detached merge request pipeline'
+
+ context 'when source project is a forked project' do
+ let(:source_project) { fork_project(project, user, repository: true) }
+
+ it_behaves_like 'detached merge request pipeline'
+ end
+ end
+
+ context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned off' do
let(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
@@ -215,6 +258,8 @@ RSpec.describe 'Pipelines', :js do
let(:target_project) { project }
before do
+ stub_feature_flags(rearrange_pipelines_table: false)
+
visit project_pipelines_path(source_project)
end
@@ -244,6 +289,47 @@ RSpec.describe 'Pipelines', :js do
end
end
+ context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned on' do
+ let(:merge_request) do
+ create(:merge_request,
+ :with_merge_request_pipeline,
+ source_project: source_project,
+ target_project: target_project,
+ merge_sha: target_project.commit.sha)
+ end
+
+ let!(:pipeline) { merge_request.all_pipelines.first }
+ let(:source_project) { project }
+ let(:target_project) { project }
+
+ before do
+ stub_feature_flags(rearrange_pipelines_table: true)
+
+ visit project_pipelines_path(source_project)
+ end
+
+ shared_examples_for 'Correct merge request pipeline information' do
+ it 'does not show detached tag for the pipeline, and shows the link of the merge request, and does not show the ref of the pipeline', :sidekiq_might_not_need_inline do
+ within '.pipeline-tags' do
+ expect(page).not_to have_content('detached')
+
+ expect(page).to have_link(merge_request.iid,
+ href: project_merge_request_path(project, merge_request))
+
+ expect(page).not_to have_link(pipeline.ref)
+ end
+ end
+ end
+
+ it_behaves_like 'Correct merge request pipeline information'
+
+ context 'when source project is a forked project' do
+ let(:source_project) { fork_project(project, user, repository: true) }
+
+ it_behaves_like 'Correct merge request pipeline information'
+ end
+ end
+
context 'when pipeline has configuration errors' do
let(:pipeline) do
create(:ci_pipeline, :invalid, project: project)
@@ -351,7 +437,9 @@ RSpec.describe 'Pipelines', :js do
context 'when user played a delayed job immediately' do
before do
find('[data-testid="pipelines-manual-actions-dropdown"]').click
- page.accept_confirm { click_button('delayed job 1') }
+ accept_gl_confirm do
+ click_button 'delayed job 1'
+ end
wait_for_requests
end
@@ -587,6 +675,7 @@ RSpec.describe 'Pipelines', :js do
context 'with pipeline key selection' do
before do
+ stub_feature_flags(rearrange_pipelines_table: false)
visit project_pipelines_path(project)
wait_for_requests
end
@@ -604,6 +693,27 @@ RSpec.describe 'Pipelines', :js do
expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}"
end
end
+
+ context 'with pipeline key selection and rearrange_pipelines_table ff on' do
+ before do
+ stub_feature_flags(rearrange_pipelines_table: true)
+ visit project_pipelines_path(project)
+ wait_for_requests
+ end
+
+ it 'changes the Pipeline ID column for Pipeline IID' do
+ page.find('[data-testid="pipeline-key-dropdown"]').click
+
+ within '.gl-new-dropdown-contents' do
+ dropdown_options = page.find_all '.gl-new-dropdown-item'
+
+ dropdown_options[1].click
+ end
+
+ expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline'
+ expect(page.find('[data-testid="pipeline-identifier"]')).to have_content "##{pipeline.iid}"
+ end
+ end
end
describe 'GET /:project/-/pipelines/show' do
@@ -750,7 +860,7 @@ RSpec.describe 'Pipelines', :js do
it 'increments jobs_cache_index' do
click_button 'Clear runner caches'
wait_for_requests
- expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
+ expect(page.find('[data-testid="alert-info"]')).to have_content 'Project cache successfully reset.'
end
end
@@ -758,7 +868,7 @@ RSpec.describe 'Pipelines', :js do
it 'sets jobs_cache_index to 1' do
click_button 'Clear runner caches'
wait_for_requests
- expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
+ expect(page.find('[data-testid="alert-info"]')).to have_content 'Project cache successfully reset.'
end
end
end
diff --git a/spec/features/projects/settings/monitor_settings_spec.rb b/spec/features/projects/settings/monitor_settings_spec.rb
index 3f6c4646f00..871391fbe9c 100644
--- a/spec/features/projects/settings/monitor_settings_spec.rb
+++ b/spec/features/projects/settings/monitor_settings_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Settings > For a forked project', :js do
let_it_be(:project) { create(:project, :repository, create_templates: :issue) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/settings/packages_settings_spec.rb b/spec/features/projects/settings/packages_settings_spec.rb
index e70839e9720..057e6b635fe 100644
--- a/spec/features/projects/settings/packages_settings_spec.rb
+++ b/spec/features/projects/settings/packages_settings_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Settings > Packages', :js do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb
index b67caa5a5f9..a0d44b579a8 100644
--- a/spec/features/projects/settings/project_settings_spec.rb
+++ b/spec/features/projects/settings/project_settings_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects settings' do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:panel) { find('.general-settings', match: :first) }
let(:button) { panel.find('.btn.gl-button.js-settings-toggle') }
let(:title) { panel.find('.settings-title') }
diff --git a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
index 91a7753fe6d..d16295aedbe 100644
--- a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
+++ b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
@@ -4,7 +4,7 @@ require "spec_helper"
RSpec.describe "User interacts with deploy keys", :js do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/show/redirects_spec.rb b/spec/features/projects/show/redirects_spec.rb
index 659edda5672..3ac82244ded 100644
--- a/spec/features/projects/show/redirects_spec.rb
+++ b/spec/features/projects/show/redirects_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe 'Projects > Show > Redirects' do
it 'redirects to private project page after sign in' do
visit project_path(private_project)
- owner = private_project.owner
+ owner = private_project.first_owner
fill_in 'user_login', with: owner.email
fill_in 'user_password', with: owner.password
click_button 'Sign in'
diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb
index 80dae4ec386..1df37eef6a9 100644
--- a/spec/features/projects/show/user_manages_notifications_spec.rb
+++ b/spec/features/projects/show/user_manages_notifications_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do
let(:project) { create(:project, :public, :repository) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
def click_notifications_button
diff --git a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
index b7af0c29b33..47e010dcf89 100644
--- a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
+++ b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects > Show > User sees a deletion failure message' do
let(:project) { create(:project, :empty_repo, pending_delete: true) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
it 'shows error message if deletion for project fails' do
diff --git a/spec/features/projects/show/user_sees_git_instructions_spec.rb b/spec/features/projects/show/user_sees_git_instructions_spec.rb
index e6157887c12..5270939f681 100644
--- a/spec/features/projects/show/user_sees_git_instructions_spec.rb
+++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe 'Projects > Show > User sees Git instructions' do
let_it_be(:project) { create(:project, :public) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
@@ -77,7 +77,7 @@ RSpec.describe 'Projects > Show > User sees Git instructions' do
.at_least(:once)
.and_return('example_branch')
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit project_path(project)
end
diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb
index f8bbaa9535b..cd94e6da018 100644
--- a/spec/features/projects/tree/tree_show_spec.rb
+++ b/spec/features/projects/tree/tree_show_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Projects tree', :js do
expect(page).to have_selector('.tree-item')
expect(page).to have_content('add tests for .gitattributes custom highlighting')
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage
end
@@ -36,7 +36,7 @@ RSpec.describe 'Projects tree', :js do
expect(page).to have_selector('.tree-item')
expect(page).to have_content('add spaces in whitespace file')
expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
it 'renders tree table with non-ASCII filenames without errors' do
@@ -46,7 +46,7 @@ RSpec.describe 'Projects tree', :js do
expect(page).to have_selector('.tree-item')
expect(page).to have_content('Files, encoding and much more')
expect(page).to have_content('テスト.txt')
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
context "with a tree that contains pathspec characters" do
@@ -139,7 +139,7 @@ RSpec.describe 'Projects tree', :js do
wait_for_requests
expect(page).to have_selector('.tree-item')
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
context 'for signed commit' do
diff --git a/spec/features/projects/user_changes_project_visibility_spec.rb b/spec/features/projects/user_changes_project_visibility_spec.rb
index 68fed9b8a74..d2a7596aec0 100644
--- a/spec/features/projects/user_changes_project_visibility_spec.rb
+++ b/spec/features/projects/user_changes_project_visibility_spec.rb
@@ -43,9 +43,9 @@ RSpec.describe 'User changes public project visibility', :js do
context 'when the project has forks' do
before do
- fork_project(project, project.owner)
+ fork_project(project, project.first_owner)
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit edit_project_path(project)
end
@@ -84,7 +84,7 @@ RSpec.describe 'User changes public project visibility', :js do
let(:project) { create(:project, :empty_repo, :public) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit edit_project_path(project)
end
@@ -98,9 +98,9 @@ RSpec.describe 'User changes public project visibility', :js do
before do
stub_feature_flags(unlink_fork_network_upon_visibility_decrease: false)
- fork_project(project, project.owner)
+ fork_project(project, project.first_owner)
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit edit_project_path(project)
end
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index 7bb15451538..cd6f09ce275 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'User uses shortcuts', :js do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index 94085b075aa..5dd30f59e3d 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe 'View on environment', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350457
project.add_maintainer(user)
end
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 63ee89bd11f..fbb5c24f6e1 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
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Wiki > User views wiki in project page' do
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
context 'when repository is disabled for project' do
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 26deca9c8f1..1049f8bc18f 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe 'Project' do
let(:path) { project_path(project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
end
it 'parses Markdown' do
@@ -123,7 +123,7 @@ RSpec.describe 'Project' do
let(:path) { project_path(project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit path
end
@@ -154,7 +154,7 @@ RSpec.describe 'Project' do
let(:path) { project_path(project) }
before do
- sign_in(project.owner)
+ sign_in(project.first_owner)
visit path
end
@@ -201,7 +201,7 @@ RSpec.describe 'Project' do
it 'does not show the name of the deleted project when the source was deleted', :sidekiq_might_not_need_inline do
forked_project
- Projects::DestroyService.new(base_project, base_project.owner).execute
+ Projects::DestroyService.new(base_project, base_project.first_owner).execute
visit project_path(forked_project)
@@ -236,7 +236,7 @@ RSpec.describe 'Project' do
it 'does not show an error' do
wait_for_requests
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
end
@@ -316,7 +316,7 @@ RSpec.describe 'Project' do
wait_for_requests
expect(page).to have_selector('.tree-item')
- expect(page).not_to have_selector('.flash-alert')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
context 'for signed commit' do
diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb
index 376f990f054..c89dd4d1f90 100644
--- a/spec/features/protected_tags_spec.rb
+++ b/spec/features/protected_tags_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Protected Tags', :js do
include ProtectedTagHelpers
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
sign_in(user)
diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb
index 12237863188..ab080f0a460 100644
--- a/spec/features/security/project/snippet/internal_access_spec.rb
+++ b/spec/features/security/project/snippet/internal_access_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe "Internal Project Snippets Access" do
include AccessMatchers
let_it_be(:project) { create(:project, :internal) }
- let_it_be(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.owner) }
- let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
+ let_it_be(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.first_owner) }
+ let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.first_owner) }
describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) }
diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb
index 0c06841399d..1e0afc09b74 100644
--- a/spec/features/security/project/snippet/private_access_spec.rb
+++ b/spec/features/security/project/snippet/private_access_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe "Private Project Snippets Access" do
include AccessMatchers
let_it_be(:project) { create(:project, :private) }
- let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
+ let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.first_owner) }
describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) }
diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb
index 2ae08205602..f734f7ba9e2 100644
--- a/spec/features/security/project/snippet/public_access_spec.rb
+++ b/spec/features/security/project/snippet/public_access_spec.rb
@@ -6,9 +6,9 @@ RSpec.describe "Public Project Snippets Access" do
include AccessMatchers
let_it_be(:project) { create(:project, :public) }
- let_it_be(:public_snippet) { create(:project_snippet, :public, project: project, author: project.owner) }
- let_it_be(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.owner) }
- let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
+ let_it_be(:public_snippet) { create(:project_snippet, :public, project: project, author: project.first_owner) }
+ let_it_be(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.first_owner) }
+ let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.first_owner) }
describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) }
diff --git a/spec/features/snippets_spec.rb b/spec/features/snippets_spec.rb
index 8cdb4bc3344..35eb5c2e193 100644
--- a/spec/features/snippets_spec.rb
+++ b/spec/features/snippets_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Snippets' do
context 'when the project has snippets' do
let(:project) { create(:project, :public) }
- let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) }
+ let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.first_owner, project: project) }
before do
allow(Snippet).to receive(:default_per_page).and_return(1)
diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb
index 2ddd86dd807..1f1824c897e 100644
--- a/spec/features/triggers_spec.rb
+++ b/spec/features/triggers_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Triggers', :js do
click_button 'Add trigger'
aggregate_failures 'display creation notice and trigger is created' do
- expect(page.find('.flash-notice')).to have_content 'Trigger was created successfully.'
+ expect(page.find('[data-testid="alert-info"]')).to have_content 'Trigger was created successfully.'
expect(page.find('.triggers-list')).to have_content 'trigger desc'
expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
end
@@ -63,7 +63,7 @@ RSpec.describe 'Triggers', :js do
click_button 'Save trigger'
aggregate_failures 'display update notice and trigger is updated' do
- expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.'
+ expect(page.find('[data-testid="alert-info"]')).to have_content 'Trigger was successfully updated.'
expect(page.find('.triggers-list')).to have_content new_trigger_title
expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
end
@@ -89,7 +89,7 @@ RSpec.describe 'Triggers', :js do
end
aggregate_failures 'trigger is removed' do
- expect(page.find('.flash-notice')).to have_content 'Trigger removed'
+ expect(page.find('[data-testid="alert-info"]')).to have_content 'Trigger removed'
expect(page).to have_css('[data-testid="no_triggers_content"]')
end
end
diff --git a/spec/features/user_sorts_things_spec.rb b/spec/features/user_sorts_things_spec.rb
index 8e6f6a96bd2..fa37d692225 100644
--- a/spec/features/user_sorts_things_spec.rb
+++ b/spec/features/user_sorts_things_spec.rb
@@ -33,18 +33,6 @@ RSpec.describe "User sorts things" do
expect(find(".issues-filters")).to have_content(sort_option)
end
- it "issues -> merge requests" do
- sort_option = 'Updated date'
-
- visit(project_issues_path(project))
-
- sort_by(sort_option)
-
- visit(project_merge_requests_path(project))
-
- expect(find(".issues-filters")).to have_content(sort_option)
- end
-
it "merge requests -> dashboard merge requests" do
sort_option = 'Updated date'
diff --git a/spec/features/users/bizible_csp_spec.rb b/spec/features/users/bizible_csp_spec.rb
new file mode 100644
index 00000000000..af0b42050b3
--- /dev/null
+++ b/spec/features/users/bizible_csp_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Bizible content security policy' do
+ before do
+ stub_config(extra: { one_trust_id: SecureRandom.uuid })
+ end
+
+ it 'has proper Content Security Policy headers' do
+ visit root_path
+
+ expect(response_headers['Content-Security-Policy']).to include('https://cdn.bizible.com/scripts/bizible.js')
+ end
+end
diff --git a/spec/features/users/logout_spec.rb b/spec/features/users/logout_spec.rb
index ffb8785b277..3129eb5e6f3 100644
--- a/spec/features/users/logout_spec.rb
+++ b/spec/features/users/logout_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Logout/Sign out', :js do
it 'sign out does not show signed out flash notice' do
gitlab_sign_out
- expect(page).not_to have_selector('.flash-notice')
+ expect(page).not_to have_selector('[data-testid="alert-info"]')
end
context 'on a read-only instance' do
diff --git a/spec/finders/autocomplete/users_finder_spec.rb b/spec/finders/autocomplete/users_finder_spec.rb
index 28bd7e12916..9b3421d1b4f 100644
--- a/spec/finders/autocomplete/users_finder_spec.rb
+++ b/spec/finders/autocomplete/users_finder_spec.rb
@@ -3,16 +3,20 @@
require 'spec_helper'
RSpec.describe Autocomplete::UsersFinder do
+ # TODO update when multiple owners are possible in projects
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/21432
+
describe '#execute' do
- let!(:user1) { create(:user, username: 'johndoe') }
- let!(:user2) { create(:user, :blocked, username: 'notsorandom') }
- let!(:external_user) { create(:user, :external) }
- let!(:omniauth_user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:user1) { create(:user, name: 'zzzzzname', username: 'johndoe') }
+ let_it_be(:user2) { create(:user, :blocked, username: 'notsorandom') }
+ let_it_be(:external_user) { create(:user, :external) }
+ let_it_be(:omniauth_user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+
let(:current_user) { create(:user) }
let(:params) { {} }
- let(:project) { nil }
- let(:group) { nil }
+ let_it_be(:project) { nil }
+ let_it_be(:group) { nil }
subject { described_class.new(params: params, current_user: current_user, project: project, group: group).execute.to_a }
@@ -23,33 +27,53 @@ RSpec.describe Autocomplete::UsersFinder do
end
context 'when project passed' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
- it { is_expected.to match_array([project.owner]) }
+ it { is_expected.to match_array([project.first_owner]) }
context 'when author_id passed' do
context 'and author is active' do
let(:params) { { author_id: user1.id } }
- it { is_expected.to match_array([project.owner, user1]) }
+ it { is_expected.to match_array([project.first_owner, user1]) }
end
context 'and author is blocked' do
let(:params) { { author_id: user2.id } }
- it { is_expected.to match_array([project.owner]) }
+ it { is_expected.to match_array([project.first_owner]) }
+ end
+ end
+
+ context 'searching with less than 3 characters' do
+ let(:params) { { search: 'zz' } }
+
+ before do
+ project.add_guest(user1)
+ end
+
+ it 'allows partial matches' do
+ expect(subject).to contain_exactly(user1)
end
end
end
context 'when group passed and project not passed' do
- let(:group) { create(:group, :public) }
+ let_it_be(:group) { create(:group, :public) }
- before do
+ before_all do
group.add_users([user1], GroupMember::DEVELOPER)
end
it { is_expected.to match_array([user1]) }
+
+ context 'searching with less than 3 characters' do
+ let(:params) { { search: 'zz' } }
+
+ it 'allows partial matches' do
+ expect(subject).to contain_exactly(user1)
+ end
+ end
end
context 'when passed a subgroup' do
@@ -73,6 +97,14 @@ RSpec.describe Autocomplete::UsersFinder do
let(:params) { { search: 'johndoe' } }
it { is_expected.to match_array([user1]) }
+
+ context 'searching with less than 3 characters' do
+ let(:params) { { search: 'zz' } }
+
+ it 'does not allow partial matches' do
+ expect(subject).to be_empty
+ end
+ end
end
context 'when filtered by skip_users' do
diff --git a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
index cf15a00323b..5352cfe5238 100644
--- a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
+++ b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
describe '#execute' do
let_it_be(:project) { create(:project, :private) }
let(:user_without_permission) { create(:user) }
- let_it_be(:user_with_permission) { project.owner }
+ let_it_be(:user_with_permission) { project.first_owner }
let_it_be(:ref_path) { 'refs/heads/master' }
let(:limit) { nil }
let_it_be(:default_branch) { false }
diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb
index ab056dd26e8..959716b1fd3 100644
--- a/spec/finders/ci/jobs_finder_spec.rb
+++ b/spec/finders/ci/jobs_finder_spec.rb
@@ -126,4 +126,41 @@ RSpec.describe Ci::JobsFinder, '#execute' do
end
end
end
+
+ context 'a runner is present' do
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:job_4) { create(:ci_build, :success, runner: runner) }
+
+ subject { described_class.new(current_user: user, runner: runner, params: params).execute }
+
+ context 'user has access to the runner', :enable_admin_mode do
+ let(:user) { admin }
+
+ it 'returns jobs for the specified project' do
+ expect(subject).to match_array([job_4])
+ end
+ end
+
+ context 'user has no access to project builds' do
+ let_it_be(:guest) { create(:user) }
+
+ let(:user) { guest }
+
+ before do
+ project.add_guest(guest)
+ end
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'without user' do
+ let(:user) { nil }
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index dac244e4300..e7ec4f01995 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -91,8 +91,8 @@ RSpec.describe Ci::RunnersFinder do
end
context 'sorting' 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(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago, token_expires_at: '2022-02-15 07:00' }
+ let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago, token_expires_at: '2022-02-15 06:00' }
let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago }
subject do
@@ -142,6 +142,22 @@ RSpec.describe Ci::RunnersFinder do
is_expected.to eq [runner1, runner3, runner2]
end
end
+
+ context 'with sort param equal to token_expires_at_asc' do
+ let(:params) { { sort: 'token_expires_at_asc' } }
+
+ it 'sorts by contacted_at ascending' do
+ is_expected.to eq [runner2, runner1, runner3]
+ end
+ end
+
+ context 'with sort param equal to token_expires_at_desc' do
+ let(:params) { { sort: 'token_expires_at_desc' } }
+
+ it 'sorts by contacted_at descending' do
+ is_expected.to eq [runner3, runner1, runner2]
+ end
+ end
end
context 'by non admin user' do
@@ -206,7 +222,7 @@ RSpec.describe Ci::RunnersFinder do
sub_group_4.runners << runner_sub_group_4
end
- shared_examples '#execute' do
+ describe '#execute' do
subject { described_class.new(current_user: user, params: params).execute }
shared_examples 'membership equal to :descendants' do
@@ -349,16 +365,6 @@ RSpec.describe Ci::RunnersFinder do
end
end
- it_behaves_like '#execute'
-
- context 'when the FF ci_find_runners_by_ci_mirrors is disabled' do
- before do
- stub_feature_flags(ci_find_runners_by_ci_mirrors: false)
- end
-
- it_behaves_like '#execute'
- end
-
describe '#sort_key' do
subject { described_class.new(current_user: user, params: params.merge(group: group)).sort_key }
diff --git a/spec/finders/clusters/agents_finder_spec.rb b/spec/finders/clusters/agents_finder_spec.rb
index 0996d76b723..4ec798daa99 100644
--- a/spec/finders/clusters/agents_finder_spec.rb
+++ b/spec/finders/clusters/agents_finder_spec.rb
@@ -15,7 +15,11 @@ RSpec.describe Clusters::AgentsFinder do
it { is_expected.to contain_exactly(matching_agent) }
context 'user does not have permission' do
- let(:user) { create(:user, developer_projects: [project]) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_reporter(user)
+ end
it { is_expected.to be_empty }
end
diff --git a/spec/finders/crm/contacts_finder_spec.rb b/spec/finders/crm/contacts_finder_spec.rb
new file mode 100644
index 00000000000..151af1ad825
--- /dev/null
+++ b/spec/finders/crm/contacts_finder_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Crm::ContactsFinder do
+ let_it_be(:user) { create(:user) }
+
+ describe '#execute' do
+ subject { described_class.new(user, group: group).execute }
+
+ context 'when customer relations feature is enabled for the group' do
+ let_it_be(:root_group) { create(:group, :crm_enabled) }
+ let_it_be(:group) { create(:group, parent: root_group) }
+
+ let_it_be(:contact_1) { create(:contact, group: root_group) }
+ let_it_be(:contact_2) { create(:contact, group: root_group) }
+
+ context 'when user does not have permissions to see contacts in the group' do
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'when user is member of the root group' do
+ before do
+ root_group.add_developer(user)
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'when feature flag is enabled' do
+ it 'returns all group contacts' do
+ expect(subject).to match_array([contact_1, contact_2])
+ end
+ end
+ end
+
+ context 'when user is member of the sub group' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
+ context 'when customer relations feature is disabled for the group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:contact) { create(:contact, group: group) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/finders/deployments_finder_spec.rb b/spec/finders/deployments_finder_spec.rb
index 6d9d0c33de3..51c293bcfd1 100644
--- a/spec/finders/deployments_finder_spec.rb
+++ b/spec/finders/deployments_finder_spec.rb
@@ -222,11 +222,7 @@ RSpec.describe DeploymentsFinder do
end
describe 'enforce sorting to `updated_at` sorting' do
- let(:params) { { **base_params, updated_before: 1.day.ago, order_by: 'id', sort: 'asc' } }
-
- before do
- allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
- end
+ let(:params) { { **base_params, updated_before: 1.day.ago, order_by: 'id', sort: 'asc', raise_for_inefficient_updated_at_query: false } }
it 'sorts by only one column' do
expect(subject.order_values.size).to eq(2)
diff --git a/spec/finders/environments/environments_by_deployments_finder_spec.rb b/spec/finders/environments/environments_by_deployments_finder_spec.rb
index 8349092c79e..c8e6b038634 100644
--- a/spec/finders/environments/environments_by_deployments_finder_spec.rb
+++ b/spec/finders/environments/environments_by_deployments_finder_spec.rb
@@ -64,6 +64,22 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
end
end
+ context 'sha deployment' do
+ before do
+ create(:deployment, :success, environment: environment, sha: project.commit.id)
+ end
+
+ it 'returns environment' do
+ expect(described_class.new(project, user, sha: project.commit.id).execute)
+ .to contain_exactly(environment)
+ end
+
+ it 'does not return environment when sha is different' do
+ expect(described_class.new(project, user, sha: '1234').execute)
+ .to be_empty
+ end
+ end
+
context 'commit deployment' do
before do
create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 59eeb078e9e..5c5db874e85 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -68,6 +68,12 @@ RSpec.describe GroupDescendantsFinder do
expect(finder.execute).to be_empty
end
+ it 'does not include projects aimed for deletion' do
+ _project_aimed_for_deletion = create(:project, :archived, marked_for_deletion_at: 2.days.ago, pending_delete: false)
+
+ expect(finder.execute).to be_empty
+ end
+
context 'with a filter' do
let(:params) { { filter: 'test' } }
@@ -165,8 +171,8 @@ RSpec.describe GroupDescendantsFinder do
end
context 'with nested groups' do
- let!(:project) { create(:project, namespace: group) }
- let!(:subgroup) { create(:group, :private, parent: group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+ let_it_be_with_reload(:subgroup) { create(:group, :private, parent: group) }
describe '#execute' do
it 'contains projects and subgroups' do
@@ -208,57 +214,69 @@ RSpec.describe GroupDescendantsFinder do
context 'with a filter' do
let(:params) { { filter: 'test' } }
- it 'contains only matching projects and subgroups' do
- matching_project = create(:project, namespace: group, name: 'Testproject')
- matching_subgroup = create(:group, name: 'testgroup', parent: group)
+ shared_examples 'filter examples' do
+ it 'contains only matching projects and subgroups' do
+ matching_project = create(:project, namespace: group, name: 'Testproject')
+ matching_subgroup = create(:group, name: 'testgroup', parent: group)
- expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
+ end
- it 'does not include subgroups the user does not have access to' do
- _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
- other_subgroup = create(:group, :private, parent: group, name: 'test2')
- public_subgroup = create(:group, :public, parent: group, name: 'test3')
- other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
- other_user = create(:user)
- other_subgroup.add_developer(other_user)
+ it 'does not include subgroups the user does not have access to' do
+ _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
+ other_subgroup = create(:group, :private, parent: group, name: 'test2')
+ public_subgroup = create(:group, :public, parent: group, name: 'test3')
+ other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
+ other_user = create(:user)
+ other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user,
- parent_group: group,
- params: params)
+ finder = described_class.new(current_user: other_user,
+ parent_group: group,
+ params: params)
- expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
- end
+ expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
+ end
- context 'with matching children' do
- it 'includes a group that has a subgroup matching the query and its parent' do
- matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
+ context 'with matching children' do
+ it 'includes a group that has a subgroup matching the query and its parent' do
+ matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
- expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
+ end
- it 'includes the parent of a matching project' do
- matching_project = create(:project, namespace: subgroup, name: 'Testproject')
+ it 'includes the parent of a matching project' do
+ matching_project = create(:project, namespace: subgroup, name: 'Testproject')
- expect(finder.execute).to contain_exactly(subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_project)
+ end
+
+ context 'with a small page size' do
+ let(:params) { { filter: 'test', per_page: 1 } }
- context 'with a small page size' do
- let(:params) { { filter: 'test', per_page: 1 } }
+ it 'contains all the ancestors of a matching subgroup regardless the page size' do
+ subgroup = create(:group, :private, parent: group)
+ matching = create(:group, :private, name: 'testgroup', parent: subgroup)
- it 'contains all the ancestors of a matching subgroup regardless the page size' do
- subgroup = create(:group, :private, parent: group)
- matching = create(:group, :private, name: 'testgroup', parent: subgroup)
+ expect(finder.execute).to contain_exactly(subgroup, matching)
+ end
+ end
+
+ it 'does not include the parent itself' do
+ group.update!(name: 'test')
- expect(finder.execute).to contain_exactly(subgroup, matching)
+ expect(finder.execute).not_to include(group)
end
end
+ end
- it 'does not include the parent itself' do
- group.update!(name: 'test')
+ it_behaves_like 'filter examples'
- expect(finder.execute).not_to include(group)
+ context 'when feature flag :linear_group_descendants_finder_upto is disabled' do
+ before do
+ stub_feature_flags(linear_group_descendants_finder_upto: false)
end
+
+ it_behaves_like 'filter examples'
end
end
end
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb
index 3fc4393df5d..4189be94cc1 100644
--- a/spec/finders/group_projects_finder_spec.rb
+++ b/spec/finders/group_projects_finder_spec.rb
@@ -9,13 +9,29 @@ RSpec.describe GroupProjectsFinder do
describe 'with a group member current user' do
before do
- group.add_maintainer(current_user)
+ root_group.add_maintainer(current_user)
end
context "only shared" do
let(:options) { { only_shared: true } }
it { is_expected.to match_array([shared_project_3, shared_project_2, shared_project_1]) }
+
+ context 'with ancestor groups projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ end
+
+ it { is_expected.to match_array([shared_project_3, shared_project_2, shared_project_1]) }
+ end
+
+ context 'with subgroups projects' do
+ before do
+ options[:include_subgroups] = true
+ end
+
+ it { is_expected.to match_array([shared_project_3, shared_project_2, shared_project_1]) }
+ end
end
context "only owned" do
@@ -29,9 +45,46 @@ RSpec.describe GroupProjectsFinder do
it { is_expected.to match_array([private_project, public_project, subgroup_project, subgroup_private_project]) }
end
- context 'without subgroups projects' do
+ context 'with ancestor group projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ end
+
+ it { is_expected.to match_array([private_project, public_project, root_group_public_project, root_group_private_project, root_group_private_project_2]) }
+ end
+
+ context 'with ancestor groups and subgroups projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ options[:include_subgroups] = true
+ end
+
+ it { is_expected.to match_array([private_project, public_project, root_group_public_project, root_group_private_project, root_group_private_project_2, subgroup_private_project, subgroup_project]) }
+ end
+
+ context 'without subgroups and ancestor group projects' do
it { is_expected.to match_array([private_project, public_project]) }
end
+
+ context 'when user is member only of a subgroup' do
+ let(:subgroup_member) { create(:user) }
+
+ context 'with ancestor groups and subgroups projects' do
+ before do
+ group.add_maintainer(subgroup_member)
+ options[:include_ancestor_groups] = true
+ options[:include_subgroups] = true
+ end
+
+ it 'does not return parent group projects' do
+ finder = described_class.new(group: group, current_user: subgroup_member, params: params, options: options)
+
+ projects = finder.execute
+
+ expect(projects).to match_array([private_project, public_project, subgroup_project, subgroup_private_project, root_group_public_project])
+ end
+ end
+ end
end
context "all" do
@@ -90,6 +143,7 @@ RSpec.describe GroupProjectsFinder do
before do
private_project.add_maintainer(current_user)
subgroup_private_project.add_maintainer(current_user)
+ root_group_private_project.add_maintainer(current_user)
end
context 'with subgroups projects' do
@@ -100,6 +154,23 @@ RSpec.describe GroupProjectsFinder do
it { is_expected.to match_array([private_project, public_project, subgroup_project, subgroup_private_project]) }
end
+ context 'with ancestor groups projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ end
+
+ it { is_expected.to match_array([private_project, public_project, root_group_public_project, root_group_private_project]) }
+ end
+
+ context 'with ancestor groups and subgroups projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ options[:include_subgroups] = true
+ end
+
+ it { is_expected.to match_array([private_project, public_project, root_group_private_project, root_group_public_project, subgroup_private_project, subgroup_project]) }
+ end
+
context 'without subgroups projects' do
it { is_expected.to match_array([private_project, public_project]) }
end
@@ -118,6 +189,23 @@ RSpec.describe GroupProjectsFinder do
it { is_expected.to match_array([public_project, subgroup_project]) }
end
+ context 'with ancestor groups projects' do
+ before do
+ options[:include_ancestor_groups] = true
+ end
+
+ it { is_expected.to match_array([public_project, root_group_public_project]) }
+ end
+
+ context 'with ancestor groups and subgroups projects' do
+ before do
+ options[:include_subgroups] = true
+ options[:include_ancestor_groups] = true
+ end
+
+ it { is_expected.to match_array([public_project, root_group_public_project, subgroup_project]) }
+ end
+
context 'without subgroups projects' do
it { is_expected.to eq([public_project]) }
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 31563a6326d..c22e56c3b9e 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -1018,6 +1018,8 @@ RSpec.describe IssuesFinder do
end
context 'filtering by due date' do
+ let_it_be(:issue_due_today) { create(:issue, project: project1, due_date: Date.current) }
+ let_it_be(:issue_due_tomorrow) { create(:issue, project: project1, due_date: 1.day.from_now) }
let_it_be(:issue_overdue) { create(:issue, project: project1, due_date: 2.days.ago) }
let_it_be(:issue_due_soon) { create(:issue, project: project1, due_date: 2.days.from_now) }
@@ -1032,6 +1034,30 @@ RSpec.describe IssuesFinder do
end
end
+ context 'with param set to any due date' do
+ let(:params) { base_params.merge(due_date: Issue::AnyDueDate.name) }
+
+ it 'returns issues with any due date' do
+ expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
+ end
+ end
+
+ context 'with param set to due today' do
+ let(:params) { base_params.merge(due_date: Issue::DueToday.name) }
+
+ it 'returns issues due today' do
+ expect(issues).to contain_exactly(issue_due_today)
+ end
+ end
+
+ context 'with param set to due tomorrow' do
+ let(:params) { base_params.merge(due_date: Issue::DueTomorrow.name) }
+
+ it 'returns issues due today' do
+ expect(issues).to contain_exactly(issue_due_tomorrow)
+ end
+ end
+
context 'with param set to overdue' do
let(:params) { base_params.merge(due_date: Issue::Overdue.name) }
@@ -1043,8 +1069,8 @@ RSpec.describe IssuesFinder do
context 'with param set to next month and previous two weeks' do
let(:params) { base_params.merge(due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) }
- it 'returns issues from the previous two weeks and next month' do
- expect(issues).to contain_exactly(issue_overdue, issue_due_soon)
+ it 'returns issues due in the previous two weeks and next month' do
+ expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
end
end
diff --git a/spec/finders/merge_request_target_project_finder_spec.rb b/spec/finders/merge_request_target_project_finder_spec.rb
index 08fbfd7229a..bf735152d99 100644
--- a/spec/finders/merge_request_target_project_finder_spec.rb
+++ b/spec/finders/merge_request_target_project_finder_spec.rb
@@ -65,8 +65,8 @@ RSpec.describe MergeRequestTargetProjectFinder do
context 'private projects' do
let(:base_project) { create(:project, :private, path: 'base') }
- let(:forked_project) { fork_project(base_project, base_project.owner) }
- let(:other_fork) { fork_project(base_project, base_project.owner) }
+ let(:forked_project) { fork_project(base_project, base_project.first_owner) }
+ let(:other_fork) { fork_project(base_project, base_project.first_owner) }
context 'when the user is a member of all projects' do
before do
diff --git a/spec/finders/merge_requests_finder/params_spec.rb b/spec/finders/merge_requests_finder/params_spec.rb
new file mode 100644
index 00000000000..8c285972f48
--- /dev/null
+++ b/spec/finders/merge_requests_finder/params_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequestsFinder::Params do
+ let(:user) { create(:user) }
+
+ subject { described_class.new(params, user, MergeRequest) }
+
+ describe 'attention' do
+ context 'attention param exists' do
+ let(:params) { { attention: user.username } }
+
+ it { expect(subject.attention).to eq(user) }
+ end
+
+ context 'attention param does not exist' do
+ let(:params) { { attention: nil } }
+
+ it { expect(subject.attention).to eq(nil) }
+ end
+ end
+end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 0b6c438fd02..1f63f69a411 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -408,6 +408,22 @@ RSpec.describe MergeRequestsFinder do
end
end
+ context 'attention' do
+ subject { described_class.new(user, params).execute }
+
+ before do
+ reviewer = merge_request1.find_reviewer(user2)
+ reviewer.update!(state: :reviewed)
+ end
+
+ context 'by username' do
+ let(:params) { { attention: user2.username } }
+ let(:expected_mr) { [merge_request2, merge_request3] }
+
+ it { is_expected.to contain_exactly(*expected_mr) }
+ end
+ end
+
context 'reviewer filtering' do
subject { described_class.new(user, params).execute }
diff --git a/spec/finders/packages/conan/package_file_finder_spec.rb b/spec/finders/packages/conan/package_file_finder_spec.rb
index 3da7da456c2..62906a7b0a9 100644
--- a/spec/finders/packages/conan/package_file_finder_spec.rb
+++ b/spec/finders/packages/conan/package_file_finder_spec.rb
@@ -49,18 +49,6 @@ RSpec.describe ::Packages::Conan::PackageFileFinder do
expect(subject).to eq(package_file)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns the correct package file' do
- expect(package.package_files.last).to eq(recent_package_file_pending_destruction)
-
- expect(subject).to eq(recent_package_file_pending_destruction)
- end
- end
end
describe '#execute' do
diff --git a/spec/finders/packages/package_file_finder_spec.rb b/spec/finders/packages/package_file_finder_spec.rb
index 8b21c9cd3ec..711e1396126 100644
--- a/spec/finders/packages/package_file_finder_spec.rb
+++ b/spec/finders/packages/package_file_finder_spec.rb
@@ -29,16 +29,6 @@ RSpec.describe Packages::PackageFileFinder do
expect(subject).to eq(package_file)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- expect(subject).to eq(recent_package_file_pending_destruction)
- end
- end
end
describe '#execute' do
diff --git a/spec/finders/releases_finder_spec.rb b/spec/finders/releases_finder_spec.rb
index 94b6fe53daa..5ddb5c33fad 100644
--- a/spec/finders/releases_finder_spec.rb
+++ b/spec/finders/releases_finder_spec.rb
@@ -23,6 +23,16 @@ RSpec.describe ReleasesFinder do
end
end
+ shared_examples_for 'when the user is not part of the group' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :read_release, group).and_return(false)
+ end
+
+ it 'returns no releases' do
+ is_expected.to be_empty
+ end
+ end
+
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27716
shared_examples_for 'when tag is nil' do
before do
@@ -66,9 +76,9 @@ RSpec.describe ReleasesFinder do
it_behaves_like 'when the user is not part of the project'
- context 'when the user is a project developer' do
+ context 'when the user is a project guest' do
before do
- project.add_developer(user)
+ project.add_guest(user)
end
it 'sorts by release date' do
@@ -118,25 +128,24 @@ RSpec.describe ReleasesFinder do
subject { described_class.new(group, user, params).execute(**args) }
- it_behaves_like 'when the user is not part of the project'
+ it_behaves_like 'when the user is not part of the group'
- context 'when the user is a project developer on one sibling project' do
+ context 'when the user is a project guest on one sibling project' do
before do
- project.add_developer(user)
+ project.add_guest(user)
v1_0_0.update_attribute(:released_at, 3.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago)
end
- it 'sorts by release date' do
- expect(subject.size).to eq(2)
- expect(subject).to eq([v1_1_0, v1_0_0])
+ it 'does not return any releases' do
+ expect(subject.size).to eq(0)
+ expect(subject).to eq([])
end
end
- context 'when the user is a project developer on all projects' do
+ context 'when the user is a guest on the group' do
before do
- project.add_developer(user)
- project2.add_developer(user)
+ group.add_guest(user)
v1_0_0.update_attribute(:released_at, 3.days.ago)
v6.update_attribute(:released_at, 2.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago)
@@ -161,22 +170,21 @@ RSpec.describe ReleasesFinder do
let(:project2) { create(:project, :repository, namespace: subgroup) }
let!(:v6) { create(:release, project: project2, tag: 'v6') }
- it_behaves_like 'when the user is not part of the project'
+ it_behaves_like 'when the user is not part of the group'
- context 'when the user a project developer in the subgroup project' do
+ context 'when the user a project guest in the subgroup project' do
before do
- project2.add_developer(user)
+ project2.add_guest(user)
end
- it 'returns only the subgroup releases' do
- expect(subject).to match_array([v6])
+ it 'does not return any releases' do
+ expect(subject).to match_array([])
end
end
- context 'when the user a project developer in both projects' do
+ context 'when the user is a guest on the group' do
before do
- project.add_developer(user)
- project2.add_developer(user)
+ group.add_guest(user)
v6.update_attribute(:released_at, 2.days.ago)
end
@@ -201,34 +209,32 @@ RSpec.describe ReleasesFinder do
p3.update_attribute(:released_at, 3.days.ago)
end
- it_behaves_like 'when the user is not part of the project'
+ it_behaves_like 'when the user is not part of the group'
- context 'when the user a project developer in the subgroup and subsubgroup project' do
+ context 'when the user a project guest in the subgroup and subsubgroup project' do
before do
- project2.add_developer(user)
- project3.add_developer(user)
+ project2.add_guest(user)
+ project3.add_guest(user)
end
- it 'returns only the subgroup and subsubgroup releases' do
- expect(subject).to match_array([v6, p3])
+ it 'does not return any releases' do
+ expect(subject).to match_array([])
end
end
- context 'when the user a project developer in the subsubgroup project' do
+ context 'when the user a project guest in the subsubgroup project' do
before do
- project3.add_developer(user)
+ project3.add_guest(user)
end
- it 'returns only the subsubgroup releases' do
- expect(subject).to match_array([p3])
+ it 'does not return any releases' do
+ expect(subject).to match_array([])
end
end
- context 'when the user a project developer in all projects' do
+ context 'when the user a guest on the group' do
before do
- project.add_developer(user)
- project2.add_developer(user)
- project3.add_developer(user)
+ group.add_guest(user)
end
it 'returns all releases' do
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
index acc86547271..70d79ced81d 100644
--- a/spec/finders/tags_finder_spec.rb
+++ b/spec/finders/tags_finder_spec.rb
@@ -32,6 +32,14 @@ RSpec.describe TagsFinder do
expect(load_tags(params).first.name).to eq('v1.0.0')
end
+
+ context 'when sort is not a string' do
+ it 'ignores sort parameter' do
+ params = { sort: { 'invalid' => 'string' } }
+
+ expect(load_tags(params).first.name).to eq('v1.0.0')
+ end
+ end
end
context 'filter only' do
@@ -70,6 +78,13 @@ RSpec.describe TagsFinder do
result = load_tags({ search: 'nope$' })
expect(result.count).to eq(0)
end
+
+ context 'when search is not a string' do
+ it 'returns no matches' do
+ result = load_tags({ search: { 'a' => 'b' } })
+ expect(result.count).to eq(0)
+ end
+ end
end
context 'filter and sort' do
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 97eecf8a89d..8e2426e697b 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -153,7 +153,12 @@ RSpec.describe TemplateFinder do
let(:params) { {} }
- subject(:result) { described_class.new(type, project, params).template_names.values.flatten.map { |el| OpenStruct.new(el) } }
+ let(:template_name_struct) { Struct.new(:name, :id, :key, :project_id, keyword_init: true) }
+
+ subject(:result) do
+ described_class.new(type, project, params).template_names.values.flatten
+ .map { |el| template_name_struct.new(el) }
+ end
where(:type, :vendored_name) do
:dockerfiles | 'Binary'
diff --git a/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
index 296e18fca47..85acebb99ba 100644
--- a/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
+++ b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
@@ -6,6 +6,9 @@
"type": "object",
"required": ["value", "title"],
"properties": {
+ "identifier": {
+ "type": "string"
+ },
"value": {
"type": "string"
},
diff --git a/spec/fixtures/api/schemas/entities/member_user.json b/spec/fixtures/api/schemas/entities/member_user.json
index 41a1e510de5..d42c686bb65 100644
--- a/spec/fixtures/api/schemas/entities/member_user.json
+++ b/spec/fixtures/api/schemas/entities/member_user.json
@@ -1,6 +1,6 @@
{
"type": "object",
- "required": ["id", "name", "username", "avatar_url", "web_url", "blocked", "two_factor_enabled"],
+ "required": ["id", "name", "username", "avatar_url", "web_url", "blocked", "two_factor_enabled", "show_status"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
@@ -17,6 +17,7 @@
"emoji": { "type": "string" }
},
"additionalProperties": false
- }
+ },
+ "show_status": { "type": "boolean" }
}
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/deployment.json b/spec/fixtures/api/schemas/public_api/v4/deployment.json
index 2371509edd6..5dab1456e7d 100644
--- a/spec/fixtures/api/schemas/public_api/v4/deployment.json
+++ b/spec/fixtures/api/schemas/public_api/v4/deployment.json
@@ -8,7 +8,8 @@
"created_at",
"updated_at",
"user",
- "deployable"
+ "deployable",
+ "status"
],
"properties": {
"id": { "type": "integer" },
@@ -30,6 +31,5 @@
]
},
"status": { "type": "string" }
- },
- "additionalProperties": false
+ }
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_request.json b/spec/fixtures/api/schemas/public_api/v4/merge_request.json
index a55c4b8974b..1ef2f9f9534 100644
--- a/spec/fixtures/api/schemas/public_api/v4/merge_request.json
+++ b/spec/fixtures/api/schemas/public_api/v4/merge_request.json
@@ -1,152 +1,91 @@
{
"type": "object",
"properties" : {
- "properties" : {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": "integer" },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "merged_by": {
- "type": ["object", "null"],
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "merge_user": {
- "type": ["object", "null"],
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "merged_at": { "type": ["string", "null"] },
- "closed_by": {
- "type": ["object", "null"],
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "closed_at": { "type": ["string", "null"], "format": "date-time" },
- "created_at": { "type": "string", "format": "date-time" },
- "updated_at": { "type": "string", "format": "date-time" },
- "target_branch": { "type": "string" },
- "source_branch": { "type": "string" },
- "upvotes": { "type": "integer" },
- "downvotes": { "type": "integer" },
- "author": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "assignee": {
- "type": ["object", "null"],
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "assignees": {
- "items": {
- "$ref": "./merge_request.json"
- }
- },
- "source_project_id": { "type": "integer" },
- "target_project_id": { "type": "integer" },
- "labels": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "work_in_progress": { "type": "boolean" },
- "milestone": {
- "type": ["object", "null"],
- "properties": {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": ["integer", "null"] },
- "group_id": { "type": ["integer", "null"] },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "string", "format": "date-time" },
- "updated_at": { "type": "string", "format": "date-time" },
- "due_date": { "type": "string", "format": "date-time" },
- "start_date": { "type": "string", "format": "date-time" }
- },
- "additionalProperties": false
- },
- "merge_when_pipeline_succeeds": { "type": "boolean" },
- "merge_status": { "type": "string" },
- "sha": { "type": "string" },
- "merge_commit_sha": { "type": ["string", "null"] },
- "user_notes_count": { "type": "integer" },
- "changes_count": { "type": "string" },
- "should_remove_source_branch": { "type": ["boolean", "null"] },
- "force_remove_source_branch": { "type": ["boolean", "null"] },
- "discussion_locked": { "type": ["boolean", "null"] },
- "web_url": { "type": "uri" },
- "squash": { "type": "boolean" },
- "time_stats": {
- "time_estimate": { "type": "integer" },
- "total_time_spent": { "type": "integer" },
- "human_time_estimate": { "type": ["string", "null"] },
- "human_total_time_spent": { "type": ["string", "null"] }
- },
- "allow_collaboration": { "type": ["boolean", "null"] },
- "allow_maintainer_to_push": { "type": ["boolean", "null"] },
- "references": {
- "short": {"type": "string"},
- "relative": {"type": "string"},
- "full": {"type": "string"}
+ "id": { "type": "integer" },
+ "iid": { "type": "integer" },
+ "project_id": { "type": "integer" },
+ "title": { "type": "string" },
+ "description": { "type": ["string", "null"] },
+ "state": { "type": "string" },
+ "merged_by": { "$ref": "user/basic.json" },
+ "merge_user": { "$ref": "user/basic.json" },
+ "merged_at": { "type": ["string", "null"] },
+ "closed_by": { "$ref": "user/basic.json" },
+ "closed_at": { "type": ["string", "null"], "format": "date-time" },
+ "created_at": { "type": "string", "format": "date-time" },
+ "updated_at": { "type": "string", "format": "date-time" },
+ "target_branch": { "type": "string" },
+ "source_branch": { "type": "string" },
+ "upvotes": { "type": "integer" },
+ "downvotes": { "type": "integer" },
+ "author": { "$ref": "user/basic.json" },
+ "assignee": { "$ref": "user/basic.json" },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "$ref": "user/basic.json"
}
},
- "required": [
- "id", "iid", "project_id", "title", "description",
- "state", "created_at", "updated_at", "target_branch",
- "source_branch", "upvotes", "downvotes", "author",
- "assignee", "source_project_id", "target_project_id",
- "labels", "work_in_progress", "milestone", "merge_when_pipeline_succeeds",
- "merge_status", "sha", "merge_commit_sha", "user_notes_count",
- "should_remove_source_branch", "force_remove_source_branch",
- "web_url", "squash"
- ],
- "head_pipeline": {
+ "reviewers": {
+ "type": "array",
+ "items": {
+ "$ref": "user/basic.json"
+ }
+ },
+ "source_project_id": { "type": "integer" },
+ "target_project_id": { "type": "integer" },
+ "labels": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "work_in_progress": { "type": "boolean" },
+ "milestone": {
"oneOf": [
{ "type": "null" },
- { "$ref": "pipeline/detail.json" }
+ { "$ref": "milestone.json" }
]
+ },
+ "merge_when_pipeline_succeeds": { "type": "boolean" },
+ "merge_status": { "type": "string" },
+ "sha": { "type": "string" },
+ "merge_commit_sha": { "type": ["string", "null"] },
+ "user_notes_count": { "type": "integer" },
+ "changes_count": { "type": "string" },
+ "should_remove_source_branch": { "type": ["boolean", "null"] },
+ "force_remove_source_branch": { "type": ["boolean", "null"] },
+ "discussion_locked": { "type": ["boolean", "null"] },
+ "web_url": { "type": "uri" },
+ "squash": { "type": "boolean" },
+ "time_stats": {
+ "time_estimate": { "type": "integer" },
+ "total_time_spent": { "type": "integer" },
+ "human_time_estimate": { "type": ["string", "null"] },
+ "human_total_time_spent": { "type": ["string", "null"] }
+ },
+ "allow_collaboration": { "type": ["boolean", "null"] },
+ "allow_maintainer_to_push": { "type": ["boolean", "null"] },
+ "references": {
+ "short": {"type": "string"},
+ "relative": {"type": "string"},
+ "full": {"type": "string"}
}
+ },
+ "required": [
+ "id", "iid", "project_id", "title", "description",
+ "state", "created_at", "updated_at", "target_branch",
+ "source_branch", "upvotes", "downvotes", "author",
+ "assignee", "source_project_id", "target_project_id",
+ "labels", "work_in_progress", "milestone", "merge_when_pipeline_succeeds",
+ "merge_status", "sha", "merge_commit_sha", "user_notes_count",
+ "should_remove_source_branch", "force_remove_source_branch",
+ "web_url", "squash"
+ ],
+ "head_pipeline": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "pipeline/detail.json" }
+ ]
}
}
diff --git a/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js b/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js
index 4ce814a01b4..41e69bffd88 100644
--- a/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js
+++ b/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js
@@ -1,4 +1,5 @@
-export const toMatchInterpolatedText = (received, match) => {
+// Custom matchers are object methods and should be traditional functions to be able to access `utils` on `this`
+export function toMatchInterpolatedText(received, match) {
let clearReceived;
let clearMatch;
@@ -15,16 +16,14 @@ export const toMatchInterpolatedText = (received, match) => {
const pass = clearReceived === clearMatch;
const message = pass
? () => `
- \n\n
- Expected: ${this.utils.printExpected(clearReceived)}
- To not equal: ${this.utils.printReceived(clearMatch)}
+ Expected to not be: ${this.utils.printExpected(clearMatch)}
+ Received: ${this.utils.printReceived(clearReceived)}
`
: () =>
`
- \n\n
- Expected: ${this.utils.printExpected(clearReceived)}
- To equal: ${this.utils.printReceived(clearMatch)}
+ Expected to be: ${this.utils.printExpected(clearMatch)}
+ Received: ${this.utils.printReceived(clearReceived)}
`;
return { actual: received, message, pass };
-};
+}
diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index ee4bbd42b1e..c07a6d8ef85 100644
--- a/spec/frontend/__helpers__/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
@@ -1,22 +1,25 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
+import { InMemoryCache } from '@apollo/client/core';
import { createMockClient as createMockApolloClient } from 'mock-apollo-client';
import VueApollo from 'vue-apollo';
-
-const defaultCacheOptions = {
- fragmentMatcher: { match: () => true },
- addTypename: false,
-};
+import possibleTypes from '~/graphql_shared/possibleTypes.json';
+import { typePolicies } from '~/lib/graphql';
export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {}) {
const cache = new InMemoryCache({
- ...defaultCacheOptions,
+ possibleTypes,
+ typePolicies,
+ addTypename: false,
...cacheOptions,
});
const mockClient = createMockApolloClient({ cache, resolvers });
if (Array.isArray(handlers)) {
- handlers.forEach(([query, value]) => mockClient.setRequestHandler(query, value));
+ handlers.forEach(([query, value]) =>
+ mockClient.setRequestHandler(query, (...args) =>
+ Promise.resolve(value(...args)).then((r) => ({ ...r })),
+ ),
+ );
} else {
throw new Error('You should pass an array of handlers to mock Apollo client');
}
diff --git a/spec/frontend/__helpers__/test_apollo_link.js b/spec/frontend/__helpers__/test_apollo_link.js
index dde3a4e99bb..eab0c2de212 100644
--- a/spec/frontend/__helpers__/test_apollo_link.js
+++ b/spec/frontend/__helpers__/test_apollo_link.js
@@ -1,7 +1,4 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
-import { ApolloClient } from 'apollo-client';
-import { ApolloLink } from 'apollo-link';
-import gql from 'graphql-tag';
+import { InMemoryCache, ApolloClient, ApolloLink, gql } from '@apollo/client/core';
const FOO_QUERY = gql`
query {
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index 6b3f1f01e6a..6f2888e5c42 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -41,10 +41,15 @@ jest.mock('@gitlab/ui/dist/components/base/popover/popover.js', () => ({
default: () => [],
},
...Object.fromEntries(
- ['title', 'target', 'triggers', 'placement', 'boundary', 'container'].map((prop) => [
- prop,
- {},
- ]),
+ [
+ 'title',
+ 'target',
+ 'triggers',
+ 'placement',
+ 'boundary',
+ 'container',
+ 'showCloseButton',
+ ].map((prop) => [prop, {}]),
),
},
render(h) {
diff --git a/spec/frontend/actioncable_link_spec.js b/spec/frontend/actioncable_link_spec.js
index c785151f8fd..b15b93cb11d 100644
--- a/spec/frontend/actioncable_link_spec.js
+++ b/spec/frontend/actioncable_link_spec.js
@@ -1,5 +1,5 @@
import { print } from 'graphql';
-import gql from 'graphql-tag';
+import { gql } from '@apollo/client/core';
import cable from '~/actioncable_consumer';
import ActionCableLink from '~/actioncable_link';
diff --git a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
index 10437c48f88..82114077455 100644
--- a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
+++ b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
@@ -17,7 +17,6 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = `
<gl-tabs-stub
contentclass="pt-0"
queryparamname="tab"
- theme="indigo"
value="0"
>
<gl-tab-stub
diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
index e7a20ae114c..9b93fd26fa0 100644
--- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
+++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal, GlSearchBoxByType } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import getDiffWithCommit from 'test_fixtures/merge_request_diffs/with_commit.json';
import AddReviewItemsModal from '~/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue';
@@ -8,8 +9,7 @@ import * as actions from '~/add_context_commits_modal/store/actions';
import mutations from '~/add_context_commits_modal/store/mutations';
import defaultState from '~/add_context_commits_modal/store/state';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('AddContextCommitsModal', () => {
let wrapper;
@@ -36,7 +36,6 @@ describe('AddContextCommitsModal', () => {
});
wrapper = shallowMount(AddReviewItemsModal, {
- localVue,
store,
propsData: {
contextCommitsPath: '',
@@ -85,11 +84,10 @@ describe('AddContextCommitsModal', () => {
expect(findModal().attributes('ok-disabled')).toBe('true');
});
- it('enabled ok button when atleast one row is selected', () => {
+ it('enabled ok button when atleast one row is selected', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
- return wrapper.vm.$nextTick().then(() => {
- expect(findModal().attributes('ok-disabled')).toBeFalsy();
- });
+ await nextTick();
+ expect(findModal().attributes('ok-disabled')).toBeFalsy();
});
});
@@ -101,11 +99,10 @@ describe('AddContextCommitsModal', () => {
expect(findModal().attributes('ok-disabled')).toBe('true');
});
- it('an enabled ok button when atleast one row is selected', () => {
+ it('an enabled ok button when atleast one row is selected', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
- return wrapper.vm.$nextTick().then(() => {
- expect(findModal().attributes('ok-disabled')).toBeFalsy();
- });
+ await nextTick();
+ expect(findModal().attributes('ok-disabled')).toBeFalsy();
});
it('a disabled ok button in first tab, when row is selected in second tab', () => {
@@ -115,33 +112,30 @@ describe('AddContextCommitsModal', () => {
});
describe('has an ok button when clicked calls action', () => {
- it('"createContextCommits" when only new commits to be added ', () => {
+ it('"createContextCommits" when only new commits to be added ', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
findModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
- expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
- commits: [{ ...commit, isSelected: true }],
- forceReload: true,
- });
+ await nextTick();
+ expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
+ commits: [{ ...commit, isSelected: true }],
+ forceReload: true,
});
});
- it('"removeContextCommits" when only added commits are to be removed ', () => {
+ it('"removeContextCommits" when only added commits are to be removed ', async () => {
wrapper.vm.$store.state.toRemoveCommits = [commit.short_id];
findModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
- expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), true);
- });
+ await nextTick();
+ expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), true);
});
- it('"createContextCommits" and "removeContextCommits" when new commits are to be added and old commits are to be removed', () => {
+ it('"createContextCommits" and "removeContextCommits" when new commits are to be added and old commits are to be removed', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
wrapper.vm.$store.state.toRemoveCommits = [commit.short_id];
findModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
- expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
- commits: [{ ...commit, isSelected: true }],
- });
- expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), undefined);
+ await nextTick();
+ expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
+ commits: [{ ...commit, isSelected: true }],
});
+ expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), undefined);
});
});
diff --git a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
index 025ae825e0d..f875cd24ee1 100644
--- a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
+++ b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DeleteUserModal from '~/admin/users/components/modals/delete_user_modal.vue';
import UserDeletionObstaclesList from '~/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue';
import ModalStub from './stubs/modal_stub';
@@ -82,11 +83,11 @@ describe('User Operation confirmation modal', () => {
});
describe('with incorrect username', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
setUsername(badUsername);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows incorrect username', () => {
@@ -100,11 +101,11 @@ describe('User Operation confirmation modal', () => {
});
describe('with correct username', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
setUsername(username);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows correct username', () => {
@@ -117,10 +118,10 @@ describe('User Operation confirmation modal', () => {
});
describe('when primary action is submitted', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findPrimaryButton().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('clears the input', () => {
@@ -136,10 +137,10 @@ describe('User Operation confirmation modal', () => {
});
describe('when secondary action is submitted', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findSecondaryButton().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('has correct form attributes and calls submit', () => {
@@ -168,7 +169,7 @@ describe('User Operation confirmation modal', () => {
it("shows enabled buttons when user's name is entered without whitespace", async () => {
setUsername('John Smith');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPrimaryButton().attributes('disabled')).toBeUndefined();
expect(findSecondaryButton().attributes('disabled')).toBeUndefined();
diff --git a/spec/frontend/admin/users/components/modals/user_modal_manager_spec.js b/spec/frontend/admin/users/components/modals/user_modal_manager_spec.js
index 65ce242662b..4786357faa1 100644
--- a/spec/frontend/admin/users/components/modals/user_modal_manager_spec.js
+++ b/spec/frontend/admin/users/components/modals/user_modal_manager_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import UserModalManager from '~/admin/users/components/modals/user_modal_manager.vue';
import ModalStub from './stubs/modal_stub';
@@ -50,20 +51,19 @@ describe('Users admin page Modal Manager', () => {
expect(() => wrapper.vm.show({ glModalAction: 'action1' })).toThrow();
});
- it('renders modal with expected props when valid configuration is passed', () => {
+ it('renders modal with expected props when valid configuration is passed', async () => {
createComponent();
wrapper.vm.show({
glModalAction: 'action1',
extraProp: 'extraPropValue',
});
- return wrapper.vm.$nextTick().then(() => {
- const modal = findModal();
- expect(modal.exists()).toBeTruthy();
- expect(modal.vm.$attrs.csrfToken).toEqual('dummyCSRF');
- expect(modal.vm.$attrs.extraProp).toEqual('extraPropValue');
- expect(modal.vm.showWasCalled).toBeTruthy();
- });
+ await nextTick();
+ const modal = findModal();
+ expect(modal.exists()).toBeTruthy();
+ expect(modal.vm.$attrs.csrfToken).toEqual('dummyCSRF');
+ expect(modal.vm.$attrs.extraProp).toEqual('extraPropValue');
+ expect(modal.vm.showWasCalled).toBeTruthy();
});
});
@@ -101,7 +101,7 @@ describe('Users admin page Modal Manager', () => {
it('renders the modal when the button is clicked', async () => {
button.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal().exists()).toBe(true);
});
@@ -110,7 +110,7 @@ describe('Users admin page Modal Manager', () => {
button.removeAttribute('data-gl-modal-action');
button.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal().exists()).toBe(false);
});
@@ -118,7 +118,7 @@ describe('Users admin page Modal Manager', () => {
it('does not render the modal when a button without the selector class is clicked', async () => {
button2.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal().exists()).toBe(false);
});
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index 9ff5961c7ec..ad1c45495b5 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -3,6 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import AdminUserActions from '~/admin/users/components/user_actions.vue';
@@ -106,8 +107,9 @@ describe('AdminUsersTable component', () => {
});
describe('when the data has been fetched', () => {
- beforeEach(() => {
+ beforeEach(async () => {
initComponent();
+ await waitForPromises();
});
it("renders the user's group count", () => {
@@ -115,8 +117,9 @@ describe('AdminUsersTable component', () => {
});
describe("and a user's group count is null", () => {
- beforeEach(() => {
+ beforeEach(async () => {
initComponent({}, createFetchGroupCount([{ id: user.id, groupCount: null }]));
+ await waitForPromises();
});
it("renders the user's group count as 0", () => {
@@ -126,12 +129,12 @@ describe('AdminUsersTable component', () => {
});
describe('when there is an error while fetching the data', () => {
- beforeEach(() => {
+ beforeEach(async () => {
initComponent({}, fetchGroupCountsError);
+ await waitForPromises();
});
it('creates a flash message and captures the error', () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith({
message: 'Could not load user group counts. Please refresh the page to try again.',
captureError: true,
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 39aab8dc1f8..5b823694b99 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -2,6 +2,7 @@ import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar } from '@
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import mockAlerts from 'jest/vue_shared/alert_details/mocks/alerts.json';
@@ -169,7 +170,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTable).exists()).toBe(true);
expect(findAlertsTable().find(GlIcon).classes('icon-critical')).toBe(true);
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 e6a6e01c41c..6193233881d 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -1,7 +1,7 @@
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
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';
@@ -50,8 +50,6 @@ import mockIntegrations from './mocks/integrations.json';
jest.mock('~/flash');
-const localVue = createLocalVue();
-
describe('AlertsSettingsWrapper', () => {
let wrapper;
let fakeApollo;
@@ -70,21 +68,12 @@ describe('AlertsSettingsWrapper', () => {
const findAlertsSettingsForm = () => wrapper.findComponent(AlertsSettingsForm);
const findAlert = () => wrapper.findComponent(GlAlert);
- async function destroyHttpIntegration(localWrapper) {
- await jest.runOnlyPendingTimers();
- await localWrapper.vm.$nextTick();
-
+ function destroyHttpIntegration(localWrapper) {
localWrapper
.find(IntegrationsList)
.vm.$emit('delete-integration', { id: integrationToDestroy.id });
}
- async function awaitApolloDomMock() {
- await nextTick(); // kick off the DOM update
- await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await nextTick(); // kick off the DOM update for flash
- }
-
const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
wrapper = extendedWrapper(
mount(AlertsSettingsWrapper, {
@@ -118,7 +107,7 @@ describe('AlertsSettingsWrapper', () => {
function createComponentWithApollo({
destroyHandler = jest.fn().mockResolvedValue(destroyIntegrationResponse),
} = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
destroyIntegrationHandler = destroyHandler;
const requestHandlers = [
@@ -129,7 +118,6 @@ describe('AlertsSettingsWrapper', () => {
fakeApollo = createMockApollo(requestHandlers);
wrapper = mount(AlertsSettingsWrapper, {
- localVue,
apolloProvider: fakeApollo,
provide: {
alertSettings: {
@@ -476,21 +464,19 @@ describe('AlertsSettingsWrapper', () => {
describe('with mocked Apollo client', () => {
it('has a selection of integrations loaded via the getIntegrationsQuery', async () => {
createComponentWithApollo();
-
- await jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
expect(findIntegrations()).toHaveLength(4);
});
it('calls a mutation with correct parameters and destroys a integration', async () => {
createComponentWithApollo();
+ await waitForPromises();
- await destroyHttpIntegration(wrapper);
+ destroyHttpIntegration(wrapper);
expect(destroyIntegrationHandler).toHaveBeenCalled();
-
- await nextTick();
+ await waitForPromises();
expect(findIntegrations()).toHaveLength(3);
});
@@ -501,7 +487,7 @@ describe('AlertsSettingsWrapper', () => {
});
await destroyHttpIntegration(wrapper);
- await awaitApolloDomMock();
+ await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
@@ -512,7 +498,7 @@ describe('AlertsSettingsWrapper', () => {
});
await destroyHttpIntegration(wrapper);
- await awaitApolloDomMock();
+ await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_INTEGRATION_ERROR,
diff --git a/spec/frontend/alerts_settings/components/mocks/apollo_mock.js b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
index e7ad2cd1d2a..694dff56632 100644
--- a/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
+++ b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
@@ -38,6 +38,7 @@ export const getIntegrationsQueryResponse = {
alertManagementIntegrations: {
nodes: [
{
+ __typename: 'AlertManagementIntegration',
id: '37',
type: 'HTTP',
active: true,
@@ -48,6 +49,7 @@ export const getIntegrationsQueryResponse = {
apiUrl: null,
},
{
+ __typename: 'AlertManagementIntegration',
id: '41',
type: 'HTTP',
active: true,
@@ -58,6 +60,7 @@ export const getIntegrationsQueryResponse = {
apiUrl: null,
},
{
+ __typename: 'AlertManagementIntegration',
id: '40',
type: 'HTTP',
active: true,
@@ -68,6 +71,7 @@ export const getIntegrationsQueryResponse = {
apiUrl: null,
},
{
+ __typename: 'AlertManagementIntegration',
id: '12',
type: 'PROMETHEUS',
active: false,
@@ -83,6 +87,7 @@ export const getIntegrationsQueryResponse = {
};
export const integrationToDestroy = {
+ __typename: 'AlertManagementIntegration',
id: '37',
type: 'HTTP',
active: true,
@@ -97,6 +102,7 @@ export const destroyIntegrationResponse = {
httpIntegrationDestroy: {
errors: [],
integration: {
+ __typename: 'AlertManagementIntegration',
id: '37',
type: 'HTTP',
active: true,
diff --git a/spec/frontend/analytics/shared/components/daterange_spec.js b/spec/frontend/analytics/shared/components/daterange_spec.js
index 854582abb82..a38df274243 100644
--- a/spec/frontend/analytics/shared/components/daterange_spec.js
+++ b/spec/frontend/analytics/shared/components/daterange_spec.js
@@ -1,7 +1,6 @@
-import { GlDaterangePicker } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { GlDaterangePicker, GlSprintf } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import Daterange from '~/analytics/shared/components/daterange.vue';
const defaultProps = {
@@ -14,13 +13,13 @@ describe('Daterange component', () => {
let wrapper;
- const factory = (props = defaultProps) => {
- wrapper = mount(Daterange, {
+ const factory = (props = defaultProps, mountFn = shallowMount) => {
+ wrapper = mountFn(Daterange, {
propsData: {
...defaultProps,
...props,
},
- directives: { GlTooltip: createMockDirective() },
+ stubs: { GlSprintf },
});
};
@@ -28,9 +27,8 @@ describe('Daterange component', () => {
wrapper.destroy();
});
- const findDaterangePicker = () => wrapper.find(GlDaterangePicker);
-
- const findDateRangeIndicator = () => wrapper.find('.daterange-indicator');
+ const findDaterangePicker = () => wrapper.findComponent(GlDaterangePicker);
+ const findDateRangeIndicator = () => wrapper.findComponent(GlSprintf);
describe('template', () => {
describe('when show is false', () => {
@@ -43,26 +41,24 @@ describe('Daterange component', () => {
describe('when show is true', () => {
it('renders the daterange picker', () => {
factory({ show: true });
+
expect(findDaterangePicker().exists()).toBe(true);
});
});
describe('with a minDate being set', () => {
- it('emits the change event with the minDate when the user enters a start date before the minDate', () => {
+ it('emits the change event with the minDate when the user enters a start date before the minDate', async () => {
const startDate = new Date('2019-09-01');
const endDate = new Date('2019-09-30');
const minDate = new Date('2019-06-01');
- factory({ show: true, startDate, endDate, minDate });
-
+ factory({ show: true, startDate, endDate, minDate }, mount);
const input = findDaterangePicker().find('input');
input.setValue('2019-01-01');
- input.trigger('change');
+ await input.trigger('change');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().change).toEqual([[{ startDate: minDate, endDate }]]);
- });
+ expect(wrapper.emitted().change).toEqual([[{ startDate: minDate, endDate }]]);
});
});
@@ -76,16 +72,13 @@ describe('Daterange component', () => {
});
it('displays the correct number of selected days in the indicator', () => {
- expect(findDateRangeIndicator().find('span').text()).toBe('10 days selected');
+ expect(findDateRangeIndicator().text()).toMatchInterpolatedText('10 days selected');
});
- it('displays a tooltip', () => {
- const icon = wrapper.find('[data-testid="helper-icon"]');
- const tooltip = getBinding(icon.element, 'gl-tooltip');
-
- expect(tooltip).toBeDefined();
- expect(icon.attributes('title')).toBe(
- 'Showing data for workflow items created in this date range. Date range cannot exceed 30 days.',
+ it('sets the tooltip', () => {
+ const tooltip = findDaterangePicker().props('tooltip');
+ expect(tooltip).toBe(
+ 'Showing data for workflow items created in this date range. Date range limited to 30 days.',
);
});
});
diff --git a/spec/frontend/cycle_analytics/metric_popover_spec.js b/spec/frontend/analytics/shared/components/metric_popover_spec.js
index 5a622fcacd5..b799c911488 100644
--- a/spec/frontend/cycle_analytics/metric_popover_spec.js
+++ b/spec/frontend/analytics/shared/components/metric_popover_spec.js
@@ -1,6 +1,6 @@
import { GlLink, GlIcon } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import MetricPopover from '~/cycle_analytics/components/metric_popover.vue';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
const MOCK_METRIC = {
key: 'deployment-frequency',
diff --git a/spec/frontend/analytics/shared/components/metric_tile_spec.js b/spec/frontend/analytics/shared/components/metric_tile_spec.js
new file mode 100644
index 00000000000..980dfad9eb0
--- /dev/null
+++ b/spec/frontend/analytics/shared/components/metric_tile_spec.js
@@ -0,0 +1,81 @@
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
+import MetricTile from '~/analytics/shared/components/metric_tile.vue';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
+import { redirectTo } from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility');
+
+describe('MetricTile', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMount(MetricTile, {
+ propsData: {
+ metric: {},
+ ...props,
+ },
+ });
+ };
+
+ const findSingleStat = () => wrapper.findComponent(GlSingleStat);
+ const findPopover = () => wrapper.findComponent(MetricPopover);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ describe('links', () => {
+ it('when the metric has links, it redirects the user on click', () => {
+ const metric = {
+ identifier: 'deploys',
+ value: '10',
+ label: 'Deploys',
+ links: [{ url: 'foo/bar' }],
+ };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ singleStat.vm.$emit('click');
+ expect(redirectTo).toHaveBeenCalledWith('foo/bar');
+ });
+
+ it("when the metric doesn't have links, it won't the user on click", () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ singleStat.vm.$emit('click');
+ expect(redirectTo).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('decimal places', () => {
+ it(`will render 0 decimal places for an integer value`, () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ expect(singleStat.props('animationDecimalPlaces')).toBe(0);
+ });
+
+ it(`will render 1 decimal place for a float value`, () => {
+ const metric = { identifier: 'deploys', value: '10.5', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ expect(singleStat.props('animationDecimalPlaces')).toBe(1);
+ });
+ });
+
+ it('renders a metric popover', () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const popover = findPopover();
+ expect(popover.exists()).toBe(true);
+ expect(popover.props()).toMatchObject({ metric, target: metric.identifier });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
index 28d7ebe28df..386fb4eb616 100644
--- a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
+++ b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
@@ -1,4 +1,5 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import { TEST_HOST } from 'helpers/test_constants';
@@ -99,9 +100,9 @@ describe('ProjectsDropdownFilter component', () => {
const findDropdownFullPathAtIndex = (index) =>
findDropdownAtIndex(index).find('[data-testid="project-full-path"]');
- const selectDropdownItemAtIndex = (index) => {
+ const selectDropdownItemAtIndex = async (index) => {
findDropdownAtIndex(index).find('button').trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
// NOTE: Selected items are now visually separated from unselected items
@@ -132,16 +133,15 @@ describe('ProjectsDropdownFilter component', () => {
expect(spyQuery).toHaveBeenCalledTimes(1);
- await wrapper.vm.$nextTick(() => {
- expect(spyQuery).toHaveBeenCalledWith({
- query: getProjects,
- variables: {
- search: 'gitlab',
- groupFullPath: wrapper.vm.groupNamespace,
- first: 50,
- includeSubgroups: true,
- },
- });
+ await nextTick();
+ expect(spyQuery).toHaveBeenCalledWith({
+ query: getProjects,
+ variables: {
+ search: 'gitlab',
+ groupFullPath: wrapper.vm.groupNamespace,
+ first: 50,
+ includeSubgroups: true,
+ },
});
});
});
@@ -193,7 +193,7 @@ describe('ProjectsDropdownFilter component', () => {
expect(wrapper.text()).toContain('2 projects selected');
findClearAllButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).not.toContain('2 projects selected');
expect(wrapper.text()).toContain('Select projects');
@@ -366,9 +366,8 @@ describe('ProjectsDropdownFilter component', () => {
selectDropdownItemAtIndex(0);
selectDropdownItemAtIndex(1);
- await wrapper.vm.$nextTick().then(() => {
- expect(findDropdownButton().text()).toBe('2 projects selected');
- });
+ await nextTick();
+ expect(findDropdownButton().text()).toBe('2 projects selected');
});
});
});
diff --git a/spec/frontend/analytics/shared/utils_spec.js b/spec/frontend/analytics/shared/utils_spec.js
index 0513ccb2890..b48e2d971b5 100644
--- a/spec/frontend/analytics/shared/utils_spec.js
+++ b/spec/frontend/analytics/shared/utils_spec.js
@@ -1,9 +1,12 @@
+import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import {
filterBySearchTerm,
extractFilterQueryParameters,
extractPaginationQueryParameters,
getDataZoomOption,
+ prepareTimeMetricsData,
} from '~/analytics/shared/utils';
+import { slugify } from '~/lib/utils/text_utility';
import { objectToQuery } from '~/lib/utils/url_utility';
describe('filterBySearchTerm', () => {
@@ -176,3 +179,36 @@ describe('getDataZoomOption', () => {
});
});
});
+
+describe('prepareTimeMetricsData', () => {
+ let prepared;
+ const [first, second] = metricsData;
+ delete second.identifier; // testing the case when identifier is missing
+
+ const firstIdentifier = first.identifier;
+ const secondIdentifier = slugify(second.title);
+
+ beforeEach(() => {
+ prepared = prepareTimeMetricsData([first, second], {
+ [firstIdentifier]: { description: 'Is a value that is good' },
+ });
+ });
+
+ it('will add a `identifier` based on the title', () => {
+ expect(prepared).toMatchObject([
+ { identifier: firstIdentifier },
+ { identifier: secondIdentifier },
+ ]);
+ });
+
+ it('will add a `label` key', () => {
+ expect(prepared).toMatchObject([{ label: 'New Issues' }, { label: 'Commits' }]);
+ });
+
+ it('will add a popover description using the key if it is provided', () => {
+ expect(prepared).toMatchObject([
+ { description: 'Is a value that is good' },
+ { description: '' },
+ ]);
+ });
+});
diff --git a/spec/frontend/analytics/usage_trends/apollo_mock_data.js b/spec/frontend/analytics/usage_trends/apollo_mock_data.js
index 98eabd577ee..934bbc63689 100644
--- a/spec/frontend/analytics/usage_trends/apollo_mock_data.js
+++ b/spec/frontend/analytics/usage_trends/apollo_mock_data.js
@@ -1,4 +1,5 @@
const defaultPageInfo = {
+ __typename: 'PageInfo',
hasNextPage: false,
hasPreviousPage: false,
startCursor: null,
diff --git a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
index 1a331100bb8..02cf7f42a0b 100644
--- a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
+++ b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
@@ -1,9 +1,10 @@
import { GlAlert } from '@gitlab/ui';
import { GlLineChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+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 UsageTrendsCountChart from '~/analytics/usage_trends/components/usage_trends_count_chart.vue';
import statsQuery from '~/analytics/usage_trends/graphql/queries/usage_count.query.graphql';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
@@ -77,9 +78,10 @@ describe('UsageTrendsCountChart', () => {
});
describe('without data', () => {
- beforeEach(() => {
+ beforeEach(async () => {
queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: [] });
wrapper = createComponent({ responseHandler: queryHandler });
+ await waitForPromises();
});
it('renders an no data message', () => {
@@ -96,9 +98,10 @@ describe('UsageTrendsCountChart', () => {
});
describe('with data', () => {
- beforeEach(() => {
+ beforeEach(async () => {
queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: mockCountsData1 });
wrapper = createComponent({ responseHandler: queryHandler });
+ await waitForPromises();
});
it('requests data', () => {
@@ -126,7 +129,7 @@ describe('UsageTrendsCountChart', () => {
const recordedAt = '2020-08-01';
describe('when the fetchMore query returns data', () => {
beforeEach(async () => {
- const newData = [{ recordedAt, count: 5 }];
+ const newData = [{ __typename: 'UsageTrendsMeasurement', recordedAt, count: 5 }];
queryHandler = mockQueryResponse({
key: queryResponseDataKey,
data: mockCountsData1,
@@ -134,7 +137,7 @@ describe('UsageTrendsCountChart', () => {
});
wrapper = createComponent({ responseHandler: queryHandler });
- await wrapper.vm.$nextTick();
+ await waitForPromises();
});
it('requests data twice', () => {
@@ -161,7 +164,7 @@ describe('UsageTrendsCountChart', () => {
.spyOn(wrapper.vm.$apollo.queries[identifier], 'fetchMore')
.mockImplementation(jest.fn().mockRejectedValue());
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls fetchMore', () => {
diff --git a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
index 04ea25a02d5..32a664a5026 100644
--- a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
+++ b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
@@ -1,9 +1,10 @@
import { GlAlert } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+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 UsersChart from '~/analytics/usage_trends/components/users_chart.vue';
import usersQuery from '~/analytics/usage_trends/graphql/queries/users.query.graphql';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
@@ -67,7 +68,7 @@ describe('UsersChart', () => {
describe('without data', () => {
beforeEach(async () => {
wrapper = createComponent({ users: [] });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders an no data message', () => {
@@ -86,7 +87,7 @@ describe('UsersChart', () => {
describe('with data', () => {
beforeEach(async () => {
wrapper = createComponent({ users: mockCountsData2 });
- await wrapper.vm.$nextTick();
+ await waitForPromises();
});
it('hides the skeleton loader', () => {
@@ -107,7 +108,7 @@ describe('UsersChart', () => {
describe('with errors', () => {
beforeEach(async () => {
wrapper = createComponent({ loadingError: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders an error message', () => {
@@ -134,7 +135,7 @@ describe('UsersChart', () => {
});
jest.spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('requests data twice', () => {
@@ -147,7 +148,7 @@ describe('UsersChart', () => {
});
describe('when the fetchMore query throws an error', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = createComponent({
users: mockCountsData2,
additionalData: mockCountsData1,
@@ -156,7 +157,7 @@ describe('UsersChart', () => {
jest
.spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore')
.mockImplementation(jest.fn().mockRejectedValue());
- return wrapper.vm.$nextTick();
+ await waitForPromises();
});
it('calls fetchMore', () => {
diff --git a/spec/frontend/analytics/usage_trends/mock_data.js b/spec/frontend/analytics/usage_trends/mock_data.js
index d96dfa26209..77bd44d17f5 100644
--- a/spec/frontend/analytics/usage_trends/mock_data.js
+++ b/spec/frontend/analytics/usage_trends/mock_data.js
@@ -4,11 +4,11 @@ export const mockUsageCounts = [
];
export const mockCountsData1 = [
- { recordedAt: '2020-07-23', count: 52 },
- { recordedAt: '2020-07-22', count: 40 },
- { recordedAt: '2020-07-21', count: 31 },
- { recordedAt: '2020-06-14', count: 23 },
- { recordedAt: '2020-06-12', count: 20 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-07-23', count: 52 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-07-22', count: 40 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-07-21', count: 31 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-06-14', count: 23 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-06-12', count: 20 },
];
export const countsMonthlyChartData1 = [
@@ -17,11 +17,11 @@ export const countsMonthlyChartData1 = [
];
export const mockCountsData2 = [
- { recordedAt: '2020-07-28', count: 10 },
- { recordedAt: '2020-07-27', count: 9 },
- { recordedAt: '2020-06-26', count: 14 },
- { recordedAt: '2020-06-25', count: 23 },
- { recordedAt: '2020-06-24', count: 25 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-07-28', count: 10 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-07-27', count: 9 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-06-26', count: 14 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-06-25', count: 23 },
+ { __typename: 'UsageTrendsMeasurement', recordedAt: '2020-06-24', count: 25 },
];
export const countsMonthlyChartData2 = [
diff --git a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
index bfa8274f0eb..2f3ff2b22f2 100644
--- a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
+++ b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox, GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import UpdateKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql';
@@ -7,8 +8,7 @@ import GetKeepLatestArtifactApplicationSetting from '~/artifacts_settings/graphq
import GetKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
import KeepLatestArtifactCheckbox from '~/artifacts_settings/keep_latest_artifact_checkbox.vue';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const keepLatestArtifactProjectMock = {
data: {
@@ -73,7 +73,6 @@ describe('Keep latest artifact checkbox', () => {
stubs: {
GlFormCheckbox,
},
- localVue,
apolloProvider,
});
};
@@ -110,13 +109,13 @@ describe('Keep latest artifact checkbox', () => {
});
it('sets correct setting value in checkbox with query result', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.element).toMatchSnapshot();
});
it('checkbox is enabled when application setting is enabled', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCheckbox().attributes('disabled')).toBeUndefined();
});
diff --git a/spec/frontend/authentication/webauthn/util_spec.js b/spec/frontend/authentication/webauthn/util_spec.js
new file mode 100644
index 00000000000..c9b8bfd8679
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/util_spec.js
@@ -0,0 +1,19 @@
+import { base64ToBuffer, bufferToBase64 } from '~/authentication/webauthn/util';
+
+const encodedString = 'SGVsbG8gd29ybGQh';
+const stringBytes = [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33];
+
+describe('Webauthn utils', () => {
+ it('base64ToBuffer', () => {
+ const toArray = (val) => new Uint8Array(val);
+
+ expect(base64ToBuffer(encodedString)).toBeInstanceOf(ArrayBuffer);
+
+ expect(toArray(base64ToBuffer(encodedString))).toEqual(toArray(stringBytes));
+ });
+
+ it('bufferToBase64', () => {
+ const buffer = base64ToBuffer(encodedString);
+ expect(bufferToBase64(buffer)).toBe(encodedString);
+ });
+});
diff --git a/spec/frontend/badges/components/badge_form_spec.js b/spec/frontend/badges/components/badge_form_spec.js
index e375fcb4705..ba2ec775b61 100644
--- a/spec/frontend/badges/components/badge_form_spec.js
+++ b/spec/frontend/badges/components/badge_form_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'helpers/test_constants';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeForm from '~/badges/components/badge_form.vue';
@@ -74,7 +74,7 @@ describe('BadgeForm component', () => {
expect(feedbackElement).toBeVisible();
};
- beforeEach((done) => {
+ beforeEach(async () => {
jest.spyOn(vm, submitAction).mockReturnValue(Promise.resolve());
store.replaceState({
...store.state,
@@ -83,14 +83,10 @@ describe('BadgeForm component', () => {
isSaving: false,
});
- Vue.nextTick()
- .then(() => {
- setValue(nameSelector, 'TestBadge');
- setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
- setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ setValue(nameSelector, 'TestBadge');
+ setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
+ setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
});
it('returns immediately if imageUrl is empty', () => {
diff --git a/spec/frontend/badges/components/badge_list_row_spec.js b/spec/frontend/badges/components/badge_list_row_spec.js
index 372663017e2..0fb0fa86a02 100644
--- a/spec/frontend/badges/components/badge_list_row_spec.js
+++ b/spec/frontend/badges/components/badge_list_row_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeListRow from '~/badges/components/badge_list_row.vue';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
@@ -73,25 +73,21 @@ describe('BadgeListRow component', () => {
expect(vm.editBadge).toHaveBeenCalled();
});
- it('calls updateBadgeInModal and shows modal when clicking then delete button', (done) => {
+ it('calls updateBadgeInModal and shows modal when clicking then delete button', async () => {
jest.spyOn(vm, 'updateBadgeInModal').mockImplementation(() => {});
const deleteButton = vm.$el.querySelector('.table-button-footer button:last-of-type');
deleteButton.click();
- Vue.nextTick()
- .then(() => {
- expect(vm.updateBadgeInModal).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.updateBadgeInModal).toHaveBeenCalled();
});
describe('for a group badge', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
badge.kind = GROUP_BADGE;
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
it('renders the badge kind', () => {
diff --git a/spec/frontend/badges/components/badge_list_spec.js b/spec/frontend/badges/components/badge_list_spec.js
index 6cc90c6de46..39fa502b207 100644
--- a/spec/frontend/badges/components/badge_list_spec.js
+++ b/spec/frontend/badges/components/badge_list_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeList from '~/badges/components/badge_list.vue';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
@@ -48,46 +48,34 @@ describe('BadgeList component', () => {
expect(rows).toHaveLength(numberOfDummyBadges);
});
- it('renders a message if no badges exist', (done) => {
+ it('renders a message if no badges exist', async () => {
store.state.badges = [];
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.innerText).toMatch('This project has no badges');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.innerText).toMatch('This project has no badges');
});
- it('shows a loading icon when loading', (done) => {
+ it('shows a loading icon when loading', async () => {
store.state.isLoading = true;
- Vue.nextTick()
- .then(() => {
- const loadingIcon = vm.$el.querySelector('.gl-spinner');
+ await nextTick();
+ const loadingIcon = vm.$el.querySelector('.gl-spinner');
- expect(loadingIcon).toBeVisible();
- })
- .then(done)
- .catch(done.fail);
+ expect(loadingIcon).toBeVisible();
});
describe('for group badges', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
store.state.kind = GROUP_BADGE;
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
- it('renders a message if no badges exist', (done) => {
+ it('renders a message if no badges exist', async () => {
store.state.badges = [];
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.innerText).toMatch('This group has no badges');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.innerText).toMatch('This group has no badges');
});
});
});
diff --git a/spec/frontend/badges/components/badge_settings_spec.js b/spec/frontend/badges/components/badge_settings_spec.js
index 0c29379763e..79cf5f3e4ff 100644
--- a/spec/frontend/badges/components/badge_settings_spec.js
+++ b/spec/frontend/badges/components/badge_settings_spec.js
@@ -1,5 +1,6 @@
import { GlModal } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import BadgeList from '~/badges/components/badge_list.vue';
import BadgeListRow from '~/badges/components/badge_list_row.vue';
@@ -7,8 +8,7 @@ import BadgeSettings from '~/badges/components/badge_settings.vue';
import store from '~/badges/store';
import { createDummyBadge } from '../dummy_badge';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('BadgeSettings component', () => {
let wrapper;
@@ -21,7 +21,6 @@ describe('BadgeSettings component', () => {
wrapper = shallowMount(BadgeSettings, {
store,
- localVue,
stubs: {
'badge-list': BadgeList,
'badge-list-row': BadgeListRow,
@@ -41,7 +40,7 @@ describe('BadgeSettings component', () => {
const button = wrapper.find('[data-testid="delete-badge"]');
button.vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
const modal = wrapper.find(GlModal);
expect(modal.isVisible()).toBe(true);
diff --git a/spec/frontend/badges/components/badge_spec.js b/spec/frontend/badges/components/badge_spec.js
index 990bc094d59..2310fb8bd8e 100644
--- a/spec/frontend/badges/components/badge_spec.js
+++ b/spec/frontend/badges/components/badge_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants';
import Badge from '~/badges/components/badge.vue';
@@ -27,7 +27,7 @@ describe('Badge component', () => {
badgeImage.addEventListener('load', resolve);
// Manually dispatch load event as it is not triggered
badgeImage.dispatchEvent(new Event('load'));
- }).then(() => Vue.nextTick());
+ }).then(() => nextTick());
};
afterEach(() => {
@@ -36,34 +36,25 @@ describe('Badge component', () => {
describe('watchers', () => {
describe('imageUrl', () => {
- it('sets isLoading and resets numRetries and hasError', (done) => {
+ it('sets isLoading and resets numRetries and hasError', async () => {
const props = { ...dummyProps };
- createComponent(props)
- .then(() => {
- expect(vm.isLoading).toBe(false);
- vm.hasError = true;
- vm.numRetries = 42;
-
- vm.imageUrl = `${props.imageUrl}#something/else`;
-
- return Vue.nextTick();
- })
- .then(() => {
- expect(vm.isLoading).toBe(true);
- expect(vm.numRetries).toBe(0);
- expect(vm.hasError).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ await createComponent(props);
+ expect(vm.isLoading).toBe(false);
+ vm.hasError = true;
+ vm.numRetries = 42;
+
+ vm.imageUrl = `${props.imageUrl}#something/else`;
+ await nextTick();
+ expect(vm.isLoading).toBe(true);
+ expect(vm.numRetries).toBe(0);
+ expect(vm.hasError).toBe(false);
});
});
});
describe('methods', () => {
- beforeEach((done) => {
- createComponent({ ...dummyProps })
- .then(done)
- .catch(done.fail);
+ beforeEach(async () => {
+ await createComponent({ ...dummyProps });
});
it('onError resets isLoading and sets hasError', () => {
@@ -116,37 +107,29 @@ describe('Badge component', () => {
expect(vm.$el.querySelector('.btn-group')).toBeHidden();
});
- it('shows a loading icon when loading', (done) => {
+ it('shows a loading icon when loading', async () => {
vm.isLoading = true;
- Vue.nextTick()
- .then(() => {
- const { badgeImage, loadingIcon, reloadButton } = findElements();
+ await nextTick();
+ const { badgeImage, loadingIcon, reloadButton } = findElements();
- expect(badgeImage).toBeHidden();
- expect(loadingIcon).toBeVisible();
- expect(reloadButton).toBeHidden();
- expect(vm.$el.querySelector('.btn-group')).toBeHidden();
- })
- .then(done)
- .catch(done.fail);
+ expect(badgeImage).toBeHidden();
+ expect(loadingIcon).toBeVisible();
+ expect(reloadButton).toBeHidden();
+ expect(vm.$el.querySelector('.btn-group')).toBeHidden();
});
- it('shows an error and reload button if loading failed', (done) => {
+ it('shows an error and reload button if loading failed', async () => {
vm.hasError = true;
- Vue.nextTick()
- .then(() => {
- const { badgeImage, loadingIcon, reloadButton } = findElements();
+ await nextTick();
+ const { badgeImage, loadingIcon, reloadButton } = findElements();
- expect(badgeImage).toBeHidden();
- expect(loadingIcon).toBeHidden();
- expect(reloadButton).toBeVisible();
- expect(reloadButton).toHaveSpriteIcon('retry');
- expect(vm.$el.innerText.trim()).toBe('No badge image');
- })
- .then(done)
- .catch(done.fail);
+ expect(badgeImage).toBeHidden();
+ expect(loadingIcon).toBeHidden();
+ expect(reloadButton).toBeVisible();
+ expect(reloadButton).toHaveSpriteIcon('retry');
+ expect(vm.$el.innerText.trim()).toBe('No badge image');
});
});
});
diff --git a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
index dcb68b1804f..6a5ff1af7c9 100644
--- a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
+++ b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
import DraftNote from '~/batch_comments/components/draft_note.vue';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Batch comments diff file drafts component', () => {
let vm;
@@ -22,9 +22,8 @@ describe('Batch comments diff file drafts component', () => {
},
});
- vm = shallowMount(localVue.extend(DiffFileDrafts), {
+ vm = shallowMount(DiffFileDrafts, {
store,
- localVue,
propsData: { fileHash: 'filehash' },
});
}
@@ -42,10 +41,12 @@ describe('Batch comments diff file drafts component', () => {
it('renders index of draft note', () => {
factory();
- expect(vm.findAll('.js-diff-notes-index').length).toEqual(2);
+ const elements = vm.findAll(DesignNotePin);
+
+ expect(elements.length).toEqual(2);
- expect(vm.findAll('.js-diff-notes-index').at(0).text()).toEqual('1');
+ expect(elements.at(0).props('label')).toEqual(1);
- expect(vm.findAll('.js-diff-notes-index').at(1).text()).toEqual('2');
+ expect(elements.at(1).props('label')).toEqual(2);
});
});
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index 5d22823e974..6a997ebaaa8 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -1,14 +1,15 @@
+import { nextTick } from 'vue';
+import { GlButton, GlBadge } from '@gitlab/ui';
import { getByRole } from '@testing-library/dom';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import DraftNote from '~/batch_comments/components/draft_note.vue';
+import PublishButton from '~/batch_comments/components/publish_button.vue';
import { createStore } from '~/batch_comments/stores';
import NoteableNote from '~/notes/components/noteable_note.vue';
import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
-const localVue = createLocalVue();
-
const NoteableNoteStub = stubComponent(NoteableNote, {
template: `
<div>
@@ -29,12 +30,13 @@ describe('Batch comments draft note component', () => {
};
const getList = () => getByRole(wrapper.element, 'list');
+ const findSubmitReviewButton = () => wrapper.findComponent(PublishButton);
+ const findAddCommentButton = () => wrapper.findComponent(GlButton);
const createComponent = (propsData = { draft }) => {
- wrapper = shallowMount(localVue.extend(DraftNote), {
+ wrapper = shallowMount(DraftNote, {
store,
propsData,
- localVue,
stubs: {
NoteableNote: NoteableNoteStub,
},
@@ -54,7 +56,7 @@ describe('Batch comments draft note component', () => {
it('renders template', () => {
createComponent();
- expect(wrapper.find('.draft-pending-label').exists()).toBe(true);
+ expect(wrapper.findComponent(GlBadge).exists()).toBe(true);
const note = wrapper.find(NoteableNote);
@@ -65,7 +67,7 @@ describe('Batch comments draft note component', () => {
describe('add comment now', () => {
it('dispatches publishSingleDraft when clicking', () => {
createComponent();
- const publishNowButton = wrapper.find({ ref: 'publishNowButton' });
+ const publishNowButton = findAddCommentButton();
publishNowButton.vm.$emit('click');
expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
@@ -74,45 +76,60 @@ describe('Batch comments draft note component', () => {
);
});
- it('sets as loading when draft is publishing', (done) => {
+ it('sets as loading when draft is publishing', async () => {
createComponent();
wrapper.vm.$store.state.batchComments.currentlyPublishingDrafts.push(1);
- wrapper.vm.$nextTick(() => {
- const publishNowButton = wrapper.find({ ref: 'publishNowButton' });
+ await nextTick();
+ const publishNowButton = findAddCommentButton();
- expect(publishNowButton.props().loading).toBe(true);
+ expect(publishNowButton.props().loading).toBe(true);
+ });
- done();
- });
+ it('sets as disabled when review is publishing', async () => {
+ createComponent();
+ wrapper.vm.$store.state.batchComments.isPublishing = true;
+
+ await nextTick();
+ const publishNowButton = findAddCommentButton();
+
+ expect(publishNowButton.props().disabled).toBe(true);
+ expect(publishNowButton.props().loading).toBe(false);
+ });
+ });
+
+ describe('submit review', () => {
+ it('sets as disabled when draft is publishing', async () => {
+ createComponent();
+ wrapper.vm.$store.state.batchComments.currentlyPublishingDrafts.push(1);
+
+ await nextTick();
+ const publishNowButton = findSubmitReviewButton();
+
+ expect(publishNowButton.attributes().disabled).toBeTruthy();
});
});
describe('update', () => {
- it('dispatches updateDraft', (done) => {
+ it('dispatches updateDraft', async () => {
createComponent();
const note = wrapper.find(NoteableNote);
note.vm.$emit('handleEdit');
- wrapper.vm
- .$nextTick()
- .then(() => {
- const formData = {
- note: draft,
- noteText: 'a',
- resolveDiscussion: false,
- };
-
- note.vm.$emit('handleUpdateNote', formData);
-
- expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
- 'batchComments/updateDraft',
- formData,
- );
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ const formData = {
+ note: draft,
+ noteText: 'a',
+ resolveDiscussion: false,
+ };
+
+ note.vm.$emit('handleUpdateNote', formData);
+
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/updateDraft',
+ formData,
+ );
});
});
@@ -130,7 +147,7 @@ describe('Batch comments draft note component', () => {
});
describe('quick actions', () => {
- it('renders referenced commands', (done) => {
+ it('renders referenced commands', async () => {
createComponent();
wrapper.setProps({
draft: {
@@ -141,14 +158,11 @@ describe('Batch comments draft note component', () => {
},
});
- wrapper.vm.$nextTick(() => {
- const referencedCommands = wrapper.find('.referenced-commands');
+ await nextTick();
+ const referencedCommands = wrapper.find('.referenced-commands');
- expect(referencedCommands.exists()).toBe(true);
- expect(referencedCommands.text()).toContain('test command');
-
- done();
- });
+ expect(referencedCommands.exists()).toBe(true);
+ expect(referencedCommands.text()).toContain('test command');
});
});
diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js
index 5f74de9c014..390ef21929c 100644
--- a/spec/frontend/batch_comments/components/drafts_count_spec.js
+++ b/spec/frontend/batch_comments/components/drafts_count_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import DraftsCount from '~/batch_comments/components/drafts_count.vue';
import { createStore } from '~/batch_comments/stores';
@@ -27,17 +27,14 @@ describe('Batch comments drafts count component', () => {
expect(vm.$el.textContent).toContain('1');
});
- it('renders screen reader text', (done) => {
+ it('renders screen reader text', async () => {
const el = vm.$el.querySelector('.sr-only');
expect(el.textContent).toContain('draft');
vm.$store.state.batchComments.drafts.push('comment 2');
- vm.$nextTick(() => {
- expect(el.textContent).toContain('drafts');
-
- done();
- });
+ await nextTick();
+ expect(el.textContent).toContain('drafts');
});
});
diff --git a/spec/frontend/batch_comments/components/preview_dropdown_spec.js b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
index 5327879f003..bf3bbf4de26 100644
--- a/spec/frontend/batch_comments/components/preview_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
@@ -49,7 +49,7 @@ describe('Batch comments preview dropdown', () => {
wrapper.findByTestId('preview-item').vm.$emit('click');
- await Vue.nextTick();
+ await nextTick();
expect(setCurrentFileHash).toHaveBeenCalledWith(expect.anything(), 'hash');
expect(scrollToDraft).toHaveBeenCalledWith(expect.anything(), { id: 1, file_hash: 'hash' });
@@ -63,7 +63,7 @@ describe('Batch comments preview dropdown', () => {
wrapper.findByTestId('preview-item').vm.$emit('click');
- await Vue.nextTick();
+ await nextTick();
expect(scrollToDraft).toHaveBeenCalledWith(expect.anything(), { id: 1 });
});
diff --git a/spec/frontend/batch_comments/components/publish_button_spec.js b/spec/frontend/batch_comments/components/publish_button_spec.js
index eca424814b4..9a782ec09b6 100644
--- a/spec/frontend/batch_comments/components/publish_button_spec.js
+++ b/spec/frontend/batch_comments/components/publish_button_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import PublishButton from '~/batch_comments/components/publish_button.vue';
import { createStore } from '~/batch_comments/stores';
@@ -29,13 +29,10 @@ describe('Batch comments publish button component', () => {
expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
});
- it('sets loading when isPublishing is true', (done) => {
+ it('sets loading when isPublishing is true', async () => {
vm.$store.state.batchComments.isPublishing = true;
- vm.$nextTick(() => {
- expect(vm.$el.getAttribute('disabled')).toBe('disabled');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.getAttribute('disabled')).toBe('disabled');
});
});
diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
index bd8091c20e0..a3168931f1f 100644
--- a/spec/frontend/batch_comments/components/publish_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
@@ -1,13 +1,13 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
import { createStore } from '~/mr_notes/stores';
import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Batch comments publish dropdown component', () => {
let wrapper;
diff --git a/spec/frontend/behaviors/copy_as_gfm_spec.js b/spec/frontend/behaviors/copy_as_gfm_spec.js
index 557b609f5f9..c96db09cc76 100644
--- a/spec/frontend/behaviors/copy_as_gfm_spec.js
+++ b/spec/frontend/behaviors/copy_as_gfm_spec.js
@@ -1,3 +1,4 @@
+import waitForPromises from 'helpers/wait_for_promises';
import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
describe('CopyAsGFM', () => {
@@ -81,49 +82,40 @@ describe('CopyAsGFM', () => {
stopPropagation() {},
};
CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection);
- return clipboardData;
+
+ return waitForPromises();
};
- beforeAll((done) => {
+ beforeAll(() => {
initCopyAsGFM();
// Fake call to nodeToGfm so the import of lazy bundle happened
- CopyAsGFM.nodeToGFM(document.createElement('div'))
- .then(() => {
- done();
- })
- .catch(done.fail);
+ return CopyAsGFM.nodeToGFM(document.createElement('div'));
});
beforeEach(() => jest.spyOn(clipboardData, 'setData'));
describe('list handling', () => {
- it('uses correct gfm for unordered lists', (done) => {
+ it('uses correct gfm for unordered lists', async () => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
window.getSelection = jest.fn(() => selection);
- simulateCopy();
+ await simulateCopy();
- setImmediate(() => {
- const expectedGFM = '* List Item1\n* List Item2';
+ const expectedGFM = '* List Item1\n* List Item2';
- expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
- done();
- });
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
- it('uses correct gfm for ordered lists', (done) => {
+ it('uses correct gfm for ordered lists', async () => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
window.getSelection = jest.fn(() => selection);
- simulateCopy();
+ await simulateCopy();
- setImmediate(() => {
- const expectedGFM = '1. List Item1\n1. List Item2';
+ const expectedGFM = '1. List Item1\n1. List Item2';
- expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
- done();
- });
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
});
});
@@ -131,10 +123,9 @@ describe('CopyAsGFM', () => {
describe('CopyAsGFM.quoted', () => {
const sampleGFM = '* List 1\n* List 2\n\n`Some code`';
- it('adds quote char `> ` to each line', (done) => {
+ it('adds quote char `> ` to each line', () => {
const expectedQuotedGFM = '> * List 1\n> * List 2\n> \n> `Some code`';
expect(CopyAsGFM.quoted(sampleGFM)).toEqual(expectedQuotedGFM);
- done();
});
});
});
diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index bb3b16b4c7a..e1811247124 100644
--- a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import Mousetrap from 'mousetrap';
+import waitForPromises from 'helpers/wait_for_promises';
import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import { getSelectedFragment } from '~/lib/utils/common_utils';
@@ -13,15 +14,11 @@ describe('ShortcutsIssuable', () => {
const snippetShowFixtureName = 'snippets/show.html';
const mrShowFixtureName = 'merge_requests/merge_request_of_current_user.html';
- beforeAll((done) => {
+ beforeAll(() => {
initCopyAsGFM();
// Fake call to nodeToGfm so the import of lazy bundle happened
- CopyAsGFM.nodeToGFM(document.createElement('div'))
- .then(() => {
- done();
- })
- .catch(done.fail);
+ return CopyAsGFM.nodeToGFM(document.createElement('div'));
});
describe('replyWithSelectedText', () => {
@@ -79,22 +76,18 @@ describe('ShortcutsIssuable', () => {
stubSelection('<p>Selected text.</p>');
});
- it('leaves existing input intact', (done) => {
+ it('leaves existing input intact', async () => {
$(FORM_SELECTOR).val('This text was already here.');
expect($(FORM_SELECTOR).val()).toBe('This text was already here.');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe(
- 'This text was already here.\n\n> Selected text.\n\n',
- );
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('This text was already here.\n\n> Selected text.\n\n');
});
- it('triggers `input`', (done) => {
+ it('triggers `input`', async () => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -102,48 +95,40 @@ describe('ShortcutsIssuable', () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(triggered).toBe(true);
- done();
- });
+ await waitForPromises();
+ expect(triggered).toBe(true);
});
- it('triggers `focus`', (done) => {
+ it('triggers `focus`', async () => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(spy).toHaveBeenCalled();
- done();
- });
+ await waitForPromises();
+ expect(spy).toHaveBeenCalled();
});
});
describe('with a one-line selection', () => {
- it('quotes the selection', (done) => {
+ it('quotes the selection', async () => {
stubSelection('<p>This text has been selected.</p>');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('> This text has been selected.\n\n');
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('> This text has been selected.\n\n');
});
});
describe('with a multi-line selection', () => {
- it('quotes the selected lines as a group', (done) => {
+ it('quotes the selected lines as a group', async () => {
stubSelection(
'<p>Selected line one.</p>\n<p>Selected line two.</p>\n<p>Selected line three.</p>',
);
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe(
- '> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n',
- );
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe(
+ '> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n',
+ );
});
});
@@ -152,23 +137,19 @@ describe('ShortcutsIssuable', () => {
stubSelection('<p>Selected text.</p>', true);
});
- it('does not add anything to the input', (done) => {
+ it('does not add anything to the input', async () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('');
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('');
});
- it('triggers `focus`', (done) => {
+ it('triggers `focus`', async () => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(spy).toHaveBeenCalled();
- done();
- });
+ await waitForPromises();
+ expect(spy).toHaveBeenCalled();
});
});
@@ -177,26 +158,22 @@ describe('ShortcutsIssuable', () => {
stubSelection('<div class="md">Selected text.</div><p>Invalid selected text.</p>', true);
});
- it('only adds the valid part to the input', (done) => {
+ it('only adds the valid part to the input', async () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
});
- it('triggers `focus`', (done) => {
+ it('triggers `focus`', async () => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(spy).toHaveBeenCalled();
- done();
- });
+ await waitForPromises();
+ expect(spy).toHaveBeenCalled();
});
- it('triggers `input`', (done) => {
+ it('triggers `input`', async () => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -204,10 +181,8 @@ describe('ShortcutsIssuable', () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(triggered).toBe(true);
- done();
- });
+ await waitForPromises();
+ expect(triggered).toBe(true);
});
});
@@ -231,26 +206,22 @@ describe('ShortcutsIssuable', () => {
});
});
- it('adds the quoted selection to the input', (done) => {
+ it('adds the quoted selection to the input', async () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('> *Selected text.*\n\n');
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('> *Selected text.*\n\n');
});
- it('triggers `focus`', (done) => {
+ it('triggers `focus`', async () => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(spy).toHaveBeenCalled();
- done();
- });
+ await waitForPromises();
+ expect(spy).toHaveBeenCalled();
});
- it('triggers `input`', (done) => {
+ it('triggers `input`', async () => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -258,10 +229,8 @@ describe('ShortcutsIssuable', () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(triggered).toBe(true);
- done();
- });
+ await waitForPromises();
+ expect(triggered).toBe(true);
});
});
@@ -285,36 +254,29 @@ describe('ShortcutsIssuable', () => {
});
});
- it('does not add anything to the input', (done) => {
+ it('does not add anything to the input', async () => {
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('');
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('');
});
- it('triggers `focus`', (done) => {
+ it('triggers `focus`', async () => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect(spy).toHaveBeenCalled();
- done();
- });
+ await waitForPromises();
+ expect(spy).toHaveBeenCalled();
});
});
describe('with a valid selection with no text content', () => {
- it('returns the proper markdown', (done) => {
+ it('returns the proper markdown', async () => {
stubSelection('<img src="https://gitlab.com/logo.png" alt="logo" />');
ShortcutsIssuable.replyWithSelectedText(true);
- setImmediate(() => {
- expect($(FORM_SELECTOR).val()).toBe('> ![logo](https://gitlab.com/logo.png)\n\n');
-
- done();
- });
+ await waitForPromises();
+ expect($(FORM_SELECTOR).val()).toBe('> ![logo](https://gitlab.com/logo.png)\n\n');
});
});
});
diff --git a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
index 22bec77276b..b3d93906445 100644
--- a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
+++ b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
@@ -13,6 +13,7 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
<blob-filepath-stub
blob="[object Object]"
+ showpath="true"
/>
</div>
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index 910fc5c946d..b1ce0e9a4c5 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -1,5 +1,6 @@
import { GlFormInput, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import BlobEditHeader from '~/blob/components/blob_edit_header.vue';
describe('Blob Header Editing', () => {
@@ -40,7 +41,7 @@ describe('Blob Header Editing', () => {
});
describe('functionality', () => {
- it('emits input event when the blob name is changed', () => {
+ it('emits input event when the blob name is changed', async () => {
const inputComponent = wrapper.find(GlFormInput);
const newValue = 'bar.txt';
@@ -51,9 +52,8 @@ describe('Blob Header Editing', () => {
});
inputComponent.vm.$emit('change');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().input[0]).toEqual([newValue]);
- });
+ await nextTick();
+ expect(wrapper.emitted().input[0]).toEqual([newValue]);
});
});
diff --git a/spec/frontend/blob/components/blob_header_default_actions_spec.js b/spec/frontend/blob/components/blob_header_default_actions_spec.js
index e321bb41774..af605b257de 100644
--- a/spec/frontend/blob/components/blob_header_default_actions_spec.js
+++ b/spec/frontend/blob/components/blob_header_default_actions_spec.js
@@ -1,13 +1,13 @@
import { GlButtonGroup, GlButton } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
import BlobHeaderActions from '~/blob/components/blob_header_default_actions.vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
BTN_COPY_CONTENTS_TITLE,
BTN_DOWNLOAD_TITLE,
BTN_RAW_TITLE,
RICH_BLOB_VIEWER,
} from '~/blob/components/constants';
-import { Blob } from './mock_data';
+import { Blob, mockEnvironmentName, mockEnvironmentPath } from './mock_data';
describe('Blob Header Default Actions', () => {
let wrapper;
@@ -17,7 +17,7 @@ describe('Blob Header Default Actions', () => {
const blobHash = 'foo-bar';
function createComponent(propsData = {}) {
- wrapper = mount(BlobHeaderActions, {
+ wrapper = shallowMountExtended(BlobHeaderActions, {
provide: {
blobHash,
},
@@ -39,8 +39,8 @@ describe('Blob Header Default Actions', () => {
});
describe('renders', () => {
- const findCopyButton = () => wrapper.find('[data-testid="copyContentsButton"]');
- const findViewRawButton = () => wrapper.find('[data-testid="viewRawButton"]');
+ const findCopyButton = () => wrapper.findByTestId('copyContentsButton');
+ const findViewRawButton = () => wrapper.findByTestId('viewRawButton');
it('gl-button-group component', () => {
expect(btnGroup.exists()).toBe(true);
@@ -89,4 +89,37 @@ describe('Blob Header Default Actions', () => {
expect(findViewRawButton().exists()).toBe(false);
});
});
+
+ describe('view on environment button', () => {
+ const findEnvironmentButton = () => wrapper.findByTestId('environment');
+
+ it.each`
+ environmentName | environmentPath | isVisible
+ ${null} | ${null} | ${false}
+ ${null} | ${mockEnvironmentPath} | ${false}
+ ${mockEnvironmentName} | ${null} | ${false}
+ ${mockEnvironmentName} | ${mockEnvironmentPath} | ${true}
+ `(
+ 'when environmentName is $environmentName and environmentPath is $environmentPath',
+ ({ environmentName, environmentPath, isVisible }) => {
+ createComponent({ environmentName, environmentPath });
+
+ expect(findEnvironmentButton().exists()).toBe(isVisible);
+ },
+ );
+
+ it('renders the correct attributes', () => {
+ createComponent({
+ environmentName: mockEnvironmentName,
+ environmentPath: mockEnvironmentPath,
+ });
+
+ expect(findEnvironmentButton().attributes()).toMatchObject({
+ title: `View on ${mockEnvironmentName}`,
+ href: mockEnvironmentPath,
+ });
+
+ expect(findEnvironmentButton().props('icon')).toBe('external-link');
+ });
+ });
});
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index bd81b1594bf..8e1b03c6126 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -1,4 +1,5 @@
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import DefaultActions from '~/blob/components/blob_header_default_actions.vue';
import BlobFilepath from '~/blob/components/blob_header_filepath.vue';
@@ -139,26 +140,24 @@ describe('Blob Header Default Actions', () => {
expect(wrapper.vm.viewer).toBe(null);
});
- it('watches the changes in viewer data and emits event when the change is registered', () => {
+ it('watches the changes in viewer data and emits event when the change is registered', async () => {
factory();
jest.spyOn(wrapper.vm, '$emit');
wrapper.vm.viewer = newViewer;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('viewer-changed', newViewer);
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('viewer-changed', newViewer);
});
- it('does not emit event if the switcher is not rendered', () => {
+ it('does not emit event if the switcher is not rendered', async () => {
factory(true);
expect(wrapper.vm.showViewerSwitcher).toBe(false);
jest.spyOn(wrapper.vm, '$emit');
wrapper.vm.viewer = newViewer;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.$emit).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
index 9a560ec11f7..91baaf3ea69 100644
--- a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
+++ b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
@@ -1,5 +1,6 @@
import { GlButtonGroup, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import BlobHeaderViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
import {
RICH_BLOB_VIEWER,
@@ -72,26 +73,24 @@ describe('Blob Header Viewer Switcher', () => {
expect(wrapper.vm.$emit).not.toHaveBeenCalled();
});
- it('emits an event when a Rich Viewer button is clicked', () => {
+ it('emits an event when a Rich Viewer button is clicked', async () => {
factory();
expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER);
richBtn.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', RICH_BLOB_VIEWER);
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', RICH_BLOB_VIEWER);
});
- it('emits an event when a Simple Viewer button is clicked', () => {
+ it('emits an event when a Simple Viewer button is clicked', async () => {
factory({
value: RICH_BLOB_VIEWER,
});
simpleBtn.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', SIMPLE_BLOB_VIEWER);
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', SIMPLE_BLOB_VIEWER);
});
});
});
diff --git a/spec/frontend/blob/components/mock_data.js b/spec/frontend/blob/components/mock_data.js
index 95789ca13cb..9a345921f16 100644
--- a/spec/frontend/blob/components/mock_data.js
+++ b/spec/frontend/blob/components/mock_data.js
@@ -55,3 +55,6 @@ export const SimpleBlobContentMock = {
path: 'foo.js',
plainData: 'Plain',
};
+
+export const mockEnvironmentName = 'my.testing.environment';
+export const mockEnvironmentPath = 'https://my.testing.environment';
diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js
index 9e9f866d40c..fe55a537b89 100644
--- a/spec/frontend/blob/viewer/index_spec.js
+++ b/spec/frontend/blob/viewer/index_spec.js
@@ -41,34 +41,30 @@ describe('Blob viewer', () => {
window.location.hash = '';
});
- it('loads source file after switching views', (done) => {
+ it('loads source file after switching views', async () => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
- setImmediate(() => {
- expect(
- document
- .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
- .classList.contains('hidden'),
- ).toBeFalsy();
+ await axios.waitForAll();
- done();
- });
+ expect(
+ document
+ .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
+ .classList.contains('hidden'),
+ ).toBeFalsy();
});
- it('loads source file when line number is in hash', (done) => {
+ it('loads source file when line number is in hash', async () => {
window.location.hash = '#L1';
new BlobViewer();
- setImmediate(() => {
- expect(
- document
- .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
- .classList.contains('hidden'),
- ).toBeFalsy();
+ await axios.waitForAll();
- done();
- });
+ expect(
+ document
+ .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
+ .classList.contains('hidden'),
+ ).toBeFalsy();
});
it('doesnt reload file if already loaded', () => {
@@ -123,24 +119,20 @@ describe('Blob viewer', () => {
expect(copyButton.blur).not.toHaveBeenCalled();
});
- it('enables after switching to simple view', (done) => {
+ it('enables after switching to simple view', async () => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
- setImmediate(() => {
- expect(copyButton.classList.contains('disabled')).toBeFalsy();
+ await axios.waitForAll();
- done();
- });
+ expect(copyButton.classList.contains('disabled')).toBeFalsy();
});
- it('updates tooltip after switching to simple view', (done) => {
+ it('updates tooltip after switching to simple view', async () => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
- setImmediate(() => {
- expect(copyButtonTooltip.getAttribute('title')).toBe('Copy file contents');
+ await axios.waitForAll();
- done();
- });
+ expect(copyButtonTooltip.getAttribute('title')).toBe('Copy file contents');
});
});
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index e0446811f64..677978d31ca 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -1,15 +1,13 @@
import { GlLabel, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
import { range } from 'lodash';
import Vuex from 'vuex';
-import setWindowLocation from 'helpers/set_window_location_helper';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
import BoardCardInner from '~/boards/components/board_card_inner.vue';
import { issuableTypes } from '~/boards/constants';
-import eventHub from '~/boards/eventhub';
import defaultStore from '~/boards/stores';
-import { updateHistory } from '~/lib/utils/url_utility';
import { mockLabelList, mockIssue, mockIssueFullPath } from './mock_data';
jest.mock('~/lib/utils/url_utility');
@@ -53,6 +51,7 @@ describe('Board card component', () => {
state: {
...defaultStore.state,
issuableType: issuableTypes.issue,
+ isShowingLabels: true,
},
getters: {
isGroupBoard: () => true,
@@ -261,7 +260,7 @@ describe('Board card component', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
'test_image_from_avatar_url?width=24',
@@ -376,7 +375,7 @@ describe('Board card component', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-card-assignee .avatar-counter').text().trim()).toEqual('99+');
});
@@ -399,58 +398,17 @@ describe('Board card component', () => {
it('does not render label if label does not have an ID', async () => {
wrapper.setProps({ item: { ...issue, labels: [label1, { title: 'closed' }] } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAll(GlLabel).length).toBe(1);
expect(wrapper.text()).not.toContain('closed');
});
- });
-
- describe('filterByLabel method', () => {
- beforeEach(() => {
- wrapper.setProps({
- updateFilters: true,
- });
- });
-
- describe('when selected label is not in the filter', () => {
- beforeEach(() => {
- jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
- setWindowLocation('?');
- wrapper.vm.filterByLabel(label1);
- });
-
- it('calls updateHistory', () => {
- expect(updateHistory).toHaveBeenCalledTimes(1);
- });
-
- it('dispatches performSearch vuex action', () => {
- expect(wrapper.vm.performSearch).toHaveBeenCalledTimes(1);
- });
-
- it('emits updateTokens event', () => {
- expect(eventHub.$emit).toHaveBeenCalledTimes(1);
- expect(eventHub.$emit).toHaveBeenCalledWith('updateTokens');
- });
- });
-
- describe('when selected label is already in the filter', () => {
- beforeEach(() => {
- jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
- setWindowLocation('?label_name[]=testing%20123');
- wrapper.vm.filterByLabel(label1);
- });
-
- it('does not call updateHistory', () => {
- expect(updateHistory).not.toHaveBeenCalled();
- });
- it('does not dispatch performSearch vuex action', () => {
- expect(wrapper.vm.performSearch).not.toHaveBeenCalled();
- });
-
- it('does not emit updateTokens event', () => {
- expect(eventHub.$emit).not.toHaveBeenCalled();
+ describe('when label params arent set', () => {
+ it('passes the right target to GlLabel', () => {
+ expect(wrapper.findAll(GlLabel).at(0).props('target')).toEqual(
+ '?label_name[]=testing%20123',
+ );
});
});
});
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index d0f14bd37c1..04192489817 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
@@ -33,9 +34,8 @@ export default function createComponent({
},
issuesCount,
} = {}) {
- const localVue = createLocalVue();
- localVue.use(VueApollo);
- localVue.use(Vuex);
+ Vue.use(VueApollo);
+ Vue.use(Vuex);
const fakeApollo = createMockApollo([
[listQuery, jest.fn().mockResolvedValue(boardListQueryResponse(issuesCount))],
@@ -85,7 +85,6 @@ export default function createComponent({
const component = shallowMount(BoardList, {
apolloProvider: fakeApollo,
- localVue,
store,
propsData: {
disabled: false,
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 1981ed5ab7f..fd9d2b6823d 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -1,6 +1,8 @@
import Draggable from 'vuedraggable';
+import { nextTick } from 'vue';
import { DraggableItemTypes } from 'ee_else_ce/boards/constants';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
+import waitForPromises from 'helpers/wait_for_promises';
import createComponent from 'jest/boards/board_list_helper';
import BoardCard from '~/boards/components/board_card.vue';
import eventHub from '~/boards/eventhub';
@@ -64,14 +66,14 @@ describe('Board list component', () => {
it('shows new issue form', async () => {
wrapper.vm.toggleForm();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
});
it('shows new issue form after eventhub event', async () => {
eventHub.$emit(`toggle-issue-form-${wrapper.vm.list.id}`);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
});
@@ -85,7 +87,7 @@ describe('Board list component', () => {
it('shows count list item', async () => {
wrapper.vm.showCount = true;
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-list-count').exists()).toBe(true);
expect(wrapper.find('.board-list-count').text()).toBe('Showing all issues');
@@ -94,7 +96,7 @@ describe('Board list component', () => {
it('sets data attribute with invalid id', async () => {
wrapper.vm.showCount = true;
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.board-list-count').attributes('data-issue-id')).toBe('-1');
});
});
@@ -104,10 +106,6 @@ describe('Board list component', () => {
fetchItemsForList: jest.fn(),
};
- beforeEach(() => {
- wrapper = createComponent();
- });
-
it('does not load issues if already loading', () => {
wrapper = createComponent({
actions,
@@ -126,20 +124,23 @@ describe('Board list component', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findIssueCountLoadingIcon().exists()).toBe(true);
});
it('shows how many more issues to load', async () => {
- // wrapper.vm.showCount = true;
wrapper = createComponent({
data: {
showCount: true,
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
+ await waitForPromises();
+ await nextTick();
+ await nextTick();
+
expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
});
});
@@ -155,7 +156,7 @@ describe('Board list component', () => {
it('sets background to bg-danger-100', async () => {
wrapper.setProps({ list: { issuesCount: 4, maxIssueCount: 3 } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.bg-danger-100').exists()).toBe(true);
});
});
diff --git a/spec/frontend/boards/components/board_add_new_column_trigger_spec.js b/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
index c35f2463f69..7dd02bf1d35 100644
--- a/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
+++ b/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
@@ -1,5 +1,5 @@
import { GlButton } from '@gitlab/ui';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
@@ -49,7 +49,7 @@ describe('BoardAddNewColumnTrigger', () => {
it('shows the tooltip', async () => {
wrapper.find(GlButton).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
const tooltip = findTooltipText();
diff --git a/spec/frontend/boards/components/board_blocked_icon_spec.js b/spec/frontend/boards/components/board_blocked_icon_spec.js
index 7b04942f056..7a5c49bd488 100644
--- a/spec/frontend/boards/components/board_blocked_icon_spec.js
+++ b/spec/frontend/boards/components/board_blocked_icon_spec.js
@@ -1,6 +1,6 @@
import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -39,7 +39,7 @@ describe('BoardBlockedIcon', () => {
const mouseenter = async () => {
findGlIcon().vm.$emit('mouseenter');
- await wrapper.vm.$nextTick();
+ await nextTick();
await waitForApollo();
};
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 3af173aa18c..aad89cf8261 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -1,6 +1,6 @@
import { GlLabel } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import BoardCard from '~/boards/components/board_card.vue';
@@ -65,12 +65,12 @@ describe('Board card', () => {
const selectCard = async () => {
wrapper.trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const multiSelectCard = async () => {
wrapper.trigger('click', { ctrlKey: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index a8398a138ba..85ba703a6ee 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -120,7 +120,7 @@ describe('BoardFilteredSearch', () => {
{ type: 'author', value: { data: 'root', operator: '=' } },
{ type: 'assignee', value: { data: 'root', operator: '=' } },
{ type: 'label', value: { data: 'label', operator: '=' } },
- { type: 'label', value: { data: 'label2', operator: '=' } },
+ { type: 'label', value: { data: 'label&2', operator: '=' } },
{ type: 'milestone', value: { data: 'New Milestone', operator: '=' } },
{ type: 'type', value: { data: 'INCIDENT', operator: '=' } },
{ type: 'weight', value: { data: '2', operator: '=' } },
@@ -134,7 +134,7 @@ describe('BoardFilteredSearch', () => {
title: '',
replace: true,
url:
- 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label2&assignee_username=root&milestone_title=New+Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0',
+ 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0',
});
});
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index 692fd3ec555..5678da2a246 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -130,7 +130,7 @@ describe('BoardForm', () => {
it('passes correct primary action text and variant', () => {
expect(findModalActionPrimary().text).toBe('Create board');
- expect(findModalActionPrimary().attributes[0].variant).toBe('success');
+ expect(findModalActionPrimary().attributes[0].variant).toBe('confirm');
});
it('does not render delete confirmation message', () => {
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 8cc0ad5f30c..14870ec76a2 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -148,7 +148,7 @@ describe('Board List Header Component', () => {
findCaret().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(toggleListCollapsedSpy).toHaveBeenCalledTimes(1);
});
@@ -156,7 +156,7 @@ describe('Board List Header Component', () => {
createComponent({ withLocalStorage: false, currentUserId: 1 });
findCaret().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(updateListSpy).toHaveBeenCalledTimes(1);
expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.collapsed`)).toBe(null);
@@ -168,7 +168,7 @@ describe('Board List Header Component', () => {
});
findCaret().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(updateListSpy).not.toHaveBeenCalled();
expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.collapsed`)).toBe(String(isCollapsed()));
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
index 57ccebf3676..8b0100d069a 100644
--- a/spec/frontend/boards/components/board_new_issue_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -1,15 +1,14 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import BoardNewIssue from '~/boards/components/board_new_issue.vue';
import BoardNewItem from '~/boards/components/board_new_item.vue';
import ProjectSelect from '~/boards/components/project_select.vue';
import eventHub from '~/boards/eventhub';
-import { mockList, mockGroupProjects } from '../mock_data';
+import { mockList, mockGroupProjects, mockIssue, mockIssue2 } from '../mock_data';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
const addListNewIssuesSpy = jest.fn().mockResolvedValue();
const mockActions = { addListNewIssue: addListNewIssuesSpy };
@@ -17,10 +16,9 @@ const mockActions = { addListNewIssue: addListNewIssuesSpy };
const createComponent = ({
state = { selectedProject: mockGroupProjects[0], fullPath: mockGroupProjects[0].fullPath },
actions = mockActions,
- getters = { isGroupBoard: () => true, isProjectBoard: () => false },
+ getters = { isGroupBoard: () => true, getBoardItemsByList: () => () => [] },
} = {}) =>
shallowMount(BoardNewIssue, {
- localVue,
store: new Vuex.Store({
state,
actions,
@@ -47,7 +45,7 @@ describe('Issue boards new issue form', () => {
beforeEach(async () => {
wrapper = createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -68,7 +66,7 @@ describe('Issue boards new issue form', () => {
it('calls addListNewIssue action when `board-new-item` emits form-submit event', async () => {
findBoardNewItem().vm.$emit('form-submit', { title: 'Foo' });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(addListNewIssuesSpy).toHaveBeenCalledWith(expect.any(Object), {
list: mockList,
issueInput: {
@@ -77,15 +75,44 @@ describe('Issue boards new issue form', () => {
assigneeIds: [],
milestoneId: undefined,
projectPath: mockGroupProjects[0].fullPath,
+ moveAfterId: undefined,
},
});
});
+ describe('when list has an existing issues', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ getters: {
+ isGroupBoard: () => true,
+ getBoardItemsByList: () => () => [mockIssue, mockIssue2],
+ },
+ });
+ });
+
+ it('it uses the first issue ID as moveAfterId', async () => {
+ findBoardNewItem().vm.$emit('form-submit', { title: 'Foo' });
+
+ await nextTick();
+ expect(addListNewIssuesSpy).toHaveBeenCalledWith(expect.any(Object), {
+ list: mockList,
+ issueInput: {
+ title: 'Foo',
+ labelIds: [],
+ assigneeIds: [],
+ milestoneId: undefined,
+ projectPath: mockGroupProjects[0].fullPath,
+ moveAfterId: mockIssue.id,
+ },
+ });
+ });
+ });
+
it('emits event `toggle-issue-form` with current list Id suffix on eventHub when `board-new-item` emits form-cancel event', async () => {
jest.spyOn(eventHub, '$emit').mockImplementation();
findBoardNewItem().vm.$emit('form-cancel');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(eventHub.$emit).toHaveBeenCalledWith(`toggle-issue-form-${mockList.id}`);
});
@@ -101,7 +128,7 @@ describe('Issue boards new issue form', () => {
describe('when in project issue board', () => {
beforeEach(() => {
wrapper = createComponent({
- getters: { isGroupBoard: () => false, isProjectBoard: () => true },
+ getters: { isGroupBoard: () => false },
});
});
diff --git a/spec/frontend/boards/components/board_new_item_spec.js b/spec/frontend/boards/components/board_new_item_spec.js
index 0151d9c1c14..86cebc8a719 100644
--- a/spec/frontend/boards/components/board_new_item_spec.js
+++ b/spec/frontend/boards/components/board_new_item_spec.js
@@ -1,4 +1,5 @@
import { GlForm, GlFormInput, GlButton } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import BoardNewItem from '~/boards/components/board_new_item.vue';
@@ -39,6 +40,27 @@ describe('BoardNewItem', () => {
});
describe('template', () => {
+ describe('when the user provides a valid input', () => {
+ it('finds an enabled create button', async () => {
+ expect(wrapper.findByTestId('create-button').props('disabled')).toBe(true);
+
+ wrapper.find(GlFormInput).vm.$emit('input', 'hello');
+ await nextTick();
+
+ expect(wrapper.findByTestId('create-button').props('disabled')).toBe(false);
+ });
+ });
+
+ describe('when the user types in a string with only spaces', () => {
+ it('disables the Create Issue button', async () => {
+ wrapper.find(GlFormInput).vm.$emit('input', ' ');
+
+ await nextTick();
+
+ expect(wrapper.findByTestId('create-button').props('disabled')).toBe(true);
+ });
+ });
+
it('renders gl-form component', () => {
expect(wrapper.findComponent(GlForm).exists()).toBe(true);
});
@@ -80,6 +102,19 @@ describe('BoardNewItem', () => {
]);
});
+ it('emits `form-submit` event with trimmed title', async () => {
+ titleInput().setValue(' Foo ');
+
+ await glForm().trigger('submit');
+
+ expect(wrapper.emitted('form-submit')[0]).toEqual([
+ {
+ title: 'Foo',
+ list: mockList,
+ },
+ ]);
+ });
+
it('emits `scroll-board-list-` event with list.id on eventHub when `submit` is triggered on gl-form', async () => {
jest.spyOn(eventHub, '$emit').mockImplementation();
await glForm().trigger('submit');
@@ -90,7 +125,7 @@ describe('BoardNewItem', () => {
it('emits `form-cancel` event and clears title value when `reset` is triggered on gl-form', async () => {
titleInput().setValue('Foo');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(titleInput().element.value).toBe('Foo');
await glForm().trigger('reset');
diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js
index 46dd109ffb1..7f40c426b30 100644
--- a/spec/frontend/boards/components/board_settings_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js
@@ -1,8 +1,9 @@
-import { GlDrawer, GlLabel } from '@gitlab/ui';
+import { GlDrawer, GlLabel, GlModal, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { MountingPortal } from 'portal-vue';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
@@ -20,8 +21,7 @@ describe('BoardSettingsSidebar', () => {
const labelTitle = mockLabelList.label.title;
const labelColor = mockLabelList.label.color;
const listId = mockLabelList.id;
-
- const findRemoveButton = () => wrapper.findByTestId('remove-list');
+ const modalID = 'board-settings-sidebar-modal';
const createComponent = ({
canAdminList = false,
@@ -46,6 +46,9 @@ describe('BoardSettingsSidebar', () => {
canAdminList,
scopedLabelsAvailable: false,
},
+ directives: {
+ GlModal: createMockDirective(),
+ },
stubs: {
GlDrawer: stubComponent(GlDrawer, {
template: '<div><slot name="header"></slot><slot></slot></div>',
@@ -56,6 +59,8 @@ describe('BoardSettingsSidebar', () => {
};
const findLabel = () => wrapper.find(GlLabel);
const findDrawer = () => wrapper.find(GlDrawer);
+ const findModal = () => wrapper.find(GlModal);
+ const findRemoveButton = () => wrapper.find(GlButton);
afterEach(() => {
jest.restoreAllMocks();
@@ -86,7 +91,7 @@ describe('BoardSettingsSidebar', () => {
findDrawer().vm.$emit('close');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlDrawer).exists()).toBe(false);
});
@@ -96,7 +101,7 @@ describe('BoardSettingsSidebar', () => {
sidebarEventHub.$emit('sidebar.closeAll');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlDrawer).exists()).toBe(false);
});
@@ -161,5 +166,16 @@ describe('BoardSettingsSidebar', () => {
expect(findRemoveButton().exists()).toBe(true);
});
+
+ it('has the correct ID on the button', () => {
+ createComponent({ canAdminList: true, activeId: listId, list: mockLabelList });
+ const binding = getBinding(findRemoveButton().element, 'gl-modal');
+ expect(binding.value).toBe(modalID);
+ });
+
+ it('has the correct ID on the modal', () => {
+ createComponent({ canAdminList: true, activeId: listId, list: mockLabelList });
+ expect(findModal().props('modalId')).toBe(modalID);
+ });
});
});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index 9cf7c5774bf..26a5bf34595 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -1,43 +1,40 @@
import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants';
import BoardsSelector from '~/boards/components/boards_selector.vue';
+import { BoardType } from '~/boards/constants';
import groupBoardQuery from '~/boards/graphql/group_board.query.graphql';
import projectBoardQuery from '~/boards/graphql/project_board.query.graphql';
+import groupBoardsQuery from '~/boards/graphql/group_boards.query.graphql';
+import projectBoardsQuery from '~/boards/graphql/project_boards.query.graphql';
+import groupRecentBoardsQuery from '~/boards/graphql/group_recent_boards.query.graphql';
+import projectRecentBoardsQuery from '~/boards/graphql/project_recent_boards.query.graphql';
import defaultStore from '~/boards/stores';
-import axios from '~/lib/utils/axios_utils';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { mockGroupBoardResponse, mockProjectBoardResponse } from '../mock_data';
+import {
+ mockGroupBoardResponse,
+ mockProjectBoardResponse,
+ mockGroupAllBoardsResponse,
+ mockProjectAllBoardsResponse,
+ mockGroupRecentBoardsResponse,
+ mockProjectRecentBoardsResponse,
+ mockSmallProjectAllBoardsResponse,
+ mockEmptyProjectRecentBoardsResponse,
+ boards,
+ recentIssueBoards,
+} from '../mock_data';
const throttleDuration = 1;
Vue.use(VueApollo);
-function boardGenerator(n) {
- return new Array(n).fill().map((board, index) => {
- const id = `${index}`;
- const name = `board${id}`;
-
- return {
- id,
- name,
- };
- });
-}
-
describe('BoardsSelector', () => {
let wrapper;
- let allBoardsResponse;
- let recentBoardsResponse;
- let mock;
let fakeApollo;
let store;
- const boards = boardGenerator(20);
- const recentBoards = boardGenerator(5);
const createStore = ({ isGroupBoard = false, isProjectBoard = false } = {}) => {
store = new Vuex.Store({
@@ -63,17 +60,43 @@ describe('BoardsSelector', () => {
};
const getDropdownItems = () => wrapper.findAll('.js-dropdown-item');
- const getDropdownHeaders = () => wrapper.findAll(GlDropdownSectionHeader);
- const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findDropdown = () => wrapper.find(GlDropdown);
+ const getDropdownHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
+ const getLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
const projectBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockProjectBoardResponse);
const groupBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockGroupBoardResponse);
- const createComponent = () => {
+ const projectBoardsQueryHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(mockProjectAllBoardsResponse);
+ const groupBoardsQueryHandlerSuccess = jest.fn().mockResolvedValue(mockGroupAllBoardsResponse);
+
+ const projectRecentBoardsQueryHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(mockProjectRecentBoardsResponse);
+ const groupRecentBoardsQueryHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(mockGroupRecentBoardsResponse);
+
+ const smallBoardsQueryHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(mockSmallProjectAllBoardsResponse);
+ const emptyRecentBoardsQueryHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(mockEmptyProjectRecentBoardsResponse);
+
+ const createComponent = ({
+ projectBoardsQueryHandler = projectBoardsQueryHandlerSuccess,
+ projectRecentBoardsQueryHandler = projectRecentBoardsQueryHandlerSuccess,
+ } = {}) => {
fakeApollo = createMockApollo([
[projectBoardQuery, projectBoardQueryHandlerSuccess],
[groupBoardQuery, groupBoardQueryHandlerSuccess],
+ [projectBoardsQuery, projectBoardsQueryHandler],
+ [groupBoardsQuery, groupBoardsQueryHandlerSuccess],
+ [projectRecentBoardsQuery, projectRecentBoardsQueryHandler],
+ [groupRecentBoardsQuery, groupRecentBoardsQueryHandlerSuccess],
]);
wrapper = mount(BoardsSelector, {
@@ -91,67 +114,34 @@ describe('BoardsSelector', () => {
attachTo: document.body,
provide: {
fullPath: '',
- recentBoardsEndpoint: `${TEST_HOST}/recent`,
},
});
-
- wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- [options.loadingKey]: true,
- });
- });
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
- mock.restore();
+ fakeApollo = null;
});
- describe('fetching all boards', () => {
+ describe('template', () => {
beforeEach(() => {
- mock = new MockAdapter(axios);
-
- allBoardsResponse = Promise.resolve({
- data: {
- group: {
- boards: {
- edges: boards.map((board) => ({ node: board })),
- },
- },
- },
- });
- recentBoardsResponse = Promise.resolve({
- data: recentBoards,
- });
-
- createStore();
+ createStore({ isProjectBoard: true });
createComponent();
-
- mock.onGet(`${TEST_HOST}/recent`).replyOnce(200, recentBoards);
});
describe('loading', () => {
- beforeEach(async () => {
- // Wait for current board to be loaded
- await nextTick();
-
- // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
- findDropdown().vm.$emit('show');
- });
-
// we are testing loading state, so don't resolve responses until after the tests
afterEach(async () => {
- await Promise.all([allBoardsResponse, recentBoardsResponse]);
await nextTick();
});
it('shows loading spinner', () => {
+ // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
+ findDropdown().vm.$emit('show');
+
+ expect(getLoadingIcon().exists()).toBe(true);
expect(getDropdownHeaders()).toHaveLength(0);
expect(getDropdownItems()).toHaveLength(0);
- expect(getLoadingIcon().exists()).toBe(true);
});
});
@@ -163,16 +153,13 @@ describe('BoardsSelector', () => {
// Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
findDropdown().vm.$emit('show');
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- await wrapper.setData({
- loadingBoards: false,
- loadingRecentBoards: false,
- });
- await Promise.all([allBoardsResponse, recentBoardsResponse]);
await nextTick();
});
+ it('fetches all issue boards', () => {
+ expect(projectBoardsQueryHandlerSuccess).toHaveBeenCalled();
+ });
+
it('hides loading spinner', async () => {
await nextTick();
expect(getLoadingIcon().exists()).toBe(false);
@@ -180,22 +167,17 @@ describe('BoardsSelector', () => {
describe('filtering', () => {
beforeEach(async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- boards,
- });
-
await nextTick();
});
it('shows all boards without filtering', () => {
- expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
+ expect(getDropdownItems()).toHaveLength(boards.length + recentIssueBoards.length);
});
it('shows only matching boards when filtering', async () => {
const filterTerm = 'board1';
- const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
+ const expectedCount = boards.filter((board) => board.node.name.includes(filterTerm))
+ .length;
fillSearchBox(filterTerm);
@@ -214,32 +196,21 @@ describe('BoardsSelector', () => {
describe('recent boards section', () => {
it('shows only when boards are greater than 10', async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- boards,
- });
-
await nextTick();
+ expect(projectRecentBoardsQueryHandlerSuccess).toHaveBeenCalled();
expect(getDropdownHeaders()).toHaveLength(2);
});
it('does not show when boards are less than 10', async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- boards: boards.slice(0, 5),
- });
+ createComponent({ projectBoardsQueryHandler: smallBoardsQueryHandlerSuccess });
await nextTick();
expect(getDropdownHeaders()).toHaveLength(0);
});
- it('does not show when recentBoards api returns empty array', async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- recentBoards: [],
+ it('does not show when recentIssueBoards api returns empty array', async () => {
+ createComponent({
+ projectRecentBoardsQueryHandler: emptyRecentBoardsQueryHandlerSuccess,
});
await nextTick();
@@ -256,15 +227,39 @@ describe('BoardsSelector', () => {
});
});
+ describe('fetching all boards', () => {
+ it.each`
+ boardType | queryHandler | notCalledHandler
+ ${BoardType.group} | ${groupBoardsQueryHandlerSuccess} | ${projectBoardsQueryHandlerSuccess}
+ ${BoardType.project} | ${projectBoardsQueryHandlerSuccess} | ${groupBoardsQueryHandlerSuccess}
+ `('fetches $boardType boards', async ({ boardType, queryHandler, notCalledHandler }) => {
+ createStore({
+ isProjectBoard: boardType === BoardType.project,
+ isGroupBoard: boardType === BoardType.group,
+ });
+ createComponent();
+
+ await nextTick();
+
+ // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
+ findDropdown().vm.$emit('show');
+
+ await nextTick();
+
+ expect(queryHandler).toHaveBeenCalled();
+ expect(notCalledHandler).not.toHaveBeenCalled();
+ });
+ });
+
describe('fetching current board', () => {
it.each`
- boardType | queryHandler | notCalledHandler
- ${'group'} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess}
- ${'project'} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess}
+ boardType | queryHandler | notCalledHandler
+ ${BoardType.group} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess}
+ ${BoardType.project} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess}
`('fetches $boardType board', async ({ boardType, queryHandler, notCalledHandler }) => {
createStore({
- isProjectBoard: boardType === 'project',
- isGroupBoard: boardType === 'group',
+ isProjectBoard: boardType === BoardType.project,
+ isGroupBoard: boardType === BoardType.group,
});
createComponent();
diff --git a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
index 12e9a9ba365..0c76c711b3a 100644
--- a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import BoardSidebarItem from '~/boards/components/sidebar/board_editable_item.vue';
describe('boards sidebar remove issue', () => {
@@ -79,17 +80,16 @@ describe('boards sidebar remove issue', () => {
createComponent({ canUpdate: true, slots });
findEditButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findCollapsed().isVisible()).toBe(false);
- expect(findExpanded().isVisible()).toBe(true);
- });
+ await nextTick();
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(true);
});
it('hides the header while editing if `toggleHeader` is true', async () => {
createComponent({ canUpdate: true, props: { toggleHeader: true } });
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEditButton().isVisible()).toBe(false);
expect(findTitle().isVisible()).toBe(false);
@@ -101,14 +101,14 @@ describe('boards sidebar remove issue', () => {
beforeEach(async () => {
createComponent({ canUpdate: true });
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('hides expanded section and displays collapsed section', async () => {
expect(findExpanded().isVisible()).toBe(true);
document.body.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCollapsed().isVisible()).toBe(true);
expect(findExpanded().isVisible()).toBe(false);
@@ -117,7 +117,7 @@ describe('boards sidebar remove issue', () => {
it('emits events', async () => {
document.body.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().close).toHaveLength(1);
expect(wrapper.emitted()['off-click']).toHaveLength(1);
@@ -129,7 +129,7 @@ describe('boards sidebar remove issue', () => {
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().open.length).toBe(1);
});
@@ -139,7 +139,7 @@ describe('boards sidebar remove issue', () => {
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.vm.collapse({ emitEvent: false });
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 4a8eda298f2..5364d929c38 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlFormInput, GlForm } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
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';
@@ -75,7 +76,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
});
findFormInput().vm.$emit('input', TEST_TITLE);
findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('collapses sidebar and renders new title', () => {
@@ -98,7 +99,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {});
findFormInput().vm.$emit('input', '');
findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('commits change to the server', () => {
@@ -113,7 +114,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
wrapper.vm.$refs.sidebarItem.expand();
findFormInput().vm.$emit('input', TEST_TITLE);
findEditableItem().vm.$emit('off-click');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not collapses sidebar and shows alert', () => {
@@ -148,7 +149,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
});
findFormInput().vm.$emit('input', TEST_TITLE);
findCancelButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('collapses sidebar and render former title', () => {
@@ -168,7 +169,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
findFormInput().vm.$emit('input', 'Invalid title');
findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('collapses sidebar and renders former item title', () => {
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index a081a60166b..24096fddea6 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -29,6 +29,85 @@ export const listObj = {
},
};
+function boardGenerator(n) {
+ return new Array(n).fill().map((board, index) => {
+ const id = `${index}`;
+ const name = `board${id}`;
+
+ return {
+ node: {
+ id,
+ name,
+ weight: 0,
+ __typename: 'Board',
+ },
+ };
+ });
+}
+
+export const boards = boardGenerator(20);
+export const recentIssueBoards = boardGenerator(5);
+
+export const mockSmallProjectAllBoardsResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/114',
+ boards: { edges: boardGenerator(3) },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockEmptyProjectRecentBoardsResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/114',
+ recentIssueBoards: { edges: [] },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockGroupAllBoardsResponse = {
+ data: {
+ group: {
+ id: 'gid://gitlab/Group/114',
+ boards: { edges: boards },
+ __typename: 'Group',
+ },
+ },
+};
+
+export const mockProjectAllBoardsResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/1',
+ boards: { edges: boards },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockGroupRecentBoardsResponse = {
+ data: {
+ group: {
+ id: 'gid://gitlab/Group/114',
+ recentIssueBoards: { edges: recentIssueBoards },
+ __typename: 'Group',
+ },
+ },
+};
+
+export const mockProjectRecentBoardsResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/1',
+ recentIssueBoards: { edges: recentIssueBoards },
+ __typename: 'Project',
+ },
+ },
+};
+
export const mockGroupBoardResponse = {
data: {
workspace: {
@@ -612,6 +691,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
title: __('Milestone'),
symbol: '%',
type: 'milestone',
+ shouldSkipSort: true,
token: MilestoneToken,
unique: true,
fetchMilestones,
diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js
index de823094630..05dc7d28eaa 100644
--- a/spec/frontend/boards/project_select_spec.js
+++ b/spec/frontend/boards/project_select_spec.js
@@ -1,6 +1,6 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ProjectSelect from '~/boards/components/project_select.vue';
import defaultState from '~/boards/stores/state';
@@ -88,7 +88,7 @@ describe('ProjectSelect component', () => {
expect(findGlDropdownLoadingIcon().exists()).toBe(true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlDropdownLoadingIcon().exists()).toBe(false);
});
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 7c842d71688..0eca0cb3ee5 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -315,14 +315,14 @@ describe('fetchMilestones', () => {
'project',
{
query: projectBoardMilestones,
- variables: { fullPath: 'gitlab-org/gitlab', state: 'active' },
+ variables: { fullPath: 'gitlab-org/gitlab' },
},
],
[
'group',
{
query: groupBoardMilestones,
- variables: { fullPath: 'gitlab-org/gitlab', state: 'active' },
+ variables: { fullPath: 'gitlab-org/gitlab' },
},
],
])(
diff --git a/spec/frontend/broadcast_notification_spec.js b/spec/frontend/broadcast_notification_spec.js
index 8d433946632..cd947cd417a 100644
--- a/spec/frontend/broadcast_notification_spec.js
+++ b/spec/frontend/broadcast_notification_spec.js
@@ -30,6 +30,7 @@ describe('broadcast message on dismiss', () => {
expect(Cookies.set).toHaveBeenCalledWith('hide_broadcast_message_1', true, {
expires: new Date(endsAt),
+ secure: false,
});
});
});
diff --git a/spec/frontend/captcha/apollo_captcha_link_spec.js b/spec/frontend/captcha/apollo_captcha_link_spec.js
index e7ff4812ee7..eab52344d1f 100644
--- a/spec/frontend/captcha/apollo_captcha_link_spec.js
+++ b/spec/frontend/captcha/apollo_captcha_link_spec.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link';
import UnsolvedCaptchaError from '~/captcha/unsolved_captcha_error';
diff --git a/spec/frontend/ci_lint/components/ci_lint_spec.js b/spec/frontend/ci_lint/components/ci_lint_spec.js
index c4b2927764e..0ad6ed56b0e 100644
--- a/spec/frontend/ci_lint/components/ci_lint_spec.js
+++ b/spec/frontend/ci_lint/components/ci_lint_spec.js
@@ -1,5 +1,6 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import CiLint from '~/ci_lint/components/ci_lint.vue';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
@@ -81,7 +82,7 @@ describe('CI Lint', () => {
it('validation displays results', async () => {
findValidateBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findValidateBtn().props('loading')).toBe(true);
@@ -96,7 +97,7 @@ describe('CI Lint', () => {
findValidateBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findValidateBtn().props('loading')).toBe(true);
diff --git a/spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js b/spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js
index 41af257ad89..6bf28a67300 100644
--- a/spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js
+++ b/spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js
@@ -1,5 +1,6 @@
import { GlTable, GlBadge } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import TriggersList from '~/ci_settings_pipeline_triggers/components/triggers_list.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -25,10 +26,10 @@ describe('TriggersList', () => {
const findEditBtn = (i) => findRowAt(i).find('[data-testid="edit-btn"]');
const findRevokeBtn = (i) => findRowAt(i).find('[data-testid="trigger_revoke_button"]');
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays a table with expected headers', () => {
diff --git a/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js b/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js
index 5c5ea102f12..e7e4897abfa 100644
--- a/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js
@@ -1,10 +1,10 @@
import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Ci environments dropdown', () => {
let wrapper;
@@ -22,7 +22,6 @@ describe('Ci environments dropdown', () => {
wrapper = mount(CiEnvironmentsDropdown, {
store,
- localVue,
propsData: {
value: term,
},
@@ -74,7 +73,7 @@ describe('Ci environments dropdown', () => {
describe('Environments found', () => {
beforeEach(async () => {
createComponent('prod');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders only the environment searched for', () => {
@@ -111,7 +110,7 @@ describe('Ci environments dropdown', () => {
it('should emit createClicked if an environment is clicked', async () => {
createComponent('newscope');
- await wrapper.vm.$nextTick();
+ await nextTick();
findDropdownItemByIndex(1).vm.$emit('click');
expect(wrapper.emitted('createClicked')).toEqual([['newscope']]);
});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
index 7c4ff67feb3..085ab1c0c30 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlFormInput } 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 { mockTracking } from 'helpers/tracking_helper';
import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
@@ -9,8 +10,7 @@ import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
import ModalStub from '../stubs';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Ci variable modal', () => {
let wrapper;
@@ -26,7 +26,6 @@ describe('Ci variable modal', () => {
stubs: {
GlModal: ModalStub,
},
- localVue,
store,
...options,
});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
index 03f90f72d87..13e417940a8 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
@@ -1,10 +1,10 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import CiVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
import createStore from '~/ci_variable_list/store';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Ci variable table', () => {
let wrapper;
@@ -16,7 +16,6 @@ describe('Ci variable table', () => {
store.state.isGroup = groupState;
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = shallowMount(CiVariableSettings, {
- localVue,
store,
});
};
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
index 8367c3f6bb8..62f9ae4eb4e 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
@@ -1,11 +1,11 @@
-import { createLocalVue, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import CiVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Ci variable table', () => {
let wrapper;
@@ -14,16 +14,15 @@ describe('Ci variable table', () => {
const createComponent = () => {
store = createStore();
jest.spyOn(store, 'dispatch').mockImplementation();
- wrapper = mount(CiVariableTable, {
+ wrapper = mountExtended(CiVariableTable, {
attachTo: document.body,
- localVue,
store,
});
};
- const findRevealButton = () => wrapper.find({ ref: 'secret-value-reveal-button' });
- const findEditButton = () => wrapper.find({ ref: 'edit-ci-variable' });
- const findEmptyVariablesPlaceholder = () => wrapper.find({ ref: 'empty-variables' });
+ const findRevealButton = () => wrapper.findByText('Reveal values');
+ const findEditButton = () => wrapper.findByLabelText('Edit');
+ const findEmptyVariablesPlaceholder = () => wrapper.findByText('There are no variables yet.');
beforeEach(() => {
createComponent();
@@ -37,18 +36,35 @@ describe('Ci variable table', () => {
expect(store.dispatch).toHaveBeenCalledWith('fetchVariables');
});
- describe('Renders correct data', () => {
- it('displays empty message when variables are not present', () => {
+ describe('When table is empty', () => {
+ beforeEach(() => {
+ store.state.variables = [];
+ });
+
+ it('displays empty message', () => {
expect(findEmptyVariablesPlaceholder().exists()).toBe(true);
});
- it('displays correct amount of variables present and no empty message', () => {
+ it('hides the reveal button', () => {
+ expect(findRevealButton().exists()).toBe(false);
+ });
+ });
+
+ describe('When table has variables', () => {
+ beforeEach(() => {
store.state.variables = mockData.mockVariables;
+ });
+
+ it('does not display the empty message', () => {
+ expect(findEmptyVariablesPlaceholder().exists()).toBe(false);
+ });
+
+ it('displays the reveal button', () => {
+ expect(findRevealButton().exists()).toBe(true);
+ });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('.js-ci-variable-row').length).toBe(1);
- expect(findEmptyVariablesPlaceholder().exists()).toBe(false);
- });
+ it('displays the correct amount of variables', async () => {
+ expect(wrapper.findAll('.js-ci-variable-row')).toHaveLength(1);
});
});
diff --git a/spec/frontend/clusters/agents/components/activity_events_list_spec.js b/spec/frontend/clusters/agents/components/activity_events_list_spec.js
index 4abbd77dfb7..6b374b6620d 100644
--- a/spec/frontend/clusters/agents/components/activity_events_list_spec.js
+++ b/spec/frontend/clusters/agents/components/activity_events_list_spec.js
@@ -70,8 +70,9 @@ describe('ActivityEvents', () => {
});
describe('when there are no agentEvents', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper({ queryResponse: jest.fn().mockResolvedValue(mockEmptyResponse) });
+ await waitForPromises();
});
it('displays an empty state with the correct illustration', () => {
@@ -83,9 +84,11 @@ describe('ActivityEvents', () => {
describe('when the agentEvents are present', () => {
const length = mockResponse.data?.project?.clusterAgent?.activityEvents?.nodes?.length;
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper();
+ await waitForPromises();
});
+
it('renders an activity-history-item components for every event', () => {
expect(findAllActivityHistoryItems()).toHaveLength(length);
});
diff --git a/spec/frontend/clusters/agents/components/show_spec.js b/spec/frontend/clusters/agents/components/show_spec.js
index 2a3c11f4b47..f2f073544e3 100644
--- a/spec/frontend/clusters/agents/components/show_spec.js
+++ b/spec/frontend/clusters/agents/components/show_spec.js
@@ -11,12 +11,14 @@ import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { MAX_LIST_COUNT, TOKEN_STATUS_ACTIVE } from '~/clusters/agents/constants';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('ClusterAgentShow', () => {
let wrapper;
+ let agentQueryResponse;
useFakeDate([2021, 2, 15]);
const provide = {
@@ -40,7 +42,7 @@ describe('ClusterAgentShow', () => {
};
const createWrapper = ({ clusterAgent, queryResponse = null }) => {
- const agentQueryResponse =
+ agentQueryResponse =
queryResponse ||
jest.fn().mockResolvedValue({ data: { project: { id: 'project-1', clusterAgent } } });
const apolloProvider = createMockApollo([[getAgentQuery, agentQueryResponse]]);
@@ -80,8 +82,21 @@ describe('ClusterAgentShow', () => {
});
describe('default behaviour', () => {
- beforeEach(() => {
- return createWrapper({ clusterAgent: defaultClusterAgent });
+ beforeEach(async () => {
+ createWrapper({ clusterAgent: defaultClusterAgent });
+ await waitForPromises();
+ });
+
+ it('sends expected params', () => {
+ const variables = {
+ agentName: provide.agentName,
+ projectPath: provide.projectPath,
+ tokenStatus: TOKEN_STATUS_ACTIVE,
+ first: MAX_LIST_COUNT,
+ last: null,
+ };
+
+ expect(agentQueryResponse).toHaveBeenCalledWith(variables);
});
it('displays the agent name', () => {
@@ -117,11 +132,13 @@ describe('ClusterAgentShow', () => {
createdByUser: null,
};
- beforeEach(() => {
- return createWrapper({ clusterAgent: missingUser });
+ beforeEach(async () => {
+ createWrapper({ clusterAgent: missingUser });
+ await waitForPromises();
});
- it('displays agent create information with unknown user', () => {
+ it('displays agent create information with unknown user', async () => {
+ await waitForPromises();
expect(findCreatedText()).toMatchInterpolatedText('Created by Unknown user 2 days ago');
});
});
@@ -132,23 +149,30 @@ describe('ClusterAgentShow', () => {
tokens: null,
};
- beforeEach(() => {
- return createWrapper({ clusterAgent: missingTokens });
+ beforeEach(async () => {
+ createWrapper({ clusterAgent: missingTokens });
+ await waitForPromises();
});
- it('displays token header with no count', () => {
+ it('displays token header with no count', async () => {
+ await waitForPromises();
expect(findTokenCount()).toMatchInterpolatedText(`${ClusterAgentShow.i18n.tokens}`);
});
});
describe('when the token list has additional pages', () => {
- const pageInfo = {
+ const pageInfoResponse = {
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'prev',
endCursor: 'next',
};
+ const pageInfo = {
+ ...pageInfoResponse,
+ __typename: 'PageInfo',
+ };
+
const tokenPagination = {
...defaultClusterAgent,
tokens: {
@@ -157,8 +181,9 @@ describe('ClusterAgentShow', () => {
},
};
- beforeEach(() => {
- return createWrapper({ clusterAgent: tokenPagination });
+ beforeEach(async () => {
+ createWrapper({ clusterAgent: tokenPagination });
+ await waitForPromises();
});
it('should render pagination buttons', () => {
@@ -166,7 +191,7 @@ describe('ClusterAgentShow', () => {
});
it('should pass pageInfo to the pagination component', () => {
- expect(findPaginationButtons().props()).toMatchObject(pageInfo);
+ expect(findPaginationButtons().props()).toMatchObject(pageInfoResponse);
});
});
diff --git a/spec/frontend/clusters/components/new_cluster_spec.js b/spec/frontend/clusters/components/new_cluster_spec.js
index e4bca5eaaa5..b73442f6ec3 100644
--- a/spec/frontend/clusters/components/new_cluster_spec.js
+++ b/spec/frontend/clusters/components/new_cluster_spec.js
@@ -1,5 +1,6 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import NewCluster from '~/clusters/components/new_cluster.vue';
import createClusterStore from '~/clusters/stores/new_cluster';
@@ -7,10 +8,10 @@ describe('NewCluster', () => {
let store;
let wrapper;
- const createWrapper = () => {
+ const createWrapper = async () => {
store = createClusterStore({ clusterConnectHelpPath: '/some/help/path' });
wrapper = shallowMount(NewCluster, { store, stubs: { GlLink, GlSprintf } });
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const findDescription = () => wrapper.find(GlSprintf);
diff --git a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
index 41bd492148e..173fefe6167 100644
--- a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
+++ b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
@@ -1,5 +1,6 @@
import { GlModal, GlSprintf } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import RemoveClusterConfirmation from '~/clusters/components/remove_cluster_confirmation.vue';
import SplitButton from '~/vue_shared/components/split_button.vue';
@@ -43,7 +44,7 @@ describe('Remove cluster confirmation modal', () => {
it('opens modal with "cleanup" option', async () => {
findSplitButton().vm.$emit('remove-cluster-and-cleanup');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal().vm.show).toHaveBeenCalled();
expect(wrapper.vm.confirmCleanup).toEqual(true);
@@ -55,7 +56,7 @@ describe('Remove cluster confirmation modal', () => {
it('opens modal without "cleanup" option', async () => {
findSplitButton().vm.$emit('remove-cluster');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal().vm.show).toHaveBeenCalled();
expect(wrapper.vm.confirmCleanup).toEqual(false);
diff --git a/spec/frontend/clusters/forms/components/integration_form_spec.js b/spec/frontend/clusters/forms/components/integration_form_spec.js
index d041cd1e164..dd278bcd2ce 100644
--- a/spec/frontend/clusters/forms/components/integration_form_spec.js
+++ b/spec/frontend/clusters/forms/components/integration_form_spec.js
@@ -1,11 +1,11 @@
import { GlToggle, GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import IntegrationForm from '~/clusters/forms/components/integration_form.vue';
import { createStore } from '~/clusters/forms/stores/index';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ClusterIntegrationForm', () => {
let wrapper;
@@ -19,7 +19,6 @@ describe('ClusterIntegrationForm', () => {
const createWrapper = (storeValues = defaultStoreValues) => {
wrapper = shallowMount(IntegrationForm, {
- localVue,
store: createStore(storeValues),
provide: {
autoDevopsHelpPath: 'topics/autodevops/index',
@@ -76,32 +75,22 @@ describe('ClusterIntegrationForm', () => {
describe('reactivity', () => {
beforeEach(() => createWrapper());
- it('enables the submit button on changing toggle to different value', () => {
- return wrapper.vm
- .$nextTick()
- .then(() => {
- // setData is a bad approach because it changes the internal implementation which we should not touch
- // but our GlFormInput lacks the ability to set a new value.
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ toggleEnabled: !defaultStoreValues.enabled });
- })
- .then(() => {
- expect(findSubmitButton().props('disabled')).toBe(false);
- });
+ it('enables the submit button on changing toggle to different value', async () => {
+ await nextTick();
+ // setData is a bad approach because it changes the internal implementation which we should not touch
+ // but our GlFormInput lacks the ability to set a new value.
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ await wrapper.setData({ toggleEnabled: !defaultStoreValues.enabled });
+ expect(findSubmitButton().props('disabled')).toBe(false);
});
- it('enables the submit button on changing input values', () => {
- return wrapper.vm
- .$nextTick()
- .then(() => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ envScope: `${defaultStoreValues.environmentScope}1` });
- })
- .then(() => {
- expect(findSubmitButton().props('disabled')).toBe(false);
- });
+ it('enables the submit button on changing input values', async () => {
+ await nextTick();
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ await wrapper.setData({ envScope: `${defaultStoreValues.environmentScope}1` });
+ expect(findSubmitButton().props('disabled')).toBe(false);
});
});
});
diff --git a/spec/frontend/clusters_list/components/agent_table_spec.js b/spec/frontend/clusters_list/components/agent_table_spec.js
index 887c17bb4ad..dc7f0ebae74 100644
--- a/spec/frontend/clusters_list/components/agent_table_spec.js
+++ b/spec/frontend/clusters_list/components/agent_table_spec.js
@@ -1,65 +1,32 @@
import { GlLink, GlIcon } from '@gitlab/ui';
+import { sprintf } from '~/locale';
import AgentTable from '~/clusters_list/components/agent_table.vue';
-import AgentOptions from '~/clusters_list/components/agent_options.vue';
-import { ACTIVE_CONNECTION_TIME } from '~/clusters_list/constants';
+import DeleteAgentButton from '~/clusters_list/components/delete_agent_button.vue';
+import { I18N_AGENT_TABLE } from '~/clusters_list/constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-
-const connectedTimeNow = new Date();
-const connectedTimeInactive = new Date(connectedTimeNow.getTime() - ACTIVE_CONNECTION_TIME);
+import { clusterAgents, connectedTimeNow, connectedTimeInactive } from './mock_data';
const provideData = {
- projectPath: 'path/to/project',
+ gitlabVersion: '14.8',
};
const propsData = {
- agents: [
- {
- name: 'agent-1',
- id: 'agent-1-id',
- configFolder: {
- webPath: '/agent/full/path',
- },
- webPath: '/agent-1',
- status: 'unused',
- lastContact: null,
- tokens: null,
- },
- {
- name: 'agent-2',
- id: 'agent-2-id',
- webPath: '/agent-2',
- status: 'active',
- lastContact: connectedTimeNow.getTime(),
- tokens: {
- nodes: [
- {
- lastUsedAt: connectedTimeNow,
- },
- ],
- },
- },
- {
- name: 'agent-3',
- id: 'agent-3-id',
- webPath: '/agent-3',
- status: 'inactive',
- lastContact: connectedTimeInactive.getTime(),
- tokens: {
- nodes: [
- {
- lastUsedAt: connectedTimeInactive,
- },
- ],
- },
- },
- ],
+ agents: clusterAgents,
};
-const AgentOptionsStub = stubComponent(AgentOptions, {
+const DeleteAgentButtonStub = stubComponent(DeleteAgentButton, {
template: `<div></div>`,
});
+const outdatedTitle = I18N_AGENT_TABLE.versionOutdatedTitle;
+const mismatchTitle = I18N_AGENT_TABLE.versionMismatchTitle;
+const mismatchOutdatedTitle = I18N_AGENT_TABLE.versionMismatchOutdatedTitle;
+const outdatedText = sprintf(I18N_AGENT_TABLE.versionOutdatedText, {
+ version: provideData.gitlabVersion,
+});
+const mismatchText = I18N_AGENT_TABLE.versionMismatchText;
+
describe('AgentTable', () => {
let wrapper;
@@ -67,16 +34,17 @@ describe('AgentTable', () => {
const findStatusIcon = (at) => wrapper.findAllComponents(GlIcon).at(at);
const findStatusText = (at) => wrapper.findAllByTestId('cluster-agent-connection-status').at(at);
const findLastContactText = (at) => wrapper.findAllByTestId('cluster-agent-last-contact').at(at);
+ const findVersionText = (at) => wrapper.findAllByTestId('cluster-agent-version').at(at);
const findConfiguration = (at) =>
wrapper.findAllByTestId('cluster-agent-configuration-link').at(at);
- const findAgentOptions = () => wrapper.findAllComponents(AgentOptions);
+ const findDeleteAgentButton = () => wrapper.findAllComponents(DeleteAgentButton);
beforeEach(() => {
wrapper = mountExtended(AgentTable, {
propsData,
provide: provideData,
stubs: {
- AgentOptions: AgentOptionsStub,
+ DeleteAgentButton: DeleteAgentButtonStub,
},
});
});
@@ -92,7 +60,7 @@ describe('AgentTable', () => {
agentName | link | lineNumber
${'agent-1'} | ${'/agent-1'} | ${0}
${'agent-2'} | ${'/agent-2'} | ${1}
- `('displays agent link', ({ agentName, link, lineNumber }) => {
+ `('displays agent link for $agentName', ({ agentName, link, lineNumber }) => {
expect(findAgentLink(lineNumber).text()).toBe(agentName);
expect(findAgentLink(lineNumber).attributes('href')).toBe(link);
});
@@ -102,33 +70,92 @@ describe('AgentTable', () => {
${'Never connected'} | ${'status-neutral'} | ${0}
${'Connected'} | ${'status-success'} | ${1}
${'Not connected'} | ${'severity-critical'} | ${2}
- `('displays agent connection status', ({ status, iconName, lineNumber }) => {
- expect(findStatusText(lineNumber).text()).toBe(status);
- expect(findStatusIcon(lineNumber).props('name')).toBe(iconName);
- });
+ `(
+ 'displays agent connection status as "$status" at line $lineNumber',
+ ({ status, iconName, lineNumber }) => {
+ expect(findStatusText(lineNumber).text()).toBe(status);
+ expect(findStatusIcon(lineNumber).props('name')).toBe(iconName);
+ },
+ );
it.each`
lastContact | lineNumber
${'Never'} | ${0}
${timeagoMixin.methods.timeFormatted(connectedTimeNow)} | ${1}
${timeagoMixin.methods.timeFormatted(connectedTimeInactive)} | ${2}
- `('displays agent last contact time', ({ lastContact, lineNumber }) => {
- expect(findLastContactText(lineNumber).text()).toBe(lastContact);
- });
+ `(
+ 'displays agent last contact time as "$lastContact" at line $lineNumber',
+ ({ lastContact, lineNumber }) => {
+ expect(findLastContactText(lineNumber).text()).toBe(lastContact);
+ },
+ );
+
+ describe.each`
+ agent | version | podsNumber | versionMismatch | versionOutdated | title | texts | lineNumber
+ ${'agent-1'} | ${''} | ${1} | ${false} | ${false} | ${''} | ${''} | ${0}
+ ${'agent-2'} | ${'14.8'} | ${2} | ${false} | ${false} | ${''} | ${''} | ${1}
+ ${'agent-3'} | ${'14.5'} | ${1} | ${false} | ${true} | ${outdatedTitle} | ${[outdatedText]} | ${2}
+ ${'agent-4'} | ${'14.7'} | ${2} | ${true} | ${false} | ${mismatchTitle} | ${[mismatchText]} | ${3}
+ ${'agent-5'} | ${'14.3'} | ${2} | ${true} | ${true} | ${mismatchOutdatedTitle} | ${[mismatchText, outdatedText]} | ${4}
+ `(
+ 'agent version column at line $lineNumber',
+ ({
+ agent,
+ version,
+ podsNumber,
+ versionMismatch,
+ versionOutdated,
+ title,
+ texts,
+ lineNumber,
+ }) => {
+ const findIcon = () => findVersionText(lineNumber).find(GlIcon);
+ const findPopover = () => wrapper.findByTestId(`popover-${agent}`);
+ const versionWarning = versionMismatch || versionOutdated;
+
+ it('shows the correct agent version', () => {
+ expect(findVersionText(lineNumber).text()).toBe(version);
+ });
+
+ if (versionWarning) {
+ it(`shows a warning icon when agent versions mismatch is ${versionMismatch} and outdated is ${versionOutdated} and the number of pods is ${podsNumber}`, () => {
+ expect(findIcon().props('name')).toBe('warning');
+ });
+
+ it(`renders correct title for the popover when agent versions mismatch is ${versionMismatch} and outdated is ${versionOutdated}`, () => {
+ expect(findPopover().props('title')).toBe(title);
+ });
+
+ it(`renders correct text for the popover when agent versions mismatch is ${versionMismatch} and outdated is ${versionOutdated}`, () => {
+ texts.forEach((text) => {
+ expect(findPopover().text()).toContain(text);
+ });
+ });
+ } else {
+ it(`doesn't show a warning icon with a popover when agent versions mismatch is ${versionMismatch} and outdated is ${versionOutdated} and the number of pods is ${podsNumber}`, () => {
+ expect(findIcon().exists()).toBe(false);
+ expect(findPopover().exists()).toBe(false);
+ });
+ }
+ },
+ );
it.each`
agentPath | hasLink | lineNumber
${'.gitlab/agents/agent-1'} | ${true} | ${0}
${'.gitlab/agents/agent-2'} | ${false} | ${1}
- `('displays config file path', ({ agentPath, hasLink, lineNumber }) => {
- const findLink = findConfiguration(lineNumber).find(GlLink);
+ `(
+ 'displays config file path as "$agentPath" at line $lineNumber',
+ ({ agentPath, hasLink, lineNumber }) => {
+ const findLink = findConfiguration(lineNumber).find(GlLink);
- expect(findLink.exists()).toBe(hasLink);
- expect(findConfiguration(lineNumber).text()).toBe(agentPath);
- });
+ expect(findLink.exists()).toBe(hasLink);
+ expect(findConfiguration(lineNumber).text()).toBe(agentPath);
+ },
+ );
it('displays actions menu for each agent', () => {
- expect(findAgentOptions()).toHaveLength(3);
+ expect(findDeleteAgentButton()).toHaveLength(5);
});
});
});
diff --git a/spec/frontend/clusters_list/components/agents_spec.js b/spec/frontend/clusters_list/components/agents_spec.js
index c9ca10f6bf7..3cfa4b92bc0 100644
--- a/spec/frontend/clusters_list/components/agents_spec.js
+++ b/spec/frontend/clusters_list/components/agents_spec.js
@@ -1,12 +1,18 @@
-import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue';
import AgentTable from '~/clusters_list/components/agent_table.vue';
import Agents from '~/clusters_list/components/agents.vue';
-import { ACTIVE_CONNECTION_TIME } from '~/clusters_list/constants';
+import {
+ ACTIVE_CONNECTION_TIME,
+ AGENT_FEEDBACK_KEY,
+ AGENT_FEEDBACK_ISSUE,
+} from '~/clusters_list/constants';
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -21,13 +27,26 @@ describe('Agents', () => {
projectPath: 'path/to/project',
};
- const createWrapper = ({ props = {}, agents = [], pageInfo = null, trees = [], count = 0 }) => {
+ const createWrapper = async ({
+ props = {},
+ glFeatures = {},
+ agents = [],
+ pageInfo = null,
+ trees = [],
+ count = 0,
+ }) => {
const provide = provideData;
const apolloQueryResponse = {
data: {
project: {
id: '1',
- clusterAgents: { nodes: agents, pageInfo, tokens: { nodes: [] }, count },
+ clusterAgents: {
+ nodes: agents,
+ pageInfo,
+ connections: { nodes: [] },
+ tokens: { nodes: [] },
+ count,
+ },
repository: { tree: { trees: { nodes: trees, pageInfo } } },
},
},
@@ -44,35 +63,48 @@ describe('Agents', () => {
...defaultProps,
...props,
},
- provide: provideData,
+ provide: {
+ ...provideData,
+ glFeatures,
+ },
+ stubs: {
+ GlBanner,
+ LocalStorageSync,
+ },
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
- const findAgentTable = () => wrapper.find(AgentTable);
- const findEmptyState = () => wrapper.find(AgentEmptyState);
- const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
+ const findAgentTable = () => wrapper.findComponent(AgentTable);
+ const findEmptyState = () => wrapper.findComponent(AgentEmptyState);
+ const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findBanner = () => wrapper.findComponent(GlBanner);
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
+ wrapper.destroy();
+
+ localStorage.removeItem(AGENT_FEEDBACK_KEY);
});
describe('when there is a list of agents', () => {
let testDate = new Date();
const agents = [
{
+ __typename: 'ClusterAgent',
id: '1',
name: 'agent-1',
webPath: '/agent-1',
+ connections: null,
tokens: null,
},
{
+ __typename: 'ClusterAgent',
id: '2',
name: 'agent-2',
webPath: '/agent-2',
+ connections: null,
tokens: {
nodes: [
{
@@ -103,6 +135,7 @@ describe('Agents', () => {
configFolder: undefined,
status: 'unused',
lastContact: null,
+ connections: null,
tokens: null,
},
{
@@ -116,6 +149,7 @@ describe('Agents', () => {
webPath: '/agent-2',
status: 'active',
lastContact: new Date(testDate).getTime(),
+ connections: null,
tokens: {
nodes: [
{
@@ -143,6 +177,49 @@ describe('Agents', () => {
expect(wrapper.emitted().onAgentsLoad).toEqual([[count]]);
});
+ describe.each`
+ featureFlagEnabled | localStorageItemExists | bannerShown
+ ${true} | ${false} | ${true}
+ ${true} | ${true} | ${false}
+ ${false} | ${true} | ${false}
+ ${false} | ${false} | ${false}
+ `(
+ 'when the feature flag enabled is $featureFlagEnabled and dismissed localStorage item exists is $localStorageItemExists',
+ ({ featureFlagEnabled, localStorageItemExists, bannerShown }) => {
+ const glFeatures = {
+ showGitlabAgentFeedback: featureFlagEnabled,
+ };
+ beforeEach(() => {
+ if (localStorageItemExists) {
+ localStorage.setItem(AGENT_FEEDBACK_KEY, true);
+ }
+
+ return createWrapper({ glFeatures, agents, count, trees });
+ });
+
+ it(`should ${bannerShown ? 'show' : 'hide'} the feedback banner`, () => {
+ expect(findBanner().exists()).toBe(bannerShown);
+ });
+ },
+ );
+
+ describe('when the agent feedback banner is present', () => {
+ const glFeatures = {
+ showGitlabAgentFeedback: true,
+ };
+ beforeEach(() => {
+ return createWrapper({ glFeatures, agents, count, trees });
+ });
+
+ it('should render the correct title', () => {
+ expect(findBanner().props('title')).toBe('Tell us what you think');
+ });
+
+ it('should render the correct issue link', () => {
+ expect(findBanner().props('buttonLink')).toBe(AGENT_FEEDBACK_ISSUE);
+ });
+ });
+
describe('when the agent has recently connected tokens', () => {
it('should set agent status to active', () => {
expect(findAgentTable().props('agents')).toMatchObject(expectedAgentsList);
@@ -179,7 +256,10 @@ describe('Agents', () => {
beforeEach(() => {
return createWrapper({
agents,
- pageInfo,
+ pageInfo: {
+ ...pageInfo,
+ __typename: 'PageInfo',
+ },
});
});
@@ -216,6 +296,10 @@ describe('Agents', () => {
expect(findAgentTable().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true);
});
+
+ it('should not show agent feedback alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
});
describe('when agents query has errored', () => {
@@ -224,7 +308,7 @@ describe('Agents', () => {
});
it('displays an alert message', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(findAlert().text()).toBe('An error occurred while loading your Agents');
});
});
@@ -239,14 +323,14 @@ describe('Agents', () => {
},
};
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = shallowMount(Agents, {
mocks,
propsData: defaultProps,
provide: provideData,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays a loading icon', () => {
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
index c7ee2a00f5b..a9f11e6fdf8 100644
--- a/spec/frontend/clusters_list/components/ancestor_notice_spec.js
+++ b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
@@ -1,5 +1,6 @@
import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import AncestorNotice from '~/clusters_list/components/ancestor_notice.vue';
import ClusterStore from '~/clusters_list/store';
@@ -7,10 +8,10 @@ describe('ClustersAncestorNotice', () => {
let store;
let wrapper;
- const createWrapper = () => {
+ const createWrapper = async () => {
store = ClusterStore({ ancestorHelperPath: '/some/ancestor/path' });
wrapper = shallowMount(AncestorNotice, { store, stubs: { GlSprintf, GlAlert } });
- return wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
@@ -22,9 +23,9 @@ describe('ClustersAncestorNotice', () => {
});
describe('when cluster does not have ancestors', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.hasAncestorClusters = false;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays no notice', () => {
@@ -33,9 +34,9 @@ describe('ClustersAncestorNotice', () => {
});
describe('when cluster has ancestors', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.hasAncestorClusters = true;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays notice text', () => {
diff --git a/spec/frontend/clusters_list/components/clusters_actions_spec.js b/spec/frontend/clusters_list/components/clusters_actions_spec.js
index cb8303ca4b2..331690fc642 100644
--- a/spec/frontend/clusters_list/components/clusters_actions_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_actions_spec.js
@@ -10,9 +10,10 @@ describe('ClustersActionsComponent', () => {
const newClusterPath = 'path/to/create/cluster';
const addClusterPath = 'path/to/connect/existing/cluster';
- const provideData = {
+ const defaultProvide = {
newClusterPath,
addClusterPath,
+ canAddCluster: true,
};
const findDropdown = () => wrapper.findComponent(GlDropdown);
@@ -21,13 +22,21 @@ describe('ClustersActionsComponent', () => {
const findConnectClusterLink = () => wrapper.findByTestId('connect-cluster-link');
const findConnectNewAgentLink = () => wrapper.findByTestId('connect-new-agent-link');
- beforeEach(() => {
+ const createWrapper = (provideData = {}) => {
wrapper = shallowMountExtended(ClustersActions, {
- provide: provideData,
+ provide: {
+ ...defaultProvide,
+ ...provideData,
+ },
directives: {
GlModalDirective: createMockDirective(),
+ GlTooltip: createMockDirective(),
},
});
+ };
+
+ beforeEach(() => {
+ createWrapper();
});
afterEach(() => {
@@ -52,4 +61,24 @@ describe('ClustersActionsComponent', () => {
expect(binding.value).toBe(INSTALL_AGENT_MODAL_ID);
});
+
+ it('shows tooltip', () => {
+ const tooltip = getBinding(findDropdown().element, 'gl-tooltip');
+ expect(tooltip.value).toBe(CLUSTERS_ACTIONS.connectWithAgent);
+ });
+
+ describe('when user cannot add clusters', () => {
+ beforeEach(() => {
+ createWrapper({ canAddCluster: false });
+ });
+
+ it('disables dropdown', () => {
+ expect(findDropdown().props('disabled')).toBe(true);
+ });
+
+ it('shows tooltip explaining why dropdown is disabled', () => {
+ const tooltip = getBinding(findDropdown().element, 'gl-tooltip');
+ expect(tooltip.value).toBe(CLUSTERS_ACTIONS.dropdownDisabledHint);
+ });
+ });
});
diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js
index 9af25a534d8..82e667093aa 100644
--- a/spec/frontend/clusters_list/components/clusters_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_spec.js
@@ -7,6 +7,7 @@ import {
import * as Sentry from '@sentry/browser';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import Clusters from '~/clusters_list/components/clusters.vue';
import ClustersEmptyState from '~/clusters_list/components/clusters_empty_state.vue';
import ClusterStore from '~/clusters_list/store';
@@ -176,9 +177,9 @@ describe('Clusters', () => {
});
describe('nodes finish loading', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.$store.state.loadingNodes = false;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it.each`
diff --git a/spec/frontend/clusters_list/components/clusters_view_all_spec.js b/spec/frontend/clusters_list/components/clusters_view_all_spec.js
index 6ef56beddee..2c1e3d909cc 100644
--- a/spec/frontend/clusters_list/components/clusters_view_all_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_view_all_spec.js
@@ -1,5 +1,5 @@
import { GlCard, GlLoadingIcon, GlButton, GlSprintf, GlBadge } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ClustersViewAll from '~/clusters_list/components/clusters_view_all.vue';
@@ -16,8 +16,7 @@ import {
} from '~/clusters_list/constants';
import { sprintf } from '~/locale';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const addClusterPath = '/path/to/add/cluster';
const defaultBranchName = 'default-branch';
@@ -33,8 +32,9 @@ describe('ClustersViewAllComponent', () => {
defaultBranchName,
};
- const provideData = {
+ const defaultProvide = {
addClusterPath,
+ canAddCluster: true,
};
const entryData = {
@@ -46,32 +46,43 @@ describe('ClustersViewAllComponent', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAgentsComponent = () => wrapper.findComponent(Agents);
const findClustersComponent = () => wrapper.findComponent(Clusters);
+ const findInstallAgentButtonTooltip = () => wrapper.findByTestId('install-agent-button-tooltip');
+ const findConnectExistingClusterButtonTooltip = () =>
+ wrapper.findByTestId('connect-existing-cluster-button-tooltip');
const findCardsContainer = () => wrapper.findByTestId('clusters-cards-container');
const findAgentCardTitle = () => wrapper.findByTestId('agent-card-title');
const findRecommendedBadge = () => wrapper.findComponent(GlBadge);
const findClustersCardTitle = () => wrapper.findByTestId('clusters-card-title');
const findFooterButton = (line) => findCards().at(line).findComponent(GlButton);
+ const getTooltipText = (el) => {
+ const binding = getBinding(el, 'gl-tooltip');
+
+ return binding.value;
+ };
const createStore = (initialState) =>
new Vuex.Store({
state: initialState,
});
- const createWrapper = ({ initialState }) => {
+ const createWrapper = ({ initialState = entryData, provideData } = {}) => {
wrapper = shallowMountExtended(ClustersViewAll, {
- localVue,
store: createStore(initialState),
propsData,
- provide: provideData,
+ provide: {
+ ...defaultProvide,
+ ...provideData,
+ },
directives: {
GlModalDirective: createMockDirective(),
+ GlTooltip: createMockDirective(),
},
stubs: { GlCard, GlSprintf },
});
};
beforeEach(() => {
- createWrapper({ initialState: entryData });
+ createWrapper();
});
afterEach(() => {
@@ -127,15 +138,20 @@ describe('ClustersViewAllComponent', () => {
expect(findAgentsComponent().props('defaultBranchName')).toBe(defaultBranchName);
});
+ it('should show install new Agent button in the footer', () => {
+ expect(findFooterButton(0).exists()).toBe(true);
+ expect(findFooterButton(0).props('disabled')).toBe(false);
+ });
+
+ it('does not show tooltip for install new Agent button', () => {
+ expect(getTooltipText(findInstallAgentButtonTooltip().element)).toBe('');
+ });
+
describe('when there are no agents', () => {
it('should show the empty title', () => {
expect(findAgentCardTitle().text()).toBe(AGENT_CARD_INFO.emptyTitle);
});
- it('should show install new Agent button in the footer', () => {
- expect(findFooterButton(0).exists()).toBe(true);
- });
-
it('should render correct modal id for the agent link', () => {
const binding = getBinding(findFooterButton(0).element, 'gl-modal-directive');
@@ -175,6 +191,22 @@ describe('ClustersViewAllComponent', () => {
});
});
});
+
+ describe('when the user cannot add clusters', () => {
+ beforeEach(() => {
+ createWrapper({ provideData: { canAddCluster: false } });
+ });
+
+ it('should disable the button', () => {
+ expect(findFooterButton(0).props('disabled')).toBe(true);
+ });
+
+ it('should show a tooltip explaining why the button is disabled', () => {
+ expect(getTooltipText(findInstallAgentButtonTooltip().element)).toBe(
+ AGENT_CARD_INFO.installAgentDisabledHint,
+ );
+ });
+ });
});
describe('clusters tab', () => {
@@ -191,13 +223,34 @@ describe('ClustersViewAllComponent', () => {
expect(findClustersCardTitle().text()).toBe(CERTIFICATE_BASED_CARD_INFO.emptyTitle);
});
- it('should show install new Agent button in the footer', () => {
+ it('should show install new cluster button in the footer', () => {
expect(findFooterButton(1).exists()).toBe(true);
+ expect(findFooterButton(1).props('disabled')).toBe(false);
});
it('should render correct href for the button in the footer', () => {
expect(findFooterButton(1).attributes('href')).toBe(addClusterPath);
});
+
+ it('does not show tooltip for install new cluster button', () => {
+ expect(getTooltipText(findConnectExistingClusterButtonTooltip().element)).toBe('');
+ });
+ });
+
+ describe('when the user cannot add clusters', () => {
+ beforeEach(() => {
+ createWrapper({ provideData: { canAddCluster: false } });
+ });
+
+ it('should disable the button', () => {
+ expect(findFooterButton(1).props('disabled')).toBe(true);
+ });
+
+ it('should show a tooltip explaining why the button is disabled', () => {
+ expect(getTooltipText(findConnectExistingClusterButtonTooltip().element)).toBe(
+ CERTIFICATE_BASED_CARD_INFO.connectExistingClusterDisabledHint,
+ );
+ });
});
describe('when the clusters are present', () => {
diff --git a/spec/frontend/clusters_list/components/agent_options_spec.js b/spec/frontend/clusters_list/components/delete_agent_button_spec.js
index 05bab247816..82850b9dea4 100644
--- a/spec/frontend/clusters_list/components/agent_options_spec.js
+++ b/spec/frontend/clusters_list/components/delete_agent_button_spec.js
@@ -1,13 +1,15 @@
-import { GlDropdown, GlDropdownItem, GlModal, GlFormInput } from '@gitlab/ui';
-import Vue from 'vue';
+import { GlButton, GlModal, GlFormInput } from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { ENTER_KEY } from '~/lib/utils/keys';
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
import deleteAgentMutation from '~/clusters_list/graphql/mutations/delete_agent.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
-import AgentOptions from '~/clusters_list/components/agent_options.vue';
-import { MAX_LIST_COUNT } from '~/clusters_list/constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import DeleteAgentButton from '~/clusters_list/components/delete_agent_button.vue';
+import { MAX_LIST_COUNT, DELETE_AGENT_BUTTON } from '~/clusters_list/constants';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { getAgentResponse, mockDeleteResponse, mockErrorDeleteResponse } from '../mocks/apollo';
Vue.use(VueApollo);
@@ -21,18 +23,23 @@ const agent = {
webPath: 'agent-webPath',
};
-describe('AgentOptions', () => {
+describe('DeleteAgentButton', () => {
let wrapper;
let toast;
let apolloProvider;
let deleteResponse;
const findModal = () => wrapper.findComponent(GlModal);
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDeleteBtn = () => wrapper.findComponent(GlDropdownItem);
+ const findDeleteBtn = () => wrapper.findComponent(GlButton);
const findInput = () => wrapper.findComponent(GlFormInput);
const findPrimaryAction = () => findModal().props('actionPrimary');
const findPrimaryActionAttributes = (attr) => findPrimaryAction().attributes[0][attr];
+ const findDeleteAgentButtonTooltip = () => wrapper.findByTestId('delete-agent-button-tooltip');
+ const getTooltipText = (el) => {
+ const binding = getBinding(el, 'gl-tooltip');
+
+ return binding.value;
+ };
const createMockApolloProvider = ({ mutationResponse }) => {
deleteResponse = jest.fn().mockResolvedValue(mutationResponse);
@@ -53,10 +60,14 @@ describe('AgentOptions', () => {
});
};
- const createWrapper = ({ mutationResponse = mockDeleteResponse } = {}) => {
+ const createWrapper = async ({
+ mutationResponse = mockDeleteResponse,
+ provideData = {},
+ } = {}) => {
apolloProvider = createMockApolloProvider({ mutationResponse });
- const provide = {
+ const defaultProvide = {
projectPath,
+ canAdminCluster: true,
};
const propsData = {
defaultBranchName,
@@ -66,9 +77,15 @@ describe('AgentOptions', () => {
toast = jest.fn();
- wrapper = shallowMountExtended(AgentOptions, {
+ wrapper = shallowMountExtended(DeleteAgentButton, {
apolloProvider,
- provide,
+ provide: {
+ ...defaultProvide,
+ ...provideData,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
propsData,
mocks: { $toast: { show: toast } },
stubs: { GlModal },
@@ -76,13 +93,14 @@ describe('AgentOptions', () => {
wrapper.vm.$refs.modal.hide = jest.fn();
writeQuery();
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const submitAgentToDelete = async () => {
findDeleteBtn().vm.$emit('click');
findInput().vm.$emit('input', agent.name);
await findModal().vm.$emit('primary');
+ await waitForPromises();
};
beforeEach(() => {
@@ -98,7 +116,13 @@ describe('AgentOptions', () => {
describe('delete agent action', () => {
it('displays a delete button', () => {
- expect(findDeleteBtn().text()).toBe('Delete agent');
+ expect(findDeleteBtn().attributes('aria-label')).toBe(DELETE_AGENT_BUTTON.deleteButton);
+ });
+
+ it('shows a tooltip for the button', () => {
+ expect(getTooltipText(findDeleteAgentButtonTooltip().element)).toBe(
+ DELETE_AGENT_BUTTON.deleteButton,
+ );
});
describe('when clicking the delete button', () => {
@@ -111,6 +135,22 @@ describe('AgentOptions', () => {
});
});
+ describe('when user cannot delete clusters', () => {
+ beforeEach(() => {
+ createWrapper({ provideData: { canAdminCluster: false } });
+ });
+
+ it('disables the button', () => {
+ expect(findDeleteBtn().attributes('disabled')).toBe('true');
+ });
+
+ it('shows a disabled tooltip', () => {
+ expect(getTooltipText(findDeleteAgentButtonTooltip().element)).toBe(
+ DELETE_AGENT_BUTTON.disabledHint,
+ );
+ });
+ });
+
describe.each`
condition | agentName | isDisabled | mutationCalled
${'the input with agent name is missing'} | ${''} | ${true} | ${false}
@@ -173,8 +213,7 @@ describe('AgentOptions', () => {
describe('when getting an error deleting agent', () => {
beforeEach(async () => {
await createWrapper({ mutationResponse: mockErrorDeleteResponse });
-
- submitAgentToDelete();
+ await submitAgentToDelete();
});
it('displays the error message', () => {
@@ -187,17 +226,17 @@ describe('AgentOptions', () => {
const loadingResponse = new Promise(() => {});
await createWrapper({ mutationResponse: loadingResponse });
- submitAgentToDelete();
+ await submitAgentToDelete();
});
- it('reenables the options dropdown', async () => {
+ it('reenables the button', async () => {
expect(findPrimaryActionAttributes('loading')).toBe(true);
- expect(findDropdown().attributes('disabled')).toBe('true');
+ expect(findDeleteBtn().attributes('disabled')).toBe('true');
await findModal().vm.$emit('hide');
expect(findPrimaryActionAttributes('loading')).toBe(false);
- expect(findDropdown().attributes('disabled')).toBeUndefined();
+ expect(findDeleteBtn().attributes('disabled')).toBeUndefined();
});
it('clears the agent name input', async () => {
diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
index 4d1429c9e50..37432ed0193 100644
--- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js
+++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
@@ -1,6 +1,7 @@
-import { GlAlert, GlButton, GlFormInputGroup } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import { GlAlert, GlButton, GlFormInputGroup, GlSprintf } from '@gitlab/ui';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import { sprintf } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockTracking } from 'helpers/tracking_helper';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
@@ -27,15 +28,14 @@ import {
createAgentTokenResponse,
createAgentTokenErrorResponse,
getAgentResponse,
+ kasDisabledErrorResponse,
} from '../mocks/apollo';
import ModalStub from '../stubs';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const projectPath = 'path/to/project';
const kasAddress = 'kas.example.com';
-const kasEnabled = true;
const emptyStateImage = 'path/to/image';
const defaultBranchName = 'default';
const maxAgents = MAX_LIST_COUNT;
@@ -49,7 +49,8 @@ describe('InstallAgentModal', () => {
const apolloQueryResponse = {
data: {
project: {
- id: '1',
+ __typename: 'Project',
+ id: 'project-1',
clusterAgents: { nodes: [] },
agentConfigurations: { nodes: configurations },
},
@@ -65,7 +66,7 @@ describe('InstallAgentModal', () => {
.wrappers.find((button) => button.props('variant') === variant);
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => findButtonByVariant('default');
- const findSecondaryButton = () => wrapper.findByTestId('agent-secondary-button');
+ const findPrimaryButton = () => wrapper.findByTestId('agent-primary-button');
const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.empty_state.altText });
const expectDisabledAttribute = (element, disabled) => {
@@ -80,7 +81,6 @@ describe('InstallAgentModal', () => {
const provide = {
projectPath,
kasAddress,
- kasEnabled,
emptyStateImage,
};
@@ -92,9 +92,9 @@ describe('InstallAgentModal', () => {
wrapper = shallowMountExtended(InstallAgentModal, {
attachTo: document.body,
stubs: {
+ GlSprintf,
GlModal: ModalStub,
},
- localVue,
apolloProvider,
provide,
propsData,
@@ -118,7 +118,7 @@ describe('InstallAgentModal', () => {
createWrapper();
writeQuery();
- await wrapper.vm.$nextTick();
+ await waitForPromises();
wrapper.vm.setAgentName('agent-name');
findActionButton().vm.$emit('click');
@@ -126,11 +126,12 @@ describe('InstallAgentModal', () => {
return waitForPromises();
};
- beforeEach(() => {
+ beforeEach(async () => {
apolloProvider = createMockApollo([
[getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
]);
createWrapper();
+ await waitForPromises();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
@@ -293,9 +294,9 @@ describe('InstallAgentModal', () => {
expect(findImage().attributes('src')).toBe(emptyStateImage);
});
- it('renders a secondary button', () => {
- expect(findSecondaryButton().isVisible()).toBe(true);
- expect(findSecondaryButton().text()).toBe(i18n.secondaryButton);
+ it('renders a primary button', () => {
+ expect(findPrimaryButton().isVisible()).toBe(true);
+ expect(findPrimaryButton().text()).toBe(i18n.primaryButton);
});
it('sends the event with the modalType', () => {
@@ -306,4 +307,35 @@ describe('InstallAgentModal', () => {
});
});
});
+
+ describe('when KAS is disabled', () => {
+ const i18n = I18N_AGENT_MODAL.empty_state;
+ beforeEach(async () => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(kasDisabledErrorResponse)],
+ ]);
+
+ createWrapper();
+ await waitForPromises();
+ });
+
+ it('renders empty state image', () => {
+ expect(findImage().attributes('src')).toBe(emptyStateImage);
+ });
+
+ it('renders an instruction to enable the KAS', () => {
+ expect(findModal().text()).toContain(
+ sprintf(i18n.enableKasText, { linkStart: '', linkEnd: '' }),
+ );
+ });
+
+ it('renders a cancel button', () => {
+ expect(findCancelButton().isVisible()).toBe(true);
+ expect(findCancelButton().text()).toBe(i18n.done);
+ });
+
+ it("doesn't render a secondary button", () => {
+ expect(findPrimaryButton().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/clusters_list/components/mock_data.js b/spec/frontend/clusters_list/components/mock_data.js
index e388d791b89..3d18b22d727 100644
--- a/spec/frontend/clusters_list/components/mock_data.js
+++ b/spec/frontend/clusters_list/components/mock_data.js
@@ -1,3 +1,5 @@
+import { ACTIVE_CONNECTION_TIME } from '~/clusters_list/constants';
+
export const agentConfigurationsResponse = {
data: {
project: {
@@ -10,3 +12,113 @@ export const agentConfigurationsResponse = {
},
},
};
+
+export const connectedTimeNow = new Date();
+export const connectedTimeInactive = new Date(connectedTimeNow.getTime() - ACTIVE_CONNECTION_TIME);
+
+export const clusterAgents = [
+ {
+ name: 'agent-1',
+ id: 'agent-1-id',
+ configFolder: {
+ webPath: '/agent/full/path',
+ },
+ webPath: '/agent-1',
+ status: 'unused',
+ lastContact: null,
+ tokens: null,
+ },
+ {
+ name: 'agent-2',
+ id: 'agent-2-id',
+ webPath: '/agent-2',
+ status: 'active',
+ lastContact: connectedTimeNow.getTime(),
+ connections: {
+ nodes: [
+ {
+ metadata: { version: 'v14.8' },
+ },
+ {
+ metadata: { version: 'v14.8' },
+ },
+ ],
+ },
+ tokens: {
+ nodes: [
+ {
+ lastUsedAt: connectedTimeNow,
+ },
+ ],
+ },
+ },
+ {
+ name: 'agent-3',
+ id: 'agent-3-id',
+ webPath: '/agent-3',
+ status: 'inactive',
+ lastContact: connectedTimeInactive.getTime(),
+ connections: {
+ nodes: [
+ {
+ metadata: { version: 'v14.5' },
+ },
+ ],
+ },
+ tokens: {
+ nodes: [
+ {
+ lastUsedAt: connectedTimeInactive,
+ },
+ ],
+ },
+ },
+ {
+ name: 'agent-4',
+ id: 'agent-4-id',
+ webPath: '/agent-4',
+ status: 'inactive',
+ lastContact: connectedTimeInactive.getTime(),
+ connections: {
+ nodes: [
+ {
+ metadata: { version: 'v14.7' },
+ },
+ {
+ metadata: { version: 'v14.8' },
+ },
+ ],
+ },
+ tokens: {
+ nodes: [
+ {
+ lastUsedAt: connectedTimeInactive,
+ },
+ ],
+ },
+ },
+ {
+ name: 'agent-5',
+ id: 'agent-5-id',
+ webPath: '/agent-5',
+ status: 'inactive',
+ lastContact: connectedTimeInactive.getTime(),
+ connections: {
+ nodes: [
+ {
+ metadata: { version: 'v14.5' },
+ },
+ {
+ metadata: { version: 'v14.3' },
+ },
+ ],
+ },
+ tokens: {
+ nodes: [
+ {
+ lastUsedAt: connectedTimeInactive,
+ },
+ ],
+ },
+ },
+];
diff --git a/spec/frontend/clusters_list/components/node_error_help_text_spec.js b/spec/frontend/clusters_list/components/node_error_help_text_spec.js
index 18d27f3fd80..8187ab75c58 100644
--- a/spec/frontend/clusters_list/components/node_error_help_text_spec.js
+++ b/spec/frontend/clusters_list/components/node_error_help_text_spec.js
@@ -1,13 +1,14 @@
import { GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import NodeErrorHelpText from '~/clusters_list/components/node_error_help_text.vue';
describe('NodeErrorHelpText', () => {
let wrapper;
- const createWrapper = (propsData) => {
+ const createWrapper = async (propsData) => {
wrapper = shallowMount(NodeErrorHelpText, { propsData, stubs: { GlPopover } });
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const findPopover = () => wrapper.find(GlPopover);
diff --git a/spec/frontend/clusters_list/mocks/apollo.js b/spec/frontend/clusters_list/mocks/apollo.js
index c4a31ed4394..b0f2978a230 100644
--- a/spec/frontend/clusters_list/mocks/apollo.js
+++ b/spec/frontend/clusters_list/mocks/apollo.js
@@ -10,6 +10,9 @@ const token = {
const tokens = {
nodes: [token],
};
+const connections = {
+ nodes: [],
+};
const pageInfo = {
endCursor: '',
hasNextPage: false,
@@ -23,6 +26,7 @@ export const createAgentResponse = {
createClusterAgent: {
clusterAgent: {
...agent,
+ connections,
tokens,
},
errors: [],
@@ -35,6 +39,7 @@ export const createAgentErrorResponse = {
createClusterAgent: {
clusterAgent: {
...agent,
+ connections,
tokens,
},
errors: ['could not create agent'],
@@ -65,8 +70,9 @@ export const createAgentTokenErrorResponse = {
export const getAgentResponse = {
data: {
project: {
+ __typename: 'Project',
id: 'project-1',
- clusterAgents: { nodes: [{ ...agent, tokens }], pageInfo, count },
+ clusterAgents: { nodes: [{ ...agent, connections, tokens }], pageInfo, count },
repository: {
tree: {
trees: { nodes: [{ ...agent, path: null }], pageInfo },
@@ -76,6 +82,11 @@ export const getAgentResponse = {
},
};
+export const kasDisabledErrorResponse = {
+ data: {},
+ errors: [{ message: 'Gitlab::Kas::Client::ConfigurationError' }],
+};
+
export const mockDeleteResponse = {
data: { clusterAgentDelete: { errors: [] } },
};
diff --git a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
index 97d9be110c8..36d2c2cabc5 100644
--- a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
+++ b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
@@ -14,7 +14,6 @@ exports[`Code navigation popover component renders popover 1`] = `
contentclass="gl-py-0"
navclass="gl-hidden"
queryparamname="tab"
- theme="indigo"
value="0"
>
<gl-tab-stub
diff --git a/spec/frontend/code_navigation/components/app_spec.js b/spec/frontend/code_navigation/components/app_spec.js
index 798f3bc0ee2..9306c15e676 100644
--- a/spec/frontend/code_navigation/components/app_spec.js
+++ b/spec/frontend/code_navigation/components/app_spec.js
@@ -1,15 +1,15 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import App from '~/code_navigation/components/app.vue';
import Popover from '~/code_navigation/components/popover.vue';
import createState from '~/code_navigation/store/state';
-const localVue = createLocalVue();
const fetchData = jest.fn();
const showDefinition = jest.fn();
let wrapper;
-localVue.use(Vuex);
+Vue.use(Vuex);
function factory(initialState = {}) {
const store = new Vuex.Store({
@@ -24,7 +24,7 @@ function factory(initialState = {}) {
},
});
- wrapper = shallowMount(App, { store, localVue });
+ wrapper = shallowMount(App, { store });
}
describe('Code navigation app component', () => {
diff --git a/spec/frontend/code_quality_walkthrough/components/step_spec.js b/spec/frontend/code_quality_walkthrough/components/step_spec.js
index bdbcda5f902..b43629c2f96 100644
--- a/spec/frontend/code_quality_walkthrough/components/step_spec.js
+++ b/spec/frontend/code_quality_walkthrough/components/step_spec.js
@@ -118,7 +118,7 @@ describe('When the code_quality_walkthrough URL parameter is present', () => {
expect(Cookies.set).toHaveBeenCalledWith(
EXPERIMENT_NAME,
{ commit_ci_file: true, data: dummyContext },
- { expires: 365 },
+ { expires: 365, secure: false },
);
});
diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js
index 3a549e66eb7..43db6db00c1 100644
--- a/spec/frontend/commit/commit_pipeline_status_component_spec.js
+++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
+import { nextTick } from 'vue';
import fixture from 'test_fixtures/pipelines/pipelines.json';
import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
@@ -112,7 +113,7 @@ describe('Commit pipeline status component', () => {
createComponent();
});
- it('shows the loading icon at start', () => {
+ it('shows the loading icon at start', async () => {
createComponent();
expect(findLoader().exists()).toBe(true);
@@ -120,17 +121,16 @@ describe('Commit pipeline status component', () => {
data: { pipelines: [] },
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findLoader().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findLoader().exists()).toBe(false);
});
describe('is successful', () => {
- beforeEach(() => {
+ beforeEach(async () => {
pollConfig.successCallback({
data: { pipelines: [{ details: { status: mockCiStatus } }] },
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not render loader', () => {
diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js
index e209f628aa2..203a4d23160 100644
--- a/spec/frontend/commit/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js
@@ -1,11 +1,14 @@
import { GlEmptyState, GlLoadingIcon, GlModal, GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import fixture from 'test_fixtures/pipelines/pipelines.json';
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 httpStatusCodes from '~/lib/utils/http_status';
+import createFlash from '~/flash';
import { TOAST_MESSAGE } from '~/pipelines/constants';
import axios from '~/lib/utils/axios_utils';
@@ -13,6 +16,8 @@ const $toast = {
show: jest.fn(),
};
+jest.mock('~/flash');
+
describe('Pipelines table in Commits and Merge requests', () => {
let wrapper;
let pipeline;
@@ -183,36 +188,61 @@ describe('Pipelines table in Commits and Merge requests', () => {
mergeRequestId: 3,
});
- jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
-
await waitForPromises();
});
+ describe('success', () => {
+ beforeEach(() => {
+ jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
+ });
+ it('displays a toast message during pipeline creation', async () => {
+ await findRunPipelineBtn().trigger('click');
- it('displays a toast message during pipeline creation', async () => {
- await findRunPipelineBtn().trigger('click');
+ expect($toast.show).toHaveBeenCalledWith(TOAST_MESSAGE);
+ });
- expect($toast.show).toHaveBeenCalledWith(TOAST_MESSAGE);
- });
+ it('on desktop, shows a loading button', async () => {
+ await findRunPipelineBtn().trigger('click');
- it('on desktop, shows a loading button', async () => {
- await findRunPipelineBtn().trigger('click');
+ expect(findRunPipelineBtn().props('loading')).toBe(true);
- expect(findRunPipelineBtn().props('loading')).toBe(true);
+ await waitForPromises();
- await waitForPromises();
+ expect(findRunPipelineBtn().props('loading')).toBe(false);
+ });
- 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);
+ });
});
- it('on mobile, shows a loading button', async () => {
- await findRunPipelineBtnMobile().trigger('click');
+ describe('failure', () => {
+ const permissionsMsg = 'You do not have permission to run a pipeline on this branch.';
- expect(findRunPipelineBtn().props('loading')).toBe(true);
+ it.each`
+ status | message
+ ${httpStatusCodes.BAD_REQUEST} | ${permissionsMsg}
+ ${httpStatusCodes.UNAUTHORIZED} | ${permissionsMsg}
+ ${httpStatusCodes.INTERNAL_SERVER_ERROR} | ${'An error occurred while trying to run a new pipeline for this merge request.'}
+ `('displays permissions error message', async ({ status, message }) => {
+ const response = { response: { status } };
- await waitForPromises();
+ jest
+ .spyOn(Api, 'postMergeRequestPipeline')
+ .mockImplementation(() => Promise.reject(response));
+
+ await findRunPipelineBtn().trigger('click');
- expect(findRunPipelineBtn().props('disabled')).toBe(false);
- expect(findRunPipelineBtn().props('loading')).toBe(false);
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({ message });
+ });
});
});
@@ -238,7 +268,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
it('on desktop, shows a security warning modal', async () => {
await findRunPipelineBtn().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findModal()).not.toBeNull();
});
diff --git a/spec/frontend/confirm_modal_spec.js b/spec/frontend/confirm_modal_spec.js
index 5e5345cbd2b..53991349ee5 100644
--- a/spec/frontend/confirm_modal_spec.js
+++ b/spec/frontend/confirm_modal_spec.js
@@ -1,4 +1,3 @@
-import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import initConfirmModal from '~/confirm_modal';
@@ -50,7 +49,6 @@ describe('ConfirmModal', () => {
const findModal = () => document.querySelector('.gl-modal');
const findModalOkButton = (modal, variant) =>
modal.querySelector(`.modal-footer .btn-${variant}`);
- const findModalCancelButton = (modal) => modal.querySelector('.modal-footer .btn-secondary');
const modalIsHidden = () => findModal() === null;
const serializeModal = (modal, buttonIndex) => {
@@ -90,20 +88,6 @@ describe('ConfirmModal', () => {
expect(findModal()).not.toBe(null);
expect(modalIsHidden()).toBe(false);
});
-
- describe('Cancel Button', () => {
- beforeEach(() => {
- findModalCancelButton(findModal()).click();
-
- return Vue.nextTick();
- });
-
- it('closes the modal', () => {
- setImmediate(() => {
- expect(modalIsHidden()).toBe(true);
- });
- });
- });
});
});
diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js
index b236c630e13..84eaa3c5f44 100644
--- a/spec/frontend/content_editor/test_utils.js
+++ b/spec/frontend/content_editor/test_utils.js
@@ -132,7 +132,7 @@ export const triggerNodeInputRule = ({ tiptapEditor, inputRuleText }) => {
export const triggerMarkInputRule = ({ tiptapEditor, inputRuleText }) => {
const { view } = tiptapEditor;
- tiptapEditor.chain().setContent(inputRuleText).setTextSelection(0).run();
+ tiptapEditor.chain().setContent(inputRuleText).setTextSelection(1).run();
const { state } = tiptapEditor;
const { selection } = state;
diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js
index cb7e13b9fed..bdf3b3636ed 100644
--- a/spec/frontend/contributors/component/contributors_spec.js
+++ b/spec/frontend/contributors/component/contributors_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import ContributorsCharts from '~/contributors/components/contributors.vue';
import { createStore } from '~/contributors/stores';
import axios from '~/lib/utils/axios_utils';
@@ -49,20 +49,18 @@ describe('Contributors charts', () => {
expect(axios.get).toHaveBeenCalledWith(endpoint);
});
- it('should display loader whiled loading data', () => {
+ it('should display loader whiled loading data', async () => {
wrapper.vm.$store.state.loading = true;
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.contributors-loader').exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find('.contributors-loader').exists()).toBe(true);
});
- it('should render charts when loading completed and there is chart data', () => {
+ it('should render charts when loading completed and there is chart data', async () => {
wrapper.vm.$store.state.loading = false;
wrapper.vm.$store.state.chartData = chartData;
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.contributors-loader').exists()).toBe(false);
- expect(wrapper.find('.contributors-charts').exists()).toBe(true);
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.find('.contributors-loader').exists()).toBe(false);
+ expect(wrapper.find('.contributors-charts').exists()).toBe(true);
+ expect(wrapper.element).toMatchSnapshot();
});
});
diff --git a/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js b/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
index 4e92fa1df16..2f835867f5f 100644
--- a/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
+++ b/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
@@ -2,6 +2,7 @@ import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import $ from 'jquery';
+import { nextTick } from 'vue';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
@@ -18,35 +19,31 @@ describe('ClusterFormDropdown', () => {
afterEach(() => wrapper.destroy());
describe('when initial value is provided', () => {
- it('sets selectedItem to initial value', () => {
+ it('sets selectedItem to initial value', async () => {
wrapper.setProps({ items, value: secondItem.value });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(secondItem.name);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(secondItem.name);
});
});
describe('when no item is selected', () => {
- it('displays placeholder text', () => {
+ it('displays placeholder text', async () => {
const placeholder = 'placeholder';
wrapper.setProps({ placeholder });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(placeholder);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(placeholder);
});
});
describe('when an item is selected', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ items });
-
- return wrapper.vm.$nextTick().then(() => {
- wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
- return wrapper.vm.$nextTick();
- });
+ await nextTick();
+ wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
+ await nextTick();
});
it('emits input event with selected item', () => {
@@ -57,18 +54,16 @@ describe('ClusterFormDropdown', () => {
describe('when multiple items are selected', () => {
const value = ['1'];
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ items, multiple: true, value });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
- return wrapper.vm.$nextTick();
- });
+
+ await nextTick();
+ wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
+
+ await nextTick();
+ wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
+
+ await nextTick();
});
it('emits input event with an array of selected items', () => {
@@ -77,9 +72,9 @@ describe('ClusterFormDropdown', () => {
});
describe('when multiple items can be selected', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ items, multiple: true, value: firstItem.value });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays a checked GlIcon next to the item', () => {
@@ -89,19 +84,18 @@ describe('ClusterFormDropdown', () => {
});
describe('when multiple values can be selected and initial value is null', () => {
- it('emits input event with an array of a single selected item', () => {
+ it('emits input event with an array of a single selected item', async () => {
wrapper.setProps({ items, multiple: true, value: null });
- return wrapper.vm.$nextTick().then(() => {
- wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
+ await nextTick();
+ wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
- expect(wrapper.emitted('input')[0]).toEqual([[firstItem.value]]);
- });
+ expect(wrapper.emitted('input')[0]).toEqual([[firstItem.value]]);
});
});
describe('when an item is selected and has a custom label property', () => {
- it('displays selected item custom label', () => {
+ it('displays selected item custom label', async () => {
const labelProperty = 'customLabel';
const label = 'Name';
const currentValue = '1';
@@ -109,9 +103,8 @@ describe('ClusterFormDropdown', () => {
wrapper.setProps({ labelProperty, items: customLabelItems, value: currentValue });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(label);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(label);
});
});
@@ -123,86 +116,79 @@ describe('ClusterFormDropdown', () => {
});
describe('when loading and loadingText is provided', () => {
- it('uses loading text as toggle button text', () => {
+ it('uses loading text as toggle button text', async () => {
const loadingText = 'loading text';
wrapper.setProps({ loading: true, loadingText });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(loadingText);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('toggleText')).toEqual(loadingText);
});
});
describe('when disabled', () => {
- it('dropdown button isDisabled', () => {
+ it('dropdown button isDisabled', async () => {
wrapper.setProps({ disabled: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('isDisabled')).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('isDisabled')).toBe(true);
});
});
describe('when disabled and disabledText is provided', () => {
- it('uses disabled text as toggle button text', () => {
+ it('uses disabled text as toggle button text', async () => {
const disabledText = 'disabled text';
wrapper.setProps({ disabled: true, disabledText });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('toggleText')).toBe(disabledText);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).props('toggleText')).toBe(disabledText);
});
});
describe('when has errors', () => {
- it('sets border-danger class selector to dropdown toggle', () => {
+ it('sets border-danger class selector to dropdown toggle', async () => {
wrapper.setProps({ hasErrors: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).classes('border-danger')).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownButton).classes('border-danger')).toBe(true);
});
});
describe('when has errors and an error message', () => {
- it('displays error message', () => {
+ it('displays error message', async () => {
const errorMessage = 'error message';
wrapper.setProps({ hasErrors: true, errorMessage });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.js-eks-dropdown-error-message').text()).toEqual(errorMessage);
- });
+ await nextTick();
+ expect(wrapper.find('.js-eks-dropdown-error-message').text()).toEqual(errorMessage);
});
});
describe('when no results are available', () => {
- it('displays empty text', () => {
+ it('displays empty text', async () => {
const emptyText = 'error message';
wrapper.setProps({ items: [], emptyText });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.js-empty-text').text()).toEqual(emptyText);
- });
+ await nextTick();
+ expect(wrapper.find('.js-empty-text').text()).toEqual(emptyText);
});
});
- it('displays search field placeholder', () => {
+ it('displays search field placeholder', async () => {
const searchFieldPlaceholder = 'Placeholder';
wrapper.setProps({ searchFieldPlaceholder });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownSearchInput).props('placeholderText')).toEqual(
- searchFieldPlaceholder,
- );
- });
+ await nextTick();
+ expect(wrapper.find(DropdownSearchInput).props('placeholderText')).toEqual(
+ searchFieldPlaceholder,
+ );
});
- it('it filters results by search query', () => {
+ it('it filters results by search query', async () => {
const searchQuery = secondItem.name;
wrapper.setProps({ items });
@@ -210,21 +196,19 @@ describe('ClusterFormDropdown', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ searchQuery });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll('.js-dropdown-item').length).toEqual(1);
- expect(wrapper.find('.js-dropdown-item').text()).toEqual(secondItem.name);
- });
+ await nextTick();
+ expect(wrapper.findAll('.js-dropdown-item').length).toEqual(1);
+ expect(wrapper.find('.js-dropdown-item').text()).toEqual(secondItem.name);
});
- it('focuses dropdown search input when dropdown is displayed', () => {
+ it('focuses dropdown search input when dropdown is displayed', async () => {
const dropdownEl = wrapper.find('.dropdown').element;
expect(wrapper.find(DropdownSearchInput).props('focused')).toBe(false);
$(dropdownEl).trigger('shown.bs.dropdown');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(DropdownSearchInput).props('focused')).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownSearchInput).props('focused')).toBe(true);
});
});
diff --git a/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js b/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js
index 95810e882a1..c8020cf8308 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import CreateEksCluster from '~/create_cluster/eks_cluster/components/create_eks_cluster.vue';
import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue';
import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('CreateEksCluster', () => {
let vm;
@@ -33,7 +33,6 @@ describe('CreateEksCluster', () => {
externalLinkIcon,
kubernetesIntegrationHelpPath,
},
- localVue,
store,
});
});
diff --git a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
index 53a6f12c381..1509d26c99d 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
@@ -1,14 +1,13 @@
import { GlFormCheckbox } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue';
import eksClusterFormState from '~/create_cluster/eks_cluster/store/state';
import clusterDropdownStoreState from '~/create_cluster/store/cluster_dropdown/state';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('EksClusterConfigurationForm', () => {
let store;
@@ -151,7 +150,6 @@ describe('EksClusterConfigurationForm', () => {
const buildWrapper = () => {
vm = shallowMount(EksClusterConfigurationForm, {
- localVue,
store,
propsData: {
gitlabManagedClusterHelpPath: '',
@@ -225,108 +223,98 @@ describe('EksClusterConfigurationForm', () => {
});
});
- it('sets isLoadingRoles to RoleDropdown loading property', () => {
+ it('sets isLoadingRoles to RoleDropdown loading property', async () => {
rolesState.isLoadingItems = true;
- return Vue.nextTick().then(() => {
- expect(findRoleDropdown().props('loading')).toBe(rolesState.isLoadingItems);
- });
+ await nextTick();
+ expect(findRoleDropdown().props('loading')).toBe(rolesState.isLoadingItems);
});
it('sets roles to RoleDropdown items property', () => {
expect(findRoleDropdown().props('items')).toBe(rolesState.items);
});
- it('sets RoleDropdown hasErrors to true when loading roles failed', () => {
+ it('sets RoleDropdown hasErrors to true when loading roles failed', async () => {
rolesState.loadingItemsError = new Error();
- return Vue.nextTick().then(() => {
- expect(findRoleDropdown().props('hasErrors')).toEqual(true);
- });
+ await nextTick();
+ expect(findRoleDropdown().props('hasErrors')).toEqual(true);
});
it('disables KeyPairDropdown when no region is selected', () => {
expect(findKeyPairDropdown().props('disabled')).toBe(true);
});
- it('enables KeyPairDropdown when no region is selected', () => {
+ it('enables KeyPairDropdown when no region is selected', async () => {
state.selectedRegion = { name: 'west-1 ' };
- return Vue.nextTick().then(() => {
- expect(findKeyPairDropdown().props('disabled')).toBe(false);
- });
+ await nextTick();
+ expect(findKeyPairDropdown().props('disabled')).toBe(false);
});
- it('sets isLoadingKeyPairs to KeyPairDropdown loading property', () => {
+ it('sets isLoadingKeyPairs to KeyPairDropdown loading property', async () => {
keyPairsState.isLoadingItems = true;
- return Vue.nextTick().then(() => {
- expect(findKeyPairDropdown().props('loading')).toBe(keyPairsState.isLoadingItems);
- });
+ await nextTick();
+ expect(findKeyPairDropdown().props('loading')).toBe(keyPairsState.isLoadingItems);
});
it('sets keyPairs to KeyPairDropdown items property', () => {
expect(findKeyPairDropdown().props('items')).toBe(keyPairsState.items);
});
- it('sets KeyPairDropdown hasErrors to true when loading key pairs fails', () => {
+ it('sets KeyPairDropdown hasErrors to true when loading key pairs fails', async () => {
keyPairsState.loadingItemsError = new Error();
- return Vue.nextTick().then(() => {
- expect(findKeyPairDropdown().props('hasErrors')).toEqual(true);
- });
+ await nextTick();
+ expect(findKeyPairDropdown().props('hasErrors')).toEqual(true);
});
it('disables VpcDropdown when no region is selected', () => {
expect(findVpcDropdown().props('disabled')).toBe(true);
});
- it('enables VpcDropdown when no region is selected', () => {
+ it('enables VpcDropdown when no region is selected', async () => {
state.selectedRegion = { name: 'west-1 ' };
- return Vue.nextTick().then(() => {
- expect(findVpcDropdown().props('disabled')).toBe(false);
- });
+ await nextTick();
+ expect(findVpcDropdown().props('disabled')).toBe(false);
});
- it('sets isLoadingVpcs to VpcDropdown loading property', () => {
+ it('sets isLoadingVpcs to VpcDropdown loading property', async () => {
vpcsState.isLoadingItems = true;
- return Vue.nextTick().then(() => {
- expect(findVpcDropdown().props('loading')).toBe(vpcsState.isLoadingItems);
- });
+ await nextTick();
+ expect(findVpcDropdown().props('loading')).toBe(vpcsState.isLoadingItems);
});
it('sets vpcs to VpcDropdown items property', () => {
expect(findVpcDropdown().props('items')).toBe(vpcsState.items);
});
- it('sets VpcDropdown hasErrors to true when loading vpcs fails', () => {
+ it('sets VpcDropdown hasErrors to true when loading vpcs fails', async () => {
vpcsState.loadingItemsError = new Error();
- return Vue.nextTick().then(() => {
- expect(findVpcDropdown().props('hasErrors')).toEqual(true);
- });
+ await nextTick();
+ expect(findVpcDropdown().props('hasErrors')).toEqual(true);
});
it('disables SubnetDropdown when no vpc is selected', () => {
expect(findSubnetDropdown().props('disabled')).toBe(true);
});
- it('enables SubnetDropdown when a vpc is selected', () => {
+ it('enables SubnetDropdown when a vpc is selected', async () => {
state.selectedVpc = { name: 'vpc-1 ' };
- return Vue.nextTick().then(() => {
- expect(findSubnetDropdown().props('disabled')).toBe(false);
- });
+ await nextTick();
+ expect(findSubnetDropdown().props('disabled')).toBe(false);
});
- it('sets isLoadingSubnets to SubnetDropdown loading property', () => {
+ it('sets isLoadingSubnets to SubnetDropdown loading property', async () => {
subnetsState.isLoadingItems = true;
- return Vue.nextTick().then(() => {
- expect(findSubnetDropdown().props('loading')).toBe(subnetsState.isLoadingItems);
- });
+ await nextTick();
+ expect(findSubnetDropdown().props('loading')).toBe(subnetsState.isLoadingItems);
});
it('sets subnets to SubnetDropdown items property', () => {
@@ -362,32 +350,29 @@ describe('EksClusterConfigurationForm', () => {
expect(findSecurityGroupDropdown().props('disabled')).toBe(true);
});
- it('enables SecurityGroupDropdown when a vpc is selected', () => {
+ it('enables SecurityGroupDropdown when a vpc is selected', async () => {
state.selectedVpc = { name: 'vpc-1 ' };
- return Vue.nextTick().then(() => {
- expect(findSecurityGroupDropdown().props('disabled')).toBe(false);
- });
+ await nextTick();
+ expect(findSecurityGroupDropdown().props('disabled')).toBe(false);
});
- it('sets isLoadingSecurityGroups to SecurityGroupDropdown loading property', () => {
+ it('sets isLoadingSecurityGroups to SecurityGroupDropdown loading property', async () => {
securityGroupsState.isLoadingItems = true;
- return Vue.nextTick().then(() => {
- expect(findSecurityGroupDropdown().props('loading')).toBe(securityGroupsState.isLoadingItems);
- });
+ await nextTick();
+ expect(findSecurityGroupDropdown().props('loading')).toBe(securityGroupsState.isLoadingItems);
});
it('sets securityGroups to SecurityGroupDropdown items property', () => {
expect(findSecurityGroupDropdown().props('items')).toBe(securityGroupsState.items);
});
- it('sets SecurityGroupDropdown hasErrors to true when loading security groups fails', () => {
+ it('sets SecurityGroupDropdown hasErrors to true when loading security groups fails', async () => {
securityGroupsState.loadingItemsError = new Error();
- return Vue.nextTick().then(() => {
- expect(findSecurityGroupDropdown().props('hasErrors')).toEqual(true);
- });
+ await nextTick();
+ expect(findSecurityGroupDropdown().props('hasErrors')).toEqual(true);
});
it('dispatches setClusterName when cluster name input changes', () => {
diff --git a/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
index a0510d46794..0d823a18012 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
@@ -1,11 +1,11 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
import eksClusterState from '~/create_cluster/eks_cluster/store/state';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ServiceCredentialsForm', () => {
let vm;
@@ -33,7 +33,6 @@ describe('ServiceCredentialsForm', () => {
createRoleArnHelpPath: '',
externalLinkIcon: '',
},
- localVue,
store,
});
});
@@ -66,14 +65,13 @@ describe('ServiceCredentialsForm', () => {
expect(findSubmitButton().attributes('disabled')).toBeTruthy();
});
- it('enables submit button when role ARN is not provided', () => {
+ it('enables submit button when role ARN is not provided', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ roleArn: '123' });
- return vm.vm.$nextTick().then(() => {
- expect(findSubmitButton().attributes('disabled')).toBeFalsy();
- });
+ await nextTick();
+ expect(findSubmitButton().attributes('disabled')).toBeFalsy();
});
it('dispatches createRole action when submit button is clicked', () => {
@@ -87,14 +85,14 @@ describe('ServiceCredentialsForm', () => {
});
describe('when is creating role', () => {
- beforeEach(() => {
+ beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ roleArn: '123' }); // set role ARN to enable button
state.isCreatingRole = true;
- return vm.vm.$nextTick();
+ await nextTick();
});
it('disables submit button', () => {
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
index 2b6f2134553..f46b84da939 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import GkeMachineTypeDropdown from '~/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue';
import createState from '~/create_cluster/gke_cluster/store/state';
@@ -19,15 +20,12 @@ const LABELS = {
DEFAULT: 'Select machine type',
};
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
const createComponent = (store, propsData = componentConfig) =>
shallowMount(GkeMachineTypeDropdown, {
propsData,
store,
- localVue,
});
const createStore = (initialState = {}, getters = {}) =>
@@ -75,7 +73,7 @@ describe('GkeMachineTypeDropdown', () => {
expect(dropdownButtonLabel()).toBe(LABELS.DISABLED_NO_ZONE);
});
- it('returns loading toggle text', () => {
+ it('returns loading toggle text', async () => {
store = createStore();
wrapper = createComponent(store);
@@ -83,9 +81,8 @@ describe('GkeMachineTypeDropdown', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdownButtonLabel()).toBe(LABELS.LOADING);
- });
+ await nextTick();
+ expect(dropdownButtonLabel()).toBe(LABELS.LOADING);
});
it('returns default toggle text', () => {
@@ -115,7 +112,7 @@ describe('GkeMachineTypeDropdown', () => {
});
describe('form input', () => {
- it('reflects new value when dropdown item is clicked', () => {
+ it('reflects new value when dropdown item is clicked', async () => {
store = createStore({
machineTypes: gapiMachineTypesResponseMock.items,
});
@@ -125,9 +122,8 @@ describe('GkeMachineTypeDropdown', () => {
wrapper.find('.dropdown-content button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(setMachineType).toHaveBeenCalledWith(expect.anything(), selectedMachineTypeMock);
- });
+ await nextTick();
+ expect(setMachineType).toHaveBeenCalledWith(expect.anything(), selectedMachineTypeMock);
});
});
});
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
index 23a56766037..addb0ef72a0 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
@@ -1,12 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
import GkeNetworkDropdown from '~/create_cluster/gke_cluster/components/gke_network_dropdown.vue';
import createClusterDropdownState from '~/create_cluster/store/cluster_dropdown/state';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GkeNetworkDropdown', () => {
let wrapper;
@@ -54,7 +53,6 @@ describe('GkeNetworkDropdown', () => {
shallowMount(GkeNetworkDropdown, {
propsData,
store,
- localVue,
});
afterEach(() => {
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
index 2b0acc8cf5d..36f8d4bd1e8 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import GkeProjectIdDropdown from '~/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue';
import createState from '~/create_cluster/gke_cluster/store/state';
@@ -19,9 +20,7 @@ const LABELS = {
EMPTY: 'No projects found',
};
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GkeProjectIdDropdown', () => {
let wrapper;
@@ -52,7 +51,6 @@ describe('GkeProjectIdDropdown', () => {
shallowMount(GkeProjectIdDropdown, {
propsData,
store,
- localVue,
});
const bootstrap = (initialState, getters) => {
@@ -80,19 +78,18 @@ describe('GkeProjectIdDropdown', () => {
expect(dropdownButtonLabel()).toBe(LABELS.VALIDATING_PROJECT_BILLING);
});
- it('returns default toggle text', () => {
+ it('returns default toggle text', async () => {
bootstrap();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdownButtonLabel()).toBe(LABELS.DEFAULT);
- });
+ await nextTick();
+ expect(dropdownButtonLabel()).toBe(LABELS.DEFAULT);
});
- it('returns project name if project selected', () => {
+ it('returns project name if project selected', async () => {
bootstrap(
{
selectedProject: selectedProjectMock,
@@ -105,12 +102,11 @@ describe('GkeProjectIdDropdown', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdownButtonLabel()).toBe(selectedProjectMock.name);
- });
+ await nextTick();
+ expect(dropdownButtonLabel()).toBe(selectedProjectMock.name);
});
- it('returns empty toggle text', () => {
+ it('returns empty toggle text', async () => {
bootstrap({
projects: null,
});
@@ -118,26 +114,24 @@ describe('GkeProjectIdDropdown', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdownButtonLabel()).toBe(LABELS.EMPTY);
- });
+ await nextTick();
+ expect(dropdownButtonLabel()).toBe(LABELS.EMPTY);
});
});
describe('selectItem', () => {
- it('reflects new value when dropdown item is clicked', () => {
+ it('reflects new value when dropdown item is clicked', async () => {
bootstrap({ projects: gapiProjectsResponseMock.projects });
expect(dropdownHiddenInputValue()).toBe('');
wrapper.find('.dropdown-content button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(setProject).toHaveBeenCalledWith(
- expect.anything(),
- gapiProjectsResponseMock.projects[0],
- );
- });
+ await nextTick();
+ expect(setProject).toHaveBeenCalledWith(
+ expect.anything(),
+ gapiProjectsResponseMock.projects[0],
+ );
});
});
});
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js
index 014ed6013bd..2bf9158628c 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js
@@ -1,10 +1,9 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import GkeSubmitButton from '~/create_cluster/gke_cluster/components/gke_submit_button.vue';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GkeSubmitButton', () => {
let wrapper;
@@ -21,7 +20,6 @@ describe('GkeSubmitButton', () => {
const buildWrapper = () =>
shallowMount(GkeSubmitButton, {
store,
- localVue,
});
const bootstrap = () => {
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
index cfa8a678a9b..9df680d94b5 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
@@ -1,12 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
import GkeSubnetworkDropdown from '~/create_cluster/gke_cluster/components/gke_subnetwork_dropdown.vue';
import createClusterDropdownState from '~/create_cluster/store/cluster_dropdown/state';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GkeSubnetworkDropdown', () => {
let wrapper;
@@ -41,7 +40,6 @@ describe('GkeSubnetworkDropdown', () => {
shallowMount(GkeSubnetworkDropdown, {
propsData,
store,
- localVue,
});
afterEach(() => {
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
index 22fc681f863..7b4c228b879 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import GkeZoneDropdown from '~/create_cluster/gke_cluster/components/gke_zone_dropdown.vue';
import { createStore } from '~/create_cluster/gke_cluster/store';
import {
@@ -46,11 +47,11 @@ describe('GkeZoneDropdown', () => {
});
describe('isLoading', () => {
- beforeEach(() => {
+ beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: true });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('returns loading toggle text', () => {
@@ -59,10 +60,10 @@ describe('GkeZoneDropdown', () => {
});
describe('project is set', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.$store.commit(SET_PROJECT, selectedProjectMock);
wrapper.vm.$store.commit(SET_PROJECT_BILLING_STATUS, true);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('returns default toggle text', () => {
@@ -71,9 +72,9 @@ describe('GkeZoneDropdown', () => {
});
describe('project is selected', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.setItem(selectedZoneMock);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('returns project name if project selected', () => {
@@ -83,21 +84,20 @@ describe('GkeZoneDropdown', () => {
});
describe('selectItem', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.$store.commit(SET_ZONES, gapiZonesResponseMock.items);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('reflects new value when dropdown item is clicked', () => {
+ it('reflects new value when dropdown item is clicked', async () => {
const dropdown = wrapper.find(DropdownHiddenInput);
expect(dropdown.attributes('value')).toBe('');
wrapper.find('.dropdown-content button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdown.attributes('value')).toBe(selectedZoneMock);
- });
+ await nextTick();
+ expect(dropdown.attributes('value')).toBe(selectedZoneMock);
});
});
});
diff --git a/spec/frontend/cycle_analytics/base_spec.js b/spec/frontend/cycle_analytics/base_spec.js
index 9a9415cc12a..7b1ef71da63 100644
--- a/spec/frontend/cycle_analytics/base_spec.js
+++ b/spec/frontend/cycle_analytics/base_spec.js
@@ -3,11 +3,11 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
import BaseComponent from '~/cycle_analytics/components/base.vue';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import StageTable from '~/cycle_analytics/components/stage_table.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
-import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
import { NOT_ENOUGH_DATA_ERROR } from '~/cycle_analytics/constants';
import initState from '~/cycle_analytics/store/state';
import {
diff --git a/spec/frontend/cycle_analytics/filter_bar_spec.js b/spec/frontend/cycle_analytics/filter_bar_spec.js
index 407f21bd956..36933790cf7 100644
--- a/spec/frontend/cycle_analytics/filter_bar_spec.js
+++ b/spec/frontend/cycle_analytics/filter_bar_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
@@ -15,8 +16,7 @@ import * as utils from '~/vue_shared/components/filtered_search_bar/filtered_sea
import initialFiltersState from '~/vue_shared/components/filtered_search_bar/store/modules/filters/state';
import UrlSync from '~/vue_shared/components/url_sync.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const milestoneTokenType = 'milestone';
const labelsTokenType = 'labels';
@@ -42,7 +42,7 @@ const defaultParams = {
};
async function shouldMergeUrlParams(wrapper, result) {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(urlUtils.mergeUrlParams).toHaveBeenCalledWith(result, window.location.href, {
spreadArrays: true,
});
@@ -77,7 +77,6 @@ describe('Filter bar', () => {
const createComponent = (initialStore) => {
return shallowMount(FilterBar, {
- localVue,
store: initialStore,
propsData: {
groupPath: 'foo',
diff --git a/spec/frontend/cycle_analytics/stage_table_spec.js b/spec/frontend/cycle_analytics/stage_table_spec.js
index 9605dce2668..107fe5fc865 100644
--- a/spec/frontend/cycle_analytics/stage_table_spec.js
+++ b/spec/frontend/cycle_analytics/stage_table_spec.js
@@ -1,5 +1,6 @@
import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import StageTable from '~/cycle_analytics/components/stage_table.vue';
@@ -263,7 +264,7 @@ describe('StageTable', () => {
expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined();
findPagination().vm.$emit('input', 2);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([{ page: 2 }]);
});
diff --git a/spec/frontend/cycle_analytics/utils_spec.js b/spec/frontend/cycle_analytics/utils_spec.js
index a6d6d022781..51405a1ba4d 100644
--- a/spec/frontend/cycle_analytics/utils_spec.js
+++ b/spec/frontend/cycle_analytics/utils_spec.js
@@ -1,13 +1,10 @@
-import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import {
transformStagesForPathNavigation,
medianTimeToParsedSeconds,
formatMedianValues,
filterStagesByHiddenStatus,
- prepareTimeMetricsData,
buildCycleAnalyticsInitialData,
} from '~/cycle_analytics/utils';
-import { slugify } from '~/lib/utils/text_utility';
import {
selectedStage,
allowedStages,
@@ -89,34 +86,6 @@ describe('Value stream analytics utils', () => {
});
});
- describe('prepareTimeMetricsData', () => {
- let prepared;
- const [first, second] = metricsData;
- const firstKey = slugify(first.title);
- const secondKey = slugify(second.title);
-
- beforeEach(() => {
- prepared = prepareTimeMetricsData([first, second], {
- [firstKey]: { description: 'Is a value that is good' },
- });
- });
-
- it('will add a `key` based on the title', () => {
- expect(prepared).toMatchObject([{ key: firstKey }, { key: secondKey }]);
- });
-
- it('will add a `label` key', () => {
- expect(prepared).toMatchObject([{ label: 'New Issues' }, { label: 'Commits' }]);
- });
-
- it('will add a popover description using the key if it is provided', () => {
- expect(prepared).toMatchObject([
- { description: 'Is a value that is good' },
- { description: '' },
- ]);
- });
- });
-
describe('buildCycleAnalyticsInitialData', () => {
let res = null;
const projectId = '5';
diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
index 082db2cc312..7a539b262fc 100644
--- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
+++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
@@ -1,20 +1,22 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import waitForPromises from 'helpers/wait_for_promises';
+import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
-import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
+import { METRICS_POPOVER_CONTENT } from '~/analytics/shared/constants';
+import { prepareTimeMetricsData } from '~/analytics/shared/utils';
+import MetricTile from '~/analytics/shared/components/metric_tile.vue';
import createFlash from '~/flash';
-import { redirectTo } from '~/lib/utils/url_utility';
import { group } from './mock_data';
jest.mock('~/flash');
-jest.mock('~/lib/utils/url_utility');
describe('ValueStreamMetrics', () => {
let wrapper;
let mockGetValueStreamSummaryMetrics;
+ let mockFilterFn;
const { full_path: requestPath } = group;
const fakeReqName = 'Mock metrics';
@@ -24,17 +26,18 @@ describe('ValueStreamMetrics', () => {
name: fakeReqName,
});
- const createComponent = ({ requestParams = {} } = {}) => {
+ const createComponent = (props = {}) => {
return shallowMount(ValueStreamMetrics, {
propsData: {
requestPath,
- requestParams,
+ requestParams: {},
requests: [metricsRequestFactory()],
+ ...props,
},
});
};
- const findMetrics = () => wrapper.findAllComponents(GlSingleStat);
+ const findMetrics = () => wrapper.findAllComponents(MetricTile);
const expectToHaveRequest = (fields) => {
expect(mockGetValueStreamSummaryMetrics).toHaveBeenCalledWith({
@@ -55,19 +58,19 @@ describe('ValueStreamMetrics', () => {
});
it('will display a loader with pending requests', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findComponent(GlSkeletonLoading).exists()).toBe(true);
});
- it('renders hidden GlSingleStat components for each metric', async () => {
+ it('renders hidden MetricTile components for each metric', async () => {
await waitForPromises();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isLoading: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
const components = findMetrics();
@@ -88,35 +91,52 @@ describe('ValueStreamMetrics', () => {
});
describe.each`
- index | value | title | unit | clickable
- ${0} | ${metricsData[0].value} | ${metricsData[0].title} | ${metricsData[0].unit} | ${false}
- ${1} | ${metricsData[1].value} | ${metricsData[1].title} | ${metricsData[1].unit} | ${false}
- ${2} | ${metricsData[2].value} | ${metricsData[2].title} | ${metricsData[2].unit} | ${false}
- ${3} | ${metricsData[3].value} | ${metricsData[3].title} | ${metricsData[3].unit} | ${true}
- `('metric tiles', ({ index, value, title, unit, clickable }) => {
- it(`renders a single stat component for "${title}" with value and unit`, () => {
+ index | identifier | value | label
+ ${0} | ${metricsData[0].identifier} | ${metricsData[0].value} | ${metricsData[0].title}
+ ${1} | ${metricsData[1].identifier} | ${metricsData[1].value} | ${metricsData[1].title}
+ ${2} | ${metricsData[2].identifier} | ${metricsData[2].value} | ${metricsData[2].title}
+ ${3} | ${metricsData[3].identifier} | ${metricsData[3].value} | ${metricsData[3].title}
+ `('metric tiles', ({ identifier, index, value, label }) => {
+ it(`renders a metric tile component for "${label}"`, () => {
const metric = findMetrics().at(index);
- expect(metric.props()).toMatchObject({ value, title, unit: unit ?? '' });
+ expect(metric.props('metric')).toMatchObject({ identifier, value, label });
expect(metric.isVisible()).toBe(true);
});
-
- it(`${
- clickable ? 'redirects' : "doesn't redirect"
- } when the user clicks the "${title}" metric`, () => {
- const metric = findMetrics().at(index);
- metric.vm.$emit('click');
- if (clickable) {
- expect(redirectTo).toHaveBeenCalledWith(metricsData[index].links[0].url);
- } else {
- expect(redirectTo).not.toHaveBeenCalled();
- }
- });
});
it('will not display a loading icon', () => {
expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
});
+ describe('filterFn', () => {
+ const transferedMetricsData = prepareTimeMetricsData(metricsData, METRICS_POPOVER_CONTENT);
+
+ it('with a filter function, will call the function with the metrics data', async () => {
+ const filteredData = [
+ { identifier: 'issues', value: '3', title: 'New Issues', description: 'foo' },
+ ];
+ mockFilterFn = jest.fn(() => filteredData);
+
+ wrapper = createComponent({
+ filterFn: mockFilterFn,
+ });
+
+ await waitForPromises();
+
+ expect(mockFilterFn).toHaveBeenCalledWith(transferedMetricsData);
+ expect(wrapper.vm.metrics).toEqual(filteredData);
+ });
+
+ it('without a filter function, it will only update the metrics', async () => {
+ wrapper = createComponent();
+
+ await waitForPromises();
+
+ expect(mockFilterFn).not.toHaveBeenCalled();
+ expect(wrapper.vm.metrics).toEqual(transferedMetricsData);
+ });
+ });
+
describe('with additional params', () => {
beforeEach(async () => {
wrapper = createComponent({
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
index 392652292cf..cc044800e5e 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import DeployFreezeSettings from '~/deploy_freeze/components/deploy_freeze_settings.vue';
@@ -6,8 +7,7 @@ import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vu
import createStore from '~/deploy_freeze/store';
import { timezoneDataFixture } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Deploy freeze settings', () => {
let wrapper;
@@ -20,7 +20,6 @@ describe('Deploy freeze settings', () => {
});
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = shallowMount(DeployFreezeSettings, {
- localVue,
store,
});
});
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
index 403d0dce3fc..137776edfab 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
@@ -1,13 +1,13 @@
import { GlModal } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Deploy freeze table', () => {
let wrapper;
@@ -21,7 +21,6 @@ describe('Deploy freeze table', () => {
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mount(DeployFreezeTable, {
attachTo: document.body,
- localVue,
store,
});
};
@@ -57,7 +56,7 @@ describe('Deploy freeze table', () => {
describe('with data', () => {
beforeEach(async () => {
store.commit(RECEIVE_FREEZE_PERIODS_SUCCESS, freezePeriodsFixture);
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays data', () => {
@@ -69,7 +68,7 @@ describe('Deploy freeze table', () => {
it('allows user to edit deploy freeze', async () => {
findEditDeployFreezeButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(store.dispatch).toHaveBeenCalledWith(
'setFreezePeriod',
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 5f4d4071f29..aea81daecef 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,12 +1,12 @@
import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import createStore from '~/deploy_freeze/store';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import { findTzByName, formatTz, timezoneDataFixture } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Deploy freeze timezone dropdown', () => {
let wrapper;
@@ -19,7 +19,6 @@ describe('Deploy freeze timezone dropdown', () => {
});
wrapper = shallowMount(TimezoneDropdown, {
store,
- localVue,
propsData: {
value: selectedTimezone,
timezoneData: timezoneDataFixture,
diff --git a/spec/frontend/deploy_keys/components/action_btn_spec.js b/spec/frontend/deploy_keys/components/action_btn_spec.js
index 6ac68061518..c4c7a9aea2d 100644
--- a/spec/frontend/deploy_keys/components/action_btn_spec.js
+++ b/spec/frontend/deploy_keys/components/action_btn_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import data from 'test_fixtures/deploy_keys/keys.json';
import actionBtn from '~/deploy_keys/components/action_btn.vue';
import eventHub from '~/deploy_keys/eventhub';
@@ -37,21 +38,19 @@ describe('Deploy keys action btn', () => {
});
});
- it('sends eventHub event with btn type', () => {
+ it('sends eventHub event with btn type', async () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
findButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('enable.key', deployKey, expect.anything());
- });
+ await nextTick();
+ expect(eventHub.$emit).toHaveBeenCalledWith('enable.key', deployKey, expect.anything());
});
- it('shows loading spinner after click', () => {
+ it('shows loading spinner after click', async () => {
findButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findButton().props('loading')).toBe(true);
- });
+ await nextTick();
+ expect(findButton().props('loading')).toBe(true);
});
});
diff --git a/spec/frontend/deploy_keys/components/app_spec.js b/spec/frontend/deploy_keys/components/app_spec.js
index 598b7a0f173..79a9aaa9184 100644
--- a/spec/frontend/deploy_keys/components/app_spec.js
+++ b/spec/frontend/deploy_keys/components/app_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import data from 'test_fixtures/deploy_keys/keys.json';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
@@ -39,20 +40,18 @@ describe('Deploy keys app component', () => {
const findKeyPanels = () => wrapper.findAll('.deploy-keys .gl-tabs-nav li');
const findModal = () => wrapper.findComponent(ConfirmModal);
- it('renders loading icon while waiting for request', () => {
+ it('renders loading icon while waiting for request', async () => {
mock.onGet(TEST_ENDPOINT).reply(() => new Promise());
mountComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(findLoadingIcon().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findLoadingIcon().exists()).toBe(true);
});
- it('renders keys panels', () => {
- return mountComponent().then(() => {
- expect(findKeyPanels().length).toBe(3);
- });
+ it('renders keys panels', async () => {
+ await mountComponent();
+ expect(findKeyPanels().length).toBe(3);
});
it.each`
@@ -75,72 +74,55 @@ describe('Deploy keys app component', () => {
});
});
- it('re-fetches deploy keys when enabling a key', () => {
+ it('re-fetches deploy keys when enabling a key', async () => {
const key = data.public_keys[0];
- return mountComponent()
- .then(() => {
- jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'enableKey').mockImplementation(() => Promise.resolve());
-
- eventHub.$emit('enable.key', key);
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.vm.service.enableKey).toHaveBeenCalledWith(key.id);
- expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
- });
+ await mountComponent();
+ jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'enableKey').mockImplementation(() => Promise.resolve());
+
+ eventHub.$emit('enable.key', key);
+
+ await nextTick();
+ expect(wrapper.vm.service.enableKey).toHaveBeenCalledWith(key.id);
+ expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
- it('re-fetches deploy keys when disabling a key', () => {
+ it('re-fetches deploy keys when disabling a key', async () => {
const key = data.public_keys[0];
- return mountComponent()
- .then(() => {
- jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
-
- eventHub.$emit('disable.key', key, () => {});
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findModal().props('visible')).toBe(true);
- findModal().vm.$emit('remove');
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
- expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
- });
+ await mountComponent();
+ jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
+
+ eventHub.$emit('disable.key', key, () => {});
+
+ await nextTick();
+ expect(findModal().props('visible')).toBe(true);
+ findModal().vm.$emit('remove');
+
+ await nextTick();
+ expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
+ expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
- it('calls disableKey when removing a key', () => {
+ it('calls disableKey when removing a key', async () => {
const key = data.public_keys[0];
- return mountComponent()
- .then(() => {
- jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
-
- eventHub.$emit('remove.key', key, () => {});
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findModal().props('visible')).toBe(true);
- findModal().vm.$emit('remove');
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
- expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
- });
+ await mountComponent();
+ jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
+
+ eventHub.$emit('remove.key', key, () => {});
+
+ await nextTick();
+ expect(findModal().props('visible')).toBe(true);
+ findModal().vm.$emit('remove');
+
+ await nextTick();
+ expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
+ expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
- it('hasKeys returns true when there are keys', () => {
- return mountComponent().then(() => {
- expect(wrapper.vm.hasKeys).toEqual(3);
- });
+ it('hasKeys returns true when there are keys', async () => {
+ await mountComponent();
+ expect(wrapper.vm.hasKeys).toEqual(3);
});
});
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index 51c120d8213..8599c55c908 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import data from 'test_fixtures/deploy_keys/keys.json';
import key from '~/deploy_keys/components/key.vue';
import DeployKeysStore from '~/deploy_keys/store';
@@ -95,18 +96,17 @@ describe('Deploy keys key', () => {
expect(labels.at(1).attributes('title')).toContain('Expand');
});
- it('expands all project labels after click', () => {
+ it('expands all project labels after click', async () => {
createComponent({ deployKey });
const { length } = deployKey.deploy_keys_projects;
wrapper.findAll('.deploy-project-label').at(1).trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- const labels = wrapper.findAll('.deploy-project-label');
+ await nextTick();
+ const labels = wrapper.findAll('.deploy-project-label');
- expect(labels.length).toBe(length);
- expect(labels.at(1).text()).not.toContain(`+${length} others`);
- expect(labels.at(1).attributes('title')).not.toContain('Expand');
- });
+ expect(labels.length).toBe(length);
+ expect(labels.at(1).text()).not.toContain(`+${length} others`);
+ expect(labels.at(1).attributes('title')).not.toContain('Expand');
});
it('shows two projects', () => {
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index f5a841d35b8..e3907fdbe15 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import BatchDeleteButton from '~/design_management/components/delete_button.vue';
describe('Batch delete button component', () => {
@@ -36,18 +37,15 @@ describe('Batch delete button component', () => {
expect(findButton().attributes('disabled')).toBeTruthy();
});
- it('emits `delete-selected-designs` event on modal ok click', () => {
+ it('emits `delete-selected-designs` event on modal ok click', async () => {
createComponent();
findButton().vm.$emit('click');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findModal().vm.$emit('ok');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('delete-selected-designs')).toBeTruthy();
- });
+
+ await nextTick();
+ findModal().vm.$emit('ok');
+
+ await nextTick();
+ expect(wrapper.emitted('delete-selected-designs')).toBeTruthy();
});
it('renders slot content', () => {
diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
index e816a05ba53..bbf2190ad47 100644
--- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
+import { nextTick } from 'vue';
import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue';
import DesignNote from '~/design_management/components/design_notes/design_note.vue';
import DesignNoteSignedOut from '~/design_management/components/design_notes/design_note_signed_out.vue';
@@ -119,12 +120,11 @@ describe('Design discussions component', () => {
expect(findResolveIcon().exists()).toBe(false);
});
- it('does not render a checkbox in reply form', () => {
+ it('does not render a checkbox in reply form', async () => {
findReplyPlaceholder().vm.$emit('focus');
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findResolveCheckbox().exists()).toBe(false);
});
});
@@ -150,13 +150,12 @@ describe('Design discussions component', () => {
expect(findResolveIcon().props('name')).toBe('check-circle');
});
- it('renders a checkbox with Resolve thread text in reply form', () => {
+ it('renders a checkbox with Resolve thread text in reply form', async () => {
findReplyPlaceholder().vm.$emit('focus');
wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().text()).toBe('Resolve thread');
- });
+ await nextTick();
+ expect(findResolveCheckbox().text()).toBe('Resolve thread');
});
it('does not render resolved message', () => {
@@ -216,7 +215,7 @@ describe('Design discussions component', () => {
findReplyForm().vm.$emit('submitForm');
await mutate();
- await wrapper.vm.$nextTick();
+ await nextTick();
const dispatchedEvent = dispatchEventSpy.mock.calls[0][0];
@@ -226,9 +225,9 @@ describe('Design discussions component', () => {
});
describe('when replies are expanded', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findRepliesWidget().vm.$emit('toggle');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders replies widget with collapsed prop equal to false', () => {
@@ -243,26 +242,24 @@ describe('Design discussions component', () => {
expect(findReplyPlaceholder().isVisible()).toBe(true);
});
- it('renders a checkbox with Unresolve thread text in reply form', () => {
+ it('renders a checkbox with Unresolve thread text in reply form', async () => {
findReplyPlaceholder().vm.$emit('focus');
wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().text()).toBe('Unresolve thread');
- });
+ await nextTick();
+ expect(findResolveCheckbox().text()).toBe('Unresolve thread');
});
});
});
- it('hides reply placeholder and opens form on placeholder click', () => {
+ it('hides reply placeholder and opens form on placeholder click', async () => {
createComponent();
findReplyPlaceholder().vm.$emit('focus');
wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyPlaceholder().exists()).toBe(false);
- expect(findReplyForm().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findReplyPlaceholder().exists()).toBe(false);
+ expect(findReplyForm().exists()).toBe(true);
});
it('calls mutation on submitting form and closes the form', async () => {
@@ -275,28 +272,24 @@ describe('Design discussions component', () => {
expect(mutate).toHaveBeenCalledWith(mutationVariables);
await mutate();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findReplyForm().exists()).toBe(false);
});
- it('clears the discussion comment on closing comment form', () => {
+ it('clears the discussion comment on closing comment form', async () => {
createComponent(
{ discussionWithOpenForm: defaultMockDiscussion.id },
{ discussionComment: 'test', isFormRendered: true },
);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findReplyForm().vm.$emit('cancel-form');
+ await nextTick();
+ findReplyForm().vm.$emit('cancel-form');
- expect(wrapper.vm.discussionComment).toBe('');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- });
+ expect(wrapper.vm.discussionComment).toBe('');
+
+ await nextTick();
+ expect(findReplyForm().exists()).toBe(false);
});
describe('when any note from a discussion is active', () => {
@@ -322,7 +315,7 @@ describe('Design discussions component', () => {
);
});
- it('calls toggleResolveDiscussion mutation on resolve thread button click', () => {
+ it('calls toggleResolveDiscussion mutation on resolve thread button click', async () => {
createComponent();
findResolveButton().trigger('click');
expect(mutate).toHaveBeenCalledWith({
@@ -332,9 +325,8 @@ describe('Design discussions component', () => {
resolve: true,
},
});
- return wrapper.vm.$nextTick(() => {
- expect(findResolveLoadingIcon().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findResolveLoadingIcon().exists()).toBe(true);
});
it('calls toggleResolveDiscussion mutation after adding a note if checkbox was checked', () => {
diff --git a/spec/frontend/design_management/components/design_notes/design_note_spec.js b/spec/frontend/design_management/components/design_notes/design_note_spec.js
index 3f5f5bcdfa7..35fd1273270 100644
--- a/spec/frontend/design_management/components/design_notes/design_note_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_note_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
+import { nextTick } from 'vue';
import DesignNote from '~/design_management/components/design_notes/design_note.vue';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -96,7 +97,7 @@ describe('Design note component', () => {
});
describe('when user has a permission to edit note', () => {
- it('should open an edit form on edit button click', () => {
+ it('should open an edit form on edit button click', async () => {
createComponent({
note: {
...note,
@@ -108,10 +109,9 @@ describe('Design note component', () => {
findEditButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyForm().exists()).toBe(true);
- expect(findNoteContent().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findReplyForm().exists()).toBe(true);
+ expect(findNoteContent().exists()).toBe(false);
});
describe('when edit form is rendered', () => {
@@ -134,27 +134,22 @@ describe('Design note component', () => {
expect(findReplyForm().exists()).toBe(true);
});
- it('hides the form on cancel-form event', () => {
+ it('hides the form on cancel-form event', async () => {
findReplyForm().vm.$emit('cancel-form');
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyForm().exists()).toBe(false);
- expect(findNoteContent().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findReplyForm().exists()).toBe(false);
+ expect(findNoteContent().exists()).toBe(true);
});
- it('calls a mutation on submit-form event and hides a form', () => {
+ it('calls a mutation on submit-form event and hides a form', async () => {
findReplyForm().vm.$emit('submit-form');
expect(mutate).toHaveBeenCalled();
- return mutate()
- .then(() => {
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- expect(findNoteContent().exists()).toBe(true);
- });
+ await mutate();
+ await nextTick();
+ expect(findReplyForm().exists()).toBe(false);
+ expect(findNoteContent().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
index a338a5ef200..0cef18c60de 100644
--- a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
const showModal = jest.fn();
@@ -30,6 +31,10 @@ describe('Design reply form component', () => {
});
}
+ beforeEach(() => {
+ gon.features = { markdownContinueLists: true };
+ });
+
afterEach(() => {
wrapper.destroy();
});
@@ -64,24 +69,22 @@ describe('Design reply form component', () => {
expect(findSubmitButton().attributes().disabled).toBeTruthy();
});
- it('does not emit submitForm event on textarea ctrl+enter keydown', () => {
+ it('does not emit submitForm event on textarea ctrl+enter keydown', async () => {
findTextarea().trigger('keydown.enter', {
ctrlKey: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submit-form')).toBeFalsy();
- });
+ await nextTick();
+ expect(wrapper.emitted('submit-form')).toBeFalsy();
});
- it('does not emit submitForm event on textarea meta+enter keydown', () => {
+ it('does not emit submitForm event on textarea meta+enter keydown', async () => {
findTextarea().trigger('keydown.enter', {
metaKey: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submit-form')).toBeFalsy();
- });
+ await nextTick();
+ expect(wrapper.emitted('submit-form')).toBeFalsy();
});
it('emits cancelForm event on pressing escape button on textarea', () => {
@@ -108,40 +111,36 @@ describe('Design reply form component', () => {
expect(findSubmitButton().attributes().disabled).toBeFalsy();
});
- it('emits submitForm event on Comment button click', () => {
+ it('emits submitForm event on Comment button click', async () => {
findSubmitButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submit-form')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
- it('emits submitForm event on textarea ctrl+enter keydown', () => {
+ it('emits submitForm event on textarea ctrl+enter keydown', async () => {
findTextarea().trigger('keydown.enter', {
ctrlKey: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submit-form')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
- it('emits submitForm event on textarea meta+enter keydown', () => {
+ it('emits submitForm event on textarea meta+enter keydown', async () => {
findTextarea().trigger('keydown.enter', {
metaKey: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submit-form')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
- it('emits input event on changing textarea content', () => {
+ it('emits input event on changing textarea content', async () => {
findTextarea().setValue('test2');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('input')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted('input')).toBeTruthy();
});
it('emits cancelForm event on Escape key if text was not changed', () => {
@@ -150,13 +149,12 @@ describe('Design reply form component', () => {
expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
- it('opens confirmation modal on Escape key when text has changed', () => {
+ it('opens confirmation modal on Escape key when text has changed', async () => {
wrapper.setProps({ value: 'test2' });
- return wrapper.vm.$nextTick().then(() => {
- findTextarea().trigger('keyup.esc');
- expect(showModal).toHaveBeenCalled();
- });
+ await nextTick();
+ findTextarea().trigger('keyup.esc');
+ expect(showModal).toHaveBeenCalled();
});
it('emits cancelForm event on Cancel button click if text was not changed', () => {
@@ -165,13 +163,12 @@ describe('Design reply form component', () => {
expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
- it('opens confirmation modal on Cancel button click when text has changed', () => {
+ it('opens confirmation modal on Cancel button click when text has changed', async () => {
wrapper.setProps({ value: 'test2' });
- return wrapper.vm.$nextTick().then(() => {
- findCancelButton().trigger('click');
- expect(showModal).toHaveBeenCalled();
- });
+ await nextTick();
+ findCancelButton().trigger('click');
+ expect(showModal).toHaveBeenCalled();
});
it('emits cancelForm event on modal Ok button click', () => {
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index 4bda5054090..056959425a6 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignOverlay from '~/design_management/components/design_overlay.vue';
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '~/design_management/constants';
import updateActiveDiscussion from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
@@ -17,12 +18,11 @@ describe('Design overlay component', () => {
const findFirstBadge = () => findBadgeAtIndex(0);
const findSecondBadge = () => findBadgeAtIndex(1);
- const clickAndDragBadge = (elem, fromPoint, toPoint) => {
+ const clickAndDragBadge = async (elem, fromPoint, toPoint) => {
elem.trigger('mousedown', { clientX: fromPoint.x, clientY: fromPoint.y });
- return wrapper.vm.$nextTick().then(() => {
- elem.trigger('mousemove', { clientX: toPoint.x, clientY: toPoint.y });
- return wrapper.vm.$nextTick();
- });
+ await nextTick();
+ elem.trigger('mousemove', { clientX: toPoint.x, clientY: toPoint.y });
+ await nextTick();
};
function createComponent(props = {}, data = {}) {
@@ -59,7 +59,7 @@ describe('Design overlay component', () => {
expect(wrapper.attributes().style).toBe('width: 100px; height: 100px; top: 0px; left: 0px;');
});
- it('should emit `openCommentForm` when clicking on overlay', () => {
+ it('should emit `openCommentForm` when clicking on overlay', async () => {
createComponent();
const newCoordinates = {
x: 10,
@@ -69,11 +69,10 @@ describe('Design overlay component', () => {
wrapper
.find('[data-qa-selector="design_image_button"]')
.trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([
- [{ x: newCoordinates.x, y: newCoordinates.y }],
- ]);
- });
+ await nextTick();
+ expect(wrapper.emitted('openCommentForm')).toEqual([
+ [{ x: newCoordinates.x, y: newCoordinates.y }],
+ ]);
});
describe('with notes', () => {
@@ -116,7 +115,7 @@ describe('Design overlay component', () => {
describe('when a discussion is active', () => {
it.each([notes[0].discussion.notes.nodes[1], notes[0].discussion.notes.nodes[0]])(
'should not apply inactive class to the pin for the active discussion',
- (note) => {
+ async (note) => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -126,13 +125,12 @@ describe('Design overlay component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findBadgeAtIndex(0).classes()).not.toContain('inactive');
- });
+ await nextTick();
+ expect(findBadgeAtIndex(0).classes()).not.toContain('inactive');
},
);
- it('should apply inactive class to all pins besides the active one', () => {
+ it('should apply inactive class to all pins besides the active one', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -142,15 +140,14 @@ describe('Design overlay component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findSecondBadge().classes()).toContain('inactive');
- expect(findFirstBadge().classes()).not.toContain('inactive');
- });
+ await nextTick();
+ expect(findSecondBadge().classes()).toContain('inactive');
+ expect(findFirstBadge().classes()).not.toContain('inactive');
});
});
});
- it('should recalculate badges positions on window resize', () => {
+ it('should recalculate badges positions on window resize', async () => {
createComponent({
notes,
dimensions: {
@@ -168,12 +165,11 @@ describe('Design overlay component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 30px;');
- });
+ await nextTick();
+ expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 30px;');
});
- it('should call an update active discussion mutation when clicking a note without moving it', () => {
+ it('should call an update active discussion mutation when clicking a note without moving it', async () => {
const note = notes[0];
const { position } = note;
const mutationVariables = {
@@ -186,31 +182,25 @@ describe('Design overlay component', () => {
findFirstBadge().trigger('mousedown', { clientX: position.x, clientY: position.y });
- return wrapper.vm.$nextTick().then(() => {
- findFirstBadge().trigger('mouseup', { clientX: position.x, clientY: position.y });
- expect(mutate).toHaveBeenCalledWith(mutationVariables);
- });
+ await nextTick();
+ findFirstBadge().trigger('mouseup', { clientX: position.x, clientY: position.y });
+ expect(mutate).toHaveBeenCalledWith(mutationVariables);
});
});
describe('when moving notes', () => {
- it('should update badge style when note is being moved', () => {
+ it('should update badge style when note is being moved', async () => {
createComponent({
notes,
});
const { position } = notes[0];
- return clickAndDragBadge(
- findFirstBadge(),
- { x: position.x, y: position.y },
- { x: 20, y: 20 },
- ).then(() => {
- expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 20px;');
- });
+ await clickAndDragBadge(findFirstBadge(), { x: position.x, y: position.y }, { x: 20, y: 20 });
+ expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 20px;');
});
- it('should emit `moveNote` event when note-moving action ends', () => {
+ it('should emit `moveNote` event when note-moving action ends', async () => {
createComponent({ notes });
const note = notes[0];
const { position } = note;
@@ -231,22 +221,19 @@ describe('Design overlay component', () => {
});
const badge = findFirstBadge();
- return clickAndDragBadge(badge, { x: position.x, y: position.y }, newCoordinates)
- .then(() => {
- badge.trigger('mouseup');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('moveNote')).toEqual([
- [
- {
- noteId: notes[0].id,
- discussionId: notes[0].discussion.id,
- coordinates: newCoordinates,
- },
- ],
- ]);
- });
+ await clickAndDragBadge(badge, { x: position.x, y: position.y }, newCoordinates);
+ badge.trigger('mouseup');
+
+ await nextTick();
+ expect(wrapper.emitted('moveNote')).toEqual([
+ [
+ {
+ noteId: notes[0].id,
+ discussionId: notes[0].discussion.id,
+ coordinates: newCoordinates,
+ },
+ ],
+ ]);
});
describe('without [repositionNote] permission', () => {
@@ -262,19 +249,18 @@ describe('Design overlay component', () => {
y: mockNoteNotAuthorised.position.y,
};
- it('should be unable to move a note', () => {
+ it('should be unable to move a note', async () => {
createComponent({
dimensions: mockDimensions,
notes: [mockNoteNotAuthorised],
});
const badge = findAllNotes().at(0);
- return clickAndDragBadge(badge, { ...mockNoteCoordinates }, { x: 20, y: 20 }).then(() => {
- // note position should not change after a click-and-drag attempt
- expect(findFirstBadge().attributes().style).toContain(
- `left: ${mockNoteCoordinates.x}px; top: ${mockNoteCoordinates.y}px;`,
- );
- });
+ await clickAndDragBadge(badge, { ...mockNoteCoordinates }, { x: 20, y: 20 });
+ // note position should not change after a click-and-drag attempt
+ expect(findFirstBadge().attributes().style).toContain(
+ `left: ${mockNoteCoordinates.x}px; top: ${mockNoteCoordinates.y}px;`,
+ );
});
});
});
@@ -292,7 +278,7 @@ describe('Design overlay component', () => {
});
describe('when moving the comment badge', () => {
- it('should update badge style to reflect new position', () => {
+ it('should update badge style to reflect new position', async () => {
const { position } = notes[0];
createComponent({
@@ -301,16 +287,15 @@ describe('Design overlay component', () => {
},
});
- return clickAndDragBadge(
+ await clickAndDragBadge(
findCommentBadge(),
{ x: position.x, y: position.y },
{ x: 20, y: 20 },
- ).then(() => {
- expect(findCommentBadge().attributes().style).toBe('left: 20px; top: 20px;');
- });
+ );
+ expect(findCommentBadge().attributes().style).toBe('left: 20px; top: 20px;');
});
- it('should update badge style when note-moving action ends', () => {
+ it('should update badge style when note-moving action ends', async () => {
const { position } = notes[0];
createComponent({
currentCommentForm: {
@@ -321,19 +306,16 @@ describe('Design overlay component', () => {
const commentBadge = findCommentBadge();
const toPoint = { x: 20, y: 20 };
- return clickAndDragBadge(commentBadge, { x: position.x, y: position.y }, toPoint)
- .then(() => {
- commentBadge.trigger('mouseup');
- // simulates the currentCommentForm being updated in index.vue component, and
- // propagated back down to this prop
- wrapper.setProps({
- currentCommentForm: { height: position.height, width: position.width, ...toPoint },
- });
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(commentBadge.attributes().style).toBe('left: 20px; top: 20px;');
- });
+ await clickAndDragBadge(commentBadge, { x: position.x, y: position.y }, toPoint);
+ commentBadge.trigger('mouseup');
+ // simulates the currentCommentForm being updated in index.vue component, and
+ // propagated back down to this prop
+ wrapper.setProps({
+ currentCommentForm: { height: position.height, width: position.width, ...toPoint },
+ });
+
+ await nextTick();
+ expect(commentBadge.attributes().style).toBe('left: 20px; top: 20px;');
});
it.each`
@@ -342,7 +324,7 @@ describe('Design overlay component', () => {
${'comment badge'} | ${findCommentBadge} | ${'mouseup'}
`(
'should emit `openCommentForm` event when $event fired on $element element',
- ({ getElementFunc, event }) => {
+ async ({ getElementFunc, event }) => {
createComponent({
notes,
currentCommentForm: {
@@ -364,9 +346,8 @@ describe('Design overlay component', () => {
});
getElementFunc().trigger(event);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
- });
+ await nextTick();
+ expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
},
);
});
diff --git a/spec/frontend/design_management/components/design_presentation_spec.js b/spec/frontend/design_management/components/design_presentation_spec.js
index adec9ef469d..d79dde84d46 100644
--- a/spec/frontend/design_management/components/design_presentation_spec.js
+++ b/spec/frontend/design_management/components/design_presentation_spec.js
@@ -74,7 +74,7 @@ describe('Design management design presentation component', () => {
.mockReturnValue((childDimensions.height - viewportDimensions.height) * scrollTopPerc);
}
- function clickDragExplore(startCoords, endCoords, { useTouchEvents, mouseup } = {}) {
+ async function clickDragExplore(startCoords, endCoords, { useTouchEvents, mouseup } = {}) {
const event = useTouchEvents
? {
mousedown: 'touchstart',
@@ -96,24 +96,17 @@ describe('Design management design presentation component', () => {
clientX: startCoords.clientX,
clientY: startCoords.clientY,
});
- return wrapper.vm
- .$nextTick()
- .then(() => {
- addCommentOverlay.trigger(event.mousemove, {
- clientX: endCoords.clientX,
- clientY: endCoords.clientY,
- });
-
- return nextTick();
- })
- .then(() => {
- if (mouseup) {
- addCommentOverlay.trigger(event.mouseup);
- return nextTick();
- }
+ await nextTick();
+ addCommentOverlay.trigger(event.mousemove, {
+ clientX: endCoords.clientX,
+ clientY: endCoords.clientY,
+ });
- return undefined;
- });
+ await nextTick();
+ if (mouseup) {
+ addCommentOverlay.trigger(event.mouseup);
+ await nextTick();
+ }
}
beforeEach(() => {
@@ -125,7 +118,7 @@ describe('Design management design presentation component', () => {
window.gon = originalGon;
});
- it('renders image and overlay when image provided', () => {
+ it('renders image and overlay when image provided', async () => {
createComponent(
{
image: 'test.jpg',
@@ -134,20 +127,18 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('renders empty state when no image provided', () => {
+ it('renders empty state when no image provided', async () => {
createComponent();
- return nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('openCommentForm event emits correct data', () => {
+ it('openCommentForm event emits correct data', async () => {
createComponent(
{
image: 'test.jpg',
@@ -158,15 +149,14 @@ describe('Design management design presentation component', () => {
wrapper.vm.openCommentForm({ x: 1, y: 1 });
- return nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([
- [{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
- ]);
- });
+ await nextTick();
+ expect(wrapper.emitted('openCommentForm')).toEqual([
+ [{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
+ ]);
});
describe('currentCommentForm', () => {
- it('is null when isAnnotating is false', () => {
+ it('is null when isAnnotating is false', async () => {
createComponent(
{
image: 'test.jpg',
@@ -175,13 +165,12 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toBeNull();
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.vm.currentCommentForm).toBeNull();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('is null when isAnnotating is true but annotation position is falsey', () => {
+ it('is null when isAnnotating is true but annotation position is falsey', async () => {
createComponent(
{
image: 'test.jpg',
@@ -191,13 +180,12 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toBeNull();
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.vm.currentCommentForm).toBeNull();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('is equal to current annotation position when isAnnotating is true', () => {
+ it('is equal to current annotation position when isAnnotating is true', async () => {
createComponent(
{
image: 'test.jpg',
@@ -215,15 +203,14 @@ describe('Design management design presentation component', () => {
},
);
- return nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toEqual({
- x: 1,
- y: 1,
- width: 100,
- height: 100,
- });
- expect(wrapper.element).toMatchSnapshot();
+ await nextTick();
+ expect(wrapper.vm.currentCommentForm).toEqual({
+ x: 1,
+ y: 1,
+ width: 100,
+ height: 100,
});
+ expect(wrapper.element).toMatchSnapshot();
});
});
@@ -388,7 +375,7 @@ describe('Design management design presentation component', () => {
});
describe('onImageResize', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createComponent(
{
image: 'test.jpg',
@@ -401,7 +388,7 @@ describe('Design management design presentation component', () => {
jest.spyOn(wrapper.vm, 'scaleZoomFocalPoint');
jest.spyOn(wrapper.vm, 'scrollToFocalPoint');
wrapper.vm.onImageResize({ width: 10, height: 10 });
- return nextTick();
+ await nextTick();
});
it('sets zoom focal point on initial load', () => {
@@ -409,12 +396,11 @@ describe('Design management design presentation component', () => {
expect(wrapper.vm.initialLoad).toBe(false);
});
- it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', () => {
+ it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', async () => {
wrapper.vm.onImageResize({ width: 10, height: 10 });
- return nextTick().then(() => {
- expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
- expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
+ expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
});
});
@@ -498,7 +484,7 @@ describe('Design management design presentation component', () => {
);
});
- it('opens a comment form if design was not dragged', () => {
+ it('opens a comment form if design was not dragged', async () => {
const addCommentOverlay = findOverlayCommentButton();
const startCoords = {
clientX: 1,
@@ -510,15 +496,10 @@ describe('Design management design presentation component', () => {
clientY: startCoords.clientY,
});
- return wrapper.vm
- .$nextTick()
- .then(() => {
- addCommentOverlay.trigger('mouseup');
- return nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('openCommentForm')).toBeDefined();
- });
+ await nextTick();
+ addCommentOverlay.trigger('mouseup');
+ await nextTick();
+ expect(wrapper.emitted('openCommentForm')).toBeDefined();
});
describe('when clicking and dragging', () => {
diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js
index 095c070e5e8..a04e2ebda5b 100644
--- a/spec/frontend/design_management/components/design_scaler_spec.js
+++ b/spec/frontend/design_management/components/design_scaler_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignScaler from '~/design_management/components/design_scaler.vue';
describe('Design management design scaler component', () => {
@@ -32,7 +33,7 @@ describe('Design management design scaler component', () => {
describe('when `scale` value is greater than 1', () => {
beforeEach(async () => {
setScale(1.6);
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('emits @scale event when "reset" button clicked', () => {
@@ -68,11 +69,11 @@ describe('Design management design scaler component', () => {
it('computes & increments correct stepSize based on maxScale', async () => {
wrapper.setProps({ maxScale: 11 });
- await wrapper.vm.$nextTick();
+ await nextTick();
getIncreaseScaleButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().scale[0][0]).toBe(3);
});
@@ -96,7 +97,7 @@ describe('Design management design scaler component', () => {
describe('when `scale` value is maximum', () => {
beforeEach(async () => {
setScale(2);
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('disables the "increment" button', () => {
diff --git a/spec/frontend/design_management/components/design_sidebar_spec.js b/spec/frontend/design_management/components/design_sidebar_spec.js
index 4cd71bdb7f3..a818a86bef6 100644
--- a/spec/frontend/design_management/components/design_sidebar_spec.js
+++ b/spec/frontend/design_management/components/design_sidebar_spec.js
@@ -1,6 +1,7 @@
import { GlCollapse, GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
+import { nextTick } from 'vue';
import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue';
import DesignNoteSignedOut from '~/design_management/components/design_notes/design_note_signed_out.vue';
import DesignSidebar from '~/design_management/components/design_sidebar.vue';
@@ -138,14 +139,13 @@ describe('Design management design sidebar component', () => {
expect(wrapper.emitted('toggleResolvedComments')).toHaveLength(1);
});
- it('opens a collapsible when resolvedDiscussionsExpanded prop changes to true', () => {
+ it('opens a collapsible when resolvedDiscussionsExpanded prop changes to true', async () => {
expect(findCollapsible().attributes('visible')).toBeUndefined();
wrapper.setProps({
resolvedDiscussionsExpanded: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findCollapsible().attributes('visible')).toBe('true');
- });
+ await nextTick();
+ expect(findCollapsible().attributes('visible')).toBe('true');
});
it('does not popover about resolved comments', () => {
@@ -182,12 +182,11 @@ describe('Design management design sidebar component', () => {
expect(wrapper.emitted('resolveDiscussionError')).toEqual([['payload']]);
});
- it('changes prop correctly on opening discussion form', () => {
+ it('changes prop correctly on opening discussion form', async () => {
findFirstDiscussion().vm.$emit('open-form', 'some-id');
- return wrapper.vm.$nextTick().then(() => {
- expect(findFirstDiscussion().props('discussionWithOpenForm')).toBe('some-id');
- });
+ await nextTick();
+ expect(findFirstDiscussion().props('discussionWithOpenForm')).toBe('some-id');
});
});
@@ -246,17 +245,19 @@ describe('Design management design sidebar component', () => {
expect(scrollIntoViewMock).toHaveBeenCalled();
});
- it('dismisses a popover on the outside click', () => {
+ it('dismisses a popover on the outside click', async () => {
wrapper.trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(findPopover().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findPopover().exists()).toBe(false);
});
it(`sets a ${cookieKey} cookie on clicking outside the popover`, () => {
jest.spyOn(Cookies, 'set');
wrapper.trigger('click');
- expect(Cookies.set).toHaveBeenCalledWith(cookieKey, 'true', { expires: 365 * 10 });
+ expect(Cookies.set).toHaveBeenCalledWith(cookieKey, 'true', {
+ expires: 365 * 10,
+ secure: false,
+ });
});
});
diff --git a/spec/frontend/design_management/components/design_todo_button_spec.js b/spec/frontend/design_management/components/design_todo_button_spec.js
index 757bf50c527..73661c9fcb0 100644
--- a/spec/frontend/design_management/components/design_todo_button_spec.js
+++ b/spec/frontend/design_management/components/design_todo_button_spec.js
@@ -1,4 +1,5 @@
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignTodoButton from '~/design_management/components/design_todo_button.vue';
import createDesignTodoMutation from '~/design_management/graphql/mutations/create_design_todo.mutation.graphql';
import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
@@ -71,7 +72,7 @@ describe('Design management design todo button', () => {
describe('when clicked', () => {
let dispatchEventSpy;
- beforeEach(() => {
+ beforeEach(async () => {
dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
jest.spyOn(document, 'querySelector').mockReturnValue({
innerText: 2,
@@ -79,7 +80,7 @@ describe('Design management design todo button', () => {
createComponent({ design: mockDesignWithPendingTodos }, { mountFn: mount });
wrapper.trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls `$apollo.mutate` with the `todoMarkDone` mutation and variables containing `id`', async () => {
@@ -117,7 +118,7 @@ describe('Design management design todo button', () => {
describe('when clicked', () => {
let dispatchEventSpy;
- beforeEach(() => {
+ beforeEach(async () => {
dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
jest.spyOn(document, 'querySelector').mockReturnValue({
innerText: 2,
@@ -125,7 +126,7 @@ describe('Design management design todo button', () => {
createComponent({}, { mountFn: mount });
wrapper.trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls `$apollo.mutate` with the `createDesignTodoMutation` mutation and variables containing `issuable_id`, `issue_id`, & `projectPath`', async () => {
diff --git a/spec/frontend/design_management/components/image_spec.js b/spec/frontend/design_management/components/image_spec.js
index ac3afc73c86..e27b2bc9fa5 100644
--- a/spec/frontend/design_management/components/image_spec.js
+++ b/spec/frontend/design_management/components/image_spec.js
@@ -1,5 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignImage from '~/design_management/components/image.vue';
describe('Design management large image component', () => {
@@ -36,7 +37,7 @@ describe('Design management large image component', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('sets correct classes and styles if imageStyle is set', () => {
+ it('sets correct classes and styles if imageStyle is set', async () => {
createComponent(
{
isLoading: false,
@@ -50,12 +51,11 @@ describe('Design management large image component', () => {
},
},
);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('renders media broken icon on error', () => {
+ it('renders media broken icon on error', async () => {
createComponent({
isLoading: false,
image: 'test.jpg',
@@ -64,10 +64,9 @@ describe('Design management large image component', () => {
const image = wrapper.find('img');
image.trigger('error');
- return wrapper.vm.$nextTick().then(() => {
- expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(image.isVisible()).toBe(false);
+ expect(wrapper.find(GlIcon).element).toMatchSnapshot();
});
describe('zoom', () => {
@@ -99,37 +98,34 @@ describe('Design management large image component', () => {
.mockReturnValue(baseImageHeight);
});
- it('emits @resize event on zoom', () => {
+ it('emits @resize event on zoom', async () => {
const zoomAmount = 2;
wrapper.vm.zoom(zoomAmount);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('resize')).toEqual([
- [{ width: baseImageWidth * zoomAmount, height: baseImageHeight * zoomAmount }],
- ]);
- });
+ await nextTick();
+ expect(wrapper.emitted('resize')).toEqual([
+ [{ width: baseImageWidth * zoomAmount, height: baseImageHeight * zoomAmount }],
+ ]);
});
- it('emits @resize event with base image size when scale=1', () => {
+ it('emits @resize event with base image size when scale=1', async () => {
wrapper.vm.zoom(1);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('resize')).toEqual([
- [{ width: baseImageWidth, height: baseImageHeight }],
- ]);
- });
+ await nextTick();
+ expect(wrapper.emitted('resize')).toEqual([
+ [{ width: baseImageWidth, height: baseImageHeight }],
+ ]);
});
- it('sets image style when zoomed', () => {
+ it('sets image style when zoomed', async () => {
const zoomAmount = 2;
wrapper.vm.zoom(zoomAmount);
expect(wrapper.vm.imageStyle).toEqual({
width: `${baseImageWidth * zoomAmount}px`,
height: `${baseImageHeight * zoomAmount}px`,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
});
});
diff --git a/spec/frontend/design_management/components/list/item_spec.js b/spec/frontend/design_management/components/list/item_spec.js
index ed105b112be..e00dda2015e 100644
--- a/spec/frontend/design_management/components/list/item_spec.js
+++ b/spec/frontend/design_management/components/list/item_spec.js
@@ -1,11 +1,11 @@
import { GlIcon, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Item from '~/design_management/components/list/item.vue';
-const localVue = createLocalVue();
-localVue.use(VueRouter);
+Vue.use(VueRouter);
const router = new VueRouter();
// Referenced from: gitlab_schema.graphql:DesignVersionEvent
@@ -34,7 +34,6 @@ describe('Design management list item component', () => {
} = {}) {
wrapper = extendedWrapper(
shallowMount(Item, {
- localVue,
router,
propsData: {
id: imgId,
@@ -72,13 +71,13 @@ describe('Design management list item component', () => {
let image;
let glIntersectionObserver;
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
image = wrapper.find('img');
glIntersectionObserver = wrapper.find(GlIntersectionObserver);
glIntersectionObserver.vm.$emit('appear');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders a tooltip', () => {
@@ -92,9 +91,9 @@ describe('Design management list item component', () => {
});
describe('after image is loaded', () => {
- beforeEach(() => {
+ beforeEach(async () => {
image.trigger('load');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders an image', () => {
@@ -102,29 +101,27 @@ describe('Design management list item component', () => {
expect(image.isVisible()).toBe(true);
});
- it('renders media broken icon when image onerror triggered', () => {
+ it('renders media broken icon when image onerror triggered', async () => {
image.trigger('error');
- return wrapper.vm.$nextTick().then(() => {
- expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(image.isVisible()).toBe(false);
+ expect(wrapper.find(GlIcon).element).toMatchSnapshot();
});
describe('when imageV432x230 and image provided', () => {
- it('renders imageV432x230 image', () => {
+ it('renders imageV432x230 image', async () => {
const mockSrc = 'mock-imageV432x230-url';
wrapper.setProps({ imageV432x230: mockSrc });
- return wrapper.vm.$nextTick().then(() => {
- expect(image.attributes('src')).toBe(mockSrc);
- });
+ await nextTick();
+ expect(image.attributes('src')).toBe(mockSrc);
});
});
describe('when image disappears from view and then reappears', () => {
- beforeEach(() => {
+ beforeEach(async () => {
glIntersectionObserver.vm.$emit('appear');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders an image', () => {
diff --git a/spec/frontend/design_management/components/toolbar/design_navigation_spec.js b/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
index 6e0592984a2..38a7fadee79 100644
--- a/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
+++ b/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
@@ -1,6 +1,7 @@
/* global Mousetrap */
import 'mousetrap';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignNavigation from '~/design_management/components/toolbar/design_navigation.vue';
import { DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
@@ -41,16 +42,15 @@ describe('Design management pagination component', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('renders navigation buttons', () => {
+ it('renders navigation buttons', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
designCollection: { designs: [{ id: '1' }, { id: '2' }] },
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
describe('keyboard buttons navigation', () => {
diff --git a/spec/frontend/design_management/components/toolbar/index_spec.js b/spec/frontend/design_management/components/toolbar/index_spec.js
index cf872046f53..412f3de911e 100644
--- a/spec/frontend/design_management/components/toolbar/index_spec.js
+++ b/spec/frontend/design_management/components/toolbar/index_spec.js
@@ -1,12 +1,12 @@
import { GlButton } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import DeleteButton from '~/design_management/components/delete_button.vue';
import Toolbar from '~/design_management/components/toolbar/index.vue';
import { DESIGNS_ROUTE_NAME } from '~/design_management/router/constants';
-const localVue = createLocalVue();
-localVue.use(VueRouter);
+Vue.use(VueRouter);
const router = new VueRouter();
const RouterLinkStub = {
@@ -28,7 +28,6 @@ describe('Design management toolbar component', () => {
updatedAt.setHours(updatedAt.getHours() - 1);
wrapper = shallowMount(Toolbar, {
- localVue,
router,
propsData: {
id: '1',
@@ -61,60 +60,54 @@ describe('Design management toolbar component', () => {
wrapper.destroy();
});
- it('renders design and updated data', () => {
+ it('renders design and updated data', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('links back to designs list', () => {
+ it('links back to designs list', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- const link = wrapper.find('a');
+ await nextTick();
+ const link = wrapper.find('a');
- expect(link.props('to')).toEqual({
- name: DESIGNS_ROUTE_NAME,
- query: {
- version: undefined,
- },
- });
+ expect(link.props('to')).toEqual({
+ name: DESIGNS_ROUTE_NAME,
+ query: {
+ version: undefined,
+ },
});
});
- it('renders delete button on latest designs version with logged in user', () => {
+ it('renders delete button on latest designs version with logged in user', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(DeleteButton).exists()).toBe(true);
});
- it('does not render delete button on non-latest version', () => {
+ it('does not render delete button on non-latest version', async () => {
createComponent(false, true, { isLatestVersion: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(DeleteButton).exists()).toBe(false);
});
- it('does not render delete button when user is not logged in', () => {
+ it('does not render delete button when user is not logged in', async () => {
createComponent(false, false);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(DeleteButton).exists()).toBe(false);
});
- it('emits `delete` event on deleteButton `delete-selected-designs` event', () => {
+ it('emits `delete` event on deleteButton `delete-selected-designs` event', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find(DeleteButton).vm.$emit('delete-selected-designs');
- expect(wrapper.emitted().delete).toBeTruthy();
- });
+ await nextTick();
+ wrapper.find(DeleteButton).vm.$emit('delete-selected-designs');
+ expect(wrapper.emitted().delete).toBeTruthy();
});
it('renders download button with correct link', () => {
diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
index a4fb671ae13..ec5db04bb80 100644
--- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
+++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import mockAllVersions from './mock_data/all_versions';
@@ -47,77 +48,69 @@ describe('Design management design version dropdown component', () => {
const findVersionLink = (index) => wrapper.findAll(GlDropdownItem).at(index);
- it('renders design version dropdown button', () => {
+ it('renders design version dropdown button', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('renders design version list', () => {
+ it('renders design version list', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
describe('selected version name', () => {
- it('has "latest" on most recent version item', () => {
+ it('has "latest" on most recent version item', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(findVersionLink(0).text()).toContain('latest');
- });
+ await nextTick();
+ expect(findVersionLink(0).text()).toContain('latest');
});
});
describe('versions list', () => {
- it('displays latest version text by default', () => {
+ it('displays latest version text by default', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
- });
+ await nextTick();
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
- it('displays latest version text when only 1 version is present', () => {
+ it('displays latest version text when only 1 version is present', async () => {
createComponent({ maxVersions: 1 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
- });
+ await nextTick();
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
- it('displays version text when the current version is not the latest', () => {
+ it('displays version text when the current version is not the latest', async () => {
createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
- });
+ await nextTick();
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
});
- it('displays latest version text when the current version is the latest', () => {
+ it('displays latest version text when the current version is the latest', async () => {
createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
- });
+ await nextTick();
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
- it('should have the same length as apollo query', () => {
+ it('should have the same length as apollo query', async () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
- });
+ await nextTick();
+ expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
});
it('should render TimeAgo', async () => {
createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAllComponents(TimeAgo)).toHaveLength(wrapper.vm.allVersions.length);
});
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index 98e2313e9f2..55d0fabe402 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -1,5 +1,6 @@
import { GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { ApolloMutation } from 'vue-apollo';
import VueRouter from 'vue-router';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
@@ -78,8 +79,7 @@ const createDiscussionMutationVariables = {
},
};
-const localVue = createLocalVue();
-localVue.use(VueRouter);
+Vue.use(VueRouter);
describe('Design management design index page', () => {
let wrapper;
@@ -128,7 +128,6 @@ describe('Design management design index page', () => {
...data,
};
},
- localVue,
router,
});
}
@@ -154,11 +153,11 @@ describe('Design management design index page', () => {
jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
createComponent({ loading: false }, { data: { design, scale: 2 } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDesignPresentation().props('scale')).toBe(2);
DesignIndex.beforeRouteUpdate.call(wrapper.vm, {}, {}, jest.fn());
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDesignPresentation().props('scale')).toBe(1);
});
@@ -201,7 +200,7 @@ describe('Design management design index page', () => {
});
});
- it('opens a new discussion form', () => {
+ it('opens a new discussion form', async () => {
createComponent(
{ loading: false },
{
@@ -213,9 +212,8 @@ describe('Design management design index page', () => {
findDesignPresentation().vm.$emit('openCommentForm', { x: 0, y: 0 });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDiscussionForm().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findDiscussionForm().exists()).toBe(true);
});
it('keeps new discussion form focused', () => {
@@ -234,7 +232,7 @@ describe('Design management design index page', () => {
expect(focusInput).toHaveBeenCalled();
});
- it('sends a mutation on submitting form and closes form', () => {
+ it('sends a mutation on submitting form and closes form', async () => {
createComponent(
{ loading: false },
{
@@ -249,17 +247,12 @@ describe('Design management design index page', () => {
findDiscussionForm().vm.$emit('submit-form');
expect(mutate).toHaveBeenCalledWith(createDiscussionMutationVariables);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- return mutate({ variables: createDiscussionMutationVariables });
- })
- .then(() => {
- expect(findDiscussionForm().exists()).toBe(false);
- });
+ await nextTick();
+ await mutate({ variables: createDiscussionMutationVariables });
+ expect(findDiscussionForm().exists()).toBe(false);
});
- it('closes the form and clears the comment on canceling form', () => {
+ it('closes the form and clears the comment on canceling form', async () => {
createComponent(
{ loading: false },
{
@@ -275,9 +268,8 @@ describe('Design management design index page', () => {
expect(wrapper.vm.comment).toBe('');
- return wrapper.vm.$nextTick().then(() => {
- expect(findDiscussionForm().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findDiscussionForm().exists()).toBe(false);
});
describe('with error', () => {
@@ -300,22 +292,21 @@ describe('Design management design index page', () => {
describe('onDesignQueryResult', () => {
describe('with no designs', () => {
- it('redirects to /designs', () => {
+ it('redirects to /designs', async () => {
createComponent({ loading: true });
router.push = jest.fn();
wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_NOT_FOUND_ERROR });
- expect(router.push).toHaveBeenCalledTimes(1);
- expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
- });
+ await nextTick();
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_NOT_FOUND_ERROR });
+ expect(router.push).toHaveBeenCalledTimes(1);
+ expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
});
describe('when no design exists for given version', () => {
- it('redirects to /designs', () => {
+ it('redirects to /designs', async () => {
createComponent({ loading: true });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -328,12 +319,11 @@ describe('Design management design index page', () => {
router.push = jest.fn();
wrapper.vm.onDesignQueryResult({ data: mockResponseWithDesigns, loading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_VERSION_NOT_EXIST_ERROR });
- expect(router.push).toHaveBeenCalledTimes(1);
- expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
- });
+ await nextTick();
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_VERSION_NOT_EXIST_ERROR });
+ expect(router.push).toHaveBeenCalledTimes(1);
+ expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
});
});
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index dd0f7972553..a240a41959f 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -1,10 +1,12 @@
import { GlEmptyState } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo, { ApolloMutation } from 'vue-apollo';
import VueRouter from 'vue-router';
import VueDraggable from 'vuedraggable';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
@@ -48,9 +50,8 @@ jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageEl);
const scrollIntoViewMock = jest.fn();
HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
-const localVue = createLocalVue();
const router = createRouter();
-localVue.use(VueRouter);
+Vue.use(VueRouter);
const mockDesigns = [
{
@@ -115,8 +116,7 @@ describe('Design management index page', () => {
const findDesignToolbarWrapper = () => wrapper.find('[data-testid="design-toolbar-wrapper"]');
async function moveDesigns(localWrapper) {
- await jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
localWrapper.find(VueDraggable).vm.$emit('change', {
@@ -159,7 +159,6 @@ describe('Design management index page', () => {
};
},
mocks: { $apollo },
- localVue,
router,
stubs: { DesignDestroyer, ApolloMutation, VueDraggable, ...stubs },
attachTo: document.body,
@@ -175,7 +174,7 @@ describe('Design management index page', () => {
function createComponentWithApollo({
moveHandler = jest.fn().mockResolvedValue(moveDesignMutationResponse),
}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
moveDesignHandler = moveHandler;
const requestHandlers = [
@@ -186,7 +185,6 @@ describe('Design management index page', () => {
fakeApollo = createMockApollo(requestHandlers);
wrapper = shallowMount(Index, {
- localVue,
apolloProvider: fakeApollo,
router,
stubs: { VueDraggable },
@@ -746,9 +744,7 @@ describe('Design management index page', () => {
describe('with mocked Apollo client', () => {
it('has a design with id 1 as a first one', async () => {
createComponentWithApollo({});
-
- await jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
expect(findDesigns()).toHaveLength(3);
expect(findDesigns().at(0).props('id')).toBe('1');
@@ -761,21 +757,18 @@ describe('Design management index page', () => {
expect(moveDesignHandler).toHaveBeenCalled();
- await nextTick();
+ await waitForPromises();
expect(findDesigns().at(0).props('id')).toBe('2');
});
it('prevents reordering when reorderDesigns mutation is in progress', async () => {
createComponentWithApollo({});
-
await moveDesigns(wrapper);
expect(draggableAttributes().disabled).toBe(true);
- await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await nextTick(); // kick off the DOM update
- await nextTick(); // kick off the DOM update for finally block
+ await waitForPromises();
expect(draggableAttributes().disabled).toBe(false);
});
@@ -786,8 +779,7 @@ describe('Design management index page', () => {
});
await moveDesigns(wrapper);
-
- await nextTick();
+ await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
@@ -798,10 +790,7 @@ describe('Design management index page', () => {
});
await moveDesigns(wrapper);
-
- await nextTick(); // kick off the DOM update
- await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await nextTick(); // kick off the DOM update for flash
+ await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({
message: 'Something went wrong when reordering designs. Please try again',
diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js
index ac5e6895408..03ab79712a4 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -1,5 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import App from '~/design_management/components/app.vue';
import DesignDetail from '~/design_management/pages/design/index.vue';
@@ -9,8 +9,7 @@ import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management/route
import '~/commons/bootstrap';
function factory(routeArg) {
- const localVue = createLocalVue();
- localVue.use(VueRouter);
+ Vue.use(VueRouter);
window.gon = { sprite_icons: '' };
@@ -20,7 +19,6 @@ function factory(routeArg) {
}
return mount(App, {
- localVue,
router,
mocks: {
$apollo: {
diff --git a/spec/frontend/design_management/utils/cache_update_spec.js b/spec/frontend/design_management/utils/cache_update_spec.js
index fa6a666bb37..5e2c37e24a1 100644
--- a/spec/frontend/design_management/utils/cache_update_spec.js
+++ b/spec/frontend/design_management/utils/cache_update_spec.js
@@ -1,4 +1,4 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
+import { InMemoryCache } from '@apollo/client/core';
import {
updateStoreAfterDesignsDelete,
updateStoreAfterAddImageDiffNote,
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index d50ac0529d6..76e4a944d87 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -69,6 +69,12 @@ describe('diffs/components/app', () => {
},
provide,
store,
+ stubs: {
+ DynamicScroller: {
+ template: `<div><slot :item="$store.state.diffs.diffFiles[0]"></slot></div>`,
+ },
+ DynamicScrollerItem: true,
+ },
});
}
@@ -154,22 +160,6 @@ describe('diffs/components/app', () => {
});
});
- it.each`
- props | state | expected
- ${{ isFluidLayout: true }} | ${{ isParallelView: false }} | ${false}
- ${{}} | ${{ isParallelView: false }} | ${true}
- ${{}} | ${{ showTreeList: true, diffFiles: [{}], isParallelView: false }} | ${false}
- ${{}} | ${{ showTreeList: false, diffFiles: [{}], isParallelView: false }} | ${true}
- ${{}} | ${{ showTreeList: false, diffFiles: [], isParallelView: false }} | ${true}
- `(
- 'uses container-limiting classes ($expected) with state ($state) and props ($props)',
- ({ props, state, expected }) => {
- createComponent(props, ({ state: origState }) => Object.assign(origState.diffs, state));
-
- expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(expected);
- },
- );
-
it('displays loading icon on loading', () => {
createComponent({}, ({ state }) => {
state.diffs.isLoading = true;
@@ -498,7 +488,6 @@ describe('diffs/components/app', () => {
expect(wrapper.find(CompareVersions).exists()).toBe(true);
expect(wrapper.find(CompareVersions).props()).toEqual(
expect.objectContaining({
- isLimitedContainer: false,
diffFilesCountText: null,
}),
);
diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
index 46caeb01132..8cc342e45a7 100644
--- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js
+++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue';
-import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '~/diffs/constants';
+import { EVT_EXPAND_ALL_FILES } from '~/diffs/constants';
import eventHub from '~/diffs/event_hub';
import createStore from '~/diffs/store/modules';
@@ -13,21 +13,19 @@ const propsData = {
mergeable: true,
resolutionPath: 'a-path',
};
-const limitedClasses = CENTERED_LIMITED_CONTAINER_CLASSES.split(' ');
async function files(store, count) {
const copies = Array(count).fill(file);
store.state.diffs.diffFiles.push(...copies);
- return nextTick();
+ await nextTick();
}
describe('CollapsedFilesWarning', () => {
- const localVue = createLocalVue();
let store;
let wrapper;
- localVue.use(Vuex);
+ Vue.use(Vuex);
const getAlertActionButton = () =>
wrapper.find(CollapsedFilesWarning).find('button.gl-alert-action:first-child');
@@ -43,7 +41,6 @@ describe('CollapsedFilesWarning', () => {
wrapper = mounter(CollapsedFilesWarning, {
propsData: { ...propsData, ...props },
- localVue,
store,
});
};
@@ -54,20 +51,6 @@ describe('CollapsedFilesWarning', () => {
describe('when there is more than one file', () => {
it.each`
- limited | containerClasses
- ${true} | ${limitedClasses}
- ${false} | ${[]}
- `(
- 'has the correct container classes when limited is $limited',
- async ({ limited, containerClasses }) => {
- createComponent({ limited });
- await files(store, 2);
-
- expect(wrapper.classes()).toEqual(['col-12'].concat(containerClasses));
- },
- );
-
- it.each`
present | dismissed
${false} | ${true}
${true} | ${false}
@@ -86,7 +69,7 @@ describe('CollapsedFilesWarning', () => {
getAlertCloseButton().element.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('[data-testid="root"]').exists()).toBe(false);
});
diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js
index c48935bc4f0..21f3ee26bf8 100644
--- a/spec/frontend/diffs/components/compare_versions_spec.js
+++ b/spec/frontend/diffs/components/compare_versions_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import getDiffWithCommit from 'test_fixtures/merge_request_diffs/with_commit.json';
import setWindowLocation from 'helpers/set_window_location_helper';
@@ -8,8 +9,7 @@ import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
import { createStore } from '~/mr_notes/stores';
import diffsMockData from '../mock_data/merge_request_diffs';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const NEXT_COMMIT_URL = `${TEST_HOST}/?commit_id=next`;
const PREV_COMMIT_URL = `${TEST_HOST}/?commit_id=prev`;
@@ -30,7 +30,6 @@ describe('CompareVersions', () => {
}
wrapper = mount(CompareVersionsComponent, {
- localVue,
store,
propsData: {
mergeRequestDiffs: diffsMockData,
@@ -39,7 +38,6 @@ describe('CompareVersions', () => {
},
});
};
- const findLimitedContainer = () => wrapper.find('.container-limited.limit-container-width');
const findCompareSourceDropdown = () => wrapper.find('.mr-version-dropdown');
const findCompareTargetDropdown = () => wrapper.find('.mr-version-compare-dropdown');
const getCommitNavButtonsElement = () => wrapper.find('.commit-nav-buttons');
@@ -99,18 +97,6 @@ describe('CompareVersions', () => {
expect(inlineBtn.html()).toContain('Inline');
expect(parallelBtn.html()).toContain('Side-by-side');
});
-
- it('adds container-limiting classes when showFileTree is false with inline diffs', () => {
- createWrapper({ isLimitedContainer: true });
-
- expect(findLimitedContainer().exists()).toBe(true);
- });
-
- it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
- createWrapper({ isLimitedContainer: false });
-
- expect(findLimitedContainer().exists()).toBe(false);
- });
});
describe('noChangedFiles', () => {
@@ -233,14 +219,13 @@ describe('CompareVersions', () => {
expect(link.element.getAttribute('href')).toEqual(PREV_COMMIT_URL);
});
- it('triggers the correct Vuex action on click', () => {
+ it('triggers the correct Vuex action on click', async () => {
const link = getPrevCommitNavElement();
link.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
- direction: 'previous',
- });
+ await nextTick();
+ expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
+ direction: 'previous',
});
});
@@ -268,13 +253,12 @@ describe('CompareVersions', () => {
expect(link.element.getAttribute('href')).toEqual(NEXT_COMMIT_URL);
});
- it('triggers the correct Vuex action on click', () => {
+ it('triggers the correct Vuex action on click', async () => {
const link = getNextCommitNavElement();
link.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
- });
+ await nextTick();
+ expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
});
it('renders a disabled button when there is no next commit', () => {
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 0a7dfc02c65..7d2afe105a5 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DiffContentComponent from '~/diffs/components/diff_content.vue';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
@@ -11,8 +12,7 @@ import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_prev
import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
import diffFileMockData from '../mock_data/diff_file';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('DiffContent', () => {
let wrapper;
@@ -88,7 +88,6 @@ describe('DiffContent', () => {
...defaultProps,
...props,
},
- localVue,
store: fakeStore,
provide: { glFeatures },
});
diff --git a/spec/frontend/diffs/components/diff_discussion_reply_spec.js b/spec/frontend/diffs/components/diff_discussion_reply_spec.js
index 9443a441ec2..f03c0357a0e 100644
--- a/spec/frontend/diffs/components/diff_discussion_reply_spec.js
+++ b/spec/frontend/diffs/components/diff_discussion_reply_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DiffDiscussionReply from '~/diffs/components/diff_discussion_reply.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import NoteSignedOutWidget from '~/notes/components/note_signed_out_widget.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('DiffDiscussionReply', () => {
let wrapper;
@@ -15,7 +15,6 @@ describe('DiffDiscussionReply', () => {
const createComponent = (props = {}, slots = {}) => {
wrapper = shallowMount(DiffDiscussionReply, {
store,
- localVue,
propsData: {
...props,
},
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index bd6f4cd2545..2da68adddf6 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,5 +1,5 @@
import { GlIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import { createStore } from '~/mr_notes/stores';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
@@ -8,8 +8,6 @@ import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item
import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
-const localVue = createLocalVue();
-
describe('DiffDiscussions', () => {
let store;
let wrapper;
@@ -17,13 +15,12 @@ describe('DiffDiscussions', () => {
const createComponent = (props) => {
store = createStore();
- wrapper = mount(localVue.extend(DiffDiscussions), {
+ wrapper = mount(DiffDiscussions, {
store,
propsData: {
discussions: getDiscussionsMockData(),
...props,
},
- localVue,
});
};
@@ -74,7 +71,7 @@ describe('DiffDiscussions', () => {
expect(diffNotesToggle.text().trim()).toBe('1');
expect(diffNotesToggle.classes()).toEqual(
- expect.arrayContaining(['btn-transparent', 'badge', 'badge-pill']),
+ expect.arrayContaining(['js-diff-notes-toggle', 'gl-translate-x-n50', 'design-note-pin']),
);
});
@@ -90,8 +87,8 @@ describe('DiffDiscussions', () => {
createComponent({ renderAvatarBadge: true });
const noteableDiscussion = wrapper.find(NoteableDiscussion);
- expect(noteableDiscussion.find('.badge-pill').exists()).toBe(true);
- expect(noteableDiscussion.find('.badge-pill').text().trim()).toBe('1');
+ expect(noteableDiscussion.find('.design-note-pin').exists()).toBe(true);
+ expect(noteableDiscussion.find('.design-note-pin').text().trim()).toBe('1');
});
});
});
diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
index f53f10d955d..cd472920bb9 100644
--- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
@@ -91,7 +91,9 @@ describe('DiffExpansionCell', () => {
});
expect(findExpandUp(wrapper).exists()).toBe(true);
- expect(findExpandDown(wrapper).exists()).toBe(false);
+ expect(findExpandDown(wrapper).exists()).toBe(true);
+ expect(findExpandUp(wrapper).attributes('disabled')).not.toBeDefined();
+ expect(findExpandDown(wrapper).attributes('disabled')).toBeDefined();
expect(findExpandAll(wrapper)).not.toBe(null);
});
});
@@ -112,8 +114,10 @@ describe('DiffExpansionCell', () => {
isBottom: true,
});
- expect(findExpandUp(wrapper).exists()).toBe(false);
expect(findExpandDown(wrapper).exists()).toBe(true);
+ expect(findExpandUp(wrapper).exists()).toBe(true);
+ expect(findExpandDown(wrapper).attributes('disabled')).not.toBeDefined();
+ expect(findExpandUp(wrapper).attributes('disabled')).toBeDefined();
expect(findExpandAll(wrapper)).not.toBe(null);
});
});
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index 342b4bfcc50..f22bd312a6d 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { cloneDeep } from 'lodash';
import Vuex from 'vuex';
@@ -37,8 +38,7 @@ const diffFile = Object.freeze(
}),
);
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('DiffFileHeader component', () => {
let wrapper;
@@ -82,7 +82,7 @@ describe('DiffFileHeader component', () => {
const findExpandButton = () => wrapper.find({ ref: 'expandDiffToFullFileButton' });
const findFileActions = () => wrapper.find('.file-actions');
const findModeChangedLine = () => wrapper.find({ ref: 'fileMode' });
- const findLfsLabel = () => wrapper.find('.label-lfs');
+ const findLfsLabel = () => wrapper.find('[data-testid="label-lfs"]');
const findToggleDiscussionsButton = () => wrapper.find({ ref: 'toggleDiscussionsButton' });
const findExternalLink = () => wrapper.find({ ref: 'externalLink' });
const findReplacedFileButton = () => wrapper.find({ ref: 'replacedFileButton' });
@@ -103,7 +103,6 @@ describe('DiffFileHeader component', () => {
...props,
},
...options,
- localVue,
store,
});
};
@@ -126,30 +125,27 @@ describe('DiffFileHeader component', () => {
expect(findCollapseIcon().props('name')).toBe(icon);
});
- it('when header is clicked emits toggleFile', () => {
+ it('when header is clicked emits toggleFile', async () => {
createComponent();
findHeader().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleFile).toBeDefined();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleFile).toBeDefined();
});
- it('when collapseIcon is clicked emits toggleFile', () => {
+ it('when collapseIcon is clicked emits toggleFile', async () => {
createComponent({ props: { collapsible: true } });
findCollapseIcon().vm.$emit('click', new Event('click'));
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleFile).toBeDefined();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleFile).toBeDefined();
});
- it('when other element in header is clicked does not emits toggleFile', () => {
+ it('when other element in header is clicked does not emits toggleFile', async () => {
createComponent({ props: { collapsible: true } });
findTitleLink().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleFile).not.toBeDefined();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleFile).not.toBeDefined();
});
describe('copy to clipboard', () => {
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index dc0ed621a64..a0aa4c784bf 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DiffContentComponent from 'jh_else_ce/diffs/components/diff_content.vue';
@@ -70,9 +70,7 @@ function markFileToBeRendered(store, index = 0) {
}
function createComponent({ file, first = false, last = false, options = {}, props = {} }) {
- const localVue = createLocalVue();
-
- localVue.use(Vuex);
+ Vue.use(Vuex);
const store = new Vuex.Store({
...createNotesStore(),
@@ -85,7 +83,6 @@ function createComponent({ file, first = false, last = false, options = {}, prop
const wrapper = shallowMount(DiffFileComponent, {
store,
- localVue,
propsData: {
file,
canCurrentUserFork: false,
@@ -98,7 +95,6 @@ function createComponent({ file, first = false, last = false, options = {}, prop
});
return {
- localVue,
wrapper,
store,
};
@@ -164,7 +160,7 @@ describe('DiffFile', () => {
last,
}));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(eventHub.$emit).toHaveBeenCalledTimes(events.length);
events.forEach((event) => {
@@ -188,13 +184,13 @@ describe('DiffFile', () => {
makeFileAutomaticallyCollapsed(store);
- await wrapper.vm.$nextTick(); // Wait for store updates to flow into the component
+ await nextTick(); // Wait for store updates to flow into the component
toggleFile(wrapper);
- await wrapper.vm.$nextTick(); // Wait for the load to resolve
- await wrapper.vm.$nextTick(); // Wait for the idleCallback
- await wrapper.vm.$nextTick(); // Wait for nextTick inside postRender
+ await nextTick(); // Wait for the load to resolve
+ await nextTick(); // Wait for the idleCallback
+ await nextTick(); // Wait for nextTick inside postRender
expect(eventHub.$emit).toHaveBeenCalledTimes(2);
expect(eventHub.$emit).toHaveBeenCalledWith(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN);
@@ -218,7 +214,7 @@ describe('DiffFile', () => {
markFileToBeRendered(store);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
});
@@ -268,7 +264,7 @@ describe('DiffFile', () => {
it('performs the normal file toggle when the file is collapsed', async () => {
makeFileAutomaticallyCollapsed(store);
- await wrapper.vm.$nextTick();
+ await nextTick();
eventHub.$emit(EVT_EXPAND_ALL_FILES);
@@ -278,7 +274,7 @@ describe('DiffFile', () => {
it('does nothing when the file is not collapsed', async () => {
eventHub.$emit(EVT_EXPAND_ALL_FILES);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.handleToggle).not.toHaveBeenCalled();
});
@@ -290,7 +286,7 @@ describe('DiffFile', () => {
});
it('should not have any content at all', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDiffContentArea(wrapper).element.children.length).toBe(0);
});
@@ -396,7 +392,7 @@ describe('DiffFile', () => {
readableText,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
toggleFile(wrapper);
};
@@ -444,7 +440,7 @@ describe('DiffFile', () => {
makeFileAutomaticallyCollapsed(store);
wrapper.vm.requestDiff();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLoader(wrapper).exists()).toBe(true);
});
@@ -455,7 +451,7 @@ describe('DiffFile', () => {
({ wrapper, store } = createComponent({ file: getUnreadableFile() }));
makeFileAutomaticallyCollapsed(store);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDiffContentArea(wrapper).html()).toContain(
'Files with large changes are collapsed by default.',
@@ -474,7 +470,7 @@ describe('DiffFile', () => {
markFileToBeRendered(store);
changeViewerType(store, mode);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.classes('has-body')).toBe(true);
expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
@@ -500,7 +496,7 @@ describe('DiffFile', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const button = wrapper.find('[data-testid="blob-button"]');
@@ -525,7 +521,7 @@ describe('DiffFile', () => {
({ wrapper, store } = createComponent({ file, props: { viewDiffsFileByFile: true } }));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLoader(wrapper).exists()).toBe(true);
});
diff --git a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
index 5884a9ebd3a..c18f0b721da 100644
--- a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
+++ b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import discussionsMockData from '../mock_data/diff_discussions';
@@ -35,12 +36,11 @@ describe('DiffGutterAvatars', () => {
expect(findCollapseButton().exists()).toBe(true);
});
- it('should emit toggleDiscussions event on button click', () => {
+ it('should emit toggleDiscussions event on button click', async () => {
findCollapseButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
});
@@ -65,20 +65,18 @@ describe('DiffGutterAvatars', () => {
expect(findMoreCount().text()).toBe('+2');
});
- it('should emit toggleDiscussions event on avatars click', () => {
+ it('should emit toggleDiscussions event on avatars click', async () => {
findUserAvatars().at(0).trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
- it('should emit toggleDiscussions event on more count text click', () => {
+ it('should emit toggleDiscussions event on more count text click', async () => {
findMoreCount().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
});
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
index 3af66526050..9b8f0421b7c 100644
--- a/spec/frontend/diffs/components/diff_view_spec.js
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -50,8 +50,11 @@ describe('DiffView', () => {
};
it('renders a match line', () => {
- const wrapper = createWrapper({ diffLines: [{ isMatchLineLeft: true }] });
+ const wrapper = createWrapper({
+ diffLines: [{ isMatchLineLeft: true, left: { rich_text: 'matched text', lineDraft: {} } }],
+ });
expect(wrapper.find(DiffExpansionCell).exists()).toBe(true);
+ expect(wrapper.text()).toContain('matched text');
});
it.each`
diff --git a/spec/frontend/diffs/components/image_diff_overlay_spec.js b/spec/frontend/diffs/components/image_diff_overlay_spec.js
index 8c1a8041f6c..70191620eb6 100644
--- a/spec/frontend/diffs/components/image_diff_overlay_spec.js
+++ b/spec/frontend/diffs/components/image_diff_overlay_spec.js
@@ -1,5 +1,5 @@
import { GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { createStore } from '~/mr_notes/stores';
import { imageDiffDiscussions } from '../mock_data/diff_discussions';
@@ -19,7 +19,7 @@ describe('Diffs image diff overlay component', () => {
extendStore(store);
dispatch = jest.spyOn(store, 'dispatch').mockImplementation();
- wrapper = shallowMount(ImageDiffOverlay, {
+ wrapper = mount(ImageDiffOverlay, {
store,
parentComponent: {
data() {
diff --git a/spec/frontend/diffs/components/merge_conflict_warning_spec.js b/spec/frontend/diffs/components/merge_conflict_warning_spec.js
index 2f303f25f66..4e47249f5b4 100644
--- a/spec/frontend/diffs/components/merge_conflict_warning_spec.js
+++ b/spec/frontend/diffs/components/merge_conflict_warning_spec.js
@@ -1,13 +1,11 @@
import { shallowMount, mount } from '@vue/test-utils';
import MergeConflictWarning from '~/diffs/components/merge_conflict_warning.vue';
-import { CENTERED_LIMITED_CONTAINER_CLASSES } from '~/diffs/constants';
const propsData = {
limited: true,
mergeable: true,
resolutionPath: 'a-path',
};
-const limitedClasses = CENTERED_LIMITED_CONTAINER_CLASSES.split(' ');
function findResolveButton(wrapper) {
return wrapper.find('.gl-alert-actions a.gl-button:first-child');
@@ -32,19 +30,6 @@ describe('MergeConflictWarning', () => {
});
it.each`
- limited | containerClasses
- ${true} | ${limitedClasses}
- ${false} | ${[]}
- `(
- 'has the correct container classes when limited is $limited',
- ({ limited, containerClasses }) => {
- createComponent({ limited });
-
- expect(wrapper.classes()).toEqual(containerClasses);
- },
- );
-
- it.each`
present | resolutionPath
${false} | ${''}
${true} | ${'some-path'}
diff --git a/spec/frontend/diffs/components/no_changes_spec.js b/spec/frontend/diffs/components/no_changes_spec.js
index 164c58dc8e4..6903b844e5e 100644
--- a/spec/frontend/diffs/components/no_changes_spec.js
+++ b/spec/frontend/diffs/components/no_changes_spec.js
@@ -1,12 +1,12 @@
import { GlButton } 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 NoChanges from '~/diffs/components/no_changes.vue';
import { createStore } from '~/mr_notes/stores';
import diffsMockData from '../mock_data/merge_request_diffs';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_TARGET_BRANCH = 'foo';
const TEST_SOURCE_BRANCH = 'dev/update';
@@ -17,7 +17,6 @@ describe('Diff no changes empty state', () => {
function createComponent(mountFn = shallowMount) {
wrapper = mountFn(NoChanges, {
- localVue,
store,
propsData: {
changesEmptyStateIllustration: '',
diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js
index 2dd35519464..693fc5bfd8f 100644
--- a/spec/frontend/diffs/components/settings_dropdown_spec.js
+++ b/spec/frontend/diffs/components/settings_dropdown_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
@@ -10,7 +11,6 @@ import createDiffsStore from '../create_diffs_store';
describe('Diff settings dropdown component', () => {
let wrapper;
- let vm;
let store;
function createComponent(extendStore = () => {}) {
@@ -23,7 +23,6 @@ describe('Diff settings dropdown component', () => {
store,
}),
);
- vm = wrapper.vm;
}
function getFileByFileCheckbox(vueWrapper) {
@@ -142,7 +141,7 @@ describe('Diff settings dropdown component', () => {
checkbox.trigger('click');
- await vm.$nextTick();
+ await nextTick();
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowWhitespace', {
showWhitespace: !checked,
@@ -185,7 +184,7 @@ describe('Diff settings dropdown component', () => {
getFileByFileCheckbox(wrapper).trigger('click');
- await vm.$nextTick();
+ await nextTick();
expect(store.dispatch).toHaveBeenCalledWith('diffs/setFileByFile', {
fileByFile: setting,
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index 31044b0818c..963805f4792 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import TreeList from '~/diffs/components/tree_list.vue';
import createStore from '~/diffs/store/modules';
@@ -8,13 +9,11 @@ describe('Diffs tree list component', () => {
let wrapper;
let store;
const getFileRows = () => wrapper.findAll('.file-row');
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const createComponent = (mountFn = mount) => {
wrapper = mountFn(TreeList, {
store,
- localVue,
propsData: { hideFileStats: false },
});
};
@@ -92,12 +91,11 @@ describe('Diffs tree list component', () => {
expect(getFileRows().at(1).html()).toContain('app');
});
- it('hides file stats', () => {
+ it('hides file stats', async () => {
wrapper.setProps({ hideFileStats: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.file-row-stats').exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find('.file-row-stats').exists()).toBe(false);
});
it('calls toggleTreeOpen when clicking folder', () => {
@@ -118,20 +116,18 @@ describe('Diffs tree list component', () => {
});
});
- it('renders as file list when renderTreeList is false', () => {
+ it('renders as file list when renderTreeList is false', async () => {
wrapper.vm.$store.state.diffs.renderTreeList = false;
- return wrapper.vm.$nextTick().then(() => {
- expect(getFileRows()).toHaveLength(1);
- });
+ await nextTick();
+ expect(getFileRows()).toHaveLength(1);
});
- it('renders file paths when renderTreeList is false', () => {
+ it('renders file paths when renderTreeList is false', async () => {
wrapper.vm.$store.state.diffs.renderTreeList = false;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.file-row').html()).toContain('index.js');
- });
+ await nextTick();
+ expect(wrapper.find('.file-row').html()).toContain('index.js');
});
});
@@ -143,14 +139,13 @@ describe('Diffs tree list component', () => {
store.state.diffs.viewedDiffFileIds = viewedDiffFileIds;
});
- it('passes the viewedDiffFileIds to the FileTree', () => {
+ it('passes the viewedDiffFileIds to the FileTree', async () => {
createComponent(shallowMount);
- return wrapper.vm.$nextTick().then(() => {
- // Have to use $attrs['viewed-files'] because we are passing down an object
- // and attributes('') stringifies values (e.g. [object])...
- expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds);
- });
+ await nextTick();
+ // Have to use $attrs['viewed-files'] because we are passing down an object
+ // and attributes('') stringifies values (e.g. [object])...
+ expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds);
});
});
});
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index b5003a54917..d6a2aa104cd 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -202,7 +202,7 @@ describe('DiffsStoreActions', () => {
testAction(
fetchDiffFilesBatch,
{},
- { endpointBatch, diffViewType: 'inline' },
+ { endpointBatch, diffViewType: 'inline', diffFiles: [] },
[
{ type: types.SET_BATCH_LOADING_STATE, payload: 'loading' },
{ type: types.SET_RETRIEVING_BATCHES, payload: true },
@@ -544,10 +544,8 @@ describe('DiffsStoreActions', () => {
[{ type: types.SET_DIFF_VIEW_TYPE, payload: INLINE_DIFF_VIEW_TYPE }],
[],
() => {
- setImmediate(() => {
- expect(Cookies.get('diff_view')).toEqual(INLINE_DIFF_VIEW_TYPE);
- done();
- });
+ expect(Cookies.get('diff_view')).toEqual(INLINE_DIFF_VIEW_TYPE);
+ done();
},
);
});
@@ -562,10 +560,8 @@ describe('DiffsStoreActions', () => {
[{ type: types.SET_DIFF_VIEW_TYPE, payload: PARALLEL_DIFF_VIEW_TYPE }],
[],
() => {
- setImmediate(() => {
- expect(Cookies.get(DIFF_VIEW_COOKIE_NAME)).toEqual(PARALLEL_DIFF_VIEW_TYPE);
- done();
- });
+ expect(Cookies.get(DIFF_VIEW_COOKIE_NAME)).toEqual(PARALLEL_DIFF_VIEW_TYPE);
+ done();
},
);
});
diff --git a/spec/frontend/editor/source_editor_yaml_ext_spec.js b/spec/frontend/editor/source_editor_yaml_ext_spec.js
index a861d9c7a45..b603b0e3a98 100644
--- a/spec/frontend/editor/source_editor_yaml_ext_spec.js
+++ b/spec/frontend/editor/source_editor_yaml_ext_spec.js
@@ -353,58 +353,78 @@ foo:
});
describe('highlight', () => {
- const highlightPathOnSetup = 'abc';
const value = `foo:
bar:
- baz
- boo
- abc: def
+abc: def
`;
let instance;
let highlightLinesSpy;
let removeHighlightsSpy;
- beforeEach(() => {
- instance = getEditorInstanceWithExtension({ highlightPath: highlightPathOnSetup }, { value });
- highlightLinesSpy = jest.fn();
- removeHighlightsSpy = jest.fn();
- spyOnApi(baseExtension, {
- highlightLines: highlightLinesSpy,
- removeHighlights: removeHighlightsSpy,
- });
- });
-
afterEach(() => {
jest.clearAllMocks();
});
- it('saves the highlighted path in highlightPath', () => {
- const path = 'foo.bar';
- instance.highlight(path);
- expect(yamlExtension.obj.highlightPath).toEqual(path);
- });
-
- it('calls highlightLines with a number of lines', () => {
- const path = 'foo.bar';
- instance.highlight(path);
- expect(highlightLinesSpy).toHaveBeenCalledWith(instance, [2, 4]);
- });
-
- it('calls removeHighlights if path is null', () => {
- instance.highlight(null);
- expect(removeHighlightsSpy).toHaveBeenCalledWith(instance);
- expect(highlightLinesSpy).not.toHaveBeenCalled();
- expect(yamlExtension.obj.highlightPath).toBeNull();
- });
-
- it('throws an error if path is invalid and does not change the highlighted path', () => {
- expect(() => instance.highlight('invalidPath[0]')).toThrow(
- 'The node invalidPath[0] could not be found inside the document.',
- );
- expect(yamlExtension.obj.highlightPath).toEqual(highlightPathOnSetup);
- expect(highlightLinesSpy).not.toHaveBeenCalled();
- expect(removeHighlightsSpy).not.toHaveBeenCalled();
- });
+ it.each`
+ highlightPathOnSetup | path | keepOnNotFound | expectHighlightLinesToBeCalled | withLines | expectRemoveHighlightsToBeCalled | storedHighlightPath
+ ${null} | ${undefined} | ${false} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${'abc'} | ${undefined} | ${false} | ${undefined} | ${false} | ${'abc'}
+ ${null} | ${null} | ${false} | ${false} | ${undefined} | ${false} | ${null}
+ ${null} | ${''} | ${false} | ${false} | ${undefined} | ${true} | ${null}
+ ${null} | ${''} | ${true} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${''} | ${false} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${'foo.bar'} | ${false} | ${true} | ${[2, 4]} | ${false} | ${'foo.bar'}
+ ${'abc'} | ${['foo', 'bar']} | ${false} | ${true} | ${[2, 4]} | ${false} | ${['foo', 'bar']}
+ ${'abc'} | ${'invalid'} | ${true} | ${false} | ${undefined} | ${false} | ${'abc'}
+ ${'abc'} | ${'invalid'} | ${false} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${'invalid'} | ${undefined} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${['invalid']} | ${undefined} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${['invalid']} | ${true} | ${false} | ${undefined} | ${false} | ${'abc'}
+ ${'abc'} | ${[]} | ${true} | ${false} | ${undefined} | ${true} | ${null}
+ ${'abc'} | ${[]} | ${false} | ${false} | ${undefined} | ${true} | ${null}
+ `(
+ 'returns correct result for highlightPathOnSetup=$highlightPathOnSetup, path=$path' +
+ ' and keepOnNotFound=$keepOnNotFound',
+ ({
+ highlightPathOnSetup,
+ path,
+ keepOnNotFound,
+ expectHighlightLinesToBeCalled,
+ withLines,
+ expectRemoveHighlightsToBeCalled,
+ storedHighlightPath,
+ }) => {
+ instance = getEditorInstanceWithExtension(
+ { highlightPath: highlightPathOnSetup },
+ { value },
+ );
+
+ highlightLinesSpy = jest.fn();
+ removeHighlightsSpy = jest.fn();
+ spyOnApi(baseExtension, {
+ highlightLines: highlightLinesSpy,
+ removeHighlights: removeHighlightsSpy,
+ });
+
+ instance.highlight(path, keepOnNotFound);
+
+ if (expectHighlightLinesToBeCalled) {
+ expect(highlightLinesSpy).toHaveBeenCalledWith(instance, withLines);
+ } else {
+ expect(highlightLinesSpy).not.toHaveBeenCalled();
+ }
+
+ if (expectRemoveHighlightsToBeCalled) {
+ expect(removeHighlightsSpy).toHaveBeenCalled();
+ } else {
+ expect(removeHighlightsSpy).not.toHaveBeenCalled();
+ }
+
+ expect(yamlExtension.obj.highlightPath).toEqual(storedHighlightPath);
+ },
+ );
});
describe('locate', () => {
@@ -446,10 +466,10 @@ foo:
expect(instance.locate(path)).toEqual(expected);
});
- it('throws an error if a path cannot be found inside the yaml', () => {
+ it('returns [null, null] if a path cannot be found inside the yaml', () => {
const path = 'baz[8]';
const instance = getEditorInstanceWithExtension(options);
- expect(() => instance.locate(path)).toThrow();
+ expect(instance.locate(path)).toEqual([null, null]);
});
it('returns the expected line numbers for a path to an array entry inside the yaml', () => {
diff --git a/spec/frontend/emoji/awards_app/store/actions_spec.js b/spec/frontend/emoji/awards_app/store/actions_spec.js
index 02b643244d2..0761256ed23 100644
--- a/spec/frontend/emoji/awards_app/store/actions_spec.js
+++ b/spec/frontend/emoji/awards_app/store/actions_spec.js
@@ -87,6 +87,26 @@ describe('Awards app actions', () => {
describe('toggleAward', () => {
let mock;
+ const optimisticAwardId = Number.MAX_SAFE_INTEGER - 1;
+ const makeOptimisticAddMutation = (
+ id = optimisticAwardId,
+ name = null,
+ userId = window.gon.current_user_id,
+ ) => ({
+ type: 'ADD_NEW_AWARD',
+ payload: {
+ id,
+ name,
+ user: {
+ id: userId,
+ },
+ },
+ });
+ const makeOptimisticRemoveMutation = (id = optimisticAwardId) => ({
+ type: 'REMOVE_AWARD',
+ payload: id,
+ });
+
beforeEach(() => {
mock = new MockAdapter(axios);
});
@@ -110,8 +130,10 @@ describe('Awards app actions', () => {
mock.onPost(`${relativeRootUrl || ''}/awards`).reply(200, { id: 1 });
});
- it('commits ADD_NEW_AWARD', async () => {
+ it('adds an optimistic award, removes it, and then commits ADD_NEW_AWARD', async () => {
testAction(actions.toggleAward, null, { path: '/awards', awards: [] }, [
+ makeOptimisticAddMutation(),
+ makeOptimisticRemoveMutation(),
{ type: 'ADD_NEW_AWARD', payload: { id: 1 } },
]);
});
@@ -127,7 +149,7 @@ describe('Awards app actions', () => {
actions.toggleAward,
null,
{ path: '/awards', awards: [] },
- [],
+ [makeOptimisticAddMutation(), makeOptimisticRemoveMutation()],
[],
() => {
expect(Sentry.captureException).toHaveBeenCalled();
@@ -137,7 +159,7 @@ describe('Awards app actions', () => {
});
});
- describe('removing a award', () => {
+ describe('removing an award', () => {
const mockData = { id: 1, name: 'thumbsup', user: { id: 1 } };
describe('success', () => {
@@ -160,6 +182,9 @@ describe('Awards app actions', () => {
});
describe('error', () => {
+ const currentUserId = 1;
+ const name = 'thumbsup';
+
beforeEach(() => {
mock.onDelete(`${relativeRootUrl || ''}/awards/1`).reply(500);
});
@@ -167,13 +192,13 @@ describe('Awards app actions', () => {
it('calls Sentry.captureException', async () => {
await testAction(
actions.toggleAward,
- 'thumbsup',
+ name,
{
path: '/awards',
- currentUserId: 1,
+ currentUserId,
awards: [mockData],
},
- [],
+ [makeOptimisticRemoveMutation(1), makeOptimisticAddMutation(1, name, currentUserId)],
[],
() => {
expect(Sentry.captureException).toHaveBeenCalled();
diff --git a/spec/frontend/emoji/components/utils_spec.js b/spec/frontend/emoji/components/utils_spec.js
index 36521eb1051..03eeb6b6bf7 100644
--- a/spec/frontend/emoji/components/utils_spec.js
+++ b/spec/frontend/emoji/components/utils_spec.js
@@ -31,6 +31,7 @@ describe('addToFrequentlyUsed', () => {
expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsup', {
expires: 365,
+ secure: false,
});
});
@@ -41,6 +42,7 @@ describe('addToFrequentlyUsed', () => {
expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsdown,thumbsup', {
expires: 365,
+ secure: false,
});
});
@@ -51,6 +53,7 @@ describe('addToFrequentlyUsed', () => {
expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsup', {
expires: 365,
+ secure: false,
});
});
});
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index cf47a1cd7bb..d7acf75fc95 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -29,6 +29,9 @@ class CustomEnvironment extends JSDOMEnvironment {
},
warn(...args) {
+ if (args[0].includes('The updateQuery callback for fetchMore is deprecated')) {
+ return;
+ }
throw new ErrorWithStack(
`Unexpected call of console.warn() with:\n\n${args.join(', ')}`,
this.warn,
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
index 6c7a786e652..d58f9f9b8a2 100644
--- a/spec/frontend/environments/canary_ingress_spec.js
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import { CANARY_UPDATE_MODAL } from '~/environments/constants';
+import { rolloutStatus } from './graphql/mock_data';
describe('/environments/components/canary_ingress.vue', () => {
let wrapper;
@@ -13,16 +14,18 @@ describe('/environments/components/canary_ingress.vue', () => {
.at(x / 5)
.vm.$emit('click');
- const createComponent = () => {
+ const createComponent = (props = {}, options = {}) => {
wrapper = mount(CanaryIngress, {
propsData: {
canaryIngress: {
canary_weight: 60,
},
+ ...props,
},
directives: {
GlModal: createMockDirective(),
},
+ ...options,
});
};
@@ -94,9 +97,25 @@ describe('/environments/components/canary_ingress.vue', () => {
});
it('is set to open the change modal', () => {
- const options = canaryWeightDropdown.findAll(GlDropdownItem);
- expect(options).toHaveLength(21);
- options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ canaryWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w) =>
+ expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
+ );
+ });
+ });
+
+ describe('graphql', () => {
+ beforeEach(() => {
+ createComponent({
+ graphql: true,
+ canaryIngress: rolloutStatus.canaryIngress,
+ });
+ });
+
+ it('shows the correct weight', () => {
+ const canaryWeightDropdown = wrapper.find('[data-testid="canary-weight"]');
+ expect(canaryWeightDropdown.props('text')).toBe('50');
});
});
});
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
index c7129ee1320..22d13558a84 100644
--- a/spec/frontend/environments/canary_update_modal_spec.js
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import updateCanaryIngress from '~/environments/graphql/mutations/update_canary_ingress.mutation.graphql';
@@ -86,7 +87,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().exists()).toBe(false);
});
@@ -95,7 +96,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().text()).toBe('error');
});
@@ -105,7 +106,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
modal.vm.$emit('primary');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().text()).toBe('Something went wrong. Please try again later');
});
@@ -114,12 +115,12 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
const alert = findAlert();
alert.vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(alert.exists()).toBe(false);
});
diff --git a/spec/frontend/environments/commit_spec.js b/spec/frontend/environments/commit_spec.js
new file mode 100644
index 00000000000..32eb4b77528
--- /dev/null
+++ b/spec/frontend/environments/commit_spec.js
@@ -0,0 +1,71 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import Commit from '~/environments/components/commit.vue';
+import { resolvedEnvironment } from './graphql/mock_data';
+
+describe('~/environments/components/commit.vue', () => {
+ let commit;
+ let wrapper;
+
+ beforeEach(() => {
+ commit = resolvedEnvironment.lastDeployment.commit;
+ });
+
+ const createWrapper = ({ propsData = {} } = {}) =>
+ mountExtended(Commit, {
+ propsData: {
+ commit,
+ ...propsData,
+ },
+ });
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ describe('with gitlab user', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('links to the user profile', () => {
+ const link = wrapper.findByRole('link', { name: commit.author.name });
+ expect(link.attributes('href')).toBe(commit.author.path);
+ });
+
+ it('displays the user avatar', () => {
+ const avatar = wrapper.findByRole('img', { name: 'avatar' });
+ expect(avatar.attributes('src')).toBe(commit.author.avatarUrl);
+ });
+
+ it('links the commit message to the commit', () => {
+ const message = wrapper.findByRole('link', { name: commit.message });
+
+ expect(message.attributes('href')).toBe(commit.commitPath);
+ });
+ });
+ describe('without gitlab user', () => {
+ beforeEach(() => {
+ commit = {
+ ...commit,
+ author: null,
+ };
+ wrapper = createWrapper();
+ });
+
+ it('links to the user profile', () => {
+ const link = wrapper.findByRole('link', { name: commit.authorName });
+ expect(link.attributes('href')).toBe(`mailto:${commit.authorEmail}`);
+ });
+
+ it('displays the user avatar', () => {
+ const avatar = wrapper.findByRole('img', { name: 'avatar' });
+ expect(avatar.attributes('src')).toBe(commit.authorGravatarUrl);
+ });
+
+ it('displays the commit message', () => {
+ const message = wrapper.findByRole('link', { name: commit.message });
+
+ expect(message.attributes('href')).toBe(commit.commitPath);
+ });
+ });
+});
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
index 24e94867afd..f0fb4d1027c 100644
--- a/spec/frontend/environments/deploy_board_component_spec.js
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -1,9 +1,10 @@
import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import { deployBoardMockData, environment } from './mock_data';
+import { rolloutStatus } from './graphql/mock_data';
const logsPath = `gitlab-org/gitlab-test/-/logs?environment_name=${environment.name}`;
@@ -24,11 +25,11 @@ describe('Deploy Board', () => {
describe('with valid data', () => {
beforeEach((done) => {
wrapper = createComponent();
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render percentage with completion value provided', () => {
- expect(wrapper.vm.$refs.percentage.innerText).toEqual(`${deployBoardMockData.completion}%`);
+ expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${deployBoardMockData.completion}%`);
});
it('should render total instance count', () => {
@@ -57,20 +58,74 @@ describe('Deploy Board', () => {
it('sets up a tooltip for the legend', () => {
const iconSpan = wrapper.find('[data-testid="legend-tooltip-target"]');
- const tooltip = wrapper.find(GlTooltip);
- const icon = iconSpan.find(GlIcon);
+ const tooltip = wrapper.findComponent(GlTooltip);
+ const icon = iconSpan.findComponent(GlIcon);
expect(tooltip.props('target')()).toBe(iconSpan.element);
expect(icon.props('name')).toBe('question');
});
it('renders the canary weight selector', () => {
- const canary = wrapper.find(CanaryIngress);
+ const canary = wrapper.findComponent(CanaryIngress);
expect(canary.exists()).toBe(true);
expect(canary.props('canaryIngress')).toEqual({ canary_weight: 50 });
});
});
+ describe('with new valid data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ graphql: true,
+ deployBoardData: rolloutStatus,
+ });
+ await nextTick();
+ });
+
+ it('should render percentage with completion value provided', () => {
+ expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${rolloutStatus.completion}%`);
+ });
+
+ it('should render total instance count', () => {
+ const renderedTotal = wrapper.find('.deploy-board-instances-text');
+ const actualTotal = rolloutStatus.instances.length;
+ const output = `${actualTotal > 1 ? 'Instances' : 'Instance'} (${actualTotal})`;
+
+ expect(renderedTotal.text()).toEqual(output);
+ });
+
+ it('should render all instances', () => {
+ const instances = wrapper.findAll('.deploy-board-instances-container a');
+
+ expect(instances).toHaveLength(rolloutStatus.instances.length);
+ expect(
+ instances.at(1).classes(`deployment-instance-${rolloutStatus.instances[2].status}`),
+ ).toBe(true);
+ });
+
+ it('should render an abort and a rollback button with the provided url', () => {
+ const buttons = wrapper.findAll('.deploy-board-actions a');
+
+ expect(buttons.at(0).attributes('href')).toEqual(rolloutStatus.rollbackUrl);
+ expect(buttons.at(1).attributes('href')).toEqual(rolloutStatus.abortUrl);
+ });
+
+ it('sets up a tooltip for the legend', () => {
+ const iconSpan = wrapper.find('[data-testid="legend-tooltip-target"]');
+ const tooltip = wrapper.findComponent(GlTooltip);
+ const icon = iconSpan.findComponent(GlIcon);
+
+ expect(tooltip.props('target')()).toBe(iconSpan.element);
+ expect(icon.props('name')).toBe('question');
+ });
+
+ it('renders the canary weight selector', () => {
+ const canary = wrapper.findComponent(CanaryIngress);
+ expect(canary.exists()).toBe(true);
+ expect(canary.props('canaryIngress')).toEqual({ canaryWeight: 50 });
+ expect(canary.props('graphql')).toBe(true);
+ });
+ });
+
describe('with empty state', () => {
beforeEach((done) => {
wrapper = createComponent({
@@ -79,7 +134,7 @@ describe('Deploy Board', () => {
isEmpty: true,
logsPath,
});
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render the empty state', () => {
@@ -98,11 +153,11 @@ describe('Deploy Board', () => {
isEmpty: false,
logsPath,
});
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -116,7 +171,7 @@ describe('Deploy Board', () => {
deployBoardData: deployBoardMockData,
});
({ statuses } = wrapper.vm);
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('with all the possible statuses', () => {
diff --git a/spec/frontend/environments/deploy_board_wrapper_spec.js b/spec/frontend/environments/deploy_board_wrapper_spec.js
new file mode 100644
index 00000000000..c8e6df4d324
--- /dev/null
+++ b/spec/frontend/environments/deploy_board_wrapper_spec.js
@@ -0,0 +1,124 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlCollapse, GlIcon } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubTransition } from 'helpers/stub_transition';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { __, s__ } from '~/locale';
+import DeployBoardWrapper from '~/environments/components/deploy_board_wrapper.vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
+import setEnvironmentToChangeCanaryMutation from '~/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql';
+import { resolvedEnvironment, rolloutStatus } from './graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('~/environments/components/deploy_board_wrapper.vue', () => {
+ let wrapper;
+ let mockApollo;
+
+ const findDeployBoard = () => wrapper.findComponent(DeployBoard);
+
+ const createWrapper = ({ propsData = {} } = {}) => {
+ mockApollo = createMockApollo();
+ return mountExtended(DeployBoardWrapper, {
+ propsData: { environment: resolvedEnvironment, rolloutStatus, ...propsData },
+ provide: { helpPagePath: '/help' },
+ stubs: { transition: stubTransition() },
+ apolloProvider: mockApollo,
+ });
+ };
+
+ const expandCollapsedSection = async () => {
+ const button = wrapper.findByRole('button', { name: __('Expand') });
+ await button.trigger('click');
+
+ return button;
+ };
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ it('is labeled Kubernetes Pods', () => {
+ wrapper = createWrapper();
+
+ expect(wrapper.findByText(s__('DeployBoard|Kubernetes Pods')).exists()).toBe(true);
+ });
+
+ describe('collapse', () => {
+ let icon;
+ let collapse;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ collapse = wrapper.findComponent(GlCollapse);
+ icon = wrapper.findComponent(GlIcon);
+ });
+
+ it('is collapsed by default', () => {
+ expect(collapse.attributes('visible')).toBeUndefined();
+ expect(icon.props('name')).toBe('angle-right');
+ });
+
+ it('opens on click', async () => {
+ const button = await expandCollapsedSection();
+
+ expect(button.attributes('aria-label')).toBe(__('Collapse'));
+ expect(collapse.attributes('visible')).toBe('visible');
+ expect(icon.props('name')).toBe('angle-down');
+
+ const deployBoard = findDeployBoard();
+ expect(deployBoard.exists()).toBe(true);
+ });
+ });
+
+ describe('deploy board', () => {
+ it('passes the rollout status on and sets graphql to true', async () => {
+ wrapper = createWrapper();
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+ expect(deployBoard.props('deployBoardData')).toEqual(rolloutStatus);
+ expect(deployBoard.props('graphql')).toBe(true);
+ });
+
+ it('sets the update to the canary via graphql', () => {
+ wrapper = createWrapper();
+ jest.spyOn(mockApollo.defaultClient, 'mutate');
+ const deployBoard = findDeployBoard();
+ deployBoard.vm.$emit('changeCanaryWeight', 15);
+ expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: setEnvironmentToChangeCanaryMutation,
+ variables: { environment: resolvedEnvironment, weight: 15 },
+ });
+ });
+
+ describe('is loading', () => {
+ it('should set the loading prop', async () => {
+ wrapper = createWrapper({
+ propsData: { rolloutStatus: { ...rolloutStatus, status: 'loading' } },
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+
+ expect(deployBoard.props('isLoading')).toBe(true);
+ });
+ });
+
+ describe('is empty', () => {
+ it('should set the empty prop', async () => {
+ wrapper = createWrapper({
+ propsData: { rolloutStatus: { ...rolloutStatus, status: 'not_found' } },
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+
+ expect(deployBoard.props('isEmpty')).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/deployment_spec.js b/spec/frontend/environments/deployment_spec.js
index 37209bdc86c..6cc363e000b 100644
--- a/spec/frontend/environments/deployment_spec.js
+++ b/spec/frontend/environments/deployment_spec.js
@@ -1,17 +1,32 @@
+import { GlCollapse } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { useFakeDate } from 'helpers/fake_date';
+import { stubTransition } from 'helpers/stub_transition';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { __, s__ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Deployment from '~/environments/components/deployment.vue';
+import Commit from '~/environments/components/commit.vue';
import DeploymentStatusBadge from '~/environments/components/deployment_status_badge.vue';
import { resolvedEnvironment } from './graphql/mock_data';
describe('~/environments/components/deployment.vue', () => {
+ useFakeDate(2022, 0, 8, 16);
+
+ let deployment;
let wrapper;
+ beforeEach(() => {
+ deployment = resolvedEnvironment.lastDeployment;
+ });
+
const createWrapper = ({ propsData = {} } = {}) =>
mountExtended(Deployment, {
propsData: {
- deployment: resolvedEnvironment.lastDeployment,
+ deployment,
...propsData,
},
+ stubs: { transition: stubTransition() },
});
afterEach(() => {
@@ -21,9 +36,229 @@ describe('~/environments/components/deployment.vue', () => {
describe('status', () => {
it('should pass the deployable status to the badge', () => {
wrapper = createWrapper();
- expect(wrapper.findComponent(DeploymentStatusBadge).props('status')).toBe(
- resolvedEnvironment.lastDeployment.status,
- );
+ expect(wrapper.findComponent(DeploymentStatusBadge).props('status')).toBe(deployment.status);
+ });
+ });
+
+ describe('latest', () => {
+ it('should show a badge if the deployment is latest', () => {
+ wrapper = createWrapper({ propsData: { latest: true } });
+
+ const badge = wrapper.findByText(s__('Deployment|Latest Deployed'));
+
+ expect(badge.exists()).toBe(true);
+ });
+
+ it('should not show a badge if the deployment is not latest', () => {
+ wrapper = createWrapper();
+
+ const badge = wrapper.findByText(s__('Deployment|Latest Deployed'));
+
+ expect(badge.exists()).toBe(false);
+ });
+ });
+
+ describe('iid', () => {
+ const findIid = () => wrapper.findByTitle(s__('Deployment|Deployment ID'));
+ const findDeploymentIcon = () => wrapper.findComponent({ ref: 'deployment-iid-icon' });
+
+ describe('is present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('should show the iid', () => {
+ const iid = findIid();
+ expect(iid.exists()).toBe(true);
+ });
+
+ it('should show an icon for the iid', () => {
+ const deploymentIcon = findDeploymentIcon();
+ expect(deploymentIcon.props('name')).toBe('deployments');
+ });
+ });
+
+ describe('is not present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, iid: '' } } });
+ });
+
+ it('should not show the iid', () => {
+ const iid = findIid();
+ expect(iid.exists()).toBe(false);
+ });
+
+ it('should not show an icon for the iid', () => {
+ const deploymentIcon = findDeploymentIcon();
+ expect(deploymentIcon.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('shortSha', () => {
+ describe('is present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('shows the short SHA for the commit of the deployment', () => {
+ const sha = wrapper.findByTitle(__('Commit SHA'));
+
+ expect(sha.exists()).toBe(true);
+ expect(sha.text()).toBe(deployment.commit.shortId);
+ });
+
+ it('shows the commit icon', () => {
+ const icon = wrapper.findComponent({ ref: 'deployment-commit-icon' });
+ expect(icon.props('name')).toBe('commit');
+ });
+
+ it('shows a copy button for the sha', () => {
+ const button = wrapper.findComponent(ClipboardButton);
+ expect(button.props()).toMatchObject({
+ text: deployment.commit.shortId,
+ title: __('Copy commit SHA'),
+ });
+ });
+ });
+
+ describe('is not present', () => {
+ it('does not show the short SHA for the commit of the deployment', () => {
+ wrapper = createWrapper({
+ propsData: {
+ deployment: {
+ ...deployment,
+ commit: null,
+ },
+ },
+ });
+ const sha = wrapper.findByTestId('deployment-commit-sha');
+ expect(sha.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('created at time', () => {
+ describe('is present', () => {
+ it('shows the timestamp the deployment was deployed at', () => {
+ wrapper = createWrapper();
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.text()).toBe('1 day ago');
+ });
+ });
+ describe('is not present', () => {
+ it('does not show the timestamp', () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, createdAt: null } } });
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('commit message', () => {
+ describe('with commit', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('shows the commit component', () => {
+ const commit = wrapper.findComponent(Commit);
+ expect(commit.props('commit')).toBe(deployment.commit);
+ });
+ });
+
+ describe('without a commit', () => {
+ it('displays nothing', () => {
+ const noCommit = {
+ ...deployment,
+ commit: null,
+ };
+ wrapper = createWrapper({ propsData: { deployment: noCommit } });
+
+ const commit = wrapper.findComponent(Commit);
+ expect(commit.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('collapse', () => {
+ let collapse;
+ let button;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ collapse = wrapper.findComponent(GlCollapse);
+ button = wrapper.findComponent({ ref: 'details-toggle' });
+ });
+
+ it('is collapsed by default', () => {
+ expect(collapse.attributes('visible')).toBeUndefined();
+ expect(button.props('icon')).toBe('expand-down');
+ expect(button.text()).toBe(__('Show details'));
+ });
+
+ it('opens on click', async () => {
+ await button.trigger('click');
+
+ expect(button.text()).toBe(__('Hide details'));
+ expect(button.props('icon')).toBe('expand-up');
+ expect(collapse.attributes('visible')).toBe('visible');
+
+ const username = wrapper.findByRole('link', { name: `@${deployment.user.username}` });
+
+ expect(username.attributes('href')).toBe(deployment.user.path);
+ const job = wrapper.findByRole('link', { name: deployment.deployable.name });
+ expect(job.attributes('href')).toBe(deployment.deployable.buildPath);
+ const apiBadge = wrapper.findByText(__('API'));
+ expect(apiBadge.exists()).toBe(false);
+
+ const branchLabel = wrapper.findByText(__('Branch'));
+ expect(branchLabel.exists()).toBe(true);
+ const tagLabel = wrapper.findByText(__('Tag'));
+ expect(tagLabel.exists()).toBe(false);
+ const ref = wrapper.findByRole('link', { name: deployment.ref.name });
+ expect(ref.attributes('href')).toBe(deployment.ref.refPath);
+ });
+ });
+
+ describe('with tagged deployment', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, tag: true } } });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows tag instead of branch', () => {
+ const refLabel = wrapper.findByText(__('Tag'));
+ expect(refLabel.exists()).toBe(true);
+ });
+ });
+
+ describe('with API deployment', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, deployable: null } } });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows API instead of a job name', () => {
+ const apiBadge = wrapper.findByText(__('API'));
+ expect(apiBadge.exists()).toBe(true);
+ });
+ });
+ describe('without a job path', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({
+ propsData: {
+ deployment: { ...deployment, deployable: { name: deployment.deployable.name } },
+ },
+ });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows a span instead of a link', () => {
+ const job = wrapper.findByTitle(deployment.deployable.name);
+ expect(job.attributes('href')).toBeUndefined();
});
});
});
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index 1b68a692db8..336c207428e 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -1,6 +1,6 @@
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { TEST_HOST } from 'helpers/test_constants';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -108,7 +108,7 @@ describe('EnvironmentActions Component', () => {
jest.spyOn(window, 'confirm').mockImplementation(() => confirm);
findDropdownItem(scheduledJobAction).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
diff --git a/spec/frontend/environments/environment_pin_spec.js b/spec/frontend/environments/environment_pin_spec.js
index a9a58071e12..669c974ea4f 100644
--- a/spec/frontend/environments/environment_pin_spec.js
+++ b/spec/frontend/environments/environment_pin_spec.js
@@ -1,5 +1,9 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import cancelAutoStopMutation from '~/environments/graphql/mutations/cancel_auto_stop.mutation.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
import PinComponent from '~/environments/components/environment_pin.vue';
import eventHub from '~/environments/event_hub';
@@ -18,28 +22,66 @@ describe('Pin Component', () => {
const autoStopUrl = '/root/auto-stop-env-test/-/environments/38/cancel_auto_stop';
- beforeEach(() => {
- factory({
- propsData: {
- autoStopUrl,
- },
+ describe('without graphql', () => {
+ beforeEach(() => {
+ factory({
+ propsData: {
+ autoStopUrl,
+ },
+ });
});
- });
- afterEach(() => {
- wrapper.destroy();
- });
+ afterEach(() => {
+ wrapper.destroy();
+ });
- it('should render the component with descriptive text', () => {
- expect(wrapper.text()).toBe('Prevent auto-stopping');
+ it('should render the component with descriptive text', () => {
+ expect(wrapper.text()).toBe('Prevent auto-stopping');
+ });
+
+ it('should emit onPinClick when clicked', () => {
+ const eventHubSpy = jest.spyOn(eventHub, '$emit');
+ const item = wrapper.find(GlDropdownItem);
+
+ item.vm.$emit('click');
+
+ expect(eventHubSpy).toHaveBeenCalledWith('cancelAutoStop', autoStopUrl);
+ });
});
- it('should emit onPinClick when clicked', () => {
- const eventHubSpy = jest.spyOn(eventHub, '$emit');
- const item = wrapper.find(GlDropdownItem);
+ describe('with graphql', () => {
+ Vue.use(VueApollo);
+ let mockApollo;
- item.vm.$emit('click');
+ beforeEach(() => {
+ mockApollo = createMockApollo();
+ factory({
+ propsData: {
+ autoStopUrl,
+ graphql: true,
+ },
+ apolloProvider: mockApollo,
+ });
+ });
- expect(eventHubSpy).toHaveBeenCalledWith('cancelAutoStop', autoStopUrl);
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render the component with descriptive text', () => {
+ expect(wrapper.text()).toBe('Prevent auto-stopping');
+ });
+
+ it('should emit onPinClick when clicked', () => {
+ jest.spyOn(mockApollo.defaultClient, 'mutate');
+ const item = wrapper.find(GlDropdownItem);
+
+ item.vm.$emit('click');
+
+ expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: cancelAutoStopMutation,
+ variables: { autoStopUrl },
+ });
+ });
});
});
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index 1851163ac68..c7582e4b06d 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import EnvironmentTable from '~/environments/components/environments_table.vue';
@@ -181,7 +182,7 @@ describe('Environment table', () => {
});
wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
weight: 40,
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index cd05ecbfb53..92d1820681c 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -1,6 +1,7 @@
import { GlTabs } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Container from '~/environments/components/container.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
@@ -186,14 +187,13 @@ describe('Environment', () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false);
});
- it('should close an opened folder', () => {
+ it('should close an opened folder', async () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true);
// close folder
wrapper.find('.folder-name').trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
it('should show children environments', () => {
diff --git a/spec/frontend/environments/graphql/mock_data.js b/spec/frontend/environments/graphql/mock_data.js
index fce30973547..1b7b35702de 100644
--- a/spec/frontend/environments/graphql/mock_data.js
+++ b/spec/frontend/environments/graphql/mock_data.js
@@ -1,3 +1,69 @@
+export const rolloutStatus = {
+ instances: [
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2334 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2335 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2336 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2337 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2338 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2339 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ { status: 'succeeded', tooltip: 'tanuki-2340 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2334 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2335 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2336 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2337 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2338 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2339 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2340 Finished', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2341 Deploying', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2342 Deploying', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2343 Deploying', podName: 'production-tanuki-1' },
+ { status: 'failed', tooltip: 'tanuki-2344 Failed', podName: 'production-tanuki-1' },
+ { status: 'unknown', tooltip: 'tanuki-2345 Ready', podName: 'production-tanuki-1' },
+ { status: 'unknown', tooltip: 'tanuki-2346 Ready', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2348 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2349 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2350 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2353 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2354 waiting', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2355 waiting', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2356 waiting', podName: 'production-tanuki-1' },
+ ],
+ abortUrl: 'url',
+ rollbackUrl: 'url',
+ completion: 100,
+ status: 'found',
+ canaryIngress: { canaryWeight: 50 },
+};
export const environmentsApp = {
environments: [
{
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
index 6b53dc24f0f..21d7e09bad5 100644
--- a/spec/frontend/environments/graphql/resolvers_spec.js
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -173,9 +173,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should post to the auto stop path', async () => {
mock.onPost(ENDPOINT).reply(200);
- await mockResolvers.Mutation.cancelAutoStop(null, {
- environment: { autoStopPath: ENDPOINT },
- });
+ await mockResolvers.Mutation.cancelAutoStop(null, { autoStopUrl: ENDPOINT });
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
diff --git a/spec/frontend/environments/new_environment_folder_spec.js b/spec/frontend/environments/new_environment_folder_spec.js
index 6823c88a5a1..460263587be 100644
--- a/spec/frontend/environments/new_environment_folder_spec.js
+++ b/spec/frontend/environments/new_environment_folder_spec.js
@@ -32,6 +32,7 @@ describe('~/environments/components/new_environments_folder.vue', () => {
apolloProvider,
propsData,
stubs: { transition: stubTransition() },
+ provide: { helpPagePath: '/help' },
});
beforeEach(async () => {
diff --git a/spec/frontend/environments/new_environment_item_spec.js b/spec/frontend/environments/new_environment_item_spec.js
index 244aef5c43b..db596688dad 100644
--- a/spec/frontend/environments/new_environment_item_spec.js
+++ b/spec/frontend/environments/new_environment_item_spec.js
@@ -2,12 +2,14 @@ import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { GlCollapse, GlIcon } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import { stubTransition } from 'helpers/stub_transition';
-import { __, s__ } from '~/locale';
+import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
+import { __, s__, sprintf } from '~/locale';
import EnvironmentItem from '~/environments/components/new_environment_item.vue';
import Deployment from '~/environments/components/deployment.vue';
-import { resolvedEnvironment } from './graphql/mock_data';
+import DeployBoardWrapper from '~/environments/components/deploy_board_wrapper.vue';
+import { resolvedEnvironment, rolloutStatus } from './graphql/mock_data';
Vue.use(VueApollo);
@@ -22,11 +24,19 @@ describe('~/environments/components/new_environment_item.vue', () => {
mountExtended(EnvironmentItem, {
apolloProvider,
propsData: { environment: resolvedEnvironment, ...propsData },
+ provide: { helpPagePath: '/help' },
stubs: { transition: stubTransition() },
});
const findDeployment = () => wrapper.findComponent(Deployment);
+ const expandCollapsedSection = async () => {
+ const button = wrapper.findByRole('button', { name: __('Expand') });
+ await button.trigger('click');
+
+ return button;
+ };
+
afterEach(() => {
wrapper?.destroy();
});
@@ -165,25 +175,92 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
describe('pin', () => {
- it('shows the option to pin the environment if there is an autostop date', () => {
- wrapper = createWrapper({
- propsData: {
- environment: { ...resolvedEnvironment, autoStopAt: new Date(Date.now() + 100000) },
- },
- apolloProvider: createApolloProvider(),
+ describe('with autostop', () => {
+ let environment;
+
+ beforeEach(() => {
+ environment = {
+ ...resolvedEnvironment,
+ autoStopAt: new Date(Date.now() + 100000).toString(),
+ };
+ wrapper = createWrapper({
+ propsData: {
+ environment,
+ },
+ apolloProvider: createApolloProvider(),
+ });
});
- const rollback = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+ it('shows the option to pin the environment if there is an autostop date', () => {
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
- expect(rollback.exists()).toBe(true);
+ expect(pin.exists()).toBe(true);
+ });
+
+ it('shows when the environment auto stops', () => {
+ const autoStop = wrapper.findByTitle(formatDate(environment.autoStopAt));
+
+ expect(autoStop.text()).toBe('in 1 minute');
+ });
});
- it('does not show the option to pin the environment if there is no autostop date', () => {
- wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+ describe('without autostop', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+ });
- const rollback = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+ it('does not show the option to pin the environment if there is no autostop date', () => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
- expect(rollback.exists()).toBe(false);
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+
+ expect(pin.exists()).toBe(false);
+ });
+
+ it('does not show when the environment auto stops', () => {
+ const autoStop = wrapper.findByText(
+ sprintf(s__('Environment|Auto stop %{time}'), {
+ time: getTimeago().format(resolvedEnvironment.autoStopAt),
+ }),
+ );
+
+ expect(autoStop.exists()).toBe(false);
+ });
+ });
+
+ describe('with past autostop', () => {
+ let environment;
+
+ beforeEach(() => {
+ environment = {
+ ...resolvedEnvironment,
+ autoStopAt: new Date(Date.now() - 100000).toString(),
+ };
+ wrapper = createWrapper({
+ propsData: {
+ environment,
+ },
+ apolloProvider: createApolloProvider(),
+ });
+ });
+
+ it('does not show the option to pin the environment if there is no autostop date', () => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+
+ expect(pin.exists()).toBe(false);
+ });
+
+ it('does not show when the environment auto stops', () => {
+ const autoStop = wrapper.findByText(
+ sprintf(s__('Environment|Auto stop %{time}'), {
+ time: getTimeago().format(environment.autoStopAt),
+ }),
+ );
+
+ expect(autoStop.exists()).toBe(false);
+ });
});
});
@@ -258,14 +335,12 @@ describe('~/environments/components/new_environment_item.vue', () => {
describe('collapse', () => {
let icon;
let collapse;
- let button;
let environmentName;
beforeEach(() => {
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
collapse = wrapper.findComponent(GlCollapse);
icon = wrapper.findComponent(GlIcon);
- button = wrapper.findByRole('button', { name: __('Expand') });
environmentName = wrapper.findByText(resolvedEnvironment.name);
});
@@ -278,7 +353,7 @@ describe('~/environments/components/new_environment_item.vue', () => {
it('opens on click', async () => {
expect(findDeployment().isVisible()).toBe(false);
- await button.trigger('click');
+ const button = await expandCollapsedSection();
expect(button.attributes('aria-label')).toBe(__('Collapse'));
expect(collapse.attributes('visible')).toBe('visible');
@@ -338,4 +413,78 @@ describe('~/environments/components/new_environment_item.vue', () => {
expect(deployment.exists()).toBe(false);
});
});
+
+ describe('empty state', () => {
+ it('should link to documentation', async () => {
+ const environment = {
+ ...resolvedEnvironment,
+ lastDeployment: null,
+ upcomingDeployment: null,
+ };
+
+ wrapper = createWrapper({
+ propsData: { environment },
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const text = s__(
+ 'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
+ );
+
+ const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
+
+ const link = extendedWrapper(emptyState).findByRole('link');
+
+ expect(link.attributes('href')).toBe('/help');
+ });
+
+ it('should not link to the documentation when there are deployments', async () => {
+ wrapper = createWrapper({
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const text = s__(
+ 'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
+ );
+
+ const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
+
+ expect(emptyState.exists()).toBe(false);
+ });
+ });
+
+ describe('deploy boards', () => {
+ it('should show a deploy board if the environment has a rollout status', async () => {
+ const environment = {
+ ...resolvedEnvironment,
+ rolloutStatus,
+ };
+
+ wrapper = createWrapper({
+ propsData: { environment },
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = wrapper.findComponent(DeployBoardWrapper);
+ expect(deployBoard.exists()).toBe(true);
+ expect(deployBoard.props('rolloutStatus')).toBe(rolloutStatus);
+ });
+
+ it('should not show a deploy board if the environment has no rollout status', async () => {
+ wrapper = createWrapper({
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = wrapper.findComponent(DeployBoardWrapper);
+ expect(deployBoard.exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/environments/new_environments_app_spec.js b/spec/frontend/environments/new_environments_app_spec.js
index c9eccc26694..42e3608109b 100644
--- a/spec/frontend/environments/new_environments_app_spec.js
+++ b/spec/frontend/environments/new_environments_app_spec.js
@@ -10,6 +10,7 @@ import EnvironmentsApp from '~/environments/components/new_environments_app.vue'
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
import EnvironmentsItem from '~/environments/components/new_environment_item.vue';
import StopEnvironmentModal from '~/environments/components/stop_environment_modal.vue';
+import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import { resolvedEnvironmentsApp, resolvedFolder, resolvedEnvironment } from './graphql/mock_data';
Vue.use(VueApollo);
@@ -20,6 +21,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
let environmentFolderMock;
let paginationMock;
let environmentToStopMock;
+ let environmentToChangeCanaryMock;
+ let weightMock;
const createApolloProvider = () => {
const mockResolvers = {
@@ -28,6 +31,10 @@ describe('~/environments/components/new_environments_app.vue', () => {
folder: environmentFolderMock,
pageInfo: paginationMock,
environmentToStop: environmentToStopMock,
+ environmentToDelete: jest.fn().mockResolvedValue(resolvedEnvironment),
+ environmentToRollback: jest.fn().mockResolvedValue(resolvedEnvironment),
+ environmentToChangeCanary: environmentToChangeCanaryMock,
+ weight: weightMock,
},
};
@@ -40,6 +47,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
newEnvironmentPath: '/environments/new',
canCreateEnvironment: true,
defaultBranchName: 'main',
+ helpPagePath: '/help',
...provide,
},
apolloProvider,
@@ -50,6 +58,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentsApp,
folder,
environmentToStop = {},
+ environmentToChangeCanary = {},
+ weight = 0,
pageInfo = {
total: 20,
perPage: 5,
@@ -64,6 +74,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentFolderMock.mockReturnValue(folder);
paginationMock.mockReturnValue(pageInfo);
environmentToStopMock.mockReturnValue(environmentToStop);
+ environmentToChangeCanaryMock.mockReturnValue(environmentToChangeCanary);
+ weightMock.mockReturnValue(weight);
const apolloProvider = createApolloProvider();
wrapper = createWrapper({ apolloProvider, provide });
@@ -75,11 +87,13 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentAppMock = jest.fn();
environmentFolderMock = jest.fn();
environmentToStopMock = jest.fn();
+ environmentToChangeCanaryMock = jest.fn();
+ weightMock = jest.fn();
paginationMock = jest.fn();
});
afterEach(() => {
- wrapper?.destroy();
+ wrapper.destroy();
});
it('should show all the folders that are fetched', async () => {
@@ -149,8 +163,6 @@ describe('~/environments/components/new_environments_app.vue', () => {
},
folder: resolvedFolder,
});
- await waitForPromises();
- await nextTick();
const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
expect(button.exists()).toBe(false);
@@ -206,6 +218,19 @@ describe('~/environments/components/new_environments_app.vue', () => {
expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
});
+
+ it('should pass the environment to change canary to the canary update modal', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ environmentToChangeCanary: resolvedEnvironment,
+ weight: 10,
+ });
+
+ const modal = wrapper.findComponent(CanaryUpdateModal);
+
+ expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
+ });
});
describe('pagination', () => {
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 77f51193258..03ae437a89e 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -7,7 +7,8 @@ import {
GlAlert,
GlSprintf,
} from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import {
severityLevel,
@@ -27,8 +28,7 @@ import Tracking from '~/tracking';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ErrorDetails', () => {
let store;
@@ -53,7 +53,6 @@ describe('ErrorDetails', () => {
function mountComponent() {
wrapper = shallowMount(ErrorDetails, {
stubs: { GlButton, GlSprintf },
- localVue,
store,
mocks,
propsData: {
@@ -140,32 +139,30 @@ describe('ErrorDetails', () => {
mountComponent();
});
- it('when before timeout, still shows loading', () => {
+ it('when before timeout, still shows loading', async () => {
Date.now.mockReturnValue(endTime - 1);
wrapper.vm.onNoApolloResult();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(createFlash).not.toHaveBeenCalled();
- expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(createFlash).not.toHaveBeenCalled();
+ expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
});
- it('when timeout is hit and no apollo result, stops loading and shows flash', () => {
+ it('when timeout is hit and no apollo result, stops loading and shows flash', async () => {
Date.now.mockReturnValue(endTime + 1);
wrapper.vm.onNoApolloResult();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlLink).exists()).toBe(false);
- expect(createFlash).toHaveBeenCalledWith({
- message: 'Could not connect to Sentry. Refresh the page to try again.',
- type: 'warning',
- });
- expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(GlLink).exists()).toBe(false);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Could not connect to Sentry. Refresh the page to try again.',
+ type: 'warning',
});
+ expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
});
});
@@ -225,7 +222,7 @@ describe('ErrorDetails', () => {
});
describe('Badges', () => {
- it('should show language and error level badges', () => {
+ it('should show language and error level badges', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -233,12 +230,11 @@ describe('ErrorDetails', () => {
tags: { level: 'error', logger: 'ruby' },
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlBadge).length).toBe(2);
- });
+ await nextTick();
+ expect(wrapper.findAll(GlBadge).length).toBe(2);
});
- it('should NOT show the badge if the tag is not present', () => {
+ it('should NOT show the badge if the tag is not present', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -246,14 +242,13 @@ describe('ErrorDetails', () => {
tags: { level: 'error' },
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlBadge).length).toBe(1);
- });
+ await nextTick();
+ expect(wrapper.findAll(GlBadge).length).toBe(1);
});
it.each(Object.keys(severityLevel))(
'should set correct severity level variant for %s badge',
- (level) => {
+ async (level) => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -261,15 +256,14 @@ describe('ErrorDetails', () => {
tags: { level: severityLevel[level] },
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlBadge).props('variant')).toEqual(
- severityLevelVariant[severityLevel[level]],
- );
- });
+ await nextTick();
+ expect(wrapper.find(GlBadge).props('variant')).toEqual(
+ severityLevelVariant[severityLevel[level]],
+ );
},
);
- it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', () => {
+ it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -277,32 +271,29 @@ describe('ErrorDetails', () => {
tags: { level: 'someNewErrorLevel' },
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlBadge).props('variant')).toEqual(
- severityLevelVariant[severityLevel.ERROR],
- );
- });
+ await nextTick();
+ expect(wrapper.find(GlBadge).props('variant')).toEqual(
+ severityLevelVariant[severityLevel.ERROR],
+ );
});
});
describe('Stacktrace', () => {
- it('should show stacktrace', () => {
+ it('should show stacktrace', async () => {
store.state.details.loadingStacktrace = false;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(true);
- expect(findAlert().exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(Stacktrace).exists()).toBe(true);
+ expect(findAlert().exists()).toBe(false);
});
- it('should NOT show stacktrace if no entries and show Alert message', () => {
+ it('should NOT show stacktrace if no entries and show Alert message', async () => {
store.state.details.loadingStacktrace = false;
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
- expect(findAlert().text()).toBe('No stack trace for this error');
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(Stacktrace).exists()).toBe(false);
+ expect(findAlert().text()).toBe('No stack trace for this error');
});
});
@@ -339,10 +330,10 @@ describe('ErrorDetails', () => {
});
describe('when error is unresolved', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.details.errorStatus = errorStatus.UNRESOLVED;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays Ignore and Resolve buttons', () => {
@@ -366,10 +357,10 @@ describe('ErrorDetails', () => {
});
describe('when error is ignored', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.details.errorStatus = errorStatus.IGNORED;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays Undo Ignore and Resolve buttons', () => {
@@ -393,10 +384,10 @@ describe('ErrorDetails', () => {
});
describe('when error is resolved', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.details.errorStatus = errorStatus.RESOLVED;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays Ignore and Unresolve buttons', () => {
@@ -418,7 +409,7 @@ describe('ErrorDetails', () => {
);
});
- it('should show alert with closed issueId', () => {
+ it('should show alert with closed issueId', async () => {
const closedIssueId = 123;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -427,10 +418,9 @@ describe('ErrorDetails', () => {
closedIssueId,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toContain(`#${closedIssueId}`);
- });
+ await nextTick();
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toContain(`#${closedIssueId}`);
});
});
});
@@ -496,7 +486,7 @@ describe('ErrorDetails', () => {
'/gitlab-org/gitlab-test/commit/7975be0116940bf2ad4321f79d02a55c5f7779aa';
const findGitLabCommitLink = () => wrapper.find(`[href$="${gitlabCommitPath}"]`);
- it('should display a link', () => {
+ it('should display a link', async () => {
mocks.$apollo.queries.error.loading = false;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -506,12 +496,11 @@ describe('ErrorDetails', () => {
gitlabCommitPath,
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findGitLabCommitLink().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findGitLabCommitLink().exists()).toBe(true);
});
- it('should not display a link', () => {
+ it('should not display a link', async () => {
mocks.$apollo.queries.error.loading = false;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -520,9 +509,8 @@ describe('ErrorDetails', () => {
gitlabCommit: null,
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findGitLabCommitLink().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findGitLabCommitLink().exists()).toBe(false);
});
});
@@ -595,33 +583,25 @@ describe('ErrorDetails', () => {
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
- it('should track IGNORE status update', () => {
+ it('should track IGNORE status update', async () => {
Tracking.event.mockClear();
- findUpdateIgnoreStatusButton().vm.$emit('click');
- setImmediate(() => {
- const { category, action } = trackErrorStatusUpdateOptions('ignored');
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
+ await findUpdateIgnoreStatusButton().trigger('click');
+ const { category, action } = trackErrorStatusUpdateOptions('ignored');
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
- it('should track RESOLVE status update', () => {
+ it('should track RESOLVE status update', async () => {
Tracking.event.mockClear();
- findUpdateResolveStatusButton().vm.$emit('click');
- setImmediate(() => {
- const { category, action } = trackErrorStatusUpdateOptions('resolved');
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
+ await findUpdateResolveStatusButton().trigger('click');
+ const { category, action } = trackErrorStatusUpdateOptions('resolved');
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
- it('should track external Sentry link views', () => {
+ it('should track external Sentry link views', async () => {
Tracking.event.mockClear();
- findExternalUrl().trigger('click');
- setImmediate(() => {
- const { category, action, label, property } = trackClickErrorLinkToSentryOptions(
- externalUrl,
- );
- expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property });
- });
+ await findExternalUrl().trigger('click');
+ const { category, action, label, property } = trackClickErrorLinkToSentryOptions(externalUrl);
+ expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property });
});
});
});
diff --git a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
index e21c40423c3..7ed4e5f6b05 100644
--- a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
describe('Error Tracking Actions', () => {
@@ -37,13 +38,12 @@ describe('Error Tracking Actions', () => {
const findButtons = () => wrapper.findAll(GlButton);
describe('when error status is unresolved', () => {
- it('renders the correct actions buttons to allow ignore and resolve', () => {
+ it('renders the correct actions buttons to allow ignore and resolve', async () => {
expect(findButtons().exists()).toBe(true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findButtons().at(0).attributes('title')).toBe('Ignore');
- expect(findButtons().at(1).attributes('title')).toBe('Resolve');
- });
+ await nextTick();
+ expect(findButtons().at(0).attributes('title')).toBe('Ignore');
+ expect(findButtons().at(1).attributes('title')).toBe('Resolve');
});
});
@@ -52,12 +52,11 @@ describe('Error Tracking Actions', () => {
mountComponent({ error: { status: 'ignored' } });
});
- it('renders the correct action button to undo ignore', () => {
+ it('renders the correct action button to undo ignore', async () => {
expect(findButtons().exists()).toBe(true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore');
- });
+ await nextTick();
+ expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore');
});
});
@@ -66,12 +65,11 @@ describe('Error Tracking Actions', () => {
mountComponent({ error: { status: 'resolved' } });
});
- it('renders the correct action button to undo unresolve', () => {
+ it('renders the correct action button to undo unresolve', async () => {
expect(findButtons().exists()).toBe(true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findButtons().at(1).attributes('title')).toBe('Unresolve');
- });
+ await nextTick();
+ expect(findButtons().at(1).attributes('title')).toBe('Unresolve');
});
});
});
diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
index 74d5731bbea..59671c175e7 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -1,5 +1,6 @@
import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
@@ -8,8 +9,7 @@ import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '~/err
import Tracking from '~/tracking';
import errorsList from './list_mock.json';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ErrorTrackingList', () => {
let store;
@@ -32,7 +32,6 @@ describe('ErrorTrackingList', () => {
stubs = {},
} = {}) {
wrapper = mount(ErrorTrackingList, {
- localVue,
store,
propsData: {
indexPath: '/path',
@@ -317,15 +316,14 @@ describe('ErrorTrackingList', () => {
expect(findRecentSearchesDropdown().text()).toContain("You don't have any recent searches");
});
- it('shows items', () => {
+ it('shows items', async () => {
store.state.list.recentSearches = ['great', 'search'];
- return wrapper.vm.$nextTick().then(() => {
- const dropdownItems = wrapper.findAll('.filtered-search-box li');
- expect(dropdownItems.length).toBe(3);
- expect(dropdownItems.at(0).text()).toBe('great');
- expect(dropdownItems.at(1).text()).toBe('search');
- });
+ await nextTick();
+ const dropdownItems = wrapper.findAll('.filtered-search-box li');
+ expect(dropdownItems.length).toBe(3);
+ expect(dropdownItems.at(0).text()).toBe('great');
+ expect(dropdownItems.at(1).text()).toBe('search');
});
describe('clear', () => {
@@ -337,23 +335,21 @@ describe('ErrorTrackingList', () => {
expect(clearRecentButton().exists()).toBe(false);
});
- it('is visible when list has items', () => {
+ it('is visible when list has items', async () => {
store.state.list.recentSearches = ['some', 'searches'];
- return wrapper.vm.$nextTick().then(() => {
- expect(clearRecentButton().exists()).toBe(true);
- expect(clearRecentButton().text()).toBe('Clear recent searches');
- });
+ await nextTick();
+ expect(clearRecentButton().exists()).toBe(true);
+ expect(clearRecentButton().text()).toBe('Clear recent searches');
});
- it('clears items on click', () => {
+ it('clears items on click', async () => {
store.state.list.recentSearches = ['some', 'searches'];
- return wrapper.vm.$nextTick().then(() => {
- clearRecentButton().vm.$emit('click');
+ await nextTick();
+ clearRecentButton().vm.$emit('click');
- expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1);
- });
+ expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1);
});
});
});
@@ -388,7 +384,7 @@ describe('ErrorTrackingList', () => {
describe('and the user is not on the first page', () => {
describe('and the previous button is clicked', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.list.loading = false;
mountComponent({
stubs: {
@@ -399,7 +395,7 @@ describe('ErrorTrackingList', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ pageValue: 2 });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('fetches the previous page of results', () => {
@@ -451,7 +447,7 @@ describe('ErrorTrackingList', () => {
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
- it('should track status updates', () => {
+ it('should track status updates', async () => {
Tracking.event.mockClear();
const status = 'ignored';
findErrorActions().vm.$emit('update-issue-status', {
@@ -459,10 +455,10 @@ describe('ErrorTrackingList', () => {
status,
});
- setImmediate(() => {
- const { category, action } = trackErrorStatusUpdateOptions(status);
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
+ await nextTick();
+
+ const { category, action } = trackErrorStatusUpdateOptions(status);
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
});
});
diff --git a/spec/frontend/error_tracking_settings/components/app_spec.js b/spec/frontend/error_tracking_settings/components/app_spec.js
index 844faff64a1..4d19ec047ef 100644
--- a/spec/frontend/error_tracking_settings/components/app_spec.js
+++ b/spec/frontend/error_tracking_settings/components/app_spec.js
@@ -1,6 +1,6 @@
import { GlFormRadioGroup, GlFormRadio, GlFormInputGroup } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { TEST_HOST } from 'helpers/test_constants';
@@ -10,8 +10,7 @@ import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracki
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
import createStore from '~/error_tracking_settings/store';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_GITLAB_DSN = 'https://gitlab.example.com/123456';
@@ -22,7 +21,6 @@ describe('error tracking settings app', () => {
function mountComponent() {
wrapper = extendedWrapper(
shallowMount(ErrorTrackingSettings, {
- localVue,
store, // Override the imported store
propsData: {
initialEnabled: 'true',
@@ -81,12 +79,11 @@ describe('error tracking settings app', () => {
expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeFalsy();
});
- it('disables the button when saving', () => {
+ it('disables the button when saving', async () => {
store.state.settingsLoading = true;
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy();
});
});
diff --git a/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js b/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
index 2e8a42dbfe6..69d684faec2 100644
--- a/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
+++ b/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
@@ -1,12 +1,12 @@
import { GlFormInput, GlButton } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
import createStore from '~/error_tracking_settings/store';
import { defaultProps } from '../mock';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('error tracking settings form', () => {
let wrapper;
@@ -14,7 +14,6 @@ describe('error tracking settings form', () => {
function mountComponent() {
wrapper = shallowMount(ErrorTrackingForm, {
- localVue,
store,
propsData: defaultProps,
});
diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
index 79518a487d4..1ba5a505f57 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -1,19 +1,18 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { pick, clone } from 'lodash';
import Vuex from 'vuex';
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
import { defaultProps, projectList, staleProject } from '../mock';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('error tracking settings project dropdown', () => {
let wrapper;
function mountComponent() {
wrapper = shallowMount(ProjectDropdown, {
- localVue,
propsData: {
...pick(
defaultProps,
@@ -64,10 +63,10 @@ describe('error tracking settings project dropdown', () => {
});
describe('populated project list', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ projects: clone(projectList), hasProjects: true });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders the dropdown', () => {
@@ -84,9 +83,9 @@ describe('error tracking settings project dropdown', () => {
describe('selected project', () => {
const selectedProject = clone(projectList[0]);
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ projects: clone(projectList), selectedProject, hasProjects: true });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not show helper text', () => {
@@ -96,13 +95,13 @@ describe('error tracking settings project dropdown', () => {
});
describe('invalid project selected', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({
projects: clone(projectList),
selectedProject: staleProject,
isProjectInvalid: true,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays a error', () => {
diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
index f244da228b3..4a0242b4a46 100644
--- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
+++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Component from '~/feature_flags/components/configure_feature_flags_modal.vue';
@@ -56,7 +57,7 @@ describe('Configure Feature Flags Modal', () => {
it('should emit a `token` event when clicking on the Primary action', async () => {
findGlModal().vm.$emit('secondary', mockEvent);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('token')).toEqual([[]]);
expect(mockEvent.preventDefault).toHaveBeenCalled();
});
@@ -64,7 +65,7 @@ describe('Configure Feature Flags Modal', () => {
it('should clear the project name input after generating the token', async () => {
findProjectNameInput().vm.$emit('input', provide.projectName);
findGlModal().vm.$emit('primary', mockEvent);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findProjectNameInput().attributes('value')).toBe('');
});
@@ -116,7 +117,7 @@ describe('Configure Feature Flags Modal', () => {
it('should enable the secondary action', async () => {
findProjectNameInput().vm.$emit('input', provide.projectName);
- await wrapper.vm.$nextTick();
+ await nextTick();
const [{ disabled }] = findSecondaryAction().attributes;
expect(disabled).toBe(false);
});
diff --git a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
index 721b7249abc..05709cd05e6 100644
--- a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
@@ -1,7 +1,7 @@
import { GlToggle, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -12,6 +12,7 @@ import createStore from '~/feature_flags/store/edit';
import axios from '~/lib/utils/axios_utils';
Vue.use(Vuex);
+
describe('Edit feature flag form', () => {
let wrapper;
let mock;
@@ -66,13 +67,12 @@ describe('Edit feature flag form', () => {
});
describe('with error', () => {
- it('should render the error', () => {
+ it('should render the error', async () => {
store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] });
- return wrapper.vm.$nextTick(() => {
- const warningGlAlert = findWarningGlAlert();
- expect(warningGlAlert.exists()).toEqual(true);
- expect(warningGlAlert.text()).toContain('The name is required');
- });
+ await nextTick();
+ const warningGlAlert = findWarningGlAlert();
+ expect(warningGlAlert.exists()).toEqual(true);
+ expect(warningGlAlert.text()).toContain('The name is required');
});
});
diff --git a/spec/frontend/feature_flags/components/empty_state_spec.js b/spec/frontend/feature_flags/components/empty_state_spec.js
index 86d0c1a05fd..4ac82ae44a6 100644
--- a/spec/frontend/feature_flags/components/empty_state_spec.js
+++ b/spec/frontend/feature_flags/components/empty_state_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlEmptyState, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import EmptyState from '~/feature_flags/components/empty_state.vue';
const DEFAULT_PROPS = {
@@ -123,7 +124,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
beforeEach(async () => {
wrapper = factory();
- await wrapper.vm.$nextTick();
+ await nextTick();
slot = wrapper.find('[data-testid="test-slot"]');
});
diff --git a/spec/frontend/feature_flags/components/environments_dropdown_spec.js b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
index 9194db3a182..cca472012e9 100644
--- a/spec/frontend/feature_flags/components/environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon, GlButton, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue';
@@ -54,7 +55,7 @@ describe('Feature flags > Environments dropdown ', () => {
factory();
findEnvironmentSearchInput().vm.$emit('focus');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
});
@@ -66,7 +67,7 @@ describe('Feature flags > Environments dropdown ', () => {
factory();
findEnvironmentSearchInput().vm.$emit('keyup');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
});
@@ -80,7 +81,7 @@ describe('Feature flags > Environments dropdown ', () => {
findEnvironmentSearchInput().vm.$emit('focus');
findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets filter value', () => {
@@ -103,7 +104,7 @@ describe('Feature flags > Environments dropdown ', () => {
.filter((b) => b.text() === 'production')
.at(0);
button.vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('selectEnvironment')).toEqual([['production']]);
});
});
@@ -111,7 +112,7 @@ describe('Feature flags > Environments dropdown ', () => {
describe('on click clear button', () => {
beforeEach(async () => {
wrapper.find(GlButton).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('resets filter value', () => {
@@ -132,12 +133,12 @@ describe('Feature flags > Environments dropdown ', () => {
findEnvironmentSearchInput().vm.$emit('focus');
findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('emits create event', async () => {
wrapper.findAll(GlButton).at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('createClicked')).toEqual([['production']]);
});
});
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index db4bdc736de..d27b23c5cd1 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
@@ -13,8 +14,7 @@ import axios from '~/lib/utils/axios_utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import { getRequestData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Feature flags', () => {
const mockData = {
@@ -45,7 +45,6 @@ describe('Feature flags', () => {
const factory = (provide = mockData, fn = mount) => {
store = createStore(mockState);
wrapper = fn(FeatureFlagsComponent, {
- localVue,
store,
provide,
stubs: {
@@ -72,12 +71,12 @@ describe('Feature flags', () => {
describe('when limit exceeded', () => {
const provideData = { ...mockData, featureFlagsLimitExceeded: true };
- beforeEach((done) => {
+ beforeEach(() => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory(provideData);
- setImmediate(done);
+ return waitForPromises();
});
it('makes the new feature flag button do nothing if clicked', () => {
@@ -117,12 +116,12 @@ describe('Feature flags', () => {
userListPath: null,
};
- beforeEach((done) => {
+ beforeEach(() => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory(provideData);
- setImmediate(done);
+ return waitForPromises();
});
it('does not render configure button', () => {
@@ -173,7 +172,7 @@ describe('Feature flags', () => {
factory();
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
emptyState = wrapper.findComponent(GlEmptyState);
});
@@ -203,7 +202,7 @@ describe('Feature flags', () => {
});
describe('with paginated feature flags', () => {
- beforeEach((done) => {
+ beforeEach(() => {
mock.onGet(mockState.endpoint, { params: { page: '1' } }).replyOnce(200, getRequestData, {
'x-next-page': '2',
'x-page': '1',
@@ -215,7 +214,7 @@ describe('Feature flags', () => {
factory();
jest.spyOn(store, 'dispatch');
- setImmediate(done);
+ return waitForPromises();
});
it('should render a table with feature flags', () => {
@@ -271,11 +270,11 @@ describe('Feature flags', () => {
});
describe('unsuccessful request', () => {
- beforeEach((done) => {
+ beforeEach(() => {
mock.onGet(mockState.endpoint, { params: { page: '1' } }).replyOnce(500, {});
factory();
- setImmediate(done);
+ return waitForPromises();
});
it('should render error state', () => {
@@ -301,12 +300,12 @@ describe('Feature flags', () => {
});
describe('rotate instance id', () => {
- beforeEach((done) => {
+ beforeEach(() => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory();
- setImmediate(done);
+ return waitForPromises();
});
it('should fire the rotate action when a `token` event is received', () => {
diff --git a/spec/frontend/feature_flags/components/feature_flags_table_spec.js b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
index d06d60ae310..99864a95f59 100644
--- a/spec/frontend/feature_flags/components/feature_flags_table_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
@@ -1,5 +1,6 @@
import { GlToggle, GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { mockTracking } from 'helpers/tracking_helper';
import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
@@ -148,13 +149,12 @@ describe('Feature flag table', () => {
});
});
- it('should trigger a toggle event', () => {
+ it('should trigger a toggle event', async () => {
toggle.vm.$emit('change');
const flag = { ...props.featureFlags[0], active: !props.featureFlags[0].active };
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]);
- });
+ await nextTick();
+ expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]);
});
it('tracks a click', () => {
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index c0f9638390a..3ad1225906b 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Api from '~/api';
import Form from '~/feature_flags/components/form.vue';
@@ -126,28 +127,26 @@ describe('feature flag form', () => {
expect(wrapper.findAll(Strategy)).toHaveLength(2);
});
- it('adds an all users strategy when clicking the Add button', () => {
+ it('adds an all users strategy when clicking the Add button', async () => {
wrapper.find(GlButton).vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- const strategies = wrapper.findAll(Strategy);
+ await nextTick();
+ const strategies = wrapper.findAll(Strategy);
- expect(strategies).toHaveLength(3);
- expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy);
- });
+ expect(strategies).toHaveLength(3);
+ expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy);
});
- it('should remove a strategy on delete', () => {
+ it('should remove a strategy on delete', async () => {
const strategy = {
type: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '30' },
scopes: [],
};
wrapper.find(Strategy).vm.$emit('delete');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(Strategy)).toHaveLength(1);
- expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
- });
+ await nextTick();
+ expect(wrapper.findAll(Strategy)).toHaveLength(1);
+ expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
});
});
});
diff --git a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
index 6342ac0bda7..63fa5d19982 100644
--- a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -47,16 +48,13 @@ describe('New Environments Dropdown', () => {
describe('with empty results', () => {
let item;
- beforeEach(() => {
+ beforeEach(async () => {
axiosMock.onGet(TEST_HOST).reply(200, []);
wrapper.find(GlSearchBoxByType).vm.$emit('focus');
wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH);
- return axios
- .waitForAll()
- .then(() => wrapper.vm.$nextTick())
- .then(() => {
- item = wrapper.find(GlDropdownItem);
- });
+ await axios.waitForAll();
+ await nextTick();
+ item = wrapper.find(GlDropdownItem);
});
it('should display a Create item label', () => {
diff --git a/spec/frontend/feature_flags/components/new_feature_flag_spec.js b/spec/frontend/feature_flags/components/new_feature_flag_spec.js
index fe98b6421d4..9c1657bc0d2 100644
--- a/spec/frontend/feature_flags/components/new_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/new_feature_flag_spec.js
@@ -1,5 +1,6 @@
import { GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants';
import Form from '~/feature_flags/components/form.vue';
@@ -10,8 +11,7 @@ import { allUsersStrategy } from '../mock_data';
const userCalloutId = 'feature_flags_new_version';
const userCalloutsPath = `${TEST_HOST}/user_callouts`;
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('New feature flag form', () => {
let wrapper;
@@ -27,7 +27,6 @@ describe('New feature flag form', () => {
wrapper = null;
}
wrapper = shallowMount(NewFeatureFlag, {
- localVue,
store,
provide: {
showUserCallout: true,
@@ -52,13 +51,12 @@ describe('New feature flag form', () => {
});
describe('with error', () => {
- it('should render the error', () => {
+ it('should render the error', async () => {
store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] });
- return wrapper.vm.$nextTick(() => {
- const warningGlAlert = findWarningGlAlert();
- expect(warningGlAlert.at(0).exists()).toBe(true);
- expect(warningGlAlert.at(0).text()).toContain('The name is required');
- });
+ await nextTick();
+ const warningGlAlert = findWarningGlAlert();
+ expect(warningGlAlert.at(0).exists()).toBe(true);
+ expect(warningGlAlert.at(0).text()).toContain('The name is required');
});
});
diff --git a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
index 07aa456e69e..56b14d80ab3 100644
--- a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
@@ -1,5 +1,6 @@
import { GlFormInput, GlFormSelect } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import FlexibleRollout from '~/feature_flags/components/strategies/flexible_rollout.vue';
import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue';
import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants';
@@ -51,7 +52,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
it('emits a change when the percentage value changes', async () => {
percentageInput.setValue('75');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toEqual([
[
{
diff --git a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
index 6188672b23b..3b69194494f 100644
--- a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Api from '~/api';
import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
@@ -12,15 +13,13 @@ const DEFAULT_PROPS = {
strategy: userListStrategy,
};
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
let wrapper;
const factory = (props = {}) =>
mount(GitlabUserList, {
- localVue,
store: createStore({ projectId: '1' }),
propsData: { ...DEFAULT_PROPS, ...props },
});
@@ -72,7 +71,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
);
const searchWrapper = wrapper.find(GlSearchBoxByType);
searchWrapper.vm.$emit('input', 'new');
- await wrapper.vm.$nextTick();
+ await nextTick();
const loadingIcon = wrapper.find(GlLoadingIcon);
expect(loadingIcon.exists()).toBe(true);
@@ -80,7 +79,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
r({ data: [userList] });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(loadingIcon.exists()).toBe(false);
});
diff --git a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
index 442f7faf161..180697e93e4 100644
--- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
@@ -1,5 +1,6 @@
import { GlFormInput } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue';
import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants';
@@ -39,7 +40,7 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
it('emits a change when the value changes', async () => {
input.setValue('75');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toEqual([
[{ parameters: { percentage: '75', groupId: PERCENT_ROLLOUT_GROUP_ID } }],
]);
diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js
index 4fdf436bfc4..aee3873721c 100644
--- a/spec/frontend/feature_flags/components/strategy_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { last } from 'lodash';
import Vuex from 'vuex';
import Api from '~/api';
@@ -26,8 +27,7 @@ const provide = {
environmentsEndpoint: '',
};
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Feature flags strategy', () => {
let wrapper;
@@ -48,7 +48,7 @@ describe('Feature flags strategy', () => {
wrapper.destroy();
wrapper = null;
}
- wrapper = mount(Strategy, { localVue, store: createStore({ projectId: '1' }), ...opts });
+ wrapper = mount(Strategy, { store: createStore({ projectId: '1' }), ...opts });
};
beforeEach(() => {
@@ -85,11 +85,11 @@ describe('Feature flags strategy', () => {
let propsData;
let strategy;
- beforeEach(() => {
+ beforeEach(async () => {
strategy = { name, parameters: {}, scopes: [] };
propsData = { strategy, index: 0 };
factory({ propsData, provide });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('should set the select to match the strategy name', () => {
@@ -138,19 +138,18 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
- it('should revert to all-environments scope when last scope is removed', () => {
+ it('should revert to all-environments scope when last scope is removed', async () => {
const token = wrapper.find(GlToken);
token.vm.$emit('close');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlToken)).toHaveLength(0);
- expect(last(wrapper.emitted('change'))).toEqual([
- {
- name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
- scopes: [{ environmentScope: '*' }],
- },
- ]);
- });
+ await nextTick();
+ expect(wrapper.findAll(GlToken)).toHaveLength(0);
+ expect(last(wrapper.emitted('change'))).toEqual([
+ {
+ name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
+ scopes: [{ environmentScope: '*' }],
+ },
+ ]);
});
});
@@ -167,56 +166,52 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
- it('should change the parameters if a different strategy is chosen', () => {
+ it('should change the parameters if a different strategy is chosen', async () => {
const select = wrapper.find(GlFormSelect);
select.setValue(ROLLOUT_STRATEGY_ALL_USERS);
- return wrapper.vm.$nextTick().then(() => {
- expect(last(wrapper.emitted('change'))).toEqual([
- {
- name: ROLLOUT_STRATEGY_ALL_USERS,
- parameters: {},
- scopes: [{ environmentScope: '*' }],
- },
- ]);
- });
+ await nextTick();
+ expect(last(wrapper.emitted('change'))).toEqual([
+ {
+ name: ROLLOUT_STRATEGY_ALL_USERS,
+ parameters: {},
+ scopes: [{ environmentScope: '*' }],
+ },
+ ]);
});
- it('should display selected scopes', () => {
+ it('should display selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlToken)).toHaveLength(1);
- expect(wrapper.find(GlToken).text()).toBe('production');
- });
+ await nextTick();
+ expect(wrapper.findAll(GlToken)).toHaveLength(1);
+ expect(wrapper.find(GlToken).text()).toBe('production');
});
- it('should display all selected scopes', () => {
+ it('should display all selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
- return wrapper.vm.$nextTick().then(() => {
- const tokens = wrapper.findAll(GlToken);
- expect(tokens).toHaveLength(2);
- expect(tokens.at(0).text()).toBe('production');
- expect(tokens.at(1).text()).toBe('staging');
- });
+ await nextTick();
+ const tokens = wrapper.findAll(GlToken);
+ expect(tokens).toHaveLength(2);
+ expect(tokens.at(0).text()).toBe('production');
+ expect(tokens.at(1).text()).toBe('staging');
});
- it('should emit selected scopes', () => {
+ it('should emit selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
- return wrapper.vm.$nextTick().then(() => {
- expect(last(wrapper.emitted('change'))).toEqual([
- {
- name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
- scopes: [
- { environmentScope: '*', shouldBeDestroyed: true },
- { environmentScope: 'production' },
- ],
- },
- ]);
- });
+ await nextTick();
+ expect(last(wrapper.emitted('change'))).toEqual([
+ {
+ name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
+ scopes: [
+ { environmentScope: '*', shouldBeDestroyed: true },
+ { environmentScope: 'production' },
+ ],
+ },
+ ]);
});
it('should emit a delete if the delete button is clicked', () => {
@@ -236,39 +231,36 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
- it('should display selected scopes', () => {
+ it('should display selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlToken)).toHaveLength(1);
- expect(wrapper.find(GlToken).text()).toBe('production');
- });
+ await nextTick();
+ expect(wrapper.findAll(GlToken)).toHaveLength(1);
+ expect(wrapper.find(GlToken).text()).toBe('production');
});
- it('should display all selected scopes', () => {
+ it('should display all selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
- return wrapper.vm.$nextTick().then(() => {
- const tokens = wrapper.findAll(GlToken);
- expect(tokens).toHaveLength(2);
- expect(tokens.at(0).text()).toBe('production');
- expect(tokens.at(1).text()).toBe('staging');
- });
+ await nextTick();
+ const tokens = wrapper.findAll(GlToken);
+ expect(tokens).toHaveLength(2);
+ expect(tokens.at(0).text()).toBe('production');
+ expect(tokens.at(1).text()).toBe('staging');
});
- it('should emit selected scopes', () => {
+ it('should emit selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
- return wrapper.vm.$nextTick().then(() => {
- expect(last(wrapper.emitted('change'))).toEqual([
- {
- name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
- scopes: [{ environmentScope: 'production' }],
- },
- ]);
- });
+ await nextTick();
+ expect(last(wrapper.emitted('change'))).toEqual([
+ {
+ name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
+ scopes: [{ environmentScope: 'production' }],
+ },
+ ]);
});
});
});
diff --git a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
index e5e3974e103..650f9eb1bbc 100644
--- a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
+++ b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
@@ -1,5 +1,6 @@
import { GlPopover, GlLink, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { POPOVER_TARGET_ID } from '~/feature_highlight/constants';
import { dismiss } from '~/feature_highlight/feature_highlight_helper';
import FeatureHighlightPopover from '~/feature_highlight/feature_highlight_popover.vue';
@@ -71,7 +72,7 @@ describe('feature_highlight/feature_highlight_popover', () => {
it('hides the popover target', async () => {
await findDismissButton().trigger('click');
findPopover().vm.$emit('hidden');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPopoverTarget().exists()).toBe(false);
});
diff --git a/spec/frontend/filtered_search/dropdown_user_spec.js b/spec/frontend/filtered_search/dropdown_user_spec.js
index 9a20fb1bae6..ee0eef6a1b6 100644
--- a/spec/frontend/filtered_search/dropdown_user_spec.js
+++ b/spec/frontend/filtered_search/dropdown_user_spec.js
@@ -74,7 +74,7 @@ describe('Dropdown User', () => {
});
describe('hideCurrentUser', () => {
- const fixtureTemplate = 'issues/issue_list.html';
+ const fixtureTemplate = 'merge_requests/merge_request_list.html';
let dropdown;
let authorFilterDropdownElement;
diff --git a/spec/frontend/filtered_search/dropdown_utils_spec.js b/spec/frontend/filtered_search/dropdown_utils_spec.js
index 49e14f58630..4c1e79eba42 100644
--- a/spec/frontend/filtered_search/dropdown_utils_spec.js
+++ b/spec/frontend/filtered_search/dropdown_utils_spec.js
@@ -4,7 +4,7 @@ import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dro
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
describe('Dropdown Utils', () => {
- const issueListFixture = 'issues/issue_list.html';
+ const issuableListFixture = 'merge_requests/merge_request_list.html';
describe('getEscapedText', () => {
it('should return same word when it has no space', () => {
@@ -350,7 +350,7 @@ describe('Dropdown Utils', () => {
let authorToken;
beforeEach(() => {
- loadFixtures(issueListFixture);
+ loadFixtures(issuableListFixture);
authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
const searchTermToken = FilteredSearchSpecHelper.createSearchVisualToken('search term');
diff --git a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
index 44f67f269a2..c4e125e96da 100644
--- a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
@@ -1,6 +1,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
describe('Filtered Search Visual Tokens', () => {
@@ -715,18 +716,16 @@ describe('Filtered Search Visual Tokens', () => {
`);
});
- it('renders a author token value element', () => {
+ it('renders a author token value element', async () => {
const { tokenNameElement, tokenValueElement } = findElements(authorToken);
const tokenName = tokenNameElement.textContent;
const tokenValue = 'new value';
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
- jest.runOnlyPendingTimers();
+ await waitForPromises();
- setImmediate(() => {
- expect(tokenValueElement.textContent).toBe(tokenValue);
- });
+ expect(tokenValueElement.textContent).toBe(tokenValue);
});
});
});
diff --git a/spec/frontend/filtered_search/recent_searches_root_spec.js b/spec/frontend/filtered_search/recent_searches_root_spec.js
index fa3267c98a1..59c428fb3fa 100644
--- a/spec/frontend/filtered_search/recent_searches_root_spec.js
+++ b/spec/frontend/filtered_search/recent_searches_root_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { setHTMLFixture } from 'helpers/fixtures';
import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
@@ -10,7 +11,7 @@ describe('RecentSearchesRoot', () => {
let vm;
let containerEl;
- beforeEach(() => {
+ beforeEach(async () => {
setHTMLFixture(`
<div id="${containerId}">
<div id="${dropdownElementId}"></div>
@@ -33,7 +34,7 @@ describe('RecentSearchesRoot', () => {
RecentSearchesRoot.prototype.render.call(recentSearchesRootMockInstance);
vm = recentSearchesRootMockInstance.vm;
- return vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
diff --git a/spec/frontend/fixtures/application_settings.rb b/spec/frontend/fixtures/application_settings.rb
index 9fa8d68e695..a7a989f31ec 100644
--- a/spec/frontend/fixtures/application_settings.rb
+++ b/spec/frontend/fixtures/application_settings.rb
@@ -13,6 +13,7 @@ RSpec.describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', ty
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ allow(Gitlab::Metrics).to receive(:metrics_folder_present?).and_return(true)
sign_in(admin)
enable_admin_mode!(admin)
end
diff --git a/spec/frontend/fixtures/blob.rb b/spec/frontend/fixtures/blob.rb
index 35a7ff4eb07..af548823886 100644
--- a/spec/frontend/fixtures/blob.rb
+++ b/spec/frontend/fixtures/blob.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :control
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
render_views
diff --git a/spec/frontend/fixtures/branches.rb b/spec/frontend/fixtures/branches.rb
index 828564977e0..b3bb4b8873a 100644
--- a/spec/frontend/fixtures/branches.rb
+++ b/spec/frontend/fixtures/branches.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Branches (JavaScript fixtures)' do
let_it_be(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
after(:all) do
remove_repository(project)
diff --git a/spec/frontend/fixtures/clusters.rb b/spec/frontend/fixtures/clusters.rb
index ea883555255..49596d98774 100644
--- a/spec/frontend/fixtures/clusters.rb
+++ b/spec/frontend/fixtures/clusters.rb
@@ -8,7 +8,7 @@ RSpec.describe Projects::ClustersController, '(JavaScript fixtures)', type: :con
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace) }
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
render_views
diff --git a/spec/frontend/fixtures/commit.rb b/spec/frontend/fixtures/commit.rb
index f9e0f604b52..815c140950d 100644
--- a/spec/frontend/fixtures/commit.rb
+++ b/spec/frontend/fixtures/commit.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Commit (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:commit) { project.commit("master") }
before do
diff --git a/spec/frontend/fixtures/freeze_period.rb b/spec/frontend/fixtures/freeze_period.rb
index d9573c8000d..dd16bd81b51 100644
--- a/spec/frontend/fixtures/freeze_period.rb
+++ b/spec/frontend/fixtures/freeze_period.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Freeze Periods (JavaScript fixtures)' do
include TimeZoneHelper
let_it_be(:project) { create(:project, :repository, path: 'freeze-periods-project') }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
after(:all) do
remove_repository(project)
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index 6519416cb9e..8bedb802242 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -37,17 +37,6 @@ RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', type: :contr
render_issue(create(:closed_issue, project: project))
end
- it 'issues/issue_list.html' do
- create(:issue, project: project)
-
- get :index, params: {
- namespace_id: project.namespace.to_param,
- project_id: project
- }
-
- expect(response).to be_successful
- end
-
private
def render_issue(issue)
diff --git a/spec/frontend/fixtures/jobs.rb b/spec/frontend/fixtures/jobs.rb
index 12584f38629..3cc87432655 100644
--- a/spec/frontend/fixtures/jobs.rb
+++ b/spec/frontend/fixtures/jobs.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::JobsController, '(JavaScript fixtures)', type: :control
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'builds-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id) }
let!(:build_with_artifacts) { create(:ci_build, :success, :artifacts, :trace_artifact, pipeline: pipeline, stage: 'test', artifacts_expire_at: Time.now + 18.months) }
let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline, stage: 'build') }
diff --git a/spec/frontend/fixtures/listbox.rb b/spec/frontend/fixtures/listbox.rb
new file mode 100644
index 00000000000..8f8489a2827
--- /dev/null
+++ b/spec/frontend/fixtures/listbox.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'initRedirectListboxBehavior', '(JavaScript fixtures)', type: :helper do
+ include JavaScriptFixturesHelpers
+ include ListboxHelper
+
+ let(:response) { @tag }
+
+ it 'listbox/redirect_listbox.html' do
+ items = [{
+ value: 'foo',
+ text: 'Foo',
+ href: '/foo',
+ arbitrary_key: 'foo xyz'
+ }, {
+ value: 'bar',
+ text: 'Bar',
+ href: '/bar',
+ arbitrary_key: 'bar xyz'
+ }, {
+ value: 'qux',
+ text: 'Qux',
+ href: '/qux',
+ arbitrary_key: 'qux xyz'
+ }]
+
+ @tag = helper.gl_redirect_listbox_tag(items, 'bar', class: %w[test-class-1 test-class-2], data: { right: true })
+ end
+end
diff --git a/spec/frontend/fixtures/merge_requests.rb b/spec/frontend/fixtures/merge_requests.rb
index 68ed2ca2359..1eb48c0ce2c 100644
--- a/spec/frontend/fixtures/merge_requests.rb
+++ b/spec/frontend/fixtures/merge_requests.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type:
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'merge-requests-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
# rubocop: disable Layout/TrailingWhitespace
let(:description) do
@@ -119,6 +119,17 @@ RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type:
end
end
+ it 'merge_requests/merge_request_list.html' do
+ create(:merge_request, source_project: project, target_project: project)
+
+ get :index, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project
+ }
+
+ expect(response).to be_successful
+ end
+
private
def render_discussions_json(merge_request)
diff --git a/spec/frontend/fixtures/merge_requests_diffs.rb b/spec/frontend/fixtures/merge_requests_diffs.rb
index e733764f248..7f0d650b710 100644
--- a/spec/frontend/fixtures/merge_requests_diffs.rb
+++ b/spec/frontend/fixtures/merge_requests_diffs.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)'
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'merge-requests-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project, description: '- [ ] Task List Item') }
let(:path) { "files/ruby/popen.rb" }
let(:position) do
diff --git a/spec/frontend/fixtures/pipeline_schedules.rb b/spec/frontend/fixtures/pipeline_schedules.rb
index 6389f59aa0a..e155d27920d 100644
--- a/spec/frontend/fixtures/pipeline_schedules.rb
+++ b/spec/frontend/fixtures/pipeline_schedules.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', t
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :public, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
let!(:pipeline_schedule_populated) { create(:ci_pipeline_schedule, project: project, owner: user) }
let!(:pipeline_schedule_variable1) { create(:ci_pipeline_schedule_variable, key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule_populated) }
diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb
index 3c8964d398a..fa7d61df3e8 100644
--- a/spec/frontend/fixtures/projects.rb
+++ b/spec/frontend/fixtures/projects.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
let(:project) { create(:project, namespace: namespace, path: 'builds-project', runners_token: runners_token, avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png')) }
let(:project_with_repo) { create(:project, :repository, description: 'Code and stuff', avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png')) }
let(:project_variable_populated) { create(:project, namespace: namespace, path: 'builds-project2', runners_token: runners_token) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
render_views
diff --git a/spec/frontend/fixtures/prometheus_service.rb b/spec/frontend/fixtures/prometheus_service.rb
index bbd938c66f6..aed73dc1096 100644
--- a/spec/frontend/fixtures/prometheus_service.rb
+++ b/spec/frontend/fixtures/prometheus_service.rb
@@ -8,7 +8,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!(:integration) { create(:prometheus_integration, project: project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
render_views
diff --git a/spec/frontend/fixtures/runner.rb b/spec/frontend/fixtures/runner.rb
index 36e6cf72750..cdb4c3fd8ba 100644
--- a/spec/frontend/fixtures/runner.rb
+++ b/spec/frontend/fixtures/runner.rb
@@ -11,11 +11,13 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
let_it_be(:admin) { create(:admin) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:project_2) { 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(:group_runner_2) { create(:ci_runner, :group, groups: [group], active: false, version: '2.0.0', revision: '456', description: 'Group runner 2', 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') }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project, project_2], active: false, version: '2.0.0', revision: '456', description: 'Project runner', ip_address: '127.0.0.1') }
+ let_it_be(:build) { create(:ci_build, runner: instance_runner) }
query_path = 'runner/graphql/'
fixtures_path = 'graphql/runner/'
@@ -78,6 +80,46 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
expect_graphql_errors_to_be_empty
end
+
+ it "#{fixtures_path}#{get_runner_query_name}.with_group.json" do
+ post_graphql(query, current_user: admin, variables: {
+ id: group_runner.to_global_id.to_s
+ })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+
+ describe GraphQL::Query, type: :request do
+ get_runner_projects_query_name = 'get_runner_projects.query.graphql'
+
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}#{get_runner_projects_query_name}")
+ end
+
+ it "#{fixtures_path}#{get_runner_projects_query_name}.json" do
+ post_graphql(query, current_user: admin, variables: {
+ id: project_runner.to_global_id.to_s
+ })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+
+ describe GraphQL::Query, type: :request do
+ get_runner_jobs_query_name = 'get_runner_jobs.query.graphql'
+
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}#{get_runner_jobs_query_name}")
+ end
+
+ it "#{fixtures_path}#{get_runner_jobs_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 a8293a080a9..f0bb8fb962f 100644
--- a/spec/frontend/fixtures/services.rb
+++ b/spec/frontend/fixtures/services.rb
@@ -8,7 +8,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_integration, project: project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
render_views
diff --git a/spec/frontend/fixtures/snippet.rb b/spec/frontend/fixtures/snippet.rb
index 397fb3e7124..f05ff3ee269 100644
--- a/spec/frontend/fixtures/snippet.rb
+++ b/spec/frontend/fixtures/snippet.rb
@@ -7,7 +7,7 @@ RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:snippet) { create(:personal_snippet, :public, title: 'snippet.md', content: '# snippet', file_name: 'snippet.md', author: user) }
render_views
diff --git a/spec/frontend/fixtures/tags.rb b/spec/frontend/fixtures/tags.rb
index 6cfa5f82efe..fdf85844ee2 100644
--- a/spec/frontend/fixtures/tags.rb
+++ b/spec/frontend/fixtures/tags.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Tags (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
let_it_be(:project) { create(:project, :repository, path: 'tags-project') }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
after(:all) do
remove_repository(project)
diff --git a/spec/frontend/fixtures/todos.rb b/spec/frontend/fixtures/todos.rb
index a0573b0b658..7dce09e8f49 100644
--- a/spec/frontend/fixtures/todos.rb
+++ b/spec/frontend/fixtures/todos.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Todos (JavaScript fixtures)' do
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'todos-project') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:issue_1) { create(:issue, title: 'issue_1', project: project) }
let!(:todo_1) { create(:todo, user: user, project: project, target: issue_1, created_at: 5.hours.ago) }
let(:issue_2) { create(:issue, title: 'issue_2', project: project) }
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index d5451ec2064..942e2c330fa 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -517,16 +517,12 @@ describe('Flash', () => {
`;
});
- it('removes global flash on click', (done) => {
+ it('removes global flash on click', () => {
addDismissFlashClickListener(el, false);
el.querySelector('.js-close-icon').click();
- setImmediate(() => {
- expect(document.querySelector('.flash')).toBeNull();
-
- done();
- });
+ expect(document.querySelector('.flash')).toBeNull();
});
});
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index a94cb3e2fcc..ba989bf53ab 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
@@ -97,7 +97,7 @@ describe('Frequent Items App Component', () => {
triggerDropdownOpen();
store.state[TEST_VUEX_MODULE].isLoadingItems = true;
- await wrapper.vm.$nextTick();
+ await nextTick();
const loading = findLoading();
@@ -119,7 +119,7 @@ describe('Frequent Items App Component', () => {
expect(findFrequentItems().length).toBe(1);
triggerDropdownOpen();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findFrequentItems().length).toBe(expectedResult.length);
expect(findFrequentItemsList().props()).toEqual({
@@ -135,7 +135,7 @@ describe('Frequent Items App Component', () => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects.data);
setSearch('gitlab');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLoading().exists()).toBe(true);
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
index 5a05265afdc..8220ea16342 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { trimText } from 'helpers/text_helper';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
@@ -8,8 +9,7 @@ import { createStore } from '~/frequent_items/store';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
import { mockProject } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('FrequentItemsListItemComponent', () => {
let wrapper;
@@ -40,7 +40,6 @@ describe('FrequentItemsListItemComponent', () => {
provide: {
vuexModule: 'frequentProjects',
},
- localVue,
});
};
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
index c015914c991..beaab1913d0 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
@@ -1,12 +1,12 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
import { createStore } from '~/frequent_items/store';
import { mockFrequentProjects } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('FrequentItemsListComponent', () => {
let wrapper;
@@ -22,7 +22,6 @@ describe('FrequentItemsListComponent', () => {
matcher: 'lab',
...props,
},
- localVue,
provide: {
vuexModule: 'frequentProjects',
},
@@ -45,7 +44,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
items: mockFrequentProjects,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isListEmpty).toBe(false);
});
@@ -64,7 +63,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
isFetchFailed: false,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.listEmptyMessage).toBe('Projects you visit often will appear here');
});
@@ -82,7 +81,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
isFetchFailed: false,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
});
@@ -90,25 +89,23 @@ describe('FrequentItemsListComponent', () => {
});
describe('template', () => {
- it('should render component element with list of projects', () => {
+ it('should render component element with list of projects', async () => {
createComponent();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.classes('frequent-items-list-container')).toBe(true);
- expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1);
- expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5);
- });
+ await nextTick();
+ expect(wrapper.classes('frequent-items-list-container')).toBe(true);
+ expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1);
+ expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5);
});
- it('should render component element with empty message', () => {
+ it('should render component element with empty message', async () => {
createComponent({
items: [],
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1);
- expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0);
- });
+ await nextTick();
+ expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1);
+ expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0);
});
});
});
diff --git a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
index c9b7e0f3d13..d0a4cf70f5f 100644
--- a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
@@ -1,12 +1,12 @@
import { GlSearchBoxByType } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue';
import { createStore } from '~/frequent_items/store';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('FrequentItemsSearchInputComponent', () => {
let wrapper;
@@ -18,7 +18,6 @@ describe('FrequentItemsSearchInputComponent', () => {
shallowMount(searchComponent, {
store,
propsData: { namespace },
- localVue,
provide: {
vuexModule: 'frequentProjects',
},
@@ -62,7 +61,7 @@ describe('FrequentItemsSearchInputComponent', () => {
findSearchBoxByType().vm.$emit('input', value);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'type_search_query', {
label: 'projects_dropdown_frequent_items_search_input',
diff --git a/spec/frontend/gl_form_spec.js b/spec/frontend/gl_form_spec.js
index 07487fbb60e..ab5627ce216 100644
--- a/spec/frontend/gl_form_spec.js
+++ b/spec/frontend/gl_form_spec.js
@@ -8,7 +8,7 @@ describe('GLForm', () => {
const testContext = {};
describe('when instantiated', () => {
- beforeEach((done) => {
+ beforeEach(() => {
window.gl = window.gl || {};
testContext.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
@@ -18,22 +18,11 @@ describe('GLForm', () => {
jest.spyOn($.prototype, 'css').mockImplementation(() => {});
testContext.glForm = new GLForm(testContext.form, false);
-
- setImmediate(() => {
- $.prototype.off.mockClear();
- $.prototype.on.mockClear();
- $.prototype.css.mockClear();
- done();
- });
});
describe('setupAutosize', () => {
- beforeEach((done) => {
+ beforeEach(() => {
testContext.glForm.setupAutosize();
-
- setImmediate(() => {
- done();
- });
});
it('should register an autosize event handler on the textarea', () => {
diff --git a/spec/frontend/google_cloud/components/app_spec.js b/spec/frontend/google_cloud/components/app_spec.js
index 92bc7596f7d..5ddc0ffa50f 100644
--- a/spec/frontend/google_cloud/components/app_spec.js
+++ b/spec/frontend/google_cloud/components/app_spec.js
@@ -24,8 +24,8 @@ const HOME_PROPS = {
serviceAccounts: [{}, {}],
createServiceAccountUrl: '#url-create-service-account',
emptyIllustrationUrl: '#url-empty-illustration',
- deploymentsCloudRunUrl: '#url-deployments-cloud-run',
- deploymentsCloudStorageUrl: '#deploymentsCloudStorageUrl',
+ enableCloudRunUrl: '#url-enable-cloud-run',
+ enableCloudStorageUrl: '#enableCloudStorageUrl',
};
describe('google_cloud App component', () => {
diff --git a/spec/frontend/google_cloud/components/deployments_service_table_spec.js b/spec/frontend/google_cloud/components/deployments_service_table_spec.js
index 76c3bfd00a8..882376547c4 100644
--- a/spec/frontend/google_cloud/components/deployments_service_table_spec.js
+++ b/spec/frontend/google_cloud/components/deployments_service_table_spec.js
@@ -12,8 +12,8 @@ describe('google_cloud DeploymentsServiceTable component', () => {
beforeEach(() => {
const propsData = {
- cloudRunUrl: '#url-deployments-cloud-run',
- cloudStorageUrl: '#url-deployments-cloud-storage',
+ cloudRunUrl: '#url-enable-cloud-run',
+ cloudStorageUrl: '#url-enable-cloud-storage',
};
wrapper = mount(DeploymentsServiceTable, { propsData });
});
@@ -29,12 +29,13 @@ describe('google_cloud DeploymentsServiceTable component', () => {
it('should contain configure cloud run button', () => {
const cloudRunButton = findCloudRunButton();
expect(cloudRunButton.exists()).toBe(true);
- expect(cloudRunButton.props().disabled).toBe(true);
+ expect(cloudRunButton.attributes('href')).toBe('#url-enable-cloud-run');
});
it('should contain configure cloud storage button', () => {
const cloudStorageButton = findCloudStorageButton();
expect(cloudStorageButton.exists()).toBe(true);
expect(cloudStorageButton.props().disabled).toBe(true);
+ expect(cloudStorageButton.attributes('href')).toBe('#url-enable-cloud-storage');
});
});
diff --git a/spec/frontend/google_cloud/components/home_spec.js b/spec/frontend/google_cloud/components/home_spec.js
index 3a009fc88ce..57cf831b19b 100644
--- a/spec/frontend/google_cloud/components/home_spec.js
+++ b/spec/frontend/google_cloud/components/home_spec.js
@@ -20,8 +20,8 @@ describe('google_cloud Home component', () => {
serviceAccounts: [{}, {}],
createServiceAccountUrl: '#url-create-service-account',
emptyIllustrationUrl: '#url-empty-illustration',
- deploymentsCloudRunUrl: '#url-deployments-cloud-run',
- deploymentsCloudStorageUrl: '#deploymentsCloudStorageUrl',
+ enableCloudRunUrl: '#url-enable-cloud-run',
+ enableCloudStorageUrl: '#enableCloudStorageUrl',
};
beforeEach(() => {
diff --git a/spec/frontend/google_cloud/components/service_accounts_form_spec.js b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
index 5394d0cdaef..7262e12c84d 100644
--- a/spec/frontend/google_cloud/components/service_accounts_form_spec.js
+++ b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox } from '@gitlab/ui';
import ServiceAccountsForm from '~/google_cloud/components/service_accounts_form.vue';
describe('ServiceAccountsForm component', () => {
@@ -9,11 +9,12 @@ describe('ServiceAccountsForm component', () => {
const findAllFormGroups = () => wrapper.findAllComponents(GlFormGroup);
const findAllFormSelects = () => wrapper.findAllComponents(GlFormSelect);
const findAllButtons = () => wrapper.findAllComponents(GlButton);
+ const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const propsData = { gcpProjects: [], environments: [], cancelPath: '#cancel-url' };
beforeEach(() => {
- wrapper = shallowMount(ServiceAccountsForm, { propsData });
+ wrapper = shallowMount(ServiceAccountsForm, { propsData, stubs: { GlFormCheckbox } });
});
afterEach(() => {
@@ -35,8 +36,8 @@ describe('ServiceAccountsForm component', () => {
});
it('contains Environments form group', () => {
- const formGorup = findAllFormGroups().at(1);
- expect(formGorup.exists()).toBe(true);
+ const formGroup = findAllFormGroups().at(1);
+ expect(formGroup.exists()).toBe(true);
});
it('contains Environments dropdown', () => {
@@ -56,4 +57,14 @@ describe('ServiceAccountsForm component', () => {
expect(button.text()).toBe(ServiceAccountsForm.i18n.cancelLabel);
expect(button.attributes('href')).toBe('#cancel-url');
});
+
+ it('contains Confirmation checkbox', () => {
+ const checkbox = findCheckbox();
+ expect(checkbox.text()).toBe(ServiceAccountsForm.i18n.checkboxLabel);
+ });
+
+ it('checkbox must be required', () => {
+ const checkbox = findCheckbox();
+ expect(checkbox.attributes('required')).toBe('true');
+ });
});
diff --git a/spec/frontend/google_cloud/components/service_accounts_list_spec.js b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
index cdb3f74051c..f7051c8a53d 100644
--- a/spec/frontend/google_cloud/components/service_accounts_list_spec.js
+++ b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import ServiceAccountsList from '~/google_cloud/components/service_accounts_list.vue';
describe('ServiceAccounts component', () => {
@@ -28,7 +28,7 @@ describe('ServiceAccounts component', () => {
it('shows the link to create new service accounts', () => {
const button = findButtonInEmptyState();
expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Create service account');
+ expect(button.text()).toBe(ServiceAccountsList.i18n.createServiceAccount);
expect(button.attributes('href')).toBe('#create-url');
});
});
@@ -41,6 +41,7 @@ describe('ServiceAccounts component', () => {
const findTable = () => wrapper.findComponent(GlTable);
const findRows = () => findTable().findAll('tr');
const findButton = () => wrapper.findComponent(GlButton);
+ const findSecretManagerTip = () => wrapper.findComponent(GlAlert);
beforeEach(() => {
const propsData = {
@@ -52,13 +53,11 @@ describe('ServiceAccounts component', () => {
});
it('shows the title', () => {
- expect(findTitle().text()).toBe('Service Accounts');
+ expect(findTitle().text()).toBe(ServiceAccountsList.i18n.serviceAccountsTitle);
});
it('shows the description', () => {
- expect(findDescription().text()).toBe(
- 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
- );
+ expect(findDescription().text()).toBe(ServiceAccountsList.i18n.serviceAccountsDescription);
});
it('shows the table', () => {
@@ -72,8 +71,14 @@ describe('ServiceAccounts component', () => {
it('shows the link to create new service accounts', () => {
const button = findButton();
expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Create service account');
+ expect(button.text()).toBe(ServiceAccountsList.i18n.createServiceAccount);
expect(button.attributes('href')).toBe('#create-url');
});
+
+ it('must contain secret managers tip', () => {
+ const tip = findSecretManagerTip();
+ const expectedText = ServiceAccountsList.i18n.secretManagersDescription.substr(0, 48);
+ expect(tip.text()).toContain(expectedText);
+ });
});
});
diff --git a/spec/frontend/google_tag_manager/index_spec.js b/spec/frontend/google_tag_manager/index_spec.js
index ff38de28da6..9112b0e17e7 100644
--- a/spec/frontend/google_tag_manager/index_spec.js
+++ b/spec/frontend/google_tag_manager/index_spec.js
@@ -1,4 +1,5 @@
import { merge } from 'lodash';
+import { v4 as uuidv4 } from 'uuid';
import {
trackFreeTrialAccountSubmissions,
trackNewRegistrations,
@@ -8,11 +9,14 @@ import {
trackSaasTrialProject,
trackSaasTrialProjectImport,
trackSaasTrialGetStarted,
+ trackCheckout,
+ trackTransaction,
} from '~/google_tag_manager';
import { setHTMLFixture } from 'helpers/fixtures';
import { logError } from '~/lib/logger';
jest.mock('~/lib/logger');
+jest.mock('uuid');
describe('~/google_tag_manager/index', () => {
let spy;
@@ -209,6 +213,180 @@ describe('~/google_tag_manager/index', () => {
expect(spy).toHaveBeenCalledWith({ event: 'saasTrialSubmit' });
expect(logError).not.toHaveBeenCalled();
});
+
+ describe('when trackCheckout is invoked', () => {
+ it('with selectedPlan: 2c92a00d76f0d5060176f2fb0a5029ff', () => {
+ expect(spy).not.toHaveBeenCalled();
+
+ trackCheckout('2c92a00d76f0d5060176f2fb0a5029ff', 1);
+
+ expect(spy.mock.calls.flatMap((x) => x)).toEqual([
+ { ecommerce: null },
+ {
+ event: 'EECCheckout',
+ ecommerce: {
+ currencyCode: 'USD',
+ checkout: {
+ actionField: { step: 1 },
+ products: [
+ {
+ brand: 'GitLab',
+ category: 'DevOps',
+ id: '0002',
+ name: 'Premium',
+ price: '228',
+ quantity: 1,
+ variant: 'SaaS',
+ },
+ ],
+ },
+ },
+ },
+ ]);
+ });
+
+ it('with selectedPlan: 2c92a0ff76f0d5250176f2f8c86f305a', () => {
+ expect(spy).not.toHaveBeenCalled();
+
+ trackCheckout('2c92a0ff76f0d5250176f2f8c86f305a', 1);
+
+ expect(spy).toHaveBeenCalledTimes(2);
+ expect(spy).toHaveBeenCalledWith({ ecommerce: null });
+ expect(spy).toHaveBeenCalledWith({
+ event: 'EECCheckout',
+ ecommerce: {
+ currencyCode: 'USD',
+ checkout: {
+ actionField: { step: 1 },
+ products: [
+ {
+ brand: 'GitLab',
+ category: 'DevOps',
+ id: '0001',
+ name: 'Ultimate',
+ price: '1188',
+ quantity: 1,
+ variant: 'SaaS',
+ },
+ ],
+ },
+ },
+ });
+ });
+
+ it('with selectedPlan: Something else', () => {
+ expect(spy).not.toHaveBeenCalled();
+
+ trackCheckout('Something else', 1);
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+
+ it('with a different number of users', () => {
+ expect(spy).not.toHaveBeenCalled();
+
+ trackCheckout('2c92a0ff76f0d5250176f2f8c86f305a', 5);
+
+ expect(spy).toHaveBeenCalledTimes(2);
+ expect(spy).toHaveBeenCalledWith({ ecommerce: null });
+ expect(spy).toHaveBeenCalledWith({
+ event: 'EECCheckout',
+ ecommerce: {
+ currencyCode: 'USD',
+ checkout: {
+ actionField: { step: 1 },
+ products: [
+ {
+ brand: 'GitLab',
+ category: 'DevOps',
+ id: '0001',
+ name: 'Ultimate',
+ price: '1188',
+ quantity: 5,
+ variant: 'SaaS',
+ },
+ ],
+ },
+ },
+ });
+ });
+ });
+
+ describe('when trackTransactions is invoked', () => {
+ describe.each([
+ {
+ selectedPlan: '2c92a00d76f0d5060176f2fb0a5029ff',
+ revenue: 228,
+ name: 'Premium',
+ id: '0002',
+ },
+ {
+ selectedPlan: '2c92a0ff76f0d5250176f2f8c86f305a',
+ revenue: 1188,
+ name: 'Ultimate',
+ id: '0001',
+ },
+ ])('with %o', (planObject) => {
+ it('invokes pushes a new event that references the selected plan', () => {
+ const { selectedPlan, revenue, name, id } = planObject;
+
+ expect(spy).not.toHaveBeenCalled();
+ uuidv4.mockImplementationOnce(() => '123');
+
+ const transactionDetails = {
+ paymentOption: 'visa',
+ revenue,
+ tax: 10,
+ selectedPlan,
+ quantity: 1,
+ };
+
+ trackTransaction(transactionDetails);
+
+ expect(spy.mock.calls.flatMap((x) => x)).toEqual([
+ { ecommerce: null },
+ {
+ event: 'EECtransactionSuccess',
+ ecommerce: {
+ currencyCode: 'USD',
+ purchase: {
+ actionField: {
+ id: '123',
+ affiliation: 'GitLab',
+ option: 'visa',
+ revenue: revenue.toString(),
+ tax: '10',
+ },
+ products: [
+ {
+ brand: 'GitLab',
+ category: 'DevOps',
+ id,
+ name,
+ price: revenue.toString(),
+ quantity: 1,
+ variant: 'SaaS',
+ },
+ ],
+ },
+ },
+ },
+ ]);
+ });
+ });
+ });
+
+ describe('when trackTransaction is invoked', () => {
+ describe('with an invalid plan object', () => {
+ it('does not get called', () => {
+ expect(spy).not.toHaveBeenCalled();
+
+ trackTransaction({ selectedPlan: 'notAplan' });
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+ });
+ });
});
describe.each([
diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
index d5338430054..d2111194097 100644
--- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js
+++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import createFlash from '~/flash';
@@ -93,29 +94,28 @@ describe('grafana integration component', () => {
},
];
- it('submits form on click', () => {
+ it('submits form on click', async () => {
axios.patch.mockResolvedValue();
findSubmitButton(wrapper).trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
- return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled());
+ await nextTick();
+ expect(refreshCurrentPage).toHaveBeenCalled();
});
- it('creates flash banner on error', () => {
+ it('creates flash banner on error', async () => {
const message = 'mockErrorMessage';
axios.patch.mockRejectedValue({ response: { data: { message } } });
findSubmitButton().trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
- return wrapper.vm
- .$nextTick()
- .then(jest.runAllTicks)
- .then(() =>
- expect(createFlash).toHaveBeenCalledWith({
- message: `There was an error saving your changes. ${message}`,
- }),
- );
+
+ await nextTick();
+ await jest.runAllTicks();
+ expect(createFlash).toHaveBeenCalledWith({
+ message: `There was an error saving your changes. ${message}`,
+ });
});
});
});
diff --git a/spec/frontend/group_settings/components/shared_runners_form_spec.js b/spec/frontend/group_settings/components/shared_runners_form_spec.js
index 617d91178e4..26e9cd39cfd 100644
--- a/spec/frontend/group_settings/components/shared_runners_form_spec.js
+++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue';
import axios from '~/lib/utils/axios_utils';
@@ -76,7 +77,7 @@ describe('group_settings/components/shared_runners_form', () => {
findEnabledToggle().vm.$emit('change', true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(isLoadingIconVisible()).toBe(true);
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index bc8c6460cf4..848e50c86ba 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -1,7 +1,7 @@
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import appComponent from '~/groups/components/app.vue';
@@ -58,7 +58,7 @@ describe('AppComponent', () => {
wrapper = null;
});
- beforeEach(() => {
+ beforeEach(async () => {
mock = new AxiosMockAdapter(axios);
mock.onGet('/dashboard/groups.json').reply(200, mockGroups);
Vue.component('GroupFolder', groupFolderComponent);
@@ -66,7 +66,7 @@ describe('AppComponent', () => {
createShallowComponent();
getGroupsSpy = jest.spyOn(vm.service, 'getGroups');
- return vm.$nextTick();
+ await nextTick();
});
describe('computed', () => {
@@ -280,6 +280,7 @@ describe('AppComponent', () => {
expect(vm.targetParentGroup).toBe(null);
vm.showLeaveGroupModal(group, mockParentGroupItem);
+ expect(vm.isModalVisible).toBe(true);
expect(vm.targetGroup).not.toBe(null);
expect(vm.targetParentGroup).not.toBe(null);
});
@@ -290,6 +291,7 @@ describe('AppComponent', () => {
expect(vm.groupLeaveConfirmationMessage).toBe('');
vm.showLeaveGroupModal(group, mockParentGroupItem);
+ expect(vm.isModalVisible).toBe(true);
expect(vm.groupLeaveConfirmationMessage).toBe(
`Are you sure you want to leave the "${group.fullName}" group?`,
);
@@ -397,66 +399,60 @@ describe('AppComponent', () => {
});
describe('created', () => {
- it('should bind event listeners on eventHub', () => {
+ it('should bind event listeners on eventHub', async () => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
createShallowComponent();
- return vm.$nextTick().then(() => {
- expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function));
- });
+ await nextTick();
+ expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function));
});
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', () => {
+ it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', async () => {
createShallowComponent();
- return vm.$nextTick().then(() => {
- expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search');
- });
+ await nextTick();
+ expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search');
});
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', () => {
+ it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', async () => {
createShallowComponent(true);
- return vm.$nextTick().then(() => {
- expect(vm.searchEmptyMessage).toBe('No groups matched your search');
- });
+ await nextTick();
+ expect(vm.searchEmptyMessage).toBe('No groups matched your search');
});
});
describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', () => {
+ it('should unbind event listeners on eventHub', async () => {
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
createShallowComponent();
wrapper.destroy();
- return vm.$nextTick().then(() => {
- expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', expect.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function));
- });
+ await nextTick();
+ expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', expect.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function));
});
});
describe('template', () => {
- it('should render loading icon', () => {
+ it('should render loading icon', async () => {
vm.isLoading = true;
- return vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('should render groups tree', () => {
+ it('should render groups tree', async () => {
vm.store.state.groups = [mockParentGroupItem];
vm.isLoading = false;
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
});
it('renders modal confirmation dialog', () => {
diff --git a/spec/frontend/groups/components/group_folder_spec.js b/spec/frontend/groups/components/group_folder_spec.js
index 1d8e10479b6..98b7c2dd6c6 100644
--- a/spec/frontend/groups/components/group_folder_spec.js
+++ b/spec/frontend/groups/components/group_folder_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue';
@@ -18,13 +18,13 @@ const createComponent = (groups = mockGroups, parentGroup = mockParentGroupItem)
describe('GroupFolderComponent', () => {
let vm;
- beforeEach(() => {
+ beforeEach(async () => {
Vue.component('GroupItem', groupItemComponent);
vm = createComponent();
vm.$mount();
- return Vue.nextTick();
+ await nextTick();
});
afterEach(() => {
diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js
index 0ec1ef5a49e..590b4fb3d57 100644
--- a/spec/frontend/groups/components/groups_spec.js
+++ b/spec/frontend/groups/components/groups_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import groupFolderComponent from '~/groups/components/group_folder.vue';
@@ -21,13 +21,13 @@ const createComponent = (searchEmpty = false) => {
describe('GroupsComponent', () => {
let vm;
- beforeEach(() => {
+ beforeEach(async () => {
Vue.component('GroupFolder', groupFolderComponent);
Vue.component('GroupItem', groupItemComponent);
vm = createComponent();
- return vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -52,20 +52,18 @@ describe('GroupsComponent', () => {
});
describe('template', () => {
- it('should render component template correctly', () => {
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
- expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
- expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
- expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
- });
+ it('should render component template correctly', async () => {
+ await nextTick();
+ expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
+ expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
+ expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
+ expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
});
- it('should render empty search message when `searchEmpty` is `true`', () => {
+ it('should render empty search message when `searchEmpty` is `true`', async () => {
vm.searchEmpty = true;
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined();
});
});
});
diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js
index c81edad499c..1924f400861 100644
--- a/spec/frontend/groups/components/invite_members_banner_spec.js
+++ b/spec/frontend/groups/components/invite_members_banner_spec.js
@@ -1,6 +1,7 @@
import { GlBanner } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
import eventHub from '~/invite_members/event_hub';
@@ -75,7 +76,6 @@ describe('InviteMembersBanner', () => {
it('calls openModal through the eventHub', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('openModal', {
- inviteeType: 'members',
source: 'invite_members_banner',
});
});
@@ -140,7 +140,7 @@ describe('InviteMembersBanner', () => {
expect(wrapper.find(GlBanner).exists()).toBe(true);
wrapper.find(GlBanner).vm.$emit('close');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlBanner).exists()).toBe(false);
});
});
diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js
index ffbdf9b1aa6..3ceb038dd3c 100644
--- a/spec/frontend/groups/components/item_actions_spec.js
+++ b/spec/frontend/groups/components/item_actions_spec.js
@@ -1,4 +1,4 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ItemActions from '~/groups/components/item_actions.vue';
import eventHub from '~/groups/event_hub';
import { mockParentGroupItem, mockChildren } from '../mock_data';
@@ -13,7 +13,7 @@ describe('ItemActions', () => {
};
const createComponent = (props = {}) => {
- wrapper = shallowMount(ItemActions, {
+ wrapper = shallowMountExtended(ItemActions, {
propsData: { ...defaultProps, ...props },
});
};
@@ -23,8 +23,10 @@ describe('ItemActions', () => {
wrapper = null;
});
- const findEditGroupBtn = () => wrapper.find('[data-testid="edit-group-btn"]');
- const findLeaveGroupBtn = () => wrapper.find('[data-testid="leave-group-btn"]');
+ const findEditGroupBtn = () => wrapper.findByTestId(`edit-group-${mockParentGroupItem.id}-btn`);
+ const findLeaveGroupBtn = () => wrapper.findByTestId(`leave-group-${mockParentGroupItem.id}-btn`);
+ const findRemoveGroupBtn = () =>
+ wrapper.findByTestId(`remove-group-${mockParentGroupItem.id}-btn`);
describe('template', () => {
let group;
@@ -34,6 +36,7 @@ describe('ItemActions', () => {
...mockParentGroupItem,
canEdit: true,
canLeave: true,
+ canRemove: true,
};
createComponent({ group });
});
@@ -41,21 +44,21 @@ describe('ItemActions', () => {
it('renders component template correctly', () => {
createComponent();
- expect(wrapper.classes()).toContain('controls');
+ expect(wrapper.classes()).toContain('gl-display-flex', 'gl-justify-content-end', 'gl-ml-5');
});
- it('renders "Edit group" button with correct attribute values', () => {
+ it('renders "Edit" group button with correct attribute values', () => {
const button = findEditGroupBtn();
expect(button.exists()).toBe(true);
- expect(button.props('icon')).toBe('pencil');
- expect(button.attributes('aria-label')).toBe('Edit group');
+ expect(button.attributes('href')).toBe(mockParentGroupItem.editPath);
});
- it('renders "Leave this group" button with correct attribute values', () => {
- const button = findLeaveGroupBtn();
+ it('renders "Delete" group button with correct attribute values', () => {
+ const button = findRemoveGroupBtn();
expect(button.exists()).toBe(true);
- expect(button.props('icon')).toBe('leave');
- expect(button.attributes('aria-label')).toBe('Leave this group');
+ expect(button.attributes('href')).toBe(
+ `${mockParentGroupItem.editPath}#js-remove-group-form`,
+ );
});
it('emits `showLeaveGroupModal` event in the event hub', () => {
@@ -103,4 +106,15 @@ describe('ItemActions', () => {
expect(findEditGroupBtn().exists()).toBe(false);
});
+
+ it('does not render delete button if group can not be edited', () => {
+ createComponent({
+ group: {
+ ...mockParentGroupItem,
+ canRemove: false,
+ },
+ });
+
+ expect(findRemoveGroupBtn().exists()).toBe(false);
+ });
});
diff --git a/spec/frontend/groups/components/transfer_group_form_spec.js b/spec/frontend/groups/components/transfer_group_form_spec.js
new file mode 100644
index 00000000000..6dc760f4f7c
--- /dev/null
+++ b/spec/frontend/groups/components/transfer_group_form_spec.js
@@ -0,0 +1,131 @@
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import Component from '~/groups/components/transfer_group_form.vue';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+
+describe('Transfer group form', () => {
+ let wrapper;
+
+ const confirmButtonText = 'confirm';
+ const confirmationPhrase = 'confirmation-phrase';
+ const paidGroupHelpLink = 'some/fake/link';
+ const groupNamespaces = [
+ {
+ id: 1,
+ humanName: 'Group 1',
+ },
+ {
+ id: 2,
+ humanName: 'Group 2',
+ },
+ ];
+
+ const defaultProps = {
+ groupNamespaces,
+ paidGroupHelpLink,
+ isPaidGroup: false,
+ confirmationPhrase,
+ confirmButtonText,
+ };
+
+ const createComponent = (propsData = {}) =>
+ shallowMountExtended(Component, {
+ propsData: {
+ ...defaultProps,
+ ...propsData,
+ },
+ stubs: { GlSprintf },
+ });
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger);
+ const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect);
+ const findHiddenInput = () => wrapper.find('[name="new_parent_group_id"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('renders the namespace select component', () => {
+ expect(findNamespaceSelect().exists()).toBe(true);
+ });
+
+ it('sets the namespace select properties', () => {
+ expect(findNamespaceSelect().props()).toMatchObject({
+ defaultText: 'Select parent group',
+ fullWidth: false,
+ includeHeaders: false,
+ emptyNamespaceTitle: 'No parent group',
+ includeEmptyNamespace: true,
+ groupNamespaces,
+ });
+ });
+
+ it('renders the hidden input field', () => {
+ expect(findHiddenInput().exists()).toBe(true);
+ expect(findHiddenInput().attributes('value')).toBeUndefined();
+ });
+
+ it('does not render the alert message', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('renders the confirm danger component', () => {
+ expect(findConfirmDanger().exists()).toBe(true);
+ });
+
+ it('sets the confirm danger properties', () => {
+ expect(findConfirmDanger().props()).toMatchObject({
+ buttonClass: 'qa-transfer-button',
+ disabled: true,
+ buttonText: confirmButtonText,
+ phrase: confirmationPhrase,
+ });
+ });
+ });
+
+ describe('with a selected project', () => {
+ const [firstGroup] = groupNamespaces;
+ beforeEach(() => {
+ wrapper = createComponent();
+ findNamespaceSelect().vm.$emit('select', firstGroup);
+ });
+
+ it('sets the confirm danger disabled property to false', () => {
+ expect(findConfirmDanger().props()).toMatchObject({ disabled: false });
+ });
+
+ it('sets the hidden input field', () => {
+ expect(findHiddenInput().exists()).toBe(true);
+ expect(parseInt(findHiddenInput().attributes('value'), 10)).toBe(firstGroup.id);
+ });
+
+ it('emits "confirm" event when the danger modal is confirmed', () => {
+ expect(wrapper.emitted('confirm')).toBeUndefined();
+
+ findConfirmDanger().vm.$emit('confirm');
+
+ expect(wrapper.emitted('confirm')).toHaveLength(1);
+ });
+ });
+
+ describe('isPaidGroup = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ isPaidGroup: true });
+ });
+
+ it('disables the transfer button', () => {
+ expect(findConfirmDanger().props()).toMatchObject({ disabled: true });
+ });
+
+ it('hides the namespace selector button', () => {
+ expect(findNamespaceSelect().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/groups/landing_spec.js b/spec/frontend/groups/landing_spec.js
index f90f541eb96..d60adea202b 100644
--- a/spec/frontend/groups/landing_spec.js
+++ b/spec/frontend/groups/landing_spec.js
@@ -159,7 +159,10 @@ describe('Landing', () => {
});
it('should call Cookies.set', () => {
- expect(Cookies.set).toHaveBeenCalledWith(test.cookieName, 'true', { expires: 365 });
+ expect(Cookies.set).toHaveBeenCalledWith(test.cookieName, 'true', {
+ expires: 365,
+ secure: false,
+ });
});
});
diff --git a/spec/frontend/groups/transfer_edit_spec.js b/spec/frontend/groups/transfer_edit_spec.js
deleted file mode 100644
index bc070920d02..00000000000
--- a/spec/frontend/groups/transfer_edit_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import $ from 'jquery';
-
-import { loadHTMLFixture } from 'helpers/fixtures';
-import setupTransferEdit from '~/groups/transfer_edit';
-
-describe('setupTransferEdit', () => {
- const formSelector = '.js-group-transfer-form';
- const targetSelector = '#new_parent_group_id';
-
- beforeEach(() => {
- loadHTMLFixture('groups/edit.html');
- setupTransferEdit(formSelector, targetSelector);
- });
-
- it('disables submit button on load', () => {
- expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
- });
-
- it('enables submit button when selection changes to non-empty value', () => {
- const lastValue = $(formSelector).find(targetSelector).find('.dropdown-content li').last();
- $(formSelector).find(targetSelector).val(lastValue).trigger('change');
-
- expect($(formSelector).find(':submit').prop('disabled')).toBeFalsy();
- });
-
- it('disables submit button when selection changes to empty value', () => {
- $(formSelector).find(targetSelector).val('').trigger('change');
-
- expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
- });
-});
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
index 3200c6614f1..dcbeeeffb2d 100644
--- a/spec/frontend/header_search/components/app_spec.js
+++ b/spec/frontend/header_search/components/app_spec.js
@@ -1,5 +1,5 @@
import { GlSearchBoxByType } from '@gitlab/ui';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import HeaderSearchApp from '~/header_search/components/app.vue';
@@ -202,7 +202,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('focus');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
});
@@ -211,7 +211,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
});
@@ -265,7 +265,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(true);
findDropdownKeyboardNavigation().vm.$emit('tab');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(false);
});
@@ -284,7 +284,7 @@ describe('HeaderSearchApp', () => {
it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, async () => {
findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.currentFocusedOption).toBe(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX]);
});
});
@@ -299,7 +299,7 @@ describe('HeaderSearchApp', () => {
it('onKey-enter submits a search', async () => {
findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY);
});
@@ -316,7 +316,7 @@ describe('HeaderSearchApp', () => {
it('onKey-enter clicks the selected dropdown item rather than submitting a search', async () => {
findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
- await wrapper.vm.$nextTick();
+ await nextTick();
findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
expect(visitUrl).toHaveBeenCalledWith(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX].url);
});
diff --git a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
index bec0cbc8a5c..502f10ff771 100644
--- a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
@@ -1,6 +1,6 @@
import { GlDropdownItem, GlLoadingIcon, GlAvatar } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
import {
@@ -143,7 +143,7 @@ describe('HeaderSearchAutocompleteItems', () => {
wrapper.setProps({ currentFocusedOption: MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0] });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(scrollSpy).toHaveBeenCalledWith(false);
scrollSpy.mockRestore();
diff --git a/spec/frontend/ide/components/activity_bar_spec.js b/spec/frontend/ide/components/activity_bar_spec.js
index 657817eb3d8..39fe2c7e723 100644
--- a/spec/frontend/ide/components/activity_bar_spec.js
+++ b/spec/frontend/ide/components/activity_bar_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import ActivityBar from '~/ide/components/activity_bar.vue';
import { leftSidebarViews } from '~/ide/constants';
@@ -61,14 +61,11 @@ describe('IDE activity bar', () => {
expect(vm.$el.querySelector('.js-ide-edit-mode').classList).toContain('active');
});
- it('sets commit item active', (done) => {
+ it('sets commit item active', async () => {
vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-ide-commit-mode').classList).toContain('active');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.js-ide-commit-mode').classList).toContain('active');
});
});
diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js
index 0efa7af2c6c..b6e3274153a 100644
--- a/spec/frontend/ide/components/branches/search_list_spec.js
+++ b/spec/frontend/ide/components/branches/search_list_spec.js
@@ -1,13 +1,13 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Item from '~/ide/components/branches/item.vue';
import List from '~/ide/components/branches/search_list.vue';
import { __ } from '~/locale';
import { branches } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE branches search list', () => {
let wrapper;
@@ -31,7 +31,6 @@ describe('IDE branches search list', () => {
});
wrapper = shallowMount(List, {
- localVue,
store: fakeStore,
});
};
@@ -51,13 +50,12 @@ describe('IDE branches search list', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('renders branches not found when search is not empty and branches list is empty', () => {
+ it('renders branches not found when search is not empty and branches list is empty', async () => {
createComponent({ branches: [] });
wrapper.find('input[type="search"]').setValue('something');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.text()).toContain(__('No branches found'));
- });
+ await nextTick();
+ expect(wrapper.text()).toContain(__('No branches found'));
});
describe('with branches', () => {
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
index ed9d11246ae..c9425f6c9cd 100644
--- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData, branches } from 'jest/ide/mock_data';
import commitActions from '~/ide/components/commit_sidebar/actions.vue';
@@ -71,15 +71,12 @@ describe('IDE commit sidebar actions', () => {
expect(findText()).toContain('Commit to main branch');
});
- it('hides merge request option when project merge requests are disabled', (done) => {
+ it('hides merge request option when project merge requests are disabled', async () => {
createComponent({ hasMR: false });
- vm.$nextTick(() => {
- expect(findRadios().length).toBe(2);
- expect(findText()).not.toContain('Create a new branch and merge request');
-
- done();
- });
+ await nextTick();
+ expect(findRadios().length).toBe(2);
+ expect(findText()).not.toContain('Create a new branch and merge request');
});
describe('currentBranchText', () => {
@@ -105,22 +102,18 @@ describe('IDE commit sidebar actions', () => {
expect(vm.$store.dispatch).not.toHaveBeenCalled();
});
- it('calls again after staged changes', (done) => {
+ it('calls again after staged changes', async () => {
createComponent({ currentBranchId: null });
vm.$store.state.currentBranchId = 'main';
vm.$store.state.changedFiles.push({});
vm.$store.state.stagedFiles.push({});
- vm.$nextTick()
- .then(() => {
- expect(vm.$store.dispatch).toHaveBeenCalledWith(
- ACTION_UPDATE_COMMIT_ACTION,
- expect.anything(),
- );
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$store.dispatch).toHaveBeenCalledWith(
+ ACTION_UPDATE_COMMIT_ACTION,
+ expect.anything(),
+ );
});
it.each`
diff --git a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
index 50635ffe894..6e4c66cb780 100644
--- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
@@ -1,11 +1,11 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import EditorHeader from '~/ide/components/commit_sidebar/editor_header.vue';
import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_FILE_PATH = 'test/file/path';
@@ -16,7 +16,6 @@ describe('IDE commit editor header', () => {
const createComponent = (fileProps = {}) => {
wrapper = mount(EditorHeader, {
store,
- localVue,
propsData: {
activeFile: {
...file(TEST_FILE_PATH),
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index 83d1bbb842e..d3b2923ac6c 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -1,6 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
@@ -56,7 +56,6 @@ describe('IDE commit form', () => {
disabled: findCommitButton().props('disabled'),
tooltip: getBinding(findCommitButtonTooltip().element, 'gl-tooltip').value.title,
});
- const clickCommitButton = () => findCommitButton().vm.$emit('click');
const findForm = () => wrapper.find('form');
const submitForm = () => findForm().trigger('submit');
const findCommitMessageInput = () => wrapper.find(CommitMessageField);
@@ -98,7 +97,7 @@ describe('IDE commit form', () => {
it(`at view=${viewFn.name}, ${buttonFn.name} has disabled=${disabled} tooltip=${tooltip}`, async () => {
viewFn();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(buttonFn()).toEqual({
disabled,
@@ -116,7 +115,7 @@ describe('IDE commit form', () => {
goToEditView();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders commit button in compact mode', () => {
@@ -135,7 +134,7 @@ describe('IDE commit form', () => {
it('when begin commit button is clicked, shows form', async () => {
findBeginCommitButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(true);
});
@@ -143,7 +142,7 @@ describe('IDE commit form', () => {
it('when begin commit button is clicked, sets activity view', async () => {
findBeginCommitButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name);
});
@@ -153,14 +152,14 @@ describe('IDE commit form', () => {
setLastCommitMessage('test');
goToEditView();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(true);
// Now test that it collapses when lastCommitMsg is cleared
setLastCommitMessage('');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(false);
});
@@ -177,7 +176,7 @@ describe('IDE commit form', () => {
goToCommitView();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -188,12 +187,12 @@ describe('IDE commit form', () => {
expect(findForm().exists()).toBe(false);
store.state.stagedFiles = [];
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(false);
store.state.stagedFiles.push('test');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(false);
});
@@ -208,7 +207,7 @@ describe('IDE commit form', () => {
goToCommitView();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows form', () => {
@@ -222,7 +221,7 @@ describe('IDE commit form', () => {
describe('when no changed files', () => {
beforeEach(async () => {
store.state.stagedFiles = [];
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('hides form', () => {
@@ -231,7 +230,7 @@ describe('IDE commit form', () => {
it('expands again when staged files are added', async () => {
store.state.stagedFiles.push('test');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForm().exists()).toBe(true);
});
@@ -240,7 +239,7 @@ describe('IDE commit form', () => {
it('updates commitMessage in store on input', async () => {
setCommitMessageInput('testing commit message');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(store.state.commit.commitMessage).toBe('testing commit message');
});
@@ -253,14 +252,14 @@ describe('IDE commit form', () => {
it('resets commitMessage when clicking discard button', async () => {
setCommitMessageInput('testing commit message');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCommitMessageInput().props('text')).toBe('testing commit message');
// Test that commitMessage is cleared on click
findDiscardDraftButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCommitMessageInput().props('text')).toBe('');
});
@@ -274,24 +273,24 @@ describe('IDE commit form', () => {
goToCommitView();
- await wrapper.vm.$nextTick();
+ await nextTick();
setCommitMessageInput('testing commit message');
- await wrapper.vm.$nextTick();
+ await nextTick();
jest.spyOn(store, 'dispatch').mockResolvedValue();
});
- it.each([clickCommitButton, submitForm])('when %p, commits changes', (fn) => {
- fn();
+ it('when submitting form, commits changes', () => {
+ submitForm();
expect(store.dispatch).toHaveBeenCalledWith('commit/commitChanges', undefined);
});
it('when cannot push code, submitting does nothing', async () => {
store.state.projects.abcproject.userPermissions.pushCode = false;
- await wrapper.vm.$nextTick();
+ await nextTick();
submitForm();
@@ -309,7 +308,7 @@ describe('IDE commit form', () => {
const error = createError();
store.state.commit.commitError = error;
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(modal.vm.show).toHaveBeenCalled();
expect(modal.props()).toMatchObject({
@@ -342,7 +341,7 @@ describe('IDE commit form', () => {
async ({ commitError, expectedActions }) => {
store.state.commit.commitError = commitError('test message');
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.find(GlModal).vm.$emit('ok');
diff --git a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
index b91ee88e0d6..dea920ecb5e 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
@@ -1,5 +1,6 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import listItem from '~/ide/components/commit_sidebar/list_item.vue';
import { createRouter } from '~/ide/ide_router';
@@ -41,54 +42,42 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(findPathText()).toContain(f.path);
});
- it('correctly renders renamed entries', (done) => {
+ it('correctly renders renamed entries', async () => {
Vue.set(vm.file, 'prevName', 'Old name');
- vm.$nextTick()
- .then(() => {
- expect(findPathText()).toEqual(`Old name → ${f.name}`);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findPathText()).toEqual(`Old name → ${f.name}`);
});
- it('correctly renders entry, the name of which did not change after rename (as within a folder)', (done) => {
+ it('correctly renders entry, the name of which did not change after rename (as within a folder)', async () => {
Vue.set(vm.file, 'prevName', f.name);
- vm.$nextTick()
- .then(() => {
- expect(findPathText()).toEqual(f.name);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findPathText()).toEqual(f.name);
});
- it('opens a closed file in the editor when clicking the file path', (done) => {
+ it('opens a closed file in the editor when clicking the file path', async () => {
jest.spyOn(vm, 'openPendingTab');
jest.spyOn(router, 'push').mockImplementation(() => {});
findPathEl.click();
- setImmediate(() => {
- expect(vm.openPendingTab).toHaveBeenCalled();
- expect(router.push).toHaveBeenCalled();
+ await nextTick();
- done();
- });
+ expect(vm.openPendingTab).toHaveBeenCalled();
+ expect(router.push).toHaveBeenCalled();
});
- it('calls updateViewer with diff when clicking file', (done) => {
+ it('calls updateViewer with diff when clicking file', async () => {
jest.spyOn(vm, 'openFileInEditor');
jest.spyOn(vm, 'updateViewer');
jest.spyOn(router, 'push').mockImplementation(() => {});
findPathEl.click();
- setImmediate(() => {
- expect(vm.updateViewer).toHaveBeenCalledWith('diff');
+ await waitForPromises();
- done();
- });
+ expect(vm.updateViewer).toHaveBeenCalledWith('diff');
});
describe('computed', () => {
@@ -134,14 +123,11 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(vm.$el.querySelector('.is-active')).toBe(null);
});
- it('adds active class when keys match', (done) => {
+ it('adds active class when keys match', async () => {
vm.keyPrefix = 'staged';
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.is-active')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.is-active')).not.toBe(null);
});
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/list_spec.js b/spec/frontend/ide/components/commit_sidebar/list_spec.js
index eb12fc994a5..1d42512c9ee 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import commitSidebarList from '~/ide/components/commit_sidebar/list.vue';
import { createStore } from '~/ide/stores';
@@ -31,12 +31,11 @@ describe('Multi-file editor commit sidebar list', () => {
});
describe('with a list of files', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
const f = file('file name');
f.changed = true;
vm.fileList.push(f);
-
- Vue.nextTick(done);
+ await nextTick();
});
it('renders list', () => {
diff --git a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
index 1514fbc2c3b..e66de6bb0b0 100644
--- a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import createComponent from 'helpers/vue_mount_component_helper';
import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
@@ -23,34 +23,23 @@ describe('IDE commit message field', () => {
vm.$destroy();
});
- it('adds is-focused class on focus', (done) => {
+ it('adds is-focused class on focus', async () => {
vm.$el.querySelector('textarea').focus();
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
});
- it('removed is-focused class on blur', (done) => {
+ it('removed is-focused class on blur', async () => {
vm.$el.querySelector('textarea').focus();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
-
- vm.$el.querySelector('textarea').blur();
+ await nextTick();
+ expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.$el.querySelector('.is-focused')).toBeNull();
+ vm.$el.querySelector('textarea').blur();
- done();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelector('.is-focused')).toBeNull();
});
it('emits input event on input', () => {
@@ -66,105 +55,78 @@ describe('IDE commit message field', () => {
describe('highlights', () => {
describe('subject line', () => {
- it('does not highlight less than 50 characters', (done) => {
+ it('does not highlight less than 50 characters', async () => {
vm.text = 'text less than 50 chars';
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.highlights span').textContent).toContain(
- 'text less than 50 chars',
- );
+ await nextTick();
+ expect(vm.$el.querySelector('.highlights span').textContent).toContain(
+ 'text less than 50 chars',
+ );
- expect(vm.$el.querySelector('mark').style.display).toBe('none');
- })
- .then(done)
- .catch(done.fail);
+ expect(vm.$el.querySelector('mark').style.display).toBe('none');
});
- it('highlights characters over 50 length', (done) => {
+ it('highlights characters over 50 length', async () => {
vm.text =
'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.highlights span').textContent).toContain(
- 'text less than 50 chars that should not highlighte',
- );
-
- expect(vm.$el.querySelector('mark').style.display).not.toBe('none');
- expect(vm.$el.querySelector('mark').textContent).toBe(
- 'd. text more than 50 should be highlighted',
- );
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelector('.highlights span').textContent).toContain(
+ 'text less than 50 chars that should not highlighte',
+ );
+
+ expect(vm.$el.querySelector('mark').style.display).not.toBe('none');
+ expect(vm.$el.querySelector('mark').textContent).toBe(
+ 'd. text more than 50 should be highlighted',
+ );
});
});
describe('body text', () => {
- it('does not highlight body text less tan 72 characters', (done) => {
+ it('does not highlight body text less tan 72 characters', async () => {
vm.text = 'subject line\nbody content';
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
+ expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none');
});
- it('highlights body text more than 72 characters', (done) => {
+ it('highlights body text more than 72 characters', async () => {
vm.text =
'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none');
- expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
+ expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none');
+ expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
});
- it('highlights body text & subject line', (done) => {
+ it('highlights body text & subject line', async () => {
vm.text =
'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark').length).toBe(2);
+ await nextTick();
+ expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
+ expect(vm.$el.querySelectorAll('mark').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark')[0].textContent).toContain('d');
- expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
- })
- .then(done)
- .catch(done.fail);
+ expect(vm.$el.querySelectorAll('mark')[0].textContent).toContain('d');
+ expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
});
});
});
describe('scrolling textarea', () => {
- it('updates transform of highlights', (done) => {
+ it('updates transform of highlights', async () => {
vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content';
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('textarea').scrollTo(0, 50);
-
- vm.handleScroll();
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.scrollTop).toBe(50);
- expect(vm.$el.querySelector('.highlights').style.transform).toBe(
- 'translate3d(0, -50px, 0)',
- );
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ vm.$el.querySelector('textarea').scrollTo(0, 50);
+
+ vm.handleScroll();
+
+ await nextTick();
+ expect(vm.scrollTop).toBe(50);
+ expect(vm.$el.querySelector('.highlights').style.transform).toBe('translate3d(0, -50px, 0)');
});
});
});
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 4474647552d..64b53264b4d 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
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData, branches } from 'jest/ide/mock_data';
import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
@@ -72,15 +72,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('has new MR', (done) => {
+ it('has new MR', async () => {
setMR();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.textContent).not.toBe('');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).not.toBe('');
});
});
@@ -96,15 +92,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).toBe('');
});
- it('has new MR', (done) => {
+ it('has new MR', async () => {
setMR();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.textContent).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).toBe('');
});
});
});
@@ -121,15 +113,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is rendered if MR exists', (done) => {
+ it('is rendered if MR exists', async () => {
setMR();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.textContent).not.toBe('');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).not.toBe('');
});
});
@@ -144,15 +132,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is hidden if MR exists', (done) => {
+ it('is hidden if MR exists', async () => {
setMR();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.textContent).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).toBe('');
});
});
});
@@ -168,15 +152,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is hidden if MR exists', (done) => {
+ it('is hidden if MR exists', async () => {
setMR();
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.textContent).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).toBe('');
});
it('shows enablded checkbox', () => {
diff --git a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
index a6f3253321b..d899bc4f7d8 100644
--- a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
import { createStore } from '~/ide/stores';
@@ -7,7 +7,7 @@ describe('IDE commit sidebar radio group', () => {
let vm;
let store;
- beforeEach((done) => {
+ beforeEach(async () => {
store = createStore();
const Component = Vue.extend(radioGroup);
@@ -22,7 +22,7 @@ describe('IDE commit sidebar radio group', () => {
vm.$mount();
- Vue.nextTick(done);
+ await nextTick();
});
afterEach(() => {
@@ -33,7 +33,7 @@ describe('IDE commit sidebar radio group', () => {
expect(vm.$el.textContent).toContain('test');
});
- it('uses slot if label is not present', (done) => {
+ it('uses slot if label is not present', async () => {
vm.$destroy();
vm = new Vue({
@@ -47,25 +47,19 @@ describe('IDE commit sidebar radio group', () => {
vm.$mount();
- Vue.nextTick(() => {
- expect(vm.$el.textContent).toContain('Testing slot');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.textContent).toContain('Testing slot');
});
- it('updates store when changing radio button', (done) => {
+ it('updates store when changing radio button', async () => {
vm.$el.querySelector('input').dispatchEvent(new Event('change'));
- Vue.nextTick(() => {
- expect(store.state.commit.commitAction).toBe('1');
-
- done();
- });
+ await nextTick();
+ expect(store.state.commit.commitAction).toBe('1');
});
describe('with input', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
vm.$destroy();
const Component = Vue.extend(radioGroup);
@@ -82,32 +76,27 @@ describe('IDE commit sidebar radio group', () => {
vm.$mount();
- Vue.nextTick(done);
+ await nextTick();
});
it('renders input box when commitAction matches value', () => {
expect(vm.$el.querySelector('.form-control')).not.toBeNull();
});
- it('hides input when commitAction doesnt match value', (done) => {
+ it('hides input when commitAction doesnt match value', async () => {
store.state.commit.commitAction = '2';
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.form-control')).toBeNull();
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.form-control')).toBeNull();
});
- it('updates branch name in store on input', (done) => {
+ it('updates branch name in store on input', async () => {
const input = vm.$el.querySelector('.form-control');
input.value = 'testing-123';
input.dispatchEvent(new Event('input'));
- Vue.nextTick(() => {
- expect(store.state.commit.newBranchName).toBe('testing-123');
-
- done();
- });
+ await nextTick();
+ expect(store.state.commit.newBranchName).toBe('testing-123');
});
it('renders newBranchName if present', () => {
diff --git a/spec/frontend/ide/components/commit_sidebar/success_message_spec.js b/spec/frontend/ide/components/commit_sidebar/success_message_spec.js
index 7bbe47d37af..52e35bdbb73 100644
--- a/spec/frontend/ide/components/commit_sidebar/success_message_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/success_message_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import successMessage from '~/ide/components/commit_sidebar/success_message.vue';
import { createStore } from '~/ide/stores';
@@ -23,13 +23,10 @@ describe('IDE commit panel successful commit state', () => {
vm.$destroy();
});
- it('renders last commit message when it exists', (done) => {
+ it('renders last commit message when it exists', async () => {
vm.$store.state.lastCommitMsg = 'testing commit message';
- Vue.nextTick(() => {
- expect(vm.$el.textContent).toContain('testing commit message');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.textContent).toContain('testing commit message');
});
});
diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js
index 2de3fa863a8..17568158131 100644
--- a/spec/frontend/ide/components/error_message_spec.js
+++ b/spec/frontend/ide/components/error_message_spec.js
@@ -1,10 +1,10 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ErrorMessage from '~/ide/components/error_message.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE error message component', () => {
let wrapper;
@@ -25,7 +25,6 @@ describe('IDE error message component', () => {
},
},
store: fakeStore,
- localVue,
});
};
@@ -87,19 +86,15 @@ describe('IDE error message component', () => {
expect(actionMock).toHaveBeenCalledWith(message.actionPayload);
});
- it('does not dispatch action when already loading', () => {
+ it('does not dispatch action when already loading', async () => {
findActionButton().trigger('click');
actionMock.mockReset();
- return wrapper.vm.$nextTick(() => {
- findActionButton().trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(actionMock).not.toHaveBeenCalled();
- });
- });
+ findActionButton().trigger('click');
+ await nextTick();
+ expect(actionMock).not.toHaveBeenCalled();
});
- it('shows loading icon when loading', () => {
+ it('shows loading icon when loading', async () => {
let resolveAction;
actionMock.mockImplementation(
() =>
@@ -109,19 +104,16 @@ describe('IDE error message component', () => {
);
findActionButton().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
- resolveAction();
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
+ resolveAction();
});
- it('hides loading icon when operation finishes', () => {
+ it('hides loading icon when operation finishes', async () => {
findActionButton().trigger('click');
- return actionMock()
- .then(() => wrapper.vm.$nextTick())
- .then(() => {
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false);
- });
+ await actionMock();
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 641407c7b77..5a7a1fe7db0 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import { createStore } from '~/ide/stores';
@@ -70,28 +70,22 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
});
- it('does not show when tree is open', (done) => {
+ it('does not show when tree is open', async () => {
vm.file.type = 'tree';
vm.file.opened = true;
changesCount = 1;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
});
- it('shows for trees with changes', (done) => {
+ it('shows for trees with changes', async () => {
vm.file.type = 'tree';
vm.file.opened = false;
changesCount = 1;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-tree-changes')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.ide-tree-changes')).not.toBe(null);
});
});
@@ -100,55 +94,40 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
});
- it('shows when file is changed', (done) => {
+ it('shows when file is changed', async () => {
vm.file.changed = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
});
- it('shows when file is staged', (done) => {
+ it('shows when file is staged', async () => {
vm.file.staged = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
});
- it('shows when file is a tempFile', (done) => {
+ it('shows when file is a tempFile', async () => {
vm.file.tempFile = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
});
- it('shows when file is renamed', (done) => {
+ it('shows when file is renamed', async () => {
vm.file.prevPath = 'original-file';
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
});
- it('hides when file is renamed', (done) => {
+ it('hides when file is renamed', async () => {
vm.file.prevPath = 'original-file';
vm.file.type = 'tree';
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
});
});
@@ -157,14 +136,11 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
});
- it('shows when a merge request change', (done) => {
+ it('shows when a merge request change', async () => {
vm.file.mrChange = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
});
});
});
diff --git a/spec/frontend/ide/components/file_templates/bar_spec.js b/spec/frontend/ide/components/file_templates/bar_spec.js
index 4ca99f8d055..e8ebfa78fe9 100644
--- a/spec/frontend/ide/components/file_templates/bar_spec.js
+++ b/spec/frontend/ide/components/file_templates/bar_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import Bar from '~/ide/components/file_templates/bar.vue';
import { createStore } from '~/ide/stores';
@@ -46,7 +46,7 @@ describe('IDE file templates bar component', () => {
});
describe('template dropdown', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
vm.$store.state.fileTemplates.templates = [
{
name: 'test',
@@ -57,7 +57,7 @@ describe('IDE file templates bar component', () => {
key: 'gitlab_ci_ymls',
};
- vm.$nextTick(done);
+ await nextTick();
});
it('renders dropdown component', () => {
@@ -75,14 +75,11 @@ describe('IDE file templates bar component', () => {
});
});
- it('shows undo button if updateSuccess is true', (done) => {
+ it('shows undo button if updateSuccess is true', async () => {
vm.$store.state.fileTemplates.updateSuccess = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.btn-default').style.display).not.toBe('none');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.btn-default').style.display).not.toBe('none');
});
it('calls undoFileTemplate when clicking undo button', () => {
@@ -93,7 +90,7 @@ describe('IDE file templates bar component', () => {
expect(vm.undoFileTemplate).toHaveBeenCalled();
});
- it('calls setSelectedTemplateType if activeFile name matches a template', (done) => {
+ it('calls setSelectedTemplateType if activeFile name matches a template', async () => {
const fileName = '.gitlab-ci.yml';
jest.spyOn(vm, 'setSelectedTemplateType').mockImplementation(() => {});
@@ -101,13 +98,10 @@ describe('IDE file templates bar component', () => {
vm.setInitialType();
- vm.$nextTick(() => {
- expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
- name: fileName,
- key: 'gitlab_ci_ymls',
- });
-
- done();
+ await nextTick();
+ expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
+ name: fileName,
+ key: 'gitlab_ci_ymls',
});
});
});
diff --git a/spec/frontend/ide/components/file_templates/dropdown_spec.js b/spec/frontend/ide/components/file_templates/dropdown_spec.js
index 44ac9aa954d..e54b322b9db 100644
--- a/spec/frontend/ide/components/file_templates/dropdown_spec.js
+++ b/spec/frontend/ide/components/file_templates/dropdown_spec.js
@@ -1,11 +1,11 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import $ from 'jquery';
import Vuex from 'vuex';
import Dropdown from '~/ide/components/file_templates/dropdown.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE file templates dropdown component', () => {
let wrapper;
@@ -44,7 +44,6 @@ describe('IDE file templates dropdown component', () => {
...props,
},
store: fakeStore,
- localVue,
});
({ element } = wrapper);
@@ -55,15 +54,14 @@ describe('IDE file templates dropdown component', () => {
wrapper = null;
});
- it('calls clickItem on click', () => {
+ it('calls clickItem on click', async () => {
const itemData = { name: 'test.yml ' };
createComponent({ props: { data: [itemData] } });
const item = findItemButtons().at(0);
item.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().click[0][0]).toBe(itemData);
- });
+ await nextTick();
+ expect(wrapper.emitted().click[0][0]).toBe(itemData);
});
it('renders dropdown title', () => {
@@ -112,7 +110,7 @@ describe('IDE file templates dropdown component', () => {
expect(items.wrappers.map((x) => x.text())).toEqual(templates.map((x) => x.name));
});
- it('searches template data', () => {
+ it('searches template data', async () => {
const templates = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }];
const matches = ['match 1', 'match 2'];
createComponent({
@@ -120,12 +118,11 @@ describe('IDE file templates dropdown component', () => {
state: { templates },
});
findSearch().setValue('match');
- return wrapper.vm.$nextTick().then(() => {
- const items = findItemButtons();
+ await nextTick();
+ const items = findItemButtons();
- expect(items.length).toBe(matches.length);
- expect(items.wrappers.map((x) => x.text())).toEqual(matches);
- });
+ expect(items.length).toBe(matches.length);
+ expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
it('does not render input when `searchable` is true & `showLoading` is true', () => {
@@ -160,17 +157,16 @@ describe('IDE file templates dropdown component', () => {
expect(findSearch().exists()).toBe(true);
});
- it('searches data', () => {
+ it('searches data', async () => {
const data = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }];
const matches = ['match 1', 'match 2'];
createComponent({ props: { searchable: true, data } });
findSearch().setValue('match');
- return wrapper.vm.$nextTick().then(() => {
- const items = findItemButtons();
+ await nextTick();
+ const items = findItemButtons();
- expect(items.length).toBe(matches.length);
- expect(items.wrappers.map((x) => x.text())).toEqual(matches);
- });
+ expect(items.length).toBe(matches.length);
+ expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
});
});
diff --git a/spec/frontend/ide/components/ide_file_row_spec.js b/spec/frontend/ide/components/ide_file_row_spec.js
index 20c105460f2..baf3d7cca9d 100644
--- a/spec/frontend/ide/components/ide_file_row_spec.js
+++ b/spec/frontend/ide/components/ide_file_row_spec.js
@@ -1,12 +1,12 @@
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import IdeFileRow from '~/ide/components/ide_file_row.vue';
import { createStore } from '~/ide/stores';
import FileRow from '~/vue_shared/components/file_row.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_EXTRA_PROPS = {
testattribute: 'abc',
@@ -30,7 +30,6 @@ describe('Ide File Row component', () => {
...props,
},
store: createStore(),
- localVue,
...options,
});
};
@@ -44,7 +43,7 @@ describe('Ide File Row component', () => {
const findFileRow = () => wrapper.find(FileRow);
const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen');
- it('fileRow component has listeners', () => {
+ it('fileRow component has listeners', async () => {
const toggleTreeOpen = jest.fn();
createComponent(
{},
@@ -57,9 +56,8 @@ describe('Ide File Row component', () => {
findFileRow().vm.$emit('toggleTreeOpen');
- return wrapper.vm.$nextTick().then(() => {
- expect(toggleTreeOpen).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(toggleTreeOpen).toHaveBeenCalled();
});
describe('default', () => {
@@ -86,32 +84,30 @@ describe('Ide File Row component', () => {
});
describe('with open dropdown', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
findFileRowExtra().vm.$emit('toggle', true);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows open dropdown', () => {
expect(hasDropdownOpen()).toBe(true);
});
- it('hides dropdown when mouseleave', () => {
+ it('hides dropdown when mouseleave', async () => {
findFileRow().vm.$emit('mouseleave');
- return wrapper.vm.$nextTick().then(() => {
- expect(hasDropdownOpen()).toEqual(false);
- });
+ await nextTick();
+ expect(hasDropdownOpen()).toEqual(false);
});
- it('hides dropdown on toggle', () => {
+ it('hides dropdown on toggle', async () => {
findFileRowExtra().vm.$emit('toggle', false);
- return wrapper.vm.$nextTick().then(() => {
- expect(hasDropdownOpen()).toEqual(false);
- });
+ await nextTick();
+ expect(hasDropdownOpen()).toEqual(false);
});
});
});
diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js
index 7a92f59641f..13d20761263 100644
--- a/spec/frontend/ide/components/ide_review_spec.js
+++ b/spec/frontend/ide/components/ide_review_spec.js
@@ -1,5 +1,5 @@
-import { createLocalVue, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { keepAlive } from 'helpers/keep_alive_component_helper';
import { trimText } from 'helpers/text_helper';
@@ -9,8 +9,7 @@ import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE review mode', () => {
let wrapper;
@@ -28,7 +27,6 @@ describe('IDE review mode', () => {
wrapper = mount(keepAlive(IdeReview), {
store,
- localVue,
});
});
@@ -76,14 +74,14 @@ describe('IDE review mode', () => {
});
describe('merge request', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.currentMergeRequestId = '1';
store.state.projects.abcproject.mergeRequests['1'] = {
iid: 123,
web_url: 'testing123',
};
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders edit dropdown', () => {
@@ -93,7 +91,7 @@ describe('IDE review mode', () => {
it('renders merge request link & IID', async () => {
store.state.viewer = 'mrdiff';
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(trimText(wrapper.text())).toContain('Merge request (!123)');
});
@@ -101,7 +99,7 @@ describe('IDE review mode', () => {
it('changes text to latest changes when viewer is not mrdiff', async () => {
store.state.viewer = 'diff';
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).toContain('Latest changes');
});
diff --git a/spec/frontend/ide/components/ide_side_bar_spec.js b/spec/frontend/ide/components/ide_side_bar_spec.js
index c683612b142..34f14ef23a4 100644
--- a/spec/frontend/ide/components/ide_side_bar_spec.js
+++ b/spec/frontend/ide/components/ide_side_bar_spec.js
@@ -1,5 +1,6 @@
import { GlSkeletonLoading } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import IdeReview from '~/ide/components/ide_review.vue';
@@ -10,8 +11,7 @@ import { leftSidebarViews } from '~/ide/constants';
import { createStore } from '~/ide/stores';
import { projectData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IdeSidebar', () => {
let wrapper;
@@ -26,7 +26,6 @@ describe('IdeSidebar', () => {
return mount(IdeSidebar, {
store,
- localVue,
});
}
@@ -46,7 +45,7 @@ describe('IdeSidebar', () => {
store.state.loading = true;
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(3);
});
@@ -61,7 +60,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.review.name;
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(IdeReview).exists()).toBe(true);
@@ -69,7 +68,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(IdeReview).exists()).toBe(false);
@@ -85,7 +84,7 @@ describe('IdeSidebar', () => {
view,
});
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(tree);
expect(wrapper.find(IdeReview).exists()).toBe(review);
@@ -100,7 +99,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(RepoCommitSection).exists()).toBe(true);
@@ -108,7 +107,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.edit.name;
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
// reference to the elements remains the same, meaning the components were kept alive
expect(wrapper.find(IdeTree).element).toEqual(ideTreeComponent);
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index f8d29fc7b47..37b42001a80 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
@@ -9,8 +10,7 @@ import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_FORK_IDE_PATH = '/test/ide/path';
@@ -34,7 +34,6 @@ describe('WebIDE', () => {
wrapper = shallowMount(Ide, {
store,
- localVue,
});
};
diff --git a/spec/frontend/ide/components/ide_status_bar_spec.js b/spec/frontend/ide/components/ide_status_bar_spec.js
index f1a0b64caf2..00ef75fcf3a 100644
--- a/spec/frontend/ide/components/ide_status_bar_spec.js
+++ b/spec/frontend/ide/components/ide_status_bar_spec.js
@@ -1,5 +1,5 @@
import _ from 'lodash';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
@@ -73,7 +73,7 @@ describe('ideStatusBar', () => {
});
describe('pipeline status', () => {
- it('opens right sidebar on clicking icon', (done) => {
+ it('opens right sidebar on clicking icon', async () => {
jest.spyOn(vm, 'openRightPane').mockImplementation(() => {});
Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
details: {
@@ -88,14 +88,10 @@ describe('ideStatusBar', () => {
},
});
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('.ide-status-pipeline button').click();
+ await nextTick();
+ vm.$el.querySelector('.ide-status-pipeline button').click();
- expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
- })
- .then(done)
- .catch(done.fail);
+ expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
});
});
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index 036edfb3ec1..371fbc6becd 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -1,5 +1,6 @@
import { GlLink } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import IdeStatusList from '~/ide/components/ide_status_list.vue';
import TerminalSyncStatusSafe from '~/ide/components/terminal_sync/terminal_sync_status_safe.vue';
@@ -16,8 +17,7 @@ const TEST_FILE_EDITOR = {
};
const TEST_EDITOR_POSITION = `${TEST_FILE_EDITOR.editorRow}:${TEST_FILE_EDITOR.editorColumn}`;
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/components/ide_status_list', () => {
let activeFileEditor;
@@ -42,7 +42,6 @@ describe('ide/components/ide_status_list', () => {
});
wrapper = shallowMount(IdeStatusList, {
- localVue,
store,
...options,
});
diff --git a/spec/frontend/ide/components/ide_tree_list_spec.js b/spec/frontend/ide/components/ide_tree_list_spec.js
index ace51204374..a85c52f5e86 100644
--- a/spec/frontend/ide/components/ide_tree_list_spec.js
+++ b/spec/frontend/ide/components/ide_tree_list_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeTreeList from '~/ide/components/ide_tree_list.vue';
import { createStore } from '~/ide/stores';
@@ -48,15 +48,12 @@ describe('IDE tree list', () => {
expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
});
- it('renders loading indicator', (done) => {
+ it('renders loading indicator', async () => {
store.state.trees['abcproject/main'].loading = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
- expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
+ expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
});
it('renders list of files', () => {
diff --git a/spec/frontend/ide/components/ide_tree_spec.js b/spec/frontend/ide/components/ide_tree_spec.js
index 0792b88aeb6..8465ef9f5f3 100644
--- a/spec/frontend/ide/components/ide_tree_spec.js
+++ b/spec/frontend/ide/components/ide_tree_spec.js
@@ -1,4 +1,4 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { keepAlive } from 'helpers/keep_alive_component_helper';
@@ -7,8 +7,7 @@ import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IdeTree', () => {
let store;
@@ -27,7 +26,6 @@ describe('IdeTree', () => {
wrapper = mount(keepAlive(IdeTree), {
store,
- localVue,
});
});
diff --git a/spec/frontend/ide/components/jobs/detail_spec.js b/spec/frontend/ide/components/jobs/detail_spec.js
index 3634599f328..9122471d421 100644
--- a/spec/frontend/ide/components/jobs/detail_spec.js
+++ b/spec/frontend/ide/components/jobs/detail_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import JobDetail from '~/ide/components/jobs/detail.vue';
@@ -48,14 +48,11 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').textContent).toContain('testing');
});
- it('renders empty message output', (done) => {
+ it('renders empty message output', async () => {
vm.$store.state.pipelines.detailJob.output = '';
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.bash').textContent).toContain('No messages were logged');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.bash').textContent).toContain('No messages were logged');
});
it('renders loading icon', () => {
@@ -68,14 +65,11 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').style.display).toBe('none');
});
- it('hide loading icon when isLoading is false', (done) => {
+ it('hide loading icon when isLoading is false', async () => {
vm.$store.state.pipelines.detailJob.isLoading = false;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.build-loader-animation').style.display).toBe('none');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.build-loader-animation').style.display).toBe('none');
});
it('resets detailJob when clicking header button', () => {
@@ -107,17 +101,16 @@ describe('IDE jobs detail view', () => {
fnName | btnName | scrollPos
${'scrollDown'} | ${'down'} | ${0}
${'scrollUp'} | ${'up'} | ${1}
- `('triggers $fnName when clicking $btnName button', ({ fnName, scrollPos }) => {
+ `('triggers $fnName when clicking $btnName button', async ({ fnName, scrollPos }) => {
jest.spyOn(vm, fnName).mockImplementation();
vm = vm.$mount();
vm.scrollPos = scrollPos;
- return vm.$nextTick().then(() => {
- vm.$el.querySelector('.btn-scroll:not([disabled])').click();
- expect(vm[fnName]).toHaveBeenCalled();
- });
+ await nextTick();
+ vm.$el.querySelector('.btn-scroll:not([disabled])').click();
+ expect(vm[fnName]).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js
index 7343fc80a03..c76760a5522 100644
--- a/spec/frontend/ide/components/jobs/item_spec.js
+++ b/spec/frontend/ide/components/jobs/item_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import JobItem from '~/ide/components/jobs/item.vue';
import { jobs } from '../../mock_data';
@@ -27,13 +27,10 @@ describe('IDE jobs item', () => {
expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
});
- it('does not render view logs button if not started', (done) => {
+ it('does not render view logs button if not started', async () => {
vm.job.started = false;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.btn')).toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.btn')).toBe(null);
});
});
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js
index 8797e07aef1..cb2c9f8f04f 100644
--- a/spec/frontend/ide/components/jobs/list_spec.js
+++ b/spec/frontend/ide/components/jobs/list_spec.js
@@ -1,11 +1,11 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import StageList from '~/ide/components/jobs/list.vue';
import Stage from '~/ide/components/jobs/stage.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const storeActions = {
fetchJobs: jest.fn(),
toggleStageCollapsed: jest.fn(),
@@ -42,7 +42,6 @@ describe('IDE stages list', () => {
...defaultProps,
...props,
},
- localVue,
store,
});
};
@@ -92,7 +91,6 @@ describe('IDE stages list', () => {
wrapper = mount(StageList, {
propsData: { ...defaultProps, stages },
store,
- localVue,
});
});
diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js
index 9accd81a2ba..f158c59cd32 100644
--- a/spec/frontend/ide/components/jobs/stage_spec.js
+++ b/spec/frontend/ide/components/jobs/stage_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Item from '~/ide/components/jobs/item.vue';
import Stage from '~/ide/components/jobs/stage.vue';
import { stages, jobs } from '../../mock_data';
@@ -47,23 +48,21 @@ describe('IDE pipeline stage', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('emits toggleCollaped event with stage id when clicking header', () => {
+ it('emits toggleCollaped event with stage id when clicking header', async () => {
const id = 5;
createComponent({ stage: { ...defaultProps.stage, id } });
findHeader().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id);
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id);
});
- it('emits clickViewLog entity with job', () => {
+ it('emits clickViewLog entity with job', async () => {
const [job] = defaultProps.stage.jobs;
createComponent();
wrapper.findAll(Item).at(0).vm.$emit('clickViewLog', job);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
- });
+ await nextTick();
+ expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
it('renders stage details & icon', () => {
diff --git a/spec/frontend/ide/components/merge_requests/item_spec.js b/spec/frontend/ide/components/merge_requests/item_spec.js
index f0a97a0b10a..d6cf8127b53 100644
--- a/spec/frontend/ide/components/merge_requests/item_spec.js
+++ b/spec/frontend/ide/components/merge_requests/item_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import Item from '~/ide/components/merge_requests/item.vue';
import { createRouter } from '~/ide/ide_router';
@@ -11,8 +12,7 @@ const TEST_ITEM = {
};
describe('IDE merge request item', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
let wrapper;
let store;
@@ -28,7 +28,6 @@ describe('IDE merge request item', () => {
currentProjectId: TEST_ITEM.projectPathWithNamespace,
...props,
},
- localVue,
router,
store,
});
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index 610e20d5868..583671a0af6 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -1,13 +1,13 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Item from '~/ide/components/merge_requests/item.vue';
import List from '~/ide/components/merge_requests/list.vue';
import TokenedInput from '~/ide/components/shared/tokened_input.vue';
import { mergeRequests as mergeRequestsMock } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE merge requests list', () => {
let wrapper;
@@ -41,7 +41,6 @@ describe('IDE merge requests list', () => {
wrapper = shallowMount(List, {
store: fakeStore,
- localVue,
});
};
@@ -67,33 +66,28 @@ describe('IDE merge requests list', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('renders no search results text when search is not empty', () => {
+ it('renders no search results text when search is not empty', async () => {
createComponent();
findTokenedInput().vm.$emit('input', 'something');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.text()).toContain('No merge requests found');
- });
+ await nextTick();
+ expect(wrapper.text()).toContain('No merge requests found');
});
- it('clicking on search type, sets currentSearchType and loads merge requests', () => {
+ it('clicking on search type, sets currentSearchType and loads merge requests', async () => {
createComponent();
findTokenedInput().vm.$emit('focus');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findSearchTypeButtons().at(0).trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- const searchType = wrapper.vm.$options.searchTypes[0];
+ await nextTick();
+ findSearchTypeButtons().at(0).trigger('click');
- expect(findTokenedInput().props('tokens')).toEqual([searchType]);
- expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
- type: searchType.type,
- search: '',
- });
- });
+ await nextTick();
+ const searchType = wrapper.vm.$options.searchTypes[0];
+
+ expect(findTokenedInput().props('tokens')).toEqual([searchType]);
+ expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
+ type: searchType.type,
+ search: '',
+ });
});
describe('with merge requests', () => {
@@ -120,16 +114,15 @@ describe('IDE merge requests list', () => {
});
describe('when searching merge requests', () => {
- it('calls `loadMergeRequests` on input in search field', () => {
+ it('calls `loadMergeRequests` on input in search field', async () => {
createComponent(defaultStateWithMergeRequests);
const input = findTokenedInput();
input.vm.$emit('input', 'something');
- return wrapper.vm.$nextTick().then(() => {
- expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
- search: 'something',
- type: '',
- });
+ await nextTick();
+ expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
+ search: 'something',
+ type: '',
});
});
});
@@ -144,9 +137,9 @@ describe('IDE merge requests list', () => {
});
describe('without search value', () => {
- beforeEach(() => {
+ beforeEach(async () => {
input.vm.$emit('focus');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows search types', () => {
@@ -156,22 +149,20 @@ describe('IDE merge requests list', () => {
);
});
- it('hides search types when search changes', () => {
+ it('hides search types when search changes', async () => {
input.vm.$emit('input', 'something');
- return wrapper.vm.$nextTick().then(() => {
- expect(findSearchTypeButtons().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findSearchTypeButtons().exists()).toBe(false);
});
describe('with search type', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findSearchTypeButtons().at(0).trigger('click');
- return wrapper.vm
- .$nextTick()
- .then(() => input.vm.$emit('focus'))
- .then(() => wrapper.vm.$nextTick());
+ await nextTick();
+ await input.vm.$emit('focus');
+ await nextTick();
});
it('does not show search types', () => {
@@ -181,10 +172,10 @@ describe('IDE merge requests list', () => {
});
describe('with search value', () => {
- beforeEach(() => {
+ beforeEach(async () => {
input.vm.$emit('input', 'something');
input.vm.$emit('focus');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not show search types', () => {
diff --git a/spec/frontend/ide/components/nav_dropdown_button_spec.js b/spec/frontend/ide/components/nav_dropdown_button_spec.js
index a02bfa5c391..1c14685df68 100644
--- a/spec/frontend/ide/components/nav_dropdown_button_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_button_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
@@ -36,38 +36,26 @@ describe('NavDropdown', () => {
expect(trimText(vm.$el.textContent)).toEqual('- -');
});
- it('renders branch name, if state has currentBranchId', (done) => {
+ it('renders branch name, if state has currentBranchId', async () => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
});
- it('renders mr id, if state has currentMergeRequestId', (done) => {
+ it('renders mr id, if state has currentMergeRequestId', async () => {
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
});
- it('renders branch and mr, if state has both', (done) => {
+ it('renders branch and mr, if state has both', async () => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
});
it('shows icons', () => {
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index 6a1be7ee964..33e638843f5 100644
--- a/spec/frontend/ide/components/nav_dropdown_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import $ from 'jquery';
+import { nextTick } from 'vue';
import NavDropdown from '~/ide/components/nav_dropdown.vue';
import { PERMISSION_READ_MR } from '~/ide/constants';
import { createStore } from '~/ide/stores';
@@ -58,29 +59,19 @@ describe('IDE NavDropdown', () => {
expect(findNavForm().exists()).toBe(false);
});
- it('renders nav form when show.bs.dropdown', (done) => {
+ it('renders nav form when show.bs.dropdown', async () => {
showDropdown();
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(findNavForm().exists()).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findNavForm().exists()).toBe(true);
});
- it('destroys nav form when closed', (done) => {
+ it('destroys nav form when closed', async () => {
showDropdown();
hideDropdown();
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(findNavForm().exists()).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findNavForm().exists()).toBe(false);
});
it('renders merge request icon', () => {
diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js
index 32fa2babcdb..298d7b810e1 100644
--- a/spec/frontend/ide/components/new_dropdown/button_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/button_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import Button from '~/ide/components/new_dropdown/button.vue';
@@ -37,14 +37,11 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.$emit).toHaveBeenCalledWith('click');
});
- it('hides label if showLabel is false', (done) => {
+ it('hides label if showLabel is false', async () => {
vm.showLabel = false;
- vm.$nextTick(() => {
- expect(vm.$el.textContent).not.toContain('Testing');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.textContent).not.toContain('Testing');
});
describe('tooltipTitle', () => {
@@ -52,14 +49,11 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.tooltipTitle).toBe('');
});
- it('returns label', (done) => {
+ it('returns label', async () => {
vm.showLabel = false;
- vm.$nextTick(() => {
- expect(vm.tooltipTitle).toBe('Testing');
-
- done();
- });
+ await nextTick();
+ expect(vm.tooltipTitle).toBe('Testing');
});
});
});
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index fa34d1b257f..19dcd9569b3 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import newDropdown from '~/ide/components/new_dropdown/index.vue';
import { createStore } from '~/ide/stores';
@@ -57,17 +57,15 @@ describe('new dropdown component', () => {
});
describe('isOpen', () => {
- it('scrolls dropdown into view', (done) => {
+ it('scrolls dropdown into view', async () => {
jest.spyOn(vm.$refs.dropdownMenu, 'scrollIntoView').mockImplementation(() => {});
vm.isOpen = true;
- setImmediate(() => {
- expect(vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
- block: 'nearest',
- });
+ await nextTick();
- done();
+ expect(vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
+ block: 'nearest',
});
});
});
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index 41111f5dbb4..8134248bbf4 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import createFlash from '~/flash';
import modal from '~/ide/components/new_dropdown/modal.vue';
@@ -19,14 +19,14 @@ describe('new file modal component', () => {
${'tree'} | ${'Create new directory'} | ${'Create directory'} | ${false}
${'blob'} | ${'Create new file'} | ${'Create file'} | ${true}
`('$entryType', ({ entryType, modalTitle, btnTitle, showsFileTemplates }) => {
- beforeEach((done) => {
+ beforeEach(async () => {
const store = createStore();
vm = createComponentWithStore(Component, store).$mount();
vm.open(entryType);
vm.name = 'testing';
- vm.$nextTick(done);
+ await nextTick();
});
afterEach(() => {
@@ -71,16 +71,13 @@ describe('new file modal component', () => {
${'blob'} | ${'Rename file'} | ${'Rename file'}
`(
'renders title and button for renaming $entryType',
- ({ entryType, modalTitle, btnTitle }, done) => {
+ async ({ entryType, modalTitle, btnTitle }) => {
vm.$store.state.entries['test-path'].type = entryType;
vm.open('rename', 'test-path');
- vm.$nextTick(() => {
- expect(document.querySelector('.modal-title').textContent.trim()).toBe(modalTitle);
- expect(document.querySelector('.btn-success').textContent.trim()).toBe(btnTitle);
-
- done();
- });
+ await nextTick();
+ expect(document.querySelector('.modal-title').textContent.trim()).toBe(modalTitle);
+ expect(document.querySelector('.btn-success').textContent.trim()).toBe(btnTitle);
},
);
diff --git a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
index 7216f50b05c..7f2ee0fe7d9 100644
--- a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
+++ b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
@@ -1,12 +1,12 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import IdeSidebarNav from '~/ide/components/ide_sidebar_nav.vue';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import { createStore } from '~/ide/stores';
import paneModule from '~/ide/stores/modules/pane';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/components/panes/collapsible_sidebar.vue', () => {
let wrapper;
@@ -17,7 +17,6 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
const createComponent = (props) => {
wrapper = shallowMount(CollapsibleSidebar, {
- localVue,
store,
propsData: {
extensionTabs: [],
@@ -46,7 +45,7 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
let extensionTabs;
beforeEach(() => {
- const FakeComponent = localVue.component(fakeComponentName, {
+ const FakeComponent = Vue.component(fakeComponentName, {
render: () => null,
});
diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js
index c6231d129ff..d12acd6dc4c 100644
--- a/spec/frontend/ide/components/panes/right_spec.js
+++ b/spec/frontend/ide/components/panes/right_spec.js
@@ -1,5 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import RightPane from '~/ide/components/panes/right.vue';
@@ -7,8 +7,7 @@ import { rightSidebarViews } from '~/ide/constants';
import { createStore } from '~/ide/stores';
import extendStore from '~/ide/stores/extend';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/components/panes/right.vue', () => {
let wrapper;
@@ -18,7 +17,6 @@ describe('ide/components/panes/right.vue', () => {
extendStore(store, document.createElement('div'));
wrapper = shallowMount(RightPane, {
- localVue,
store,
propsData: {
...props,
@@ -88,19 +86,18 @@ describe('ide/components/panes/right.vue', () => {
createComponent();
});
- it('adds terminal tab', () => {
+ it('adds terminal tab', async () => {
store.state.terminal.isVisible = true;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- show: true,
- title: 'Terminal',
- }),
- ]),
- );
- });
+ await nextTick();
+ expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ show: true,
+ title: 'Terminal',
+ }),
+ ]),
+ );
});
it('hides terminal tab when not visible', () => {
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index b168eec0f16..426fbd5c04c 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -1,16 +1,19 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import { dispatch } from 'codesandbox-api';
import smooshpack from 'smooshpack';
import Vuex from 'vuex';
+import waitForPromises from 'helpers/wait_for_promises';
import Clientside from '~/ide/components/preview/clientside.vue';
+import { PING_USAGE_PREVIEW_KEY, PING_USAGE_PREVIEW_SUCCESS_KEY } from '~/ide/constants';
import eventHub from '~/ide/eventhub';
jest.mock('smooshpack', () => ({
Manager: jest.fn(),
}));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const dummyPackageJson = () => ({
raw: JSON.stringify({
@@ -39,8 +42,7 @@ describe('IDE clientside preview', () => {
const storeClientsideActions = {
pingUsage: jest.fn().mockReturnValue(Promise.resolve({})),
};
-
- const waitForCalls = () => new Promise(setImmediate);
+ const dispatchCodesandboxReady = () => dispatch({ type: 'done' });
const createComponent = ({ state, getters } = {}) => {
store = new Vuex.Store({
@@ -67,7 +69,6 @@ describe('IDE clientside preview', () => {
wrapper = shallowMount(Clientside, {
store,
- localVue,
});
};
@@ -98,7 +99,7 @@ describe('IDE clientside preview', () => {
beforeEach(() => {
createComponent({ getters: { packageJson: dummyPackageJson } });
- return waitForCalls();
+ return waitForPromises();
});
it('creates sandpack manager', () => {
@@ -111,6 +112,20 @@ describe('IDE clientside preview', () => {
it('pings usage', () => {
expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(1);
+ expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith(
+ expect.anything(),
+ PING_USAGE_PREVIEW_KEY,
+ );
+ });
+
+ it('pings usage success', async () => {
+ dispatchCodesandboxReady();
+ await nextTick();
+ expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(2);
+ expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith(
+ expect.anything(),
+ PING_USAGE_PREVIEW_SUCCESS_KEY,
+ );
});
});
@@ -123,7 +138,7 @@ describe('IDE clientside preview', () => {
state: { codesandboxBundlerUrl: TEST_BUNDLER_URL },
});
- return waitForCalls();
+ return waitForPromises();
});
it('creates sandpack manager with bundlerURL', () => {
@@ -138,7 +153,7 @@ describe('IDE clientside preview', () => {
beforeEach(() => {
createComponent({ getters: { packageJson: dummyPackageJson } });
- return waitForCalls();
+ return waitForPromises();
});
it('creates sandpack manager', () => {
@@ -324,7 +339,7 @@ describe('IDE clientside preview', () => {
wrapper.setData({ sandpackReady: true });
wrapper.vm.update();
- return waitForCalls().then(() => {
+ return waitForPromises().then(() => {
expect(smooshpack.Manager).toHaveBeenCalled();
});
});
@@ -352,39 +367,36 @@ describe('IDE clientside preview', () => {
});
describe('template', () => {
- it('renders ide-preview element when showPreview is true', () => {
+ it('renders ide-preview element when showPreview is true', async () => {
createComponent({ getters: { packageJson: dummyPackageJson } });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('#ide-preview').exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find('#ide-preview').exists()).toBe(true);
});
- it('renders empty state', () => {
+ it('renders empty state', async () => {
createComponent();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.text()).toContain(
- 'Preview your web application using Web IDE client-side evaluation.',
- );
- });
+ await nextTick();
+ expect(wrapper.text()).toContain(
+ 'Preview your web application using Web IDE client-side evaluation.',
+ );
});
- it('renders loading icon', () => {
+ it('renders loading icon', async () => {
createComponent();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/preview/navigator_spec.js b/spec/frontend/ide/components/preview/navigator_spec.js
index ee760364c7e..a199f4704f7 100644
--- a/spec/frontend/ide/components/preview/navigator_spec.js
+++ b/spec/frontend/ide/components/preview/navigator_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { listen } from 'codesandbox-api';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import ClientsideNavigator from '~/ide/components/preview/navigator.vue';
@@ -29,31 +30,28 @@ describe('IDE clientside preview navigator', () => {
wrapper.destroy();
});
- it('renders readonly URL bar', () => {
+ it('renders readonly URL bar', async () => {
listenHandler({ type: 'urlchange', url: manager.bundlerURL });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('input[readonly]').element.value).toBe('/');
- });
+ await nextTick();
+ expect(wrapper.find('input[readonly]').element.value).toBe('/');
});
it('renders loading icon by default', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('removes loading icon when done event is fired', () => {
+ it('removes loading icon when done event is fired', async () => {
listenHandler({ type: 'done' });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
- it('does not count visiting same url multiple times', () => {
+ it('does not count visiting same url multiple times', async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'done', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'done', url: `${TEST_HOST}/url1` });
- return wrapper.vm.$nextTick().then(() => {
- expect(findBackButton().attributes('disabled')).toBe('disabled');
- });
+ await nextTick();
+ expect(findBackButton().attributes('disabled')).toBe('disabled');
});
it('unsubscribes from listen on destroy', () => {
@@ -64,107 +62,93 @@ describe('IDE clientside preview navigator', () => {
});
describe('back button', () => {
- beforeEach(() => {
+ beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url: TEST_HOST });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('is disabled by default', () => {
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
- it('is enabled when there is previous entry', () => {
+ it('is enabled when there is previous entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
- return wrapper.vm.$nextTick().then(() => {
- findBackButton().trigger('click');
- expect(findBackButton().attributes('disabled')).toBeFalsy();
- });
+ await nextTick();
+ findBackButton().trigger('click');
+ expect(findBackButton().attributes('disabled')).toBeFalsy();
});
- it('is disabled when there is no previous entry', () => {
+ it('is disabled when there is no previous entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findBackButton().trigger('click');
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findBackButton().attributes('disabled')).toBe('disabled');
- });
+
+ await nextTick();
+ findBackButton().trigger('click');
+
+ await nextTick();
+ expect(findBackButton().attributes('disabled')).toBe('disabled');
});
- it('updates manager iframe src', () => {
+ it('updates manager iframe src', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` });
- return wrapper.vm.$nextTick().then(() => {
- findBackButton().trigger('click');
+ await nextTick();
+ findBackButton().trigger('click');
- expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
- });
+ expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
});
describe('forward button', () => {
- beforeEach(() => {
+ beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url: TEST_HOST });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('is disabled by default', () => {
expect(findForwardButton().attributes('disabled')).toBe('disabled');
});
- it('is enabled when there is next entry', () => {
+ it('is enabled when there is next entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findBackButton().trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findForwardButton().attributes('disabled')).toBeFalsy();
- });
+
+ await nextTick();
+ findBackButton().trigger('click');
+
+ await nextTick();
+ expect(findForwardButton().attributes('disabled')).toBeFalsy();
});
- it('is disabled when there is no next entry', () => {
+ it('is disabled when there is no next entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findBackButton().trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- findForwardButton().trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findForwardButton().attributes('disabled')).toBe('disabled');
- });
+
+ await nextTick();
+ findBackButton().trigger('click');
+
+ await nextTick();
+ findForwardButton().trigger('click');
+
+ await nextTick();
+ expect(findForwardButton().attributes('disabled')).toBe('disabled');
});
- it('updates manager iframe src', () => {
+ it('updates manager iframe src', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` });
- return wrapper.vm.$nextTick().then(() => {
- findBackButton().trigger('click');
+ await nextTick();
+ findBackButton().trigger('click');
- expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
- });
+ expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
});
describe('refresh button', () => {
const url = `${TEST_HOST}/some_url`;
- beforeEach(() => {
+ beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls refresh with current path', () => {
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 15af2d03704..96c9baeb328 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { editor as monacoEditor, Range } from 'monaco-editor';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import '~/behaviors/markdown/render_gfm';
import waitForPromises from 'helpers/wait_for_promises';
@@ -367,17 +367,17 @@ describe('RepoEditor', () => {
expect(vm.$store.state.panelResizing).toBe(false); // default value
vm.$store.state.panelResizing = true;
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).not.toHaveBeenCalled();
vm.$store.state.panelResizing = false;
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
vm.$store.state.panelResizing = true;
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
});
@@ -387,12 +387,12 @@ describe('RepoEditor', () => {
expect(vm.$store.state.rightPane.isOpen).toBe(false); // default value
vm.$store.state.rightPane.isOpen = true;
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
vm.$store.state.rightPane.isOpen = false;
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(2);
});
@@ -411,7 +411,7 @@ describe('RepoEditor', () => {
`('tabs in $mode are $isVisible', async ({ mode, isVisible } = {}) => {
vm.$store.state.currentActivityView = leftSidebarViews[mode].name;
- await vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.nav-links').exists()).toBe(isVisible);
});
});
@@ -436,7 +436,7 @@ describe('RepoEditor', () => {
});
changeViewMode(FILE_VIEW_MODE_PREVIEW);
- await vm.$nextTick();
+ await nextTick();
});
it('do not show the editor', () => {
@@ -448,7 +448,7 @@ describe('RepoEditor', () => {
expect(updateDimensionsSpy).not.toHaveBeenCalled();
changeViewMode(FILE_VIEW_MODE_EDITOR);
- await vm.$nextTick();
+ await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalled();
});
@@ -460,7 +460,7 @@ describe('RepoEditor', () => {
jest.spyOn(vm, 'shouldHideEditor', 'get').mockReturnValue(true);
vm.initEditor();
- await vm.$nextTick();
+ await nextTick();
};
it('does not fetch file information for temp entries', async () => {
@@ -511,20 +511,20 @@ describe('RepoEditor', () => {
const origFile = vm.file;
vm.file.pending = true;
- await vm.$nextTick();
+ await nextTick();
wrapper.setProps({
file: file('testing'),
});
vm.file.content = 'foo'; // need to prevent full cycle of initEditor
- await vm.$nextTick();
+ await nextTick();
expect(vm.removePendingTab).toHaveBeenCalledWith(origFile);
});
it('does not call initEditor if the file did not change', async () => {
Vue.set(vm, 'file', vm.file);
- await vm.$nextTick();
+ await nextTick();
expect(vm.initEditor).not.toHaveBeenCalled();
});
@@ -538,7 +538,7 @@ describe('RepoEditor', () => {
key: 'new',
},
});
- await vm.$nextTick();
+ await nextTick();
expect(vm.initEditor).toHaveBeenCalled();
});
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index 95d52e8f7a9..b16fd8f80ba 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -1,5 +1,6 @@
import { GlTab } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { stubComponent } from 'helpers/stub_component';
import RepoTab from '~/ide/components/repo_tab.vue';
@@ -7,8 +8,7 @@ import { createRouter } from '~/ide/ide_router';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const GlTabStub = stubComponent(GlTab, {
template: '<li><slot name="title" /></li>',
@@ -23,7 +23,6 @@ describe('RepoTab', () => {
function createComponent(propsData) {
wrapper = mount(RepoTab, {
- localVue,
store,
propsData,
stubs: {
diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js
index 6ee73b0a437..1cfc1f12745 100644
--- a/spec/frontend/ide/components/repo_tabs_spec.js
+++ b/spec/frontend/ide/components/repo_tabs_spec.js
@@ -1,11 +1,11 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import RepoTabs from '~/ide/components/repo_tabs.vue';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RepoTabs', () => {
let wrapper;
@@ -22,7 +22,6 @@ describe('RepoTabs', () => {
activeFile: file('activeFile'),
},
store,
- localVue,
});
});
@@ -30,17 +29,14 @@ describe('RepoTabs', () => {
wrapper.destroy();
});
- it('renders a list of tabs', (done) => {
+ it('renders a list of tabs', async () => {
store.state.openFiles[0].active = true;
- wrapper.vm.$nextTick(() => {
- const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
+ await nextTick();
+ const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
- expect(tabs.length).toEqual(2);
- expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
- expect(tabs[1].parentNode.classList.contains('active')).toEqual(false);
-
- done();
- });
+ expect(tabs.length).toEqual(2);
+ expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
+ expect(tabs[1].parentNode.classList.contains('active')).toEqual(false);
});
});
diff --git a/spec/frontend/ide/components/resizable_panel_spec.js b/spec/frontend/ide/components/resizable_panel_spec.js
index 6a5af52ea35..55b9423aba8 100644
--- a/spec/frontend/ide/components/resizable_panel_spec.js
+++ b/spec/frontend/ide/components/resizable_panel_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ResizablePanel from '~/ide/components/resizable_panel.vue';
import { SIDE_LEFT, SIDE_RIGHT } from '~/ide/constants';
@@ -8,8 +9,7 @@ const TEST_WIDTH = 500;
const TEST_MIN_WIDTH = 400;
describe('~/ide/components/resizable_panel', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
let wrapper;
let store;
@@ -33,7 +33,6 @@ describe('~/ide/components/resizable_panel', () => {
...props,
},
store,
- localVue,
});
};
const findResizer = () => wrapper.find(PanelResizer);
@@ -100,15 +99,14 @@ describe('~/ide/components/resizable_panel', () => {
});
});
- it('when resizer emits update:size, changes inline width', () => {
+ it('when resizer emits update:size, changes inline width', async () => {
const newSize = TEST_WIDTH - 100;
const resizer = findResizer();
resizer.vm.$emit('update:size', newSize);
- return wrapper.vm.$nextTick().then(() => {
- expect(findInlineStyle()).toBe(createInlineStyle(newSize));
- });
+ await nextTick();
+ expect(findInlineStyle()).toBe(createInlineStyle(newSize));
});
});
});
diff --git a/spec/frontend/ide/components/shared/tokened_input_spec.js b/spec/frontend/ide/components/shared/tokened_input_spec.js
index 837bfe6b574..a37c08af0a1 100644
--- a/spec/frontend/ide/components/shared/tokened_input_spec.js
+++ b/spec/frontend/ide/components/shared/tokened_input_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import TokenedInput from '~/ide/components/shared/tokened_input.vue';
@@ -54,15 +54,11 @@ describe('IDE shared/TokenedInput', () => {
expect(vm.$refs.input).toHaveValue(TEST_VALUE);
});
- it('renders placeholder, when tokens are empty', (done) => {
+ it('renders placeholder, when tokens are empty', async () => {
vm.tokens = [];
- vm.$nextTick()
- .then(() => {
- expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER);
});
it('triggers "removeToken" on token click', () => {
diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js
index 5659a7d15da..6a70ddb46a8 100644
--- a/spec/frontend/ide/components/terminal/session_spec.js
+++ b/spec/frontend/ide/components/terminal/session_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import TerminalSession from '~/ide/components/terminal/session.vue';
import Terminal from '~/ide/components/terminal/terminal.vue';
@@ -13,8 +14,7 @@ import {
const TEST_TERMINAL_PATH = 'terminal/path';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE TerminalSession', () => {
let wrapper;
@@ -33,7 +33,6 @@ describe('IDE TerminalSession', () => {
});
wrapper = shallowMount(TerminalSession, {
- localVue,
store,
...options,
});
@@ -68,32 +67,30 @@ describe('IDE TerminalSession', () => {
});
[STARTING, PENDING, RUNNING].forEach((status) => {
- it(`show stop button when status is ${status}`, () => {
+ it(`show stop button when status is ${status}`, async () => {
state.session = { status };
factory();
const button = findButton();
button.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(button.text()).toEqual('Stop Terminal');
- expect(actions.stopSession).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(button.text()).toEqual('Stop Terminal');
+ expect(actions.stopSession).toHaveBeenCalled();
});
});
[STOPPING, STOPPED].forEach((status) => {
- it(`show stop button when status is ${status}`, () => {
+ it(`show stop button when status is ${status}`, async () => {
state.session = { status };
factory();
const button = findButton();
button.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(button.text()).toEqual('Restart Terminal');
- expect(actions.restartSession).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(button.text()).toEqual('Restart Terminal');
+ expect(actions.restartSession).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
index 416096083f0..71ec0dca89d 100644
--- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
import TerminalControls from '~/ide/components/terminal/terminal_controls.vue';
@@ -39,27 +40,25 @@ describe('IDE TerminalControls', () => {
);
});
- it('emits "scroll-up" when click up button', () => {
+ it('emits "scroll-up" when click up button', async () => {
factory({ propsData: { canScrollUp: true } });
expect(wrapper.emitted()).toEqual({});
buttons.at(0).vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('scroll-up')).toEqual([[]]);
- });
+ await nextTick();
+ expect(wrapper.emitted('scroll-up')).toEqual([[]]);
});
- it('emits "scroll-down" when click down button', () => {
+ it('emits "scroll-down" when click down button', async () => {
factory({ propsData: { canScrollDown: true } });
expect(wrapper.emitted()).toEqual({});
buttons.at(1).vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('scroll-down')).toEqual([[]]);
- });
+ await nextTick();
+ expect(wrapper.emitted('scroll-down')).toEqual([[]]);
});
});
diff --git a/spec/frontend/ide/components/terminal/view_spec.js b/spec/frontend/ide/components/terminal/view_spec.js
index e97d4d8a73b..49f9513d2ac 100644
--- a/spec/frontend/ide/components/terminal/view_spec.js
+++ b/spec/frontend/ide/components/terminal/view_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
@@ -9,8 +10,7 @@ import TerminalView from '~/ide/components/terminal/view.vue';
const TEST_HELP_PATH = `${TEST_HOST}/help`;
const TEST_SVG_PATH = `${TEST_HOST}/illustration.svg`;
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('IDE TerminalView', () => {
let state;
@@ -30,7 +30,7 @@ describe('IDE TerminalView', () => {
},
});
- wrapper = shallowMount(TerminalView, { localVue, store });
+ wrapper = shallowMount(TerminalView, { store });
// Uses deferred components, so wait for those to load...
await waitForPromises();
diff --git a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
index 69077ef2c68..f921037d744 100644
--- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
+++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
@@ -1,10 +1,10 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import TerminalSyncStatus from '~/ide/components/terminal_sync/terminal_sync_status.vue';
import TerminalSyncStatusSafe from '~/ide/components/terminal_sync/terminal_sync_status_safe.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/components/terminal_sync/terminal_sync_status_safe', () => {
let store;
@@ -16,7 +16,6 @@ describe('ide/components/terminal_sync/terminal_sync_status_safe', () => {
});
wrapper = shallowMount(TerminalSyncStatusSafe, {
- localVue,
store,
});
};
diff --git a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
index c916c43d1e2..3a326b08fff 100644
--- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
+++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import TerminalSyncStatus from '~/ide/components/terminal_sync/terminal_sync_status.vue';
import {
@@ -11,8 +12,7 @@ import {
const TEST_MESSAGE = 'lorem ipsum dolar sit';
const START_LOADING = 'START_LOADING';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/components/terminal_sync/terminal_sync_status', () => {
let moduleState;
@@ -35,7 +35,6 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
});
wrapper = shallowMount(TerminalSyncStatus, {
- localVue,
store,
});
};
diff --git a/spec/frontend/ide/lib/common/model_spec.js b/spec/frontend/ide/lib/common/model_spec.js
index 51df1e2e42f..5d1623429c0 100644
--- a/spec/frontend/ide/lib/common/model_spec.js
+++ b/spec/frontend/ide/lib/common/model_spec.js
@@ -81,16 +81,13 @@ describe('Multi-file editor library model', () => {
});
describe('onChange', () => {
- it('calls callback on change', (done) => {
+ it('calls callback on change', () => {
const spy = jest.fn();
model.onChange(spy);
model.getModel().setValue('123');
- setImmediate(() => {
- expect(spy).toHaveBeenCalledWith(model, expect.anything());
- done();
- });
+ expect(spy).toHaveBeenCalledWith(model, expect.anything());
});
});
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 6b94d7cf6f1..45d1beea3f8 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import eventHub from '~/ide/eventhub';
import { createRouter } from '~/ide/ide_router';
import service from '~/ide/services';
@@ -68,7 +68,7 @@ describe('IDE store file actions', () => {
return store
.dispatch('closeFile', localFile)
- .then(Vue.nextTick)
+ .then(nextTick)
.then(() => {
expect(store.state.openFiles.length).toBe(0);
expect(store.state.changedFiles.length).toBe(1);
@@ -83,7 +83,7 @@ describe('IDE store file actions', () => {
return store
.dispatch('closeFile', localFile)
- .then(Vue.nextTick)
+ .then(nextTick)
.then(() => {
expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/main/-/newOpenFile/');
});
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index e575667b8c6..be43c618095 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -274,24 +274,17 @@ describe('Multi-file store actions', () => {
});
describe('scrollToTab', () => {
- it('focuses the current active element', (done) => {
+ it('focuses the current active element', () => {
document.body.innerHTML +=
'<div id="tabs"><div class="active"><div class="repo-tab"></div></div></div>';
const el = document.querySelector('.repo-tab');
jest.spyOn(el, 'focus').mockImplementation();
- store
- .dispatch('scrollToTab')
- .then(() => {
- setImmediate(() => {
- expect(el.focus).toHaveBeenCalled();
+ return store.dispatch('scrollToTab').then(() => {
+ expect(el.focus).toHaveBeenCalled();
- document.getElementById('tabs').remove();
-
- done();
- });
- })
- .catch(done.fail);
+ document.getElementById('tabs').remove();
+ });
});
});
diff --git a/spec/frontend/ide/stores/modules/clientside/actions_spec.js b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
index 88d7a630a90..d2777623b0d 100644
--- a/spec/frontend/ide/stores/modules/clientside/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
@@ -1,11 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import { PING_USAGE_PREVIEW_KEY } from '~/ide/constants';
import * as actions from '~/ide/stores/modules/clientside/actions';
import axios from '~/lib/utils/axios_utils';
const TEST_PROJECT_URL = `${TEST_HOST}/lorem/ipsum`;
-const TEST_USAGE_URL = `${TEST_PROJECT_URL}/service_ping/web_ide_clientside_preview`;
+const TEST_USAGE_URL = `${TEST_PROJECT_URL}/service_ping/${PING_USAGE_PREVIEW_KEY}`;
describe('IDE store module clientside actions', () => {
let rootGetters;
@@ -30,7 +31,7 @@ describe('IDE store module clientside actions', () => {
mock.onPost(TEST_USAGE_URL).reply(() => usageSpy());
- testAction(actions.pingUsage, null, rootGetters, [], [], () => {
+ testAction(actions.pingUsage, PING_USAGE_PREVIEW_KEY, rootGetters, [], [], () => {
expect(usageSpy).toHaveBeenCalled();
done();
});
diff --git a/spec/frontend/ide/stores/plugins/terminal_spec.js b/spec/frontend/ide/stores/plugins/terminal_spec.js
index d4cdad16ecb..912de88cb39 100644
--- a/spec/frontend/ide/stores/plugins/terminal_spec.js
+++ b/spec/frontend/ide/stores/plugins/terminal_spec.js
@@ -1,4 +1,4 @@
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import terminalModule from '~/ide/stores/modules/terminal';
@@ -11,8 +11,7 @@ const TEST_DATASET = {
eeWebTerminalConfigHelpPath: `${TEST_HOST}/web/terminal/config/help`,
eeWebTerminalRunnersHelpPath: `${TEST_HOST}/web/terminal/runners/help`,
};
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ide/stores/extend', () => {
let store;
diff --git a/spec/frontend/image_diff/helpers/badge_helper_spec.js b/spec/frontend/image_diff/helpers/badge_helper_spec.js
index c970ccc535d..9ac6ebf6fdb 100644
--- a/spec/frontend/image_diff/helpers/badge_helper_spec.js
+++ b/spec/frontend/image_diff/helpers/badge_helper_spec.js
@@ -62,7 +62,10 @@ describe('badge helper', () => {
});
it('should add badge classes', () => {
- expect(buttonEl.className).toContain('badge badge-pill');
+ const classes = buttonEl.className.split(' ');
+ expect(classes).toEqual(
+ expect.arrayContaining(['design-note-pin', 'on-image', 'gl-absolute']),
+ );
});
it('should set the badge text', () => {
@@ -105,7 +108,7 @@ describe('badge helper', () => {
beforeEach(() => {
containerEl.innerHTML = `
<div id="${noteId}">
- <div class="badge hidden">
+ <div class="design-note-pin hidden">
</div>
</div>
`;
@@ -116,7 +119,7 @@ describe('badge helper', () => {
badgeNumber,
},
});
- avatarBadgeEl = containerEl.querySelector(`#${noteId} .badge`);
+ avatarBadgeEl = containerEl.querySelector(`#${noteId} .design-note-pin`);
});
it('should update badge number', () => {
diff --git a/spec/frontend/image_diff/helpers/dom_helper_spec.js b/spec/frontend/image_diff/helpers/dom_helper_spec.js
index 9357d626bbe..1c5f1cbe3da 100644
--- a/spec/frontend/image_diff/helpers/dom_helper_spec.js
+++ b/spec/frontend/image_diff/helpers/dom_helper_spec.js
@@ -37,14 +37,16 @@ describe('domHelper', () => {
discussionEl = document.createElement('div');
discussionEl.innerHTML = `
<a href="#" class="image-diff-avatar-link">
- <div class="badge"></div>
+ <div class="design-note-pin"></div>
</a>
`;
domHelper.updateDiscussionAvatarBadgeNumber(discussionEl, badgeNumber);
});
it('should update avatar badge number', () => {
- expect(discussionEl.querySelector('.badge').textContent).toEqual(badgeNumber.toString());
+ expect(discussionEl.querySelector('.design-note-pin').textContent).toEqual(
+ badgeNumber.toString(),
+ );
});
});
@@ -54,13 +56,15 @@ describe('domHelper', () => {
beforeEach(() => {
discussionEl = document.createElement('div');
discussionEl.innerHTML = `
- <div class="badge"></div>
+ <div class="design-note-pin"></div>
`;
domHelper.updateDiscussionBadgeNumber(discussionEl, badgeNumber);
});
it('should update discussion badge number', () => {
- expect(discussionEl.querySelector('.badge').textContent).toEqual(badgeNumber.toString());
+ expect(discussionEl.querySelector('.design-note-pin').textContent).toEqual(
+ badgeNumber.toString(),
+ );
});
});
diff --git a/spec/frontend/image_diff/image_diff_spec.js b/spec/frontend/image_diff/image_diff_spec.js
index 16d19f45496..710aa7108a8 100644
--- a/spec/frontend/image_diff/image_diff_spec.js
+++ b/spec/frontend/image_diff/image_diff_spec.js
@@ -15,9 +15,9 @@ describe('ImageDiff', () => {
<div class="js-image-frame">
<img src="${TEST_HOST}/image.png">
<div class="comment-indicator"></div>
- <div id="badge-1" class="badge">1</div>
- <div id="badge-2" class="badge">2</div>
- <div id="badge-3" class="badge">3</div>
+ <div id="badge-1" class="design-note-pin">1</div>
+ <div id="badge-2" class="design-note-pin">2</div>
+ <div id="badge-3" class="design-note-pin">3</div>
</div>
<div class="note-container">
<div class="discussion-notes">
@@ -335,7 +335,7 @@ describe('ImageDiff', () => {
describe('cascade badge count', () => {
it('should update next imageBadgeEl value', () => {
- const imageBadgeEls = imageDiff.imageFrameEl.querySelectorAll('.badge');
+ const imageBadgeEls = imageDiff.imageFrameEl.querySelectorAll('.design-note-pin');
expect(imageBadgeEls[0].textContent).toEqual('1');
expect(imageBadgeEls[1].textContent).toEqual('2');
diff --git a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
index c6ddce17fe4..52c868e5356 100644
--- a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
+++ b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
@@ -1,4 +1,4 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
+import { InMemoryCache } from '@apollo/client/core';
import MockAdapter from 'axios-mock-adapter';
import { createMockClient } from 'mock-apollo-client';
import waitForPromises from 'helpers/wait_for_promises';
diff --git a/spec/frontend/import_entities/import_groups/graphql/fixtures.js b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
index ed4e343f331..938020e03f0 100644
--- a/spec/frontend/import_entities/import_groups/graphql/fixtures.js
+++ b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
@@ -16,6 +16,7 @@ export const generateFakeEntry = ({ id, status, message, ...rest }) => ({
status === STATUSES.NONE || status === STATUSES.PENDING
? null
: {
+ __typename: clientTypenames.BulkImportProgress,
id,
status,
message: message || '',
diff --git a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
index 0e748baa313..0b12df83cd1 100644
--- a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
@@ -1,6 +1,6 @@
import { GlLoadingIcon, GlButton, GlIntersectionObserver, GlFormInput } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { STATUSES } from '~/import_entities/constants';
import ImportProjectsTable from '~/import_entities/import_projects/components/import_projects_table.vue';
@@ -46,8 +46,7 @@ describe('ImportProjectsTable', () => {
filterable,
paginatable,
} = {}) {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const store = new Vuex.Store({
state: { ...state(), defaultTargetNamespace: USER_NAMESPACE, ...initialState },
@@ -67,7 +66,6 @@ describe('ImportProjectsTable', () => {
});
wrapper = shallowMount(ImportProjectsTable, {
- localVue,
store,
propsData: {
providerTitle,
diff --git a/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js b/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
index 72640f3d601..c8afa9ea57d 100644
--- a/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
@@ -1,6 +1,6 @@
import { GlBadge, GlButton, GlDropdown } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { STATUSES } from '~/import_entities//constants';
import ImportGroupDropdown from '~/import_entities/components/group_dropdown.vue';
@@ -38,13 +38,11 @@ describe('ProviderRepoTableRow', () => {
};
function mountComponent(props) {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const store = initStore();
wrapper = shallowMount(ProviderRepoTableRow, {
- localVue,
store,
propsData: { availableNamespaces, userNamespace, ...props },
});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 48545ffd2d6..1be6007d844 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlLoadingIcon, GlTable, GlAvatar, GlEmptyState } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import IncidentsList from '~/incidents/components/incidents_list.vue';
import {
I18N,
@@ -210,7 +211,7 @@ describe('Incidents List', () => {
it('sets button loading on click', async () => {
findCreateIncidentBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCreateIncidentBtn().attributes('loading')).toBe('true');
});
@@ -233,7 +234,7 @@ describe('Incidents List', () => {
it('should track create new incident button', async () => {
findCreateIncidentBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(Tracking.event).toHaveBeenCalled();
});
});
@@ -263,10 +264,10 @@ describe('Incidents List', () => {
const columnHeader = () => wrapper.find(`[${attr}="${value}"]`);
expect(columnHeader().attributes('aria-sort')).toBe(initialSort);
columnHeader().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(columnHeader().attributes('aria-sort')).toBe(firstSort);
columnHeader().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(columnHeader().attributes('aria-sort')).toBe(nextSort);
},
);
@@ -287,7 +288,7 @@ describe('Incidents List', () => {
it('should track incident creation events', async () => {
findCreateIncidentBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
const { category, action } = trackIncidentCreateNewOptions;
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
diff --git a/spec/frontend/incidents/mocks/incidents.json b/spec/frontend/incidents/mocks/incidents.json
index 78783a0dce5..357b94e5b6c 100644
--- a/spec/frontend/incidents/mocks/incidents.json
+++ b/spec/frontend/incidents/mocks/incidents.json
@@ -1,5 +1,6 @@
[
{
+ "id": 1,
"iid": "15",
"title": "New: Alert",
"createdAt": "2020-06-03T15:46:08Z",
@@ -9,6 +10,7 @@
"slaDueAt": "2020-06-04T12:46:08Z"
},
{
+ "id": 2,
"iid": "14",
"title": "Create issue4",
"createdAt": "2020-05-19T09:26:07Z",
@@ -27,6 +29,7 @@
"slaDueAt": null
},
{
+ "id": 3,
"iid": "13",
"title": "Create issue3",
"createdAt": "2020-05-19T08:53:55Z",
@@ -35,6 +38,7 @@
"severity": "LOW"
},
{
+ "id": 4,
"iid": "12",
"title": "Create issue2",
"createdAt": "2020-05-18T17:13:35Z",
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 1e3c344ce65..0f042dfaa4c 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
@@ -40,7 +40,6 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
>
<gl-tabs-stub
queryparamname="tab"
- theme="indigo"
value="0"
>
<!---->
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
index 0dc31616166..c335b593f7d 100644
--- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -1,6 +1,7 @@
import { GlFormCheckbox } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import { createStore } from '~/integrations/edit/store';
@@ -68,7 +69,7 @@ describe('ActiveCheckbox', () => {
it('switches the form value', async () => {
findInputInCheckbox().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
});
});
diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
index 805d3971994..cbe3402727a 100644
--- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
+++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
@@ -1,6 +1,7 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import { createStore } from '~/integrations/edit/store';
@@ -40,7 +41,7 @@ describe('ConfirmationModal', () => {
findGlModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().submit).toHaveLength(1);
});
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index b0fb94d2b29..ee2f6541b03 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -2,22 +2,14 @@ import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea
import { mount } from '@vue/test-utils';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
+import { mockField } from '../mock_data';
describe('DynamicField', () => {
let wrapper;
- const defaultProps = {
- help: 'The URL of the project',
- name: 'project_url',
- placeholder: 'https://jira.example.com',
- title: 'Project URL',
- type: 'text',
- value: '1',
- };
-
const createComponent = (props, isInheriting = false) => {
wrapper = mount(DynamicField, {
- propsData: { ...defaultProps, ...props },
+ propsData: { ...mockField, ...props },
computed: {
isInheriting: () => isInheriting,
},
@@ -61,7 +53,7 @@ describe('DynamicField', () => {
});
it(`renders GlFormCheckbox with correct text content when checkboxLabel is ${checkboxLabel}`, () => {
- expect(findGlFormCheckbox().text()).toContain(checkboxLabel ?? defaultProps.title);
+ expect(findGlFormCheckbox().text()).toContain(checkboxLabel ?? mockField.title);
});
it('does not render other types of input', () => {
@@ -160,7 +152,7 @@ describe('DynamicField', () => {
type: 'text',
id: 'service_project_url',
name: 'service[project_url]',
- placeholder: defaultProps.placeholder,
+ placeholder: mockField.placeholder,
required: 'required',
});
expect(findGlFormInput().attributes('readonly')).toBe(readonly);
@@ -179,7 +171,7 @@ describe('DynamicField', () => {
it('renders description with help text', () => {
createComponent();
- expect(findGlFormGroup().find('small').text()).toBe(defaultProps.help);
+ expect(findGlFormGroup().find('small').text()).toBe(mockField.help);
});
describe('when type is checkbox', () => {
@@ -189,7 +181,7 @@ describe('DynamicField', () => {
});
expect(findGlFormGroup().find('small').exists()).toBe(false);
- expect(findGlFormCheckbox().text()).toContain(defaultProps.help);
+ expect(findGlFormCheckbox().text()).toContain(mockField.help);
});
});
@@ -221,40 +213,36 @@ describe('DynamicField', () => {
it('renders label with title', () => {
createComponent();
- expect(findGlFormGroup().find('label').text()).toBe(defaultProps.title);
+ expect(findGlFormGroup().find('label').text()).toBe(mockField.title);
});
});
- describe('validations', () => {
- describe('password field', () => {
- beforeEach(() => {
+ describe('password field validations', () => {
+ describe('without value', () => {
+ it('requires validation', () => {
createComponent({
type: 'password',
required: true,
value: null,
+ isValidated: true,
});
- wrapper.vm.validated = true;
- });
-
- describe('without value', () => {
- it('requires validation', () => {
- expect(wrapper.vm.valid).toBe(false);
- expect(findGlFormGroup().classes('is-invalid')).toBe(true);
- expect(findGlFormInput().classes('is-invalid')).toBe(true);
- });
+ expect(findGlFormGroup().classes('is-invalid')).toBe(true);
+ expect(findGlFormInput().classes('is-invalid')).toBe(true);
});
+ });
- describe('with value', () => {
- beforeEach(() => {
- wrapper.setProps({ value: 'true' });
+ describe('with value', () => {
+ it('does not require validation', () => {
+ createComponent({
+ type: 'password',
+ required: true,
+ value: 'test value',
+ isValidated: true,
});
- it('does not require validation', () => {
- expect(wrapper.vm.valid).toBe(true);
- expect(findGlFormGroup().classes('is-valid')).toBe(true);
- expect(findGlFormInput().classes('is-valid')).toBe(true);
- });
+ expect(findGlFormGroup().classes('is-valid')).toBe(true);
+ expect(findGlFormInput().classes('is-valid')).toBe(true);
});
});
});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 8cf8a403e5d..7e01b79383a 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -17,16 +17,13 @@ import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import {
integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
- VALIDATE_INTEGRATION_FORM_EVENT,
I18N_DEFAULT_ERROR_MESSAGE,
} from '~/integrations/constants';
import { createStore } from '~/integrations/edit/store';
-import eventHub from '~/integrations/edit/event_hub';
import httpStatus from '~/lib/utils/http_status';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import { mockIntegrationProps } from '../mock_data';
+import { mockIntegrationProps, mockField } from '../mock_data';
-jest.mock('~/integrations/edit/event_hub');
jest.mock('@sentry/browser');
jest.mock('~/lib/utils/url_utility');
@@ -36,13 +33,6 @@ describe('IntegrationForm', () => {
let wrapper;
let dispatch;
let mockAxios;
- let mockForm;
- let vueIntegrationFormFeatureFlag;
-
- const createForm = () => {
- mockForm = document.createElement('form');
- jest.spyOn(document, 'querySelector').mockReturnValue(mockForm);
- };
const createComponent = ({
customStateProps = {},
@@ -56,10 +46,6 @@ describe('IntegrationForm', () => {
});
dispatch = jest.spyOn(store, 'dispatch').mockImplementation();
- if (!vueIntegrationFormFeatureFlag) {
- createForm();
- }
-
wrapper = mountFn(IntegrationForm, {
propsData: { ...props },
store,
@@ -75,11 +61,6 @@ describe('IntegrationForm', () => {
show: mockToastShow,
},
},
- provide: {
- glFeatures: {
- vueIntegrationForm: vueIntegrationFormFeatureFlag,
- },
- },
});
};
@@ -96,12 +77,7 @@ describe('IntegrationForm', () => {
const findTriggerFields = () => wrapper.findComponent(TriggerFields);
const findGlForm = () => wrapper.findComponent(GlForm);
const findRedirectToField = () => wrapper.findByTestId('redirect-to-field');
- const findFormElement = () => (vueIntegrationFormFeatureFlag ? findGlForm().element : mockForm);
-
- const mockFormFunctions = ({ checkValidityReturn }) => {
- jest.spyOn(findFormElement(), 'checkValidity').mockReturnValue(checkValidityReturn);
- jest.spyOn(findFormElement(), 'submit');
- };
+ const findDynamicField = () => wrapper.findComponent(DynamicField);
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@@ -357,17 +333,14 @@ describe('IntegrationForm', () => {
});
});
- describe('when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled', () => {
- it('renders hidden fields', () => {
- vueIntegrationFormFeatureFlag = true;
- createComponent({
- customStateProps: {
- redirectTo: '/services',
- },
- });
-
- expect(findRedirectToField().attributes('value')).toBe('/services');
+ it('renders hidden fields', () => {
+ createComponent({
+ customStateProps: {
+ redirectTo: '/services',
+ },
});
+
+ expect(findRedirectToField().attributes('value')).toBe('/services');
});
});
@@ -389,216 +362,200 @@ describe('IntegrationForm', () => {
});
describe.each`
- formActive | vueIntegrationFormEnabled | novalidate
- ${true} | ${true} | ${null}
- ${false} | ${true} | ${'novalidate'}
- ${true} | ${false} | ${null}
- ${false} | ${false} | ${'true'}
+ formActive | novalidate
+ ${true} | ${undefined}
+ ${false} | ${'true'}
`(
- 'when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled and `toggle-integration-active` is emitted with $formActive',
- ({ formActive, vueIntegrationFormEnabled, novalidate }) => {
+ 'when `toggle-integration-active` is emitted with $formActive',
+ ({ formActive, novalidate }) => {
beforeEach(async () => {
- vueIntegrationFormFeatureFlag = vueIntegrationFormEnabled;
-
createComponent({
customStateProps: {
showActive: true,
initialActivated: false,
},
- mountFn: mountExtended,
});
- mockFormFunctions({ checkValidityReturn: false });
await findActiveCheckbox().vm.$emit('toggle-integration-active', formActive);
});
it(`sets noValidate to ${novalidate}`, () => {
- expect(findFormElement().getAttribute('novalidate')).toBe(novalidate);
+ expect(findGlForm().attributes('novalidate')).toBe(novalidate);
});
},
);
});
- describe.each`
- vueIntegrationFormEnabled
- ${true}
- ${false}
- `(
- 'when `vueIntegrationForm` feature flag is $vueIntegrationFormEnabled',
- ({ vueIntegrationFormEnabled }) => {
- beforeEach(() => {
- vueIntegrationFormFeatureFlag = vueIntegrationFormEnabled;
- });
-
- describe('when `save` button is clicked', () => {
- describe('buttons', () => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- },
- mountFn: mountExtended,
- });
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
+ describe('when `save` button is clicked', () => {
+ describe('buttons', () => {
+ beforeEach(async () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: true,
+ },
+ mountFn: mountExtended,
+ });
- it('sets save button `loading` prop to `true`', () => {
- expect(findProjectSaveButton().props('loading')).toBe(true);
- });
+ await findProjectSaveButton().vm.$emit('click', new Event('click'));
+ });
- it('sets test button `disabled` prop to `true`', () => {
- expect(findTestButton().props('disabled')).toBe(true);
+ it('sets save button `loading` prop to `true`', () => {
+ expect(findProjectSaveButton().props('loading')).toBe(true);
+ });
+
+ it('sets test button `disabled` prop to `true`', () => {
+ expect(findTestButton().props('disabled')).toBe(true);
+ });
+ });
+
+ describe.each`
+ checkValidityReturn | integrationActive
+ ${true} | ${false}
+ ${true} | ${true}
+ ${false} | ${false}
+ `(
+ 'when form is valid (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
+ ({ integrationActive, checkValidityReturn }) => {
+ beforeEach(async () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: integrationActive,
+ },
+ mountFn: mountExtended,
});
+ jest.spyOn(findGlForm().element, 'submit');
+ jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(checkValidityReturn);
+
+ await findProjectSaveButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('submit form', () => {
+ expect(findGlForm().element.submit).toHaveBeenCalledTimes(1);
});
+ },
+ );
- describe.each`
- checkValidityReturn | integrationActive
- ${true} | ${false}
- ${true} | ${true}
- ${false} | ${false}
- `(
- 'when form is valid (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
- ({ integrationActive, checkValidityReturn }) => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: integrationActive,
- },
- mountFn: mountExtended,
- });
-
- mockFormFunctions({ checkValidityReturn });
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
-
- it('submits form', () => {
- expect(findFormElement().submit).toHaveBeenCalledTimes(1);
- });
+ describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
+ beforeEach(async () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: true,
+ fields: [mockField],
},
- );
-
- describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
- beforeEach(async () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- initialActivated: true,
- },
- mountFn: mountExtended,
- });
- mockFormFunctions({ checkValidityReturn: false });
-
- await findProjectSaveButton().vm.$emit('click', new Event('click'));
- });
+ mountFn: mountExtended,
+ });
+ jest.spyOn(findGlForm().element, 'submit');
+ jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(false);
- it('does not submit form', () => {
- expect(findFormElement().submit).not.toHaveBeenCalled();
- });
+ await findProjectSaveButton().vm.$emit('click', new Event('click'));
+ });
- it('sets save button `loading` prop to `false`', () => {
- expect(findProjectSaveButton().props('loading')).toBe(false);
- });
+ it('does not submit form', () => {
+ expect(findGlForm().element.submit).not.toHaveBeenCalled();
+ });
- it('sets test button `disabled` prop to `false`', () => {
- expect(findTestButton().props('disabled')).toBe(false);
- });
+ it('sets save button `loading` prop to `false`', () => {
+ expect(findProjectSaveButton().props('loading')).toBe(false);
+ });
- it('emits `VALIDATE_INTEGRATION_FORM_EVENT`', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
- });
+ it('sets test button `disabled` prop to `false`', () => {
+ expect(findTestButton().props('disabled')).toBe(false);
+ });
+
+ it('sets `isValidated` props on form fields', () => {
+ expect(findDynamicField().props('isValidated')).toBe(true);
+ });
+ });
+ });
+
+ describe('when `test` button is clicked', () => {
+ describe('when form is invalid', () => {
+ it('sets `isValidated` props on form fields', async () => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ fields: [mockField],
+ },
+ mountFn: mountExtended,
});
+ jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(false);
+
+ await findTestButton().vm.$emit('click', new Event('click'));
+
+ expect(findDynamicField().props('isValidated')).toBe(true);
});
+ });
- describe('when `test` button is clicked', () => {
- describe('when form is invalid', () => {
- it('emits `VALIDATE_INTEGRATION_FORM_EVENT` event to the event hub', () => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- },
- mountFn: mountExtended,
- });
- mockFormFunctions({ checkValidityReturn: false });
+ describe('when form is valid', () => {
+ const mockTestPath = '/test';
- findTestButton().vm.$emit('click', new Event('click'));
+ beforeEach(() => {
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ testPath: mockTestPath,
+ },
+ mountFn: mountExtended,
+ });
+ jest.spyOn(findGlForm().element, 'checkValidity').mockReturnValue(true);
+ });
- expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
- });
+ describe('buttons', () => {
+ beforeEach(async () => {
+ await findTestButton().vm.$emit('click', new Event('click'));
});
- describe('when form is valid', () => {
- const mockTestPath = '/test';
+ it('sets test button `loading` prop to `true`', () => {
+ expect(findTestButton().props('loading')).toBe(true);
+ });
- beforeEach(() => {
- createComponent({
- customStateProps: {
- showActive: true,
- canTest: true,
- testPath: mockTestPath,
- },
- mountFn: mountExtended,
- });
- mockFormFunctions({ checkValidityReturn: true });
+ it('sets save button `disabled` prop to `true`', () => {
+ expect(findProjectSaveButton().props('disabled')).toBe(true);
+ });
+ });
+
+ describe.each`
+ scenario | replyStatus | errorMessage | expectToast | expectSentry
+ ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
+ ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${'an error'} | ${false}
+ ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
+ `('$scenario', ({ replyStatus, errorMessage, expectToast, expectSentry }) => {
+ beforeEach(async () => {
+ mockAxios.onPut(mockTestPath).replyOnce(replyStatus, {
+ error: Boolean(errorMessage),
+ message: errorMessage,
});
- describe('buttons', () => {
- beforeEach(async () => {
- await findTestButton().vm.$emit('click', new Event('click'));
- });
+ await findTestButton().vm.$emit('click', new Event('click'));
+ await waitForPromises();
+ });
- it('sets test button `loading` prop to `true`', () => {
- expect(findTestButton().props('loading')).toBe(true);
- });
+ it(`calls toast with '${expectToast}'`, () => {
+ expect(mockToastShow).toHaveBeenCalledWith(expectToast);
+ });
- it('sets save button `disabled` prop to `true`', () => {
- expect(findProjectSaveButton().props('disabled')).toBe(true);
- });
- });
+ it('sets `loading` prop of test button to `false`', () => {
+ expect(findTestButton().props('loading')).toBe(false);
+ });
- describe.each`
- scenario | replyStatus | errorMessage | expectToast | expectSentry
- ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
- ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${'an error'} | ${false}
- ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
- `('$scenario', ({ replyStatus, errorMessage, expectToast, expectSentry }) => {
- beforeEach(async () => {
- mockAxios.onPut(mockTestPath).replyOnce(replyStatus, {
- error: Boolean(errorMessage),
- message: errorMessage,
- });
-
- await findTestButton().vm.$emit('click', new Event('click'));
- await waitForPromises();
- });
-
- it(`calls toast with '${expectToast}'`, () => {
- expect(mockToastShow).toHaveBeenCalledWith(expectToast);
- });
-
- it('sets `loading` prop of test button to `false`', () => {
- expect(findTestButton().props('loading')).toBe(false);
- });
-
- it('sets save button `disabled` prop to `false`', () => {
- expect(findProjectSaveButton().props('disabled')).toBe(false);
- });
-
- it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
- expect(Sentry.captureException).toHaveBeenCalledTimes(expectSentry ? 1 : 0);
- });
- });
+ it('sets save button `disabled` prop to `false`', () => {
+ expect(findProjectSaveButton().props('disabled')).toBe(false);
+ });
+
+ it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
+ expect(Sentry.captureException).toHaveBeenCalledTimes(expectSentry ? 1 : 0);
});
});
- },
- );
+ });
+ });
describe('when `reset-confirmation-modal` emits `reset` event', () => {
const mockResetPath = '/reset';
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 b5a8eed3598..33fd08a5959 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,9 +1,8 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
-import eventHub from '~/integrations/edit/event_hub';
import { createStore } from '~/integrations/edit/store';
describe('JiraIssuesFields', () => {
@@ -195,7 +194,7 @@ describe('JiraIssuesFields', () => {
await setEnableCheckbox(true);
expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBe('true');
wrapper.setProps({ showJiraVulnerabilitiesIntegration: false });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBeUndefined();
});
@@ -222,7 +221,7 @@ describe('JiraIssuesFields', () => {
});
describe('Project key input field', () => {
- beforeEach(() => {
+ it('sets Project Key `state` attribute to `true` by default', () => {
createComponent({
props: {
initialProjectKey: '',
@@ -230,29 +229,32 @@ describe('JiraIssuesFields', () => {
},
mountFn: shallowMountExtended,
});
- });
- it('sets Project Key `state` attribute to `true` by default', () => {
assertProjectKeyState('true');
});
- describe('when event hub recieves `VALIDATE_INTEGRATION_FORM_EVENT` event', () => {
+ describe('when `isValidated` prop is true', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ initialProjectKey: '',
+ initialEnableJiraIssues: true,
+ isValidated: true,
+ },
+ mountFn: shallowMountExtended,
+ });
+ });
+
describe('with no project key', () => {
it('sets Project Key `state` attribute to `undefined`', async () => {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
- await wrapper.vm.$nextTick();
-
assertProjectKeyState(undefined);
});
});
describe('when project key is set', () => {
it('sets Project Key `state` attribute to `true`', async () => {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
-
// set the project key
await findProjectKey().vm.$emit('input', 'AB');
- await wrapper.vm.$nextTick();
assertProjectKeyState('true');
});
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 9e01371f542..49fbebb9396 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -1,4 +1,5 @@
import { GlFormCheckbox } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
@@ -71,12 +72,11 @@ describe('JiraTriggerFields', () => {
});
describe('on enable comments', () => {
- it('shows comment detail', () => {
+ it('shows comment detail', async () => {
findCommentSettingsCheckbox().vm.$emit('input', true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findCommentDetail().isVisible()).toBe(true);
- });
+ await nextTick();
+ expect(findCommentDetail().isVisible()).toBe(true);
});
});
});
@@ -107,7 +107,7 @@ describe('JiraTriggerFields', () => {
});
describe('initialJiraIssueTransitionAutomatic is false, initialJiraIssueTransitionId is not set', () => {
- it('selects automatic transitions when enabling transitions', () => {
+ it('selects automatic transitions when enabling transitions', async () => {
createComponent({
initialTriggerCommit: true,
initialEnableComments: true,
@@ -117,11 +117,10 @@ describe('JiraTriggerFields', () => {
expect(checkbox.element.checked).toBe(false);
checkbox.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
- expect(radio1.element.checked).toBe(true);
- expect(radio2.element.checked).toBe(false);
- });
+ await nextTick();
+ const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
+ expect(radio1.element.checked).toBe(true);
+ expect(radio2.element.checked).toBe(false);
});
});
diff --git a/spec/frontend/integrations/edit/mock_data.js b/spec/frontend/integrations/edit/mock_data.js
index 3c45ed0fb1b..39e5f8521e8 100644
--- a/spec/frontend/integrations/edit/mock_data.js
+++ b/spec/frontend/integrations/edit/mock_data.js
@@ -20,3 +20,12 @@ export const mockJiraIssueTypes = [
{ id: '2', name: 'bug', description: 'bug' },
{ id: '3', name: 'epic', description: 'epic' },
];
+
+export const mockField = {
+ help: 'The URL of the project',
+ name: 'project_url',
+ placeholder: 'https://jira.example.com',
+ title: 'Project URL',
+ type: 'text',
+ value: '1',
+};
diff --git a/spec/frontend/invite_members/components/group_select_spec.js b/spec/frontend/invite_members/components/group_select_spec.js
index 2ef8fe07650..192f3fdd381 100644
--- a/spec/frontend/invite_members/components/group_select_spec.js
+++ b/spec/frontend/invite_members/components/group_select_spec.js
@@ -4,14 +4,21 @@ import waitForPromises from 'helpers/wait_for_promises';
import * as groupsApi from '~/api/groups_api';
import GroupSelect from '~/invite_members/components/group_select.vue';
-const createComponent = () => {
- return mount(GroupSelect, {});
-};
-
+const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
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];
+const createComponent = (props = {}) => {
+ return mount(GroupSelect, {
+ propsData: {
+ invalidGroups: [],
+ accessLevels,
+ ...props,
+ },
+ });
+};
+
describe('GroupSelect', () => {
let wrapper;
@@ -61,6 +68,7 @@ describe('GroupSelect', () => {
expect(groupsApi.getGroups).toHaveBeenCalledWith(group1.name, {
active: true,
exclude_internal: true,
+ min_access_level: accessLevels.Guest,
});
});
@@ -83,6 +91,20 @@ describe('GroupSelect', () => {
size: '32',
});
});
+
+ describe('when filtering out the group from results', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ invalidGroups: [group1.id] });
+ });
+
+ it('does not find an invalid group', () => {
+ expect(findAvatarByLabel(group1.full_name)).toBe(undefined);
+ });
+
+ it('finds a group that is valid', () => {
+ expect(findAvatarByLabel(group2.full_name).exists()).toBe(true);
+ });
+ });
});
describe('when group is selected from the dropdown', () => {
diff --git a/spec/frontend/invite_members/components/import_a_project_modal_spec.js b/spec/frontend/invite_members/components/import_a_project_modal_spec.js
index fecbf84fb57..6db881d5c75 100644
--- a/spec/frontend/invite_members/components/import_a_project_modal_spec.js
+++ b/spec/frontend/invite_members/components/import_a_project_modal_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlSprintf, GlModal } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -91,7 +92,7 @@ describe('ImportAProjectModal', () => {
it('sets isLoading to true when the Invite button is clicked', async () => {
clickImportButton();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findImportButton().props('loading')).toBe(true);
});
@@ -157,7 +158,7 @@ describe('ImportAProjectModal', () => {
clickCancelButton();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(formGroupInvalidFeedback()).toBe('');
expect(formGroupErrorState()).not.toBe(false);
diff --git a/spec/frontend/invite_members/components/invite_group_trigger_spec.js b/spec/frontend/invite_members/components/invite_group_trigger_spec.js
index cb9967ebe8c..84ddb779a9e 100644
--- a/spec/frontend/invite_members/components/invite_group_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_group_trigger_spec.js
@@ -44,7 +44,7 @@ describe('InviteGroupTrigger', () => {
});
it('emits event that triggers opening the modal', () => {
- expect(eventHub.$emit).toHaveBeenLastCalledWith('openModal', { inviteeType: 'group' });
+ expect(eventHub.$emit).toHaveBeenLastCalledWith('openGroupModal');
});
});
});
diff --git a/spec/frontend/invite_members/components/invite_groups_modal_spec.js b/spec/frontend/invite_members/components/invite_groups_modal_spec.js
new file mode 100644
index 00000000000..49c55d56080
--- /dev/null
+++ b/spec/frontend/invite_members/components/invite_groups_modal_spec.js
@@ -0,0 +1,143 @@
+import { GlModal, GlSprintf } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import Api from '~/api';
+import InviteGroupsModal from '~/invite_members/components/invite_groups_modal.vue';
+import InviteModalBase from '~/invite_members/components/invite_modal_base.vue';
+import GroupSelect from '~/invite_members/components/group_select.vue';
+import { stubComponent } from 'helpers/stub_component';
+import { propsData, sharedGroup } from '../mock_data/group_modal';
+
+describe('InviteGroupsModal', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMountExtended(InviteGroupsModal, {
+ propsData: {
+ ...propsData,
+ ...props,
+ },
+ stubs: {
+ InviteModalBase,
+ GlSprintf,
+ GlModal: stubComponent(GlModal, {
+ template: '<div><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ });
+ };
+
+ const createInviteGroupToProjectWrapper = () => {
+ createComponent({ isProject: true });
+ };
+
+ const createInviteGroupToGroupWrapper = () => {
+ createComponent({ isProject: false });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGroupSelect = () => wrapper.findComponent(GroupSelect);
+ const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text();
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findInviteButton = () => wrapper.findByTestId('invite-button');
+ const findMembersFormGroup = () => wrapper.findByTestId('members-form-group');
+ const membersFormGroupInvalidFeedback = () =>
+ findMembersFormGroup().attributes('invalid-feedback');
+ const clickInviteButton = () => findInviteButton().vm.$emit('click');
+ const clickCancelButton = () => findCancelButton().vm.$emit('click');
+ const triggerGroupSelect = (val) => findGroupSelect().vm.$emit('input', val);
+
+ describe('displaying the correct introText and form group description', () => {
+ describe('when inviting to a project', () => {
+ it('includes the correct type, and formatted intro text', () => {
+ createInviteGroupToProjectWrapper();
+
+ expect(findIntroText()).toBe("You're inviting a group to the test name project.");
+ });
+ });
+
+ describe('when inviting to a group', () => {
+ it('includes the correct type, and formatted intro text', () => {
+ createInviteGroupToGroupWrapper();
+
+ expect(findIntroText()).toBe("You're inviting a group to the test name group.");
+ });
+ });
+ });
+
+ describe('submitting the invite form', () => {
+ describe('when sharing the group is successful', () => {
+ const groupPostData = {
+ group_id: sharedGroup.id,
+ group_access: propsData.defaultAccessLevel,
+ expires_at: undefined,
+ format: 'json',
+ };
+
+ beforeEach(() => {
+ createComponent();
+ triggerGroupSelect(sharedGroup);
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'groupShareWithGroup').mockResolvedValue({ data: groupPostData });
+
+ clickInviteButton();
+ });
+
+ it('calls Api groupShareWithGroup with the correct params', () => {
+ expect(Api.groupShareWithGroup).toHaveBeenCalledWith(propsData.id, groupPostData);
+ });
+
+ it('displays the successful toastMessage', () => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
+ });
+ });
+
+ describe('when sharing the group fails', () => {
+ beforeEach(() => {
+ createInviteGroupToGroupWrapper();
+ triggerGroupSelect(sharedGroup);
+
+ wrapper.vm.$toast = { show: jest.fn() };
+
+ jest
+ .spyOn(Api, 'groupShareWithGroup')
+ .mockRejectedValue({ response: { data: { success: false } } });
+
+ clickInviteButton();
+ });
+
+ it('does not show the toast message on failure', () => {
+ expect(wrapper.vm.$toast.show).not.toHaveBeenCalled();
+ });
+
+ it('displays the generic error for http server error', () => {
+ expect(membersFormGroupInvalidFeedback()).toBe('Something went wrong');
+ });
+
+ describe('clearing the invalid state and message', () => {
+ it('clears the error when the cancel button is clicked', async () => {
+ clickCancelButton();
+
+ await nextTick();
+
+ expect(membersFormGroupInvalidFeedback()).toBe('');
+ });
+
+ it('clears the error when the modal is hidden', async () => {
+ wrapper.findComponent(GlModal).vm.$emit('hide');
+
+ await nextTick();
+
+ expect(membersFormGroupInvalidFeedback()).toBe('');
+ });
+ });
+ });
+ });
+});
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 3ab89b3dff2..15a366474e4 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -1,28 +1,19 @@
-import {
- GlDropdown,
- GlDropdownItem,
- GlDatepicker,
- GlFormGroup,
- GlSprintf,
- GlLink,
- GlModal,
-} from '@gitlab/ui';
+import { GlLink, GlModal, GlSprintf } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
+import InviteModalBase from '~/invite_members/components/invite_modal_base.vue';
import ModalConfetti from '~/invite_members/components/confetti.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import {
INVITE_MEMBERS_FOR_TASK,
- CANCEL_BUTTON_TEXT,
- INVITE_BUTTON_TEXT,
MEMBERS_MODAL_CELEBRATE_INTRO,
MEMBERS_MODAL_CELEBRATE_TITLE,
- MEMBERS_MODAL_DEFAULT_TITLE,
MEMBERS_PLACEHOLDER,
MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
LEARN_GITLAB,
@@ -32,9 +23,16 @@ import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import { getParameterValues } from '~/lib/utils/url_utility';
import { apiPaths, membersApiResponse, invitationsApiResponse } from '../mock_data/api_responses';
-
-let wrapper;
-let mock;
+import {
+ propsData,
+ inviteSource,
+ newProjectPath,
+ user1,
+ user2,
+ user3,
+ user4,
+ GlEmoji,
+} from '../mock_data/member_modal';
jest.mock('~/experimentation/experiment_tracking');
jest.mock('~/lib/utils/url_utility', () => ({
@@ -42,211 +40,125 @@ jest.mock('~/lib/utils/url_utility', () => ({
getParameterValues: jest.fn(() => []),
}));
-const id = '1';
-const name = 'test name';
-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 tasksToBeDoneOptions = [
- { text: 'First task', value: 'first' },
- { text: 'Second task', value: 'second' },
-];
-const newProjectPath = 'projects/new';
-const projects = [
- { text: 'First project', value: '1' },
- { text: 'Second project', value: '2' },
-];
-
-const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
-const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' };
-const user3 = {
- id: 'user-defined-token',
- name: 'email@example.com',
- username: 'one_2',
- avatar_url: '',
-};
-const user4 = {
- id: 'user-defined-token',
- name: 'email4@example.com',
- username: 'one_4',
- avatar_url: '',
-};
-const sharedGroup = { id: '981' };
-const GlEmoji = { template: '<img/>' };
-
-const createComponent = (data = {}, props = {}) => {
- wrapper = shallowMountExtended(InviteMembersModal, {
- provide: {
- newProjectPath,
- },
- propsData: {
- id,
- name,
- isProject,
- inviteeType,
- accessLevels,
- defaultAccessLevel,
- tasksToBeDoneOptions,
- projects,
- helpLink,
- ...props,
- },
- data() {
- return data;
- },
- stubs: {
- GlModal: stubComponent(GlModal, {
- template:
- '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
- }),
- GlDropdown: true,
- GlDropdownItem: true,
- GlEmoji,
- GlSprintf,
- GlFormGroup: stubComponent(GlFormGroup, {
- props: ['state', 'invalidFeedback', 'description'],
- }),
- },
- });
-};
-
-const createInviteMembersToProjectWrapper = () => {
- createComponent({ inviteeType: 'members' }, { isProject: true });
-};
-
-const createInviteMembersToGroupWrapper = () => {
- createComponent({ inviteeType: 'members' }, { isProject: false });
-};
+describe('InviteMembersModal', () => {
+ let wrapper;
+ let mock;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMountExtended(InviteMembersModal, {
+ provide: {
+ newProjectPath,
+ },
+ propsData: {
+ ...propsData,
+ ...props,
+ },
+ stubs: {
+ InviteModalBase,
+ GlSprintf,
+ GlModal: stubComponent(GlModal, {
+ template: '<div><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ GlEmoji,
+ },
+ });
+ };
-const createInviteGroupToProjectWrapper = () => {
- createComponent({ inviteeType: 'group' }, { isProject: true });
-};
+ const createInviteMembersToProjectWrapper = () => {
+ createComponent({ isProject: true });
+ };
-const createInviteGroupToGroupWrapper = () => {
- createComponent({ inviteeType: 'group' }, { isProject: false });
-};
+ const createInviteMembersToGroupWrapper = () => {
+ createComponent({ isProject: false });
+ };
-beforeEach(() => {
- gon.api_version = 'v4';
- mock = new MockAdapter(axios);
-});
+ beforeEach(() => {
+ gon.api_version = 'v4';
+ mock = new MockAdapter(axios);
+ });
-afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- mock.restore();
-});
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mock.restore();
+ });
-describe('InviteMembersModal', () => {
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDropdownItems = () => findDropdown().findAllComponents(GlDropdownItem);
- const findDatepicker = () => wrapper.findComponent(GlDatepicker);
- const findLink = () => wrapper.findComponent(GlLink);
- const findIntroText = () => wrapper.find({ ref: 'introText' }).text();
+ const findBase = () => wrapper.findComponent(InviteModalBase);
+ const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text();
const findCancelButton = () => wrapper.findByTestId('cancel-button');
const findInviteButton = () => wrapper.findByTestId('invite-button');
const clickInviteButton = () => findInviteButton().vm.$emit('click');
const clickCancelButton = () => findCancelButton().vm.$emit('click');
const findMembersFormGroup = () => wrapper.findByTestId('members-form-group');
- const membersFormGroupInvalidFeedback = () => findMembersFormGroup().props('invalidFeedback');
- const membersFormGroupDescription = () => findMembersFormGroup().props('description');
+ const membersFormGroupInvalidFeedback = () =>
+ findMembersFormGroup().attributes('invalid-feedback');
+ const membersFormGroupDescription = () => findMembersFormGroup().attributes('description');
const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect);
const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done');
const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks');
const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select');
const findNoProjectsAlert = () => wrapper.findByTestId('invite-members-modal-no-projects-alert');
- const findCelebrationEmoji = () => wrapper.findComponent(GlModal).find(GlEmoji);
-
- describe('rendering the modal', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders the modal with the correct title', () => {
- expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_DEFAULT_TITLE);
- });
-
- it('renders the Cancel button text correctly', () => {
- expect(findCancelButton().text()).toBe(CANCEL_BUTTON_TEXT);
- });
-
- it('renders the Invite button text correctly', () => {
- expect(findInviteButton().text()).toBe(INVITE_BUTTON_TEXT);
- });
-
- it('renders the Invite button modal without isLoading', () => {
- expect(findInviteButton().props('loading')).toBe(false);
- });
-
- describe('rendering the access levels dropdown', () => {
- it('sets the default dropdown text to the default access level name', () => {
- expect(findDropdown().attributes('text')).toBe('Guest');
- });
-
- it('renders dropdown items for each accessLevel', () => {
- expect(findDropdownItems()).toHaveLength(5);
- });
- });
-
- describe('rendering the help link', () => {
- it('renders the correct link', () => {
- expect(findLink().attributes('href')).toBe(helpLink);
- });
- });
-
- describe('rendering the access expiration date field', () => {
- it('renders the datepicker', () => {
- expect(findDatepicker().exists()).toBe(true);
- });
- });
- });
+ const findCelebrationEmoji = () => wrapper.findComponent(GlEmoji);
+ const triggerOpenModal = async ({ mode = 'default', source }) => {
+ eventHub.$emit('openModal', { mode, source });
+ await nextTick();
+ };
+ const triggerMembersTokenSelect = async (val) => {
+ findMembersSelect().vm.$emit('input', val);
+ await nextTick();
+ };
+ const triggerTasks = async (val) => {
+ findTasks().vm.$emit('input', val);
+ await nextTick();
+ };
+ const triggerAccessLevel = async (val) => {
+ findBase().vm.$emit('access-level', val);
+ await nextTick();
+ };
describe('rendering the tasks to be done', () => {
- const setupComponent = (
- extraData = {},
- props = {},
- urlParameter = ['invite_members_for_task'],
- ) => {
- const data = {
- selectedAccessLevel: 30,
- selectedTasksToBeDone: ['ci', 'code'],
- ...extraData,
- };
+ const setupComponent = async (props = {}, urlParameter = ['invite_members_for_task']) => {
getParameterValues.mockImplementation(() => urlParameter);
- createComponent(data, props);
+ createComponent(props);
+
+ await triggerAccessLevel(30);
+ };
+
+ const setupComponentWithTasks = async (...args) => {
+ await setupComponent(...args);
+ await triggerTasks(['ci', 'code']);
};
afterAll(() => {
getParameterValues.mockImplementation(() => []);
});
- it('renders the tasks to be done', () => {
- setupComponent();
+ it('renders the tasks to be done', async () => {
+ await setupComponent();
expect(findTasksToBeDone().exists()).toBe(true);
});
describe('when the selected access level is lower than 30', () => {
- it('does not render the tasks to be done', () => {
- setupComponent({ selectedAccessLevel: 20 });
+ it('does not render the tasks to be done', async () => {
+ await setupComponent();
+ await triggerAccessLevel(20);
expect(findTasksToBeDone().exists()).toBe(false);
});
});
describe('when the url does not contain the parameter `open_modal=invite_members_for_task`', () => {
- it('does not render the tasks to be done', () => {
- setupComponent({}, {}, []);
+ it('does not render the tasks to be done', async () => {
+ await setupComponent({}, []);
expect(findTasksToBeDone().exists()).toBe(false);
});
describe('when opened from the Learn GitLab page', () => {
- it('does render the tasks to be done', () => {
- setupComponent({ source: LEARN_GITLAB }, {}, []);
+ it('does render the tasks to be done', async () => {
+ await setupComponent({}, []);
+ await triggerOpenModal({ source: LEARN_GITLAB });
expect(findTasksToBeDone().exists()).toBe(true);
});
@@ -254,27 +166,27 @@ describe('InviteMembersModal', () => {
});
describe('rendering the tasks', () => {
- it('renders the tasks', () => {
- setupComponent();
+ it('renders the tasks', async () => {
+ await setupComponent();
expect(findTasks().exists()).toBe(true);
});
- it('does not render an alert', () => {
- setupComponent();
+ it('does not render an alert', async () => {
+ await setupComponent();
expect(findNoProjectsAlert().exists()).toBe(false);
});
describe('when there are no projects passed in the data', () => {
- it('does not render the tasks', () => {
- setupComponent({}, { projects: [] });
+ it('does not render the tasks', async () => {
+ await setupComponent({ projects: [] });
expect(findTasks().exists()).toBe(false);
});
- it('renders an alert with a link to the new projects path', () => {
- setupComponent({}, { projects: [] });
+ it('renders an alert with a link to the new projects path', async () => {
+ await setupComponent({ projects: [] });
expect(findNoProjectsAlert().exists()).toBe(true);
expect(findNoProjectsAlert().findComponent(GlLink).attributes('href')).toBe(
@@ -285,23 +197,23 @@ describe('InviteMembersModal', () => {
});
describe('rendering the project dropdown', () => {
- it('renders the project select', () => {
- setupComponent();
+ it('renders the project select', async () => {
+ await setupComponentWithTasks();
expect(findProjectSelect().exists()).toBe(true);
});
describe('when the modal is shown for a project', () => {
- it('does not render the project select', () => {
- setupComponent({}, { isProject: true });
+ it('does not render the project select', async () => {
+ await setupComponentWithTasks({ isProject: true });
expect(findProjectSelect().exists()).toBe(false);
});
});
describe('when no tasks are selected', () => {
- it('does not render the project select', () => {
- setupComponent({ selectedTasksToBeDone: [] });
+ it('does not render the project select', async () => {
+ await setupComponent();
expect(findProjectSelect().exists()).toBe(false);
});
@@ -309,8 +221,8 @@ describe('InviteMembersModal', () => {
});
describe('tracking events', () => {
- it('tracks the view for invite_members_for_task', () => {
- setupComponent();
+ it('tracks the view for invite_members_for_task', async () => {
+ await setupComponentWithTasks();
expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
@@ -318,8 +230,8 @@ describe('InviteMembersModal', () => {
);
});
- it('tracks the submit for invite_members_for_task', () => {
- setupComponent();
+ it('tracks the submit for invite_members_for_task', async () => {
+ await setupComponentWithTasks();
clickInviteButton();
expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, {
@@ -352,8 +264,9 @@ describe('InviteMembersModal', () => {
});
describe('when inviting members with celebration', () => {
- beforeEach(() => {
- createComponent({ mode: 'celebrate', inviteeType: 'members' }, { isProject: true });
+ beforeEach(async () => {
+ createComponent({ isProject: true });
+ await triggerOpenModal({ mode: 'celebrate' });
});
it('renders the modal with confetti', () => {
@@ -372,34 +285,14 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
-
- describe('when sharing with a group', () => {
- it('includes the correct invitee, type, and formatted name', () => {
- createInviteGroupToProjectWrapper();
-
- expect(findIntroText()).toBe("You're inviting a group to the test name project.");
- expect(membersFormGroupDescription()).toBe('');
- });
- });
});
describe('when inviting to a group', () => {
- describe('when inviting members', () => {
- it('includes the correct invitee, type, and formatted name', () => {
- createInviteMembersToGroupWrapper();
-
- expect(findIntroText()).toBe("You're inviting members to the test name group.");
- expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
- });
- });
-
- describe('when sharing with a group', () => {
- it('includes the correct invitee, type, and formatted name', () => {
- createInviteGroupToGroupWrapper();
+ it('includes the correct invitee, type, and formatted name', () => {
+ createInviteMembersToGroupWrapper();
- expect(findIntroText()).toBe("You're inviting a group to the test name group.");
- expect(membersFormGroupDescription()).toBe('');
- });
+ expect(findIntroText()).toBe("You're inviting members to the test name group.");
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
});
@@ -419,7 +312,7 @@ describe('InviteMembersModal', () => {
describe('when inviting an existing user to group by user ID', () => {
const postData = {
user_id: '1,2',
- access_level: defaultAccessLevel,
+ access_level: propsData.defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
@@ -428,8 +321,9 @@ describe('InviteMembersModal', () => {
};
describe('when member is added successfully', () => {
- beforeEach(() => {
- createComponent({ newUsersToInvite: [user1, user2] });
+ beforeEach(async () => {
+ createComponent();
+ await triggerMembersTokenSelect([user1, user2]);
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
@@ -445,19 +339,17 @@ describe('InviteMembersModal', () => {
});
it('calls Api addGroupMembersByUserId with the correct params', () => {
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, postData);
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, postData);
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
- onComplete: expect.any(Function),
- });
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added');
});
});
describe('when opened from a Learn GitLab page', () => {
it('emits the `showSuccessfulInvitationsAlert` event', async () => {
- eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
+ await triggerOpenModal({ source: LEARN_GITLAB });
jest.spyOn(eventHub, '$emit').mockImplementation();
@@ -471,12 +363,10 @@ describe('InviteMembersModal', () => {
});
describe('when member is not added successfully', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createInviteMembersToGroupWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ newUsersToInvite: [user1] });
+ await triggerMembersTokenSelect([user1]);
});
it('displays "Member already exists" api message for http status conflict', async () => {
@@ -487,7 +377,6 @@ describe('InviteMembersModal', () => {
await waitForPromises();
expect(membersFormGroupInvalidFeedback()).toBe('Member already exists');
- expect(findMembersFormGroup().props('state')).toBe(false);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
});
@@ -503,35 +392,31 @@ describe('InviteMembersModal', () => {
it('clears the error when the list of members to invite is cleared', async () => {
expect(membersFormGroupInvalidFeedback()).toBe('Member already exists');
- expect(findMembersFormGroup().props('state')).toBe(false);
expect(findMembersSelect().props('validationState')).toBe(false);
findMembersSelect().vm.$emit('clear');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
- expect(findMembersFormGroup().props('state')).not.toBe(false);
expect(findMembersSelect().props('validationState')).not.toBe(false);
});
it('clears the error when the cancel button is clicked', async () => {
clickCancelButton();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
- expect(findMembersFormGroup().props('state')).not.toBe(false);
expect(findMembersSelect().props('validationState')).not.toBe(false);
});
it('clears the error when the modal is hidden', async () => {
wrapper.findComponent(GlModal).vm.$emit('hide');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
- expect(findMembersFormGroup().props('state')).not.toBe(false);
expect(findMembersSelect().props('validationState')).not.toBe(false);
});
});
@@ -544,7 +429,6 @@ describe('InviteMembersModal', () => {
await waitForPromises();
expect(membersFormGroupInvalidFeedback()).toBe('Member already exists');
- expect(findMembersFormGroup().props('state')).toBe(false);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
@@ -553,8 +437,7 @@ describe('InviteMembersModal', () => {
await waitForPromises();
expect(membersFormGroupInvalidFeedback()).toBe('');
- expect(findMembersFormGroup().props('state')).not.toBe(false);
- expect(findMembersSelect().props('validationState')).not.toBe(false);
+ expect(findMembersSelect().props('validationState')).toBe(null);
expect(findInviteButton().props('loading')).toBe(false);
});
@@ -608,7 +491,7 @@ describe('InviteMembersModal', () => {
describe('when inviting a new user by email address', () => {
const postData = {
- access_level: defaultAccessLevel,
+ access_level: propsData.defaultAccessLevel,
expires_at: undefined,
email: 'email@example.com',
invite_source: inviteSource,
@@ -618,8 +501,9 @@ describe('InviteMembersModal', () => {
};
describe('when invites are sent successfully', () => {
- beforeEach(() => {
- createComponent({ newUsersToInvite: [user3] });
+ beforeEach(async () => {
+ createComponent();
+ await triggerMembersTokenSelect([user3]);
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
@@ -631,24 +515,20 @@ describe('InviteMembersModal', () => {
});
it('calls Api inviteGroupMembersByEmail with the correct params', () => {
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, postData);
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, postData);
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
- onComplete: expect.any(Function),
- });
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added');
});
});
});
describe('when invites are not sent successfully', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createInviteMembersToGroupWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ newUsersToInvite: [user3] });
+ await triggerMembersTokenSelect([user3]);
});
it('displays the api error for invalid email syntax', async () => {
@@ -683,9 +563,7 @@ describe('InviteMembersModal', () => {
await waitForPromises();
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
- onComplete: expect.any(Function),
- });
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added');
expect(findMembersSelect().props('validationState')).toBe(null);
});
@@ -716,9 +594,7 @@ describe('InviteMembersModal', () => {
it('displays the invalid syntax error if one of the emails is invalid', async () => {
createInviteMembersToGroupWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ newUsersToInvite: [user3, user4] });
+ await triggerMembersTokenSelect([user3, user4]);
mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.ERROR_EMAIL_INVALID);
clickInviteButton();
@@ -733,7 +609,7 @@ describe('InviteMembersModal', () => {
describe('when inviting members and non-members in same click', () => {
const postData = {
- access_level: defaultAccessLevel,
+ access_level: propsData.defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
@@ -745,8 +621,9 @@ describe('InviteMembersModal', () => {
const idPostData = { ...postData, user_id: '1' };
describe('when invites are sent successfully', () => {
- beforeEach(() => {
- createComponent({ newUsersToInvite: [user1, user3] });
+ beforeEach(async () => {
+ createComponent();
+ await triggerMembersTokenSelect([user1, user3]);
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
@@ -759,30 +636,28 @@ describe('InviteMembersModal', () => {
});
it('calls Api inviteGroupMembersByEmail with the correct params', () => {
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, emailPostData);
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, emailPostData);
});
it('calls Api addGroupMembersByUserId with the correct params', () => {
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, idPostData);
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, idPostData);
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
- onComplete: expect.any(Function),
- });
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added');
});
});
- it('calls Apis with the invite source passed through to openModal', () => {
- eventHub.$emit('openModal', { inviteeType: 'members', source: '_invite_source_' });
+ it('calls Apis with the invite source passed through to openModal', async () => {
+ await triggerOpenModal({ source: '_invite_source_' });
clickInviteButton();
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, {
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, {
...emailPostData,
invite_source: '_invite_source_',
});
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, {
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, {
...idPostData,
invite_source: '_invite_source_',
});
@@ -790,12 +665,10 @@ describe('InviteMembersModal', () => {
});
describe('when any invite failed for any reason', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createInviteMembersToGroupWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ newUsersToInvite: [user1, user3] });
+ await triggerMembersTokenSelect([user1, user3]);
mockInvitationsApi(httpStatus.BAD_REQUEST, invitationsApiResponse.EMAIL_INVALID);
mockMembersApi(httpStatus.OK, '200 OK');
@@ -811,71 +684,17 @@ describe('InviteMembersModal', () => {
});
});
- describe('when inviting a group to share', () => {
- describe('when sharing the group is successful', () => {
- const groupPostData = {
- group_id: sharedGroup.id,
- group_access: defaultAccessLevel,
- expires_at: undefined,
- format: 'json',
- };
-
- beforeEach(() => {
- createComponent({ groupToBeSharedWith: sharedGroup });
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ inviteeType: 'group' });
- wrapper.vm.$toast = { show: jest.fn() };
- jest.spyOn(Api, 'groupShareWithGroup').mockResolvedValue({ data: groupPostData });
-
- clickInviteButton();
- });
-
- it('calls Api groupShareWithGroup with the correct params', () => {
- expect(Api.groupShareWithGroup).toHaveBeenCalledWith(id, groupPostData);
- });
-
- it('displays the successful toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
- onComplete: expect.any(Function),
- });
- });
- });
-
- describe('when sharing the group fails', () => {
- beforeEach(() => {
- createInviteGroupToGroupWrapper();
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ groupToBeSharedWith: sharedGroup });
- wrapper.vm.$toast = { show: jest.fn() };
-
- jest
- .spyOn(Api, 'groupShareWithGroup')
- .mockRejectedValue({ response: { data: { success: false } } });
-
- clickInviteButton();
- });
-
- it('displays the generic error message', () => {
- expect(membersFormGroupInvalidFeedback()).toBe('Something went wrong');
- expect(membersFormGroupDescription()).toBe('');
- });
- });
- });
-
describe('tracking', () => {
- beforeEach(() => {
- createComponent({ newUsersToInvite: [user3] });
+ beforeEach(async () => {
+ createComponent();
+ await triggerMembersTokenSelect([user3]);
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({});
});
it('tracks the view for learn_gitlab source', () => {
- eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
+ eventHub.$emit('openModal', { source: LEARN_GITLAB });
expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(LEARN_GITLAB);
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 429b6fad24a..28402c8331c 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -71,7 +71,6 @@ describe.each(triggerItems)('with triggerElement as %s', (triggerItem) => {
findButton().vm.$emit('click');
expect(spy).toHaveBeenCalledWith('openModal', {
- inviteeType: 'members',
source: triggerSource,
});
});
diff --git a/spec/frontend/invite_members/components/invite_modal_base_spec.js b/spec/frontend/invite_members/components/invite_modal_base_spec.js
new file mode 100644
index 00000000000..4b183bfd670
--- /dev/null
+++ b/spec/frontend/invite_members/components/invite_modal_base_spec.js
@@ -0,0 +1,103 @@
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDatepicker,
+ GlFormGroup,
+ GlSprintf,
+ GlLink,
+ GlModal,
+} from '@gitlab/ui';
+import { stubComponent } from 'helpers/stub_component';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import InviteModalBase from '~/invite_members/components/invite_modal_base.vue';
+import { CANCEL_BUTTON_TEXT, INVITE_BUTTON_TEXT } from '~/invite_members/constants';
+import { propsData } from '../mock_data/modal_base';
+
+describe('InviteModalBase', () => {
+ let wrapper;
+
+ const createComponent = (data = {}, props = {}) => {
+ wrapper = shallowMountExtended(InviteModalBase, {
+ propsData: {
+ ...propsData,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ GlDropdown: true,
+ GlDropdownItem: true,
+ GlSprintf,
+ GlFormGroup: stubComponent(GlFormGroup, {
+ props: ['state', 'invalidFeedback', 'description'],
+ }),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => findDropdown().findAllComponents(GlDropdownItem);
+ const findDatepicker = () => wrapper.findComponent(GlDatepicker);
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text();
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findInviteButton = () => wrapper.findByTestId('invite-button');
+
+ describe('rendering the modal', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the modal with the correct title', () => {
+ expect(wrapper.findComponent(GlModal).props('title')).toBe(propsData.modalTitle);
+ });
+
+ it('displays the introText', () => {
+ expect(findIntroText()).toBe(propsData.labelIntroText);
+ });
+
+ it('renders the Cancel button text correctly', () => {
+ expect(findCancelButton().text()).toBe(CANCEL_BUTTON_TEXT);
+ });
+
+ it('renders the Invite button text correctly', () => {
+ expect(findInviteButton().text()).toBe(INVITE_BUTTON_TEXT);
+ });
+
+ it('renders the Invite button modal without isLoading', () => {
+ expect(findInviteButton().props('loading')).toBe(false);
+ });
+
+ describe('rendering the access levels dropdown', () => {
+ it('sets the default dropdown text to the default access level name', () => {
+ expect(findDropdown().attributes('text')).toBe('Guest');
+ });
+
+ it('renders dropdown items for each accessLevel', () => {
+ expect(findDropdownItems()).toHaveLength(5);
+ });
+ });
+
+ describe('rendering the help link', () => {
+ it('renders the correct link', () => {
+ expect(findLink().attributes('href')).toBe(propsData.helpLink);
+ });
+ });
+
+ describe('rendering the access expiration date field', () => {
+ it('renders the datepicker', () => {
+ expect(findDatepicker().exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/invite_members/mock_data/group_modal.js b/spec/frontend/invite_members/mock_data/group_modal.js
new file mode 100644
index 00000000000..c05c4edb7d0
--- /dev/null
+++ b/spec/frontend/invite_members/mock_data/group_modal.js
@@ -0,0 +1,11 @@
+export const propsData = {
+ id: '1',
+ name: 'test name',
+ isProject: false,
+ invalidGroups: [],
+ accessLevels: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
+ defaultAccessLevel: 10,
+ helpLink: 'https://example.com',
+};
+
+export const sharedGroup = { id: '981' };
diff --git a/spec/frontend/invite_members/mock_data/member_modal.js b/spec/frontend/invite_members/mock_data/member_modal.js
new file mode 100644
index 00000000000..590502909b2
--- /dev/null
+++ b/spec/frontend/invite_members/mock_data/member_modal.js
@@ -0,0 +1,36 @@
+export const propsData = {
+ id: '1',
+ name: 'test name',
+ isProject: false,
+ accessLevels: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
+ defaultAccessLevel: 30,
+ helpLink: 'https://example.com',
+ tasksToBeDoneOptions: [
+ { text: 'First task', value: 'first' },
+ { text: 'Second task', value: 'second' },
+ ],
+ projects: [
+ { text: 'First project', value: '1' },
+ { text: 'Second project', value: '2' },
+ ],
+};
+
+export const inviteSource = 'unknown';
+export const newProjectPath = 'projects/new';
+
+export const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
+export const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' };
+export const user3 = {
+ id: 'user-defined-token',
+ name: 'email@example.com',
+ username: 'one_2',
+ avatar_url: '',
+};
+export const user4 = {
+ id: 'user-defined-token',
+ name: 'email4@example.com',
+ username: 'one_4',
+ avatar_url: '',
+};
+
+export const GlEmoji = { template: '<img/>' };
diff --git a/spec/frontend/invite_members/mock_data/modal_base.js b/spec/frontend/invite_members/mock_data/modal_base.js
new file mode 100644
index 00000000000..ea5a8d2b00d
--- /dev/null
+++ b/spec/frontend/invite_members/mock_data/modal_base.js
@@ -0,0 +1,11 @@
+export const propsData = {
+ modalTitle: '_modal_title_',
+ modalId: '_modal_id_',
+ name: '_name_',
+ accessLevels: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
+ defaultAccessLevel: 10,
+ helpLink: 'https://example.com',
+ labelIntroText: '_label_intro_text_',
+ labelSearchField: '_label_search_field_',
+ formGroupDescription: '_form_group_description_',
+};
diff --git a/spec/frontend/issuable/components/issue_milestone_spec.js b/spec/frontend/issuable/components/issue_milestone_spec.js
index 44416676180..9d67f602136 100644
--- a/spec/frontend/issuable/components/issue_milestone_spec.js
+++ b/spec/frontend/issuable/components/issue_milestone_spec.js
@@ -1,6 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { mockMilestone } from 'jest/boards/mock_data';
import IssueMilestone from '~/issuable/components/issue_milestone.vue';
@@ -19,12 +19,12 @@ describe('IssueMilestoneComponent', () => {
let wrapper;
let vm;
- beforeEach((done) => {
+ beforeEach(async () => {
wrapper = createComponent();
({ vm } = wrapper);
- Vue.nextTick(done);
+ await nextTick();
});
afterEach(() => {
@@ -37,7 +37,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, start_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isMilestoneStarted).toBe(false);
});
@@ -46,7 +46,7 @@ describe('IssueMilestoneComponent', () => {
await wrapper.setProps({
milestone: { ...mockMilestone, start_date: '1990-07-22' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isMilestoneStarted).toBe(true);
});
@@ -57,7 +57,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, due_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isMilestonePastDue).toBe(false);
});
@@ -80,7 +80,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, due_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)');
});
@@ -89,7 +89,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, start_date: '', due_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesAbsolute).toBe('');
});
@@ -100,7 +100,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, due_date: `${new Date().getFullYear() + 10}-01-01` },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining');
});
@@ -109,7 +109,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, start_date: '1990-07-22', due_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesHuman).toContain('Started');
});
@@ -122,7 +122,7 @@ describe('IssueMilestoneComponent', () => {
due_date: '',
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesHuman).toContain('Starts');
});
@@ -131,7 +131,7 @@ describe('IssueMilestoneComponent', () => {
wrapper.setProps({
milestone: { ...mockMilestone, start_date: '', due_date: '' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.milestoneDatesHuman).toBe('');
});
diff --git a/spec/frontend/issuable/components/related_issuable_item_spec.js b/spec/frontend/issuable/components/related_issuable_item_spec.js
index 6a896ccd21a..6b48f83041a 100644
--- a/spec/frontend/issuable/components/related_issuable_item_spec.js
+++ b/spec/frontend/issuable/components/related_issuable_item_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
@@ -105,7 +106,7 @@ describe('RelatedIssuableItem', () => {
state: 'closed',
closedAt: '2018-12-01T00:00:00.00Z',
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true);
});
@@ -140,7 +141,7 @@ describe('RelatedIssuableItem', () => {
closedAt: '2018-12-01T00:00:00.00Z',
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(IssueDueDate).props('closed')).toBe(true);
});
@@ -172,14 +173,14 @@ describe('RelatedIssuableItem', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ removeDisabled: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
});
it('triggers onRemoveRequest when clicked', async () => {
findRemoveButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
const { relatedIssueRemoveRequest } = wrapper.emitted();
expect(relatedIssueRemoveRequest.length).toBe(1);
diff --git a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
index ff6922989cb..ce98a16dbb7 100644
--- a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
+++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
@@ -1,4 +1,6 @@
+import { GlFormGroup } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
import IssueToken from '~/related_issues/components/issue_token.vue';
import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
@@ -152,6 +154,30 @@ describe('AddIssuableForm', () => {
});
});
+ describe('categorized issuables', () => {
+ it.each`
+ issuableType | pathIdSeparator | contextHeader | contextFooter
+ ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issue(s)'}
+ ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epic(s)'}
+ `(
+ 'show header text as "$contextHeader" and footer text as "$contextFooter" issuableType is set to $issuableType',
+ ({ issuableType, contextHeader, contextFooter }) => {
+ wrapper = shallowMount(AddIssuableForm, {
+ propsData: {
+ issuableType,
+ inputValue: '',
+ showCategorizedIssues: true,
+ pathIdSeparator,
+ pendingReferences: [],
+ },
+ });
+
+ expect(wrapper.findComponent(GlFormGroup).attributes('label')).toBe(contextHeader);
+ expect(wrapper.find('p.bold').text()).toContain(contextFooter);
+ },
+ );
+ });
+
describe('when it is a Linked Issues form', () => {
beforeEach(() => {
wrapper = mount(AddIssuableForm, {
@@ -194,63 +220,55 @@ describe('AddIssuableForm', () => {
});
describe('when the form is submitted', () => {
- it('emits an event with a "relates_to" link type when the "relates to" radio input selected', (done) => {
+ it('emits an event with a "relates_to" link type when the "relates to" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO;
wrapper.vm.onFormSubmit();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
- pendingReferences: '',
- linkedIssueType: linkedIssueTypesMap.RELATES_TO,
- });
- done();
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.RELATES_TO,
});
});
- it('emits an event with a "blocks" link type when the "blocks" radio input selected', (done) => {
+ it('emits an event with a "blocks" link type when the "blocks" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS;
wrapper.vm.onFormSubmit();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
- pendingReferences: '',
- linkedIssueType: linkedIssueTypesMap.BLOCKS,
- });
- done();
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.BLOCKS,
});
});
- it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', (done) => {
+ it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY;
wrapper.vm.onFormSubmit();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
- pendingReferences: '',
- linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY,
- });
- done();
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY,
});
});
- it('shows error message when error is present', (done) => {
+ it('shows error message when error is present', async () => {
const itemAddFailureMessage = 'Something went wrong while submitting.';
wrapper.setProps({
hasError: true,
itemAddFailureMessage,
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.gl-field-error').exists()).toBe(true);
- expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage);
- done();
- });
+ await nextTick();
+ expect(wrapper.find('.gl-field-error').exists()).toBe(true);
+ expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage);
});
});
});
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
index 608fec45bbd..c7925034eb0 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -7,6 +7,7 @@ import {
} from 'jest/issuable/components/related_issuable_mock_data';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import {
+ issuableTypesMap,
linkedIssueTypesMap,
linkedIssueTypesTextMap,
PathIdSeparator,
@@ -29,14 +30,34 @@ describe('RelatedIssuesBlock', () => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
- issuableType: 'issue',
+ issuableType: issuableTypesMap.ISSUE,
},
});
});
- it('displays "Linked issues" in the header', () => {
- expect(wrapper.find('.card-title').text()).toContain('Linked issues');
- });
+ it.each`
+ issuableType | pathIdSeparator | titleText | helpLinkText | addButtonText
+ ${'issue'} | ${PathIdSeparator.Issue} | ${'Linked issues'} | ${'Read more about related issues'} | ${'Add a related issue'}
+ ${'epic'} | ${PathIdSeparator.Epic} | ${'Linked epics'} | ${'Read more about related epics'} | ${'Add a related epic'}
+ `(
+ 'displays "$titleText" in the header, "$helpLinkText" aria-label for help link, and "$addButtonText" aria-label for add button when issuableType is set to "$issuableType"',
+ ({ issuableType, pathIdSeparator, titleText, helpLinkText, addButtonText }) => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator,
+ issuableType,
+ canAdmin: true,
+ helpPath: '/help/user/project/issues/related_issues',
+ },
+ });
+
+ expect(wrapper.find('.card-title').text()).toContain(titleText);
+ expect(wrapper.find('[data-testid="help-link"]').attributes('aria-label')).toBe(
+ helpLinkText,
+ );
+ expect(findIssueCountBadgeAddButton().attributes('aria-label')).toBe(addButtonText);
+ },
+ );
it('unable to add new related issues', () => {
expect(findIssueCountBadgeAddButton().exists()).toBe(false);
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 01de4da7900..b59717a1f60 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
@@ -1,5 +1,6 @@
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import {
defaultProps,
@@ -210,40 +211,37 @@ describe('RelatedIssuesRoot', () => {
}),
);
- it('when canceling and hiding add issuable form', () => {
+ it('when canceling and hiding add issuable form', async () => {
wrapper.vm.onPendingFormCancel();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.isFormVisible).toEqual(false);
- expect(wrapper.vm.inputValue).toEqual('');
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
- });
+ await nextTick();
+ expect(wrapper.vm.isFormVisible).toEqual(false);
+ expect(wrapper.vm.inputValue).toEqual('');
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
});
});
describe('fetchRelatedIssues', () => {
beforeEach(() => createComponent());
- it('sets isFetching while fetching', () => {
+ it('sets isFetching while fetching', async () => {
wrapper.vm.fetchRelatedIssues();
expect(wrapper.vm.isFetching).toEqual(true);
- return waitForPromises().then(() => {
- expect(wrapper.vm.isFetching).toEqual(false);
- });
+ await waitForPromises();
+ expect(wrapper.vm.isFetching).toEqual(false);
});
- it('should fetch related issues', () => {
+ it('should fetch related issues', async () => {
mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]);
wrapper.vm.fetchRelatedIssues();
- return waitForPromises().then(() => {
- expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
- expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
- expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
- });
+ await waitForPromises();
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
+ expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
});
});
diff --git a/spec/frontend/issues/create_merge_request_dropdown_spec.js b/spec/frontend/issues/create_merge_request_dropdown_spec.js
index fdc0bd7d72e..637b4d31999 100644
--- a/spec/frontend/issues/create_merge_request_dropdown_spec.js
+++ b/spec/frontend/issues/create_merge_request_dropdown_spec.js
@@ -59,7 +59,7 @@ describe('CreateMergeRequestDropdown', () => {
describe('updateCreatePaths', () => {
it('escapes branch names correctly', () => {
dropdown.createBranchPath = `${TEST_HOST}/branches?branch_name=some-branch&issue=42`;
- dropdown.createMrPath = `${TEST_HOST}/create_merge_request?branch_name=some-branch&ref=main`;
+ dropdown.createMrPath = `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=test&merge_request%5Btarget_branch%5D=master`;
dropdown.updateCreatePaths('branch', 'contains#hash');
@@ -68,7 +68,7 @@ describe('CreateMergeRequestDropdown', () => {
);
expect(dropdown.createMrPath).toBe(
- `${TEST_HOST}/create_merge_request?branch_name=contains%23hash&ref=main`,
+ `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=contains%23hash&merge_request%5Btarget_branch%5D=master`,
);
});
});
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 66428ee0492..88652ddc3cc 100644
--- a/spec/frontend/issues/list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues/list/components/issues_list_app_spec.js
@@ -16,6 +16,8 @@ import {
getIssuesQueryResponse,
filteredTokens,
locationSearch,
+ setSortPreferenceMutationResponse,
+ setSortPreferenceMutationResponseWithErrors,
urlParams,
} from 'jest/issues/list/mock_data';
import createFlash, { FLASH_TYPES } from '~/flash';
@@ -28,8 +30,6 @@ import IssuesListApp from '~/issues/list/components/issues_list_app.vue';
import NewIssueDropdown from '~/issues/list/components/new_issue_dropdown.vue';
import {
CREATED_DESC,
- DUE_DATE_OVERDUE,
- PARAM_DUE_DATE,
RELATIVE_POSITION,
RELATIVE_POSITION_ASC,
TOKEN_TYPE_ASSIGNEE,
@@ -43,16 +43,15 @@ import {
urlSortParams,
} from '~/issues/list/constants';
import eventHub from '~/issues/list/eventhub';
-import { getSortOptions } from '~/issues/list/utils';
+import setSortPreferenceMutation from '~/issues/list/queries/set_sort_preference.mutation.graphql';
+import { getSortKey, getSortOptions } from '~/issues/list/utils';
import axios from '~/lib/utils/axios_utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
import { joinPaths } from '~/lib/utils/url_utility';
jest.mock('@sentry/browser');
jest.mock('~/flash');
-jest.mock('~/lib/utils/scroll_utils', () => ({
- scrollUp: jest.fn().mockName('scrollUpMock'),
-}));
+jest.mock('~/lib/utils/scroll_utils', () => ({ scrollUp: jest.fn() }));
describe('CE IssuesListApp component', () => {
let axiosMock;
@@ -61,6 +60,7 @@ describe('CE IssuesListApp component', () => {
Vue.use(VueApollo);
const defaultProvide = {
+ autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path',
calendarPath: 'calendar/path',
canBulkUpdate: false,
emptyStateSvgPath: 'empty-state.svg',
@@ -72,10 +72,16 @@ describe('CE IssuesListApp component', () => {
hasIssuableHealthStatusFeature: true,
hasIssueWeightsFeature: true,
hasIterationsFeature: true,
+ hasMultipleIssueAssigneesFeature: true,
+ initialEmail: 'email@example.com',
+ initialSort: CREATED_DESC,
+ isAnonymousSearchDisabled: false,
+ isIssueRepositioningDisabled: false,
isProject: true,
isSignedIn: true,
jiraIntegrationPath: 'jira/integration/path',
newIssuePath: 'new/issue/path',
+ releasesPath: 'releases/path',
rssPath: 'rss/path',
showNewIssueLink: true,
signInPath: 'sign/in/path',
@@ -103,11 +109,13 @@ describe('CE IssuesListApp component', () => {
provide = {},
issuesQueryResponse = jest.fn().mockResolvedValue(defaultQueryResponse),
issuesCountsQueryResponse = jest.fn().mockResolvedValue(getIssuesCountsQueryResponse),
+ sortPreferenceMutationResponse = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse),
mountFn = shallowMount,
} = {}) => {
const requestHandlers = [
[getIssuesQuery, issuesQueryResponse],
[getIssuesCountsQuery, issuesCountsQueryResponse],
+ [setSortPreferenceMutation, sortPreferenceMutationResponse],
];
const apolloProvider = createMockApollo(requestHandlers);
@@ -131,9 +139,10 @@ describe('CE IssuesListApp component', () => {
});
describe('IssuableList', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = mountComponent();
jest.runOnlyPendingTimers();
+ await waitForPromises();
});
it('renders', () => {
@@ -167,8 +176,9 @@ describe('CE IssuesListApp component', () => {
});
describe('header action buttons', () => {
- it('renders rss button', () => {
+ it('renders rss button', async () => {
wrapper = mountComponent({ mountFn: mount });
+ await waitForPromises();
expect(findGlButtonAt(0).props('icon')).toBe('rss');
expect(findGlButtonAt(0).attributes()).toMatchObject({
@@ -177,8 +187,9 @@ describe('CE IssuesListApp component', () => {
});
});
- it('renders calendar button', () => {
+ it('renders calendar button', async () => {
wrapper = mountComponent({ mountFn: mount });
+ await waitForPromises();
expect(findGlButtonAt(1).props('icon')).toBe('calendar');
expect(findGlButtonAt(1).attributes()).toMatchObject({
@@ -189,19 +200,21 @@ describe('CE IssuesListApp component', () => {
describe('csv import/export component', () => {
describe('when user is signed in', () => {
- const search = '?search=refactor&sort=created_date&state=opened';
+ beforeEach(async () => {
+ setWindowLocation('?search=refactor&state=opened');
- beforeEach(() => {
- setWindowLocation(search);
-
- wrapper = mountComponent({ provide: { isSignedIn: true }, mountFn: mount });
+ wrapper = mountComponent({
+ provide: { initialSortBy: CREATED_DESC, isSignedIn: true },
+ mountFn: mount,
+ });
jest.runOnlyPendingTimers();
+ await waitForPromises();
});
it('renders', () => {
expect(findCsvImportExportButtons().props()).toMatchObject({
- exportCsvPath: `${defaultProvide.exportCsvPath}${search}`,
+ exportCsvPath: `${defaultProvide.exportCsvPath}?search=refactor&sort=created_date&state=opened`,
issuableCount: 1,
});
});
@@ -281,16 +294,6 @@ describe('CE IssuesListApp component', () => {
});
describe('initial url params', () => {
- describe('due_date', () => {
- it('is set from the url params', () => {
- setWindowLocation(`?${PARAM_DUE_DATE}=${DUE_DATE_OVERDUE}`);
-
- wrapper = mountComponent();
-
- expect(findIssuableList().props('urlParams')).toMatchObject({ due_date: DUE_DATE_OVERDUE });
- });
- });
-
describe('search', () => {
it('is set from the url params', () => {
setWindowLocation(locationSearch);
@@ -302,31 +305,57 @@ describe('CE IssuesListApp component', () => {
});
describe('sort', () => {
- it.each(Object.keys(urlSortParams))('is set as %s from the url params', (sortKey) => {
- setWindowLocation(`?sort=${urlSortParams[sortKey]}`);
+ describe('when initial sort value uses old enum values', () => {
+ const oldEnumSortValues = Object.values(urlSortParams);
- wrapper = mountComponent();
+ it.each(oldEnumSortValues)('initial sort is set with value %s', (sort) => {
+ wrapper = mountComponent({ provide: { initialSort: sort } });
- expect(findIssuableList().props()).toMatchObject({
- initialSortBy: sortKey,
- urlParams: {
- sort: urlSortParams[sortKey],
- },
+ expect(findIssuableList().props()).toMatchObject({
+ initialSortBy: getSortKey(sort),
+ urlParams: { sort },
+ });
+ });
+ });
+
+ describe('when initial sort value uses new GraphQL enum values', () => {
+ const graphQLEnumSortValues = Object.keys(urlSortParams);
+
+ it.each(graphQLEnumSortValues)('initial sort is set with value %s', (sort) => {
+ wrapper = mountComponent({ provide: { initialSort: sort.toLowerCase() } });
+
+ expect(findIssuableList().props()).toMatchObject({
+ initialSortBy: sort,
+ urlParams: { sort: urlSortParams[sort] },
+ });
});
});
- describe('when issue repositioning is disabled and the sort is manual', () => {
+ describe('when initial sort value is invalid', () => {
+ it.each(['', 'asdf', null, undefined])(
+ 'initial sort is set to value CREATED_DESC',
+ (sort) => {
+ wrapper = mountComponent({ provide: { initialSort: sort } });
+
+ expect(findIssuableList().props()).toMatchObject({
+ initialSortBy: CREATED_DESC,
+ urlParams: { sort: urlSortParams[CREATED_DESC] },
+ });
+ },
+ );
+ });
+
+ describe('when sort is manual and issue repositioning is disabled', () => {
beforeEach(() => {
- setWindowLocation(`?sort=${RELATIVE_POSITION}`);
- wrapper = mountComponent({ provide: { isIssueRepositioningDisabled: true } });
+ wrapper = mountComponent({
+ provide: { initialSort: RELATIVE_POSITION, isIssueRepositioningDisabled: true },
+ });
});
it('changes the sort to the default of created descending', () => {
expect(findIssuableList().props()).toMatchObject({
initialSortBy: CREATED_DESC,
- urlParams: {
- sort: urlSortParams[CREATED_DESC],
- },
+ urlParams: { sort: urlSortParams[CREATED_DESC] },
});
});
@@ -585,16 +614,17 @@ describe('CE IssuesListApp component', () => {
${'fetching issues'} | ${'issuesQueryResponse'} | ${IssuesListApp.i18n.errorFetchingIssues}
${'fetching issue counts'} | ${'issuesCountsQueryResponse'} | ${IssuesListApp.i18n.errorFetchingCounts}
`('when there is an error $error', ({ mountOption, message }) => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = mountComponent({
[mountOption]: jest.fn().mockRejectedValue(new Error('ERROR')),
});
jest.runOnlyPendingTimers();
+ await waitForPromises();
});
it('shows an error message', () => {
expect(findIssuableList().props('error')).toBe(message);
- expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Network error: ERROR'));
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('ERROR'));
});
});
@@ -687,12 +717,13 @@ describe('CE IssuesListApp component', () => {
`(
'when moving issue $description',
({ issueToMove, oldIndex, newIndex, moveBeforeId, moveAfterId }) => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = mountComponent({
provide: { isProject },
issuesQueryResponse: jest.fn().mockResolvedValue(response(isProject)),
});
jest.runOnlyPendingTimers();
+ await waitForPromises();
});
it('makes API call to reorder the issue', async () => {
@@ -705,7 +736,6 @@ describe('CE IssuesListApp component', () => {
data: JSON.stringify({
move_before_id: getIdFromGraphQLId(moveBeforeId),
move_after_id: getIdFromGraphQLId(moveAfterId),
- group_full_path: isProject ? undefined : defaultProvide.fullPath,
}),
});
});
@@ -715,11 +745,12 @@ describe('CE IssuesListApp component', () => {
});
describe('when unsuccessful', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = mountComponent({
issuesQueryResponse: jest.fn().mockResolvedValue(response()),
});
jest.runOnlyPendingTimers();
+ await waitForPromises();
});
it('displays an error message', async () => {
@@ -758,8 +789,9 @@ describe('CE IssuesListApp component', () => {
const initialSort = CREATED_DESC;
beforeEach(() => {
- setWindowLocation(`?sort=${initialSort}`);
- wrapper = mountComponent({ provide: { isIssueRepositioningDisabled: true } });
+ wrapper = mountComponent({
+ provide: { initialSort, isIssueRepositioningDisabled: true },
+ });
findIssuableList().vm.$emit('sort', RELATIVE_POSITION_ASC);
});
@@ -777,6 +809,43 @@ describe('CE IssuesListApp component', () => {
});
});
});
+
+ describe('when user is signed in', () => {
+ it('calls mutation to save sort preference', () => {
+ const mutationMock = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse);
+ wrapper = mountComponent({ sortPreferenceMutationResponse: mutationMock });
+
+ findIssuableList().vm.$emit('sort', CREATED_DESC);
+
+ expect(mutationMock).toHaveBeenCalledWith({ input: { issuesSort: CREATED_DESC } });
+ });
+
+ it('captures error when mutation response has errors', async () => {
+ const mutationMock = jest
+ .fn()
+ .mockResolvedValue(setSortPreferenceMutationResponseWithErrors);
+ wrapper = mountComponent({ sortPreferenceMutationResponse: mutationMock });
+
+ findIssuableList().vm.$emit('sort', CREATED_DESC);
+ await waitForPromises();
+
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('oh no!'));
+ });
+ });
+
+ describe('when user is signed out', () => {
+ it('does not call mutation to save sort preference', () => {
+ const mutationMock = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse);
+ wrapper = mountComponent({
+ provide: { isSignedIn: false },
+ sortPreferenceMutationResponse: mutationMock,
+ });
+
+ findIssuableList().vm.$emit('sort', CREATED_DESC);
+
+ expect(mutationMock).not.toHaveBeenCalled();
+ });
+ });
});
describe('when "update-legacy-bulk-edit" event is emitted by IssuableList', () => {
diff --git a/spec/frontend/issues/list/components/jira_issues_import_status_app_spec.js b/spec/frontend/issues/list/components/jira_issues_import_status_app_spec.js
index d6d6bb14e9d..2d773e8bf56 100644
--- a/spec/frontend/issues/list/components/jira_issues_import_status_app_spec.js
+++ b/spec/frontend/issues/list/components/jira_issues_import_status_app_spec.js
@@ -1,6 +1,6 @@
import { GlAlert, GlLabel } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import JiraIssuesImportStatus from '~/issues/list/components/jira_issues_import_status_app.vue';
describe('JiraIssuesImportStatus', () => {
@@ -100,7 +100,7 @@ describe('JiraIssuesImportStatus', () => {
});
describe('alert message', () => {
- it('is hidden when dismissed', () => {
+ it('is hidden when dismissed', async () => {
wrapper = mountComponent({
shouldShowInProgressAlert: true,
});
@@ -109,9 +109,8 @@ describe('JiraIssuesImportStatus', () => {
findAlert().vm.$emit('dismiss');
- return Vue.nextTick(() => {
- expect(wrapper.find(GlAlert).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js b/spec/frontend/issues/list/components/new_issue_dropdown_spec.js
index 0c52e66ff14..2c8cf9caf5d 100644
--- a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js
+++ b/spec/frontend/issues/list/components/new_issue_dropdown_spec.js
@@ -1,10 +1,13 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import NewIssueDropdown from '~/issues/list/components/new_issue_dropdown.vue';
import searchProjectsQuery from '~/issues/list/queries/search_projects.query.graphql';
import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
+import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
import {
emptySearchProjectsQueryResponse,
project1,
@@ -15,8 +18,7 @@ import {
describe('NewIssueDropdown component', () => {
let wrapper;
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const mountComponent = ({
search = '',
@@ -27,7 +29,6 @@ describe('NewIssueDropdown component', () => {
const apolloProvider = createMockApollo(requestHandlers);
return mountFn(NewIssueDropdown, {
- localVue,
apolloProvider,
provide: {
fullPath: 'mushroom-kingdom',
@@ -42,8 +43,9 @@ describe('NewIssueDropdown component', () => {
const findInput = () => wrapper.findComponent(GlSearchBoxByType);
const showDropdown = async () => {
findDropdown().vm.$emit('shown');
- await wrapper.vm.$apollo.queries.projects.refetch();
- jest.runOnlyPendingTimers();
+ await waitForPromises();
+ jest.advanceTimersByTime(DEBOUNCE_DELAY);
+ await waitForPromises();
};
afterEach(() => {
@@ -74,7 +76,6 @@ describe('NewIssueDropdown component', () => {
it('renders projects with issues enabled', async () => {
wrapper = mountComponent({ mountFn: mount });
-
await showDropdown();
const listItems = wrapper.findAll('li');
@@ -112,10 +113,11 @@ describe('NewIssueDropdown component', () => {
describe('when a project is selected', () => {
beforeEach(async () => {
wrapper = mountComponent({ mountFn: mount });
-
+ await waitForPromises();
await showDropdown();
wrapper.findComponent(GlDropdownItem).vm.$emit('click', project1);
+ await waitForPromises();
});
it('dropdown button is a link', () => {
diff --git a/spec/frontend/issues/list/mock_data.js b/spec/frontend/issues/list/mock_data.js
index 948699876ce..c883b20682e 100644
--- a/spec/frontend/issues/list/mock_data.js
+++ b/spec/frontend/issues/list/mock_data.js
@@ -7,8 +7,10 @@ export const getIssuesQueryResponse = {
data: {
project: {
id: '1',
+ __typename: 'Project',
issues: {
pageInfo: {
+ __typename: 'PageInfo',
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'startcursor',
@@ -16,6 +18,7 @@ export const getIssuesQueryResponse = {
},
nodes: [
{
+ __typename: 'Issue',
id: 'gid://gitlab/Issue/123456',
iid: '789',
closedAt: null,
@@ -36,6 +39,7 @@ export const getIssuesQueryResponse = {
assignees: {
nodes: [
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/234',
avatarUrl: 'avatar/url',
name: 'Marge Simpson',
@@ -45,6 +49,7 @@ export const getIssuesQueryResponse = {
],
},
author: {
+ __typename: 'UserCore',
id: 'gid://gitlab/User/456',
avatarUrl: 'avatar/url',
name: 'Homer Simpson',
@@ -90,6 +95,22 @@ export const getIssuesCountsQueryResponse = {
},
};
+export const setSortPreferenceMutationResponse = {
+ data: {
+ userPreferencesUpdate: {
+ errors: [],
+ },
+ },
+};
+
+export const setSortPreferenceMutationResponseWithErrors = {
+ data: {
+ userPreferencesUpdate: {
+ errors: ['oh no!'],
+ },
+ },
+};
+
export const locationSearch = [
'?search=find+issues',
'author_username=homer',
diff --git a/spec/frontend/issues/list/utils_spec.js b/spec/frontend/issues/list/utils_spec.js
index 0e4979fd7b4..1d3e94df897 100644
--- a/spec/frontend/issues/list/utils_spec.js
+++ b/spec/frontend/issues/list/utils_spec.js
@@ -10,7 +10,6 @@ import {
} from 'jest/issues/list/mock_data';
import {
defaultPageSizeParams,
- DUE_DATE_VALUES,
largePageSizeParams,
RELATIVE_POSITION_ASC,
urlSortParams,
@@ -19,11 +18,11 @@ import {
convertToApiParams,
convertToSearchQuery,
convertToUrlParams,
- getDueDateValue,
getFilterTokens,
getInitialPageParams,
getSortKey,
getSortOptions,
+ isSortKey,
} from '~/issues/list/utils';
describe('getInitialPageParams', () => {
@@ -45,13 +44,13 @@ describe('getSortKey', () => {
});
});
-describe('getDueDateValue', () => {
- it.each(DUE_DATE_VALUES)('returns the argument when it is `%s`', (value) => {
- expect(getDueDateValue(value)).toBe(value);
+describe('isSortKey', () => {
+ it.each(Object.keys(urlSortParams))('returns true given %s', (sort) => {
+ expect(isSortKey(sort)).toBe(true);
});
- it('returns undefined when the argument is invalid', () => {
- expect(getDueDateValue('invalid value')).toBeUndefined();
+ it.each(['', 'asdf', null, undefined])('returns false given %s', (sort) => {
+ expect(isSortKey(sort)).toBe(false);
});
});
diff --git a/spec/frontend/issues/new/components/title_suggestions_spec.js b/spec/frontend/issues/new/components/title_suggestions_spec.js
index f6b93cc5a62..0a64890e4ca 100644
--- a/spec/frontend/issues/new/components/title_suggestions_spec.js
+++ b/spec/frontend/issues/new/components/title_suggestions_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import TitleSuggestions from '~/issues/new/components/title_suggestions.vue';
import TitleSuggestionsItem from '~/issues/new/components/title_suggestions_item.vue';
@@ -22,12 +23,11 @@ describe('Issue title suggestions component', () => {
wrapper.destroy();
});
- it('does not render with empty search', () => {
+ it('does not render with empty search', async () => {
wrapper.setProps({ search: '' });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.isVisible()).toBe(false);
});
describe('with data', () => {
@@ -37,28 +37,26 @@ describe('Issue title suggestions component', () => {
data = { issues: [{ id: 1 }, { id: 2 }] };
});
- it('renders component', () => {
+ it('renders component', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').length).toBe(data.issues.length);
- });
+ await nextTick();
+ expect(wrapper.findAll('li').length).toBe(data.issues.length);
});
- it('does not render with empty search', () => {
+ it('does not render with empty search', async () => {
wrapper.setProps({ search: '' });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.isVisible()).toBe(false);
});
- it('does not render when loading', () => {
+ it('does not render when loading', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -66,49 +64,44 @@ describe('Issue title suggestions component', () => {
loading: 1,
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.isVisible()).toBe(false);
});
- it('does not render with empty issues data', () => {
+ it('does not render with empty issues data', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ issues: [] });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.isVisible()).toBe(false);
});
- it('renders list of issues', () => {
+ it('renders list of issues', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2);
- });
+ await nextTick();
+ expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2);
});
- it('adds margin class to first item', () => {
+ it('adds margin class to first item', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
- });
+ await nextTick();
+ expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
});
- it('does not add margin class to last item', () => {
+ it('does not add margin class to last item', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
- });
+ await nextTick();
+ expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
});
});
});
diff --git a/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js
index 4d780a674be..4df04cd5257 100644
--- a/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js
+++ b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js
@@ -1,4 +1,4 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import mockData from 'test_fixtures/issues/related_merge_requests.json';
import axios from '~/lib/utils/axios_utils';
@@ -7,13 +7,12 @@ import createStore from '~/issues/related_merge_requests/store/index';
import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
const API_ENDPOINT = '/api/v4/projects/2/issues/33/related_merge_requests';
-const localVue = createLocalVue();
describe('RelatedMergeRequests', () => {
let wrapper;
let mock;
- beforeEach((done) => {
+ beforeEach(() => {
// put the fixture in DOM as the component expects
document.body.innerHTML = `<div id="js-issuable-app"></div>`;
document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(mockData);
@@ -21,8 +20,7 @@ describe('RelatedMergeRequests', () => {
mock = new MockAdapter(axios);
mock.onGet(`${API_ENDPOINT}?per_page=100`).reply(200, mockData, { 'x-total': 2 });
- wrapper = mount(localVue.extend(RelatedMergeRequests), {
- localVue,
+ wrapper = mount(RelatedMergeRequests, {
store: createStore(),
propsData: {
endpoint: API_ENDPOINT,
@@ -31,7 +29,7 @@ describe('RelatedMergeRequests', () => {
},
});
- setImmediate(done);
+ return axios.waitForAll();
});
afterEach(() => {
diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js
index 02db82b84dc..ac2717a5028 100644
--- a/spec/frontend/issues/show/components/app_spec.js
+++ b/spec/frontend/issues/show/components/app_spec.js
@@ -145,33 +145,30 @@ describe('Issuable output', () => {
});
});
- it('shows actions if permissions are correct', () => {
+ it('shows actions if permissions are correct', async () => {
wrapper.vm.showForm = true;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.markdown-selector').exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find('.markdown-selector').exists()).toBe(true);
});
- it('does not show actions if permissions are incorrect', () => {
+ it('does not show actions if permissions are incorrect', async () => {
wrapper.vm.showForm = true;
wrapper.setProps({ canUpdate: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.markdown-selector').exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find('.markdown-selector').exists()).toBe(false);
});
- it('does not update formState if form is already open', () => {
+ it('does not update formState if form is already open', async () => {
wrapper.vm.updateAndShowForm();
wrapper.vm.state.titleText = 'testing 123';
wrapper.vm.updateAndShowForm();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
- });
+ await nextTick();
+ expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
});
describe('Pinned links propagated', () => {
@@ -186,31 +183,29 @@ describe('Issuable output', () => {
});
describe('updateIssuable', () => {
- it('fetches new data after update', () => {
+ it('fetches new data after update', async () => {
const updateStoreSpy = jest.spyOn(wrapper.vm, 'updateStoreState');
const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData');
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: { web_url: window.location.pathname },
});
- return wrapper.vm.updateIssuable().then(() => {
- expect(updateStoreSpy).toHaveBeenCalled();
- expect(getDataSpy).toHaveBeenCalled();
- });
+ await wrapper.vm.updateIssuable();
+ expect(updateStoreSpy).toHaveBeenCalled();
+ expect(getDataSpy).toHaveBeenCalled();
});
- it('correctly updates issuable data', () => {
+ it('correctly updates issuable data', async () => {
const spy = jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: { web_url: window.location.pathname },
});
- return wrapper.vm.updateIssuable().then(() => {
- expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
- });
+ await wrapper.vm.updateIssuable();
+ expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
});
- it('does not redirect if issue has not moved', () => {
+ it('does not redirect if issue has not moved', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: window.location.pathname,
@@ -218,12 +213,11 @@ describe('Issuable output', () => {
},
});
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).not.toHaveBeenCalled();
- });
+ await wrapper.vm.updateIssuable();
+ expect(visitUrl).not.toHaveBeenCalled();
});
- it('does not redirect if issue has not moved and user has switched tabs', () => {
+ it('does not redirect if issue has not moved and user has switched tabs', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: '',
@@ -231,12 +225,11 @@ describe('Issuable output', () => {
},
});
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).not.toHaveBeenCalled();
- });
+ await wrapper.vm.updateIssuable();
+ expect(visitUrl).not.toHaveBeenCalled();
});
- it('redirects if returned web_url has changed', () => {
+ it('redirects if returned web_url has changed', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: '/testing-issue-move',
@@ -246,108 +239,95 @@ describe('Issuable output', () => {
wrapper.vm.updateIssuable();
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
- });
+ await wrapper.vm.updateIssuable();
+ expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
});
describe('shows dialog when issue has unsaved changed', () => {
- it('confirms on title change', () => {
+ it('confirms on title change', async () => {
wrapper.vm.showForm = true;
wrapper.vm.state.titleText = 'title has changed';
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).not.toBeNull();
- });
+ await nextTick();
+ expect(e.returnValue).not.toBeNull();
});
- it('confirms on description change', () => {
+ it('confirms on description change', async () => {
wrapper.vm.showForm = true;
wrapper.vm.state.descriptionText = 'description has changed';
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).not.toBeNull();
- });
+ await nextTick();
+ expect(e.returnValue).not.toBeNull();
});
- it('does nothing when nothing has changed', () => {
+ it('does nothing when nothing has changed', async () => {
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).toBeNull();
- });
+ await nextTick();
+ expect(e.returnValue).toBeNull();
});
});
describe('error when updating', () => {
- it('closes form on error', () => {
+ it('closes form on error', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
- return wrapper.vm.updateIssuable().then(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating issue`,
- );
- });
+ await wrapper.vm.updateIssuable();
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating issue`,
+ );
});
- it('returns the correct error message for issuableType', () => {
+ it('returns the correct error message for issuableType', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
wrapper.setProps({ issuableType: 'merge request' });
- return wrapper.vm
- .$nextTick()
- .then(wrapper.vm.updateIssuable)
- .then(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating merge request`,
- );
- });
+ await nextTick();
+ await wrapper.vm.updateIssuable();
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating merge request`,
+ );
});
- it('shows error message from backend if exists', () => {
+ it('shows error message from backend if exists', async () => {
const msg = 'Custom error message from backend';
jest
.spyOn(wrapper.vm.service, 'updateIssuable')
.mockRejectedValue({ response: { data: { errors: [msg] } } });
- return wrapper.vm.updateIssuable().then(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `${wrapper.vm.defaultErrorMessage}. ${msg}`,
- );
- });
+ await wrapper.vm.updateIssuable();
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `${wrapper.vm.defaultErrorMessage}. ${msg}`,
+ );
});
});
});
describe('updateAndShowForm', () => {
- it('shows locked warning if form is open & data is different', () => {
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.vm.updateAndShowForm();
-
- wrapper.vm.poll.makeRequest();
-
- return new Promise((resolve) => {
- wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
- if (value) {
- resolve();
- }
- });
- });
- })
- .then(() => {
- expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
- expect(wrapper.vm.formState.lock_version).toBe(1);
- expect(findAlert().exists()).toBe(true);
+ it('shows locked warning if form is open & data is different', async () => {
+ await nextTick();
+ wrapper.vm.updateAndShowForm();
+
+ wrapper.vm.poll.makeRequest();
+
+ await new Promise((resolve) => {
+ wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
+ if (value) {
+ resolve();
+ }
});
+ });
+
+ expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
+ expect(wrapper.vm.formState.lock_version).toBe(1);
+ expect(findAlert().exists()).toBe(true);
});
});
@@ -398,12 +378,11 @@ describe('Issuable output', () => {
expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
- it('should render if showInlineEditButton', () => {
+ it('should render if showInlineEditButton', async () => {
wrapper.setProps({ showInlineEditButton: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.btn-edit').exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
});
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
index d39e00b9c9e..3890fc7a353 100644
--- a/spec/frontend/issues/show/components/description_spec.js
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -1,21 +1,56 @@
import $ from 'jquery';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import '~/behaviors/markdown/render_gfm';
+import { GlPopover, GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
import Description from '~/issues/show/components/description.vue';
import TaskList from '~/task_list';
-import { descriptionProps as props } from '../mock_data/mock_data';
+import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
+import {
+ descriptionProps as initialProps,
+ descriptionHtmlWithCheckboxes,
+} from '../mock_data/mock_data';
jest.mock('~/task_list');
+const showModal = jest.fn();
+const hideModal = jest.fn();
+
describe('Description component', () => {
- let vm;
- let DescriptionComponent;
+ let wrapper;
+
+ const findGfmContent = () => wrapper.find('[data-testid="gfm-content"]');
+ const findTextarea = () => wrapper.find('[data-testid="textarea"]');
+ const findTaskActionButtons = () => wrapper.findAll('.js-add-task');
+ const findConvertToTaskButton = () => wrapper.find('[data-testid="convert-to-task"]');
+ const findTaskSvg = () => wrapper.find('[data-testid="issue-open-m-icon"]');
+
+ const findPopovers = () => wrapper.findAllComponents(GlPopover);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findCreateWorkItem = () => wrapper.findComponent(CreateWorkItem);
+
+ function createComponent({ props = {}, provide = {} } = {}) {
+ wrapper = shallowMount(Description, {
+ propsData: {
+ ...initialProps,
+ ...props,
+ },
+ provide,
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ methods: {
+ show: showModal,
+ hide: hideModal,
+ },
+ }),
+ GlPopover,
+ },
+ });
+ }
beforeEach(() => {
- DescriptionComponent = Vue.extend(Description);
-
if (!document.querySelector('.issuable-meta')) {
const metaData = document.createElement('div');
metaData.classList.add('issuable-meta');
@@ -24,91 +59,102 @@ describe('Description component', () => {
document.body.appendChild(metaData);
}
-
- vm = mountComponent(DescriptionComponent, props);
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
afterAll(() => {
$('.issuable-meta .flash-container').remove();
});
- it('doesnt animate first description changes', () => {
- vm.descriptionHtml = 'changed';
-
- return vm.$nextTick().then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
- ).toBeFalsy();
- jest.runAllTimers();
- return vm.$nextTick();
+ it('doesnt animate first description changes', async () => {
+ createComponent();
+ await wrapper.setProps({
+ descriptionHtml: 'changed',
});
+
+ expect(findGfmContent().classes()).not.toContain('issue-realtime-pre-pulse');
});
- it('animates description changes on live update', () => {
- vm.descriptionHtml = 'changed';
- return vm
- .$nextTick()
- .then(() => {
- vm.descriptionHtml = 'changed second time';
- return vm.$nextTick();
- })
- .then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
- ).toBeTruthy();
- jest.runAllTimers();
- return vm.$nextTick();
- })
- .then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
- ).toBeTruthy();
- });
+ it('animates description changes on live update', async () => {
+ createComponent();
+ await wrapper.setProps({
+ descriptionHtml: 'changed',
+ });
+
+ expect(findGfmContent().classes()).not.toContain('issue-realtime-pre-pulse');
+
+ await wrapper.setProps({
+ descriptionHtml: 'changed second time',
+ });
+
+ expect(findGfmContent().classes()).toContain('issue-realtime-pre-pulse');
+
+ await jest.runOnlyPendingTimers();
+
+ expect(findGfmContent().classes()).toContain('issue-realtime-trigger-pulse');
});
- it('applies syntax highlighting and math when description changed', () => {
- const vmSpy = jest.spyOn(vm, 'renderGFM');
+ it('applies syntax highlighting and math when description changed', async () => {
const prototypeSpy = jest.spyOn($.prototype, 'renderGFM');
- vm.descriptionHtml = 'changed';
+ createComponent();
- return vm.$nextTick().then(() => {
- expect(vm.$refs['gfm-content']).toBeDefined();
- expect(vmSpy).toHaveBeenCalled();
- expect(prototypeSpy).toHaveBeenCalled();
- expect($.prototype.renderGFM).toHaveBeenCalled();
+ await wrapper.setProps({
+ descriptionHtml: 'changed',
});
+
+ expect(findGfmContent().exists()).toBe(true);
+ expect(prototypeSpy).toHaveBeenCalled();
});
it('sets data-update-url', () => {
- expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(TEST_HOST);
+ createComponent();
+ expect(findTextarea().attributes('data-update-url')).toBe(TEST_HOST);
});
describe('TaskList', () => {
beforeEach(() => {
- vm.$destroy();
TaskList.mockClear();
- vm = mountComponent(DescriptionComponent, { ...props, issuableType: 'issuableType' });
});
it('re-inits the TaskList when description changed', () => {
- vm.descriptionHtml = 'changed';
+ createComponent({
+ props: {
+ issuableType: 'issuableType',
+ },
+ });
+ wrapper.setProps({
+ descriptionHtml: 'changed',
+ });
expect(TaskList).toHaveBeenCalled();
});
- it('does not re-init the TaskList when canUpdate is false', () => {
- vm.canUpdate = false;
- vm.descriptionHtml = 'changed';
+ it('does not re-init the TaskList when canUpdate is false', async () => {
+ createComponent({
+ props: {
+ issuableType: 'issuableType',
+ canUpdate: false,
+ },
+ });
+ wrapper.setProps({
+ descriptionHtml: 'changed',
+ });
- expect(TaskList).toHaveBeenCalledTimes(1);
+ expect(TaskList).not.toHaveBeenCalled();
});
it('calls with issuableType dataType', () => {
- vm.descriptionHtml = 'changed';
+ createComponent({
+ props: {
+ issuableType: 'issuableType',
+ },
+ });
+ wrapper.setProps({
+ descriptionHtml: 'changed',
+ });
expect(TaskList).toHaveBeenCalledWith({
dataType: 'issuableType',
@@ -123,65 +169,119 @@ describe('Description component', () => {
});
describe('taskStatus', () => {
- it('adds full taskStatus', () => {
- vm.taskStatus = '1 of 1';
-
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
- '1 of 1',
- );
+ it('adds full taskStatus', async () => {
+ createComponent({
+ props: {
+ taskStatus: '1 of 1',
+ },
});
- });
+ await nextTick();
- it('adds short taskStatus', () => {
- vm.taskStatus = '1 of 1';
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
+ '1 of 1',
+ );
+ });
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
- '1/1 task',
- );
+ it('adds short taskStatus', async () => {
+ createComponent({
+ props: {
+ taskStatus: '1 of 1',
+ },
});
- });
+ await nextTick();
- it('clears task status text when no tasks are present', () => {
- vm.taskStatus = '0 of 0';
+ expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
+ '1/1 task',
+ );
+ });
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
+ it('clears task status text when no tasks are present', async () => {
+ createComponent({
+ props: {
+ taskStatus: '0 of 0',
+ },
});
+
+ await nextTick();
+
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
});
});
- describe('taskListUpdateStarted', () => {
- it('emits event to parent', () => {
- const spy = jest.spyOn(vm, '$emit');
-
- vm.taskListUpdateStarted();
+ describe('with work items feature flag is enabled', () => {
+ describe('empty description', () => {
+ beforeEach(async () => {
+ createComponent({
+ props: {
+ descriptionHtml: '',
+ },
+ provide: {
+ glFeatures: {
+ workItems: true,
+ },
+ },
+ });
+ await nextTick();
+ });
- expect(spy).toHaveBeenCalledWith('taskListUpdateStarted');
+ it('renders without error', () => {
+ expect(findTaskActionButtons()).toHaveLength(0);
+ });
});
- });
- describe('taskListUpdateSuccess', () => {
- it('emits event to parent', () => {
- const spy = jest.spyOn(vm, '$emit');
+ describe('description with checkboxes', () => {
+ beforeEach(async () => {
+ createComponent({
+ props: {
+ descriptionHtml: descriptionHtmlWithCheckboxes,
+ },
+ provide: {
+ glFeatures: {
+ workItems: true,
+ },
+ },
+ });
+ await nextTick();
+ });
- vm.taskListUpdateSuccess();
+ it('renders a list of hidden buttons corresponding to checkboxes in description HTML', () => {
+ expect(findTaskActionButtons()).toHaveLength(3);
+ });
- expect(spy).toHaveBeenCalledWith('taskListUpdateSucceeded');
- });
- });
+ it('renders a list of popovers corresponding to checkboxes in description HTML', () => {
+ expect(findPopovers()).toHaveLength(3);
+ expect(findPopovers().at(0).props('target')).toBe(
+ findTaskActionButtons().at(0).attributes('id'),
+ );
+ });
- describe('taskListUpdateError', () => {
- it('should create flash notification and emit an event to parent', () => {
- const msg =
- 'Someone edited this issue at the same time you did. The description has been updated and you will need to make your changes again.';
- const spy = jest.spyOn(vm, '$emit');
+ it('does not show a modal by default', () => {
+ expect(findModal().props('visible')).toBe(false);
+ });
- vm.taskListUpdateError();
+ it('opens a modal when a button on popover is clicked and displays correct title', async () => {
+ findConvertToTaskButton().vm.$emit('click');
+ expect(showModal).toHaveBeenCalled();
+ await nextTick();
+ expect(findCreateWorkItem().props('initialTitle').trim()).toBe('todo 1');
+ });
+
+ it('closes the modal on `closeCreateTaskModal` event', () => {
+ findConvertToTaskButton().vm.$emit('click');
+ findCreateWorkItem().vm.$emit('closeModal');
+ expect(hideModal).toHaveBeenCalled();
+ });
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
- expect(spy).toHaveBeenCalledWith('taskListUpdateFailed');
+ it('updates description HTML on `onCreate` event', async () => {
+ const newTitle = 'New title';
+ findConvertToTaskButton().vm.$emit('click');
+ findCreateWorkItem().vm.$emit('onCreate', newTitle);
+ expect(hideModal).toHaveBeenCalled();
+ await nextTick();
+
+ expect(findTaskSvg().exists()).toBe(true);
+ expect(wrapper.text()).toContain(newTitle);
+ });
});
});
});
diff --git a/spec/frontend/issues/show/components/fields/description_spec.js b/spec/frontend/issues/show/components/fields/description_spec.js
index 3043c4c3673..dd511c3945c 100644
--- a/spec/frontend/issues/show/components/fields/description_spec.js
+++ b/spec/frontend/issues/show/components/fields/description_spec.js
@@ -25,6 +25,7 @@ describe('Description field component', () => {
beforeEach(() => {
jest.spyOn(eventHub, '$emit');
+ gon.features = { markdownContinueLists: true };
});
afterEach(() => {
diff --git a/spec/frontend/issues/show/components/fields/type_spec.js b/spec/frontend/issues/show/components/fields/type_spec.js
index 7f7b16583e6..3333ceffca9 100644
--- a/spec/frontend/issues/show/components/fields/type_spec.js
+++ b/spec/frontend/issues/show/components/fields/type_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -10,8 +11,7 @@ import {
updateIssueStateQueryResponse,
} from '../../mock_data/apollo_mock';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Issue type field component', () => {
let wrapper;
@@ -43,7 +43,6 @@ describe('Issue type field component', () => {
fakeApollo = createMockApollo([], mockResolvers);
wrapper = shallowMount(IssueTypeField, {
- localVue,
apolloProvider: fakeApollo,
data() {
return {
@@ -93,7 +92,7 @@ describe('Issue type field component', () => {
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();
+ await nextTick();
expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.incident);
});
diff --git a/spec/frontend/issues/show/components/form_spec.js b/spec/frontend/issues/show/components/form_spec.js
index db49d2635ba..5c0fe991b22 100644
--- a/spec/frontend/issues/show/components/form_spec.js
+++ b/spec/frontend/issues/show/components/form_spec.js
@@ -1,5 +1,6 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Autosave from '~/autosave';
import DescriptionTemplate from '~/issues/show/components/fields/description_template.vue';
import IssueTypeField from '~/issues/show/components/fields/type.vue';
@@ -148,7 +149,7 @@ describe('Inline edit form component', () => {
formState: { ...defaultProps.formState, lock_version: 'lock version from server' },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().exists()).toBe(true);
});
});
diff --git a/spec/frontend/issues/show/components/header_actions_spec.js b/spec/frontend/issues/show/components/header_actions_spec.js
index d09bf6faa13..4a557a60b94 100644
--- a/spec/frontend/issues/show/components/header_actions_spec.js
+++ b/spec/frontend/issues/show/components/header_actions_spec.js
@@ -1,5 +1,5 @@
import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
@@ -153,7 +153,7 @@ describe('HeaderActions component', () => {
it('dispatches a custom event to update the issue page', async () => {
findToggleIssueStateButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
});
diff --git a/spec/frontend/issues/show/components/title_spec.js b/spec/frontend/issues/show/components/title_spec.js
index f9026557be2..29b5353ef1c 100644
--- a/spec/frontend/issues/show/components/title_spec.js
+++ b/spec/frontend/issues/show/components/title_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import titleComponent from '~/issues/show/components/title.vue';
import eventHub from '~/issues/show/event_hub';
import Store from '~/issues/show/stores';
@@ -29,36 +29,33 @@ describe('Title component', () => {
expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
});
- it('updates page title when changing titleHtml', () => {
+ it('updates page title when changing titleHtml', async () => {
const spy = jest.spyOn(vm, 'setPageTitle');
vm.titleHtml = 'test';
- return vm.$nextTick().then(() => {
- expect(spy).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(spy).toHaveBeenCalled();
});
- it('animates title changes', () => {
+ it('animates title changes', async () => {
vm.titleHtml = 'test';
- return vm
- .$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
- jest.runAllTimers();
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
- });
+
+ await nextTick();
+
+ expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
+ jest.runAllTimers();
+
+ await nextTick();
+
+ expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
});
- it('updates page title after changing title', () => {
+ it('updates page title after changing title', async () => {
vm.titleHtml = 'changed';
vm.titleText = 'changed';
- return vm.$nextTick().then(() => {
- expect(document.querySelector('title').textContent.trim()).toContain('changed');
- });
+ await nextTick();
+ expect(document.querySelector('title').textContent.trim()).toContain('changed');
});
describe('inline edit button', () => {
@@ -80,16 +77,15 @@ describe('Title component', () => {
expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
});
- it('should trigger open.form event when clicked', () => {
+ it('should trigger open.form event when clicked', async () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm.showInlineEditButton = true;
vm.canUpdate = true;
- Vue.nextTick(() => {
- vm.$el.querySelector('.btn-edit').click();
+ await nextTick();
+ vm.$el.querySelector('.btn-edit').click();
- expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
});
});
});
diff --git a/spec/frontend/issues/show/mock_data/mock_data.js b/spec/frontend/issues/show/mock_data/mock_data.js
index a73826954c3..89653ff82b2 100644
--- a/spec/frontend/issues/show/mock_data/mock_data.js
+++ b/spec/frontend/issues/show/mock_data/mock_data.js
@@ -58,3 +58,17 @@ export const appProps = {
zoomMeetingUrl,
publishedIncidentUrl,
};
+
+export const descriptionHtmlWithCheckboxes = `
+ <ul dir="auto" class="task-list" data-sourcepos"3:1-5:12">
+ <li class="task-list-item" data-sourcepos="3:1-3:11">
+ <input class="task-list-item-checkbox" type="checkbox"> todo 1
+ </li>
+ <li class="task-list-item" data-sourcepos="4:1-4:12">
+ <input class="task-list-item-checkbox" type="checkbox"> todo 2
+ </li>
+ <li class="task-list-item" data-sourcepos="5:1-5:12">
+ <input class="task-list-item-checkbox" type="checkbox"> todo 3
+ </li>
+ </ul>
+`;
diff --git a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
index 7326b84ad54..b9fed5f34f1 100644
--- a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
+++ b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
@@ -1,5 +1,6 @@
-import { GlAlert, GlForm, GlFormInput, GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlAlert, GlForm, GlFormInput, GlButton, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -9,17 +10,12 @@ import SourceBranchDropdown from '~/jira_connect/branches/components/source_bran
import {
CREATE_BRANCH_ERROR_GENERIC,
CREATE_BRANCH_ERROR_WITH_CONTEXT,
+ I18N_NEW_BRANCH_PERMISSION_ALERT,
} from '~/jira_connect/branches/constants';
import createBranchMutation from '~/jira_connect/branches/graphql/mutations/create_branch.mutation.graphql';
+import { mockProjects } from '../mock_data';
-const mockProject = {
- id: 'test',
- fullPath: 'test-path',
- repository: {
- branchNames: ['main', 'f-test', 'release'],
- rootRef: 'main',
- },
-};
+const mockProject = mockProjects[0];
const mockCreateBranchMutationResponse = {
data: {
createBranch: {
@@ -45,28 +41,27 @@ const mockCreateBranchMutationWithErrors = jest
const mockCreateBranchMutationFailed = jest.fn().mockRejectedValue(new Error('GraphQL error'));
const mockMutationLoading = jest.fn().mockReturnValue(new Promise(() => {}));
-const localVue = createLocalVue();
-
describe('NewBranchForm', () => {
let wrapper;
const findSourceBranchDropdown = () => wrapper.findComponent(SourceBranchDropdown);
const findProjectDropdown = () => wrapper.findComponent(ProjectDropdown);
const findAlert = () => wrapper.findComponent(GlAlert);
+ const findAlertSprintf = () => findAlert().findComponent(GlSprintf);
const findForm = () => wrapper.findComponent(GlForm);
const findInput = () => wrapper.findComponent(GlFormInput);
const findButton = () => wrapper.findComponent(GlButton);
const completeForm = async () => {
- await findInput().vm.$emit('input', 'cool-branch-name');
await findProjectDropdown().vm.$emit('change', mockProject);
await findSourceBranchDropdown().vm.$emit('change', 'source-branch');
+ await findInput().vm.$emit('input', 'cool-branch-name');
};
function createMockApolloProvider({
mockCreateBranchMutation = mockCreateBranchMutationSuccess,
} = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const mockApollo = createMockApollo([[createBranchMutation, mockCreateBranchMutation]]);
@@ -75,7 +70,6 @@ describe('NewBranchForm', () => {
function createComponent({ mockApollo, provide } = {}) {
wrapper = shallowMount(NewBranchForm, {
- localVue,
apolloProvider: mockApollo || createMockApolloProvider(),
provide: {
initialBranchName: '',
@@ -89,27 +83,107 @@ describe('NewBranchForm', () => {
});
describe('when selecting items from dropdowns', () => {
- describe('when a project is selected', () => {
- it('sets the `selectedProject` prop for ProjectDropdown and SourceBranchDropdown', async () => {
+ describe('when no project selected', () => {
+ beforeEach(() => {
createComponent();
+ });
- const projectDropdown = findProjectDropdown();
- await projectDropdown.vm.$emit('change', mockProject);
+ it('hides source branch selection and branch name input', () => {
+ expect(findSourceBranchDropdown().exists()).toBe(false);
+ expect(findInput().exists()).toBe(false);
+ });
- expect(projectDropdown.props('selectedProject')).toEqual(mockProject);
- expect(findSourceBranchDropdown().props('selectedProject')).toEqual(mockProject);
+ it('disables the submit button', () => {
+ expect(findButton().props('disabled')).toBe(true);
});
});
- describe('when a source branch is selected', () => {
- it('sets the `selectedBranchName` prop for SourceBranchDropdown', async () => {
+ describe('when a valid project is selected', () => {
+ describe("when a source branch isn't selected", () => {
+ beforeEach(async () => {
+ createComponent();
+ await findProjectDropdown().vm.$emit('change', mockProject);
+ });
+
+ it('sets the `selectedProject` prop for ProjectDropdown and SourceBranchDropdown', () => {
+ expect(findProjectDropdown().props('selectedProject')).toEqual(mockProject);
+ expect(findSourceBranchDropdown().exists()).toBe(true);
+ expect(findSourceBranchDropdown().props('selectedProject')).toEqual(mockProject);
+ });
+
+ it('disables the submit button', () => {
+ expect(findButton().props('disabled')).toBe(true);
+ });
+
+ it('renders branch input field', () => {
+ expect(findInput().exists()).toBe(true);
+ });
+ });
+
+ describe('when `initialBranchName` is provided', () => {
+ it('sets value of branch name input to `initialBranchName` by default', async () => {
+ const mockInitialBranchName = 'ap1-test-branch-name';
+
+ createComponent({ provide: { initialBranchName: mockInitialBranchName } });
+ await findProjectDropdown().vm.$emit('change', mockProject);
+
+ expect(findInput().attributes('value')).toBe(mockInitialBranchName);
+ });
+ });
+
+ describe('when a source branch is selected', () => {
+ it('sets the `selectedBranchName` prop for SourceBranchDropdown', async () => {
+ createComponent();
+ await completeForm();
+
+ const mockBranchName = 'main';
+ const sourceBranchDropdown = findSourceBranchDropdown();
+ await sourceBranchDropdown.vm.$emit('change', mockBranchName);
+
+ expect(sourceBranchDropdown.props('selectedBranchName')).toBe(mockBranchName);
+ });
+
+ describe.each`
+ branchName | submitButtonDisabled
+ ${undefined} | ${true}
+ ${''} | ${true}
+ ${' '} | ${true}
+ ${'test-branch'} | ${false}
+ `('when branch name is $branchName', ({ branchName, submitButtonDisabled }) => {
+ it(`sets submit button 'disabled' prop to ${submitButtonDisabled}`, async () => {
+ createComponent();
+ await completeForm();
+ await findInput().vm.$emit('input', branchName);
+
+ expect(findButton().props('disabled')).toBe(submitButtonDisabled);
+ });
+ });
+ });
+ });
+
+ describe("when user doesn't have push permissions for the selected project", () => {
+ beforeEach(async () => {
createComponent();
- const mockBranchName = 'main';
- const sourceBranchDropdown = findSourceBranchDropdown();
- await sourceBranchDropdown.vm.$emit('change', mockBranchName);
+ const projectDropdown = findProjectDropdown();
+ await projectDropdown.vm.$emit('change', {
+ ...mockProject,
+ userPermissions: { pushCode: false },
+ });
+ });
+
+ it('displays an alert', () => {
+ const alert = findAlert();
+
+ expect(alert.exists()).toBe(true);
+ expect(findAlertSprintf().attributes('message')).toBe(I18N_NEW_BRANCH_PERMISSION_ALERT);
+ expect(alert.props('variant')).toBe('warning');
+ expect(alert.props('dismissible')).toBe(false);
+ });
- expect(sourceBranchDropdown.props('selectedBranchName')).toBe(mockBranchName);
+ it('hides source branch selection and branch name input', () => {
+ expect(findSourceBranchDropdown().exists()).toBe(false);
+ expect(findInput().exists()).toBe(false);
});
});
});
@@ -181,7 +255,7 @@ describe('NewBranchForm', () => {
it('displays an alert', () => {
const alert = findAlert();
expect(alert.exists()).toBe(true);
- expect(alert.text()).toBe(alertText);
+ expect(findAlertSprintf().attributes('message')).toBe(alertText);
expect(alert.props()).toMatchObject({ title: alertTitle, variant: 'danger' });
});
@@ -192,15 +266,6 @@ describe('NewBranchForm', () => {
});
});
- describe('when `initialBranchName` is specified', () => {
- it('sets value of branch name input to `initialBranchName` by default', () => {
- const mockInitialBranchName = 'ap1-test-branch-name';
-
- createComponent({ provide: { initialBranchName: mockInitialBranchName } });
- expect(findInput().attributes('value')).toBe(mockInitialBranchName);
- });
- });
-
describe('error handling', () => {
describe.each`
component | componentName
@@ -211,13 +276,15 @@ describe('NewBranchForm', () => {
beforeEach(async () => {
createComponent();
+ await completeForm();
await wrapper.findComponent(component).vm.$emit('error', { message: mockErrorMessage });
});
it('displays an alert', () => {
const alert = findAlert();
+
expect(alert.exists()).toBe(true);
- expect(alert.text()).toBe(mockErrorMessage);
+ expect(findAlertSprintf().attributes('message')).toBe(mockErrorMessage);
expect(alert.props('variant')).toBe('danger');
});
diff --git a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
index ec4cb2739f8..136a5967ee4 100644
--- a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
+++ b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
@@ -1,5 +1,12 @@
-import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import {
+ GlAvatarLabeled,
+ GlDropdown,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -7,32 +14,7 @@ import ProjectDropdown from '~/jira_connect/branches/components/project_dropdown
import { PROJECTS_PER_PAGE } from '~/jira_connect/branches/constants';
import getProjectsQuery from '~/jira_connect/branches/graphql/queries/get_projects.query.graphql';
-const localVue = createLocalVue();
-
-const mockProjects = [
- {
- id: 'test',
- name: 'test',
- nameWithNamespace: 'test',
- avatarUrl: 'https://gitlab.com',
- path: 'test-path',
- fullPath: 'test-path',
- repository: {
- empty: false,
- },
- },
- {
- id: 'gitlab',
- name: 'GitLab',
- nameWithNamespace: 'gitlab-org/gitlab',
- avatarUrl: 'https://gitlab.com',
- path: 'gitlab',
- fullPath: 'gitlab-org/gitlab',
- repository: {
- empty: false,
- },
- },
-];
+import { mockProjects } from '../mock_data';
const mockProjectsQueryResponse = {
data: {
@@ -57,12 +39,12 @@ describe('ProjectDropdown', () => {
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findDropdownItemByText = (text) =>
- findAllDropdownItems().wrappers.find((item) => item.text() === text);
+ const findDropdownItemByProjectId = (projectId) =>
+ wrapper.find(`[data-testid="test-project-${projectId}"]`);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
function createMockApolloProvider({ mockGetProjectsQuery = mockGetProjectsQuerySuccess } = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const mockApollo = createMockApollo([[getProjectsQuery, mockGetProjectsQuery]]);
@@ -71,7 +53,6 @@ describe('ProjectDropdown', () => {
function createComponent({ mockApollo, props, mountFn = shallowMount } = {}) {
wrapper = mountFn(ProjectDropdown, {
- localVue,
apolloProvider: mockApollo || createMockApolloProvider(),
propsData: props,
});
@@ -101,25 +82,38 @@ describe('ProjectDropdown', () => {
beforeEach(async () => {
createComponent();
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets dropdown `loading` prop to `false`', () => {
expect(findDropdown().props('loading')).toBe(false);
});
- it('renders dropdown items', () => {
+ it('renders dropdown items with correct props', () => {
const dropdownItems = findAllDropdownItems();
+ const avatars = dropdownItems.wrappers.map((item) => item.findComponent(GlAvatarLabeled));
+ const avatarAttributes = avatars.map((avatar) => avatar.attributes());
+ const avatarProps = avatars.map((avatar) => avatar.props());
+
expect(dropdownItems.wrappers).toHaveLength(mockProjects.length);
- expect(dropdownItems.wrappers.map((item) => item.text())).toEqual(
- mockProjects.map((project) => project.nameWithNamespace),
+ expect(avatarProps).toMatchObject(
+ mockProjects.map((project) => ({
+ label: project.name,
+ subLabel: project.nameWithNamespace,
+ })),
+ );
+ expect(avatarAttributes).toMatchObject(
+ mockProjects.map((project) => ({
+ src: project.avatarUrl,
+ 'entity-name': project.name,
+ })),
);
});
describe('when selecting a dropdown item', () => {
- it('emits `change` event with the selected project name', async () => {
+ it('emits `change` event with the selected project', async () => {
const mockProject = mockProjects[0];
- const itemToSelect = findDropdownItemByText(mockProject.nameWithNamespace);
+ const itemToSelect = findDropdownItemByProjectId(mockProject.id);
await itemToSelect.vm.$emit('click');
expect(wrapper.emitted('change')[0]).toEqual([mockProject]);
@@ -129,14 +123,14 @@ describe('ProjectDropdown', () => {
describe('when `selectedProject` prop is specified', () => {
const mockProject = mockProjects[0];
- beforeEach(async () => {
+ beforeEach(() => {
wrapper.setProps({
selectedProject: mockProject,
});
});
it('sets `isChecked` prop of the corresponding dropdown item to `true`', () => {
- expect(findDropdownItemByText(mockProject.nameWithNamespace).props('isChecked')).toBe(true);
+ expect(findDropdownItemByProjectId(mockProject.id).props('isChecked')).toBe(true);
});
it('sets dropdown text to `selectedBranchName` value', () => {
diff --git a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js
index 9dd11dd6345..56eb6d75def 100644
--- a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js
+++ b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js
@@ -1,22 +1,22 @@
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import SourceBranchDropdown from '~/jira_connect/branches/components/source_branch_dropdown.vue';
import { BRANCHES_PER_PAGE } from '~/jira_connect/branches/constants';
import getProjectQuery from '~/jira_connect/branches/graphql/queries/get_project.query.graphql';
-
-const localVue = createLocalVue();
+import { mockProjects } from '../mock_data';
const mockProject = {
id: 'test',
- fullPath: 'test-path',
repository: {
branchNames: ['main', 'f-test', 'release'],
rootRef: 'main',
},
};
+const mockSelectedProject = mockProjects[0];
const mockProjectQueryResponse = {
data: {
@@ -45,7 +45,7 @@ describe('SourceBranchDropdown', () => {
};
function createMockApolloProvider({ getProjectQueryLoading = false } = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const mockApollo = createMockApollo([
[getProjectQuery, getProjectQueryLoading ? mockQueryLoading : mockGetProjectQuery],
@@ -56,7 +56,6 @@ describe('SourceBranchDropdown', () => {
function createComponent({ mockApollo, props, mountFn = shallowMount } = {}) {
wrapper = mountFn(SourceBranchDropdown, {
- localVue,
apolloProvider: mockApollo || createMockApolloProvider(),
propsData: props,
});
@@ -78,7 +77,7 @@ describe('SourceBranchDropdown', () => {
describe('when `selectedProject` becomes specified', () => {
beforeEach(async () => {
wrapper.setProps({
- selectedProject: mockProject,
+ selectedProject: mockSelectedProject,
});
await waitForPromises();
@@ -103,7 +102,7 @@ describe('SourceBranchDropdown', () => {
it('renders loading icon in dropdown', () => {
createComponent({
mockApollo: createMockApolloProvider({ getProjectQueryLoading: true }),
- props: { selectedProject: mockProject },
+ props: { selectedProject: mockSelectedProject },
});
expect(findLoadingIcon().isVisible()).toBe(true);
@@ -113,7 +112,7 @@ describe('SourceBranchDropdown', () => {
describe('when branches have loaded', () => {
describe('when searching branches', () => {
it('triggers a refetch', async () => {
- createComponent({ mountFn: mount, props: { selectedProject: mockProject } });
+ createComponent({ mountFn: mount, props: { selectedProject: mockSelectedProject } });
await waitForPromises();
jest.clearAllMocks();
@@ -131,7 +130,7 @@ describe('SourceBranchDropdown', () => {
describe('template', () => {
beforeEach(async () => {
- createComponent({ props: { selectedProject: mockProject } });
+ createComponent({ props: { selectedProject: mockSelectedProject } });
await waitForPromises();
});
diff --git a/spec/frontend/jira_connect/branches/mock_data.js b/spec/frontend/jira_connect/branches/mock_data.js
new file mode 100644
index 00000000000..742ab5392c8
--- /dev/null
+++ b/spec/frontend/jira_connect/branches/mock_data.js
@@ -0,0 +1,30 @@
+export const mockProjects = [
+ {
+ id: 'test',
+ name: 'test',
+ nameWithNamespace: 'test',
+ avatarUrl: 'https://gitlab.com',
+ path: 'test-path',
+ fullPath: 'test-path',
+ repository: {
+ empty: false,
+ },
+ userPermissions: {
+ pushCode: true,
+ },
+ },
+ {
+ id: 'gitlab',
+ name: 'GitLab',
+ nameWithNamespace: 'gitlab-org/gitlab',
+ avatarUrl: 'https://gitlab.com',
+ path: 'gitlab',
+ fullPath: 'gitlab-org/gitlab',
+ repository: {
+ empty: false,
+ },
+ userPermissions: {
+ pushCode: true,
+ },
+ },
+];
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js
index 15e9a740c83..b0d5859cd31 100644
--- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
@@ -63,7 +64,7 @@ describe('GroupsListItem', () => {
clickLinkButton();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLinkButton().props('loading')).toBe(true);
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
index 04aba8bda23..d871b1e1dcc 100644
--- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlLoadingIcon, GlSearchBoxByType, GlPagination } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { fetchGroups } from '~/jira_connect/subscriptions/api';
@@ -61,7 +62,7 @@ describe('GroupsList', () => {
fetchGroups.mockReturnValue(new Promise(() => {}));
createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlLoadingIcon().exists()).toBe(true);
});
@@ -100,6 +101,8 @@ describe('GroupsList', () => {
});
createComponent();
+ // wait for the initial loadGroups
+ // to finish.
await waitForPromises();
});
@@ -124,7 +127,7 @@ describe('GroupsList', () => {
findFirstItem().vm.$emit('error', errorMessage);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlAlert().exists()).toBe(true);
expect(findGlAlert().text()).toContain(errorMessage);
@@ -136,10 +139,12 @@ describe('GroupsList', () => {
describe('while groups are loading', () => {
beforeEach(async () => {
fetchGroups.mockClear();
+ // return a never-ending promise to make test
+ // deterministic.
fetchGroups.mockReturnValue(new Promise(() => {}));
findSearchBox().vm.$emit('input', mockSearchTeam);
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls `fetchGroups` with search term', () => {
@@ -172,7 +177,7 @@ describe('GroupsList', () => {
describe('when group search finishes loading', () => {
beforeEach(async () => {
fetchGroups.mockResolvedValue({ data: [mockGroup1] });
- findSearchBox().vm.$emit('input');
+ findSearchBox().vm.$emit('input', mockSearchTeam);
await waitForPromises();
});
@@ -183,32 +188,48 @@ describe('GroupsList', () => {
});
});
- it.each`
- userSearchTerm | finalSearchTerm
- ${'gitl'} | ${'gitl'}
- ${'git'} | ${'git'}
- ${'gi'} | ${''}
- ${'g'} | ${''}
- ${''} | ${''}
- ${undefined} | ${undefined}
+ describe.each`
+ previousSearch | newSearch | shouldSearch | expectedSearchValue
+ ${''} | ${'git'} | ${true} | ${'git'}
+ ${'g'} | ${'git'} | ${true} | ${'git'}
+ ${'git'} | ${'gitl'} | ${true} | ${'gitl'}
+ ${'git'} | ${'gi'} | ${true} | ${''}
+ ${'gi'} | ${'g'} | ${false} | ${undefined}
+ ${'g'} | ${''} | ${false} | ${undefined}
+ ${''} | ${'g'} | ${false} | ${undefined}
`(
- 'searches for "$finalSearchTerm" when user enters "$userSearchTerm"',
- async ({ userSearchTerm, finalSearchTerm }) => {
- fetchGroups.mockResolvedValue({
- data: [mockGroup1],
- headers: { 'X-PAGE': 1, 'X-TOTAL': 1 },
+ 'when previous search was "$previousSearch" and user enters "$newSearch"',
+ ({ previousSearch, newSearch, shouldSearch, expectedSearchValue }) => {
+ beforeEach(async () => {
+ fetchGroups.mockResolvedValue({
+ data: [mockGroup1],
+ headers: { 'X-PAGE': 1, 'X-TOTAL': 1 },
+ });
+
+ // wait for initial load
+ createComponent();
+ await waitForPromises();
+
+ // set up the "previous search"
+ findSearchBox().vm.$emit('input', previousSearch);
+ await waitForPromises();
+
+ fetchGroups.mockClear();
});
- createComponent();
- await waitForPromises();
-
- const searchBox = findSearchBox();
- searchBox.vm.$emit('input', userSearchTerm);
-
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 1,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: finalSearchTerm,
+ it(`${shouldSearch ? 'should' : 'should not'} execute fetch new results`, () => {
+ // enter the new search
+ findSearchBox().vm.$emit('input', newSearch);
+
+ if (shouldSearch) {
+ expect(fetchGroups).toHaveBeenCalledWith(mockGroupsPath, {
+ page: 1,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: expectedSearchValue,
+ });
+ } else {
+ expect(fetchGroups).not.toHaveBeenCalled();
+ }
});
},
);
@@ -226,7 +247,13 @@ describe('GroupsList', () => {
await waitForPromises();
const paginationEl = findPagination();
- paginationEl.vm.$emit('input', 2);
+
+ // mock the response from page 2
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-TOTAL': totalItems, 'X-PAGE': 2 },
+ data: mockGroups,
+ });
+ await paginationEl.vm.$emit('input', 2);
});
it('should load results for page 2', () => {
@@ -237,18 +264,23 @@ describe('GroupsList', () => {
});
});
- it('resets page to 1 on search `input` event', () => {
- const mockSearchTerm = 'gitlab';
- const searchBox = findSearchBox();
-
- searchBox.vm.$emit('input', mockSearchTerm);
+ it.each`
+ scenario | searchTerm | expectedPage | expectedSearchTerm
+ ${'preserves current page'} | ${'gi'} | ${2} | ${''}
+ ${'resets page to 1'} | ${'gitlab'} | ${1} | ${'gitlab'}
+ `(
+ '$scenario when search term is $searchTerm',
+ ({ searchTerm, expectedPage, expectedSearchTerm }) => {
+ const searchBox = findSearchBox();
+ searchBox.vm.$emit('input', searchTerm);
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 1,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: mockSearchTerm,
- });
- });
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: expectedPage,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: expectedSearchTerm,
+ });
+ },
+ );
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
index 47fe96262ee..aa0f1440b20 100644
--- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
@@ -1,10 +1,10 @@
-import { GlAlert, GlLink, GlEmptyState } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
-import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
-import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
-import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
+import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue';
+import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue';
import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
@@ -20,14 +20,12 @@ describe('JiraConnectApp', () => {
let wrapper;
let store;
- const findAlert = () => wrapper.findComponent(GlAlert);
+ const findAlert = () => wrapper.findByTestId('jira-connect-persisted-alert');
const findAlertLink = () => findAlert().findComponent(GlLink);
- const findSignInButton = () => wrapper.findComponent(SignInButton);
- const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
- const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findSignInPage = () => wrapper.findComponent(SignInPage);
+ const findSubscriptionsPage = () => wrapper.findComponent(SubscriptionsPage);
- const createComponent = ({ provide, mountFn = shallowMount } = {}) => {
+ const createComponent = ({ provide, mountFn = shallowMountExtended } = {}) => {
store = createStore();
wrapper = mountFn(JiraConnectApp, {
@@ -42,49 +40,35 @@ describe('JiraConnectApp', () => {
describe('template', () => {
describe.each`
- scenario | usersPath | subscriptions | expectSignInButton | expectEmptyState | expectNamespaceButton | expectSubscriptionsList
- ${'user is not signed in with subscriptions'} | ${'/users'} | ${[mockSubscription]} | ${true} | ${false} | ${false} | ${true}
- ${'user is not signed in without subscriptions'} | ${'/users'} | ${undefined} | ${true} | ${false} | ${false} | ${false}
- ${'user is signed in with subscriptions'} | ${undefined} | ${[mockSubscription]} | ${false} | ${false} | ${true} | ${true}
- ${'user is signed in without subscriptions'} | ${undefined} | ${undefined} | ${false} | ${true} | ${false} | ${false}
- `(
- 'when $scenario',
- ({
- usersPath,
- expectSignInButton,
- subscriptions,
- expectEmptyState,
- expectNamespaceButton,
- expectSubscriptionsList,
- }) => {
- beforeEach(() => {
- createComponent({
- provide: {
- usersPath,
- subscriptions,
- },
- });
- });
-
- it(`${expectSignInButton ? 'renders' : 'does not render'} sign in button`, () => {
- expect(findSignInButton().exists()).toBe(expectSignInButton);
- });
-
- it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => {
- expect(findEmptyState().exists()).toBe(expectEmptyState);
+ scenario | usersPath | shouldRenderSignInPage | shouldRenderSubscriptionsPage
+ ${'user is not signed in'} | ${'/users'} | ${true} | ${false}
+ ${'user is signed in'} | ${undefined} | ${false} | ${true}
+ `('when $scenario', ({ usersPath, shouldRenderSignInPage, shouldRenderSubscriptionsPage }) => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ usersPath,
+ subscriptions: [mockSubscription],
+ },
});
+ });
- it(`${
- expectNamespaceButton ? 'renders' : 'does not render'
- } button to add namespace`, () => {
- expect(findAddNamespaceButton().exists()).toBe(expectNamespaceButton);
- });
+ it(`${shouldRenderSignInPage ? 'renders' : 'does not render'} sign in page`, () => {
+ expect(findSignInPage().exists()).toBe(shouldRenderSignInPage);
+ if (shouldRenderSignInPage) {
+ expect(findSignInPage().props('hasSubscriptions')).toBe(true);
+ }
+ });
- it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
- expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
- });
- },
- );
+ it(`${
+ shouldRenderSubscriptionsPage ? 'renders' : 'does not render'
+ } subscriptions page`, () => {
+ expect(findSubscriptionsPage().exists()).toBe(shouldRenderSubscriptionsPage);
+ if (shouldRenderSubscriptionsPage) {
+ expect(findSubscriptionsPage().props('hasSubscriptions')).toBe(true);
+ }
+ });
+ });
it('renders UserLink component', () => {
createComponent({
@@ -116,7 +100,7 @@ describe('JiraConnectApp', () => {
createComponent();
store.commit(SET_ALERT, { message, variant });
- await wrapper.vm.$nextTick();
+ await nextTick();
const alert = findAlert();
@@ -134,22 +118,22 @@ describe('JiraConnectApp', () => {
createComponent();
store.commit(SET_ALERT, { message: 'test message' });
- await wrapper.vm.$nextTick();
+ await nextTick();
findAlert().vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().exists()).toBe(false);
});
it('renders link when `linkUrl` is set', async () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
store.commit(SET_ALERT, {
message: __('test message %{linkStart}test link%{linkEnd}'),
linkUrl: 'https://gitlab.com',
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const alertLink = findAlertLink();
diff --git a/spec/frontend/jira_connect/subscriptions/components/compatibility_alert_spec.js b/spec/frontend/jira_connect/subscriptions/components/compatibility_alert_spec.js
new file mode 100644
index 00000000000..f8ee8c2c664
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/compatibility_alert_spec.js
@@ -0,0 +1,56 @@
+import { GlAlert, GlLink } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+import CompatibilityAlert from '~/jira_connect/subscriptions/components/compatibility_alert.vue';
+
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+
+describe('CompatibilityAlert', () => {
+ let wrapper;
+
+ const createComponent = ({ mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(CompatibilityAlert);
+ };
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays an alert', () => {
+ createComponent();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('renders help link with target="_blank" and rel="noopener noreferrer"', () => {
+ createComponent({ mountFn: mount });
+ expect(findLink().attributes()).toMatchObject({
+ target: '_blank',
+ rel: 'noopener noreferrer',
+ });
+ });
+
+ it('`local-storage-sync` value prop is initially false', () => {
+ createComponent();
+
+ expect(findLocalStorageSync().props('value')).toBe(false);
+ });
+
+ describe('when dismissed', () => {
+ beforeEach(async () => {
+ createComponent();
+ await findAlert().vm.$emit('dismiss');
+ });
+
+ it('hides alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('updates value prop of `local-storage-sync`', () => {
+ expect(findLocalStorageSync().props('value')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
index cb5ae877c47..94dcf9decec 100644
--- a/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
@@ -11,11 +11,12 @@ jest.mock('~/jira_connect/subscriptions/utils');
describe('SignInButton', () => {
let wrapper;
- const createComponent = () => {
+ const createComponent = ({ slots } = {}) => {
wrapper = shallowMount(SignInButton, {
propsData: {
usersPath: MOCK_USERS_PATH,
},
+ slots,
});
};
@@ -29,6 +30,7 @@ describe('SignInButton', () => {
createComponent();
expect(findButton().exists()).toBe(true);
+ expect(findButton().text()).toBe(SignInButton.i18n.defaultButtonText);
});
describe.each`
@@ -45,4 +47,12 @@ describe('SignInButton', () => {
expect(findButton().attributes('href')).toBe(expectedHref);
});
});
+
+ describe('with slot', () => {
+ const mockSlotContent = 'custom button content!';
+ it('renders slot content in button', () => {
+ createComponent({ slots: { default: mockSlotContent } });
+ expect(wrapper.text()).toMatchInterpolatedText(mockSlotContent);
+ });
+ });
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
index 4e4a2b58600..2aad533f677 100644
--- a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
@@ -71,7 +72,7 @@ describe('SubscriptionsList', () => {
clickUnlinkButton();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findUnlinkButton().props('loading')).toBe(true);
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js
new file mode 100644
index 00000000000..4e3297506f1
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js
@@ -0,0 +1,62 @@
+import { mount } from '@vue/test-utils';
+
+import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue';
+import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
+import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
+import createStore from '~/jira_connect/subscriptions/store';
+
+jest.mock('~/jira_connect/subscriptions/utils');
+
+describe('SignInPage', () => {
+ let wrapper;
+ let store;
+
+ const findSignInButton = () => wrapper.findComponent(SignInButton);
+ const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
+
+ const createComponent = ({ provide, props } = {}) => {
+ store = createStore();
+
+ wrapper = mount(SignInPage, {
+ store,
+ provide,
+ propsData: props,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ const mockUsersPath = '/test';
+ describe.each`
+ scenario | expectSubscriptionsList | signInButtonText
+ ${'with subscriptions'} | ${true} | ${SignInPage.i18n.signinButtonTextWithSubscriptions}
+ ${'without subscriptions'} | ${false} | ${SignInButton.i18n.defaultButtonText}
+ `('$scenario', ({ expectSubscriptionsList, signInButtonText }) => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ usersPath: mockUsersPath,
+ },
+ props: {
+ hasSubscriptions: expectSubscriptionsList,
+ },
+ });
+ });
+
+ it(`renders sign in button with text ${signInButtonText}`, () => {
+ expect(findSignInButton().text()).toMatchInterpolatedText(signInButtonText);
+ });
+
+ it('renders sign in button with `usersPath` prop', () => {
+ expect(findSignInButton().props('usersPath')).toBe(mockUsersPath);
+ });
+
+ it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
+ expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/pages/subscriptions_spec.js b/spec/frontend/jira_connect/subscriptions/pages/subscriptions_spec.js
new file mode 100644
index 00000000000..198278efc1f
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/pages/subscriptions_spec.js
@@ -0,0 +1,56 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue';
+import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
+import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
+import createStore from '~/jira_connect/subscriptions/store';
+
+describe('SubscriptionsPage', () => {
+ let wrapper;
+ let store;
+
+ const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
+ const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+
+ const createComponent = ({ props } = {}) => {
+ store = createStore();
+
+ wrapper = shallowMount(SubscriptionsPage, {
+ store,
+ propsData: props,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ describe.each`
+ scenario | expectSubscriptionsList | expectEmptyState
+ ${'with subscriptions'} | ${true} | ${false}
+ ${'without subscriptions'} | ${false} | ${true}
+ `('$scenario', ({ expectEmptyState, expectSubscriptionsList }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ hasSubscriptions: expectSubscriptionsList,
+ },
+ });
+ });
+
+ it('renders button to add namespace', () => {
+ expect(findAddNamespaceButton().exists()).toBe(true);
+ });
+
+ it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => {
+ expect(findEmptyState().exists()).toBe(expectEmptyState);
+ });
+
+ it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
+ expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_import/components/jira_import_app_spec.js b/spec/frontend/jira_import/components/jira_import_app_spec.js
index 27314a0eb6e..cd8024d4962 100644
--- a/spec/frontend/jira_import/components/jira_import_app_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_app_spec.js
@@ -1,6 +1,6 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import JiraImportApp from '~/jira_import/components/jira_import_app.vue';
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
import JiraImportProgress from '~/jira_import/components/jira_import_progress.vue';
@@ -230,7 +230,7 @@ describe('JiraImportApp', () => {
getFormComponent().vm.$emit('error', 'There was an error');
- await Vue.nextTick();
+ await nextTick();
expect(getAlert().exists()).toBe(true);
});
@@ -248,7 +248,7 @@ describe('JiraImportApp', () => {
getAlert().vm.$emit('dismiss');
- await Vue.nextTick();
+ await nextTick();
expect(getAlert().exists()).toBe(false);
});
diff --git a/spec/frontend/jobs/bridge/app_spec.js b/spec/frontend/jobs/bridge/app_spec.js
index c0faab90552..210dcfa364b 100644
--- a/spec/frontend/jobs/bridge/app_spec.js
+++ b/spec/frontend/jobs/bridge/app_spec.js
@@ -1,5 +1,6 @@
-import { nextTick } from 'vue';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import { GlLoadingIcon } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
@@ -17,9 +18,6 @@ import {
mockPipelineQueryResponse,
} from './mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
describe('Bridge Show Page', () => {
let wrapper;
let mockApollo;
@@ -47,10 +45,10 @@ describe('Bridge Show Page', () => {
const createComponentWithApollo = () => {
const handlers = [[getPipelineQuery, mockPipelineQuery]];
+ Vue.use(VueApollo);
mockApollo = createMockApollo(handlers);
createComponent({
- localVue,
apolloProvider: mockApollo,
mocks: {},
});
@@ -81,10 +79,10 @@ describe('Bridge Show Page', () => {
});
describe('after pipeline query is loaded', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockPipelineQuery.mockResolvedValue(mockPipelineQueryResponse);
createComponentWithApollo();
- waitForPromises();
+ await waitForPromises();
});
it('query is called with correct variables', async () => {
@@ -109,10 +107,10 @@ describe('Bridge Show Page', () => {
});
describe('sidebar expansion', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockPipelineQuery.mockResolvedValue(mockPipelineQueryResponse);
createComponentWithApollo();
- waitForPromises();
+ await waitForPromises();
});
describe('on resize', () => {
diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js
index 07e6ee46c41..d4e1e711777 100644
--- a/spec/frontend/jobs/components/job_app_spec.js
+++ b/spec/frontend/jobs/components/job_app_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import delayedJobFixture from 'test_fixtures/jobs/delayed.json';
@@ -16,8 +17,7 @@ import axios from '~/lib/utils/axios_utils';
import job from '../mock_data';
describe('Job App', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
let store;
let wrapper;
@@ -45,7 +45,7 @@ describe('Job App', () => {
wrapper = mount(JobApp, { propsData: { ...props }, store });
};
- const setupAndMount = ({ jobData = {}, jobLogData = {} } = {}) => {
+ const setupAndMount = async ({ jobData = {}, jobLogData = {} } = {}) => {
mock.onGet(initSettings.endpoint).replyOnce(200, { ...job, ...jobData });
mock.onGet(`${initSettings.pagePath}/trace.json`).reply(200, jobLogData);
@@ -53,12 +53,10 @@ describe('Job App', () => {
createComponent();
- return asyncInit
- .then(() => {
- jest.runOnlyPendingTimers();
- })
- .then(() => axios.waitForAll())
- .then(() => wrapper.vm.$nextTick());
+ await asyncInit;
+ jest.runOnlyPendingTimers();
+ await axios.waitForAll();
+ await nextTick();
};
const findLoadingComponent = () => wrapper.find(GlLoadingIcon);
diff --git a/spec/frontend/jobs/components/job_container_item_spec.js b/spec/frontend/jobs/components/job_container_item_spec.js
index 6b488821bc1..eb2b0184e5f 100644
--- a/spec/frontend/jobs/components/job_container_item_spec.js
+++ b/spec/frontend/jobs/components/job_container_item_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import delayedJobFixture from 'test_fixtures/jobs/delayed.json';
import JobContainerItem from '~/jobs/components/job_container_item.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -87,7 +88,7 @@ describe('JobContainerItem', () => {
});
it('displays remaining time in tooltip', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
const link = wrapper.findComponent(GlLink);
diff --git a/spec/frontend/jobs/components/job_log_controllers_spec.js b/spec/frontend/jobs/components/job_log_controllers_spec.js
index 0ba07522243..226322a2951 100644
--- a/spec/frontend/jobs/components/job_log_controllers_spec.js
+++ b/spec/frontend/jobs/components/job_log_controllers_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import JobLogControllers from '~/jobs/components/job_log_controllers.vue';
describe('Job log controllers', () => {
@@ -111,7 +112,7 @@ describe('Job log controllers', () => {
it('emits scrollJobLogTop event on click', async () => {
findScrollTop().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().scrollJobLogTop).toHaveLength(1);
});
@@ -133,7 +134,7 @@ describe('Job log controllers', () => {
it('does not emit scrollJobLogTop event on click', async () => {
findScrollTop().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().scrollJobLogTop).toBeUndefined();
});
@@ -149,7 +150,7 @@ describe('Job log controllers', () => {
it('emits scrollJobLogBottom event on click', async () => {
findScrollBottom().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().scrollJobLogBottom).toHaveLength(1);
});
@@ -171,7 +172,7 @@ describe('Job log controllers', () => {
it('does not emit scrollJobLogBottom event on click', async () => {
findScrollBottom().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().scrollJobLogBottom).toBeUndefined();
});
diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js
index 96bdf03796b..22ddc8b1c2d 100644
--- a/spec/frontend/jobs/components/log/collapsible_section_spec.js
+++ b/spec/frontend/jobs/components/log/collapsible_section_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CollapsibleSection from '~/jobs/components/log/collapsible_section.vue';
import { collapsibleSectionClosed, collapsibleSectionOpened } from './mock_data';
@@ -69,7 +70,7 @@ describe('Job Log Collapsible Section', () => {
});
});
- it('emits onClickCollapsibleLine on click', () => {
+ it('emits onClickCollapsibleLine on click', async () => {
createComponent({
section: collapsibleSectionOpened,
jobLogEndpoint,
@@ -77,8 +78,7 @@ describe('Job Log Collapsible Section', () => {
findCollapsibleLine().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('onClickCollapsibleLine').length).toBe(1);
- });
+ await nextTick();
+ expect(wrapper.emitted('onClickCollapsibleLine').length).toBe(1);
});
});
diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js
index 9763e2f437b..8055fe64d95 100644
--- a/spec/frontend/jobs/components/log/line_header_spec.js
+++ b/spec/frontend/jobs/components/log/line_header_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DurationBadge from '~/jobs/components/log/duration_badge.vue';
import LineHeader from '~/jobs/components/log/line_header.vue';
import LineNumber from '~/jobs/components/log/line_number.vue';
@@ -75,12 +76,11 @@ describe('Job Log Header Line', () => {
createComponent(data);
});
- it('emits toggleLine event', () => {
+ it('emits toggleLine event', async () => {
wrapper.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleLine.length).toBe(1);
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleLine.length).toBe(1);
});
});
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index 9a5522ab4cd..7e11738f82e 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import Log from '~/jobs/components/log/log.vue';
import { logLinesParserLegacy, logLinesParser } from '~/jobs/store/utils';
@@ -11,12 +12,10 @@ describe('Job Log', () => {
let store;
let origGon;
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const createComponent = () => {
wrapper = mount(Log, {
- localVue,
store,
});
};
@@ -91,12 +90,10 @@ describe('Job Log, infinitelyCollapsibleSections feature flag enabled', () => {
let store;
let origGon;
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const createComponent = () => {
wrapper = mount(Log, {
- localVue,
store,
});
};
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index a5278af8e33..6faab3ddf31 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -1,12 +1,10 @@
import { GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ManualVariablesForm from '~/jobs/components/manual_variables_form.vue';
-const localVue = createLocalVue();
-
Vue.use(Vuex);
describe('Manual Variables Form', () => {
@@ -29,9 +27,8 @@ describe('Manual Variables Form', () => {
});
wrapper = extendedWrapper(
- mount(localVue.extend(ManualVariablesForm), {
+ mount(ManualVariablesForm, {
propsData: { ...requiredProps, ...props },
- localVue,
store,
stubs: {
GlSprintf,
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 500a1b48950..6e327725627 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ArtifactsBlock from '~/jobs/components/artifacts_block.vue';
import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
@@ -189,7 +190,7 @@ describe('Sidebar details block', () => {
locked: false,
};
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findArtifactsBlock().exists()).toBe(true);
});
diff --git a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
index 6caf36e1461..263698e94e1 100644
--- a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
+++ b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
@@ -1,13 +1,16 @@
import { GlModal } from '@gitlab/ui';
import { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
import JobRetryMutation from '~/jobs/components/table/graphql/mutations/job_retry.mutation.graphql';
import JobUnscheduleMutation from '~/jobs/components/table/graphql/mutations/job_unschedule.mutation.graphql';
+import JobCancelMutation from '~/jobs/components/table/graphql/mutations/job_cancel.mutation.graphql';
import {
playableJob,
retryableJob,
+ cancelableJob,
scheduledJob,
cannotRetryJob,
cannotPlayJob,
@@ -20,6 +23,7 @@ describe('Job actions cell', () => {
const findRetryButton = () => wrapper.findByTestId('retry');
const findPlayButton = () => wrapper.findByTestId('play');
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
const findDownloadArtifactsButton = () => wrapper.findByTestId('download-artifacts');
const findCountdownButton = () => wrapper.findByTestId('countdown');
const findPlayScheduledJobButton = () => wrapper.findByTestId('play-scheduled');
@@ -32,6 +36,7 @@ describe('Job actions cell', () => {
data: { JobUnscheduleMutation: { jobId: scheduledJob.id } },
};
const MUTATION_SUCCESS_PLAY = { data: { JobPlayMutation: { jobId: playableJob.id } } };
+ const MUTATION_SUCCESS_CANCEL = { data: { JobCancelMutation: { jobId: cancelableJob.id } } };
const $toast = {
show: jest.fn(),
@@ -88,6 +93,7 @@ describe('Job actions cell', () => {
${findPlayButton} | ${'play'} | ${playableJob}
${findRetryButton} | ${'retry'} | ${retryableJob}
${findDownloadArtifactsButton} | ${'download artifacts'} | ${playableJob}
+ ${findCancelButton} | ${'cancel'} | ${cancelableJob}
`('displays the $action button', ({ button, jobType }) => {
createComponent(jobType);
@@ -95,9 +101,10 @@ describe('Job actions cell', () => {
});
it.each`
- button | mutationResult | action | jobType | mutationFile
- ${findPlayButton} | ${MUTATION_SUCCESS_PLAY} | ${'play'} | ${playableJob} | ${JobPlayMutation}
- ${findRetryButton} | ${MUTATION_SUCCESS} | ${'retry'} | ${retryableJob} | ${JobRetryMutation}
+ button | mutationResult | action | jobType | mutationFile
+ ${findPlayButton} | ${MUTATION_SUCCESS_PLAY} | ${'play'} | ${playableJob} | ${JobPlayMutation}
+ ${findRetryButton} | ${MUTATION_SUCCESS} | ${'retry'} | ${retryableJob} | ${JobRetryMutation}
+ ${findCancelButton} | ${MUTATION_SUCCESS_CANCEL} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation}
`('performs the $action mutation', ({ button, mutationResult, jobType, mutationFile }) => {
createComponent(jobType, mutationResult);
@@ -111,6 +118,24 @@ describe('Job actions cell', () => {
});
});
+ it.each`
+ button | action | jobType
+ ${findPlayButton} | ${'play'} | ${playableJob}
+ ${findRetryButton} | ${'retry'} | ${retryableJob}
+ ${findCancelButton} | ${'cancel'} | ${cancelableJob}
+ ${findUnscheduleButton} | ${'unschedule'} | ${scheduledJob}
+ `('disables the $action button after first request', async ({ button, jobType }) => {
+ createComponent(jobType);
+
+ expect(button().props('disabled')).toBe(false);
+
+ button().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(button().props('disabled')).toBe(true);
+ });
+
describe('Scheduled Jobs', () => {
const today = () => new Date('2021-08-31');
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 05988eecb10..5ccd38af735 100644
--- a/spec/frontend/jobs/components/table/job_table_app_spec.js
+++ b/spec/frontend/jobs/components/table/job_table_app_spec.js
@@ -1,5 +1,6 @@
import { GlSkeletonLoader, GlAlert, GlEmptyState, GlPagination } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -7,11 +8,15 @@ import getJobsQuery from '~/jobs/components/table/graphql/queries/get_jobs.query
import JobsTable from '~/jobs/components/table/jobs_table.vue';
import JobsTableApp from '~/jobs/components/table/jobs_table_app.vue';
import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue';
-import { mockJobsQueryResponse, mockJobsQueryEmptyResponse } from '../../mock_data';
+import {
+ mockJobsQueryResponse,
+ mockJobsQueryEmptyResponse,
+ mockJobsQueryResponseLastPage,
+ mockJobsQueryResponseFirstPage,
+} from '../../mock_data';
const projectPath = 'gitlab-org/gitlab';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Job table app', () => {
let wrapper;
@@ -50,7 +55,6 @@ describe('Job table app', () => {
provide: {
projectPath,
},
- localVue,
apolloProvider: createMockApolloProvider(handler),
});
};
@@ -96,35 +100,14 @@ describe('Job table app', () => {
describe('pagination', () => {
it('should disable the next page button on the last page', async () => {
createComponent({
- handler: successHandler,
+ handler: jest.fn().mockResolvedValue(mockJobsQueryResponseLastPage),
mountFn: mount,
data: {
- pagination: {
- currentPage: 3,
- },
- jobs: {
- pageInfo: {
- hasPreviousPage: true,
- startCursor: 'abc',
- endCursor: 'bcd',
- },
- },
+ pagination: { currentPage: 3 },
},
});
- await wrapper.vm.$nextTick();
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- jobs: {
- pageInfo: {
- hasNextPage: false,
- },
- },
- });
-
- await wrapper.vm.$nextTick();
+ await waitForPromises();
expect(findPrevious().exists()).toBe(true);
expect(findNext().exists()).toBe(true);
@@ -133,24 +116,16 @@ describe('Job table app', () => {
it('should disable the previous page button on the first page', async () => {
createComponent({
- handler: successHandler,
+ handler: jest.fn().mockResolvedValue(mockJobsQueryResponseFirstPage),
mountFn: mount,
data: {
pagination: {
currentPage: 1,
},
- jobs: {
- pageInfo: {
- hasNextPage: true,
- hasPreviousPage: false,
- startCursor: 'abc',
- endCursor: 'bcd',
- },
- },
},
});
- await wrapper.vm.$nextTick();
+ await waitForPromises();
expect(findPrevious().exists()).toBe(true);
expect(findPrevious().classes('disabled')).toBe(true);
diff --git a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
index 63dcd72f967..1d3845b19bb 100644
--- a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
+++ b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import delayedJobFixture from 'test_fixtures/jobs/delayed.json';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
@@ -34,7 +35,7 @@ describe('DelayedJobMixin', () => {
});
it('does not update remaining time after mounting', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).toBe('00:00:00');
});
@@ -57,7 +58,7 @@ describe('DelayedJobMixin', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets remaining time', () => {
@@ -68,7 +69,7 @@ describe('DelayedJobMixin', () => {
remainingTimeInMilliseconds = 41000;
jest.advanceTimersByTime(1000);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).toBe('00:00:41');
});
});
@@ -104,7 +105,7 @@ describe('DelayedJobMixin', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets remaining time', () => {
@@ -115,7 +116,7 @@ describe('DelayedJobMixin', () => {
remainingTimeInMilliseconds = 41000;
jest.advanceTimersByTime(1000);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).toBe('00:00:41');
});
});
diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js
index 45d297ba364..2be78bac8a9 100644
--- a/spec/frontend/jobs/mock_data.js
+++ b/spec/frontend/jobs/mock_data.js
@@ -1579,6 +1579,44 @@ export const mockJobsQueryResponse = {
},
};
+export const mockJobsQueryResponseLastPage = {
+ data: {
+ project: {
+ id: '1',
+ jobs: {
+ ...mockJobsQueryResponse.data.project.jobs,
+ pageInfo: {
+ endCursor: 'eyJpZCI6IjIzMTcifQ',
+ hasNextPage: false,
+ hasPreviousPage: true,
+ startCursor: 'eyJpZCI6IjIzMzYifQ',
+ __typename: 'PageInfo',
+ },
+ },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockJobsQueryResponseFirstPage = {
+ data: {
+ project: {
+ id: '1',
+ jobs: {
+ ...mockJobsQueryResponse.data.project.jobs,
+ pageInfo: {
+ endCursor: 'eyJpZCI6IjIzMTcifQ',
+ hasNextPage: true,
+ hasPreviousPage: false,
+ startCursor: 'eyJpZCI6IjIzMzYifQ',
+ __typename: 'PageInfo',
+ },
+ },
+ __typename: 'Project',
+ },
+ },
+};
+
export const mockJobsQueryEmptyResponse = {
data: {
project: {
@@ -1653,6 +1691,65 @@ export const retryableJob = {
__typename: 'CiJob',
};
+export const cancelableJob = {
+ artifacts: {
+ nodes: [],
+ __typename: 'CiJobArtifactConnection',
+ },
+ allowFailure: false,
+ status: 'PENDING',
+ scheduledAt: null,
+ manualJob: false,
+ triggered: null,
+ createdByTag: false,
+ detailedStatus: {
+ id: 'pending-1305-1305',
+ detailsPath: '/root/lots-of-jobs-project/-/jobs/1305',
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ tooltip: 'pending',
+ action: {
+ id: 'Ci::Build-pending-1305',
+ buttonTitle: 'Cancel this job',
+ icon: 'cancel',
+ method: 'post',
+ path: '/root/lots-of-jobs-project/-/jobs/1305/cancel',
+ title: 'Cancel',
+ __typename: 'StatusAction',
+ },
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/1305',
+ refName: 'main',
+ refPath: '/root/lots-of-jobs-project/-/commits/main',
+ tags: [],
+ shortSha: '750605f2',
+ commitPath: '/root/lots-of-jobs-project/-/commit/750605f29530778cf0912779eba6d073128962a5',
+ stage: {
+ id: 'gid://gitlab/Ci::Stage/181',
+ name: 'deploy',
+ __typename: 'CiStage',
+ },
+ name: 'job_212',
+ duration: null,
+ finishedAt: null,
+ coverage: null,
+ retryable: false,
+ playable: false,
+ cancelable: true,
+ active: true,
+ stuck: false,
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: true,
+ __typename: 'JobPermissions',
+ },
+ __typename: 'CiJob',
+};
+
export const cannotRetryJob = {
...retryableJob,
userPermissions: { readBuild: true, updateBuild: false, __typename: 'JobPermissions' },
diff --git a/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js b/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
index 7b604724977..971ba8b583c 100644
--- a/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
+++ b/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
import waitForPromises from 'helpers/wait_for_promises';
import { getSuppressNetworkErrorsDuringNavigationLink } from '~/lib/apollo/suppress_network_errors_during_navigation_link';
import { isNavigatingAway } from '~/lib/utils/is_navigating_away';
diff --git a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
index c0e5b06651f..e58bc063004 100644
--- a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
+++ b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
@@ -1,4 +1,4 @@
-import { ApolloLink, Observable } from 'apollo-link';
+import { ApolloLink, Observable } from '@apollo/client/core';
import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
describe('StartupJSLink', () => {
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 3e2ba918d9b..3fea08d5512 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -394,8 +394,7 @@ describe('common_utils', () => {
describe('backOff', () => {
beforeEach(() => {
- // shortcut our timeouts otherwise these tests will take a long time to finish
- jest.spyOn(window, 'setTimeout').mockImplementation((cb) => setImmediate(cb, 0));
+ jest.spyOn(window, 'setTimeout');
});
it('solves the promise from the callback', (done) => {
@@ -446,6 +445,7 @@ describe('common_utils', () => {
if (numberOfCalls < 3) {
numberOfCalls += 1;
next();
+ jest.runOnlyPendingTimers();
} else {
stop(resp);
}
@@ -464,7 +464,10 @@ describe('common_utils', () => {
it('rejects the backOff promise after timing out', (done) => {
commonUtils
- .backOff((next) => next(), 64000)
+ .backOff((next) => {
+ next();
+ jest.runOnlyPendingTimers();
+ }, 64000)
.catch((errBackoffResp) => {
const timeouts = window.setTimeout.mock.calls.map(([, timeout]) => timeout);
diff --git a/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
index d19f9352bbc..e06d1384610 100644
--- a/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
+++ b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
@@ -6,11 +6,13 @@ describe('Confirm Modal', () => {
let wrapper;
let modal;
- const createComponent = ({ primaryText, primaryVariant } = {}) => {
+ const createComponent = ({ primaryText, primaryVariant, title, hideCancel = false } = {}) => {
wrapper = mount(ConfirmModal, {
propsData: {
primaryText,
primaryVariant,
+ hideCancel,
+ title,
},
});
};
@@ -55,5 +57,19 @@ describe('Confirm Modal', () => {
expect(customProps.text).toBe('OK');
expect(customProps.attributes.variant).toBe('confirm');
});
+
+ it('should hide the cancel button if `hideCancel` is set', () => {
+ createComponent({ hideCancel: true });
+ const props = findGlModal().props();
+
+ expect(props.actionCancel).toBeNull();
+ });
+
+ it('should set the modal title when the `title` prop is set', () => {
+ const title = 'Modal title';
+ createComponent({ title });
+
+ expect(findGlModal().props().title).toBe(title);
+ });
});
});
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index e743678ea90..dc4aa0ea5ed 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -4,6 +4,7 @@ import {
bytesToMiB,
bytesToGiB,
numberToHumanSize,
+ numberToMetricPrefix,
sum,
isOdd,
median,
@@ -99,6 +100,21 @@ describe('Number Utils', () => {
});
});
+ describe('numberToMetricPrefix', () => {
+ it.each`
+ number | expected
+ ${123} | ${'123'}
+ ${1234} | ${'1.2k'}
+ ${12345} | ${'12.3k'}
+ ${123456} | ${'123.5k'}
+ ${1234567} | ${'1.2m'}
+ ${12345678} | ${'12.3m'}
+ ${123456789} | ${'123.5m'}
+ `('returns $expected given $number', ({ number, expected }) => {
+ expect(numberToMetricPrefix(number)).toBe(expected);
+ });
+ });
+
describe('sum', () => {
it('should add up two values', () => {
expect(sum(1, 2)).toEqual(3);
diff --git a/spec/frontend/lib/utils/table_utility_spec.js b/spec/frontend/lib/utils/table_utility_spec.js
index 75b9252aa40..0ceccbe4c74 100644
--- a/spec/frontend/lib/utils/table_utility_spec.js
+++ b/spec/frontend/lib/utils/table_utility_spec.js
@@ -8,4 +8,35 @@ describe('table_utility', () => {
expect(tableUtils.thWidthClass(width)).toBe(`gl-w-${width}p ${DEFAULT_TH_CLASSES}`);
});
});
+
+ describe('sortObjectToString', () => {
+ it('returns the expected sorting string ending in "DESC" when sortDesc is true', () => {
+ expect(tableUtils.sortObjectToString({ sortBy: 'mergedAt', sortDesc: true })).toBe(
+ 'MERGED_AT_DESC',
+ );
+ });
+
+ it('returns the expected sorting string ending in "ASC" when sortDesc is false', () => {
+ expect(tableUtils.sortObjectToString({ sortBy: 'mergedAt', sortDesc: false })).toBe(
+ 'MERGED_AT_ASC',
+ );
+ });
+ });
+
+ describe('sortStringToObject', () => {
+ it.each`
+ sortBy | sortDesc | sortString
+ ${'mergedAt'} | ${true} | ${'MERGED_AT_DESC'}
+ ${'mergedAt'} | ${false} | ${'MERGED_AT_ASC'}
+ ${'severity'} | ${true} | ${'SEVERITY_DESC'}
+ ${'severity'} | ${false} | ${'SEVERITY_ASC'}
+ ${null} | ${null} | ${'SEVERITY'}
+ ${null} | ${null} | ${''}
+ `(
+ 'returns the expected sort object when the sort string is "$sortString"',
+ ({ sortBy, sortDesc, sortString }) => {
+ expect(tableUtils.sortStringToObject(sortString)).toStrictEqual({ sortBy, sortDesc });
+ },
+ );
+ });
});
diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js
index ab81ec47b64..dded32cc890 100644
--- a/spec/frontend/lib/utils/text_markdown_spec.js
+++ b/spec/frontend/lib/utils/text_markdown_spec.js
@@ -165,6 +165,80 @@ describe('init markdown', () => {
// cursor placement should be between tags
expect(textArea.selectionStart).toBe(start.length + tag.length);
});
+
+ describe('Continuing markdown lists', () => {
+ const enterEvent = new KeyboardEvent('keydown', { key: 'Enter' });
+
+ beforeEach(() => {
+ gon.features = { markdownContinueLists: true };
+ });
+
+ it.each`
+ text | expected
+ ${'- item'} | ${'- item\n- '}
+ ${'- [ ] item'} | ${'- [ ] item\n- [ ] '}
+ ${'- [x] item'} | ${'- [x] item\n- [x] '}
+ ${'- item\n - second'} | ${'- item\n - second\n - '}
+ ${'1. item'} | ${'1. item\n1. '}
+ ${'1. [ ] item'} | ${'1. [ ] item\n1. [ ] '}
+ ${'1. [x] item'} | ${'1. [x] item\n1. [x] '}
+ ${'108. item'} | ${'108. item\n108. '}
+ ${'108. item\n - second'} | ${'108. item\n - second\n - '}
+ ${'108. item\n 1. second'} | ${'108. item\n 1. second\n 1. '}
+ `('adds correct list continuation characters', ({ text, expected }) => {
+ textArea.value = text;
+ textArea.setSelectionRange(text.length, text.length);
+
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.dispatchEvent(enterEvent);
+
+ expect(textArea.value).toEqual(expected);
+ expect(textArea.selectionStart).toBe(expected.length);
+ });
+
+ // test that when pressing Enter on an empty list item, the empty
+ // list item text is selected, so that when the Enter propagates,
+ // it's removed
+ it.each`
+ text | expected
+ ${'- item\n- '} | ${'- item\n'}
+ ${'- [ ] item\n- [ ] '} | ${'- [ ] item\n'}
+ ${'- [x] item\n- [x] '} | ${'- [x] item\n'}
+ ${'- item\n - second\n - '} | ${'- item\n - second\n'}
+ ${'1. item\n1. '} | ${'1. item\n'}
+ ${'1. [ ] item\n1. [ ] '} | ${'1. [ ] item\n'}
+ ${'1. [x] item\n1. [x] '} | ${'1. [x] item\n'}
+ ${'108. item\n108. '} | ${'108. item\n'}
+ ${'108. item\n - second\n - '} | ${'108. item\n - second\n'}
+ ${'108. item\n 1. second\n 1. '} | ${'108. item\n 1. second\n'}
+ `('adds correct list continuation characters', ({ text, expected }) => {
+ textArea.value = text;
+ textArea.setSelectionRange(text.length, text.length);
+
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.dispatchEvent(enterEvent);
+
+ expect(textArea.value.substr(0, textArea.selectionStart)).toEqual(expected);
+ expect(textArea.selectionStart).toBe(expected.length);
+ expect(textArea.selectionEnd).toBe(text.length);
+ });
+
+ it('does nothing if feature flag disabled', () => {
+ gon.features = { markdownContinueLists: false };
+
+ const text = '- item';
+ const expected = '- item';
+
+ textArea.value = text;
+ textArea.setSelectionRange(text.length, text.length);
+
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.dispatchEvent(enterEvent);
+
+ expect(textArea.value).toEqual(expected);
+ expect(textArea.selectionStart).toBe(expected.length);
+ });
+ });
});
describe('with selection', () => {
diff --git a/spec/frontend/lib/utils/vuex_module_mappers_spec.js b/spec/frontend/lib/utils/vuex_module_mappers_spec.js
index d7e51e4daca..1821a15f677 100644
--- a/spec/frontend/lib/utils/vuex_module_mappers_spec.js
+++ b/spec/frontend/lib/utils/vuex_module_mappers_spec.js
@@ -1,4 +1,4 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import {
@@ -10,13 +10,12 @@ import {
const TEST_MODULE_NAME = 'testModuleName';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
// setup test component and store ----------------------------------------------
//
// These are used to indirectly test `vuex_module_mappers`.
-const TestComponent = Vue.extend({
+const TestComponent = {
props: {
vuexModule: {
type: String,
@@ -47,7 +46,7 @@ const TestComponent = Vue.extend({
<pre data-testid="state">{{ stateJson }}</pre>
<pre data-testid="getters">{{ gettersJson }}</pre>
</div>`,
-});
+};
const createTestStore = () => {
return new Vuex.Store({
@@ -94,7 +93,6 @@ describe('~/lib/utils/vuex_module_mappers', () => {
vuexModule: TEST_MODULE_NAME,
},
store,
- localVue,
});
});
diff --git a/spec/frontend/lib/utils/yaml_spec.js b/spec/frontend/lib/utils/yaml_spec.js
new file mode 100644
index 00000000000..d1ce00130e2
--- /dev/null
+++ b/spec/frontend/lib/utils/yaml_spec.js
@@ -0,0 +1,105 @@
+import { Document, parseDocument } from 'yaml';
+import { merge } from '~/lib/utils/yaml';
+
+// Mock data for Comments on pairs
+const COMMENTS_ON_PAIRS_SOURCE = `foo:
+ # barbaz
+ bar: baz
+
+ # bazboo
+ baz: boo
+`;
+
+const COMMENTS_ON_PAIRS_TARGET = `foo:
+ # abcdef
+ abc: def
+ # boobaz
+ boo: baz
+`;
+
+const COMMENTS_ON_PAIRS_EXPECTED = `foo:
+ # abcdef
+ abc: def
+ # boobaz
+ boo: baz
+ # barbaz
+ bar: baz
+
+ # bazboo
+ baz: boo
+`;
+
+// Mock data for Comments on seqs
+const COMMENTS_ON_SEQS_SOURCE = `foo:
+ # barbaz
+ - barbaz
+ # bazboo
+ - baz: boo
+`;
+
+const COMMENTS_ON_SEQS_TARGET = `foo:
+ # abcdef
+ - abcdef
+
+ # boobaz
+ - boobaz
+`;
+
+const COMMENTS_ON_SEQS_EXPECTED = `foo:
+ # abcdef
+ - abcdef
+
+ # boobaz
+ - boobaz
+ # barbaz
+ - barbaz
+ # bazboo
+ - baz: boo
+`;
+
+describe('Yaml utility functions', () => {
+ describe('merge', () => {
+ const getAsNode = (yamlStr) => {
+ return parseDocument(yamlStr).contents;
+ };
+
+ describe('Merge two Nodes', () => {
+ it.each`
+ scenario | source | target | options | expected
+ ${'merge a map'} | ${getAsNode('foo:\n bar: baz\n')} | ${'foo:\n abc: def\n'} | ${undefined} | ${'foo:\n abc: def\n bar: baz\n'}
+ ${'merge a seq'} | ${getAsNode('foo:\n - bar\n')} | ${'foo:\n - abc\n'} | ${undefined} | ${'foo:\n - bar\n'}
+ ${'merge-append seqs'} | ${getAsNode('foo:\n - bar\n')} | ${'foo:\n - abc\n'} | ${{ onSequence: 'append' }} | ${'foo:\n - abc\n - bar\n'}
+ ${'merge-replace a seq'} | ${getAsNode('foo:\n - bar\n')} | ${'foo:\n - abc\n'} | ${{ onSequence: 'replace' }} | ${'foo:\n - bar\n'}
+ ${'override existing paths'} | ${getAsNode('foo:\n bar: baz\n')} | ${'foo:\n bar: boo\n'} | ${undefined} | ${'foo:\n bar: baz\n'}
+ ${'deep maps'} | ${getAsNode('foo:\n bar:\n abc: def\n')} | ${'foo:\n bar:\n baz: boo\n jkl: mno\n'} | ${undefined} | ${'foo:\n bar:\n baz: boo\n abc: def\n jkl: mno\n'}
+ ${'append maps inside seqs'} | ${getAsNode('foo:\n - abc: def\n')} | ${'foo:\n - bar: baz\n'} | ${{ onSequence: 'append' }} | ${'foo:\n - bar: baz\n - abc: def\n'}
+ ${'inexistent paths create new nodes'} | ${getAsNode('foo:\n bar: baz\n')} | ${'abc: def\n'} | ${undefined} | ${'abc: def\nfoo:\n bar: baz\n'}
+ ${'document as source'} | ${parseDocument('foo:\n bar: baz\n')} | ${'foo:\n abc: def\n'} | ${undefined} | ${'foo:\n abc: def\n bar: baz\n'}
+ ${'object as source'} | ${{ foo: { bar: 'baz' } }} | ${'foo:\n abc: def\n'} | ${undefined} | ${'foo:\n abc: def\n bar: baz\n'}
+ ${'comments on pairs'} | ${parseDocument(COMMENTS_ON_PAIRS_SOURCE)} | ${COMMENTS_ON_PAIRS_TARGET} | ${undefined} | ${COMMENTS_ON_PAIRS_EXPECTED}
+ ${'comments on seqs'} | ${parseDocument(COMMENTS_ON_SEQS_SOURCE)} | ${COMMENTS_ON_SEQS_TARGET} | ${{ onSequence: 'append' }} | ${COMMENTS_ON_SEQS_EXPECTED}
+ `('$scenario', ({ source, target, expected, options }) => {
+ const targetDoc = parseDocument(target);
+ merge(targetDoc, source, options);
+ const expectedDoc = parseDocument(expected);
+ expect(targetDoc.toString()).toEqual(expectedDoc.toString());
+ });
+
+ it('type conflict will throw an Error', () => {
+ const sourceDoc = parseDocument('foo:\n bar:\n - baz\n');
+ const targetDoc = parseDocument('foo:\n bar: def\n');
+ expect(() => merge(targetDoc, sourceDoc)).toThrow(
+ 'Type conflict at "foo.bar": Destination node is of type Scalar, the node' +
+ ' to be merged is of type YAMLSeq',
+ );
+ });
+
+ it('merging a collection into an empty doc', () => {
+ const targetDoc = new Document();
+ merge(targetDoc, { foo: { bar: 'baz' } });
+ const expected = parseDocument('foo:\n bar: baz\n');
+ expect(targetDoc.toString()).toEqual(expected.toString());
+ });
+ });
+ });
+});
diff --git a/spec/frontend/listbox/index_spec.js b/spec/frontend/listbox/index_spec.js
new file mode 100644
index 00000000000..45659a0e523
--- /dev/null
+++ b/spec/frontend/listbox/index_spec.js
@@ -0,0 +1,111 @@
+import { nextTick } from 'vue';
+import { getAllByRole, getByRole } from '@testing-library/dom';
+import { GlDropdown } from '@gitlab/ui';
+import { createWrapper } from '@vue/test-utils';
+import { initListbox, parseAttributes } from '~/listbox';
+import { getFixture, setHTMLFixture } from 'helpers/fixtures';
+
+jest.mock('~/lib/utils/url_utility');
+
+const fixture = getFixture('listbox/redirect_listbox.html');
+
+const parsedAttributes = (() => {
+ const div = document.createElement('div');
+ div.innerHTML = fixture;
+ return parseAttributes(div.firstChild);
+})();
+
+describe('initListbox', () => {
+ let instance;
+
+ afterEach(() => {
+ if (instance) {
+ instance.$destroy();
+ }
+ });
+
+ const setup = (...args) => {
+ instance = initListbox(...args);
+ };
+
+ // TODO: Rewrite these finders to use better semantics once the
+ // implementation is switched to GlListbox
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/348738
+ const findToggleButton = () => document.body.querySelector('.gl-dropdown-toggle');
+ const findItem = (text) => getByRole(document.body, 'menuitem', { name: text });
+ const findItems = () => getAllByRole(document.body, 'menuitem');
+ const findSelectedItems = () =>
+ findItems().filter(
+ (menuitem) =>
+ !menuitem
+ .querySelector('.gl-new-dropdown-item-check-icon')
+ .classList.contains('gl-visibility-hidden'),
+ );
+
+ it('returns null given no element', () => {
+ setup();
+
+ expect(instance).toBe(null);
+ });
+
+ it('throws given an invalid element', () => {
+ expect(() => setup(document.body)).toThrow();
+ });
+
+ describe('given a valid element', () => {
+ let onChangeSpy;
+
+ beforeEach(async () => {
+ setHTMLFixture(fixture);
+ onChangeSpy = jest.fn();
+ setup(document.querySelector('.js-redirect-listbox'), { onChange: onChangeSpy });
+
+ await nextTick();
+ });
+
+ it('returns an instance', () => {
+ expect(instance).not.toBe(null);
+ });
+
+ it('renders button with selected item text', () => {
+ expect(findToggleButton().textContent.trim()).toBe('Bar');
+ });
+
+ it('has the correct item selected', () => {
+ const selectedItems = findSelectedItems();
+ expect(selectedItems).toHaveLength(1);
+ expect(selectedItems[0].textContent.trim()).toBe('Bar');
+ });
+
+ it('applies additional classes from the original element', () => {
+ expect(instance.$el.classList).toContain('test-class-1', 'test-class-2');
+ });
+
+ describe.each(parsedAttributes.items)('clicking on an item', (item) => {
+ beforeEach(async () => {
+ findItem(item.text).click();
+
+ await nextTick();
+ });
+
+ it('calls the onChange callback with the item', () => {
+ expect(onChangeSpy).toHaveBeenCalledWith(item);
+ });
+
+ it('updates the toggle button text', () => {
+ expect(findToggleButton().textContent.trim()).toBe(item.text);
+ });
+
+ it('marks the item as selected', () => {
+ const selectedItems = findSelectedItems();
+ expect(selectedItems).toHaveLength(1);
+ expect(selectedItems[0].textContent.trim()).toBe(item.text);
+ });
+ });
+
+ it('passes the "right" prop through to the underlying component', () => {
+ const wrapper = createWrapper(instance).findComponent(GlDropdown);
+ expect(wrapper.props('right')).toBe(parsedAttributes.right);
+ });
+ });
+});
diff --git a/spec/frontend/listbox/redirect_behavior_spec.js b/spec/frontend/listbox/redirect_behavior_spec.js
new file mode 100644
index 00000000000..7b2a40b65ce
--- /dev/null
+++ b/spec/frontend/listbox/redirect_behavior_spec.js
@@ -0,0 +1,51 @@
+import { initListbox } from '~/listbox';
+import { initRedirectListboxBehavior } from '~/listbox/redirect_behavior';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { getFixture, setHTMLFixture } from 'helpers/fixtures';
+
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/listbox', () => ({
+ initListbox: jest.fn().mockReturnValue({ foo: true }),
+}));
+
+const fixture = getFixture('listbox/redirect_listbox.html');
+
+describe('initRedirectListboxBehavior', () => {
+ let instances;
+
+ beforeEach(() => {
+ setHTMLFixture(`
+ ${fixture}
+ ${fixture}
+ `);
+
+ instances = initRedirectListboxBehavior();
+ });
+
+ it('calls initListbox for each .js-redirect-listbox', () => {
+ expect(instances).toEqual([{ foo: true }, { foo: true }]);
+
+ expect(initListbox).toHaveBeenCalledTimes(2);
+
+ initListbox.mock.calls.forEach((callArgs, i) => {
+ const elements = document.querySelectorAll('.js-redirect-listbox');
+
+ expect(callArgs[0]).toBe(elements[i]);
+ expect(callArgs[1]).toEqual({
+ onChange: expect.any(Function),
+ });
+ });
+ });
+
+ it('passes onChange handler to initListbox that calls redirectTo', () => {
+ const [firstCallArgs] = initListbox.mock.calls;
+ const { onChange } = firstCallArgs[1];
+ const mockItem = { href: '/foo' };
+
+ expect(redirectTo).not.toHaveBeenCalled();
+
+ onChange(mockItem);
+
+ expect(redirectTo).toHaveBeenCalledWith(mockItem.href);
+ });
+});
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index b107708ac2c..84dc0bdf6cd 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -1,5 +1,6 @@
import { GlSprintf, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { scrollDown } from '~/lib/utils/scroll_utils';
import EnvironmentLogs from '~/logs/components/environment_logs.vue';
@@ -338,35 +339,32 @@ describe('EnvironmentLogs', () => {
expect(store.dispatch).not.toHaveBeenCalledWith(`${module}/fetchMoreLogsPrepend`, undefined);
});
- it('`scroll` on a scrollable target results in enabled scroll buttons', () => {
+ it('`scroll` on a scrollable target results in enabled scroll buttons', async () => {
const target = { scrollTop: 10, clientHeight: 10, scrollHeight: 21 };
state.logs.isLoading = true;
findInfiniteScroll().vm.$emit('scroll', { target });
- return wrapper.vm.$nextTick(() => {
- expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(false);
- });
+ await nextTick();
+ expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(false);
});
- it('`scroll` on a non-scrollable target in disabled scroll buttons', () => {
+ it('`scroll` on a non-scrollable target in disabled scroll buttons', async () => {
const target = { scrollTop: 10, clientHeight: 10, scrollHeight: 20 };
state.logs.isLoading = true;
findInfiniteScroll().vm.$emit('scroll', { target });
- return wrapper.vm.$nextTick(() => {
- expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true);
- });
+ await nextTick();
+ expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true);
});
- it('`scroll` on no target results in disabled scroll buttons', () => {
+ it('`scroll` on no target results in disabled scroll buttons', async () => {
state.logs.isLoading = true;
findInfiniteScroll().vm.$emit('scroll', { target: undefined });
- return wrapper.vm.$nextTick(() => {
- expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true);
- });
+ await nextTick();
+ expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true);
});
});
});
diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js
index 9c1617e4daa..e249272b87d 100644
--- a/spec/frontend/logs/components/log_control_buttons_spec.js
+++ b/spec/frontend/logs/components/log_control_buttons_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import LogControlButtons from '~/logs/components/log_control_buttons.vue';
describe('LogControlButtons', () => {
@@ -33,7 +34,7 @@ describe('LogControlButtons', () => {
expect(findRefreshBtn().is(GlButton)).toBe(true);
});
- it('emits a `refresh` event on click on `refresh` button', () => {
+ it('emits a `refresh` event on click on `refresh` button', async () => {
initWrapper();
// An `undefined` value means no event was emitted
@@ -41,16 +42,15 @@ describe('LogControlButtons', () => {
findRefreshBtn().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('refresh')).toHaveLength(1);
- });
+ await nextTick();
+ expect(wrapper.emitted('refresh')).toHaveLength(1);
});
describe('when scrolling actions are enabled', () => {
- beforeEach(() => {
+ beforeEach(async () => {
// mock scrolled to the middle of a long page
initWrapper();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('click on "scroll to top" scrolls up', () => {
@@ -71,19 +71,18 @@ describe('LogControlButtons', () => {
});
describe('when scrolling actions are disabled', () => {
- beforeEach(() => {
+ beforeEach(async () => {
initWrapper({ listeners: {} });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('buttons are disabled', () => {
- return wrapper.vm.$nextTick(() => {
- expect(findScrollToTop().exists()).toBe(false);
- expect(findScrollToBottom().exists()).toBe(false);
- // This should be enabled when gitlab-ui contains:
- // https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1149
- // expect(findScrollToBottom().is('[disabled]')).toBe(true);
- });
+ it('buttons are disabled', async () => {
+ await nextTick();
+ expect(findScrollToTop().exists()).toBe(false);
+ expect(findScrollToBottom().exists()).toBe(false);
+ // This should be enabled when gitlab-ui contains:
+ // https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1149
+ // expect(findScrollToBottom().is('[disabled]')).toBe(true);
});
});
});
diff --git a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
index 936715e7723..08d7cf3c932 100644
--- a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlForm } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
@@ -7,8 +8,7 @@ import { MEMBER_TYPES } from '~/members/constants';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ApproveAccessRequestButton', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('ApproveAccessRequestButton', () => {
const createComponent = (propsData = {}, state) => {
wrapper = shallowMount(ApproveAccessRequestButton, {
- localVue,
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.accessRequest,
diff --git a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
index f91aef131a1..ca655e36c42 100644
--- a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
@@ -1,13 +1,13 @@
import { GlButton } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import RemoveGroupLinkButton from '~/members/components/action_buttons/remove_group_link_button.vue';
import { MEMBER_TYPES } from '~/members/constants';
import { group } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RemoveGroupLinkButton', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('RemoveGroupLinkButton', () => {
const createComponent = () => {
wrapper = mount(RemoveGroupLinkButton, {
- localVue,
store: createStore(),
provide: {
namespace: MEMBER_TYPES.group,
diff --git a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
index 1a031cc56d6..0e5b667eb9b 100644
--- a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
@@ -1,13 +1,13 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { modalData } from 'jest/members/mock_data';
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
import { MEMBER_TYPES } from '~/members/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RemoveMemberButton', () => {
let wrapper;
@@ -33,7 +33,6 @@ describe('RemoveMemberButton', () => {
const createComponent = (propsData = {}, state) => {
wrapper = shallowMount(RemoveMemberButton, {
- localVue,
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.user,
diff --git a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
index 547e067450c..8e933d16463 100644
--- a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ResendInviteButton from '~/members/components/action_buttons/resend_invite_button.vue';
@@ -7,8 +8,7 @@ import { MEMBER_TYPES } from '~/members/constants';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ResendInviteButton', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('ResendInviteButton', () => {
const createComponent = (propsData = {}, state) => {
wrapper = shallowMount(ResendInviteButton, {
- localVue,
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.invite,
diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js
index 9590cd9d8d4..4124a1870a6 100644
--- a/spec/frontend/members/components/app_spec.js
+++ b/spec/frontend/members/components/app_spec.js
@@ -1,6 +1,6 @@
import { GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import * as commonUtils from '~/lib/utils/common_utils';
import MembersApp from '~/members/components/app.vue';
@@ -11,8 +11,7 @@ import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_
import mutations from '~/members/store/mutations';
describe('MembersApp', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
let wrapper;
let store;
@@ -33,7 +32,6 @@ describe('MembersApp', () => {
});
wrapper = shallowMount(MembersApp, {
- localVue,
propsData: {
namespace: MEMBER_TYPES.group,
tabQueryParamValue: TAB_QUERY_PARAM_VALUES.group,
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 5cf3a4cdc13..7bcf4a11413 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -1,7 +1,8 @@
import { GlAvatarLink, GlBadge } from '@gitlab/ui';
-import { within } from '@testing-library/dom';
-import { mount, createWrapper } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
+
import { member as memberMock, member2faEnabled, orphanedMember } from '../../mock_data';
describe('UserAvatar', () => {
@@ -10,7 +11,7 @@ describe('UserAvatar', () => {
const { user } = memberMock;
const createComponent = (propsData = {}, provide = {}) => {
- wrapper = mount(UserAvatar, {
+ wrapper = mountExtended(UserAvatar, {
propsData: {
member: memberMock,
isCurrentUser: false,
@@ -23,9 +24,6 @@ describe('UserAvatar', () => {
});
};
- const getByText = (text, options) =>
- createWrapper(within(wrapper.element).findByText(text, options));
-
const findStatusEmoji = (emoji) => wrapper.find(`gl-emoji[data-name="${emoji}"]`);
afterEach(() => {
@@ -48,13 +46,13 @@ describe('UserAvatar', () => {
it("renders user's name", () => {
createComponent();
- expect(getByText(user.name).exists()).toBe(true);
+ expect(wrapper.findByText(user.name).exists()).toBe(true);
});
it("renders user's username", () => {
createComponent();
- expect(getByText(`@${user.username}`).exists()).toBe(true);
+ expect(wrapper.findByText(`@${user.username}`).exists()).toBe(true);
});
it("renders user's avatar", () => {
@@ -67,7 +65,7 @@ describe('UserAvatar', () => {
it('displays an orphaned user', () => {
createComponent({ member: orphanedMember });
- expect(getByText('Orphaned member').exists()).toBe(true);
+ expect(wrapper.findByText('Orphaned member').exists()).toBe(true);
});
});
@@ -85,13 +83,13 @@ describe('UserAvatar', () => {
it('renders the "It\'s you" badge when member is current user', () => {
createComponent({ isCurrentUser: true });
- expect(getByText("It's you").exists()).toBe(true);
+ expect(wrapper.findByText("It's you").exists()).toBe(true);
});
it('does not render 2FA badge when `canManageMembers` is `false`', () => {
createComponent({ member: member2faEnabled }, { canManageMembers: false });
- expect(within(wrapper.element).queryByText('2FA')).toBe(null);
+ expect(wrapper.findByText('2FA').exists()).toBe(false);
});
});
@@ -112,6 +110,23 @@ describe('UserAvatar', () => {
expect(findStatusEmoji(emoji).exists()).toBe(true);
});
+
+ describe('when `user.showStatus` is `false', () => {
+ it('does not display status emoji', () => {
+ createComponent({
+ member: {
+ ...memberMock,
+ user: {
+ ...memberMock.user,
+ showStatus: false,
+ status: { emoji, messageHtml: 'On vacation' },
+ },
+ },
+ });
+
+ expect(findStatusEmoji(emoji).exists()).toBe(false);
+ });
+ });
});
describe('when not set', () => {
@@ -122,4 +137,30 @@ describe('UserAvatar', () => {
});
});
});
+
+ describe('user availability', () => {
+ describe('when `user.availability` is `null`', () => {
+ it("does not show `(Busy)` next to user's name", () => {
+ createComponent();
+
+ expect(wrapper.findByText('(Busy)').exists()).toBe(false);
+ });
+ });
+
+ describe(`when user.availability is ${AVAILABILITY_STATUS.BUSY}`, () => {
+ it("shows `(Busy)` next to user's name", () => {
+ createComponent({
+ member: {
+ ...memberMock,
+ user: {
+ ...memberMock.user,
+ availability: AVAILABILITY_STATUS.BUSY,
+ },
+ },
+ });
+
+ expect(wrapper.findByText('(Busy)').exists()).toBe(true);
+ });
+ });
+ });
});
diff --git a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
index 16ac52737bc..4ca8a3bdc36 100644
--- a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
+++ b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
import { MEMBER_TYPES } from '~/members/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('FilterSortContainer', () => {
let wrapper;
@@ -32,7 +32,6 @@ describe('FilterSortContainer', () => {
});
wrapper = shallowMount(FilterSortContainer, {
- localVue,
store,
provide: {
namespace: MEMBER_TYPES.user,
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index 3f47fa024bc..ee2fbbe57b9 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -1,5 +1,6 @@
import { GlFilteredSearchToken } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
import { redirectTo } from '~/lib/utils/url_utility';
@@ -18,8 +19,7 @@ jest.mock('~/lib/utils/url_utility', () => {
};
});
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('MembersFilteredSearchBar', () => {
let wrapper;
@@ -44,7 +44,6 @@ describe('MembersFilteredSearchBar', () => {
});
wrapper = shallowMount(MembersFilteredSearchBar, {
- localVue,
provide: {
sourceId: 1,
canManageMembers: true,
diff --git a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
index d0684acd487..709ad907a38 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -1,13 +1,13 @@
import { GlSorting, GlSortingItem } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
import * as urlUtilities from '~/lib/utils/url_utility';
import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
import { MEMBER_TYPES } from '~/members/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('SortDropdown', () => {
let wrapper;
@@ -35,7 +35,6 @@ describe('SortDropdown', () => {
});
wrapper = mount(SortDropdown, {
- localVue,
provide: {
sourceId: 1,
namespace: MEMBER_TYPES.user,
diff --git a/spec/frontend/members/components/modals/leave_modal_spec.js b/spec/frontend/members/components/modals/leave_modal_spec.js
index f755f08dbf2..cdbabb2f646 100644
--- a/spec/frontend/members/components/modals/leave_modal_spec.js
+++ b/spec/frontend/members/components/modals/leave_modal_spec.js
@@ -1,8 +1,8 @@
import { GlModal, GlForm } from '@gitlab/ui';
import { within } from '@testing-library/dom';
-import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { mount, createWrapper } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
import { LEAVE_MODAL_ID, MEMBER_TYPES } from '~/members/constants';
@@ -12,8 +12,7 @@ import { member } from '../../mock_data';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('LeaveModal', () => {
let wrapper;
@@ -34,7 +33,6 @@ describe('LeaveModal', () => {
const createComponent = (propsData = {}, state) => {
wrapper = mount(LeaveModal, {
- localVue,
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.user,
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 313c237f51c..447496910b8 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
@@ -1,7 +1,7 @@
import { GlModal, GlForm } from '@gitlab/ui';
import { within } from '@testing-library/dom';
-import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount, createWrapper } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import RemoveGroupLinkModal from '~/members/components/modals/remove_group_link_modal.vue';
import { REMOVE_GROUP_LINK_MODAL_ID, MEMBER_TYPES } from '~/members/constants';
@@ -9,8 +9,7 @@ import { group } from '../../mock_data';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RemoveGroupLinkModal', () => {
let wrapper;
@@ -38,7 +37,6 @@ describe('RemoveGroupLinkModal', () => {
const createComponent = (state) => {
wrapper = mount(RemoveGroupLinkModal, {
- localVue,
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.group,
diff --git a/spec/frontend/members/components/table/expiration_datepicker_spec.js b/spec/frontend/members/components/table/expiration_datepicker_spec.js
index 3c4a9ba37ff..4fb43fbd888 100644
--- a/spec/frontend/members/components/table/expiration_datepicker_spec.js
+++ b/spec/frontend/members/components/table/expiration_datepicker_spec.js
@@ -1,6 +1,6 @@
import { GlDatepicker } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { useFakeDate } from 'helpers/fake_date';
import waitForPromises from 'helpers/wait_for_promises';
@@ -8,8 +8,7 @@ import ExpirationDatepicker from '~/members/components/table/expiration_datepick
import { MEMBER_TYPES } from '~/members/constants';
import { member } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ExpirationDatepicker', () => {
// March 15th, 2020 3:00
@@ -49,7 +48,6 @@ describe('ExpirationDatepicker', () => {
provide: {
namespace: MEMBER_TYPES.user,
},
- localVue,
store: createStore(),
mocks: {
$toast,
diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js
index 5375ee11736..6575a7c7126 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import MembersTableCell from '~/members/components/table/members_table_cell.vue';
import { MEMBER_TYPES } from '~/members/constants';
@@ -36,9 +37,8 @@ describe('MembersTableCell', () => {
},
};
- const localVue = createLocalVue();
- localVue.use(Vuex);
- localVue.component('WrappedComponent', WrappedComponent);
+ Vue.use(Vuex);
+ Vue.component('WrappedComponent', WrappedComponent);
const createStore = (state = {}) => {
return new Vuex.Store({
@@ -50,7 +50,6 @@ describe('MembersTableCell', () => {
const createComponent = (propsData, state) => {
wrapper = mount(MembersTableCell, {
- localVue,
propsData,
store: createStore(state),
provide: {
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 580e5edd652..b2756e506eb 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -1,5 +1,5 @@
import { GlBadge, GlPagination, GlTable } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -16,6 +16,7 @@ import {
MEMBER_STATE_AWAITING,
MEMBER_STATE_ACTIVE,
USER_STATE_BLOCKED_PENDING_APPROVAL,
+ BADGE_LABELS_AWAITING_USER_SIGNUP,
BADGE_LABELS_PENDING_OWNER_APPROVAL,
TAB_QUERY_PARAM_VALUES,
} from '~/members/constants';
@@ -28,8 +29,7 @@ import {
pagination,
} from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('MembersTable', () => {
let wrapper;
@@ -56,7 +56,6 @@ describe('MembersTable', () => {
const createComponent = (state, provide = {}) => {
wrapper = mountExtended(MembersTable, {
- localVue,
propsData: {
tabQueryParamValue: TAB_QUERY_PARAM_VALUES.invite,
},
@@ -133,9 +132,9 @@ describe('MembersTable', () => {
describe('Invited column', () => {
describe.each`
state | userState | expectedBadgeLabel
- ${MEMBER_STATE_CREATED} | ${null} | ${''}
+ ${MEMBER_STATE_CREATED} | ${null} | ${BADGE_LABELS_AWAITING_USER_SIGNUP}
${MEMBER_STATE_CREATED} | ${USER_STATE_BLOCKED_PENDING_APPROVAL} | ${BADGE_LABELS_PENDING_OWNER_APPROVAL}
- ${MEMBER_STATE_AWAITING} | ${''} | ${''}
+ ${MEMBER_STATE_AWAITING} | ${''} | ${BADGE_LABELS_AWAITING_USER_SIGNUP}
${MEMBER_STATE_AWAITING} | ${USER_STATE_BLOCKED_PENDING_APPROVAL} | ${BADGE_LABELS_PENDING_OWNER_APPROVAL}
${MEMBER_STATE_AWAITING} | ${'something_else'} | ${BADGE_LABELS_PENDING_OWNER_APPROVAL}
${MEMBER_STATE_ACTIVE} | ${null} | ${''}
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index a4a4c620921..d4d950e99ba 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -1,8 +1,8 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { within } from '@testing-library/dom';
-import { mount, createWrapper, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount, createWrapper } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import { BV_DROPDOWN_SHOW } from '~/lib/utils/constants';
@@ -10,8 +10,7 @@ import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import { MEMBER_TYPES } from '~/members/constants';
import { member } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RoleDropdown', () => {
let wrapper;
@@ -42,7 +41,6 @@ describe('RoleDropdown', () => {
permissions: {},
...propsData,
},
- localVue,
store: createStore(),
mocks: {
$toast,
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 218db0b587a..83856a00a15 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -25,6 +25,8 @@ export const member = {
twoFactorEnabled: false,
oncallSchedules: [{ name: 'schedule 1' }],
escalationPolicies: [{ name: 'policy 1' }],
+ availability: null,
+ showStatus: true,
},
id: 238,
createdAt: '2020-07-17T16:22:46.923Z',
diff --git a/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js
index a09edb50f20..750fff9b0aa 100644
--- a/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js
+++ b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js
@@ -1,5 +1,6 @@
import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import InlineConflictLines from '~/merge_conflicts/components/inline_conflict_lines.vue';
import ParallelConflictLines from '~/merge_conflicts/components/parallel_conflict_lines.vue';
@@ -8,8 +9,7 @@ import { createStore } from '~/merge_conflicts/store';
import { decorateFiles } from '~/merge_conflicts/utils';
import { conflictsMock } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Merge Conflict Resolver App', () => {
let wrapper;
@@ -93,7 +93,7 @@ describe('Merge Conflict Resolver App', () => {
expect(inlineButton.props('selected')).toBe(false);
inlineButton.vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(inlineButton.props('selected')).toBe(true);
});
@@ -111,7 +111,7 @@ describe('Merge Conflict Resolver App', () => {
mountComponent();
findSideBySideButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
const parallelConflictLinesComponent = findParallelConflictLines(findFiles().at(0));
diff --git a/spec/frontend/merge_conflicts/store/actions_spec.js b/spec/frontend/merge_conflicts/store/actions_spec.js
index 8fa8765a9f9..3e1774a6d56 100644
--- a/spec/frontend/merge_conflicts/store/actions_spec.js
+++ b/spec/frontend/merge_conflicts/store/actions_spec.js
@@ -207,7 +207,10 @@ describe('merge conflicts actions', () => {
],
[],
() => {
- expect(Cookies.set).toHaveBeenCalledWith('diff_view', payload);
+ expect(Cookies.set).toHaveBeenCalledWith('diff_view', payload, {
+ expires: 365,
+ secure: false,
+ });
done();
},
);
diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js
index 0b7ed349507..9229b353685 100644
--- a/spec/frontend/merge_request_spec.js
+++ b/spec/frontend/merge_request_spec.js
@@ -1,6 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST } from 'spec/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MergeRequest from '~/merge_request';
@@ -27,31 +28,31 @@ describe('MergeRequest', () => {
mock.restore();
});
- it('modifies the Markdown field', (done) => {
+ it('modifies the Markdown field', async () => {
jest.spyOn($, 'ajax').mockImplementation();
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
$('input[type=checkbox]').first().attr('checked', true)[0].dispatchEvent(changeEvent);
- setImmediate(() => {
- expect($('.js-task-list-field').val()).toBe(
- '- [x] Task List Item\n- [ ]\n- [ ] Task List Item 2\n',
- );
- done();
- });
+
+ await waitForPromises();
+
+ expect($('.js-task-list-field').val()).toBe(
+ '- [x] Task List Item\n- [ ]\n- [ ] Task List Item 2\n',
+ );
});
- it('ensure that task with only spaces does not get checked incorrectly', (done) => {
+ it('ensure that task with only spaces does not get checked incorrectly', async () => {
// fixed in 'deckar01-task_list', '2.2.1' gem
jest.spyOn($, 'ajax').mockImplementation();
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
$('input[type=checkbox]').last().attr('checked', true)[0].dispatchEvent(changeEvent);
- setImmediate(() => {
- expect($('.js-task-list-field').val()).toBe(
- '- [ ] Task List Item\n- [ ]\n- [x] Task List Item 2\n',
- );
- done();
- });
+
+ await waitForPromises();
+
+ expect($('.js-task-list-field').val()).toBe(
+ '- [ ] Task List Item\n- [ ]\n- [x] Task List Item 2\n',
+ );
});
describe('tasklist', () => {
@@ -60,29 +61,27 @@ describe('MergeRequest', () => {
const index = 3;
const checked = true;
- it('submits an ajax request on tasklist:changed', (done) => {
+ it('submits an ajax request on tasklist:changed', async () => {
$('.js-task-list-field').trigger({
type: 'tasklist:changed',
detail: { lineNumber, lineSource, index, checked },
});
- setImmediate(() => {
- expect(axios.patch).toHaveBeenCalledWith(
- `${TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`,
- {
- merge_request: {
- description: '- [ ] Task List Item\n- [ ]\n- [ ] Task List Item 2\n',
- lock_version: 0,
- update_task: { line_number: lineNumber, line_source: lineSource, index, checked },
- },
- },
- );
+ await waitForPromises();
- done();
- });
+ expect(axios.patch).toHaveBeenCalledWith(
+ `${TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`,
+ {
+ merge_request: {
+ description: '- [ ] Task List Item\n- [ ]\n- [ ] Task List Item 2\n',
+ lock_version: 0,
+ update_task: { line_number: lineNumber, line_source: lineSource, index, checked },
+ },
+ },
+ );
});
- it('shows an error notification when tasklist update failed', (done) => {
+ it('shows an error notification when tasklist update failed', async () => {
mock
.onPatch(`${TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`)
.reply(409, {});
@@ -92,13 +91,11 @@ describe('MergeRequest', () => {
detail: { lineNumber, lineSource, index, checked },
});
- setImmediate(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
- );
+ await waitForPromises();
- done();
- });
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
+ );
});
});
});
diff --git a/spec/frontend/mocks_spec.js b/spec/frontend/mocks_spec.js
index 110c418e579..0813d2073b9 100644
--- a/spec/frontend/mocks_spec.js
+++ b/spec/frontend/mocks_spec.js
@@ -8,13 +8,10 @@ describe('Mock auto-injection', () => {
failMock = jest.spyOn(global, 'fail').mockImplementation();
});
- it('~/lib/utils/axios_utils', () => {
- return Promise.all([
- expect(axios.get('http://gitlab.com')).rejects.toThrow('Unexpected unmocked request'),
- setImmediate(() => {
- expect(failMock).toHaveBeenCalledTimes(1);
- }),
- ]);
+ it('~/lib/utils/axios_utils', async () => {
+ await expect(axios.get('http://gitlab.com')).rejects.toThrow('Unexpected unmocked request');
+
+ expect(failMock).toHaveBeenCalledTimes(1);
});
it('jQuery.ajax()', () => {
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 681fb05a6c4..bd2e818df4f 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -8,6 +8,28 @@ exports[`Dashboard template matches the default snapshot 1`] = `
metricsdashboardbasepath="/monitoring/monitor-project/-/environments/1/metrics"
metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json"
>
+ <div>
+ <gl-alert-stub
+ class="mb-3"
+ dismissible="true"
+ dismisslabel="Dismiss"
+ primarybuttonlink=""
+ primarybuttontext=""
+ secondarybuttonlink=""
+ secondarybuttontext=""
+ title="Feature deprecation and removal"
+ variant="danger"
+ >
+ <gl-sprintf-stub
+ message="The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
+ />
+
+ <gl-sprintf-stub
+ message="For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
+ />
+ </gl-alert-stub>
+ </div>
+
<div
class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light"
>
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index f47728313c6..9cab3650f28 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -2,6 +2,7 @@ import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts';
import { shallowMount, mount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
import timezoneMock from 'timezone-mock';
+import { nextTick } from 'vue';
import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
import { stackedColumnGraphData } from '../../graph_data';
@@ -34,9 +35,9 @@ describe('Stacked column chart component', () => {
});
describe('when graphData is present', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('chart is rendered', () => {
@@ -116,25 +117,24 @@ describe('Stacked column chart component', () => {
expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('4:01 AM');
});
- it('date is shown in UTC', () => {
+ it('date is shown in UTC', async () => {
wrapper.setProps({ timezone: 'UTC' });
- return wrapper.vm.$nextTick().then(() => {
- const { xAxis } = findChart().props('option');
- expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM');
- });
+ await nextTick();
+ const { xAxis } = findChart().props('option');
+ expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM');
});
});
});
describe('when graphData has results missing', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const graphData = cloneDeep(stackedColumnMockedData);
graphData.metrics[0].result = null;
createWrapper({ graphData });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('chart is rendered', () => {
@@ -147,7 +147,7 @@ describe('Stacked column chart component', () => {
wrapper = createWrapper({}, mount);
});
- it('allows user to override legend label texts using props', () => {
+ it('allows user to override legend label texts using props', async () => {
const legendRelatedProps = {
legendMinText: 'legendMinText',
legendMaxText: 'legendMaxText',
@@ -158,9 +158,8 @@ describe('Stacked column chart component', () => {
...legendRelatedProps,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findChart().props()).toMatchObject(legendRelatedProps);
- });
+ await nextTick();
+ expect(findChart().props()).toMatchObject(legendRelatedProps);
});
it('should render a tabular legend layout by default', () => {
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index ff6f0b9b0c7..73abd81d889 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -7,6 +7,7 @@ import {
} from '@gitlab/ui/dist/charts';
import { mount, shallowMount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { setTestTimeout } from 'helpers/timeout';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
@@ -70,12 +71,12 @@ describe('Time series component', () => {
describe('general functions', () => {
const findChart = () => wrapper.find({ ref: 'chart' });
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper({}, mount);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('allows user to override legend label texts using props', () => {
+ it('allows user to override legend label texts using props', async () => {
const legendRelatedProps = {
legendMinText: 'legendMinText',
legendMaxText: 'legendMaxText',
@@ -86,9 +87,8 @@ describe('Time series component', () => {
...legendRelatedProps,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findChart().props()).toMatchObject(legendRelatedProps);
- });
+ await nextTick();
+ expect(findChart().props()).toMatchObject(legendRelatedProps);
});
it('chart sets a default height', () => {
@@ -96,14 +96,13 @@ describe('Time series component', () => {
expect(wrapper.props('height')).toBe(chartHeight);
});
- it('chart has a configurable height', () => {
+ it('chart has a configurable height', async () => {
const mockHeight = 599;
createWrapper();
wrapper.setProps({ height: mockHeight });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.props('height')).toBe(mockHeight);
- });
+ await nextTick();
+ expect(wrapper.props('height')).toBe(mockHeight);
});
describe('events', () => {
@@ -112,7 +111,7 @@ describe('Time series component', () => {
let startValue;
let endValue;
- beforeEach(() => {
+ beforeEach(async () => {
eChartMock = {
handlers: {},
getOption: () => ({
@@ -132,9 +131,8 @@ describe('Time series component', () => {
};
createWrapper({}, mount);
- return wrapper.vm.$nextTick(() => {
- findChart().vm.$emit('created', eChartMock);
- });
+ await nextTick();
+ findChart().vm.$emit('created', eChartMock);
});
it('handles datazoom event from chart', () => {
@@ -203,10 +201,10 @@ describe('Time series component', () => {
});
describe('when series is of line type', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper({}, mount);
wrapper.vm.formatTooltipText(mockLineSeriesData());
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('formats tooltip title', () => {
@@ -241,34 +239,31 @@ describe('Time series component', () => {
timezoneMock.unregister();
});
- it('formats tooltip title in local timezone by default', () => {
+ it('formats tooltip title in local timezone by default', async () => {
createWrapper();
wrapper.vm.formatTooltipText(mockLineSeriesData());
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)');
- });
+ await nextTick();
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)');
});
- it('formats tooltip title in local timezone', () => {
+ it('formats tooltip title in local timezone', async () => {
createWrapper({ timezone: 'LOCAL' });
wrapper.vm.formatTooltipText(mockLineSeriesData());
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)');
- });
+ await nextTick();
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)');
});
- it('formats tooltip title in UTC format', () => {
+ it('formats tooltip title in UTC format', async () => {
createWrapper({ timezone: 'UTC' });
wrapper.vm.formatTooltipText(mockLineSeriesData());
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)');
- });
+ await nextTick();
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)');
});
});
});
describe('when series is of scatter type, for deployments', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.formatTooltipText({
...mockAnnotationsSeriesData,
seriesData: mockAnnotationsSeriesData.seriesData.map((data) => ({
@@ -276,7 +271,7 @@ describe('Time series component', () => {
data: annotationsMetadata,
})),
});
- return wrapper.vm.$nextTick;
+ await nextTick();
});
it('set tooltip type to deployments', () => {
@@ -297,9 +292,9 @@ describe('Time series component', () => {
});
describe('when series is of scatter type and deployments data is missing', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.vm.formatTooltipText(mockAnnotationsSeriesData);
- return wrapper.vm.$nextTick;
+ await nextTick();
});
it('formats tooltip title', () => {
@@ -397,14 +392,13 @@ describe('Time series component', () => {
});
});
- it('is not set if time range is not set or incorrectly set', () => {
+ it('is not set if time range is not set or incorrectly set', async () => {
wrapper.setProps({
timeRange: {},
});
- return wrapper.vm.$nextTick(() => {
- expect(getChartOptions().xAxis).not.toHaveProperty('min');
- expect(getChartOptions().xAxis).not.toHaveProperty('max');
- });
+ await nextTick();
+ expect(getChartOptions().xAxis).not.toHaveProperty('min');
+ expect(getChartOptions().xAxis).not.toHaveProperty('max');
});
});
@@ -430,17 +424,16 @@ describe('Time series component', () => {
option2: 'option2',
};
- it('arbitrary options', () => {
+ it('arbitrary options', async () => {
wrapper.setProps({
option: mockOption,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(getChartOptions()).toEqual(expect.objectContaining(mockOption));
- });
+ await nextTick();
+ expect(getChartOptions()).toEqual(expect.objectContaining(mockOption));
});
- it('additional series', () => {
+ it('additional series', async () => {
wrapper.setProps({
option: {
series: [
@@ -453,15 +446,14 @@ describe('Time series component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- const optionSeries = getChartOptions().series;
+ await nextTick();
+ const optionSeries = getChartOptions().series;
- expect(optionSeries.length).toEqual(2);
- expect(optionSeries[0].name).toEqual(mockSeriesName);
- });
+ expect(optionSeries.length).toEqual(2);
+ expect(optionSeries[0].name).toEqual(mockSeriesName);
});
- it('additional y-axis data', () => {
+ it('additional y-axis data', async () => {
const mockCustomYAxisOption = {
name: 'Custom y-axis label',
axisLabel: {
@@ -475,14 +467,13 @@ describe('Time series component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- const { yAxis } = getChartOptions();
+ await nextTick();
+ const { yAxis } = getChartOptions();
- expect(yAxis[0]).toMatchObject(mockCustomYAxisOption);
- });
+ expect(yAxis[0]).toMatchObject(mockCustomYAxisOption);
});
- it('additional x axis data', () => {
+ it('additional x axis data', async () => {
const mockCustomXAxisOption = {
name: 'Custom x axis label',
};
@@ -493,11 +484,10 @@ describe('Time series component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- const { xAxis } = getChartOptions();
+ await nextTick();
+ const { xAxis } = getChartOptions();
- expect(xAxis).toMatchObject(mockCustomXAxisOption);
- });
+ expect(xAxis).toMatchObject(mockCustomXAxisOption);
});
});
@@ -625,12 +615,12 @@ describe('Time series component', () => {
describe(`GitLab UI: ${dynamicComponent.chartType}`, () => {
const findChartComponent = () => wrapper.find(dynamicComponent.component);
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper(
{ graphData: timeSeriesGraphData({ type: dynamicComponent.chartType }) },
mount,
);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('exists', () => {
@@ -645,22 +635,21 @@ describe('Time series component', () => {
expect(props.formatTooltipText).toBe(wrapper.vm.formatTooltipText);
});
- it('receives a tooltip title', () => {
+ it('receives a tooltip title', async () => {
const mockTitle = 'mockTitle';
wrapper.vm.tooltip.title = mockTitle;
- return wrapper.vm.$nextTick(() => {
- expect(
- shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', mockTitle),
- ).toBe(true);
- });
+ await nextTick();
+ expect(
+ shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', mockTitle),
+ ).toBe(true);
});
describe('when tooltip is showing deployment data', () => {
const mockSha = 'mockSha';
const commitUrl = `${mockProjectDir}/-/commit/${mockSha}`;
- beforeEach(() => {
+ beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -668,7 +657,7 @@ describe('Time series component', () => {
type: 'deployments',
},
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('uses deployment title', () => {
@@ -677,16 +666,15 @@ describe('Time series component', () => {
).toBe(true);
});
- it('renders clickable commit sha in tooltip content', () => {
+ it('renders clickable commit sha in tooltip content', async () => {
wrapper.vm.tooltip.sha = mockSha;
wrapper.vm.tooltip.commitUrl = commitUrl;
- return wrapper.vm.$nextTick(() => {
- const commitLink = wrapper.find(GlLink);
+ await nextTick();
+ const commitLink = wrapper.find(GlLink);
- expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true);
- expect(commitLink.attributes('href')).toEqual(commitUrl);
- });
+ expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true);
+ expect(commitLink.attributes('href')).toEqual(commitUrl);
});
});
});
@@ -696,11 +684,11 @@ describe('Time series component', () => {
describe('with multiple time series', () => {
describe('General functions', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const graphData = timeSeriesGraphData({ type: panelTypes.AREA_CHART, multiMetric: true });
createWrapper({ graphData }, mount);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
describe('Color match', () => {
@@ -742,9 +730,9 @@ describe('Time series component', () => {
describe('legend layout', () => {
const findLegend = () => wrapper.find(GlChartLegend);
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper({}, mount);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('should render a tabular legend layout by default', () => {
diff --git a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
index 8202d423ff3..88de3467580 100644
--- a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
+++ b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CreateDashboardModal from '~/monitoring/components/create_dashboard_modal.vue';
describe('Create dashboard modal', () => {
@@ -32,13 +33,12 @@ describe('Create dashboard modal', () => {
wrapper.destroy();
});
- it('has button that links to the project url', () => {
+ it('has button that links to the project url', async () => {
findRepoButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findRepoButton().exists()).toBe(true);
- expect(findRepoButton().attributes('href')).toBe(defaultProps.projectPath);
- });
+ await nextTick();
+ expect(findRepoButton().exists()).toBe(true);
+ expect(findRepoButton().attributes('href')).toBe(defaultProps.projectPath);
});
it('has button that links to the docs', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index f2116c1f478..d0d0c3071d5 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -1,5 +1,6 @@
import { GlDropdownItem, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
@@ -60,22 +61,20 @@ describe('Actions menu', () => {
});
describe('add metric item', () => {
- it('is rendered when custom metrics are available', () => {
+ it('is rendered when custom metrics are available', async () => {
createShallowWrapper();
- return wrapper.vm.$nextTick(() => {
- expect(findAddMetricItem().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findAddMetricItem().exists()).toBe(true);
});
- it('is not rendered when custom metrics are not available', () => {
+ it('is not rendered when custom metrics are not available', async () => {
createShallowWrapper({
addingMetricsAvailable: false,
});
- return wrapper.vm.$nextTick(() => {
- expect(findAddMetricItem().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findAddMetricItem().exists()).toBe(false);
});
describe('when available', () => {
@@ -119,30 +118,23 @@ describe('Actions menu', () => {
origPage = document.body.dataset.page;
document.body.dataset.page = 'projects:environments:metrics';
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
afterEach(() => {
document.body.dataset.page = origPage;
});
- it('is tracked', (done) => {
+ it('is tracked', async () => {
const submitButton = findAddMetricModalSubmitButton().vm;
- wrapper.vm.$nextTick(() => {
- submitButton.$el.click();
- wrapper.vm.$nextTick(() => {
- expect(Tracking.event).toHaveBeenCalledWith(
- document.body.dataset.page,
- 'click_button',
- {
- label: 'add_new_metric',
- property: 'modal',
- value: undefined,
- },
- );
- done();
- });
+ await nextTick();
+ submitButton.$el.click();
+ await nextTick();
+ expect(Tracking.event).toHaveBeenCalledWith(document.body.dataset.page, 'click_button', {
+ label: 'add_new_metric',
+ property: 'modal',
+ value: undefined,
});
});
});
@@ -172,14 +164,13 @@ describe('Actions menu', () => {
);
});
- it('is disabled for ootb dashboards', () => {
+ it('is disabled for ootb dashboards', async () => {
createShallowWrapper({
isOotbDashboard: true,
});
- return wrapper.vm.$nextTick(() => {
- expect(findAddPanelItemDisabled().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findAddPanelItemDisabled().exists()).toBe(true);
});
it('is visible for custom dashboards', () => {
@@ -256,16 +247,15 @@ describe('Actions menu', () => {
expect(findDuplicateDashboardModal().exists()).toBe(true);
});
- it('clicking on item opens up the duplicate dashboard modal', () => {
+ it('clicking on item opens up the duplicate dashboard modal', async () => {
const modalId = 'duplicateDashboard';
const modalTrigger = findDuplicateDashboardItem();
const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit');
modalTrigger.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(rootEmit.mock.calls[0]).toContainEqual(modalId);
- });
+ await nextTick();
+ expect(rootEmit.mock.calls[0]).toContainEqual(modalId);
});
});
@@ -300,16 +290,15 @@ describe('Actions menu', () => {
setupAllDashboards(store, dashboardGitResponse[0].path);
});
- it('redirects to the newly created dashboard', () => {
+ it('redirects to the newly created dashboard', async () => {
const newDashboard = dashboardGitResponse[1];
const newDashboardUrl = 'root/sandbox/-/metrics/dashboard.yml';
findDuplicateDashboardModal().vm.$emit('dashboardDuplicated', newDashboard);
- return wrapper.vm.$nextTick().then(() => {
- expect(redirectTo).toHaveBeenCalled();
- expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl);
- });
+ await nextTick();
+ expect(redirectTo).toHaveBeenCalled();
+ expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl);
});
});
});
@@ -330,32 +319,30 @@ describe('Actions menu', () => {
expect(findStarDashboardItem().attributes('disabled')).toBeFalsy();
});
- it('is disabled when starring is taking place', () => {
+ it('is disabled when starring is taking place', async () => {
store.commit(`monitoringDashboard/${types.REQUEST_DASHBOARD_STARRING}`);
- return wrapper.vm.$nextTick(() => {
- expect(findStarDashboardItem().exists()).toBe(true);
- expect(findStarDashboardItem().attributes('disabled')).toBe('true');
- });
+ await nextTick();
+ expect(findStarDashboardItem().exists()).toBe(true);
+ expect(findStarDashboardItem().attributes('disabled')).toBe('true');
});
- it('on click it dispatches a toggle star action', () => {
+ it('on click it dispatches a toggle star action', async () => {
findStarDashboardItem().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/toggleStarredValue',
- undefined,
- );
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/toggleStarredValue',
+ undefined,
+ );
});
describe('when dashboard is not starred', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentDashboard: dashboardGitResponse[0].path,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('item text shows "Star dashboard"', () => {
@@ -364,11 +351,11 @@ describe('Actions menu', () => {
});
describe('when dashboard is starred', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentDashboard: dashboardGitResponse[1].path,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('item text shows "Unstar dashboard"', () => {
@@ -403,16 +390,15 @@ describe('Actions menu', () => {
expect(findCreateDashboardModal().exists()).toBe(true);
});
- it('clicking opens up the modal', () => {
+ it('clicking opens up the modal', async () => {
const modalId = 'createDashboard';
const modalTrigger = findCreateDashboardItem();
const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit');
modalTrigger.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(rootEmit.mock.calls[0]).toContainEqual(modalId);
- });
+ await nextTick();
+ expect(rootEmit.mock.calls[0]).toContainEqual(modalId);
});
it('modal gets passed correct props', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index 8be7d641953..e28c2913949 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -1,5 +1,6 @@
import { GlDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { redirectTo } from '~/lib/utils/url_utility';
import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
@@ -110,9 +111,9 @@ describe('Dashboard header', () => {
});
describe('when environments data is not loaded', () => {
- beforeEach(() => {
+ beforeEach(async () => {
setupStoreWithDashboard(store);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('there are no environments listed', () => {
@@ -124,13 +125,13 @@ describe('Dashboard header', () => {
const currentDashboard = dashboardGitResponse[0].path;
const currentEnvironmentName = environmentData[0].name;
- beforeEach(() => {
+ beforeEach(async () => {
setupStoreWithData(store);
store.state.monitoringDashboard.projectPath = mockProjectPath;
store.state.monitoringDashboard.currentDashboard = currentDashboard;
store.state.monitoringDashboard.currentEnvironmentName = currentEnvironmentName;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders dropdown items with the environment name', () => {
@@ -159,51 +160,41 @@ describe('Dashboard header', () => {
expect(selectedItems.at(0).text()).toBe(currentEnvironmentName);
});
- it('filters rendered dropdown items', () => {
+ it('filters rendered dropdown items', async () => {
const searchTerm = 'production';
const resultEnvs = environmentData.filter(({ name }) => name.indexOf(searchTerm) !== -1);
setSearchTerm(searchTerm);
- return wrapper.vm.$nextTick().then(() => {
- expect(findEnvsDropdownItems()).toHaveLength(resultEnvs.length);
- });
+ await nextTick();
+ expect(findEnvsDropdownItems()).toHaveLength(resultEnvs.length);
});
- it('does not filter dropdown items if search term is empty string', () => {
+ it('does not filter dropdown items if search term is empty string', async () => {
const searchTerm = '';
setSearchTerm(searchTerm);
- return wrapper.vm.$nextTick(() => {
- expect(findEnvsDropdownItems()).toHaveLength(environmentData.length);
- });
+ await nextTick();
+ expect(findEnvsDropdownItems()).toHaveLength(environmentData.length);
});
- it("shows error message if search term doesn't match", () => {
+ it("shows error message if search term doesn't match", async () => {
const searchTerm = 'does-not-exist';
setSearchTerm(searchTerm);
- return wrapper.vm.$nextTick(() => {
- expect(findEnvsDropdownSearchMsg().isVisible()).toBe(true);
- });
+ await nextTick();
+ expect(findEnvsDropdownSearchMsg().isVisible()).toBe(true);
});
- it('shows loading element when environments fetch is still loading', () => {
+ it('shows loading element when environments fetch is still loading', async () => {
store.commit(`monitoringDashboard/${types.REQUEST_ENVIRONMENTS_DATA}`);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(findEnvsDropdownLoadingIcon().exists()).toBe(true);
- })
- .then(() => {
- store.commit(
- `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
- environmentData,
- );
- })
- .then(() => {
- expect(findEnvsDropdownLoadingIcon().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findEnvsDropdownLoadingIcon().exists()).toBe(true);
+ await store.commit(
+ `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
+ environmentData,
+ );
+ expect(findEnvsDropdownLoadingIcon().exists()).toBe(false);
});
});
});
@@ -262,11 +253,11 @@ describe('Dashboard header', () => {
});
describe('external dashboard link', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.monitoringDashboard.externalDashboardUrl = '/mockUrl';
createShallowWrapper();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows the link', () => {
@@ -295,82 +286,78 @@ describe('Dashboard header', () => {
});
describe('adding metrics prop', () => {
- it.each(ootbDashboards)('gets passed true if current dashboard is OOTB', (dashboardPath) => {
- createShallowWrapper({ customMetricsAvailable: true });
+ it.each(ootbDashboards)(
+ 'gets passed true if current dashboard is OOTB',
+ async (dashboardPath) => {
+ createShallowWrapper({ customMetricsAvailable: true });
- store.state.monitoringDashboard.emptyState = false;
- setupAllDashboards(store, dashboardPath);
+ store.state.monitoringDashboard.emptyState = false;
+ setupAllDashboards(store, dashboardPath);
- return wrapper.vm.$nextTick().then(() => {
+ await nextTick();
expect(findActionsMenu().props('addingMetricsAvailable')).toBe(true);
- });
- });
+ },
+ );
it.each(customDashboards)(
'gets passed false if current dashboard is custom',
- (dashboardPath) => {
+ async (dashboardPath) => {
createShallowWrapper({ customMetricsAvailable: true });
store.state.monitoringDashboard.emptyState = false;
setupAllDashboards(store, dashboardPath);
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
- });
+ await nextTick();
+ expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
},
);
- it('gets passed false if empty state is shown', () => {
+ it('gets passed false if empty state is shown', async () => {
createShallowWrapper({ customMetricsAvailable: true });
store.state.monitoringDashboard.emptyState = true;
setupAllDashboards(store, ootbDashboards[0]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
- });
+ await nextTick();
+ expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
});
- it('gets passed false if custom metrics are not available', () => {
+ it('gets passed false if custom metrics are not available', async () => {
createShallowWrapper({ customMetricsAvailable: false });
store.state.monitoringDashboard.emptyState = false;
setupAllDashboards(store, ootbDashboards[0]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
- });
+ await nextTick();
+ expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false);
});
});
- it('custom metrics path gets passed', () => {
+ it('custom metrics path gets passed', async () => {
const path = 'https://path/to/customMetrics';
createShallowWrapper({ customMetricsPath: path });
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('customMetricsPath')).toBe(path);
- });
+ await nextTick();
+ expect(findActionsMenu().props('customMetricsPath')).toBe(path);
});
- it('validate query path gets passed', () => {
+ it('validate query path gets passed', async () => {
const path = 'https://path/to/validateQuery';
createShallowWrapper({ validateQueryPath: path });
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('validateQueryPath')).toBe(path);
- });
+ await nextTick();
+ expect(findActionsMenu().props('validateQueryPath')).toBe(path);
});
- it('default branch gets passed', () => {
+ it('default branch gets passed', async () => {
const branch = 'branchName';
createShallowWrapper({ defaultBranch: branch });
- return wrapper.vm.$nextTick().then(() => {
- expect(findActionsMenu().props('defaultBranch')).toBe(branch);
- });
+ await nextTick();
+ expect(findActionsMenu().props('defaultBranch')).toBe(branch);
});
});
@@ -385,40 +372,36 @@ describe('Dashboard header', () => {
store.state.monitoringDashboard.operationsSettingsPath = '';
});
- it('is rendered when the user can access the project settings and path to settings is available', () => {
+ it('is rendered when the user can access the project settings and path to settings is available', async () => {
store.state.monitoringDashboard.canAccessOperationsSettings = true;
store.state.monitoringDashboard.operationsSettingsPath = url;
- return wrapper.vm.$nextTick(() => {
- expect(findSettingsButton().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findSettingsButton().exists()).toBe(true);
});
- it('is not rendered when the user can not access the project settings', () => {
+ it('is not rendered when the user can not access the project settings', async () => {
store.state.monitoringDashboard.canAccessOperationsSettings = false;
store.state.monitoringDashboard.operationsSettingsPath = url;
- return wrapper.vm.$nextTick(() => {
- expect(findSettingsButton().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findSettingsButton().exists()).toBe(false);
});
- it('is not rendered when the path to settings is unavailable', () => {
+ it('is not rendered when the path to settings is unavailable', async () => {
store.state.monitoringDashboard.canAccessOperationsSettings = false;
store.state.monitoringDashboard.operationsSettingsPath = '';
- return wrapper.vm.$nextTick(() => {
- expect(findSettingsButton().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findSettingsButton().exists()).toBe(false);
});
- it('leads to the project settings page', () => {
+ it('leads to the project settings page', async () => {
store.state.monitoringDashboard.canAccessOperationsSettings = true;
store.state.monitoringDashboard.operationsSettingsPath = url;
- return wrapper.vm.$nextTick(() => {
- expect(findSettingsButton().attributes('href')).toBe(url);
- });
+ await nextTick();
+ expect(findSettingsButton().attributes('href')).toBe(url);
});
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
index 400ac2e8f85..f19ef6c6fb7 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
@@ -1,5 +1,6 @@
import { GlCard, GlForm, GlFormTextarea, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue';
import { createStore } from '~/monitoring/stores';
@@ -90,21 +91,20 @@ describe('dashboard invalid url parameters', () => {
expect(mockShowToast).toHaveBeenCalledTimes(1);
});
- it('on submit fetches a panel preview', () => {
+ it('on submit fetches a panel preview', async () => {
findForm().vm.$emit('submit', new Event('submit'));
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/fetchPanelPreview',
- expect.stringContaining('title:'),
- );
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/fetchPanelPreview',
+ expect.stringContaining('title:'),
+ );
});
describe('when form is submitted', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.REQUEST_PANEL_PREVIEW}`, 'mock yml content');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('submit button is disabled', () => {
@@ -118,23 +118,21 @@ describe('dashboard invalid url parameters', () => {
expect(findTimeRangePicker().exists()).toBe(true);
});
- it('when changed does not trigger data fetch unless preview panel button is clicked', () => {
+ it('when changed does not trigger data fetch unless preview panel button is clicked', async () => {
// mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false
store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false);
- return wrapper.vm.$nextTick(() => {
- expect(store.dispatch).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(store.dispatch).not.toHaveBeenCalled();
});
- it('when changed triggers data fetch if preview panel button is clicked', () => {
+ it('when changed triggers data fetch if preview panel button is clicked', async () => {
findForm().vm.$emit('submit', new Event('submit'));
store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange);
- return wrapper.vm.$nextTick(() => {
- expect(store.dispatch).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalled();
});
});
@@ -143,27 +141,25 @@ describe('dashboard invalid url parameters', () => {
expect(findRefreshButton().exists()).toBe(true);
});
- it('when clicked does not trigger data fetch unless preview panel button is clicked', () => {
+ it('when clicked does not trigger data fetch unless preview panel button is clicked', async () => {
// mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false
store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false);
- return wrapper.vm.$nextTick(() => {
- expect(store.dispatch).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(store.dispatch).not.toHaveBeenCalled();
});
- it('when clicked triggers data fetch if preview panel button is clicked', () => {
+ it('when clicked triggers data fetch if preview panel button is clicked', async () => {
// mimic state where preview is visible. SET_PANEL_PREVIEW_IS_SHOWN is set to true
store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, true);
findRefreshButton().vm.$emit('click');
- return wrapper.vm.$nextTick(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/fetchPanelPreviewMetrics',
- undefined,
- );
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/fetchPanelPreviewMetrics',
+ undefined,
+ );
});
});
@@ -190,9 +186,9 @@ describe('dashboard invalid url parameters', () => {
describe('when there is an error', () => {
const mockError = 'an error occurred!';
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_FAILURE}`, mockError);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays an alert', () => {
@@ -204,19 +200,18 @@ describe('dashboard invalid url parameters', () => {
expect(findPanel().props('graphData')).toBe(null);
});
- it('changing time range should not refetch data', () => {
+ it('changing time range should not refetch data', async () => {
store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange);
- return wrapper.vm.$nextTick(() => {
- expect(store.dispatch).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(store.dispatch).not.toHaveBeenCalled();
});
});
describe('when panel data is available', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_SUCCESS}`, mockPanel);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays no alert', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index 9a73dc820af..7bd062b81f1 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -2,6 +2,7 @@ import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
+import { nextTick } from 'vue';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import invalidUrl from '~/lib/utils/invalid_url';
@@ -186,7 +187,7 @@ describe('Dashboard Panel', () => {
expect(findCopyLink().exists()).toBe(false);
});
- it('should emit `timerange` event when a zooming in/out in a chart occcurs', () => {
+ it('should emit `timerange` event when a zooming in/out in a chart occcurs', async () => {
const timeRange = {
start: '2020-01-01T00:00:00.000Z',
end: '2020-01-01T01:00:00.000Z',
@@ -196,9 +197,8 @@ describe('Dashboard Panel', () => {
findTimeChart().vm.$emit('datazoom', timeRange);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('timerangezoom', timeRange);
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('timerangezoom', timeRange);
});
it('includes a default group id', () => {
@@ -253,16 +253,15 @@ describe('Dashboard Panel', () => {
describe('computed', () => {
describe('fixedCurrentTimeRange', () => {
- it('returns fixed time for valid time range', () => {
+ it('returns fixed time for valid time range', async () => {
state.timeRange = mockTimeRange;
- return wrapper.vm.$nextTick(() => {
- expect(findTimeChart().props('timeRange')).toEqual(
- expect.objectContaining({
- start: expect.any(String),
- end: expect.any(String),
- }),
- );
- });
+ await nextTick();
+ expect(findTimeChart().props('timeRange')).toEqual(
+ expect.objectContaining({
+ start: expect.any(String),
+ end: expect.any(String),
+ }),
+ );
});
it.each`
@@ -271,11 +270,10 @@ describe('Dashboard Panel', () => {
${undefined} | ${{}}
${null} | ${{}}
${'2020-12-03'} | ${{}}
- `('returns $output for invalid input like $input', ({ input, output }) => {
+ `('returns $output for invalid input like $input', async ({ input, output }) => {
state.timeRange = input;
- return wrapper.vm.$nextTick(() => {
- expect(findTimeChart().props('timeRange')).toEqual(output);
- });
+ await nextTick();
+ expect(findTimeChart().props('timeRange')).toEqual(output);
});
});
});
@@ -285,17 +283,16 @@ describe('Dashboard Panel', () => {
const findEditCustomMetricLink = () => wrapper.find({ ref: 'editMetricLink' });
const mockEditPath = '/root/kubernetes-gke-project/prometheus/metrics/23/edit';
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper();
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('is not present if the panel is not a custom metric', () => {
expect(findEditCustomMetricLink().exists()).toBe(false);
});
- it('is present when the panel contains an edit_path property', () => {
+ it('is present when the panel contains an edit_path property', async () => {
wrapper.setProps({
graphData: {
...graphData,
@@ -308,14 +305,13 @@ describe('Dashboard Panel', () => {
},
});
- return wrapper.vm.$nextTick(() => {
- expect(findEditCustomMetricLink().exists()).toBe(true);
- expect(findEditCustomMetricLink().text()).toBe('Edit metric');
- expect(findEditCustomMetricLink().attributes('href')).toBe(mockEditPath);
- });
+ await nextTick();
+ expect(findEditCustomMetricLink().exists()).toBe(true);
+ expect(findEditCustomMetricLink().text()).toBe('Edit metric');
+ expect(findEditCustomMetricLink().attributes('href')).toBe(mockEditPath);
});
- it('shows an "Edit metrics" link pointing to settingsPath for a panel with multiple metrics', () => {
+ it('shows an "Edit metrics" link pointing to settingsPath for a panel with multiple metrics', async () => {
wrapper.setProps({
graphData: {
...graphData,
@@ -332,63 +328,58 @@ describe('Dashboard Panel', () => {
},
});
- return wrapper.vm.$nextTick(() => {
- expect(findEditCustomMetricLink().text()).toBe('Edit metrics');
- expect(findEditCustomMetricLink().attributes('href')).toBe(dashboardProps.settingsPath);
- });
+ await nextTick();
+ expect(findEditCustomMetricLink().text()).toBe('Edit metrics');
+ expect(findEditCustomMetricLink().attributes('href')).toBe(dashboardProps.settingsPath);
});
});
describe('View Logs dropdown item', () => {
const findViewLogsLink = () => wrapper.find({ ref: 'viewLogsLink' });
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('is not present by default', () =>
- wrapper.vm.$nextTick(() => {
- expect(findViewLogsLink().exists()).toBe(false);
- }));
+ it('is not present by default', async () => {
+ await nextTick();
+ expect(findViewLogsLink().exists()).toBe(false);
+ });
- it('is not present if a time range is not set', () => {
+ it('is not present if a time range is not set', async () => {
state.logsPath = mockLogsPath;
state.timeRange = null;
- return wrapper.vm.$nextTick(() => {
- expect(findViewLogsLink().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findViewLogsLink().exists()).toBe(false);
});
- it('is not present if the logs path is default', () => {
+ it('is not present if the logs path is default', async () => {
state.logsPath = invalidUrl;
state.timeRange = mockTimeRange;
- return wrapper.vm.$nextTick(() => {
- expect(findViewLogsLink().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findViewLogsLink().exists()).toBe(false);
});
- it('is not present if the logs path is not set', () => {
+ it('is not present if the logs path is not set', async () => {
state.logsPath = null;
state.timeRange = mockTimeRange;
- return wrapper.vm.$nextTick(() => {
- expect(findViewLogsLink().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findViewLogsLink().exists()).toBe(false);
});
- it('is present when logs path and time a range is present', () => {
+ it('is present when logs path and time a range is present', async () => {
state.logsPath = mockLogsPath;
state.timeRange = mockTimeRange;
- return wrapper.vm.$nextTick(() => {
- expect(findViewLogsLink().attributes('href')).toMatch(mockLogsHref);
- });
+ await nextTick();
+ expect(findViewLogsLink().attributes('href')).toMatch(mockLogsHref);
});
- it('it is overridden when a datazoom event is received', () => {
+ it('it is overridden when a datazoom event is received', async () => {
state.logsPath = mockLogsPath;
state.timeRange = mockTimeRange;
@@ -399,13 +390,12 @@ describe('Dashboard Panel', () => {
findTimeChart().vm.$emit('datazoom', zoomedTimeRange);
- return wrapper.vm.$nextTick(() => {
- const start = encodeURIComponent(zoomedTimeRange.start);
- const end = encodeURIComponent(zoomedTimeRange.end);
- expect(findViewLogsLink().attributes('href')).toMatch(
- `${mockLogsPath}?start=${start}&end=${end}`,
- );
- });
+ await nextTick();
+ const start = encodeURIComponent(zoomedTimeRange.start);
+ const end = encodeURIComponent(zoomedTimeRange.end);
+ expect(findViewLogsLink().attributes('href')).toMatch(
+ `${mockLogsPath}?start=${start}&end=${end}`,
+ );
});
});
@@ -447,7 +437,7 @@ describe('Dashboard Panel', () => {
});
describe('when downloading metrics data as CSV', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = shallowMount(DashboardPanel, {
propsData: {
clipboardText: exampleText,
@@ -459,7 +449,7 @@ describe('Dashboard Panel', () => {
},
store,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -509,29 +499,26 @@ describe('Dashboard Panel', () => {
});
});
- it('handles namespaced time range and logs path state', () => {
+ it('handles namespaced time range and logs path state', async () => {
store.state[mockNamespace].timeRange = mockTimeRange;
store.state[mockNamespace].logsPath = mockLogsPath;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find({ ref: 'viewLogsLink' }).attributes().href).toBe(mockLogsHref);
- });
+ await nextTick();
+ expect(wrapper.find({ ref: 'viewLogsLink' }).attributes().href).toBe(mockLogsHref);
});
- it('handles namespaced deployment data state', () => {
+ it('handles namespaced deployment data state', async () => {
store.state[mockNamespace].deploymentData = mockDeploymentData;
- return wrapper.vm.$nextTick().then(() => {
- expect(findTimeChart().props().deploymentData).toEqual(mockDeploymentData);
- });
+ await nextTick();
+ expect(findTimeChart().props().deploymentData).toEqual(mockDeploymentData);
});
- it('handles namespaced project path state', () => {
+ it('handles namespaced project path state', async () => {
store.state[mockNamespace].projectPath = mockProjectPath;
- return wrapper.vm.$nextTick().then(() => {
- expect(findTimeChart().props().projectPath).toBe(mockProjectPath);
- });
+ await nextTick();
+ expect(findTimeChart().props().projectPath).toBe(mockProjectPath);
});
it('it renders a time series chart with no errors', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 7730e7f347f..6c5972e1140 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -1,5 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import VueDraggable from 'vuedraggable';
+import { nextTick } from 'vue';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -77,51 +78,47 @@ describe('Dashboard', () => {
});
describe('request information to the server', () => {
- it('calls to set time range and fetch data', () => {
+ it('calls to set time range and fetch data', async () => {
createShallowWrapper({ hasMetrics: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/setTimeRange',
- expect.any(Object),
- );
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/setTimeRange',
+ expect.any(Object),
+ );
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- });
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
- it('shows up a loading state', () => {
+ it('shows up a loading state', async () => {
store.state.monitoringDashboard.emptyState = dashboardEmptyStates.LOADING;
createShallowWrapper({ hasMetrics: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(EmptyState).exists()).toBe(true);
- expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING);
- });
+ await nextTick();
+ expect(wrapper.find(EmptyState).exists()).toBe(true);
+ expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING);
});
- it('hides the group panels when showPanels is false', () => {
+ it('hides the group panels when showPanels is false', async () => {
createMountedWrapper({ hasMetrics: true, showPanels: false });
setupStoreWithData(store);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.emptyState).toBeNull();
- expect(wrapper.findAll('.prometheus-panel')).toHaveLength(0);
- });
+ await nextTick();
+ expect(wrapper.vm.emptyState).toBeNull();
+ expect(wrapper.findAll('.prometheus-panel')).toHaveLength(0);
});
- it('fetches the metrics data with proper time window', () => {
+ it('fetches the metrics data with proper time window', async () => {
createMountedWrapper({ hasMetrics: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/setTimeRange',
- expect.objectContaining({ duration: { seconds: 28800 } }),
- );
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/setTimeRange',
+ expect.objectContaining({ duration: { seconds: 28800 } }),
+ );
});
});
@@ -133,69 +130,63 @@ describe('Dashboard', () => {
.at(index);
};
- beforeEach(() => {
+ beforeEach(async () => {
createMountedWrapper({ hasMetrics: true });
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
describe('when the graph group has an even number of panels', () => {
- it('2 panels - all panel wrappers take half width of their parent', () => {
+ it('2 panels - all panel wrappers take half width of their parent', async () => {
setupStoreWithDataForPanelCount(store, 2);
- wrapper.vm.$nextTick(() => {
- expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
- });
+ await nextTick();
+ expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
});
- it('4 panels - all panel wrappers take half width of their parent', () => {
+ it('4 panels - all panel wrappers take half width of their parent', async () => {
setupStoreWithDataForPanelCount(store, 4);
- wrapper.vm.$nextTick(() => {
- expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true);
- });
+ await nextTick();
+ expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true);
});
});
describe('when the graph group has an odd number of panels', () => {
- it('1 panel - panel wrapper does not take half width of its parent', () => {
+ it('1 panel - panel wrapper does not take half width of its parent', async () => {
setupStoreWithDataForPanelCount(store, 1);
- wrapper.vm.$nextTick(() => {
- expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(false);
- });
+ await nextTick();
+ expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(false);
});
- it('3 panels - all panels but last take half width of their parents', () => {
+ it('3 panels - all panels but last take half width of their parents', async () => {
setupStoreWithDataForPanelCount(store, 3);
- wrapper.vm.$nextTick(() => {
- expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(false);
- });
+ await nextTick();
+ expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(false);
});
- it('5 panels - all panels but last take half width of their parents', () => {
+ it('5 panels - all panels but last take half width of their parents', async () => {
setupStoreWithDataForPanelCount(store, 5);
- wrapper.vm.$nextTick(() => {
- expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true);
- expect(findPanelLayoutWrapperAt(4).classes('col-lg-6')).toBe(false);
- });
+ await nextTick();
+ expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true);
+ expect(findPanelLayoutWrapperAt(4).classes('col-lg-6')).toBe(false);
});
});
});
describe('dashboard validation warning', () => {
- it('displays a warning if there are validation warnings', () => {
+ it('displays a warning if there are validation warnings', async () => {
createMountedWrapper({ hasMetrics: true });
store.commit(
@@ -203,12 +194,11 @@ describe('Dashboard', () => {
true,
);
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(createFlash).toHaveBeenCalled();
});
- it('does not display a warning if there are no validation warnings', () => {
+ it('does not display a warning if there are no validation warnings', async () => {
createMountedWrapper({ hasMetrics: true });
store.commit(
@@ -216,9 +206,8 @@ describe('Dashboard', () => {
false,
);
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(createFlash).not.toHaveBeenCalled();
});
});
@@ -233,7 +222,7 @@ describe('Dashboard', () => {
setWindowLocation(location);
});
- it('when the URL points to a panel it expands', () => {
+ it('when the URL points to a panel it expands', async () => {
const panelGroup = metricsDashboardViewModel.panelGroups[0];
const panel = panelGroup.panels[0];
@@ -246,32 +235,30 @@ describe('Dashboard', () => {
createMountedWrapper({ hasMetrics: true });
setupStoreWithData(store);
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setExpandedPanel', {
- group: panelGroup.group,
- panel: expect.objectContaining({
- title: panel.title,
- y_label: panel.y_label,
- }),
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setExpandedPanel', {
+ group: panelGroup.group,
+ panel: expect.objectContaining({
+ title: panel.title,
+ y_label: panel.y_label,
+ }),
});
});
- it('when the URL does not link to any panel, no panel is expanded', () => {
+ it('when the URL does not link to any panel, no panel is expanded', async () => {
setSearch();
createMountedWrapper({ hasMetrics: true });
setupStoreWithData(store);
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'monitoringDashboard/setExpandedPanel',
- expect.anything(),
- );
- });
+ await nextTick();
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'monitoringDashboard/setExpandedPanel',
+ expect.anything(),
+ );
});
- it('when the URL points to an incorrect panel it shows an error', () => {
+ it('when the URL points to an incorrect panel it shows an error', async () => {
const panelGroup = metricsDashboardViewModel.panelGroups[0];
const panel = panelGroup.panels[0];
@@ -284,13 +271,12 @@ describe('Dashboard', () => {
createMountedWrapper({ hasMetrics: true });
setupStoreWithData(store);
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalled();
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'monitoringDashboard/setExpandedPanel',
- expect.anything(),
- );
- });
+ await nextTick();
+ expect(createFlash).toHaveBeenCalled();
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'monitoringDashboard/setExpandedPanel',
+ expect.anything(),
+ );
});
});
@@ -319,7 +305,7 @@ describe('Dashboard', () => {
window.history.pushState.mockRestore();
});
- it('URL is updated with panel parameters', () => {
+ it('URL is updated with panel parameters', async () => {
createMountedWrapper({ hasMetrics: true });
expandPanel(group, panel);
@@ -329,17 +315,16 @@ describe('Dashboard', () => {
y_label: panel.y_label,
});
- return wrapper.vm.$nextTick(() => {
- expect(window.history.pushState).toHaveBeenCalledTimes(1);
- expect(window.history.pushState).toHaveBeenCalledWith(
- expect.anything(), // state
- expect.any(String), // document title
- expect.stringContaining(`${expectedSearch}`),
- );
- });
+ await nextTick();
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(), // state
+ expect.any(String), // document title
+ expect.stringContaining(`${expectedSearch}`),
+ );
});
- it('URL is updated with panel parameters and custom dashboard', () => {
+ it('URL is updated with panel parameters and custom dashboard', async () => {
const dashboard = 'dashboard.yml';
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
@@ -355,36 +340,34 @@ describe('Dashboard', () => {
y_label: panel.y_label,
});
- return wrapper.vm.$nextTick(() => {
- expect(window.history.pushState).toHaveBeenCalledTimes(1);
- expect(window.history.pushState).toHaveBeenCalledWith(
- expect.anything(), // state
- expect.any(String), // document title
- expect.stringContaining(`${expectedSearch}`),
- );
- });
+ await nextTick();
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(), // state
+ expect.any(String), // document title
+ expect.stringContaining(`${expectedSearch}`),
+ );
});
- it('URL is updated with no parameters', () => {
+ it('URL is updated with no parameters', async () => {
expandPanel(group, panel);
createMountedWrapper({ hasMetrics: true });
expandPanel(null, null);
- return wrapper.vm.$nextTick(() => {
- expect(window.history.pushState).toHaveBeenCalledTimes(1);
- expect(window.history.pushState).toHaveBeenCalledWith(
- expect.anything(), // state
- expect.any(String), // document title
- expect.not.stringMatching(/group|title|y_label/), // no panel params
- );
- });
+ await nextTick();
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(), // state
+ expect.any(String), // document title
+ expect.not.stringMatching(/group|title|y_label/), // no panel params
+ );
});
});
describe('when all panels in the first group are loading', () => {
const findGroupAt = (i) => wrapper.findAll(GraphGroup).at(i);
- beforeEach(() => {
+ beforeEach(async () => {
setupStoreWithDashboard(store);
const { panels } = store.state.monitoringDashboard.dashboard.panelGroups[0];
@@ -396,7 +379,7 @@ describe('Dashboard', () => {
createShallowWrapper();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('a loading icon appears in the first group', () => {
@@ -409,7 +392,7 @@ describe('Dashboard', () => {
});
describe('when all requests have been committed by the store', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentEnvironmentName: 'production',
currentDashboard: dashboardGitResponse[0].path,
@@ -418,26 +401,25 @@ describe('Dashboard', () => {
createMountedWrapper({ hasMetrics: true });
setupStoreWithData(store);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('it does not show loading icons in any group', () => {
+ it('it does not show loading icons in any group', async () => {
setupStoreWithData(store);
- wrapper.vm.$nextTick(() => {
- wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => {
- expect(groupWrapper.props('isLoading')).toBe(false);
- });
+ await nextTick();
+ wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => {
+ expect(groupWrapper.props('isLoading')).toBe(false);
});
});
});
describe('variables section', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true });
setupStoreWithData(store);
store.state.monitoringDashboard.variables = storeVariables;
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows the variables section', () => {
@@ -446,12 +428,11 @@ describe('Dashboard', () => {
});
describe('links section', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true });
setupStoreWithData(store);
setupStoreWithLinks(store);
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows the links section', () => {
@@ -464,10 +445,10 @@ describe('Dashboard', () => {
const findExpandedPanel = () => wrapper.find({ ref: 'expandedPanel' });
describe('when the panel is not expanded', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true });
setupStoreWithData(store);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('expanded panel is not visible', () => {
@@ -502,7 +483,7 @@ describe('Dashboard', () => {
template: `<div><slot name="top-left"/></div>`,
};
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true }, { stubs: { DashboardPanel: MockPanel } });
setupStoreWithData(store);
@@ -517,8 +498,7 @@ describe('Dashboard', () => {
});
jest.spyOn(store, 'dispatch');
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays a single panel and others are hidden', () => {
@@ -561,13 +541,12 @@ describe('Dashboard', () => {
});
describe('when one of the metrics is missing', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true });
setupStoreWithDashboard(store);
setMetricResult({ store, result: [], panel: 2 });
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows a group empty area', () => {
@@ -590,14 +569,13 @@ describe('Dashboard', () => {
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
- beforeEach(() => {
+ beforeEach(async () => {
// call original dispatch
store.dispatch.mockRestore();
createShallowWrapper({ hasMetrics: true });
setupStoreWithData(store);
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('wraps vuedraggable', () => {
@@ -611,9 +589,9 @@ describe('Dashboard', () => {
});
describe('when rearrange is enabled', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.setProps({ rearrangePanelsAvailable: true });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays rearrange button', () => {
@@ -624,9 +602,9 @@ describe('Dashboard', () => {
const findFirstDraggableRemoveButton = () =>
findDraggablePanels().at(0).find('.js-draggable-remove');
- beforeEach(() => {
+ beforeEach(async () => {
findRearrangeButton().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('it enables draggables', () => {
@@ -634,7 +612,7 @@ describe('Dashboard', () => {
expect(findEnabledDraggables().wrappers).toEqual(findDraggables().wrappers);
});
- it('metrics can be swapped', () => {
+ it('metrics can be swapped', async () => {
const firstDraggable = findDraggables().at(0);
const mockMetrics = [...metricsDashboardViewModel.panelGroups[0].panels];
@@ -645,43 +623,40 @@ describe('Dashboard', () => {
[mockMetrics[0], mockMetrics[1]] = [mockMetrics[1], mockMetrics[0]];
firstDraggable.vm.$emit('input', mockMetrics);
- return wrapper.vm.$nextTick(() => {
- const { panels } = wrapper.vm.dashboard.panelGroups[0];
+ await nextTick();
+ const { panels } = wrapper.vm.dashboard.panelGroups[0];
- expect(panels[1].title).toEqual(firstTitle);
- expect(panels[0].title).toEqual(secondTitle);
- });
+ expect(panels[1].title).toEqual(firstTitle);
+ expect(panels[0].title).toEqual(secondTitle);
});
- it('shows a remove button, which removes a panel', () => {
+ it('shows a remove button, which removes a panel', async () => {
expect(findFirstDraggableRemoveButton().find('a').exists()).toBe(true);
expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount);
findFirstDraggableRemoveButton().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount - 1);
- });
+ await nextTick();
+ expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount - 1);
});
- it('it disables draggables when clicked again', () => {
+ it('it disables draggables when clicked again', async () => {
findRearrangeButton().vm.$emit('click');
- return wrapper.vm.$nextTick(() => {
- expect(findRearrangeButton().attributes('pressed')).toBeFalsy();
- expect(findEnabledDraggables().length).toBe(0);
- });
+ await nextTick();
+ expect(findRearrangeButton().attributes('pressed')).toBeFalsy();
+ expect(findEnabledDraggables().length).toBe(0);
});
});
});
});
describe('cluster health', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createShallowWrapper({ hasMetrics: true, showHeader: false });
// all_dashboards is not defined in health dashboards
store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('hides dashboard header by default', () => {
@@ -706,34 +681,31 @@ describe('Dashboard', () => {
document.title = '';
});
- it('is prepended with the overview dashboard name by default', () => {
+ it('is prepended with the overview dashboard name by default', async () => {
setupAllDashboards(store);
- return wrapper.vm.$nextTick().then(() => {
- expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true);
- });
+ await nextTick();
+ expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true);
});
- it('is prepended with dashboard name if path is known', () => {
+ it('is prepended with dashboard name if path is known', async () => {
const dashboard = dashboardGitResponse[1];
const currentDashboard = dashboard.path;
setupAllDashboards(store, currentDashboard);
- return wrapper.vm.$nextTick().then(() => {
- expect(document.title.startsWith(`${dashboard.display_name} · `)).toBe(true);
- });
+ await nextTick();
+ expect(document.title.startsWith(`${dashboard.display_name} · `)).toBe(true);
});
- it('is prepended with the overview dashboard name if path is not known', () => {
+ it('is prepended with the overview dashboard name if path is not known', async () => {
setupAllDashboards(store, 'unknown/path');
- return wrapper.vm.$nextTick().then(() => {
- expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true);
- });
+ await nextTick();
+ expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true);
});
- it('is not modified when dashboard name is not provided', () => {
+ it('is not modified when dashboard name is not provided', async () => {
const dashboard = { ...dashboardGitResponse[1], display_name: null };
const currentDashboard = dashboard.path;
@@ -743,9 +715,8 @@ describe('Dashboard', () => {
currentDashboard,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(document.title).toBe(originalTitle);
- });
+ await nextTick();
+ expect(document.title).toBe(originalTitle);
});
});
@@ -756,14 +727,13 @@ describe('Dashboard', () => {
const getClipboardTextFirstPanel = () =>
wrapper.findAll(DashboardPanel).at(panelIndex).props('clipboardText');
- beforeEach(() => {
+ beforeEach(async () => {
setupStoreWithData(store);
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentDashboard,
});
createShallowWrapper({ hasMetrics: true });
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('contains a link to the dashboard', () => {
@@ -785,7 +755,7 @@ describe('Dashboard', () => {
// the dashboard panels have a ref attribute set.
const getDashboardPanel = () => wrapper.find({ ref: panelRef });
- beforeEach(() => {
+ beforeEach(async () => {
setupStoreWithData(store);
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentDashboard,
@@ -795,8 +765,7 @@ describe('Dashboard', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ hoveredPanel: panelRef });
-
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('contains a ref attribute inside a DashboardPanel component', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index e6785f34597..246dd598d19 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
@@ -51,23 +52,22 @@ describe('dashboard invalid url parameters', () => {
queryToObject.mockReset();
});
- it('passes default url parameters to the time range picker', () => {
+ it('passes default url parameters to the time range picker', async () => {
queryToObject.mockReturnValue({});
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange);
+ await nextTick();
+ expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange);
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/setTimeRange',
- expect.any(Object),
- );
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- });
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/setTimeRange',
+ expect.any(Object),
+ );
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
- it('passes a fixed time range in the URL to the time range picker', () => {
+ it('passes a fixed time range in the URL to the time range picker', async () => {
const params = {
start: '2019-01-01T00:00:00.000Z',
end: '2019-01-10T00:00:00.000Z',
@@ -77,37 +77,35 @@ describe('dashboard invalid url parameters', () => {
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- expect(findDateTimePicker().props('value')).toEqual(params);
+ await nextTick();
+ expect(findDateTimePicker().props('value')).toEqual(params);
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setTimeRange', params);
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- });
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setTimeRange', params);
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
- it('passes a rolling time range in the URL to the time range picker', () => {
+ it('passes a rolling time range in the URL to the time range picker', async () => {
queryToObject.mockReturnValue({
duration_seconds: '120',
});
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- const expectedTimeRange = {
- duration: { seconds: 60 * 2 },
- };
+ await nextTick();
+ const expectedTimeRange = {
+ duration: { seconds: 60 * 2 },
+ };
- expect(findDateTimePicker().props('value')).toMatchObject(expectedTimeRange);
+ expect(findDateTimePicker().props('value')).toMatchObject(expectedTimeRange);
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/setTimeRange',
- expectedTimeRange,
- );
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- });
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/setTimeRange',
+ expectedTimeRange,
+ );
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
- it('shows an error message and loads a default time range if invalid url parameters are passed', () => {
+ it('shows an error message and loads a default time range if invalid url parameters are passed', async () => {
queryToObject.mockReturnValue({
start: '<script>alert("XSS")</script>',
end: '<script>alert("XSS")</script>',
@@ -115,37 +113,35 @@ describe('dashboard invalid url parameters', () => {
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalled();
+ await nextTick();
+ expect(createFlash).toHaveBeenCalled();
- expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange);
+ expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange);
- expect(store.dispatch).toHaveBeenCalledWith(
- 'monitoringDashboard/setTimeRange',
- defaultTimeRange,
- );
- expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
- });
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'monitoringDashboard/setTimeRange',
+ defaultTimeRange,
+ );
+ expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
- it('redirects to different time range', () => {
+ it('redirects to different time range', async () => {
const toUrl = `${mockProjectDir}/-/environments/1/metrics`;
removeParams.mockReturnValueOnce(toUrl);
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- findDateTimePicker().vm.$emit('input', {
- duration: { seconds: 120 },
- });
-
- // redirect to with new parameters
- expect(mergeUrlParams).toHaveBeenCalledWith({ duration_seconds: '120' }, toUrl);
- expect(redirectTo).toHaveBeenCalledTimes(1);
+ await nextTick();
+ findDateTimePicker().vm.$emit('input', {
+ duration: { seconds: 120 },
});
+
+ // redirect to with new parameters
+ expect(mergeUrlParams).toHaveBeenCalledWith({ duration_seconds: '120' }, toUrl);
+ expect(redirectTo).toHaveBeenCalledTimes(1);
});
- it('changes the url when a panel moves the time slider', () => {
+ it('changes the url when a panel moves the time slider', async () => {
const timeRange = {
start: '2020-01-01T00:00:00.000Z',
end: '2020-01-01T01:00:00.000Z',
@@ -155,12 +151,11 @@ describe('dashboard invalid url parameters', () => {
createMountedWrapper();
- return wrapper.vm.$nextTick().then(() => {
- wrapper.vm.onTimeRangeZoom(timeRange);
+ await nextTick();
+ wrapper.vm.onTimeRangeZoom(timeRange);
- expect(updateHistory).toHaveBeenCalled();
- expect(wrapper.vm.selectedTimeRange.start.toString()).toBe(timeRange.start);
- expect(wrapper.vm.selectedTimeRange.end.toString()).toBe(timeRange.end);
- });
+ expect(updateHistory).toHaveBeenCalled();
+ expect(wrapper.vm.selectedTimeRange.start.toString()).toBe(timeRange.start);
+ expect(wrapper.vm.selectedTimeRange.end.toString()).toBe(timeRange.end);
});
});
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index 79b223d96e4..47366b345a8 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlCard } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue';
@@ -12,8 +13,7 @@ import {
multipleEmbedProps,
} from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Embed Group', () => {
let wrapper;
@@ -23,7 +23,6 @@ describe('Embed Group', () => {
function mountComponent({ urls = [TEST_HOST], shallow = true, stubs } = {}) {
const mountMethod = shallow ? shallowMount : mount;
wrapper = mountMethod(EmbedGroup, {
- localVue,
store,
propsData: {
urls,
@@ -76,16 +75,14 @@ describe('Embed Group', () => {
expect(wrapper.find('.gl-card-body').classes()).not.toContain('d-none');
});
- it('collapses when clicked', (done) => {
+ it('collapses when clicked', async () => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
wrapper.find(GlButton).trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.gl-card-body').classes()).toContain('d-none');
- done();
- });
+ await nextTick();
+ expect(wrapper.find('.gl-card-body').classes()).toContain('d-none');
});
});
diff --git a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
index 90647f50b14..f9f1be4f277 100644
--- a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
+++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { setHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
@@ -6,8 +7,7 @@ import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
import { groups, initialState, metricsData, metricsWithData } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('MetricEmbed', () => {
let wrapper;
@@ -17,7 +17,6 @@ describe('MetricEmbed', () => {
function mountComponent() {
wrapper = shallowMount(MetricEmbed, {
- localVue,
store,
propsData: {
dashboardUrl: TEST_HOST,
diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js
index 625dd3f0b33..c5b45564089 100644
--- a/spec/frontend/monitoring/components/graph_group_spec.js
+++ b/spec/frontend/monitoring/components/graph_group_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import GraphGroup from '~/monitoring/components/graph_group.vue';
describe('Graph group component', () => {
@@ -38,13 +39,12 @@ describe('Graph group component', () => {
expect(findCaretIcon().props('name')).toBe('angle-down');
});
- it('should show the angle-right caret icon when the user collapses the group', () => {
+ it('should show the angle-right caret icon when the user collapses the group', async () => {
findToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findContent().isVisible()).toBe(false);
- expect(findCaretIcon().props('name')).toBe('angle-right');
- });
+ await nextTick();
+ expect(findContent().isVisible()).toBe(false);
+ expect(findCaretIcon().props('name')).toBe('angle-right');
});
it('should contain a tab index for the collapse button', () => {
@@ -53,15 +53,14 @@ describe('Graph group component', () => {
expect(groupToggle.attributes('tabindex')).toBeDefined();
});
- it('should show the open the group when collapseGroup is set to true', () => {
+ it('should show the open the group when collapseGroup is set to true', async () => {
wrapper.setProps({
collapseGroup: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findContent().isVisible()).toBe(true);
- expect(findCaretIcon().props('name')).toBe('angle-down');
- });
+ await nextTick();
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().props('name')).toBe('angle-down');
});
});
@@ -77,12 +76,11 @@ describe('Graph group component', () => {
expect(findCaretIcon().props('name')).toBe('angle-right');
});
- it('should show the angle-right caret icon when collapseGroup is false', () => {
+ it('should show the angle-right caret icon when collapseGroup is false', async () => {
findToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findCaretIcon().props('name')).toBe('angle-down');
- });
+ await nextTick();
+ expect(findCaretIcon().props('name')).toBe('angle-down');
});
it('should call collapse the graph group content when enter is pressed on the caret icon', () => {
@@ -137,15 +135,14 @@ describe('Graph group component', () => {
expect(findCaretIcon().exists()).toBe(false);
});
- it('should show the panel content when collapse is set to false', () => {
+ it('should show the panel content when collapse is set to false', async () => {
wrapper.setProps({
collapseGroup: false,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findContent().isVisible()).toBe(true);
- expect(findCaretIcon().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js
index e37abf6722a..c9b5aeeecb8 100644
--- a/spec/frontend/monitoring/components/links_section_spec.js
+++ b/spec/frontend/monitoring/components/links_section_spec.js
@@ -36,7 +36,7 @@ describe('Links Section component', () => {
expect(findLinks().length).toBe(0);
});
- it('renders a link inside a section', () => {
+ it('renders a link inside a section', async () => {
setState([
{
title: 'GitLab Website',
@@ -44,23 +44,21 @@ describe('Links Section component', () => {
},
]);
- return wrapper.vm.$nextTick(() => {
- expect(findLinks()).toHaveLength(1);
- const firstLink = findLinks().at(0);
+ await nextTick();
+ expect(findLinks()).toHaveLength(1);
+ const firstLink = findLinks().at(0);
- expect(firstLink.attributes('href')).toBe('https://gitlab.com');
- expect(firstLink.text()).toBe('GitLab Website');
- });
+ expect(firstLink.attributes('href')).toBe('https://gitlab.com');
+ expect(firstLink.text()).toBe('GitLab Website');
});
- it('renders multiple links inside a section', () => {
+ it('renders multiple links inside a section', async () => {
const links = new Array(10)
.fill(null)
.map((_, i) => ({ title: `Title ${i}`, url: `https://gitlab.com/projects/${i}` }));
setState(links);
- return wrapper.vm.$nextTick(() => {
- expect(findLinks()).toHaveLength(10);
- });
+ await nextTick();
+ expect(findLinks()).toHaveLength(10);
});
});
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index 248cf32d54b..0e45cc021c5 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
+import { nextTick } from 'vue';
import RefreshButton from '~/monitoring/components/refresh_button.vue';
import { createStore } from '~/monitoring/stores';
@@ -79,9 +80,9 @@ describe('RefreshButton', () => {
describe('when a refresh rate is chosen', () => {
const optIndex = 2; // Other option than "Off"
- beforeEach(() => {
+ beforeEach(async () => {
findOptionAt(optIndex).vm.$emit('click');
- return wrapper.vm.$nextTick;
+ await nextTick();
});
it('refresh rate appears in the dropdown', () => {
@@ -101,7 +102,7 @@ describe('RefreshButton', () => {
jest.runOnlyPendingTimers();
expectFetchDataToHaveBeenCalledTimes(2);
- await wrapper.vm.$nextTick();
+ await nextTick();
jest.runOnlyPendingTimers();
expectFetchDataToHaveBeenCalledTimes(3);
@@ -113,7 +114,7 @@ describe('RefreshButton', () => {
jest.runOnlyPendingTimers();
expectFetchDataToHaveBeenCalledTimes(1);
- await wrapper.vm.$nextTick();
+ await nextTick();
jest.runOnlyPendingTimers();
expectFetchDataToHaveBeenCalledTimes(1);
@@ -128,9 +129,9 @@ describe('RefreshButton', () => {
});
describe('when "Off" refresh rate is chosen', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findOptionAt(0).vm.$emit('click');
- return wrapper.vm.$nextTick;
+ await nextTick();
});
it('refresh rate is "Off" in the dropdown', () => {
diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
index f5ee32e78e6..643bbb39f04 100644
--- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DropdownField from '~/monitoring/components/variables/dropdown_field.vue';
describe('Custom variable component', () => {
@@ -53,14 +54,13 @@ describe('Custom variable component', () => {
expect(findDropdown().exists()).toBe(true);
});
- it('changing dropdown items triggers update', () => {
+ it('changing dropdown items triggers update', async () => {
createShallowWrapper();
jest.spyOn(wrapper.vm, '$emit');
findDropdownItems().at(1).vm.$emit('click');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary');
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary');
});
});
diff --git a/spec/frontend/monitoring/components/variables/text_field_spec.js b/spec/frontend/monitoring/components/variables/text_field_spec.js
index c879803fddd..3073b3968aa 100644
--- a/spec/frontend/monitoring/components/variables/text_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/text_field_spec.js
@@ -1,5 +1,6 @@
import { GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import TextField from '~/monitoring/components/variables/text_field.vue';
describe('Text variable component', () => {
@@ -23,15 +24,14 @@ describe('Text variable component', () => {
expect(findInput().exists()).toBe(true);
});
- it('always has a default value', () => {
+ it('always has a default value', async () => {
createShallowWrapper();
- return wrapper.vm.$nextTick(() => {
- expect(findInput().attributes('value')).toBe(propsData.value);
- });
+ await nextTick();
+ expect(findInput().attributes('value')).toBe(propsData.value);
});
- it('triggers keyup enter', () => {
+ it('triggers keyup enter', async () => {
createShallowWrapper();
jest.spyOn(wrapper.vm, '$emit');
@@ -39,12 +39,11 @@ describe('Text variable component', () => {
findInput().trigger('input');
findInput().trigger('keyup.enter');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'prod-pod');
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'prod-pod');
});
- it('triggers blur enter', () => {
+ it('triggers blur enter', async () => {
createShallowWrapper();
jest.spyOn(wrapper.vm, '$emit');
@@ -52,8 +51,7 @@ describe('Text variable component', () => {
findInput().trigger('input');
findInput().trigger('blur');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary-pod');
- });
+ await nextTick();
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary-pod');
});
});
diff --git a/spec/frontend/monitoring/components/variables_section_spec.js b/spec/frontend/monitoring/components/variables_section_spec.js
index 6157de0dafe..64b93bd3027 100644
--- a/spec/frontend/monitoring/components/variables_section_spec.js
+++ b/spec/frontend/monitoring/components/variables_section_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
+import { nextTick } from 'vue';
import { updateHistory, mergeUrlParams } from '~/lib/utils/url_utility';
import DropdownField from '~/monitoring/components/variables/dropdown_field.vue';
import TextField from '~/monitoring/components/variables/text_field.vue';
@@ -40,11 +41,11 @@ describe('Metrics dashboard/variables section component', () => {
});
describe('when variables are set', () => {
- beforeEach(() => {
+ beforeEach(async () => {
store.state.monitoringDashboard.variables = storeVariables;
createShallowWrapper();
- return wrapper.vm.$nextTick;
+ await nextTick();
});
it('shows the variables section', () => {
@@ -83,34 +84,32 @@ describe('Metrics dashboard/variables section component', () => {
createShallowWrapper();
});
- it('merges the url params and refreshes the dashboard when a text-based variables inputs are updated', () => {
+ it('merges the url params and refreshes the dashboard when a text-based variables inputs are updated', async () => {
const firstInput = findTextInputs().at(0);
firstInput.vm.$emit('input', 'test');
- return wrapper.vm.$nextTick(() => {
- expect(updateVariablesAndFetchData).toHaveBeenCalled();
- expect(mergeUrlParams).toHaveBeenCalledWith(
- convertVariablesForURL(storeVariables),
- window.location.href,
- );
- expect(updateHistory).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(updateVariablesAndFetchData).toHaveBeenCalled();
+ expect(mergeUrlParams).toHaveBeenCalledWith(
+ convertVariablesForURL(storeVariables),
+ window.location.href,
+ );
+ expect(updateHistory).toHaveBeenCalled();
});
- it('merges the url params and refreshes the dashboard when a custom-based variables inputs are updated', () => {
+ it('merges the url params and refreshes the dashboard when a custom-based variables inputs are updated', async () => {
const firstInput = findCustomInputs().at(0);
firstInput.vm.$emit('input', 'test');
- return wrapper.vm.$nextTick(() => {
- expect(updateVariablesAndFetchData).toHaveBeenCalled();
- expect(mergeUrlParams).toHaveBeenCalledWith(
- convertVariablesForURL(storeVariables),
- window.location.href,
- );
- expect(updateHistory).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(updateVariablesAndFetchData).toHaveBeenCalled();
+ expect(mergeUrlParams).toHaveBeenCalledWith(
+ convertVariablesForURL(storeVariables),
+ window.location.href,
+ );
+ expect(updateHistory).toHaveBeenCalled();
});
it('does not merge the url params and refreshes the dashboard if the value entered is not different that is what currently stored', () => {
diff --git a/spec/frontend/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js
index b027d60f61e..7758dd351b7 100644
--- a/spec/frontend/monitoring/router_spec.js
+++ b/spec/frontend/monitoring/router_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import VueRouter from 'vue-router';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardPage from '~/monitoring/pages/dashboard_page.vue';
@@ -25,8 +26,7 @@ describe('Monitoring router', () => {
let store;
const createWrapper = (basePath, routeArg) => {
- const localVue = createLocalVue();
- localVue.use(VueRouter);
+ Vue.use(VueRouter);
router = createRouter(basePath);
if (routeArg !== undefined) {
@@ -34,7 +34,6 @@ describe('Monitoring router', () => {
}
return mount(MockApp, {
- localVue,
store,
router,
});
diff --git a/spec/frontend/mr_popover/mr_popover_spec.js b/spec/frontend/mr_popover/mr_popover_spec.js
index 36ad82e93a5..23f97073e9e 100644
--- a/spec/frontend/mr_popover/mr_popover_spec.js
+++ b/spec/frontend/mr_popover/mr_popover_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import MRPopover from '~/mr_popover/components/mr_popover.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -25,16 +26,15 @@ describe('MR Popover', () => {
});
});
- it('shows skeleton-loader while apollo is loading', () => {
+ it('shows skeleton-loader while apollo is loading', async () => {
wrapper.vm.$apollo.queries.mergeRequest.loading = true;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
describe('loaded state', () => {
- it('matches the snapshot', () => {
+ it('matches the snapshot', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -51,12 +51,11 @@ describe('MR Popover', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('does not show CI Icon if there is no pipeline data', () => {
+ it('does not show CI Icon if there is no pipeline data', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -69,15 +68,13 @@ describe('MR Popover', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(CiIcon).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(CiIcon).exists()).toBe(false);
});
- it('falls back to cached MR title when request fails', () => {
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.text()).toContain('MR Title');
- });
+ it('falls back to cached MR title when request fails', async () => {
+ await nextTick();
+ expect(wrapper.text()).toContain('MR Title');
});
});
});
diff --git a/spec/frontend/nav/components/responsive_app_spec.js b/spec/frontend/nav/components/responsive_app_spec.js
index 4af8c6020bc..76b8ebdc92f 100644
--- a/spec/frontend/nav/components/responsive_app_spec.js
+++ b/spec/frontend/nav/components/responsive_app_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ResponsiveApp from '~/nav/components/responsive_app.vue';
import ResponsiveHeader from '~/nav/components/responsive_header.vue';
import ResponsiveHome from '~/nav/components/responsive_home.vue';
@@ -62,7 +63,7 @@ describe('~/nav/components/responsive_app.vue', () => {
wrapper.vm.$root.$emit(evt);
- await wrapper.vm.$nextTick();
+ await nextTick();
}, Promise.resolve());
expect(hasMobileOverlayVisible()).toBe(expectation);
@@ -97,7 +98,7 @@ describe('~/nav/components/responsive_app.vue', () => {
findHome().vm.$emit('menu-item-click', { view });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows header', () => {
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 71154e18915..a7430d8c73f 100644
--- a/spec/frontend/nav/components/top_nav_menu_item_spec.js
+++ b/spec/frontend/nav/components/top_nav_menu_item_spec.js
@@ -137,6 +137,7 @@ describe('~/nav/components/top_nav_menu_item.vue', () => {
expect(wrapper.classes()).toStrictEqual([
'top-nav-menu-item',
'gl-display-block',
+ 'gl-pr-3!',
...expectedClasses,
]);
});
diff --git a/spec/frontend/notebook/cells/code_spec.js b/spec/frontend/notebook/cells/code_spec.js
index 669bdc2f89a..9a2db061278 100644
--- a/spec/frontend/notebook/cells/code_spec.js
+++ b/spec/frontend/notebook/cells/code_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import fixture from 'test_fixtures/blob/notebook/basic.json';
import CodeComponent from '~/notebook/cells/code.vue';
@@ -25,12 +25,10 @@ describe('Code component', () => {
};
describe('without output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = setupComponent(json.cells[0]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('does not render output prompt', () => {
@@ -39,12 +37,10 @@ describe('Code component', () => {
});
describe('with output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = setupComponent(json.cells[2]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('does not render output prompt', () => {
@@ -58,12 +54,12 @@ describe('Code component', () => {
describe('with string for output', () => {
// NBFormat Version 4.1 allows outputs.text to be a string
- beforeEach(() => {
+ beforeEach(async () => {
const cell = json.cells[2];
cell.outputs[0].text = cell.outputs[0].text.join('');
vm = setupComponent(cell);
- return vm.$nextTick();
+ await nextTick();
});
it('does not render output prompt', () => {
@@ -76,12 +72,12 @@ describe('Code component', () => {
});
describe('with string for cell.source', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const cell = json.cells[0];
cell.source = cell.source.join('');
vm = setupComponent(cell);
- return vm.$nextTick();
+ await nextTick();
});
it('renders the same input as when cell.source is an array', () => {
diff --git a/spec/frontend/notebook/cells/markdown_spec.js b/spec/frontend/notebook/cells/markdown_spec.js
index 36b1e91f15f..7dc6f90d202 100644
--- a/spec/frontend/notebook/cells/markdown_spec.js
+++ b/spec/frontend/notebook/cells/markdown_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import katex from 'katex';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import markdownTableJson from 'test_fixtures/blob/notebook/markdown-table.json';
import basicJson from 'test_fixtures/blob/notebook/basic.json';
import mathJson from 'test_fixtures/blob/notebook/math.json';
@@ -37,7 +37,7 @@ describe('Markdown component', () => {
let cell;
let json;
- beforeEach(() => {
+ beforeEach(async () => {
json = basicJson;
// eslint-disable-next-line prefer-destructuring
@@ -45,7 +45,7 @@ describe('Markdown component', () => {
vm = buildCellComponent(cell);
- return vm.$nextTick();
+ await nextTick();
});
it('does not render prompt', () => {
@@ -67,7 +67,7 @@ describe('Markdown component', () => {
],
});
- await vm.$nextTick();
+ await nextTick();
expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
});
@@ -77,7 +77,7 @@ describe('Markdown component', () => {
source: ['<a href="test.js" data-remote=true data-type="script" class="xss-link">XSS</a>\n'],
});
- await vm.$nextTick();
+ await nextTick();
expect(findLink().getAttribute('data-remote')).toBe(null);
expect(findLink().getAttribute('data-type')).toBe(null);
});
@@ -99,7 +99,7 @@ describe('Markdown component', () => {
])('%s', async ([testMd, mustContain]) => {
vm = buildMarkdownComponent([testMd], '/raw/');
- await vm.$nextTick();
+ await nextTick();
expect(vm.$el.innerHTML).toContain(mustContain);
});
@@ -110,29 +110,28 @@ describe('Markdown component', () => {
json = markdownTableJson;
});
- it('renders images and text', () => {
+ it('renders images and text', async () => {
vm = buildCellComponent(json.cells[0]);
- return vm.$nextTick().then(() => {
- const images = vm.$el.querySelectorAll('img');
- expect(images.length).toBe(5);
-
- const columns = vm.$el.querySelectorAll('td');
- expect(columns.length).toBe(6);
-
- expect(columns[0].textContent).toEqual('Hello ');
- expect(columns[1].textContent).toEqual('Test ');
- expect(columns[2].textContent).toEqual('World ');
- expect(columns[3].textContent).toEqual('Fake ');
- expect(columns[4].textContent).toEqual('External image: ');
- expect(columns[5].textContent).toEqual('Empty');
-
- expect(columns[0].innerHTML).toContain('<img src="data:image/jpeg;base64');
- expect(columns[1].innerHTML).toContain('<img src="data:image/png;base64');
- expect(columns[2].innerHTML).toContain('<img src="data:image/jpeg;base64');
- expect(columns[3].innerHTML).toContain('<img>');
- expect(columns[4].innerHTML).toContain('<img src="https://www.google.com/');
- });
+ await nextTick();
+ const images = vm.$el.querySelectorAll('img');
+ expect(images.length).toBe(5);
+
+ const columns = vm.$el.querySelectorAll('td');
+ expect(columns.length).toBe(6);
+
+ expect(columns[0].textContent).toEqual('Hello ');
+ expect(columns[1].textContent).toEqual('Test ');
+ expect(columns[2].textContent).toEqual('World ');
+ expect(columns[3].textContent).toEqual('Fake ');
+ expect(columns[4].textContent).toEqual('External image: ');
+ expect(columns[5].textContent).toEqual('Empty');
+
+ expect(columns[0].innerHTML).toContain('<img src="data:image/jpeg;base64');
+ expect(columns[1].innerHTML).toContain('<img src="data:image/png;base64');
+ expect(columns[2].innerHTML).toContain('<img src="data:image/jpeg;base64');
+ expect(columns[3].innerHTML).toContain('<img>');
+ expect(columns[4].innerHTML).toContain('<img src="https://www.google.com/');
});
});
@@ -144,28 +143,28 @@ describe('Markdown component', () => {
it('renders multi-line katex', async () => {
vm = buildCellComponent(json.cells[0]);
- await vm.$nextTick();
+ await nextTick();
expect(vm.$el.querySelector('.katex')).not.toBeNull();
});
it('renders inline katex', async () => {
vm = buildCellComponent(json.cells[1]);
- await vm.$nextTick();
+ await nextTick();
expect(vm.$el.querySelector('p:first-child .katex')).not.toBeNull();
});
it('renders multiple inline katex', async () => {
vm = buildCellComponent(json.cells[1]);
- await vm.$nextTick();
+ await nextTick();
expect(vm.$el.querySelectorAll('p:nth-child(2) .katex')).toHaveLength(4);
});
it('output cell in case of katex error', async () => {
vm = buildMarkdownComponent(['Some invalid $a & b$ inline formula $b & c$\n', '\n']);
- await vm.$nextTick();
+ await nextTick();
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p')).toHaveLength(1);
expect(vm.$el.querySelectorAll('p .katex')).toHaveLength(0);
@@ -177,7 +176,7 @@ describe('Markdown component', () => {
'\n',
]);
- await vm.$nextTick();
+ await nextTick();
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p')).toHaveLength(1);
expect(vm.$el.querySelectorAll('p .katex')).toHaveLength(1);
@@ -186,7 +185,7 @@ describe('Markdown component', () => {
it('renders math formula in list object', async () => {
vm = buildMarkdownComponent(["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n']);
- await vm.$nextTick();
+ await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
@@ -195,7 +194,7 @@ describe('Markdown component', () => {
it("renders math formula with tick ' in it", async () => {
vm = buildMarkdownComponent(["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n']);
- await vm.$nextTick();
+ await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
@@ -204,7 +203,7 @@ describe('Markdown component', () => {
it('renders math formula with less-than-operator < in it', async () => {
vm = buildMarkdownComponent(['- list with inline $a=2$ inline formula $a + b < c$\n', '\n']);
- await vm.$nextTick();
+ await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
@@ -213,7 +212,7 @@ describe('Markdown component', () => {
it('renders math formula with greater-than-operator > in it', async () => {
vm = buildMarkdownComponent(['- list with inline $a=2$ inline formula $a + b > c$\n', '\n']);
- await vm.$nextTick();
+ await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
diff --git a/spec/frontend/notebook/cells/output/index_spec.js b/spec/frontend/notebook/cells/output/index_spec.js
index 7ece73d375c..8e04e4c146c 100644
--- a/spec/frontend/notebook/cells/output/index_spec.js
+++ b/spec/frontend/notebook/cells/output/index_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import json from 'test_fixtures/blob/notebook/basic.json';
import CodeComponent from '~/notebook/cells/output/index.vue';
@@ -18,13 +18,11 @@ describe('Output component', () => {
};
describe('text output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
const textType = json.cells[2];
createComponent(textType.outputs[0]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders as plain text', () => {
@@ -37,13 +35,11 @@ describe('Output component', () => {
});
describe('image output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
const imageType = json.cells[3];
createComponent(imageType.outputs[0]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders as an image', () => {
@@ -86,13 +82,11 @@ describe('Output component', () => {
});
describe('svg output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
const svgType = json.cells[5];
createComponent(svgType.outputs[0]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders as an svg', () => {
@@ -101,13 +95,11 @@ describe('Output component', () => {
});
describe('default to plain text', () => {
- beforeEach((done) => {
+ beforeEach(() => {
const unknownType = json.cells[6];
createComponent(unknownType.outputs[0]);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders as plain text', () => {
@@ -119,16 +111,14 @@ describe('Output component', () => {
expect(vm.$el.querySelector('.prompt span')).not.toBeNull();
});
- it("renders as plain text when doesn't recognise other types", (done) => {
+ it("renders as plain text when doesn't recognise other types", async () => {
const unknownType = json.cells[7];
createComponent(unknownType.outputs[0]);
- setImmediate(() => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- expect(vm.$el.textContent.trim()).toContain('testing');
+ await nextTick();
- done();
- });
+ expect(vm.$el.querySelector('pre')).not.toBeNull();
+ expect(vm.$el.textContent.trim()).toContain('testing');
});
});
});
diff --git a/spec/frontend/notebook/cells/prompt_spec.js b/spec/frontend/notebook/cells/prompt_spec.js
index 8cdcd1f84de..89b2d7b2b90 100644
--- a/spec/frontend/notebook/cells/prompt_spec.js
+++ b/spec/frontend/notebook/cells/prompt_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import PromptComponent from '~/notebook/cells/prompt.vue';
const Component = Vue.extend(PromptComponent);
@@ -7,7 +7,7 @@ describe('Prompt component', () => {
let vm;
describe('input', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = new Component({
propsData: {
type: 'In',
@@ -16,9 +16,7 @@ describe('Prompt component', () => {
});
vm.$mount();
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders in label', () => {
@@ -31,7 +29,7 @@ describe('Prompt component', () => {
});
describe('output', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = new Component({
propsData: {
type: 'Out',
@@ -40,9 +38,7 @@ describe('Prompt component', () => {
});
vm.$mount();
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders in label', () => {
diff --git a/spec/frontend/notebook/index_spec.js b/spec/frontend/notebook/index_spec.js
index cd531d628b3..475c41a72f6 100644
--- a/spec/frontend/notebook/index_spec.js
+++ b/spec/frontend/notebook/index_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import json from 'test_fixtures/blob/notebook/basic.json';
import jsonWithWorksheet from 'test_fixtures/blob/notebook/worksheets.json';
import Notebook from '~/notebook/index.vue';
@@ -17,12 +17,10 @@ describe('Notebook component', () => {
}
describe('without JSON', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = buildComponent({});
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('does not render', () => {
@@ -31,12 +29,10 @@ describe('Notebook component', () => {
});
describe('with JSON', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = buildComponent(json);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders cells', () => {
@@ -57,12 +53,10 @@ describe('Notebook component', () => {
});
describe('with worksheets', () => {
- beforeEach((done) => {
+ beforeEach(() => {
vm = buildComponent(jsonWithWorksheet);
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
it('renders cells', () => {
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index 16dbf60cef4..a605edc4357 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -20,7 +20,6 @@ import { loggedOutnoteableData, notesDataMock, userDataMock, noteableDataMock }
jest.mock('autosize');
jest.mock('~/commons/nav/user_merge_requests');
jest.mock('~/flash');
-jest.mock('~/gl_form');
Vue.use(Vuex);
@@ -466,8 +465,8 @@ describe('issue_comment_form component', () => {
await findCloseReopenButton().trigger('click');
- await wrapper.vm.$nextTick;
- await wrapper.vm.$nextTick;
+ await nextTick;
+ await nextTick;
expect(createFlash).toHaveBeenCalledWith({
message: `Something went wrong while closing the ${type}. Please try again later.`,
@@ -502,8 +501,8 @@ describe('issue_comment_form component', () => {
await findCloseReopenButton().trigger('click');
- await wrapper.vm.$nextTick;
- await wrapper.vm.$nextTick;
+ await nextTick;
+ await nextTick;
expect(createFlash).toHaveBeenCalledWith({
message: `Something went wrong while reopening the ${type}. Please try again later.`,
@@ -521,7 +520,7 @@ describe('issue_comment_form component', () => {
await findCloseReopenButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(refreshUserMergeRequestCounts).toHaveBeenCalled();
});
@@ -581,7 +580,7 @@ describe('issue_comment_form component', () => {
// check checkbox
checkbox.element.checked = shouldCheckboxBeChecked;
checkbox.trigger('change');
- await wrapper.vm.$nextTick();
+ await nextTick();
// submit comment
findCommentButton().trigger('click');
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index fa34a5e8d39..9f94dd693cb 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue';
import createStore from '~/notes/stores';
@@ -24,16 +25,15 @@ describe('diff_discussion_header component', () => {
wrapper.destroy();
});
- it('should render user avatar', () => {
+ it('should render user avatar', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
wrapper.setProps({ discussion });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.user-avatar-link').exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find('.user-avatar-link').exists()).toBe(true);
});
describe('action text', () => {
@@ -41,7 +41,7 @@ describe('diff_discussion_header component', () => {
const truncatedCommitId = commitId.substr(0, 8);
let commitElement;
- beforeEach((done) => {
+ beforeEach(async () => {
store.state.diffs = {
projectPath: 'something',
};
@@ -58,41 +58,30 @@ describe('diff_discussion_header component', () => {
},
});
- wrapper.vm
- .$nextTick()
- .then(() => {
- commitElement = wrapper.find('.commit-sha');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ commitElement = wrapper.find('.commit-sha');
});
describe('for diff threads without a commit id', () => {
- it('should show started a thread on the diff text', (done) => {
+ it('should show started a thread on the diff text', async () => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.text()).toContain('started a thread on the diff');
-
- done();
- });
+ await nextTick();
+ expect(wrapper.text()).toContain('started a thread on the diff');
});
- it('should show thread on older version text', (done) => {
+ it('should show thread on older version text', async () => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
active: false,
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.text()).toContain('started a thread on an old version of the diff');
-
- done();
- });
+ await nextTick();
+ expect(wrapper.text()).toContain('started a thread on an old version of the diff');
});
});
@@ -105,31 +94,25 @@ describe('diff_discussion_header component', () => {
});
describe('for diff thread with a commit id', () => {
- it('should display started thread on commit header', (done) => {
+ it('should display started thread on commit header', async () => {
wrapper.vm.discussion.for_commit = false;
- wrapper.vm.$nextTick(() => {
- expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`);
-
- expect(commitElement).not.toBe(null);
+ await nextTick();
+ expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`);
- done();
- });
+ expect(commitElement).not.toBe(null);
});
- it('should display outdated change on commit header', (done) => {
+ it('should display outdated change on commit header', async () => {
wrapper.vm.discussion.for_commit = false;
wrapper.vm.discussion.active = false;
- wrapper.vm.$nextTick(() => {
- expect(wrapper.text()).toContain(
- `started a thread on an outdated change in commit ${truncatedCommitId}`,
- );
+ await nextTick();
+ expect(wrapper.text()).toContain(
+ `started a thread on an outdated change in commit ${truncatedCommitId}`,
+ );
- expect(commitElement).not.toBe(null);
-
- done();
- });
+ expect(commitElement).not.toBe(null);
});
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index c454d502beb..a856d002d2e 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
import notesModule from '~/notes/stores/modules';
@@ -10,9 +11,8 @@ describe('DiscussionCounter component', () => {
let store;
let wrapper;
let setExpandDiscussionsFn;
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
beforeEach(() => {
window.mrTabs = {};
@@ -45,7 +45,7 @@ describe('DiscussionCounter component', () => {
describe('has no discussions', () => {
it('does not render', () => {
- wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ wrapper = shallowMount(DiscussionCounter, { store });
expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(false);
});
@@ -55,7 +55,7 @@ describe('DiscussionCounter component', () => {
it('does not render', () => {
store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [{ ...discussionMock, resolvable: false }]);
store.dispatch('updateResolvableDiscussionsCounts');
- wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ wrapper = shallowMount(DiscussionCounter, { store });
expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(false);
});
@@ -75,7 +75,7 @@ describe('DiscussionCounter component', () => {
it('renders', () => {
updateStore();
- wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ wrapper = shallowMount(DiscussionCounter, { store });
expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(true);
});
@@ -86,7 +86,7 @@ describe('DiscussionCounter component', () => {
${'allResolved'} | ${true} | ${true} | ${1}
`('renders correctly if $title', ({ resolved, isActive, groupLength }) => {
updateStore({ resolvable: true, resolved });
- wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ wrapper = shallowMount(DiscussionCounter, { store });
expect(wrapper.find(`.is-active`).exists()).toBe(isActive);
expect(wrapper.findAll(GlButton)).toHaveLength(groupLength);
@@ -99,7 +99,7 @@ describe('DiscussionCounter component', () => {
const discussion = { ...discussionMock, expanded };
store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [discussion]);
store.dispatch('updateResolvableDiscussionsCounts');
- wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ wrapper = shallowMount(DiscussionCounter, { store });
toggleAllButton = wrapper.find('.toggle-all-discussions-btn');
};
@@ -113,7 +113,7 @@ describe('DiscussionCounter component', () => {
expect(setExpandDiscussionsFn).toHaveBeenCalledTimes(1);
});
- it('collapses all discussions if expanded', () => {
+ it('collapses all discussions if expanded', async () => {
updateStoreWithExpanded(true);
expect(wrapper.vm.allExpanded).toBe(true);
@@ -121,13 +121,12 @@ describe('DiscussionCounter component', () => {
toggleAllButton.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.allExpanded).toBe(false);
- expect(toggleAllButton.props('icon')).toBe('angle-down');
- });
+ await nextTick();
+ expect(wrapper.vm.allExpanded).toBe(false);
+ expect(toggleAllButton.props('icon')).toBe('angle-down');
});
- it('expands all discussions if collapsed', () => {
+ it('expands all discussions if collapsed', async () => {
updateStoreWithExpanded(false);
expect(wrapper.vm.allExpanded).toBe(false);
@@ -135,10 +134,9 @@ describe('DiscussionCounter component', () => {
toggleAllButton.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.allExpanded).toBe(true);
- expect(toggleAllButton.props('icon')).toBe('angle-up');
- });
+ await nextTick();
+ expect(wrapper.vm.allExpanded).toBe(true);
+ expect(toggleAllButton.props('icon')).toBe('angle-up');
});
});
});
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index 17998dfc9d5..27206bddbfc 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
@@ -12,9 +13,7 @@ import notesModule from '~/notes/stores/modules';
import { discussionFiltersMock, discussionMock } from '../mock_data';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(Vuex);
const DISCUSSION_PATH = `${TEST_HOST}/example`;
@@ -58,7 +57,6 @@ describe('DiscussionFilter component', () => {
filters: discussionFiltersMock,
selectedValue: DISCUSSION_FILTERS_DEFAULT_VALUE,
},
- localVue,
});
};
@@ -153,13 +151,11 @@ describe('DiscussionFilter component', () => {
window.mrTabs = undefined;
});
- it('only renders when discussion tab is active', (done) => {
+ it('only renders when discussion tab is active', async () => {
eventHub.$emit('MergeRequestTabChange', 'commit');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.html()).toBe('');
- done();
- });
+ await nextTick();
+ expect(wrapper.html()).toBe('');
});
});
@@ -168,58 +164,48 @@ describe('DiscussionFilter component', () => {
window.location.hash = '';
});
- it('updates the filter when the URL links to a note', (done) => {
+ it('updates the filter when the URL links to a note', async () => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
wrapper.vm.handleLocationHash();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
});
- it('does not update the filter when the current filter is "Show all activity"', (done) => {
+ it('does not update the filter when the current filter is "Show all activity"', async () => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.handleLocationHash();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
});
- it('only updates filter when the URL links to a note', (done) => {
+ it('only updates filter when the URL links to a note', async () => {
window.location.hash = `testing123`;
wrapper.vm.handleLocationHash();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
});
- it('fetches discussions when there is a hash', (done) => {
+ it('fetches discussions when there is a hash', async () => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
wrapper.vm.handleLocationHash();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.selectFilter).toHaveBeenCalled();
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.selectFilter).toHaveBeenCalled();
});
- it('does not fetch discussions when there is no hash', (done) => {
+ it('does not fetch discussions when there is no hash', async () => {
window.location.hash = '';
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
wrapper.vm.handleLocationHash();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.selectFilter).not.toHaveBeenCalled();
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.selectFilter).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/notes/components/discussion_navigator_spec.js b/spec/frontend/notes/components/discussion_navigator_spec.js
index e430e18b76a..77ae7b2c3b5 100644
--- a/spec/frontend/notes/components/discussion_navigator_spec.js
+++ b/spec/frontend/notes/components/discussion_navigator_spec.js
@@ -1,6 +1,6 @@
/* global Mousetrap */
import 'mousetrap';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import {
keysFor,
@@ -11,8 +11,6 @@ import DiscussionNavigator from '~/notes/components/discussion_navigator.vue';
import eventHub from '~/notes/event_hub';
describe('notes/components/discussion_navigator', () => {
- const localVue = createLocalVue();
-
let wrapper;
let jumpToNextDiscussion;
let jumpToPreviousDiscussion;
@@ -20,12 +18,12 @@ describe('notes/components/discussion_navigator', () => {
const createComponent = () => {
wrapper = shallowMount(DiscussionNavigator, {
mixins: [
- localVue.extend({
+ {
methods: {
jumpToNextDiscussion,
jumpToPreviousDiscussion,
},
- }),
+ },
],
});
};
@@ -48,7 +46,7 @@ describe('notes/components/discussion_navigator', () => {
beforeEach(() => {
onSpy = jest.spyOn(eventHub, '$on');
- vm = new (Vue.extend(DiscussionNavigator))();
+ vm = new Vue(DiscussionNavigator);
});
it('listens for jumpToFirstUnresolvedDiscussion events', () => {
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 59ac75f00e6..3506b6ac9f3 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,6 +1,7 @@
import { getByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import '~/behaviors/markdown/render_gfm';
+import { nextTick } from 'vue';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableNote from '~/notes/components/noteable_note.vue';
import { SYSTEM_NOTE } from '~/notes/constants';
@@ -135,28 +136,25 @@ describe('DiscussionNotes', () => {
createComponent({ shouldGroupReplies: true, isExpanded: true });
});
- it('emits deleteNote when first note emits handleDeleteNote', () => {
+ it('emits deleteNote when first note emits handleDeleteNote', async () => {
findNoteAtIndex(0).vm.$emit('handleDeleteNote');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().deleteNote).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().deleteNote).toBeTruthy();
});
- it('emits startReplying when first note emits startReplying', () => {
+ it('emits startReplying when first note emits startReplying', async () => {
findNoteAtIndex(0).vm.$emit('startReplying');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().startReplying).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().startReplying).toBeTruthy();
});
- it('emits deleteNote when second note emits handleDeleteNote', () => {
+ it('emits deleteNote when second note emits handleDeleteNote', async () => {
findNoteAtIndex(1).vm.$emit('handleDeleteNote');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().deleteNote).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().deleteNote).toBeTruthy();
});
});
@@ -167,12 +165,11 @@ describe('DiscussionNotes', () => {
note = wrapper.find('.notes > *');
});
- it('emits deleteNote when first note emits handleDeleteNote', () => {
+ it('emits deleteNote when first note emits handleDeleteNote', async () => {
note.vm.$emit('handleDeleteNote');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().deleteNote).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().deleteNote).toBeTruthy();
});
});
});
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index 64e061830b9..ca0c0ca6de8 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import resolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
const buttonTitle = 'Resolve discussion';
@@ -26,15 +27,14 @@ describe('resolveDiscussionButton', () => {
wrapper.destroy();
});
- it('should emit a onClick event on button click', () => {
+ it('should emit a onClick event on button click', async () => {
const button = wrapper.find(GlButton);
button.vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted()).toEqual({
- onClick: [[]],
- });
+ await nextTick();
+ expect(wrapper.emitted()).toEqual({
+ onClick: [[]],
});
});
@@ -57,7 +57,7 @@ describe('resolveDiscussionButton', () => {
expect(button.props('loading')).toEqual(true);
});
- it('should only show a loading spinner while resolving', () => {
+ it('should only show a loading spinner while resolving', async () => {
factory({
propsData: {
isResolving: false,
@@ -67,8 +67,7 @@ describe('resolveDiscussionButton', () => {
const button = wrapper.find(GlButton);
- wrapper.vm.$nextTick(() => {
- expect(button.props('loading')).toEqual(false);
- });
+ await nextTick();
+ expect(button.props('loading')).toEqual(false);
});
});
diff --git a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
index 4348445f7ca..5bc6282db03 100644
--- a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
@@ -1,17 +1,14 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
-const localVue = createLocalVue();
-
describe('ResolveWithIssueButton', () => {
let wrapper;
const url = `${TEST_HOST}/hello-world/`;
beforeEach(() => {
wrapper = shallowMount(ResolveWithIssueButton, {
- localVue,
propsData: {
url,
},
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index ecce854b00a..780f24b3aa8 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -1,6 +1,6 @@
-import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { mount, createWrapper } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
@@ -20,11 +20,9 @@ describe('noteActions', () => {
const findUserAccessRoleBadgeText = (idx) => findUserAccessRoleBadge(idx).text().trim();
const mountNoteActions = (propsData, computed) => {
- const localVue = createLocalVue();
- return mount(localVue.extend(noteActions), {
+ return mount(noteActions, {
store,
propsData,
- localVue,
computed,
});
};
@@ -78,15 +76,14 @@ describe('noteActions', () => {
expect(findUserAccessRoleBadgeText(1)).toBe(props.accessLevel);
});
- it('should render contributor badge', () => {
+ it('should render contributor badge', async () => {
wrapper.setProps({
accessLevel: null,
isContributor: true,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findUserAccessRoleBadgeText(1)).toBe('Contributor');
- });
+ await nextTick();
+ expect(findUserAccessRoleBadgeText(1)).toBe('Contributor');
});
it('should render emoji link', () => {
@@ -107,7 +104,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(true);
});
- it('should not show copy link action when `noteUrl` prop is empty', (done) => {
+ it('should not show copy link action when `noteUrl` prop is empty', async () => {
wrapper.setProps({
...props,
author: {
@@ -121,30 +118,23 @@ describe('noteActions', () => {
noteUrl: '',
});
- Vue.nextTick()
- .then(() => {
- expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(false);
});
it('should be possible to delete comment', () => {
expect(wrapper.find('.js-note-delete').exists()).toBe(true);
});
- it('closes tooltip when dropdown opens', (done) => {
+ it('closes tooltip when dropdown opens', async () => {
wrapper.find('.more-actions-toggle').trigger('click');
const rootWrapper = createWrapper(wrapper.vm.$root);
- Vue.nextTick()
- .then(() => {
- const emitted = Object.keys(rootWrapper.emitted());
-
- expect(emitted).toEqual([BV_HIDE_TOOLTIP]);
- done();
- })
- .catch(done.fail);
+
+ await nextTick();
+ const emitted = Object.keys(rootWrapper.emitted());
+
+ expect(emitted).toEqual([BV_HIDE_TOOLTIP]);
});
it('should not be possible to assign or unassign the comment author in a merge request', () => {
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index 4e345c9ac8d..63f3cd865d5 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { suggestionCommitMessage } from '~/diffs/store/getters';
@@ -46,9 +46,9 @@ describe('issue_note_body component', () => {
});
describe('isEditing', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
vm.isEditing = true;
- Vue.nextTick(done);
+ await nextTick();
});
it('renders edit form', () => {
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index d3b5ab02f24..3e80b24f128 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -45,6 +45,8 @@ describe('issue_note_form component', () => {
noteBody: 'Magni suscipit eius consectetur enim et ex et commodi.',
noteId: '545',
};
+
+ gon.features = { markdownContinueLists: true };
});
afterEach(() => {
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index 774d5aaa7d3..8d82cf3d2c7 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -1,13 +1,12 @@
import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import NoteHeader from '~/notes/components/note_header.vue';
import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const actions = {
setTargetNoteHash: jest.fn(),
@@ -42,7 +41,6 @@ describe('NoteHeader component', () => {
const createComponent = (props) => {
wrapper = shallowMount(NoteHeader, {
- localVue,
store: new Vuex.Store({
actions,
}),
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 038aff3be04..c7115a5911b 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
@@ -107,11 +107,11 @@ describe('issue_note', () => {
line,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findMultilineComment().text()).toBe('Comment on lines 1 to 2');
});
- it('should only render if it has everything it needs', () => {
+ it('should only render if it has everything it needs', async () => {
const position = {
line_range: {
start: {
@@ -140,12 +140,11 @@ describe('issue_note', () => {
line,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findMultilineComment().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findMultilineComment().exists()).toBe(false);
});
- it('should not render if has single line comment', () => {
+ it('should not render if has single line comment', async () => {
const position = {
line_range: {
start: {
@@ -174,9 +173,8 @@ describe('issue_note', () => {
line,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findMultilineComment().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findMultilineComment().exists()).toBe(false);
});
it('should not render if `line_range` is unavailable', () => {
@@ -204,7 +202,7 @@ describe('issue_note', () => {
line,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findComponent(UserAvatarLink).props('imgSize')).toBe(24);
});
@@ -318,13 +316,13 @@ describe('issue_note', () => {
callback: () => {},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
let noteBodyProps = noteBody.props();
expect(noteBodyProps.note.note_html).toBe(`<p>${updatedText}</p>\n`);
noteBody.vm.$emit('cancelForm', {});
- await wrapper.vm.$nextTick();
+ await nextTick();
noteBodyProps = noteBody.props();
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 84d94857fe5..bf36d6cb7a2 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -1,7 +1,7 @@
import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import setWindowLocation from 'helpers/set_window_location_helper';
import { setTestTimeout } from 'helpers/timeout';
import waitForPromises from 'helpers/wait_for_promises';
@@ -294,24 +294,22 @@ describe('note_app', () => {
return waitForDiscussionsRequest();
});
- it('should render markdown docs url', () => {
+ it('should render markdown docs url', async () => {
wrapper.find('.js-note-edit').trigger('click');
const { markdownDocsPath } = mockData.notesDataMock;
- return Vue.nextTick().then(() => {
- expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
- 'Markdown is supported',
- );
- });
+ await nextTick();
+ expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
+ 'Markdown is supported',
+ );
});
- it('should not render quick actions docs url', () => {
+ it('should not render quick actions docs url', async () => {
wrapper.find('.js-note-edit').trigger('click');
const { quickActionsDocsPath } = mockData.notesDataMock;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
});
});
diff --git a/spec/frontend/notes/components/sort_discussion_spec.js b/spec/frontend/notes/components/sort_discussion_spec.js
index 60f03a0f5b5..a279dfd1ef3 100644
--- a/spec/frontend/notes/components/sort_discussion_spec.js
+++ b/spec/frontend/notes/components/sort_discussion_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import SortDiscussion from '~/notes/components/sort_discussion.vue';
import { ASC, DESC } from '~/notes/constants';
@@ -6,8 +7,7 @@ import createStore from '~/notes/stores';
import Tracking from '~/tracking';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Sort Discussion component', () => {
let wrapper;
@@ -17,7 +17,6 @@ describe('Sort Discussion component', () => {
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = shallowMount(SortDiscussion, {
- localVue,
store,
});
};
diff --git a/spec/frontend/notes/components/timeline_toggle_spec.js b/spec/frontend/notes/components/timeline_toggle_spec.js
index 73fb2079e31..84fa3008835 100644
--- a/spec/frontend/notes/components/timeline_toggle_spec.js
+++ b/spec/frontend/notes/components/timeline_toggle_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import TimelineToggle, {
timelineEnabledTooltip,
@@ -10,8 +11,7 @@ import createStore from '~/notes/stores';
import { trackToggleTimelineView } from '~/notes/utils';
import Tracking from '~/tracking';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Timeline toggle', () => {
let wrapper;
@@ -23,7 +23,6 @@ describe('Timeline toggle', () => {
jest.spyOn(Tracking, 'event').mockImplementation();
wrapper = shallowMount(TimelineToggle, {
- localVue,
store,
});
};
@@ -65,7 +64,7 @@ describe('Timeline toggle', () => {
it('should set correct UI state', async () => {
store.state.isTimelineEnabled = true;
findGlButton().vm.$emit('click', mockEvent);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlButton().attributes('title')).toBe(timelineEnabledTooltip);
expect(findGlButton().attributes('selected')).toBe('true');
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
@@ -73,7 +72,7 @@ describe('Timeline toggle', () => {
it('should track Snowplow event', async () => {
store.state.isTimelineEnabled = true;
- await wrapper.vm.$nextTick();
+ await nextTick();
findGlButton().trigger('click');
@@ -98,7 +97,7 @@ describe('Timeline toggle', () => {
it('should set correct UI state', async () => {
store.state.isTimelineEnabled = false;
findGlButton().vm.$emit('click', mockEvent);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlButton().attributes('title')).toBe(timelineDisabledTooltip);
expect(findGlButton().attributes('selected')).toBe(undefined);
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
@@ -106,7 +105,7 @@ describe('Timeline toggle', () => {
it('should track Snowplow event', async () => {
store.state.isTimelineEnabled = false;
- await wrapper.vm.$nextTick();
+ await nextTick();
findGlButton().trigger('click');
diff --git a/spec/frontend/notes/deprecated_notes_spec.js b/spec/frontend/notes/deprecated_notes_spec.js
index 34623f8aa13..7c52920da90 100644
--- a/spec/frontend/notes/deprecated_notes_spec.js
+++ b/spec/frontend/notes/deprecated_notes_spec.js
@@ -5,6 +5,7 @@ import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { createSpyObj } from 'helpers/jest_helpers';
import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
import { setTestTimeoutOnce } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -549,15 +550,14 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
});
- it('should remove placeholder note when new comment is done posting', (done) => {
+ it('should remove placeholder note when new comment is done posting', async () => {
mockNotesPost();
$('.js-comment-button').click();
- setImmediate(() => {
- expect($notesContainer.find('.note.being-posted').length).toEqual(0);
- done();
- });
+ await waitForPromises();
+
+ expect($notesContainer.find('.note.being-posted').length).toEqual(0);
});
describe('postComment', () => {
@@ -584,40 +584,37 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
});
});
- it('should show actual note element when new comment is done posting', (done) => {
+ it('should show actual note element when new comment is done posting', async () => {
mockNotesPost();
$('.js-comment-button').click();
- setImmediate(() => {
- expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
- done();
- });
+ await waitForPromises();
+
+ expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
});
- it('should reset Form when new comment is done posting', (done) => {
+ it('should reset Form when new comment is done posting', async () => {
mockNotesPost();
$('.js-comment-button').click();
- setImmediate(() => {
- expect($form.find('textarea.js-note-text').val()).toEqual('');
- done();
- });
+ await waitForPromises();
+
+ expect($form.find('textarea.js-note-text').val()).toEqual('');
});
- it('should show flash error message when new comment failed to be posted', (done) => {
+ it('should show flash error message when new comment failed to be posted', async () => {
mockNotesPostError();
jest.spyOn(notes, 'addFlash');
$('.js-comment-button').click();
- setImmediate(() => {
- expect(notes.addFlash).toHaveBeenCalled();
- // JSDom doesn't support the :visible selector yet
- expect(notes.flashContainer.style.display).not.toBe('none');
- done();
- });
+ await waitForPromises();
+
+ expect(notes.addFlash).toHaveBeenCalled();
+ // JSDom doesn't support the :visible selector yet
+ expect(notes.flashContainer.style.display).not.toBe('none');
});
});
@@ -657,16 +654,15 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should remove quick action placeholder when comment with quick actions is done posting', (done) => {
+ it('should remove quick action placeholder when comment with quick actions is done posting', async () => {
jest.spyOn(gl.awardsHandler, 'addAwardToEmojiBar');
$('.js-comment-button').click();
expect($notesContainer.find('.note.being-posted').length).toEqual(1); // Placeholder shown
- setImmediate(() => {
- expect($notesContainer.find('.note.being-posted').length).toEqual(0); // Placeholder removed
- done();
- });
+ await waitForPromises();
+
+ expect($notesContainer.find('.note.being-posted').length).toEqual(0); // Placeholder removed
});
});
@@ -692,16 +688,15 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should show message placeholder including lines starting with slash', (done) => {
+ it('should show message placeholder including lines starting with slash', async () => {
$('.js-comment-button').click();
expect($notesContainer.find('.note.being-posted').length).toEqual(1); // Placeholder shown
expect($notesContainer.find('.note-body p').text()).toEqual(sampleComment); // No quick action processing
- setImmediate(() => {
- expect($notesContainer.find('.note.being-posted').length).toEqual(0); // Placeholder removed
- done();
- });
+ await waitForPromises();
+
+ expect($notesContainer.find('.note.being-posted').length).toEqual(0); // Placeholder removed
});
});
@@ -730,23 +725,21 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
$form.find('textarea.js-note-text').html(sampleComment);
});
- it('should not render a script tag', (done) => {
+ it('should not render a script tag', async () => {
$('.js-comment-button').click();
- setImmediate(() => {
- const $noteEl = $notesContainer.find(`#note_${note.id}`);
- $noteEl.find('.js-note-edit').click();
- $noteEl.find('textarea.js-note-text').html(updatedComment);
- $noteEl.find('.js-comment-save-button').click();
+ await waitForPromises();
- const $updatedNoteEl = $notesContainer
- .find(`#note_${note.id}`)
- .find('.js-task-list-container');
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').html(updatedComment);
+ $noteEl.find('.js-comment-save-button').click();
- expect($updatedNoteEl.find('.note-text').text().trim()).toEqual('');
+ const $updatedNoteEl = $notesContainer
+ .find(`#note_${note.id}`)
+ .find('.js-task-list-container');
- done();
- });
+ expect($updatedNoteEl.find('.note-text').text().trim()).toEqual('');
});
});
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 26a072b82f8..aba80789a01 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { setHTMLFixture } from 'helpers/fixtures';
import createEventHub from '~/helpers/event_hub_factory';
@@ -27,8 +27,7 @@ const createComponent = () => ({
});
describe('Discussion navigation mixin', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
let wrapper;
let store;
@@ -65,7 +64,7 @@ describe('Discussion navigation mixin', () => {
});
store.state.notes.discussions = createDiscussions();
- wrapper = shallowMount(createComponent(), { store, localVue });
+ wrapper = shallowMount(createComponent(), { store });
});
afterEach(() => {
@@ -94,14 +93,13 @@ describe('Discussion navigation mixin', () => {
expect(store.dispatch).toHaveBeenCalledWith('setCurrentDiscussionId', null);
});
- it('triggers the jumpToNextDiscussion action when the previous store action succeeds', () => {
+ it('triggers the jumpToNextDiscussion action when the previous store action succeeds', async () => {
store.dispatch.mockResolvedValue();
vm.jumpToFirstUnresolvedDiscussion();
- return vm.$nextTick().then(() => {
- expect(vm.jumpToNextDiscussion).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(vm.jumpToNextDiscussion).toHaveBeenCalled();
});
});
@@ -127,11 +125,11 @@ describe('Discussion navigation mixin', () => {
});
describe('on `show` active tab', () => {
- beforeEach(() => {
+ beforeEach(async () => {
window.mrTabs.currentAction = 'show';
wrapper.vm[fn](...args);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets current discussion', () => {
@@ -145,17 +143,17 @@ describe('Discussion navigation mixin', () => {
it('scrolls to element', () => {
expect(utils.scrollToElement).toHaveBeenCalledWith(
findDiscussion('div.discussion', expected),
- { behavior: 'smooth' },
+ { behavior: 'auto' },
);
});
});
describe('on `diffs` active tab', () => {
- beforeEach(() => {
+ beforeEach(async () => {
window.mrTabs.currentAction = 'diffs';
wrapper.vm[fn](...args);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets current discussion', () => {
@@ -173,17 +171,17 @@ describe('Discussion navigation mixin', () => {
expect(utils.scrollToElementWithContext).toHaveBeenCalledWith(
findDiscussion('ul.notes', expected),
- { behavior: 'smooth' },
+ { behavior: 'auto' },
);
});
});
describe('on `other` active tab', () => {
- beforeEach(() => {
+ beforeEach(async () => {
window.mrTabs.currentAction = 'other';
wrapper.vm[fn](...args);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets current discussion', () => {
@@ -214,21 +212,15 @@ describe('Discussion navigation mixin', () => {
it('scrolls to discussion', () => {
expect(utils.scrollToElement).toHaveBeenCalledWith(
findDiscussion('div.discussion', expected),
- { behavior: 'smooth' },
+ { behavior: 'auto' },
);
});
});
});
});
- describe.each`
- diffsVirtualScrolling
- ${false}
- ${true}
- `('virtual scrolling feature is $diffsVirtualScrolling', ({ diffsVirtualScrolling }) => {
+ describe('virtual scrolling feature', () => {
beforeEach(() => {
- window.gon = { features: { diffsVirtualScrolling } };
-
jest.spyOn(store, 'dispatch');
store.state.notes.currentDiscussionId = 'a';
@@ -240,22 +232,22 @@ describe('Discussion navigation mixin', () => {
window.location.hash = '';
});
- it('resets location hash if diffsVirtualScrolling flag is true', async () => {
+ it('resets location hash', async () => {
wrapper.vm.jumpToNextDiscussion();
await nextTick();
- expect(window.location.hash).toBe(diffsVirtualScrolling ? '' : '#test');
+ expect(window.location.hash).toBe('');
});
it.each`
- tabValue | hashValue
- ${'diffs'} | ${false}
- ${'show'} | ${!diffsVirtualScrolling}
- ${'other'} | ${!diffsVirtualScrolling}
+ tabValue
+ ${'diffs'}
+ ${'show'}
+ ${'other'}
`(
'calls scrollToFile with setHash as $hashValue when the tab is $tabValue',
- async ({ hashValue, tabValue }) => {
+ async ({ tabValue }) => {
window.mrTabs.currentAction = tabValue;
wrapper.vm.jumpToNextDiscussion();
@@ -264,7 +256,6 @@ describe('Discussion navigation mixin', () => {
expect(store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', {
path: 'test.js',
- setHash: hashValue,
});
},
);
diff --git a/spec/frontend/notifications/components/custom_notifications_modal_spec.js b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
index 7a036d25559..c5d201c3aec 100644
--- a/spec/frontend/notifications/components/custom_notifications_modal_spec.js
+++ b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
@@ -2,6 +2,7 @@ import { GlSprintf, GlModal, GlFormGroup, GlFormCheckbox, GlLoadingIcon } from '
import { shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import httpStatus from '~/lib/utils/http_status';
@@ -97,7 +98,7 @@ describe('CustomNotificationsModal', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it.each`
@@ -222,7 +223,7 @@ describe('CustomNotificationsModal', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
findCheckboxAt(1).vm.$emit('change', true);
@@ -252,7 +253,7 @@ describe('CustomNotificationsModal', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
findCheckboxAt(1).vm.$emit('change', true);
diff --git a/spec/frontend/notifications/components/notifications_dropdown_spec.js b/spec/frontend/notifications/components/notifications_dropdown_spec.js
index e12251ce6d9..7ca6c2052ae 100644
--- a/spec/frontend/notifications/components/notifications_dropdown_spec.js
+++ b/spec/frontend/notifications/components/notifications_dropdown_spec.js
@@ -195,6 +195,14 @@ describe('NotificationsDropdown', () => {
);
});
});
+
+ it('passes provided `noFlip` value to `GlDropdown`', () => {
+ wrapper = createComponent({
+ noFlip: true,
+ });
+
+ expect(findDropdown().attributes('no-flip')).toBe('true');
+ });
});
describe('when selecting an item', () => {
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index 258c6eae692..c1fa1d24a82 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -181,17 +182,18 @@ describe('operation settings external dashboard component', () => {
expect(submit.text()).toBe('Save Changes');
});
- it('submits form on click', () => {
+ it('submits form on click', async () => {
mountComponent(false);
axios.patch.mockResolvedValue();
findSubmitButton().trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
- return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled());
+ await nextTick();
+ expect(refreshCurrentPage).toHaveBeenCalled();
});
- it('creates flash banner on error', () => {
+ it('creates flash banner on error', async () => {
mountComponent(false);
const message = 'mockErrorMessage';
axios.patch.mockRejectedValue({ response: { data: { message } } });
@@ -199,14 +201,11 @@ describe('operation settings external dashboard component', () => {
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
- return wrapper.vm
- .$nextTick()
- .then(jest.runAllTicks)
- .then(() =>
- expect(createFlash).toHaveBeenCalledWith({
- message: `There was an error saving your changes. ${message}`,
- }),
- );
+ await nextTick();
+ await jest.runAllTicks();
+ expect(createFlash).toHaveBeenCalledWith({
+ message: `There was an error saving your changes. ${message}`,
+ });
});
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
index 5278e730ec9..f4c22d9bfa7 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
@@ -1,6 +1,7 @@
import { GlDropdownItem, GlIcon, GlDropdown } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -54,8 +55,8 @@ describe('Details Header', () => {
const waitForMetadataItems = async () => {
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
- await wrapper.vm.$nextTick();
- await wrapper.vm.$nextTick();
+ await nextTick();
+ await nextTick();
};
const mountComponent = ({
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 0dcf988c814..ef6c4a1fa32 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { GlEmptyState } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -8,7 +8,7 @@ import { stripTypenames } from 'helpers/graphql_helpers';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
-import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
@@ -22,8 +22,6 @@ import {
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
-const localVue = createLocalVue();
-
describe('Tags List', () => {
let wrapper;
let apolloProvider;
@@ -50,13 +48,12 @@ describe('Tags List', () => {
};
const mountComponent = ({ propsData = { isMobile: false, id: 1 } } = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
- localVue,
apolloProvider,
propsData,
stubs: { RegistryList },
@@ -108,6 +105,7 @@ describe('Tags List', () => {
describe('events', () => {
it('prev-page fetch the previous page', async () => {
findRegistryList().vm.$emit('prev-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith({
first: null,
@@ -119,8 +117,9 @@ describe('Tags List', () => {
});
});
- it('next-page fetch the previous page', () => {
+ it('next-page fetch the previous page', async () => {
findRegistryList().vm.$emit('next-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith({
after: tagsPageInfo.endCursor,
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
index 060dc9dc5f3..e5df260a260 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+import component from '~/packages_and_registries/shared/components/tags_loader.vue';
import { GlSkeletonLoader } from '../../stubs';
describe('TagsLoader component', () => {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
index 4039fba869b..7727bf167fe 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
@@ -1,7 +1,8 @@
import { GlDropdown } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
-import QuickstartDropdown from '~/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue';
+import QuickstartDropdown from '~/packages_and_registries/shared/components/cli_commands.vue';
import {
QUICK_START,
LOGIN_COMMAND_LABEL,
@@ -16,28 +17,18 @@ import CodeInstruction from '~/vue_shared/components/registry/code_instruction.v
import { dockerCommands } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('cli_commands', () => {
let wrapper;
- const config = {
- repositoryUrl: 'foo',
- registryHostUrlWithPort: 'bar',
- };
-
const findDropdownButton = () => wrapper.find(GlDropdown);
const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
const mountComponent = () => {
wrapper = mount(QuickstartDropdown, {
- localVue,
- provide() {
- return {
- config,
- ...dockerCommands,
- };
+ propsData: {
+ ...dockerCommands,
},
});
};
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
index 027cdf732bc..d2086943e4f 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
@@ -1,11 +1,11 @@
import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import groupEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue';
import { GlEmptyState } from '../../stubs';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Registry Group Empty state', () => {
let wrapper;
@@ -16,7 +16,6 @@ describe('Registry Group Empty state', () => {
beforeEach(() => {
wrapper = shallowMount(groupEmptyState, {
- localVue,
stubs: {
GlEmptyState,
GlSprintf,
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
index 21748ae2813..8cfa8128021 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
@@ -1,12 +1,12 @@
import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import projectEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue';
import { dockerCommands } from '../../mock_data';
import { GlEmptyState } from '../../stubs';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Registry Project Empty state', () => {
let wrapper;
@@ -21,7 +21,6 @@ describe('Registry Project Empty state', () => {
beforeEach(() => {
wrapper = shallowMount(projectEmptyState, {
- localVue,
stubs: {
GlEmptyState,
GlSprintf,
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
index 92cfeb7633e..c91a9c0f0fb 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
@@ -1,5 +1,6 @@
import { GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue';
import {
CONTAINER_REGISTRY_TITLE,
@@ -21,7 +22,7 @@ describe('registry_header', () => {
const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
- const mountComponent = (propsData, slots) => {
+ const mountComponent = async (propsData, slots) => {
wrapper = shallowMount(Component, {
stubs: {
GlSprintf,
@@ -30,7 +31,7 @@ describe('registry_header', () => {
propsData,
slots,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
afterEach(() => {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index 7992bead60a..c602b37c3b5 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -1,7 +1,8 @@
import { GlKeysetPagination, GlEmptyState } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
+
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
@@ -11,7 +12,7 @@ import DetailsHeader from '~/packages_and_registries/container_registry/explorer
import PartialCleanupAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue';
import StatusAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue';
import TagsList from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
-import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import {
UNFINISHED_STATUS,
@@ -39,8 +40,6 @@ import {
} from '../mock_data';
import { DeleteModal } from '../stubs';
-const localVue = createLocalVue();
-
describe('Details Page', () => {
let wrapper;
let apolloProvider;
@@ -85,7 +84,7 @@ describe('Details Page', () => {
options,
config = defaultConfig,
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [
[getContainerRepositoryDetailsQuery, resolver],
@@ -96,7 +95,6 @@ describe('Details Page', () => {
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
- localVue,
apolloProvider,
stubs: {
DeleteModal,
@@ -522,7 +520,7 @@ describe('Details Page', () => {
findDeleteImage().vm.$emit('start');
- await nextTick();
+ await waitForPromises();
expect(findTagsLoader().exists()).toBe(true);
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
index 051d1e2a169..bd126fe532d 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
@@ -1,6 +1,7 @@
import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -8,7 +9,7 @@ import getContainerRepositoriesQuery from 'shared_queries/container_registry/get
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 '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
-import CliCommands from '~/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue';
+import CliCommands from '~/packages_and_registries/shared/components/cli_commands.vue';
import GroupEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue';
import ImageList from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue';
import ProjectEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue';
@@ -38,8 +39,6 @@ import {
} from '../mock_data';
import { GlModal, GlEmptyState } from '../stubs';
-const localVue = createLocalVue();
-
describe('List Page', () => {
let wrapper;
let apolloProvider;
@@ -75,7 +74,7 @@ describe('List Page', () => {
config = { isGroupPage: false },
query = {},
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [
[getContainerRepositoriesQuery, resolver],
@@ -86,7 +85,6 @@ describe('List Page', () => {
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
- localVue,
apolloProvider,
stubs: {
GlModal,
@@ -307,15 +305,8 @@ describe('List Page', () => {
await selectImageForDeletion();
findDeleteModal().vm.$emit('primary');
- await waitForApolloRequestRender();
-
- expect(wrapper.vm.itemToDelete).toEqual(deletedContainerRepository);
-
- const updatedImage = findImageList()
- .props('images')
- .find((i) => i.id === deletedContainerRepository.id);
- expect(updatedImage.status).toBe(deletedContainerRepository.status);
+ expect(mutationResolver).toHaveBeenCalledWith({ id: deletedContainerRepository.id });
});
it('should show a success alert when delete request is successful', async () => {
@@ -361,7 +352,7 @@ describe('List Page', () => {
findRegistrySearch().vm.$emit('filter:submit');
- await nextTick();
+ await waitForPromises();
};
it('has a search box element', async () => {
@@ -429,7 +420,7 @@ describe('List Page', () => {
await waitForApolloRequestRender();
findImageList().vm.$emit('prev-page');
- await nextTick();
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ before: pageInfo.startCursor }),
@@ -449,7 +440,7 @@ describe('List Page', () => {
await waitForApolloRequestRender();
findImageList().vm.$emit('next-page');
- await nextTick();
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ after: pageInfo.endCursor }),
@@ -471,8 +462,9 @@ describe('List Page', () => {
});
it('contains a description with the path of the item to delete', async () => {
+ await waitForPromises();
findImageList().vm.$emit('delete', { path: 'foo' });
- await nextTick();
+ await waitForPromises();
expect(findDeleteModal().html()).toContain('foo');
});
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index 44a7186904d..79894e25889 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -5,7 +5,7 @@ import {
GlSprintf,
GlEmptyState,
} from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -21,8 +21,6 @@ import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency
import { proxyDetailsQuery, proxyData, pagination, proxyManifests } from './mock_data';
-const localVue = createLocalVue();
-
describe('DependencyProxyApp', () => {
let wrapper;
let apolloProvider;
@@ -35,14 +33,13 @@ describe('DependencyProxyApp', () => {
};
function createComponent({ provide = provideDefaults } = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[getDependencyProxyDetailsQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(DependencyProxyApp, {
- localVue,
apolloProvider,
provide,
stubs: {
@@ -195,8 +192,9 @@ describe('DependencyProxyApp', () => {
});
});
- it('prev-page event on list fetches the previous page', () => {
+ it('prev-page event on list fetches the previous page', async () => {
findManifestList().vm.$emit('prev-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith({
before: pagination().startCursor,
@@ -206,8 +204,9 @@ describe('DependencyProxyApp', () => {
});
});
- it('next-page event on list fetches the next page', () => {
+ it('next-page event on list fetches the next page', async () => {
findManifestList().vm.$emit('next-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith({
after: pagination().endCursor,
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
index 2868af84181..69c78e64e22 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
@@ -1,6 +1,6 @@
import { GlEmptyState } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import stubChildren from 'helpers/stub_children';
@@ -19,8 +19,7 @@ import Tracking from '~/tracking';
import { mavenPackage, mavenFiles, npmPackage } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
useMockLocationHelper();
@@ -60,7 +59,6 @@ describe('PackagesApp', () => {
});
wrapper = mount(PackagesApp, {
- localVue,
store,
stubs: {
...stubChildren(PackagesApp),
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
index 24bd80ba80c..b504f7489ab 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
@@ -1,17 +1,20 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import component from '~/packages_and_registries/infrastructure_registry/details/components/details_title.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { terraformModule, mavenFiles, npmPackage } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('PackageTitle', () => {
let wrapper;
let store;
- function createComponent({ packageFiles = mavenFiles, packageEntity = terraformModule } = {}) {
+ async function createComponent({
+ packageFiles = mavenFiles,
+ packageEntity = terraformModule,
+ } = {}) {
store = new Vuex.Store({
state: {
packageEntity,
@@ -23,13 +26,12 @@ describe('PackageTitle', () => {
});
wrapper = shallowMount(component, {
- localVue,
store,
stubs: {
TitleArea,
},
});
- return wrapper.vm.$nextTick();
+ await nextTick();
}
const findTitleArea = () => wrapper.findComponent(TitleArea);
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
index 6ff4a4c51ef..78c1b840dbc 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/details/components/terraform_installation.vue';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { terraformModule as packageEntity } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('TerraformInstallation', () => {
let wrapper;
@@ -22,7 +22,6 @@ describe('TerraformInstallation', () => {
function createComponent() {
wrapper = shallowMount(TerraformInstallation, {
- localVue,
store,
});
}
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
index 7cdf21dde46..d82af8f9e63 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -3,6 +3,7 @@
exports[`packages_list_app renders 1`] = `
<div>
<infrastructure-title-stub
+ count="1"
helpurl="foo"
/>
@@ -37,8 +38,8 @@ exports[`packages_list_app renders 1`] = `
class="gl-font-size-h-display gl-line-height-36 h4"
>
- There are no packages yet
-
+ There are no packages yet
+
</h1>
<p
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
index b519ab00d06..e5230417c78 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import component from '~/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Infrastructure Search', () => {
let wrapper;
@@ -48,7 +48,6 @@ describe('Infrastructure Search', () => {
createStore(isGroupPage);
wrapper = shallowMount(component, {
- localVue,
store,
stubs: {
UrlSync,
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
index b0e586f189a..72d08d5683b 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
@@ -10,7 +10,9 @@ describe('Infrastructure Title', () => {
const findTitleArea = () => wrapper.find(TitleArea);
const findMetadataItem = () => wrapper.find(MetadataItem);
- const mountComponent = (propsData = { helpUrl: 'foo' }) => {
+ const exampleProps = { helpUrl: 'http://example.gitlab.com/help' };
+
+ const mountComponent = (propsData = exampleProps) => {
wrapper = shallowMount(component, {
store,
propsData,
@@ -26,23 +28,36 @@ describe('Infrastructure Title', () => {
});
describe('title area', () => {
- it('exists', () => {
+ beforeEach(() => {
mountComponent();
+ });
+ it('exists', () => {
expect(findTitleArea().exists()).toBe(true);
});
- it('has the correct props', () => {
- mountComponent();
+ it('has the correct title', () => {
+ expect(findTitleArea().props('title')).toBe('Infrastructure Registry');
+ });
+
+ describe('with no modules', () => {
+ it('has no info message', () => {
+ expect(findTitleArea().props('infoMessages')).toStrictEqual([]);
+ });
+ });
+
+ describe('with at least one module', () => {
+ beforeEach(() => {
+ mountComponent({ ...exampleProps, count: 1 });
+ });
- expect(findTitleArea().props()).toMatchObject({
- title: 'Infrastructure Registry',
- infoMessages: [
+ it('has an info message', () => {
+ expect(findTitleArea().props('infoMessages')).toStrictEqual([
{
text: 'Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}',
- link: 'foo',
+ link: exampleProps.helpUrl,
},
- ],
+ ]);
});
});
});
@@ -51,15 +66,15 @@ describe('Infrastructure Title', () => {
count | exist | text
${null} | ${false} | ${''}
${undefined} | ${false} | ${''}
- ${0} | ${true} | ${'0 Modules'}
+ ${0} | ${false} | ${''}
${1} | ${true} | ${'1 Module'}
${2} | ${true} | ${'2 Modules'}
`('when count is $count metadata item', ({ count, exist, text }) => {
beforeEach(() => {
- mountComponent({ count, helpUrl: 'foo' });
+ mountComponent({ ...exampleProps, count });
});
- it(`is ${exist} that it exists`, () => {
+ it(exist ? 'exists' : 'does not exist', () => {
expect(findMetadataItem().exists()).toBe(exist);
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
index cad75d2a858..31616e0b2f5 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
@@ -1,5 +1,6 @@
import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
import createFlash from '~/flash';
@@ -17,8 +18,7 @@ import InfrastructureSearch from '~/packages_and_registries/infrastructure_regis
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('packages_list_app', () => {
let wrapper;
@@ -35,7 +35,7 @@ describe('packages_list_app', () => {
const findListComponent = () => wrapper.find(PackageList);
const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
- const createStore = (filter = []) => {
+ const createStore = ({ filter = [], packageCount = 0 } = {}) => {
store = new Vuex.Store({
state: {
isLoading: false,
@@ -46,6 +46,9 @@ describe('packages_list_app', () => {
packageHelpUrl: 'foo',
},
filter,
+ pagination: {
+ total: packageCount,
+ },
},
});
store.dispatch = jest.fn();
@@ -53,7 +56,6 @@ describe('packages_list_app', () => {
const mountComponent = (provide) => {
wrapper = shallowMount(PackageListApp, {
- localVue,
store,
stubs: {
GlEmptyState,
@@ -69,6 +71,7 @@ describe('packages_list_app', () => {
beforeEach(() => {
createStore();
jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue({});
+ mountComponent();
});
afterEach(() => {
@@ -76,30 +79,26 @@ describe('packages_list_app', () => {
});
it('renders', () => {
+ createStore({ packageCount: 1 });
mountComponent();
+
expect(wrapper.element).toMatchSnapshot();
});
- it('call requestPackagesList on page:changed', () => {
- mountComponent();
- store.dispatch.mockClear();
-
+ it('calls requestPackagesList on page:changed', () => {
const list = findListComponent();
list.vm.$emit('page:changed', 1);
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList', { page: 1 });
});
- it('call requestDeletePackage on package:delete', () => {
- mountComponent();
-
+ it('calls requestDeletePackage on package:delete', () => {
const list = findListComponent();
list.vm.$emit('package:delete', 'foo');
+
expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
});
- it('does call requestPackagesList only one time on render', () => {
- mountComponent();
-
+ it('calls requestPackagesList only once on render', () => {
expect(store.dispatch).toHaveBeenCalledTimes(3);
expect(store.dispatch).toHaveBeenNthCalledWith(1, 'setSorting', expect.any(Object));
expect(store.dispatch).toHaveBeenNthCalledWith(2, 'setFilter', expect.any(Array));
@@ -114,9 +113,12 @@ describe('packages_list_app', () => {
orderBy: 'created',
};
- it('calls setSorting with the query string based sorting', () => {
+ beforeEach(() => {
+ createStore();
jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue(defaultQueryParamsMock);
+ });
+ it('calls setSorting with the query string based sorting', () => {
mountComponent();
expect(store.dispatch).toHaveBeenNthCalledWith(1, 'setSorting', {
@@ -126,8 +128,6 @@ describe('packages_list_app', () => {
});
it('calls setFilter with the query string based filters', () => {
- jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue(defaultQueryParamsMock);
-
mountComponent();
expect(store.dispatch).toHaveBeenNthCalledWith(2, 'setFilter', [
@@ -151,8 +151,6 @@ describe('packages_list_app', () => {
describe('empty state', () => {
it('generate the correct empty list link', () => {
- mountComponent();
-
const link = findListComponent().find(GlLink);
expect(link.attributes('href')).toBe(emptyListHelpUrl);
@@ -160,8 +158,6 @@ describe('packages_list_app', () => {
});
it('includes the right content on the default tab', () => {
- mountComponent();
-
const heading = findEmptyState().find('h1');
expect(heading.text()).toBe('There are no packages yet');
@@ -170,7 +166,7 @@ describe('packages_list_app', () => {
describe('filter without results', () => {
beforeEach(() => {
- createStore([{ type: 'something' }]);
+ createStore({ filter: [{ type: 'something' }] });
mountComponent();
});
@@ -182,20 +178,30 @@ describe('packages_list_app', () => {
});
});
- describe('Search', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findInfrastructureSearch().exists()).toBe(true);
+ describe('search', () => {
+ describe('with no packages', () => {
+ it('does not exist', () => {
+ expect(findInfrastructureSearch().exists()).toBe(false);
+ });
});
- it('on update fetches data from the store', () => {
- mountComponent();
- store.dispatch.mockClear();
+ describe('with packages', () => {
+ beforeEach(() => {
+ createStore({ packageCount: 1 });
+ mountComponent();
+ });
- findInfrastructureSearch().vm.$emit('update');
+ it('exists', () => {
+ expect(findInfrastructureSearch().exists()).toBe(true);
+ });
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ it('on update fetches data from the store', () => {
+ store.dispatch.mockClear();
+
+ findInfrastructureSearch().vm.$emit('update');
+
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
index 26569f20e94..fed82653016 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
@@ -1,5 +1,6 @@
import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { last } from 'lodash';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
@@ -11,8 +12,7 @@ import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registr
import Tracking from '~/tracking';
import { packageList } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('packages_list', () => {
let wrapper;
@@ -61,7 +61,6 @@ describe('packages_list', () => {
createStore(isGroupPage, packages, isLoading);
wrapper = mount(PackagesList, {
- localVue,
store,
stubs: {
...stubChildren(PackagesList),
@@ -121,16 +120,15 @@ describe('packages_list', () => {
mountComponent();
});
- it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => {
+ it('setItemToBeDeleted sets itemToBeDeleted and open the modal', async () => {
const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show');
const item = last(wrapper.vm.list);
findPackagesListRow().vm.$emit('packageToDelete', item);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.itemToBeDeleted).toEqual(item);
- expect(mockModalShow).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.vm.itemToBeDeleted).toEqual(item);
+ expect(mockModalShow).toHaveBeenCalled();
});
it('deleteItemConfirmation resets itemToBeDeleted', () => {
@@ -141,15 +139,14 @@ describe('packages_list', () => {
expect(wrapper.vm.itemToBeDeleted).toEqual(null);
});
- it('deleteItemConfirmation emit package:delete', () => {
+ it('deleteItemConfirmation emit package:delete', async () => {
const itemToBeDeleted = { id: 2 };
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ itemToBeDeleted });
wrapper.vm.deleteItemConfirmation();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
- });
+ await nextTick();
+ expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
});
it('deleteItemCanceled resets itemToBeDeleted', () => {
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
index 1052fdd1dda..79c1b18c9f9 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
@@ -1,4 +1,5 @@
import { GlLink } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -126,7 +127,7 @@ describe('packages_list_row', () => {
findDeleteButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('packageToDelete')).toBeTruthy();
expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
index 7aa42a1f1e5..bdd0fe3ad9e 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
@@ -72,12 +72,14 @@ exports[`VersionRow renders 1`] = `
<div
class="gl-display-flex gl-align-items-center gl-min-h-6"
>
- Created
- <time-ago-tooltip-stub
- cssclass=""
- time="2021-08-10T09:33:54Z"
- tooltipplacement="top"
- />
+ <span>
+ Created
+ <time-ago-tooltip-stub
+ cssclass=""
+ time="2021-08-10T09:33:54Z"
+ tooltipplacement="top"
+ />
+ </span>
</div>
</div>
</div>
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
index 6ad6007c9da..5da9cfffaae 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
@@ -24,7 +25,7 @@ const packageWithTags = {
describe('PackageTitle', () => {
let wrapper;
- function createComponent(packageEntity = packageWithTags) {
+ async function createComponent(packageEntity = packageWithTags) {
wrapper = shallowMountExtended(PackageTitle, {
propsData: { packageEntity },
stubs: {
@@ -35,7 +36,7 @@ describe('PackageTitle', () => {
GlResizeObserver: createMockDirective(),
},
});
- return wrapper.vm.$nextTick();
+ await nextTick();
}
const findTitleArea = () => wrapper.findComponent(TitleArea);
@@ -71,7 +72,7 @@ describe('PackageTitle', () => {
await createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPackageBadges()).toHaveLength(packageTags().length);
});
@@ -85,7 +86,7 @@ describe('PackageTitle', () => {
const { value } = getBinding(wrapper.element, 'gl-resize-observer');
value();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPackageBadges()).toHaveLength(packageTags().length);
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
index 5de30829fa5..14a70def7d0 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
@@ -1,4 +1,4 @@
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -16,8 +16,6 @@ import {
jest.mock('~/flash');
-const localVue = createLocalVue();
-
describe('DeletePackage', () => {
let wrapper;
let apolloProvider;
@@ -27,7 +25,7 @@ describe('DeletePackage', () => {
const eventPayload = { id: '1' };
function createComponent(propsData = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [
[getPackagesQuery, resolver],
@@ -37,7 +35,6 @@ describe('DeletePackage', () => {
wrapper = shallowMountExtended(DeletePackage, {
propsData,
- localVue,
apolloProvider,
scopedSlots: {
default(props) {
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
index 9467a613b2a..12a3eaa3873 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
@@ -1,5 +1,5 @@
import { GlSprintf } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -17,8 +17,7 @@ import { PACKAGE_ERROR_STATUS } from '~/packages_and_registries/package_registry
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { packageData, packagePipelines, packageProject, packageTags } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueRouter);
+Vue.use(VueRouter);
describe('packages_list_row', () => {
let wrapper;
@@ -47,7 +46,6 @@ describe('packages_list_row', () => {
provide = defaultProvide,
} = {}) => {
wrapper = shallowMountExtended(PackagesListRow, {
- localVue,
provide,
stubs: {
ListItem,
@@ -121,7 +119,7 @@ describe('packages_list_row', () => {
findDeleteButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('packageToDelete')).toBeTruthy();
expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
index bed7a07ff36..9e91b15bc6e 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
@@ -5,7 +5,10 @@ import component from '~/packages_and_registries/package_registry/components/lis
import PackageTypeToken from '~/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
+import { LIST_KEY_CREATED_AT } from '~/packages_and_registries/package_registry/constants';
+
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
jest.mock('~/packages_and_registries/shared/utils');
@@ -22,6 +25,7 @@ describe('Package Search', () => {
const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
const findUrlSync = () => wrapper.findComponent(UrlSync);
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
const mountComponent = (isGroupPage = false) => {
wrapper = shallowMountExtended(component, {
@@ -32,6 +36,7 @@ describe('Package Search', () => {
},
stubs: {
UrlSync,
+ LocalStorageSync,
},
});
};
@@ -64,6 +69,19 @@ describe('Package Search', () => {
expect(findUrlSync().exists()).toBe(true);
});
+ it('has a LocalStorageSync component', () => {
+ mountComponent();
+
+ expect(findLocalStorageSync().props()).toMatchObject({
+ asJson: true,
+ storageKey: 'package_registry_list_sorting',
+ value: {
+ orderBy: LIST_KEY_CREATED_AT,
+ sort: 'desc',
+ },
+ });
+ });
+
it.each`
isGroupPage | page
${false} | ${'project'}
@@ -92,7 +110,7 @@ describe('Package Search', () => {
await nextTick();
- expect(findRegistrySearch().props('sorting')).toEqual({ sort: 'foo', orderBy: 'name' });
+ expect(findRegistrySearch().props('sorting')).toEqual({ sort: 'foo', orderBy: 'created_at' });
// there is always a first call on mounted that emits up default values
expect(wrapper.emitted('update')[1]).toEqual([
@@ -101,7 +119,7 @@ describe('Package Search', () => {
packageName: '',
packageType: undefined,
},
- sort: 'NAME_FOO',
+ sort: 'CREATED_FOO',
},
]);
});
@@ -133,7 +151,7 @@ describe('Package Search', () => {
packageName: '',
packageType: undefined,
},
- sort: 'NAME_DESC',
+ sort: 'CREATED_DESC',
},
]);
});
diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js
index c6a59f20998..0a4747fc9ec 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -119,6 +119,7 @@ export const packageVersions = () => [
];
export const packageData = (extend) => ({
+ __typename: 'Package',
id: 'gid://gitlab/Packages::Package/111',
canDestroy: true,
name: '@gitlab-org/package-15',
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap
index ed96abe24b1..0154486e224 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap
@@ -38,8 +38,8 @@ exports[`PackagesListApp renders 1`] = `
class="gl-font-size-h-display gl-line-height-36 h4"
>
- There are no packages yet
-
+ There are no packages yet
+
</h1>
<p
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
index 637e2edf3be..a7e31d42c9e 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
@@ -1,6 +1,6 @@
import { GlEmptyState, GlBadge, GlTabs, GlTab } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
@@ -41,8 +41,6 @@ import {
jest.mock('~/flash');
useMockLocationHelper();
-const localVue = createLocalVue();
-
describe('PackagesApp', () => {
let wrapper;
let apolloProvider;
@@ -59,12 +57,14 @@ describe('PackagesApp', () => {
breadCrumbState,
};
+ const { __typename, ...packageWithoutTypename } = packageData();
+
function createComponent({
resolver = jest.fn().mockResolvedValue(packageDetailsQuery()),
fileDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFileMutation()),
routeId = '1',
} = {}) {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [
[getPackageDetails, resolver],
@@ -73,7 +73,6 @@ describe('PackagesApp', () => {
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(PackagesApp, {
- localVue,
apolloProvider,
provide,
stubs: {
@@ -133,7 +132,7 @@ describe('PackagesApp', () => {
expect(findPackageTitle().exists()).toBe(true);
expect(findPackageTitle().props()).toMatchObject({
- packageEntity: expect.objectContaining(packageData()),
+ packageEntity: expect.objectContaining(packageWithoutTypename),
});
});
@@ -156,7 +155,7 @@ describe('PackagesApp', () => {
expect(findPackageHistory().exists()).toBe(true);
expect(findPackageHistory().props()).toMatchObject({
- packageEntity: expect.objectContaining(packageData()),
+ packageEntity: expect.objectContaining(packageWithoutTypename),
projectName: packageDetailsQuery().data.package.project.name,
});
});
@@ -168,7 +167,7 @@ describe('PackagesApp', () => {
expect(findAdditionalMetadata().exists()).toBe(true);
expect(findAdditionalMetadata().props()).toMatchObject({
- packageEntity: expect.objectContaining(packageData()),
+ packageEntity: expect.objectContaining(packageWithoutTypename),
});
});
@@ -179,7 +178,7 @@ describe('PackagesApp', () => {
expect(findInstallationCommands().exists()).toBe(true);
expect(findInstallationCommands().props()).toMatchObject({
- packageEntity: expect.objectContaining(packageData()),
+ packageEntity: expect.objectContaining(packageWithoutTypename),
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
index 2ac2a6455ef..0e74fbbc6d9 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
@@ -1,8 +1,8 @@
import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
+
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -27,8 +27,6 @@ import { packagesListQuery, packageData, pagination } from '../mock_data';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
-const localVue = createLocalVue();
-
describe('PackagesListApp', () => {
let wrapper;
let apolloProvider;
@@ -61,13 +59,12 @@ describe('PackagesListApp', () => {
resolver = jest.fn().mockResolvedValue(packagesListQuery()),
provide = defaultProvide,
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[getPackagesQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(ListPage, {
- localVue,
apolloProvider,
provide,
stubs: {
@@ -85,7 +82,7 @@ describe('PackagesListApp', () => {
wrapper.destroy();
});
- const waitForFirstRequest = () => {
+ const waitForFirstRequest = async () => {
// emit a search update so the query is executed
findSearch().vm.$emit('update', { sort: 'NAME_DESC', filters: [] });
return waitForPromises();
@@ -149,11 +146,10 @@ describe('PackagesListApp', () => {
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(packagesListQuery());
mountComponent({ resolver });
-
- return waitForFirstRequest();
});
- it('exists and has the right props', () => {
+ it('exists and has the right props', async () => {
+ await waitForFirstRequest();
expect(findListComponent().props()).toMatchObject({
list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]),
isLoading: false,
@@ -161,16 +157,20 @@ describe('PackagesListApp', () => {
});
});
- it('when list emits next-page fetches the next set of records', () => {
+ it('when list emits next-page fetches the next set of records', async () => {
+ await waitForFirstRequest();
findListComponent().vm.$emit('next-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
);
});
- it('when list emits prev-page fetches the prev set of records', () => {
+ it('when list emits prev-page fetches the prev set of records', async () => {
+ await waitForFirstRequest();
findListComponent().vm.$emit('prev-page');
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
diff --git a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
index f6c1d212b51..94f56e5c979 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
@@ -1,5 +1,5 @@
import { GlSprintf, GlToggle } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -33,8 +33,6 @@ import {
jest.mock('~/flash');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
-const localVue = createLocalVue();
-
describe('DependencyProxySettings', () => {
let wrapper;
let apolloProvider;
@@ -47,7 +45,7 @@ describe('DependencyProxySettings', () => {
groupDependencyProxyPath: 'group_dependency_proxy_path',
};
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const mountComponent = ({
provide = defaultProvide,
@@ -63,7 +61,6 @@ describe('DependencyProxySettings', () => {
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(component, {
- localVue,
apolloProvider,
provide,
propsData: {
diff --git a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
index 933dac7f5a8..5c30074a6af 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
@@ -1,7 +1,8 @@
import { GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
+
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue';
@@ -19,8 +20,6 @@ import {
jest.mock('~/flash');
-const localVue = createLocalVue();
-
describe('Group Settings App', () => {
let wrapper;
let apolloProvider;
@@ -36,14 +35,13 @@ describe('Group Settings App', () => {
resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock),
provide = defaultProvide,
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[getGroupPackagesSettingsQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
- localVue,
apolloProvider,
provide,
mocks: {
diff --git a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
index 693af21e24a..d92d42e7834 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
@@ -1,5 +1,5 @@
import { GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -28,8 +28,6 @@ import {
jest.mock('~/flash');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
-const localVue = createLocalVue();
-
describe('Packages Settings', () => {
let wrapper;
let apolloProvider;
@@ -42,14 +40,13 @@ describe('Packages Settings', () => {
const mountComponent = ({
mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock()),
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[updateNamespacePackageSettings, mutationResolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(component, {
- localVue,
apolloProvider,
provide: defaultProvide,
propsData: {
@@ -252,7 +249,7 @@ describe('Packages Settings', () => {
emitMavenSettingsUpdate();
- await wrapper.vm.$nextTick();
+ await nextTick();
// errors are reset on mutation call
expect(findMavenDuplicatedSettings().props('duplicateExceptionRegexError')).toBe('');
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 8266f9bee89..a6c929844b1 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
@@ -1,7 +1,9 @@
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import component from '~/packages_and_registries/settings/project/components/registry_settings_app.vue';
import SettingsForm from '~/packages_and_registries/settings/project/components/settings_form.vue';
import {
@@ -19,8 +21,6 @@ import {
containerExpirationPolicyData,
} from '../mock_data';
-const localVue = createLocalVue();
-
describe('Registry Settings App', () => {
let wrapper;
let fakeApollo;
@@ -55,17 +55,14 @@ describe('Registry Settings App', () => {
};
const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [[expirationPolicyQuery, resolver]];
fakeApollo = createMockApollo(requestHandlers);
mountComponent(provide, {
- localVue,
apolloProvider: fakeApollo,
});
-
- return requestHandlers.map((request) => request[1]);
};
afterEach(() => {
@@ -101,25 +98,25 @@ describe('Registry Settings App', () => {
${'response and changes'} | ${expirationPolicyPayload()} | ${{ ...containerExpirationPolicyData(), nameRegex: '12345' }} | ${true}
${'response and empty'} | ${expirationPolicyPayload()} | ${{}} | ${true}
`('$description', async ({ apiResponse, workingCopy, result }) => {
- const requests = mountComponentWithApollo({
+ mountComponentWithApollo({
provide: { ...defaultProvidedValues, enableHistoricEntries: true },
resolver: jest.fn().mockResolvedValue(apiResponse),
});
- await Promise.all(requests);
+ await waitForPromises();
findSettingsComponent().vm.$emit('input', workingCopy);
- await wrapper.vm.$nextTick();
+ await waitForPromises();
expect(findSettingsComponent().props('isEdited')).toBe(result);
});
});
it('renders the setting form', async () => {
- const requests = mountComponentWithApollo({
+ mountComponentWithApollo({
resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()),
});
- await Promise.all(requests);
+ await waitForPromises();
expect(findSettingsComponent().exists()).toBe(true);
});
@@ -153,11 +150,11 @@ describe('Registry Settings App', () => {
});
describe('fetchSettingsError', () => {
- beforeEach(() => {
- const requests = mountComponentWithApollo({
+ beforeEach(async () => {
+ mountComponentWithApollo({
resolver: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
- return Promise.all(requests);
+ await waitForPromises();
});
it('the form is hidden', () => {
@@ -175,14 +172,14 @@ describe('Registry Settings App', () => {
${true} | ${true}
${false} | ${false}
`('is $isShown that the form is shown', async ({ enableHistoricEntries, isShown }) => {
- const requests = mountComponentWithApollo({
+ mountComponentWithApollo({
provide: {
...defaultProvidedValues,
enableHistoricEntries,
},
resolver: jest.fn().mockResolvedValue(emptyExpirationPolicyPayload()),
});
- await Promise.all(requests);
+ await waitForPromises();
expect(findSettingsComponent().exists()).toBe(isShown);
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
index bc104a25ef9..625aa37fc0f 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
@@ -1,5 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { GlCard, GlLoadingIcon } from 'jest/packages_and_registries/shared/stubs';
@@ -201,7 +202,7 @@ describe('Settings Form', () => {
finder().vm.$emit('input', 'foo');
expect(finder().props('error')).toEqual('bar');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(finder().props('error')).toEqual('');
});
@@ -213,7 +214,7 @@ describe('Settings Form', () => {
finder().vm.$emit('validation', false);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findSaveButton().props('disabled')).toBe(true);
});
@@ -252,7 +253,7 @@ describe('Settings Form', () => {
findForm().trigger('reset');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findKeepRegexInput().props('error')).toBe('');
expect(findRemoveRegexInput().props('error')).toBe('');
@@ -319,7 +320,7 @@ describe('Settings Form', () => {
findForm().trigger('submit');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE);
});
@@ -335,7 +336,7 @@ describe('Settings Form', () => {
findForm().trigger('submit');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo');
});
@@ -349,7 +350,7 @@ describe('Settings Form', () => {
findForm().trigger('submit');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE);
});
@@ -368,7 +369,7 @@ describe('Settings Form', () => {
findForm().trigger('submit');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findKeepRegexInput().props('error')).toEqual('baz');
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
index a56bb75f8ed..33406c98f4b 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
@@ -13,6 +13,7 @@ export const expirationPolicyPayload = (override) => ({
project: {
id: '1',
containerExpirationPolicy: {
+ __typename: 'ContainerExpirationPolicy',
...containerExpirationPolicyData(),
...override,
},
diff --git a/spec/frontend/pager_spec.js b/spec/frontend/pager_spec.js
index ff352303143..043ea470436 100644
--- a/spec/frontend/pager_spec.js
+++ b/spec/frontend/pager_spec.js
@@ -1,6 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import { removeParams } from '~/lib/utils/url_utility';
import Pager from '~/pager';
@@ -64,67 +65,59 @@ describe('pager', () => {
Pager.init();
});
- it('shows loader while loading next page', (done) => {
+ it('shows loader while loading next page', async () => {
mockSuccess();
jest.spyOn(Pager.loading, 'show').mockImplementation(() => {});
Pager.getOld();
- setImmediate(() => {
- expect(Pager.loading.show).toHaveBeenCalled();
+ await waitForPromises();
- done();
- });
+ expect(Pager.loading.show).toHaveBeenCalled();
});
- it('hides loader on success', (done) => {
+ it('hides loader on success', async () => {
mockSuccess();
jest.spyOn(Pager.loading, 'hide').mockImplementation(() => {});
Pager.getOld();
- setImmediate(() => {
- expect(Pager.loading.hide).toHaveBeenCalled();
+ await waitForPromises();
- done();
- });
+ expect(Pager.loading.hide).toHaveBeenCalled();
});
- it('hides loader on error', (done) => {
+ it('hides loader on error', async () => {
mockError();
jest.spyOn(Pager.loading, 'hide').mockImplementation(() => {});
Pager.getOld();
- setImmediate(() => {
- expect(Pager.loading.hide).toHaveBeenCalled();
+ await waitForPromises();
- done();
- });
+ expect(Pager.loading.hide).toHaveBeenCalled();
});
- it('sends request to url with offset and limit params', (done) => {
+ it('sends request to url with offset and limit params', async () => {
Pager.offset = 100;
Pager.limit = 20;
Pager.getOld();
- setImmediate(() => {
- const [url, params] = axios.get.mock.calls[0];
+ await waitForPromises();
- expect(params).toEqual({
- params: {
- limit: 20,
- offset: 100,
- },
- });
+ const [url, params] = axios.get.mock.calls[0];
- expect(url).toBe('/some_list');
-
- done();
+ expect(params).toEqual({
+ params: {
+ limit: 20,
+ offset: 100,
+ },
});
+
+ expect(url).toBe('/some_list');
});
- it('disables if return count is less than limit', (done) => {
+ it('disables if return count is less than limit', async () => {
Pager.offset = 0;
Pager.limit = 20;
@@ -132,12 +125,10 @@ describe('pager', () => {
jest.spyOn(Pager.loading, 'hide').mockImplementation(() => {});
Pager.getOld();
- setImmediate(() => {
- expect(Pager.loading.hide).toHaveBeenCalled();
- expect(Pager.disable).toBe(true);
+ await waitForPromises();
- done();
- });
+ expect(Pager.loading.hide).toHaveBeenCalled();
+ expect(Pager.disable).toBe(true);
});
describe('has data-href attribute from list element', () => {
diff --git a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
index 1fcc00489e3..f10b202f4d7 100644
--- a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
+++ b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Api from '~/api';
import NamespaceSelect from '~/pages/admin/projects/components/namespace_select.vue';
@@ -55,14 +56,14 @@ describe('Dropdown select component', () => {
mountDropdown({ fieldName: 'namespace-input' });
// wait for dropdown options to populate
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdownOption('user: Administrator').exists()).toBe(true);
expect(findDropdownOption('group: GitLab Org').exists()).toBe(true);
expect(findDropdownOption('group: Foobar').exists()).toBe(false);
findDropdownOption('user: Administrator').trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findNamespaceInput().attributes('value')).toBe('10');
expect(findDropdownToggle().text()).toBe('user: Administrator');
@@ -72,7 +73,7 @@ describe('Dropdown select component', () => {
mountDropdown();
// wait for dropdown options to populate
- await wrapper.vm.$nextTick();
+ await nextTick();
findDropdownOption('group: GitLab Org').trigger('click');
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index 6a7ce80ec5a..ef295e7d1ba 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -1,5 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
+import waitForPromises from 'helpers/wait_for_promises';
import '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
import { addDelimiter } from '~/lib/utils/text_utility';
@@ -71,7 +72,7 @@ describe('Todos', () => {
describe('on done todo click', () => {
let onToggleSpy;
- beforeEach((done) => {
+ beforeEach(() => {
const el = document.querySelector('.js-done-todo');
const path = el.dataset.href;
@@ -86,7 +87,7 @@ describe('Todos', () => {
el.click();
// Wait for axios and HTML to udpate
- setImmediate(done);
+ return waitForPromises();
});
it('dispatches todo:toggle', () => {
diff --git a/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js
index b722ac1e97b..c30b996437d 100644
--- a/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js
+++ b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js
@@ -1,4 +1,5 @@
import { GlModal } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
I18N_PASSWORD_PROMPT_CANCEL_BUTTON,
@@ -62,7 +63,7 @@ describe('Password prompt modal', () => {
setPassword(mockPassword);
submitModal();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(handleConfirmPasswordSpy).toHaveBeenCalledTimes(1);
expect(handleConfirmPasswordSpy).toHaveBeenCalledWith(mockPassword);
@@ -73,7 +74,7 @@ describe('Password prompt modal', () => {
expect(findConfirmBtnDisabledState()).toBe(true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findConfirmBtnDisabledState()).toBe(false);
});
@@ -84,7 +85,7 @@ describe('Password prompt modal', () => {
expect(findConfirmBtnDisabledState()).toBe(true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findConfirmBtnDisabledState()).toBe(true);
});
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 dd617b1ffc2..dc5f1cb9e61 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
@@ -4,6 +4,7 @@ import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
import { kebabCase } from 'lodash';
+import { nextTick } from 'vue';
import createFlash from '~/flash';
import httpStatus from '~/lib/utils/http_status';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -217,7 +218,7 @@ describe('ForkForm component', () => {
it('changes to kebab case when project name changes', async () => {
const newInput = `${projectPath}1`;
findForkNameInput().vm.$emit('input', newInput);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForkSlugInput().attributes('value')).toBe(kebabCase(newInput));
});
@@ -225,7 +226,7 @@ describe('ForkForm component', () => {
it('does not change to kebab case when project slug is changed manually', async () => {
const newInput = `${projectPath}1`;
findForkSlugInput().vm.$emit('input', newInput);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findForkSlugInput().attributes('value')).toBe(newInput);
});
@@ -273,7 +274,7 @@ describe('ForkForm component', () => {
expect(wrapper.vm.form.fields.visibility.value).toBe('public');
await findFormSelectOptions().at(1).setSelected();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getByRole(wrapper.element, 'radio', { name: /private/i }).checked).toBe(true);
});
@@ -283,7 +284,7 @@ describe('ForkForm component', () => {
await findFormSelectOptions().at(1).setSelected();
- await wrapper.vm.$nextTick();
+ await nextTick();
const container = getByRole(wrapper.element, 'radiogroup', { name: /visibility/i });
const visibilityRadios = getAllByRole(container, 'radio');
@@ -419,7 +420,7 @@ describe('ForkForm component', () => {
const form = wrapper.find(GlForm);
await form.trigger('submit');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
describe('with invalid form', () => {
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 1f9029b40c7..0f763e3220a 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -3,6 +3,7 @@ import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -143,7 +144,7 @@ describe('Code Coverage', () => {
it('updates the selected dropdown option with an icon', async () => {
findSecondDropdownItem().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findFirstDropdownItem().attributes('ischecked')).toBeFalsy();
expect(findSecondDropdownItem().attributes('ischecked')).toBeTruthy();
@@ -155,7 +156,7 @@ describe('Code Coverage', () => {
findSecondDropdownItem().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.selectedDailyCoverage).not.toBe(originalSelectedData);
expect(wrapper.vm.selectedDailyCoverage).toBe(expectedData);
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
index 1586aded6e6..86ccaa43786 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
@@ -135,13 +135,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Set up CI/CD"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Set up CI/CD
@@ -155,13 +155,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Start a free Ultimate trial"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Start a free Ultimate trial
@@ -175,13 +175,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Add code owners"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Add code owners
@@ -202,13 +202,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Add merge request approval"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Add merge request approval
@@ -265,13 +265,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Create an issue"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Create an issue
@@ -285,13 +285,13 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Submit a merge request"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
+ target="_self"
>
Submit a merge request
@@ -341,11 +341,12 @@ exports[`Learn GitLab renders correctly 1`] = `
>
<a
class="gl-link"
+ data-testid="uncompleted-learn-gitlab-link"
data-track-action="click_link"
data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Run a Security scan using CI/CD"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
+ href="https://docs.gitlab.com/ee/foobar/"
rel="noopener noreferrer"
target="_blank"
>
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js
index f7b2154a935..3b113f4dcd7 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js
@@ -12,6 +12,10 @@ const defaultProps = {
completed: false,
};
+const docLinkProps = {
+ url: 'https://docs.gitlab.com/ee/user/application_security/security_dashboard/',
+};
+
describe('Learn GitLab Section Link', () => {
let wrapper;
@@ -29,6 +33,8 @@ describe('Learn GitLab Section Link', () => {
const openInviteMembesrModalLink = () =>
wrapper.find('[data-testid="invite-for-help-continuous-onboarding-experiment-link"]');
+ const findUncompletedLink = () => wrapper.find('[data-testid="uncompleted-learn-gitlab-link"]');
+
it('renders no icon when not completed', () => {
createWrapper(undefined, { completed: false });
@@ -53,6 +59,32 @@ describe('Learn GitLab Section Link', () => {
expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(true);
});
+ describe('doc links', () => {
+ beforeEach(() => {
+ createWrapper('securityScanEnabled', docLinkProps);
+ });
+
+ it('renders links with blank target', () => {
+ const linkElement = findUncompletedLink();
+
+ expect(linkElement.exists()).toBe(true);
+ expect(linkElement.attributes('target')).toEqual('_blank');
+ });
+
+ it('tracks the click', () => {
+ const trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+
+ findUncompletedLink().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_link', {
+ label: 'Run a Security scan using CI/CD',
+ property: 'Growth::Conversion::Experiment::LearnGitLab',
+ });
+
+ unmockTracking();
+ });
+ });
+
describe('rendering a link to open the invite_members modal instead of a regular link', () => {
it.each`
action | experimentVariant | showModal
@@ -82,11 +114,7 @@ describe('Learn GitLab Section Link', () => {
it('calls the eventHub', () => {
openInviteMembesrModalLink().vm.$emit('click');
- expect(eventHub.$emit).toHaveBeenCalledWith('openModal', {
- inviteeType: 'members',
- source: 'learn_gitlab',
- tasksToBeDoneEnabled: true,
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('openModal', { source: 'learn_gitlab' });
});
it('tracks the click', async () => {
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
index 7e71622770f..ee682b18af3 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
@@ -1,13 +1,15 @@
import { GlProgressBar, GlAlert } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import Cookies from 'js-cookie';
import LearnGitlab from '~/pages/projects/learn_gitlab/components/learn_gitlab.vue';
import eventHub from '~/invite_members/event_hub';
+import { INVITE_MODAL_OPEN_COOKIE } from '~/pages/projects/learn_gitlab/constants';
import { testActions, testSections, testProject } from './mock_data';
describe('Learn GitLab', () => {
let wrapper;
let sidebar;
- let inviteMembersOpen = false;
+ let inviteMembers = false;
const createWrapper = () => {
wrapper = mount(LearnGitlab, {
@@ -15,7 +17,7 @@ describe('Learn GitLab', () => {
actions: testActions,
sections: testSections,
project: testProject,
- inviteMembersOpen,
+ inviteMembers,
},
});
};
@@ -36,7 +38,7 @@ describe('Learn GitLab', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
- inviteMembersOpen = false;
+ inviteMembers = false;
sidebar.remove();
});
@@ -59,24 +61,40 @@ describe('Learn GitLab', () => {
describe('Invite Members Modal', () => {
let spy;
+ let cookieSpy;
beforeEach(() => {
spy = jest.spyOn(eventHub, '$emit');
+ cookieSpy = jest.spyOn(Cookies, 'remove');
+ });
+
+ afterEach(() => {
+ Cookies.remove(INVITE_MODAL_OPEN_COOKIE);
});
it('emits openModal', () => {
- inviteMembersOpen = true;
+ inviteMembers = true;
+ Cookies.set(INVITE_MODAL_OPEN_COOKIE, true);
createWrapper();
expect(spy).toHaveBeenCalledWith('openModal', {
mode: 'celebrate',
- inviteeType: 'members',
source: 'learn-gitlab',
});
+ expect(cookieSpy).toHaveBeenCalledWith(INVITE_MODAL_OPEN_COOKIE);
+ });
+
+ it('does not emit openModal when cookie is not set', () => {
+ inviteMembers = true;
+
+ createWrapper();
+
+ expect(spy).not.toHaveBeenCalled();
+ expect(cookieSpy).toHaveBeenCalledWith(INVITE_MODAL_OPEN_COOKIE);
});
- it('does not emit openModal', () => {
+ it('does not emit openModal when inviteMembers is false', () => {
createWrapper();
expect(spy).not.toHaveBeenCalled();
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js b/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
index 1e633cb7cf5..b21965e8f48 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
@@ -35,7 +35,7 @@ export const testActions = {
svg: 'http://example.com/images/illustration.svg',
},
securityScanEnabled: {
- url: 'http://example.com/',
+ url: 'https://docs.gitlab.com/ee/foobar/',
completed: false,
svg: 'http://example.com/images/illustration.svg',
},
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 f3d76ca2c1b..ae5404f2d13 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,5 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import IntervalPatternInput from '~/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue';
@@ -98,7 +99,7 @@ describe('Interval Pattern Input Component', () => {
it('when a default option is selected', async () => {
selectEveryDayRadio();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCustomInput().attributes('disabled')).toBeUndefined();
});
@@ -106,7 +107,7 @@ describe('Interval Pattern Input Component', () => {
it('when the custom option is selected', async () => {
selectCustomRadio();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCustomInput().attributes('disabled')).toBeUndefined();
});
@@ -150,11 +151,11 @@ describe('Interval Pattern Input Component', () => {
it('when everyday is selected, update value', async () => {
selectEveryWeekRadio();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCustomInput().element.value).toBe(cronIntervalPresets.everyWeek);
selectEveryDayRadio();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCustomInput().element.value).toBe(cronIntervalPresets.everyDay);
});
});
@@ -170,7 +171,7 @@ describe('Interval Pattern Input Component', () => {
act();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCustomInput().element.value).toBe(expectedValue);
});
@@ -189,7 +190,7 @@ describe('Interval Pattern Input Component', () => {
findCustomInput().setValue(newValue);
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(findSelectedRadioKey()).toBe(customKey);
});
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
index 5fed9fcaad2..c28a03b35d7 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
+import { nextTick } from 'vue';
import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue';
const cookieKey = 'pipeline_schedules_callout_dismissed';
@@ -27,7 +28,7 @@ describe('Pipeline Schedule Callout', () => {
Cookies.set(cookieKey, true);
createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -71,7 +72,7 @@ describe('Pipeline Schedule Callout', () => {
findDismissCalloutBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findInnerContentOfCallout().exists()).toBe(false);
});
@@ -83,6 +84,7 @@ describe('Pipeline Schedule Callout', () => {
expect(setCookiesSpy).toHaveBeenCalledWith('pipeline_schedules_callout_dismissed', true, {
expires: 365,
+ secure: false,
});
});
});
@@ -90,7 +92,7 @@ describe('Pipeline Schedule Callout', () => {
it('is hidden when close button is clicked', async () => {
findDismissCalloutBtn().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findInnerContentOfCallout().exists()).toBe(false);
});
diff --git a/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js b/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js
index 7cbcbdcdd1f..6230809a6aa 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import projectSettingRow from '~/pages/projects/shared/permissions/components/project_setting_row.vue';
describe('Project Setting Row', () => {
@@ -18,43 +19,39 @@ describe('Project Setting Row', () => {
wrapper.destroy();
});
- it('should show the label if it is set', () => {
+ it('should show the label if it is set', async () => {
wrapper.setProps({ label: 'Test label' });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('label').text()).toEqual('Test label');
- });
+ await nextTick();
+ expect(wrapper.find('label').text()).toEqual('Test label');
});
it('should hide the label if it is not set', () => {
expect(wrapper.find('label').exists()).toBe(false);
});
- it('should show the help icon with the correct help path if it is set', () => {
+ it('should show the help icon with the correct help path if it is set', async () => {
wrapper.setProps({ label: 'Test label', helpPath: '/123' });
- return wrapper.vm.$nextTick(() => {
- const link = wrapper.find('a');
+ await nextTick();
+ const link = wrapper.find('a');
- expect(link.exists()).toBe(true);
- expect(link.attributes().href).toEqual('/123');
- });
+ expect(link.exists()).toBe(true);
+ expect(link.attributes().href).toEqual('/123');
});
- it('should hide the help icon if no help path is set', () => {
+ it('should hide the help icon if no help path is set', async () => {
wrapper.setProps({ label: 'Test label' });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('a').exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find('a').exists()).toBe(false);
});
- it('should show the help text if it is set', () => {
+ it('should show the help text if it is set', async () => {
wrapper.setProps({ helpText: 'Test text' });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('span').text()).toEqual('Test text');
- });
+ await nextTick();
+ expect(wrapper.find('span').text()).toEqual('Test text');
});
it('should hide the help text if it is set', () => {
diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
index 8a9bb025d55..305dce51971 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
@@ -244,7 +244,7 @@ describe('Settings Panel', () => {
wrapper = mountComponent({ currentSettings: { visibilityLevel: visibilityOptions.PUBLIC } });
expect(findRepositoryFeatureProjectRow().props('helpText')).toBe(
- 'View and edit files in this project. Non-project members will only have read access.',
+ 'View and edit files in this project. Non-project members have only read access.',
);
});
});
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 fd581eebd1e..1f964e8bae2 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -48,10 +48,10 @@ describe('WikiForm', () => {
return format.find(`option[value=${value}]`).setSelected();
};
- const triggerFormSubmit = () => {
+ const triggerFormSubmit = async () => {
findForm().element.dispatchEvent(new Event('submit'));
- return nextTick();
+ await nextTick();
};
const dispatchBeforeUnload = () => {
@@ -574,7 +574,7 @@ describe('WikiForm', () => {
wrapper.findComponent(GlModal).vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('switches to classic editor', () => {
diff --git a/spec/frontend/performance_bar/components/add_request_spec.js b/spec/frontend/performance_bar/components/add_request_spec.js
index c5247a43f27..5422481439e 100644
--- a/spec/frontend/performance_bar/components/add_request_spec.js
+++ b/spec/frontend/performance_bar/components/add_request_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import AddRequest from '~/performance_bar/components/add_request.vue';
describe('add request form', () => {
@@ -17,9 +18,9 @@ describe('add request form', () => {
});
describe('when clicking the button', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.find('button').trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows the form', () => {
@@ -27,9 +28,9 @@ describe('add request form', () => {
});
describe('when pressing escape', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.find('input').trigger('keyup.esc');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('hides the input', () => {
@@ -38,12 +39,11 @@ describe('add request form', () => {
});
describe('when submitting the form', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.find('input').setValue('http://gitlab.example.com/users/root/calendar.json');
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find('input').trigger('keyup.enter');
- return wrapper.vm.$nextTick();
- });
+ await nextTick();
+ wrapper.find('input').trigger('keyup.enter');
+ await nextTick();
});
it('emits an event to add the request', () => {
@@ -57,11 +57,10 @@ describe('add request form', () => {
expect(wrapper.find('input').exists()).toBe(false);
});
- it('clears the value for next time', () => {
+ it('clears the value for next time', async () => {
wrapper.find('button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('input').text()).toEqual('');
- });
+ await nextTick();
+ expect(wrapper.find('input').text()).toEqual('');
});
});
});
diff --git a/spec/frontend/persistent_user_callout_spec.js b/spec/frontend/persistent_user_callout_spec.js
index 1db255106ed..4633602de26 100644
--- a/spec/frontend/persistent_user_callout_spec.js
+++ b/spec/frontend/persistent_user_callout_spec.js
@@ -10,6 +10,7 @@ jest.mock('~/flash');
describe('PersistentUserCallout', () => {
const dismissEndpoint = '/dismiss';
const featureName = 'feature';
+ const groupId = '5';
function createFixture() {
const fixture = document.createElement('div');
@@ -18,6 +19,7 @@ describe('PersistentUserCallout', () => {
class="container"
data-dismiss-endpoint="${dismissEndpoint}"
data-feature-id="${featureName}"
+ data-group-id="${groupId}"
>
<button type="button" class="js-close"></button>
</div>
@@ -86,7 +88,9 @@ describe('PersistentUserCallout', () => {
return waitForPromises().then(() => {
expect(persistentUserCallout.container.remove).toHaveBeenCalled();
- expect(mockAxios.history.post[0].data).toBe(JSON.stringify({ feature_name: featureName }));
+ expect(mockAxios.history.post[0].data).toBe(
+ JSON.stringify({ feature_name: featureName, group_id: groupId }),
+ );
});
});
@@ -191,8 +195,8 @@ describe('PersistentUserCallout', () => {
return waitForPromises().then(() => {
expect(window.location.assign).toBeCalledWith(href);
- expect(mockAxios.history.post[0].data).toBe(JSON.stringify({ feature_name: featureName }));
expect(persistentUserCallout.container.remove).not.toHaveBeenCalled();
+ expect(mockAxios.history.post[0].data).toBe(JSON.stringify({ feature_name: featureName }));
});
});
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 bc77b7045eb..b54feea6ff7 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -1,17 +1,20 @@
import VueApollo from 'vue-apollo';
import { GlFormTextarea, GlFormInput, GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { objectToQuery, redirectTo } from '~/lib/utils/url_utility';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import CommitSection from '~/pipeline_editor/components/commit/commit_section.vue';
import {
COMMIT_ACTION_CREATE,
COMMIT_ACTION_UPDATE,
COMMIT_SUCCESS,
+ COMMIT_SUCCESS_WITH_REDIRECT,
} from '~/pipeline_editor/constants';
+import { resolvers } from '~/pipeline_editor/graphql/resolvers';
import commitCreate from '~/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql';
+import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
import updatePipelineEtag from '~/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql';
import {
@@ -23,18 +26,8 @@ import {
mockCommitMessage,
mockDefaultBranch,
mockProjectFullPath,
- mockNewMergeRequestPath,
} from '../../mock_data';
-const localVue = createLocalVue();
-
-jest.mock('~/lib/utils/url_utility', () => ({
- redirectTo: jest.fn(),
- refreshCurrentPage: jest.fn(),
- objectToQuery: jest.requireActual('~/lib/utils/url_utility').objectToQuery,
- mergeUrlParams: jest.requireActual('~/lib/utils/url_utility').mergeUrlParams,
-}));
-
const mockVariables = {
action: COMMIT_ACTION_UPDATE,
projectPath: mockProjectFullPath,
@@ -48,7 +41,6 @@ const mockVariables = {
const mockProvide = {
ciConfigPath: mockCiConfigPath,
projectFullPath: mockProjectFullPath,
- newMergeRequestPath: mockNewMergeRequestPath,
};
describe('Pipeline Editor | Commit section', () => {
@@ -79,11 +71,23 @@ describe('Pipeline Editor | Commit section', () => {
const createComponentWithApollo = (options) => {
const handlers = [[commitCreate, mockMutateCommitData]];
- localVue.use(VueApollo);
- mockApollo = createMockApollo(handlers);
+ Vue.use(VueApollo);
+ mockApollo = createMockApollo(handlers, resolvers);
+
+ mockApollo.clients.defaultClient.cache.writeQuery({
+ query: getCurrentBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: mockDefaultBranch,
+ },
+ },
+ },
+ });
const apolloConfig = {
- localVue,
apolloProvider: mockApollo,
};
@@ -209,20 +213,23 @@ describe('Pipeline Editor | Commit section', () => {
const newBranch = 'new-branch';
beforeEach(async () => {
+ mockMutateCommitData.mockResolvedValue(mockCommitCreateResponse);
createComponentWithApollo();
+ mockMutateCommitData.mockResolvedValue(mockCommitCreateResponse);
await submitCommit({
branch: newBranch,
openMergeRequest: true,
});
});
- it('redirects to the merge request page with source and target branches', () => {
- const branchesQuery = objectToQuery({
- 'merge_request[source_branch]': newBranch,
- 'merge_request[target_branch]': mockDefaultBranch,
- });
-
- expect(redirectTo).toHaveBeenCalledWith(`${mockNewMergeRequestPath}?${branchesQuery}`);
+ it('emits a commit event with the right type, sourceBranch and targetBranch', () => {
+ expect(wrapper.emitted('commit')).toBeTruthy();
+ expect(wrapper.emitted('commit')[0]).toMatchObject([
+ {
+ type: COMMIT_SUCCESS_WITH_REDIRECT,
+ params: { sourceBranch: newBranch, targetBranch: mockDefaultBranch },
+ },
+ ]);
});
});
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 ab9027a56a4..7dbacad34bf 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
@@ -12,6 +12,10 @@ 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 getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.query.graphql';
+import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
+import getLastCommitBranch from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
+import { resolvers } from '~/pipeline_editor/graphql/resolvers';
+
import {
mockBranchPaginationLimit,
mockDefaultBranch,
@@ -34,6 +38,7 @@ describe('Pipeline editor branch switcher', () => {
const createComponent = ({
currentBranch = mockDefaultBranch,
+ availableBranches = ['main'],
isQueryLoading = false,
mountFn = shallowMount,
options = {},
@@ -59,7 +64,7 @@ describe('Pipeline editor branch switcher', () => {
},
data() {
return {
- availableBranches: ['main'],
+ availableBranches,
currentBranch,
};
},
@@ -67,13 +72,44 @@ describe('Pipeline editor branch switcher', () => {
});
};
- const createComponentWithApollo = ({ mountFn = shallowMount, props = {} } = {}) => {
+ const createComponentWithApollo = ({
+ mountFn = shallowMount,
+ props = {},
+ availableBranches = ['main'],
+ } = {}) => {
const handlers = [[getAvailableBranchesQuery, mockAvailableBranchQuery]];
- mockApollo = createMockApollo(handlers);
+ mockApollo = createMockApollo(handlers, resolvers);
+
+ mockApollo.clients.defaultClient.cache.writeQuery({
+ query: getCurrentBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: mockDefaultBranch,
+ },
+ },
+ },
+ });
+
+ mockApollo.clients.defaultClient.cache.writeQuery({
+ query: getLastCommitBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ lastCommit: {
+ __typename: 'WorkBranch',
+ name: '',
+ },
+ },
+ },
+ });
createComponent({
mountFn,
props,
+ availableBranches,
options: {
localVue,
apolloProvider: mockApollo,
@@ -113,7 +149,7 @@ describe('Pipeline editor branch switcher', () => {
describe('when querying for the first time', () => {
beforeEach(() => {
- createComponentWithApollo();
+ createComponentWithApollo({ availableBranches: [] });
});
it('disables the dropdown', () => {
@@ -153,7 +189,7 @@ describe('Pipeline editor branch switcher', () => {
describe('on fetch error', () => {
beforeEach(async () => {
setAvailableBranchesMock(new Error());
- createComponentWithApollo();
+ createComponentWithApollo({ availableBranches: [] });
await waitForPromises();
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
index c101b1d21c7..35315db39f8 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -8,8 +9,7 @@ import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.g
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Pipeline Status', () => {
let wrapper;
@@ -21,7 +21,6 @@ describe('Pipeline Status', () => {
mockApollo = createMockApollo(handlers);
wrapper = shallowMount(PipelineStatus, {
- localVue,
apolloProvider: mockApollo,
propsData: {
commitSha: mockCommitSha,
@@ -70,13 +69,13 @@ describe('Pipeline Status', () => {
describe('when querying data', () => {
describe('when data is set', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockPipelineQuery.mockResolvedValue({
data: { project: mockProjectPipeline() },
});
createComponentWithApollo();
- waitForPromises();
+ await waitForPromises();
});
it('query is called with correct variables', async () => {
diff --git a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
index 6b9f576917f..93eb18c90cf 100644
--- a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
@@ -1,14 +1,15 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
import { PIPELINE_FAILURE } from '~/pipeline_editor/constants';
import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Pipeline Status', () => {
let wrapper;
@@ -35,7 +36,6 @@ describe('Pipeline Status', () => {
createComponent({
hasStages,
options: {
- localVue,
apolloProvider: mockApollo,
},
});
@@ -89,9 +89,10 @@ describe('Pipeline Status', () => {
});
describe('when query fails', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockLinkedPipelinesQuery.mockRejectedValue(new Error());
createComponentWithApollo();
+ await waitForPromises();
});
it('should emit an error event when query fails', async () => {
diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
index 570323826d1..1ad621e6f45 100644
--- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
@@ -1,6 +1,7 @@
import VueApollo from 'vue-apollo';
import { GlIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import { escape } from 'lodash';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -24,8 +25,7 @@ import {
mockYmlHelpPagePath,
} from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Validation segment component', () => {
let wrapper;
@@ -45,7 +45,6 @@ describe('Validation segment component', () => {
wrapper = extendedWrapper(
shallowMount(ValidationSegment, {
- localVue,
apolloProvider: mockApollo,
provide: {
ymlHelpPagePath: mockYmlHelpPagePath,
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
index a55176ccd79..d9ecee31e83 100644
--- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
@@ -8,6 +8,7 @@ import PipelineEditorMessages from '~/pipeline_editor/components/ui/pipeline_edi
import {
COMMIT_FAILURE,
COMMIT_SUCCESS,
+ COMMIT_SUCCESS_WITH_REDIRECT,
DEFAULT_FAILURE,
DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN,
@@ -34,7 +35,13 @@ describe('Pipeline Editor messages', () => {
it('shows a message for successful commit type', () => {
createComponent({ successType: COMMIT_SUCCESS, showSuccess: true });
- expect(findAlert().text()).toBe(wrapper.vm.$options.successTexts[COMMIT_SUCCESS]);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.success[COMMIT_SUCCESS]);
+ });
+
+ it('shows a message for successful commit with redirect type', () => {
+ createComponent({ successType: COMMIT_SUCCESS_WITH_REDIRECT, showSuccess: true });
+
+ expect(findAlert().text()).toBe(wrapper.vm.$options.success[COMMIT_SUCCESS_WITH_REDIRECT]);
});
it('does not show alert when there is a successType but visibility is off', () => {
@@ -46,7 +53,7 @@ describe('Pipeline Editor messages', () => {
it('shows a success alert with default copy if `showSuccess` is true and the `successType` is not valid,', () => {
createComponent({ successType: 'random', showSuccess: true });
- expect(findAlert().text()).toBe(wrapper.vm.$options.successTexts[DEFAULT_SUCCESS]);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.success[DEFAULT_SUCCESS]);
});
it('emit `hide-success` event when clicking on the dismiss button', async () => {
@@ -71,7 +78,7 @@ describe('Pipeline Editor messages', () => {
`('shows a message for $message', ({ failureType, expectedFailureType }) => {
createComponent({ failureType, showFailure: true });
- expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[expectedFailureType]);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errors[expectedFailureType]);
});
it('show failure reasons when there are some', () => {
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 63eca253c48..0a2c03b7850 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -5,6 +5,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { objectToQuery, redirectTo } from '~/lib/utils/url_utility';
import { resolvers } from '~/pipeline_editor/graphql/resolvers';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
@@ -13,7 +14,11 @@ import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_e
import ValidationSegment, {
i18n as validationSegmenti18n,
} from '~/pipeline_editor/components/header/validation_segment.vue';
-import { COMMIT_SUCCESS, COMMIT_FAILURE } from '~/pipeline_editor/constants';
+import {
+ COMMIT_SUCCESS,
+ COMMIT_SUCCESS_WITH_REDIRECT,
+ COMMIT_FAILURE,
+} from '~/pipeline_editor/constants';
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
@@ -35,15 +40,22 @@ import {
mockDefaultBranch,
mockEmptyCommitShaResults,
mockNewCommitShaResults,
+ mockNewMergeRequestPath,
mockProjectFullPath,
} from './mock_data';
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ redirectTo: jest.fn(),
+}));
+
const localVue = createLocalVue();
localVue.use(VueApollo);
const mockProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
+ newMergeRequestPath: mockNewMergeRequestPath,
projectFullPath: mockProjectFullPath,
};
@@ -311,6 +323,28 @@ describe('Pipeline editor app component', () => {
});
});
+ describe('when the commit succeeds with a redirect', () => {
+ const newBranch = 'new-branch';
+
+ beforeEach(async () => {
+ await createComponentWithApollo({ stubs: { PipelineEditorMessages } });
+
+ findEditorHome().vm.$emit('commit', {
+ type: COMMIT_SUCCESS_WITH_REDIRECT,
+ params: { sourceBranch: newBranch, targetBranch: mockDefaultBranch },
+ });
+ });
+
+ it('redirects to the merge request page with source and target branches', () => {
+ const branchesQuery = objectToQuery({
+ 'merge_request[source_branch]': newBranch,
+ 'merge_request[target_branch]': mockDefaultBranch,
+ });
+
+ expect(redirectTo).toHaveBeenCalledWith(`${mockNewMergeRequestPath}?${branchesQuery}`);
+ });
+ });
+
describe('and the commit mutation fails', () => {
const commitFailedReasons = ['Commit failed'];
diff --git a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
index 9e2bf1bd367..eec55091efa 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,6 +1,7 @@
import { GlForm, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import CreditCardValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
@@ -122,7 +123,7 @@ describe('Pipeline New Form', () => {
it('removes ci variable row on remove icon button click', async () => {
findRemoveIcons().at(1).trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findVariableRows()).toHaveLength(2);
});
@@ -132,7 +133,7 @@ describe('Pipeline New Form', () => {
input.element.value = 'test_var_2';
input.trigger('change');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findVariableRows()).toHaveLength(4);
expect(findKeyInputs().at(3).element.value).toBe('');
@@ -205,7 +206,7 @@ describe('Pipeline New Form', () => {
mainInput.element.value = 'build_var';
mainInput.trigger('change');
- await wrapper.vm.$nextTick();
+ await nextTick();
selectBranch('branch-1');
@@ -215,7 +216,7 @@ describe('Pipeline New Form', () => {
branchOneInput.element.value = 'deploy_var';
branchOneInput.trigger('change');
- await wrapper.vm.$nextTick();
+ await nextTick();
selectBranch('main');
@@ -309,7 +310,7 @@ describe('Pipeline New Form', () => {
findKeyInputs().at(0).element.value = 'yml_var_modified';
findKeyInputs().at(0).trigger('change');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findVariableRows().at(0).text()).not.toContain(mockYmlDesc);
});
@@ -418,7 +419,7 @@ describe('Pipeline New Form', () => {
findCCAlert().vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCCAlert().exists()).toBe(false);
expect(wrapper.vm.$data.error).toBe(null);
diff --git a/spec/frontend/pipeline_wizard/components/commit_spec.js b/spec/frontend/pipeline_wizard/components/commit_spec.js
new file mode 100644
index 00000000000..6496850b028
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/components/commit_spec.js
@@ -0,0 +1,282 @@
+import { GlButton, GlFormGroup } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { __, s__, sprintf } from '~/locale';
+import { mountExtended } from 'jest/__helpers__/vue_test_utils_helper';
+import CommitStep, { i18n } from '~/pipeline_wizard/components/commit.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import createCommitMutation from '~/pipeline_wizard/queries/create_commit.graphql';
+import getFileMetadataQuery from '~/pipeline_wizard/queries/get_file_meta.graphql';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import flushPromises from 'helpers/flush_promises';
+import {
+ createCommitMutationErrorResult,
+ createCommitMutationResult,
+ fileQueryErrorResult,
+ fileQueryResult,
+ fileQueryEmptyResult,
+} from '../mock/query_responses';
+
+Vue.use(VueApollo);
+
+const COMMIT_MESSAGE_ADD_FILE = s__('PipelineWizardDefaultCommitMessage|Add %{filename}');
+const COMMIT_MESSAGE_UPDATE_FILE = s__('PipelineWizardDefaultCommitMessage|Update %{filename}');
+
+describe('Pipeline Wizard - Commit Page', () => {
+ const createCommitMutationHandler = jest.fn();
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ let wrapper;
+
+ const getMockApollo = (scenario = {}) => {
+ return createMockApollo([
+ [
+ createCommitMutation,
+ createCommitMutationHandler.mockResolvedValue(
+ scenario.commitHasError ? createCommitMutationErrorResult : createCommitMutationResult,
+ ),
+ ],
+ [
+ getFileMetadataQuery,
+ (vars) => {
+ if (scenario.fileResultByRef) return scenario.fileResultByRef[vars.ref];
+ if (scenario.hasError) return fileQueryErrorResult;
+ return scenario.fileExists ? fileQueryResult : fileQueryEmptyResult;
+ },
+ ],
+ ]);
+ };
+ const createComponent = (props = {}, mockApollo = getMockApollo()) => {
+ wrapper = mountExtended(CommitStep, {
+ apolloProvider: mockApollo,
+ propsData: {
+ projectPath: 'some/path',
+ defaultBranch: 'main',
+ filename: 'newFile.yml',
+ ...props,
+ },
+ mocks: { $toast },
+ stubs: {
+ RefSelector: true,
+ GlFormGroup,
+ },
+ });
+ };
+
+ function getButtonWithLabel(label) {
+ return wrapper.findAllComponents(GlButton).filter((n) => n.text().match(label));
+ }
+
+ describe('ui setup', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('shows a commit message input with the correct label', () => {
+ expect(wrapper.findByTestId('commit_message').exists()).toBe(true);
+ expect(wrapper.find('label[for="commit_message"]').text()).toBe(i18n.commitMessageLabel);
+ });
+
+ it('shows a branch selector with the correct label', () => {
+ expect(wrapper.findByTestId('branch').exists()).toBe(true);
+ expect(wrapper.find('label[for="branch"]').text()).toBe(i18n.branchSelectorLabel);
+ });
+
+ it('shows a commit button', () => {
+ expect(getButtonWithLabel(i18n.commitButtonLabel).exists()).toBe(true);
+ });
+
+ it('shows a back button', () => {
+ expect(getButtonWithLabel(__('Back')).exists()).toBe(true);
+ });
+
+ it('does not show a next button', () => {
+ expect(getButtonWithLabel(__('Next')).exists()).toBe(false);
+ });
+ });
+
+ describe('loading the remote file', () => {
+ const projectPath = 'foo/bar';
+ const filename = 'foo.yml';
+
+ it('does not show a load error if call is successful', async () => {
+ createComponent({ projectPath, filename });
+ await flushPromises();
+ expect(wrapper.findByTestId('load-error').exists()).not.toBe(true);
+ });
+
+ it('shows a load error if call returns an unexpected error', async () => {
+ const branch = 'foo';
+ createComponent(
+ { defaultBranch: branch, projectPath, filename },
+ createMockApollo([[getFileMetadataQuery, () => fileQueryErrorResult]]),
+ );
+ await flushPromises();
+ expect(wrapper.findByTestId('load-error').exists()).toBe(true);
+ expect(wrapper.findByTestId('load-error').text()).toBe(i18n.errors.loadError);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+ });
+
+ describe('commit result handling', () => {
+ describe('successful commit', () => {
+ beforeEach(async () => {
+ createComponent();
+ await flushPromises();
+ await getButtonWithLabel(__('Commit')).trigger('click');
+ await flushPromises();
+ });
+
+ it('will not show an error', async () => {
+ expect(wrapper.findByTestId('commit-error').exists()).not.toBe(true);
+ });
+
+ it('will show a toast message', () => {
+ expect($toast.show).toHaveBeenCalledWith(
+ s__('PipelineWizard|The file has been committed.'),
+ );
+ });
+
+ it('emits a done event', () => {
+ expect(wrapper.emitted().done.length).toBe(1);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ jest.clearAllMocks();
+ });
+ });
+
+ describe('failed commit', () => {
+ beforeEach(async () => {
+ createComponent({}, getMockApollo({ commitHasError: true }));
+ await flushPromises();
+ await getButtonWithLabel(__('Commit')).trigger('click');
+ await flushPromises();
+ });
+
+ it('will show an error', async () => {
+ expect(wrapper.findByTestId('commit-error').exists()).toBe(true);
+ expect(wrapper.findByTestId('commit-error').text()).toBe(i18n.errors.commitError);
+ });
+
+ it('will not show a toast message', () => {
+ expect($toast.show).not.toHaveBeenCalledWith(i18n.commitSuccessMessage);
+ });
+
+ it('will not emit a done event', () => {
+ expect(wrapper.emitted().done?.length).toBeFalsy();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ jest.clearAllMocks();
+ });
+ });
+ });
+
+ describe('modelling different input combinations', () => {
+ const projectPath = 'some/path';
+ const defaultBranch = 'foo';
+ const fileContent = 'foo: bar';
+
+ describe.each`
+ filename | fileExistsOnDefaultBranch | fileExistsOnInputtedBranch | fileLoadError | commitMessageInputValue | branchInputValue | expectedCommitBranch | expectedCommitMessage | expectedAction
+ ${'foo.yml'} | ${false} | ${undefined} | ${false} | ${'foo'} | ${undefined} | ${defaultBranch} | ${'foo'} | ${'CREATE'}
+ ${'foo.yml'} | ${true} | ${undefined} | ${false} | ${'foo'} | ${undefined} | ${defaultBranch} | ${'foo'} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${true} | ${false} | ${'foo'} | ${'dev'} | ${'dev'} | ${'foo'} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${undefined} | ${false} | ${null} | ${undefined} | ${defaultBranch} | ${COMMIT_MESSAGE_ADD_FILE} | ${'CREATE'}
+ ${'foo.yml'} | ${true} | ${undefined} | ${false} | ${null} | ${undefined} | ${defaultBranch} | ${COMMIT_MESSAGE_UPDATE_FILE} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${true} | ${false} | ${null} | ${'dev'} | ${'dev'} | ${COMMIT_MESSAGE_UPDATE_FILE} | ${'UPDATE'}
+ `(
+ 'Test with fileExistsOnDefaultBranch=$fileExistsOnDefaultBranch, fileExistsOnInputtedBranch=$fileExistsOnInputtedBranch, commitMessageInputValue=$commitMessageInputValue, branchInputValue=$branchInputValue, commitReturnsError=$commitReturnsError',
+ ({
+ filename,
+ fileExistsOnDefaultBranch,
+ fileExistsOnInputtedBranch,
+ commitMessageInputValue,
+ branchInputValue,
+ expectedCommitBranch,
+ expectedCommitMessage,
+ expectedAction,
+ }) => {
+ let consoleSpy;
+
+ beforeAll(async () => {
+ createComponent(
+ {
+ filename,
+ defaultBranch,
+ projectPath,
+ fileContent,
+ },
+ getMockApollo({
+ fileResultByRef: {
+ [defaultBranch]: fileExistsOnDefaultBranch ? fileQueryResult : fileQueryEmptyResult,
+ [branchInputValue]: fileExistsOnInputtedBranch
+ ? fileQueryResult
+ : fileQueryEmptyResult,
+ },
+ }),
+ );
+
+ await flushPromises();
+
+ consoleSpy = jest.spyOn(console, 'error');
+
+ await wrapper
+ .findByTestId('commit_message')
+ .get('textarea')
+ .setValue(commitMessageInputValue);
+
+ if (branchInputValue) {
+ await wrapper.getComponent(RefSelector).vm.$emit('input', branchInputValue);
+ }
+ await Vue.nextTick();
+
+ await flushPromises();
+ });
+
+ afterAll(() => {
+ wrapper.destroy();
+ });
+
+ it('sets up without error', async () => {
+ expect(consoleSpy).not.toHaveBeenCalled();
+ });
+
+ it('does not show a load error', async () => {
+ expect(wrapper.findByTestId('load-error').exists()).not.toBe(true);
+ });
+
+ it('sends the expected commit mutation', async () => {
+ await getButtonWithLabel(__('Commit')).trigger('click');
+
+ expect(createCommitMutationHandler).toHaveBeenCalledWith({
+ input: {
+ actions: [
+ {
+ action: expectedAction,
+ content: fileContent,
+ filePath: `/${filename}`,
+ },
+ ],
+ branch: expectedCommitBranch,
+ message: sprintf(expectedCommitMessage, { filename }),
+ projectPath,
+ },
+ });
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/pipeline_wizard/components/editor_spec.js b/spec/frontend/pipeline_wizard/components/editor_spec.js
new file mode 100644
index 00000000000..446412a4f02
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/components/editor_spec.js
@@ -0,0 +1,69 @@
+import { mount } from '@vue/test-utils';
+import { Document } from 'yaml';
+import YamlEditor from '~/pipeline_wizard/components/editor.vue';
+
+describe('Pages Yaml Editor wrapper', () => {
+ const defaultOptions = {
+ propsData: { doc: new Document({ foo: 'bar' }), filename: 'foo.yml' },
+ };
+
+ describe('mount hook', () => {
+ const wrapper = mount(YamlEditor, defaultOptions);
+
+ it('editor is mounted', () => {
+ expect(wrapper.vm.editor).not.toBeFalsy();
+ expect(wrapper.find('.gl-source-editor').exists()).toBe(true);
+ });
+ });
+
+ describe('watchers', () => {
+ describe('doc', () => {
+ const doc = new Document({ baz: ['bar'] });
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = mount(YamlEditor, defaultOptions);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it("causes the editor's value to be set to the stringified document", async () => {
+ await wrapper.setProps({ doc });
+ expect(wrapper.vm.editor.getValue()).toEqual(doc.toString());
+ });
+
+ it('emits an update:yaml event with the yaml representation of doc', async () => {
+ await wrapper.setProps({ doc });
+ const changeEvents = wrapper.emitted('update:yaml');
+ expect(changeEvents[2]).toEqual([doc.toString()]);
+ });
+
+ it('does not cause the touch event to be emitted', () => {
+ wrapper.setProps({ doc });
+ expect(wrapper.emitted('touch')).not.toBeTruthy();
+ });
+ });
+
+ describe('highlight', () => {
+ const highlight = 'foo';
+ const wrapper = mount(YamlEditor, defaultOptions);
+
+ it('calls editor.highlight(path, keep=true)', async () => {
+ const highlightSpy = jest.spyOn(wrapper.vm.yamlEditorExtension.obj, 'highlight');
+ await wrapper.setProps({ highlight });
+ expect(highlightSpy).toHaveBeenCalledWith(expect.anything(), highlight, true);
+ });
+ });
+ });
+
+ describe('events', () => {
+ const wrapper = mount(YamlEditor, defaultOptions);
+
+ it('emits touch if content is changed in editor', async () => {
+ await wrapper.vm.editor.setValue('foo: boo');
+ expect(wrapper.emitted('touch')).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_wizard/components/step_nav_spec.js b/spec/frontend/pipeline_wizard/components/step_nav_spec.js
new file mode 100644
index 00000000000..c6eac1386fa
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/components/step_nav_spec.js
@@ -0,0 +1,79 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import StepNav from '~/pipeline_wizard/components/step_nav.vue';
+
+describe('Pipeline Wizard - Step Navigation Component', () => {
+ const defaultProps = { showBackButton: true, showNextButton: true };
+
+ let wrapper;
+ let prevButton;
+ let nextButton;
+
+ const createComponent = (props = {}) => {
+ wrapper = mountExtended(StepNav, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ prevButton = wrapper.findByTestId('back-button');
+ nextButton = wrapper.findByTestId('next-button');
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ scenario | showBackButton | showNextButton
+ ${'does not show prev button'} | ${false} | ${false}
+ ${'has prev, but not next'} | ${true} | ${false}
+ ${'has next, but not prev'} | ${false} | ${true}
+ ${'has both next and prev'} | ${true} | ${true}
+ `('$scenario', async ({ showBackButton, showNextButton }) => {
+ createComponent({ showBackButton, showNextButton });
+
+ expect(prevButton.exists()).toBe(showBackButton);
+ expect(nextButton.exists()).toBe(showNextButton);
+ });
+
+ it('shows the expected button text', () => {
+ createComponent();
+
+ expect(prevButton.text()).toBe('Back');
+ expect(nextButton.text()).toBe('Next');
+ });
+
+ it('emits "back" events when clicking prev button', async () => {
+ createComponent();
+
+ await prevButton.trigger('click');
+ expect(wrapper.emitted().back.length).toBe(1);
+ });
+
+ it('emits "next" events when clicking next button', async () => {
+ createComponent();
+
+ await nextButton.trigger('click');
+ expect(wrapper.emitted().next.length).toBe(1);
+ });
+
+ it('enables the next button if nextButtonEnabled ist set to true', async () => {
+ createComponent({ nextButtonEnabled: true });
+
+ expect(nextButton.attributes('disabled')).not.toBe('disabled');
+ });
+
+ it('disables the next button if nextButtonEnabled ist set to false', async () => {
+ createComponent({ nextButtonEnabled: false });
+
+ expect(nextButton.attributes('disabled')).toBe('disabled');
+ });
+
+ it('does not emit "next" event when clicking next button while nextButtonEnabled ist set to false', async () => {
+ createComponent({ nextButtonEnabled: false });
+
+ await nextButton.trigger('click');
+
+ expect(wrapper.emitted().next).toBe(undefined);
+ });
+});
diff --git a/spec/frontend/pipeline_wizard/components/widgets/text_spec.js b/spec/frontend/pipeline_wizard/components/widgets/text_spec.js
new file mode 100644
index 00000000000..a11c0214d15
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/components/widgets/text_spec.js
@@ -0,0 +1,152 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import TextWidget from '~/pipeline_wizard/components/widgets/text.vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('Pipeline Wizard - Text Widget', () => {
+ const defaultProps = {
+ label: 'This label',
+ description: 'some description',
+ placeholder: 'some placeholder',
+ pattern: '^[a-z]+$',
+ invalidFeedback: 'some feedback',
+ };
+
+ let wrapper;
+
+ const findGlFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findGlFormGroupInvalidFeedback = () => findGlFormGroup().find('.invalid-feedback');
+ const findGlFormInput = () => wrapper.findComponent(GlFormInput);
+
+ const createComponent = (props = {}, mountFn = mountExtended) => {
+ wrapper = mountFn(TextWidget, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ it('creates an input element with the correct label', () => {
+ createComponent();
+
+ expect(wrapper.findByLabelText(defaultProps.label).exists()).toBe(true);
+ });
+
+ it('passes the description', () => {
+ createComponent({}, shallowMount);
+
+ expect(findGlFormGroup().attributes('description')).toBe(defaultProps.description);
+ });
+
+ it('sets the "text" type on the input component', () => {
+ createComponent();
+
+ expect(findGlFormInput().attributes('type')).toBe('text');
+ });
+
+ it('passes the placeholder', () => {
+ createComponent();
+
+ expect(findGlFormInput().attributes('placeholder')).toBe(defaultProps.placeholder);
+ });
+
+ it('emits an update event on input', async () => {
+ createComponent();
+
+ const localValue = 'somevalue';
+ await findGlFormInput().setValue(localValue);
+
+ expect(wrapper.emitted('input')).toEqual([[localValue]]);
+ });
+
+ it('passes invalid feedback message', () => {
+ createComponent();
+
+ expect(findGlFormGroupInvalidFeedback().text()).toBe(defaultProps.invalidFeedback);
+ });
+
+ it('provides invalid feedback', async () => {
+ createComponent({ validate: true });
+
+ await findGlFormInput().setValue('invalid%99');
+
+ expect(findGlFormGroup().classes()).toContain('is-invalid');
+ expect(findGlFormInput().classes()).toContain('is-invalid');
+ });
+
+ it('provides valid feedback', async () => {
+ createComponent({ validate: true });
+
+ await findGlFormInput().setValue('valid');
+
+ expect(findGlFormGroup().classes()).toContain('is-valid');
+ expect(findGlFormInput().classes()).toContain('is-valid');
+ });
+
+ it('does not show validation state when untouched', () => {
+ createComponent({ value: 'invalid99' });
+
+ expect(findGlFormGroup().classes()).not.toContain('is-valid');
+ expect(findGlFormGroup().classes()).not.toContain('is-invalid');
+ });
+
+ it('shows invalid state on blur', async () => {
+ createComponent();
+
+ await findGlFormInput().setValue('invalid%99');
+
+ expect(findGlFormGroup().classes()).not.toContain('is-invalid');
+
+ await findGlFormInput().trigger('blur');
+
+ expect(findGlFormInput().classes()).toContain('is-invalid');
+ expect(findGlFormGroup().classes()).toContain('is-invalid');
+ });
+
+ it('shows invalid state when toggling `validate` prop', async () => {
+ createComponent({
+ required: true,
+ validate: false,
+ });
+
+ expect(findGlFormGroup().classes()).not.toContain('is-invalid');
+
+ await wrapper.setProps({ validate: true });
+
+ expect(findGlFormGroup().classes()).toContain('is-invalid');
+ });
+
+ it('does not update validation if not required', async () => {
+ createComponent({
+ pattern: null,
+ validate: true,
+ });
+
+ expect(findGlFormGroup().classes()).not.toContain('is-invalid');
+ });
+
+ it('sets default value', () => {
+ const defaultValue = 'foo';
+ createComponent({
+ default: defaultValue,
+ });
+
+ expect(wrapper.findByLabelText(defaultProps.label).element.value).toBe(defaultValue);
+ });
+
+ it('emits default value on setup', () => {
+ const defaultValue = 'foo';
+ createComponent({
+ default: defaultValue,
+ });
+
+ expect(wrapper.emitted('input')).toEqual([[defaultValue]]);
+ });
+});
diff --git a/spec/frontend/pipeline_wizard/mock/query_responses.js b/spec/frontend/pipeline_wizard/mock/query_responses.js
new file mode 100644
index 00000000000..95dcb881a04
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/mock/query_responses.js
@@ -0,0 +1,62 @@
+export const createCommitMutationResult = {
+ data: {
+ commitCreate: {
+ commit: {
+ id: '82a9df1',
+ },
+ content: 'foo: bar',
+ errors: null,
+ },
+ },
+};
+
+export const createCommitMutationErrorResult = {
+ data: {
+ commitCreate: {
+ commit: null,
+ content: null,
+ errors: ['Some Error Message'],
+ },
+ },
+};
+
+export const fileQueryResult = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/1',
+ repository: {
+ blobs: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Blob/9ff96777b315cd37188f7194d8382c718cb2933c',
+ },
+ ],
+ },
+ },
+ },
+ },
+};
+
+export const fileQueryEmptyResult = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/2',
+ repository: {
+ blobs: {
+ nodes: [],
+ },
+ },
+ },
+ },
+};
+
+export const fileQueryErrorResult = {
+ data: {
+ foo: 'bar',
+ project: {
+ id: null,
+ repository: null,
+ },
+ },
+ errors: [{ message: 'GraphQL Error' }],
+};
diff --git a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
index 52461885342..2d2e5db598a 100644
--- a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
+++ b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
@@ -30,6 +30,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "7",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -71,6 +72,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "12",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -112,6 +114,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "17",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -153,6 +156,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "22",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -178,6 +182,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "25",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -203,6 +208,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "28",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -237,6 +243,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "60",
+ "label": null,
"tooltip": null,
},
},
@@ -295,6 +302,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "35",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -348,6 +356,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "43",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -385,6 +394,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "50",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -423,6 +433,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "64",
+ "label": null,
"tooltip": null,
},
},
diff --git a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
index 1941a7f2777..212f8e19a6d 100644
--- a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
import { singleNote, multiNote } from './mock_data';
@@ -82,26 +83,24 @@ describe('The DAG annotations', () => {
});
describe('clicking hide', () => {
- it('hides listed items and changes text to show', () => {
+ it('hides listed items and changes text to show', async () => {
expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
expect(getToggleButton().text()).toBe('Hide list');
getToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(getAllTextBlocks().length).toBe(0);
- expect(getToggleButton().text()).toBe('Show list');
- });
+ await nextTick();
+ expect(getAllTextBlocks().length).toBe(0);
+ expect(getToggleButton().text()).toBe('Show list');
});
});
describe('clicking show', () => {
- it('shows listed items and changes text to hide', () => {
+ it('shows listed items and changes text to hide', async () => {
getToggleButton().trigger('click');
getToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
- expect(getToggleButton().text()).toBe('Hide list');
- });
+ await nextTick();
+ expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
+ expect(getToggleButton().text()).toBe('Hide list');
});
});
});
diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js
index 14030930657..d78df3eb35e 100644
--- a/spec/frontend/pipelines/components/dag/dag_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlEmptyState } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from '~/pipelines/components/dag/constants';
import Dag from '~/pipelines/components/dag/dag.vue';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
@@ -153,11 +154,11 @@ describe('Pipeline DAG graph wrapper', () => {
expect(getNotes().exists()).toBe(false);
getGraph().vm.$emit('update-annotation', { type: ADD_NOTE, data: currentNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(true);
getGraph().vm.$emit('update-annotation', { type: REMOVE_NOTE, data: currentNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(false);
});
@@ -165,11 +166,11 @@ describe('Pipeline DAG graph wrapper', () => {
expect(getNotes().exists()).toBe(false);
getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: multiNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(true);
getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: {} });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(false);
});
});
diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
index 1ea6096c922..65814ad9a7f 100644
--- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
+++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
@@ -1,5 +1,6 @@
import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -9,8 +10,7 @@ import JobsTable from '~/jobs/components/table/jobs_table.vue';
import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql';
import { mockPipelineJobsQueryResponse } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
jest.mock('~/flash');
@@ -36,7 +36,6 @@ describe('Jobs app', () => {
fullPath: 'root/ci-project',
pipelineIid: 1,
},
- localVue,
apolloProvider: createMockApolloProvider(resolver),
});
};
@@ -74,16 +73,16 @@ describe('Jobs app', () => {
await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({
- message: 'An error occured while fetching the pipelines jobs.',
+ message: 'An error occurred while fetching the pipelines jobs.',
});
});
it('handles infinite scrolling by calling fetchMore', async () => {
createComponent(resolverSpy);
-
await waitForPromises();
triggerInfiniteScroll();
+ await waitForPromises();
expect(resolverSpy).toHaveBeenCalledWith({
after: 'eyJpZCI6Ijg0NyJ9',
@@ -96,10 +95,10 @@ describe('Jobs app', () => {
createComponent(resolverSpy);
expect(findSkeletonLoader().exists()).toBe(true);
-
await waitForPromises();
triggerInfiniteScroll();
+ await waitForPromises();
expect(findSkeletonLoader().exists()).toBe(false);
});
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 661c8d99477..97b59a09518 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -1,6 +1,7 @@
import { GlFilteredSearch } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue';
@@ -103,46 +104,42 @@ describe('Pipelines filtered search', () => {
expect(wrapper.emitted('filterPipelines')[0]).toEqual([mockSearch]);
});
- it('disables tag name token when branch name token is active', () => {
+ it('disables tag name token when branch name token is active', async () => {
findFilteredSearch().vm.$emit('input', [
{ type: 'ref', value: { data: 'branch-1', operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(true);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(true);
});
- it('disables branch name token when tag name token is active', () => {
+ it('disables branch name token when tag name token is active', async () => {
findFilteredSearch().vm.$emit('input', [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(true);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(true);
+ expect(findTagToken().disabled).toBe(false);
});
- it('resets tokens disabled state on clear', () => {
+ it('resets tokens disabled state on clear', async () => {
findFilteredSearch().vm.$emit('clearInput');
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(false);
});
- it('resets tokens disabled state when clearing tokens by backspace', () => {
+ it('resets tokens disabled state when clearing tokens by backspace', async () => {
findFilteredSearch().vm.$emit('input', [{ type: 'filtered-search-term', value: { data: '' } }]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(false);
});
describe('Url query params', () => {
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index 177b026491c..fab6e6887b7 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
@@ -9,6 +10,7 @@ describe('pipeline graph action component', () => {
let wrapper;
let mock;
const findButton = () => wrapper.find(GlButton);
+ const findTooltipWrapper = () => wrapper.find('[data-testid="ci-action-icon-tooltip-wrapper"]');
beforeEach(() => {
mock = new MockAdapter(axios);
@@ -30,19 +32,14 @@ describe('pipeline graph action component', () => {
});
it('should render the provided title as a bootstrap tooltip', () => {
- expect(wrapper.attributes('title')).toBe('bar');
+ expect(findTooltipWrapper().attributes('title')).toBe('bar');
});
- it('should update bootstrap tooltip when title changes', (done) => {
+ it('should update bootstrap tooltip when title changes', async () => {
wrapper.setProps({ tooltipText: 'changed' });
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.attributes('title')).toBe('changed');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findTooltipWrapper().attributes('title')).toBe('changed');
});
it('should render an svg', () => {
@@ -64,13 +61,11 @@ describe('pipeline graph action component', () => {
.catch(done.fail);
});
- it('renders a loading icon while waiting for request', (done) => {
+ it('renders a loading icon while waiting for request', async () => {
findButton().trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true);
- done();
- });
+ await nextTick();
+ expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 04e004dc6c1..8bc6c086b9d 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -1,10 +1,11 @@
import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
import axios from '~/lib/utils/axios_utils';
@@ -100,15 +101,6 @@ describe('Pipeline graph wrapper', () => {
wrapper.destroy();
});
- beforeAll(() => {
- jest.useFakeTimers();
- });
-
- afterAll(() => {
- jest.runOnlyPendingTimers();
- jest.useRealTimers();
- });
-
describe('when data is loading', () => {
it('displays the loading icon', () => {
createComponentWithApollo();
@@ -134,8 +126,7 @@ describe('Pipeline graph wrapper', () => {
describe('when data has loaded', () => {
beforeEach(async () => {
createComponentWithApollo();
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -163,8 +154,7 @@ describe('Pipeline graph wrapper', () => {
createComponentWithApollo({
getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -187,8 +177,7 @@ describe('Pipeline graph wrapper', () => {
pipelineIid: '',
},
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -210,7 +199,7 @@ describe('Pipeline graph wrapper', () => {
createComponentWithApollo();
jest.spyOn(wrapper.vm.$apollo.queries.headerPipeline, 'refetch');
jest.spyOn(wrapper.vm.$apollo.queries.pipeline, 'refetch');
- await nextTick();
+ await waitForPromises();
getGraph().vm.$emit('refreshPipelineGraph');
});
@@ -224,8 +213,7 @@ describe('Pipeline graph wrapper', () => {
describe('when query times out', () => {
const advanceApolloTimers = async () => {
jest.runOnlyPendingTimers();
- await nextTick();
- await nextTick();
+ await waitForPromises();
};
beforeEach(async () => {
@@ -245,7 +233,7 @@ describe('Pipeline graph wrapper', () => {
.mockResolvedValueOnce(errorData);
createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail });
- await nextTick();
+ await waitForPromises();
});
it('shows correct errors and does not overwrite populated data when data is empty', async () => {
@@ -274,8 +262,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('appears when pipeline uses needs', () => {
@@ -318,7 +305,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('sets showLinks to true', async () => {
@@ -327,8 +314,9 @@ describe('Pipeline graph wrapper', () => {
expect(getLinksLayer().props('showLinks')).toBe(false);
expect(getViewSelector().props('type')).toBe(LAYER_VIEW);
await getDependenciesToggle().vm.$emit('change', true);
+
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true);
});
});
@@ -343,8 +331,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('shows the hover tip in the view selector', async () => {
@@ -365,7 +352,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not show the hover tip', async () => {
@@ -382,8 +369,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
afterEach(() => {
@@ -411,8 +397,7 @@ describe('Pipeline graph wrapper', () => {
getPipelineDetailsHandler: jest.fn().mockResolvedValue(nonNeedsResponse),
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
afterEach(() => {
@@ -435,7 +420,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not appear when pipeline does not use needs', () => {
@@ -461,8 +446,7 @@ describe('Pipeline graph wrapper', () => {
describe('with no metrics path', () => {
beforeEach(async () => {
createComponentWithApollo();
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('is not called', () => {
@@ -505,8 +489,7 @@ describe('Pipeline graph wrapper', () => {
},
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('attempts to collect metrics', () => {
@@ -517,7 +500,7 @@ describe('Pipeline graph wrapper', () => {
});
describe('with duration and no error', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mock = new MockAdapter(axios);
mock.onPost(metricsPath).reply(200, {});
@@ -536,6 +519,7 @@ describe('Pipeline graph wrapper', () => {
currentViewType: LAYER_VIEW,
},
});
+ await waitForPromises();
});
afterEach(() => {
diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js
index 06f1fa4c827..23e7ed7ebb4 100644
--- a/spec/frontend/pipelines/graph/job_item_spec.js
+++ b/spec/frontend/pipelines/graph/job_item_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import JobItem from '~/pipelines/components/graph/job_item.vue';
describe('pipeline graph job item', () => {
@@ -6,6 +7,7 @@ describe('pipeline graph job item', () => {
const findJobWithoutLink = () => wrapper.find('[data-testid="job-without-link"]');
const findJobWithLink = () => wrapper.find('[data-testid="job-with-link"]');
+ const findActionComponent = () => wrapper.find('[data-testid="ci-action-component"]');
const createWrapper = (propsData) => {
wrapper = mount(JobItem, {
@@ -68,28 +70,38 @@ describe('pipeline graph job item', () => {
hasDetails: false,
},
};
+ const mockJobWithUnauthorizedAction = {
+ id: 4258,
+ name: 'stop-environment',
+ status: {
+ icon: 'status_manual',
+ label: 'manual stop action (not allowed)',
+ tooltip: 'manual action',
+ group: 'manual',
+ detailsPath: '/root/ci-mock/builds/4258',
+ hasDetails: true,
+ action: null,
+ },
+ };
afterEach(() => {
wrapper.destroy();
});
describe('name with link', () => {
- it('should render the job name and status with a link', (done) => {
+ it('should render the job name and status with a link', async () => {
createWrapper({ job: mockJob });
- wrapper.vm.$nextTick(() => {
- const link = wrapper.find('a');
-
- expect(link.attributes('href')).toBe(mockJob.status.detailsPath);
+ await nextTick();
+ const link = wrapper.find('a');
- expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`);
+ expect(link.attributes('href')).toBe(mockJob.status.detailsPath);
- expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
+ expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`);
- expect(wrapper.text()).toBe(mockJob.name);
+ expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
- done();
- });
+ expect(wrapper.text()).toBe(mockJob.name);
});
});
@@ -118,8 +130,21 @@ describe('pipeline graph job item', () => {
it('it should render the action icon', () => {
createWrapper({ job: mockJob });
- expect(wrapper.find('.ci-action-icon-container').exists()).toBe(true);
- expect(wrapper.find('.ci-action-icon-wrapper').exists()).toBe(true);
+ const actionComponent = findActionComponent();
+
+ expect(actionComponent.exists()).toBe(true);
+ expect(actionComponent.props('actionIcon')).toBe('retry');
+ expect(actionComponent.attributes('disabled')).not.toBe('disabled');
+ });
+
+ it('it should render disabled action icon when user cannot run the action', () => {
+ createWrapper({ job: mockJobWithUnauthorizedAction });
+
+ const actionComponent = findActionComponent();
+
+ expect(actionComponent.exists()).toBe(true);
+ expect(actionComponent.props('actionIcon')).toBe('stop');
+ expect(actionComponent.attributes('disabled')).toBe('disabled');
});
});
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index af5cd907dd8..d800a8c341e 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -9,6 +9,23 @@ import mockPipeline from './linked_pipelines_mock_data';
describe('Linked pipeline', () => {
let wrapper;
+ const downstreamProps = {
+ pipeline: {
+ ...mockPipeline,
+ multiproject: false,
+ },
+ columnTitle: 'Downstream',
+ type: DOWNSTREAM,
+ expanded: false,
+ isLoading: false,
+ };
+
+ const upstreamProps = {
+ ...downstreamProps,
+ columnTitle: 'Upstream',
+ type: UPSTREAM,
+ };
+
const findButton = () => wrapper.find(GlButton);
const findDownstreamPipelineTitle = () => wrapper.find('[data-testid="downstream-title"]');
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]');
@@ -86,91 +103,65 @@ describe('Linked pipeline', () => {
});
});
- describe('parent/child', () => {
- const downstreamProps = {
- pipeline: {
- ...mockPipeline,
- multiproject: false,
- },
- columnTitle: 'Downstream',
- type: DOWNSTREAM,
- expanded: false,
- isLoading: false,
- };
+ describe('upstream pipelines', () => {
+ beforeEach(() => {
+ createWrapper(upstreamProps);
+ });
- const upstreamProps = {
- ...downstreamProps,
- columnTitle: 'Upstream',
- type: UPSTREAM,
- };
+ it('should display parent label when pipeline project id is the same as triggered_by pipeline project id', () => {
+ expect(findPipelineLabel().exists()).toBe(true);
+ });
- it('parent/child label container should exist', () => {
+ it('upstream pipeline should contain the correct link', () => {
+ expect(findPipelineLink().attributes('href')).toBe(upstreamProps.pipeline.path);
+ });
+
+ it('applies the reverse-row css class to the card', () => {
+ expect(findLinkedPipeline().classes()).toContain('gl-flex-direction-row-reverse');
+ expect(findLinkedPipeline().classes()).not.toContain('gl-flex-direction-row');
+ });
+ });
+
+ describe('downstream pipelines', () => {
+ beforeEach(() => {
createWrapper(downstreamProps);
+ });
+
+ it('parent/child label container should exist', () => {
expect(findPipelineLabel().exists()).toBe(true);
});
it('should display child label when pipeline project id is the same as triggered pipeline project id', () => {
- createWrapper(downstreamProps);
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.sourceJob.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);
- });
-
it('downstream pipeline should contain the correct link', () => {
- createWrapper(downstreamProps);
expect(findPipelineLink().attributes('href')).toBe(downstreamProps.pipeline.path);
});
- it('upstream pipeline should contain the correct link', () => {
- createWrapper(upstreamProps);
- expect(findPipelineLink().attributes('href')).toBe(upstreamProps.pipeline.path);
+ it('applies the flex-row css class to the card', () => {
+ expect(findLinkedPipeline().classes()).toContain('gl-flex-direction-row');
+ expect(findLinkedPipeline().classes()).not.toContain('gl-flex-direction-row-reverse');
});
+ });
+ describe('expand button', () => {
it.each`
- presentClass | missingClass
- ${'gl-right-0'} | ${'gl-left-0'}
- ${'gl-border-l-1!'} | ${'gl-border-r-1!'}
- `(
- 'pipeline expand button should be postioned right when child pipeline',
- ({ presentClass, missingClass }) => {
- createWrapper(downstreamProps);
- expect(findExpandButton().classes()).toContain(presentClass);
- expect(findExpandButton().classes()).not.toContain(missingClass);
- },
- );
-
- it.each`
- presentClass | missingClass
- ${'gl-left-0'} | ${'gl-right-0'}
- ${'gl-border-r-1!'} | ${'gl-border-l-1!'}
- `(
- 'pipeline expand button should be postioned left when parent pipeline',
- ({ presentClass, missingClass }) => {
- createWrapper(upstreamProps);
- expect(findExpandButton().classes()).toContain(presentClass);
- expect(findExpandButton().classes()).not.toContain(missingClass);
- },
- );
-
- it.each`
- pipelineType | anglePosition | expanded
- ${downstreamProps} | ${'angle-right'} | ${false}
- ${downstreamProps} | ${'angle-left'} | ${true}
- ${upstreamProps} | ${'angle-left'} | ${false}
- ${upstreamProps} | ${'angle-right'} | ${true}
+ pipelineType | anglePosition | borderClass | expanded
+ ${downstreamProps} | ${'angle-right'} | ${'gl-border-l-1!'} | ${false}
+ ${downstreamProps} | ${'angle-left'} | ${'gl-border-l-1!'} | ${true}
+ ${upstreamProps} | ${'angle-left'} | ${'gl-border-r-1!'} | ${false}
+ ${upstreamProps} | ${'angle-right'} | ${'gl-border-r-1!'} | ${true}
`(
- '$pipelineType.columnTitle pipeline button icon should be $anglePosition if expanded state is $expanded',
- ({ pipelineType, anglePosition, expanded }) => {
+ '$pipelineType.columnTitle pipeline button icon should be $anglePosition with $borderClass if expanded state is $expanded',
+ ({ pipelineType, anglePosition, borderClass, expanded }) => {
createWrapper({ ...pipelineType, expanded });
expect(findExpandButton().props('icon')).toBe(anglePosition);
+ expect(findExpandButton().classes()).toContain(borderClass);
},
);
});
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 2f03b846525..1673065e09c 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -1,6 +1,8 @@
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+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 getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import {
DOWNSTREAM,
@@ -40,13 +42,11 @@ describe('Linked Pipelines Column', () => {
const findPipelineGraph = () => wrapper.find(PipelineGraph);
const findExpandButton = () => wrapper.find('[data-testid="expand-pipeline-button"]');
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const createComponent = ({ apolloProvider, mountFn = shallowMount, props = {} } = {}) => {
wrapper = mountFn(LinkedPipelinesColumn, {
apolloProvider,
- localVue,
propsData: {
...defaultProps,
...props,
@@ -87,13 +87,7 @@ describe('Linked Pipelines Column', () => {
describe('click action', () => {
const clickExpandButton = async () => {
await findExpandButton().trigger('click');
- await wrapper.vm.$nextTick();
- };
-
- const clickExpandButtonAndAwaitTimers = async () => {
- await clickExpandButton();
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await waitForPromises();
};
describe('layer type rendering', () => {
@@ -106,9 +100,9 @@ describe('Linked Pipelines Column', () => {
it('calls listByLayers only once no matter how many times view is switched', async () => {
expect(layersFn).not.toHaveBeenCalled();
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
await wrapper.setProps({ viewType: LAYER_VIEW });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(layersFn).toHaveBeenCalledTimes(1);
await wrapper.setProps({ viewType: STAGE_VIEW });
await wrapper.setProps({ viewType: LAYER_VIEW });
@@ -132,7 +126,7 @@ describe('Linked Pipelines Column', () => {
});
it('shows the stage view, even when the main graph view type is layers', async () => {
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().props('viewType')).toBe(STAGE_VIEW);
});
});
@@ -145,7 +139,7 @@ describe('Linked Pipelines Column', () => {
it('toggles the pipeline visibility', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(true);
await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
@@ -167,7 +161,7 @@ describe('Linked Pipelines Column', () => {
it('does not show the pipeline', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
});
});
@@ -195,7 +189,7 @@ describe('Linked Pipelines Column', () => {
it('toggles the pipeline visibility', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(true);
await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
@@ -218,7 +212,7 @@ describe('Linked Pipelines Column', () => {
it('does not show the pipeline', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
});
});
diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js
index 41823bfdb9f..0cf7dc507f4 100644
--- a/spec/frontend/pipelines/graph/mock_data.js
+++ b/spec/frontend/pipelines/graph/mock_data.js
@@ -57,6 +57,7 @@ export const mockPipelineResponse = {
id: '7',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1482',
group: 'success',
@@ -106,6 +107,7 @@ export const mockPipelineResponse = {
id: '12',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1515',
group: 'success',
@@ -155,6 +157,7 @@ export const mockPipelineResponse = {
id: '17',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1484',
group: 'success',
@@ -204,6 +207,7 @@ export const mockPipelineResponse = {
id: '22',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1485',
group: 'success',
@@ -235,6 +239,7 @@ export const mockPipelineResponse = {
id: '25',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1486',
group: 'success',
@@ -266,6 +271,7 @@ export const mockPipelineResponse = {
id: '28',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1487',
group: 'success',
@@ -330,6 +336,7 @@ export const mockPipelineResponse = {
id: '35',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1514',
group: 'success',
@@ -413,6 +420,7 @@ export const mockPipelineResponse = {
id: '43',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1489',
group: 'success',
@@ -498,6 +506,7 @@ export const mockPipelineResponse = {
id: '50',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1490',
group: 'success',
@@ -601,6 +610,7 @@ export const mockPipelineResponse = {
id: '60',
icon: 'status_success',
tooltip: null,
+ label: null,
hasDetails: true,
detailsPath: '/root/kinder-pipe/-/pipelines/154',
group: 'success',
@@ -643,6 +653,7 @@ export const mockPipelineResponse = {
id: '64',
icon: 'status_success',
tooltip: null,
+ label: null,
hasDetails: true,
detailsPath: '/root/abcd-dag/-/pipelines/153',
group: 'success',
@@ -850,6 +861,7 @@ export const wrappedPipelineReturn = {
id: '84',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/elemenohpee/-/jobs/1662',
group: 'success',
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
index 9e51003da66..1d89f949564 100644
--- a/spec/frontend/pipelines/header_component_spec.js
+++ b/spec/frontend/pipelines/header_component_spec.js
@@ -4,6 +4,7 @@ import HeaderComponent from '~/pipelines/components/header_component.vue';
import cancelPipelineMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
import deletePipelineMutation from '~/pipelines/graphql/mutations/delete_pipeline.mutation.graphql';
import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
+import { BUTTON_TOOLTIP_RETRY } from '~/pipelines/constants';
import {
mockCancelledPipelineHeader,
mockFailedPipelineHeader,
@@ -113,6 +114,10 @@ describe('Pipeline details header', () => {
variables: { id: mockCancelledPipelineHeader.id },
});
});
+
+ it('should render retry action tooltip', () => {
+ expect(findRetryButton().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
+ });
});
describe('Cancel action', () => {
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index b9d20eb7ca5..8cb6cf3bed6 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -634,3 +634,683 @@ export const mockPipelineJobsQueryResponse = {
},
},
};
+
+export const mockPipeline = (projectPath) => {
+ return {
+ pipeline: {
+ id: 1,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: '',
+ web_url: 'http://0.0.0.0:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'merge_request_event',
+ created_at: '2021-10-19T21:17:38.698Z',
+ updated_at: '2021-10-21T18:00:42.758Z',
+ path: 'foo',
+ flags: {},
+ merge_request: {
+ iid: 1,
+ path: `/${projectPath}/1`,
+ title: 'commit',
+ source_branch: 'test-commit-name',
+ source_branch_path: `/${projectPath}`,
+ target_branch: 'main',
+ target_branch_path: `/${projectPath}/-/commit/main`,
+ },
+ ref: {
+ name: 'refs/merge-requests/1/head',
+ path: `/${projectPath}/-/commits/refs/merge-requests/1/head`,
+ tag: false,
+ branch: false,
+ merge_request: true,
+ },
+ commit: {
+ id: 'fd6df5b3229e213c97d308844a6f3e7fd71e8f8c',
+ short_id: 'fd6df5b3',
+ created_at: '2021-10-19T21:17:12.000+00:00',
+ parent_ids: ['7147906b84306e83cb3fec6582a25390b75713c6'],
+ title: 'Commit Title',
+ message: 'Commit',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2021-10-19T21:17:12.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2021-10-19T21:17:12.000+00:00',
+ trailers: {},
+ web_url: '',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: '',
+ web_url: '',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url: '',
+ commit_url: `/${projectPath}/fd6df5b3229e213c97d308844a6f3e7fd71e8f8c`,
+ commit_path: `/${projectPath}/commit/fd6df5b3229e213c97d308844a6f3e7fd71e8f8c`,
+ },
+ project: {
+ full_path: `/${projectPath}`,
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineTag = () => {
+ return {
+ pipeline: {
+ id: 311,
+ iid: 37,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-02-02T15:39:04.012Z',
+ updated_at: '2022-02-02T15:40:59.573Z',
+ path: '/root/mr-widgets/-/pipelines/311',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'accessibility',
+ title: 'accessibility: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#accessibility',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#accessibility',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=accessibility',
+ },
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=build',
+ },
+ ],
+ duration: 93,
+ finished_at: '2022-02-02T15:40:59.384Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'test',
+ path: '/root/mr-widgets/-/commits/test',
+ tag: true,
+ branch: false,
+ merge_request: false,
+ },
+ commit: {
+ id: '9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ short_id: '9b92b4f7',
+ created_at: '2022-01-13T13:59:03.000+00:00',
+ parent_ids: ['0ba763634114e207dc72c65c8e9459556b1204fb'],
+ title: 'Update hello_world.js',
+ message: 'Update hello_world.js',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2022-01-13T13:59:03.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2022-01-13T13:59:03.000+00:00',
+ trailers: {},
+ web_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ author: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commit_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ commit_path: '/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/311/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/311',
+ failed_builds: [
+ {
+ id: 1696,
+ name: 'fmt',
+ started: '2022-02-02T15:39:45.192Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1696',
+ retry_path: '/root/mr-widgets/-/jobs/1696/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-02-02T15:39:04.136Z',
+ updated_at: '2022-02-02T15:39:57.969Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1696',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1696/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineBranch = () => {
+ return {
+ pipeline: {
+ id: 268,
+ iid: 34,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-01-14T17:40:27.866Z',
+ updated_at: '2022-01-14T18:02:35.850Z',
+ path: '/root/mr-widgets/-/pipelines/268',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
+ },
+ ],
+ duration: 75,
+ finished_at: '2022-01-14T18:02:35.842Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'update-ci',
+ path: '/root/mr-widgets/-/commits/update-ci',
+ tag: false,
+ branch: true,
+ merge_request: false,
+ },
+ commit: {
+ id: '96aef9ecec5752c09371c1ade5fc77860aafc863',
+ short_id: '96aef9ec',
+ created_at: '2022-01-14T17:40:26.000+00:00',
+ parent_ids: ['06860257572d4cf84b73806250b78169050aed83'],
+ title: 'Update main.tf',
+ message: 'Update main.tf',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2022-01-14T17:40:26.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2022-01-14T17:40:26.000+00:00',
+ trailers: {},
+ web_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ author: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commit_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ commit_path: '/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/268/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/268',
+ failed_builds: [
+ {
+ id: 1260,
+ name: 'fmt',
+ started: '2022-01-14T17:40:36.435Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1260',
+ retry_path: '/root/mr-widgets/-/jobs/1260/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-01-14T17:40:27.879Z',
+ updated_at: '2022-01-14T17:40:42.129Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1260',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1260/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineNoCommit = () => {
+ return {
+ pipeline: {
+ id: 268,
+ iid: 34,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-01-14T17:40:27.866Z',
+ updated_at: '2022-01-14T18:02:35.850Z',
+ path: '/root/mr-widgets/-/pipelines/268',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
+ },
+ ],
+ duration: 75,
+ finished_at: '2022-01-14T18:02:35.842Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'update-ci',
+ path: '/root/mr-widgets/-/commits/update-ci',
+ tag: false,
+ branch: true,
+ merge_request: false,
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/268/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/268',
+ failed_builds: [
+ {
+ id: 1260,
+ name: 'fmt',
+ started: '2022-01-14T17:40:36.435Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1260',
+ retry_path: '/root/mr-widgets/-/jobs/1260/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-01-14T17:40:27.879Z',
+ updated_at: '2022-01-14T17:40:42.129Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1260',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1260/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
diff --git a/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js b/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js
new file mode 100644
index 00000000000..f626652a944
--- /dev/null
+++ b/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js
@@ -0,0 +1,146 @@
+import VueApollo from 'vue-apollo';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import DeprecatedTypeKeywordNotification from '~/pipelines/components/notification/deprecated_type_keyword_notification.vue';
+import getPipelineWarnings from '~/pipelines/graphql/queries/get_pipeline_warnings.query.graphql';
+import {
+ mockWarningsWithoutDeprecation,
+ mockWarningsRootType,
+ mockWarningsType,
+ mockWarningsTypesAll,
+} from './mock_data';
+
+const defaultProvide = {
+ deprecatedKeywordsDocPath: '/help/ci/yaml/index.md#deprecated-keywords',
+ fullPath: '/namespace/my-project',
+ pipelineIid: 4,
+};
+
+let wrapper;
+
+const mockWarnings = jest.fn();
+
+const createComponent = ({ isLoading = false, options = {} } = {}) => {
+ return shallowMount(DeprecatedTypeKeywordNotification, {
+ stubs: {
+ GlSprintf,
+ },
+ provide: {
+ ...defaultProvide,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ warnings: {
+ loading: isLoading,
+ },
+ },
+ },
+ },
+ ...options,
+ });
+};
+
+const createComponentWithApollo = () => {
+ const localVue = createLocalVue();
+ localVue.use(VueApollo);
+
+ const handlers = [[getPipelineWarnings, mockWarnings]];
+ const mockApollo = createMockApollo(handlers);
+
+ return createComponent({
+ options: {
+ localVue,
+ apolloProvider: mockApollo,
+ mocks: {},
+ },
+ });
+};
+
+const findAlert = () => wrapper.findComponent(GlAlert);
+const findAlertItems = () => findAlert().findAll('li');
+
+afterEach(() => {
+ wrapper.destroy();
+});
+
+describe('Deprecated keyword notification', () => {
+ describe('while loading the pipeline warnings', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ isLoading: true });
+ });
+
+ it('does not display the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('if there is an error in the query', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue({ errors: ['It didnt work'] });
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('does not display the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('with a valid query result', () => {
+ describe('if there are no deprecation warnings', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsWithoutDeprecation);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('does not show the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('with a root type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsRootType);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with one item', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(1);
+ expect(findAlertItems().at(0).text()).toContain('types');
+ });
+ });
+
+ describe('with a job type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsType);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with one item', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(1);
+ expect(findAlertItems().at(0).text()).toContain('type');
+ expect(findAlertItems().at(0).text()).not.toContain('types');
+ });
+ });
+
+ describe('with both the root types and job type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsTypesAll);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with two items', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(2);
+ expect(findAlertItems().at(0).text()).toContain('types');
+ expect(findAlertItems().at(1).text()).toContain('type');
+ expect(findAlertItems().at(1).text()).not.toContain('types');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/notification/mock_data.js b/spec/frontend/pipelines/notification/mock_data.js
new file mode 100644
index 00000000000..e36f391a854
--- /dev/null
+++ b/spec/frontend/pipelines/notification/mock_data.js
@@ -0,0 +1,33 @@
+const randomWarning = {
+ content: 'another random warning',
+ id: 'gid://gitlab/Ci::PipelineMessage/272',
+};
+
+const rootTypeWarning = {
+ content: 'root `types` will be removed in 15.0.',
+ id: 'gid://gitlab/Ci::PipelineMessage/273',
+};
+
+const typeWarning = {
+ content: '`type` will be removed in 15.0.',
+ id: 'gid://gitlab/Ci::PipelineMessage/274',
+};
+
+function createWarningMock(warnings) {
+ return {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/28"',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/183',
+ warningMessages: warnings,
+ },
+ },
+ },
+ };
+}
+
+export const mockWarningsWithoutDeprecation = createWarningMock([randomWarning]);
+export const mockWarningsRootType = createWarningMock([rootTypeWarning]);
+export const mockWarningsType = createWarningMock([typeWarning]);
+export const mockWarningsTypesAll = createWarningMock([rootTypeWarning, typeWarning]);
diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js
index ffb2721f159..701b1691c7b 100644
--- a/spec/frontend/pipelines/pipeline_triggerer_spec.js
+++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import pipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_triggerer.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -47,15 +48,14 @@ describe('Pipelines Triggerer', () => {
});
});
- it('should render "API" when no triggerer is provided', () => {
+ it('should render "API" when no triggerer is provided', async () => {
wrapper.setProps({
pipeline: {
user: null,
},
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
- });
+ await nextTick();
+ expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
});
});
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index 912b5afe0e1..b24e2e09ea8 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -1,41 +1,48 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { trimText } from 'helpers/text_helper';
import PipelineUrlComponent from '~/pipelines/components/pipelines_list/pipeline_url.vue';
+import {
+ mockPipeline,
+ mockPipelineBranch,
+ mockPipelineTag,
+ mockPipelineNoCommit,
+} from './mock_data';
const projectPath = 'test/test';
describe('Pipeline Url Component', () => {
let wrapper;
- const findTableCell = () => wrapper.find('[data-testid="pipeline-url-table-cell"]');
- const findPipelineUrlLink = () => wrapper.find('[data-testid="pipeline-url-link"]');
- const findScheduledTag = () => wrapper.find('[data-testid="pipeline-url-scheduled"]');
- const findLatestTag = () => wrapper.find('[data-testid="pipeline-url-latest"]');
- const findYamlTag = () => wrapper.find('[data-testid="pipeline-url-yaml"]');
- const findFailureTag = () => wrapper.find('[data-testid="pipeline-url-failure"]');
- const findAutoDevopsTag = () => wrapper.find('[data-testid="pipeline-url-autodevops"]');
- const findAutoDevopsTagLink = () => wrapper.find('[data-testid="pipeline-url-autodevops-link"]');
- const findStuckTag = () => wrapper.find('[data-testid="pipeline-url-stuck"]');
- const findDetachedTag = () => wrapper.find('[data-testid="pipeline-url-detached"]');
- const findForkTag = () => wrapper.find('[data-testid="pipeline-url-fork"]');
- const findTrainTag = () => wrapper.find('[data-testid="pipeline-url-train"]');
-
- const defaultProps = {
- pipeline: {
- id: 1,
- path: 'foo',
- project: { full_path: `/${projectPath}` },
- flags: {},
- },
- pipelineScheduleUrl: 'foo',
- pipelineKey: 'id',
- };
-
- const createComponent = (props) => {
- wrapper = shallowMount(PipelineUrlComponent, {
+ const findTableCell = () => wrapper.findByTestId('pipeline-url-table-cell');
+ const findPipelineUrlLink = () => wrapper.findByTestId('pipeline-url-link');
+ const findScheduledTag = () => wrapper.findByTestId('pipeline-url-scheduled');
+ const findLatestTag = () => wrapper.findByTestId('pipeline-url-latest');
+ const findYamlTag = () => wrapper.findByTestId('pipeline-url-yaml');
+ const findFailureTag = () => wrapper.findByTestId('pipeline-url-failure');
+ const findAutoDevopsTag = () => wrapper.findByTestId('pipeline-url-autodevops');
+ const findAutoDevopsTagLink = () => wrapper.findByTestId('pipeline-url-autodevops-link');
+ const findStuckTag = () => wrapper.findByTestId('pipeline-url-stuck');
+ const findDetachedTag = () => wrapper.findByTestId('pipeline-url-detached');
+ const findForkTag = () => wrapper.findByTestId('pipeline-url-fork');
+ const findTrainTag = () => wrapper.findByTestId('pipeline-url-train');
+ const findRefName = () => wrapper.findByTestId('merge-request-ref');
+ const findCommitShortSha = () => wrapper.findByTestId('commit-short-sha');
+ const findCommitIcon = () => wrapper.findByTestId('commit-icon');
+ const findCommitIconType = () => wrapper.findByTestId('commit-icon-type');
+
+ const findCommitTitleContainer = () => wrapper.findByTestId('commit-title-container');
+ const findCommitTitle = () => wrapper.findByTestId('commit-title');
+
+ const defaultProps = mockPipeline(projectPath);
+
+ const createComponent = (props, rearrangePipelinesTable = false) => {
+ wrapper = shallowMountExtended(PipelineUrlComponent, {
propsData: { ...defaultProps, ...props },
provide: {
targetProjectFullPath: projectPath,
+ glFeatures: {
+ rearrangePipelinesTable,
+ },
},
});
};
@@ -45,158 +52,218 @@ describe('Pipeline Url Component', () => {
wrapper = null;
});
- it('should render pipeline url table cell', () => {
- createComponent();
+ describe('with the rearrangePipelinesTable feature flag turned off', () => {
+ it('should render pipeline url table cell', () => {
+ createComponent();
- expect(findTableCell().exists()).toBe(true);
- });
+ expect(findTableCell().exists()).toBe(true);
+ });
- it('should render a link the provided path and id', () => {
- createComponent();
+ it('should render a link the provided path and id', () => {
+ createComponent();
- expect(findPipelineUrlLink().attributes('href')).toBe('foo');
+ expect(findPipelineUrlLink().attributes('href')).toBe('foo');
- expect(findPipelineUrlLink().text()).toBe('#1');
- });
+ expect(findPipelineUrlLink().text()).toBe('#1');
+ });
- it('should not render tags when flags are not set', () => {
- createComponent();
-
- expect(findStuckTag().exists()).toBe(false);
- expect(findLatestTag().exists()).toBe(false);
- expect(findYamlTag().exists()).toBe(false);
- expect(findAutoDevopsTag().exists()).toBe(false);
- expect(findFailureTag().exists()).toBe(false);
- expect(findScheduledTag().exists()).toBe(false);
- expect(findForkTag().exists()).toBe(false);
- expect(findTrainTag().exists()).toBe(false);
- });
+ it('should not render tags when flags are not set', () => {
+ createComponent();
+
+ expect(findStuckTag().exists()).toBe(false);
+ expect(findLatestTag().exists()).toBe(false);
+ expect(findYamlTag().exists()).toBe(false);
+ expect(findAutoDevopsTag().exists()).toBe(false);
+ expect(findFailureTag().exists()).toBe(false);
+ expect(findScheduledTag().exists()).toBe(false);
+ expect(findForkTag().exists()).toBe(false);
+ expect(findTrainTag().exists()).toBe(false);
+ });
- it('should render the stuck tag when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- stuck: true,
- },
- },
+ it('should render the stuck tag when flag is provided', () => {
+ const stuckPipeline = defaultProps.pipeline;
+ stuckPipeline.flags.stuck = true;
+
+ createComponent({
+ ...stuckPipeline.pipeline,
+ });
+
+ expect(findStuckTag().text()).toContain('stuck');
});
- expect(findStuckTag().text()).toContain('stuck');
- });
+ it('should render latest tag when flag is provided', () => {
+ const latestPipeline = defaultProps.pipeline;
+ latestPipeline.flags.latest = true;
- it('should render latest tag when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- latest: true,
- },
- },
+ createComponent({
+ ...latestPipeline,
+ });
+
+ expect(findLatestTag().text()).toContain('latest');
});
- expect(findLatestTag().text()).toContain('latest');
- });
+ it('should render a yaml badge when it is invalid', () => {
+ const yamlPipeline = defaultProps.pipeline;
+ yamlPipeline.flags.yaml_errors = true;
- it('should render a yaml badge when it is invalid', () => {
- createComponent({
- pipeline: {
- flags: {
- yaml_errors: true,
- },
- },
+ createComponent({
+ ...yamlPipeline,
+ });
+
+ expect(findYamlTag().text()).toContain('yaml invalid');
});
- expect(findYamlTag().text()).toContain('yaml invalid');
- });
+ it('should render an autodevops badge when flag is provided', () => {
+ const autoDevopsPipeline = defaultProps.pipeline;
+ autoDevopsPipeline.flags.auto_devops = true;
- it('should render an autodevops badge when flag is provided', () => {
- createComponent({
- pipeline: {
- ...defaultProps.pipeline,
- flags: {
- auto_devops: true,
- },
- },
+ createComponent({
+ ...autoDevopsPipeline,
+ });
+
+ expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
+
+ expect(findAutoDevopsTagLink().attributes()).toMatchObject({
+ href: '/help/topics/autodevops/index.md',
+ target: '_blank',
+ });
});
- expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
+ it('should render a detached badge when flag is provided', () => {
+ const detachedMRPipeline = defaultProps.pipeline;
+ detachedMRPipeline.flags.detached_merge_request_pipeline = true;
- expect(findAutoDevopsTagLink().attributes()).toMatchObject({
- href: '/help/topics/autodevops/index.md',
- target: '_blank',
+ createComponent({
+ ...detachedMRPipeline,
+ });
+
+ expect(findDetachedTag().text()).toContain('detached');
});
- });
- it('should render a detached badge when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- detached_merge_request_pipeline: true,
- },
- },
+ it('should render error badge when pipeline has a failure reason set', () => {
+ const failedPipeline = defaultProps.pipeline;
+ failedPipeline.flags.failure_reason = true;
+ failedPipeline.failure_reason = 'some reason';
+
+ createComponent({
+ ...failedPipeline,
+ });
+
+ expect(findFailureTag().text()).toContain('error');
+ expect(findFailureTag().attributes('title')).toContain('some reason');
});
- expect(findDetachedTag().text()).toContain('detached');
- });
+ it('should render scheduled badge when pipeline was triggered by a schedule', () => {
+ const scheduledPipeline = defaultProps.pipeline;
+ scheduledPipeline.source = 'schedule';
- it('should render error badge when pipeline has a failure reason set', () => {
- createComponent({
- pipeline: {
- flags: {
- failure_reason: true,
- },
- failure_reason: 'some reason',
- },
+ createComponent({
+ ...scheduledPipeline,
+ });
+
+ expect(findScheduledTag().exists()).toBe(true);
+ expect(findScheduledTag().text()).toContain('Scheduled');
});
- expect(findFailureTag().text()).toContain('error');
- expect(findFailureTag().attributes('title')).toContain('some reason');
- });
+ it('should render the fork badge when the pipeline was run in a fork', () => {
+ const forkedPipeline = defaultProps.pipeline;
+ forkedPipeline.project.full_path = '/test/forked';
- it('should render scheduled badge when pipeline was triggered by a schedule', () => {
- createComponent({
- pipeline: {
- flags: {},
- source: 'schedule',
- },
+ createComponent({
+ ...forkedPipeline,
+ });
+
+ expect(findForkTag().exists()).toBe(true);
+ expect(findForkTag().text()).toBe('fork');
});
- expect(findScheduledTag().exists()).toBe(true);
- expect(findScheduledTag().text()).toContain('Scheduled');
- });
+ it('should render the train badge when the pipeline is a merge train pipeline', () => {
+ const mergeTrainPipeline = defaultProps.pipeline;
+ mergeTrainPipeline.flags.merge_train_pipeline = true;
- it('should render the fork badge when the pipeline was run in a fork', () => {
- createComponent({
- pipeline: {
- flags: {},
- project: { fullPath: '/test/forked' },
- },
+ createComponent({
+ ...mergeTrainPipeline,
+ });
+
+ expect(findTrainTag().text()).toContain('train');
});
- expect(findForkTag().exists()).toBe(true);
- expect(findForkTag().text()).toBe('fork');
- });
+ it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
+ const mergeTrainPipeline = defaultProps.pipeline;
+ mergeTrainPipeline.flags.merge_train_pipeline = false;
- it('should render the train badge when the pipeline is a merge train pipeline', () => {
- createComponent({
- pipeline: {
- flags: {
- merge_train_pipeline: true,
- },
- },
+ createComponent({
+ ...mergeTrainPipeline,
+ });
+
+ expect(findTrainTag().exists()).toBe(false);
});
- expect(findTrainTag().text()).toContain('train');
+ it('should not render the commit wrapper and commit-short-sha', () => {
+ createComponent();
+
+ expect(findCommitTitleContainer().exists()).toBe(false);
+ expect(findCommitShortSha().exists()).toBe(false);
+ });
});
- it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
- createComponent({
- pipeline: {
- flags: {
- merge_train_pipeline: false,
- },
+ describe('with the rearrangePipelinesTable feature flag turned on', () => {
+ it('should render the commit title, commit reference and commit-short-sha', () => {
+ createComponent({}, true);
+
+ const commitWrapper = findCommitTitleContainer();
+
+ expect(findCommitTitle(commitWrapper).exists()).toBe(true);
+ expect(findRefName().exists()).toBe(true);
+ expect(findCommitShortSha().exists()).toBe(true);
+ });
+
+ it('should render commit icon tooltip', () => {
+ createComponent({}, true);
+
+ expect(findCommitIcon().attributes('title')).toBe('Commit');
+ });
+
+ it.each`
+ pipeline | expectedTitle
+ ${mockPipelineTag()} | ${'Tag'}
+ ${mockPipelineBranch()} | ${'Branch'}
+ ${mockPipeline()} | ${'Merge Request'}
+ `(
+ 'should render tooltip $expectedTitle for commit icon type',
+ ({ pipeline, expectedTitle }) => {
+ createComponent(pipeline, true);
+
+ expect(findCommitIconType().attributes('title')).toBe(expectedTitle);
},
+ );
+
+ describe('with commit', () => {
+ beforeEach(() => {
+ createComponent({}, true);
+ });
+
+ it('displays commit title with link to pipeline', () => {
+ expect(findCommitTitle().attributes('href')).toBe(defaultProps.pipeline.path);
+ });
+
+ it('displays commit title text', () => {
+ expect(findCommitTitle().text()).toBe(defaultProps.pipeline.commit.title);
+ });
});
- expect(findTrainTag().exists()).toBe(false);
+ describe('without commit', () => {
+ beforeEach(() => {
+ createComponent(mockPipelineNoCommit(), true);
+ });
+
+ it('displays cant find head commit text', () => {
+ expect(findCommitTitle().text()).toBe("Can't find HEAD commit for this branch");
+ });
+
+ it('displays link to pipeline', () => {
+ expect(findCommitTitle().attributes('href')).toBe(mockPipelineNoCommit().pipeline.path);
+ });
+ });
});
});
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index c4bfec8ae14..9b2ee6b8278 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -1,14 +1,21 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipelines_manual_actions.vue';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
jest.mock('~/flash');
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
+ return {
+ confirmAction: jest.fn(),
+ };
+});
describe('Pipelines Actions dropdown', () => {
let wrapper;
@@ -35,6 +42,7 @@ describe('Pipelines Actions dropdown', () => {
wrapper = null;
mock.restore();
+ confirmAction.mockReset();
});
describe('manual actions', () => {
@@ -68,7 +76,7 @@ describe('Pipelines Actions dropdown', () => {
findAllDropdownItems().at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdown().props('loading')).toBe(true);
await waitForPromises();
@@ -80,7 +88,7 @@ describe('Pipelines Actions dropdown', () => {
findAllDropdownItems().at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdown().props('loading')).toBe(true);
await waitForPromises();
@@ -111,11 +119,11 @@ describe('Pipelines Actions dropdown', () => {
it('makes post request after confirming', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
- jest.spyOn(window, 'confirm').mockReturnValue(true);
+ confirmAction.mockResolvedValueOnce(true);
findAllDropdownItems().at(0).vm.$emit('click');
- expect(window.confirm).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
await waitForPromises();
@@ -124,11 +132,11 @@ describe('Pipelines Actions dropdown', () => {
it('does not make post request if confirmation is cancelled', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
- jest.spyOn(window, 'confirm').mockReturnValue(false);
+ confirmAction.mockResolvedValueOnce(false);
findAllDropdownItems().at(0).vm.$emit('click');
- expect(window.confirm).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
await waitForPromises();
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index 6fdbe907aed..f200d683a7a 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -9,7 +9,11 @@ import PipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_tr
import PipelineUrl from '~/pipelines/components/pipelines_list/pipeline_url.vue';
import PipelinesTable from '~/pipelines/components/pipelines_list/pipelines_table.vue';
import PipelinesTimeago from '~/pipelines/components/pipelines_list/time_ago.vue';
-import { PipelineKeyOptions } from '~/pipelines/constants';
+import {
+ PipelineKeyOptions,
+ BUTTON_TOOLTIP_RETRY,
+ BUTTON_TOOLTIP_CANCEL,
+} from '~/pipelines/constants';
import eventHub from '~/pipelines/event_hub';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
@@ -33,13 +37,18 @@ describe('Pipelines Table', () => {
return pipelines.find((p) => p.user !== null && p.commit !== null);
};
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, rearrangePipelinesTable = false) => {
wrapper = extendedWrapper(
mount(PipelinesTable, {
propsData: {
...defaultProps,
...props,
},
+ provide: {
+ glFeatures: {
+ rearrangePipelinesTable,
+ },
+ },
}),
);
};
@@ -61,6 +70,8 @@ describe('Pipelines Table', () => {
const findStagesTh = () => wrapper.findByTestId('stages-th');
const findTimeAgoTh = () => wrapper.findByTestId('timeago-th');
const findActionsTh = () => wrapper.findByTestId('actions-th');
+ const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button');
+ const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button');
beforeEach(() => {
pipeline = createMockPipeline();
@@ -71,7 +82,7 @@ describe('Pipelines Table', () => {
wrapper = null;
});
- describe('Pipelines Table', () => {
+ describe('Pipelines Table with rearrangePipelinesTable feature flag turned off', () => {
beforeEach(() => {
createComponent({ pipelines: [pipeline], viewType: 'root' });
});
@@ -187,6 +198,39 @@ describe('Pipelines Table', () => {
it('should render pipeline operations', () => {
expect(findActions().exists()).toBe(true);
});
+
+ it('should render retry action tooltip', () => {
+ expect(findRetryBtn().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
+ });
+
+ it('should render cancel action tooltip', () => {
+ expect(findCancelBtn().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL);
+ });
+ });
+ });
+
+ describe('Pipelines Table with rearrangePipelinesTable feature flag turned on', () => {
+ beforeEach(() => {
+ createComponent({ pipelines: [pipeline], viewType: 'root' }, true);
+ });
+
+ it('should render table head with correct columns', () => {
+ expect(findStatusTh().text()).toBe('Status');
+ expect(findPipelineTh().text()).toBe('Pipeline');
+ expect(findStagesTh().text()).toBe('Stages');
+ expect(findActionsTh().text()).toBe('Actions');
+ });
+
+ describe('triggerer cell', () => {
+ it('should render the pipeline triggerer', () => {
+ expect(findTriggerer().exists()).toBe(true);
+ });
+ });
+
+ describe('commit cell', () => {
+ it('should not render commit information', () => {
+ expect(findCommit().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
index c995eb864d1..4b33c1522a5 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -1,11 +1,9 @@
import { GlModal } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
-const localVue = createLocalVue();
-
describe('Test case details', () => {
let wrapper;
const defaultTestCase = {
@@ -29,7 +27,6 @@ describe('Test case details', () => {
const createComponent = (testCase = {}) => {
wrapper = extendedWrapper(
shallowMount(TestCaseDetails, {
- localVue,
propsData: {
modalId: 'my-modal',
testCase: {
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index 384b7cf6930..e0daf8cb4b5 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -9,8 +10,7 @@ import TestSummary from '~/pipelines/components/test_reports/test_summary.vue';
import TestSummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports app', () => {
let wrapper;
@@ -44,7 +44,6 @@ describe('Test reports app', () => {
wrapper = extendedWrapper(
shallowMount(TestReports, {
store,
- localVue,
}),
);
};
diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
index 793bad6b82a..97241e14129 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
@@ -8,8 +9,7 @@ import * as getters from '~/pipelines/stores/test_reports/getters';
import { formatFilePath } from '~/pipelines/stores/test_reports/utils';
import skippedTestCases from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports suite table', () => {
let wrapper;
@@ -47,7 +47,6 @@ describe('Test reports suite table', () => {
wrapper = shallowMount(SuiteTable, {
store,
- localVue,
stubs: { GlFriendlyWrap },
});
};
diff --git a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
index 0813739d72f..1598d5c337f 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
@@ -1,11 +1,11 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports summary table', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('Test reports summary table', () => {
wrapper = mount(SummaryTable, {
propsData: defaultProps,
store,
- localVue,
});
};
diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js
index 2751a878e51..6fdcd34ae83 100644
--- a/spec/frontend/popovers/components/popovers_spec.js
+++ b/spec/frontend/popovers/components/popovers_spec.js
@@ -1,5 +1,6 @@
import { GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Popovers from '~/popovers/components/popovers.vue';
@@ -7,10 +8,10 @@ describe('popovers/components/popovers.vue', () => {
const { trigger: triggerMutate } = useMockMutationObserver();
let wrapper;
- const buildWrapper = (...targets) => {
+ const buildWrapper = async (...targets) => {
wrapper = shallowMount(Popovers);
wrapper.vm.addPopovers(targets);
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const createPopoverTarget = (options = {}) => {
@@ -49,7 +50,7 @@ describe('popovers/components/popovers.vue', () => {
buildWrapper(target);
wrapper.vm.addPopovers([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAll(GlPopover)).toHaveLength(1);
});
@@ -86,7 +87,7 @@ describe('popovers/components/popovers.vue', () => {
await buildWrapper(createPopoverTarget(), createPopoverTarget());
wrapper.vm.dispose();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allPopovers()).toHaveLength(0);
});
@@ -97,7 +98,7 @@ describe('popovers/components/popovers.vue', () => {
await buildWrapper(target, createPopoverTarget());
wrapper.vm.dispose(target);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allPopovers()).toHaveLength(1);
});
@@ -109,13 +110,13 @@ describe('popovers/components/popovers.vue', () => {
await buildWrapper(target);
wrapper.vm.addPopovers([target, createPopoverTarget()]);
- await wrapper.vm.$nextTick();
+ await nextTick();
triggerMutate(document.body, {
entry: { removedNodes: [target] },
options: { childList: true },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allPopovers()).toHaveLength(1);
});
diff --git a/spec/frontend/popovers/index_spec.js b/spec/frontend/popovers/index_spec.js
index ea3b78332d7..c82fe7b47d9 100644
--- a/spec/frontend/popovers/index_spec.js
+++ b/spec/frontend/popovers/index_spec.js
@@ -1,8 +1,7 @@
+import { nextTick } from 'vue';
import { initPopovers, dispose, destroy } from '~/popovers';
describe('popovers/index.js', () => {
- let popoversApp;
-
const createPopoverTarget = (trigger = 'hover') => {
const target = document.createElement('button');
const dataset = {
@@ -22,7 +21,7 @@ describe('popovers/index.js', () => {
};
const buildPopoversApp = () => {
- popoversApp = initPopovers('[data-toggle="popover"]');
+ initPopovers('[data-toggle="popover"]');
};
const triggerEvent = (target, eventName = 'mouseenter') => {
@@ -44,7 +43,7 @@ describe('popovers/index.js', () => {
triggerEvent(target);
- await popoversApp.$nextTick();
+ await nextTick();
const html = document.querySelector('.gl-popover').innerHTML;
expect(document.querySelector('.gl-popover')).not.toBe(null);
@@ -59,7 +58,7 @@ describe('popovers/index.js', () => {
buildPopoversApp();
triggerEvent(target, trigger);
- await popoversApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-popover')).not.toBe(null);
expect(document.querySelector('.gl-popover').innerHTML).toContain('default title');
@@ -73,7 +72,7 @@ describe('popovers/index.js', () => {
const trigger = 'click';
const target = createPopoverTarget(trigger);
triggerEvent(target, trigger);
- await popoversApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-popover')).not.toBe(null);
});
@@ -86,17 +85,17 @@ describe('popovers/index.js', () => {
buildPopoversApp();
triggerEvent(target);
triggerEvent(createPopoverTarget());
- await popoversApp.$nextTick();
+ await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
dispose([fakeTarget]);
- await popoversApp.$nextTick();
+ await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
dispose([target]);
- await popoversApp.$nextTick();
+ await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(1);
});
diff --git a/spec/frontend/profile/account/components/delete_account_modal_spec.js b/spec/frontend/profile/account/components/delete_account_modal_spec.js
index f1784500baf..ad62d84c43c 100644
--- a/spec/frontend/profile/account/components/delete_account_modal_spec.js
+++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import { merge } from 'lodash';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue';
@@ -56,7 +56,7 @@ describe('DeleteAccountModal component', () => {
const findModal = () => wrapper.find(GlModalStub);
describe('with password confirmation', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
createWrapper({
propsData: {
confirmWithPassword: true,
@@ -65,48 +65,40 @@ describe('DeleteAccountModal component', () => {
vm.isOpen = true;
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
- it('does not accept empty password', (done) => {
+ it('does not accept empty password', async () => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = '';
input.dispatchEvent(new Event('input'));
- Vue.nextTick()
- .then(() => {
- expect(vm.enteredPassword).toBe(input.value);
- expect(findModal().attributes('ok-disabled')).toBe('true');
- findModal().vm.$emit('primary');
+ await nextTick();
+ expect(vm.enteredPassword).toBe(input.value);
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
- expect(form.submit).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(form.submit).not.toHaveBeenCalled();
});
- it('submits form with password', (done) => {
+ it('submits form with password', async () => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'anything';
input.dispatchEvent(new Event('input'));
- Vue.nextTick()
- .then(() => {
- expect(vm.enteredPassword).toBe(input.value);
- expect(findModal().attributes('ok-disabled')).toBeUndefined();
- findModal().vm.$emit('primary');
+ await nextTick();
+ expect(vm.enteredPassword).toBe(input.value);
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
- expect(form.submit).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(form.submit).toHaveBeenCalled();
});
});
describe('with username confirmation', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
createWrapper({
propsData: {
confirmWithPassword: false,
@@ -115,43 +107,35 @@ describe('DeleteAccountModal component', () => {
vm.isOpen = true;
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
- it('does not accept wrong username', (done) => {
+ it('does not accept wrong username', async () => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'this is wrong';
input.dispatchEvent(new Event('input'));
- Vue.nextTick()
- .then(() => {
- expect(vm.enteredUsername).toBe(input.value);
- expect(findModal().attributes('ok-disabled')).toBe('true');
- findModal().vm.$emit('primary');
+ await nextTick();
+ expect(vm.enteredUsername).toBe(input.value);
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
- expect(form.submit).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(form.submit).not.toHaveBeenCalled();
});
- it('submits form with correct username', (done) => {
+ it('submits form with correct username', async () => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = username;
input.dispatchEvent(new Event('input'));
- Vue.nextTick()
- .then(() => {
- expect(vm.enteredUsername).toBe(input.value);
- expect(findModal().attributes('ok-disabled')).toBeUndefined();
- findModal().vm.$emit('primary');
+ await nextTick();
+ expect(vm.enteredUsername).toBe(input.value);
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
- expect(form.submit).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(form.submit).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index bda07af4feb..e342b7c4ba1 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -1,6 +1,7 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -58,7 +59,7 @@ describe('UpdateUsername component', () => {
it('has a disabled button if the username was not changed', async () => {
const { openModalBtn } = findElements();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(openModalBtn.props('disabled')).toBe(true);
});
@@ -69,7 +70,7 @@ describe('UpdateUsername component', () => {
input.element.value = 'newUsername';
input.trigger('input');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(openModalBtn.props('disabled')).toBe(false);
});
@@ -83,7 +84,7 @@ describe('UpdateUsername component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ newUsername });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('confirmation modal contains proper header and body', async () => {
@@ -100,7 +101,7 @@ describe('UpdateUsername component', () => {
jest.spyOn(axios, 'put');
await wrapper.vm.onConfirm();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
});
@@ -117,7 +118,7 @@ describe('UpdateUsername component', () => {
});
await wrapper.vm.onConfirm();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(input.attributes('disabled')).toBe(undefined);
expect(openModalBtn.props('disabled')).toBe(true);
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
index 30556cdeae1..e2848e615c3 100644
--- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -1,6 +1,6 @@
import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
@@ -115,7 +115,7 @@ describe('BranchesDropdown', () => {
findSearchBoxByType().vm.$emit('input', '_anything_');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(spy).toHaveBeenCalledWith('_anything_');
expect(wrapper.vm.searchTerm).toBe('_anything_');
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 93e2ae13628..79e9dab935d 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -2,6 +2,7 @@ import { GlModal, GlForm, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
import { within } from '@testing-library/dom';
import { shallowMount, mount, createWrapper } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import api from '~/api';
import axios from '~/lib/utils/axios_utils';
@@ -156,7 +157,7 @@ describe('CommitFormModal', () => {
it('Changes the start_branch input value', async () => {
findBranchesDropdown().vm.$emit('selectBranch', '_changed_branch_value_');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findStartBranch().attributes('value')).toBe('_changed_branch_value_');
});
@@ -165,7 +166,7 @@ describe('CommitFormModal', () => {
createComponent(shallowMount, {}, {}, { isCherryPick: true });
findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTargetProject().attributes('value')).toBe('_changed_project_value_');
});
@@ -174,7 +175,7 @@ describe('CommitFormModal', () => {
it('action primary button triggers Redis HLL tracking api call', async () => {
createComponent(mount, {}, {}, { primaryActionEventName: 'test_event' });
- await wrapper.vm.$nextTick();
+ await nextTick();
jest.spyOn(findForm().element, 'submit');
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index 23b4cccd92c..4e567ab030e 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -1,12 +1,12 @@
import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import * as urlUtility from '~/lib/utils/url_utility';
import AuthorSelect from '~/projects/commits/components/author_select.vue';
import { createStore } from '~/projects/commits/store';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const commitsPath = 'author/search/url';
const currentAuthor = 'lorem';
@@ -38,7 +38,6 @@ describe('Author Select', () => {
`);
wrapper = shallowMount(AuthorSelect, {
- localVue,
store: new Vuex.Store(store),
propsData: {
projectCommitsEl: document.querySelector('.js-project-commits-show'),
@@ -64,36 +63,33 @@ describe('Author Select', () => {
const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
describe('user is searching via "filter by commit message"', () => {
- it('disables dropdown container', () => {
+ it('disables dropdown container', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ hasSearchParam: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdownContainer().attributes('disabled')).toBeFalsy();
- });
+ await nextTick();
+ expect(findDropdownContainer().attributes('disabled')).toBeFalsy();
});
- it('has correct tooltip message', () => {
+ it('has correct tooltip message', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ hasSearchParam: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdownContainer().attributes('title')).toBe(
- 'Searching by both author and message is currently not supported.',
- );
- });
+ await nextTick();
+ expect(findDropdownContainer().attributes('title')).toBe(
+ 'Searching by both author and message is currently not supported.',
+ );
});
- it('disables dropdown', () => {
+ it('disables dropdown', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ hasSearchParam: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdown().attributes('disabled')).toBeFalsy();
- });
+ await nextTick();
+ expect(findDropdown().attributes('disabled')).toBeFalsy();
});
it('hasSearchParam if user types a truthy string', () => {
@@ -108,14 +104,13 @@ describe('Author Select', () => {
expect(findDropdown().attributes('text')).toBe('Author');
});
- it('displays the current selected author', () => {
+ it('displays the current selected author', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ currentAuthor });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdown().attributes('text')).toBe(currentAuthor);
- });
+ await nextTick();
+ expect(findDropdown().attributes('text')).toBe(currentAuthor);
});
it('displays correct header text', () => {
@@ -150,13 +145,12 @@ describe('Author Select', () => {
expect(findDropdownItems().at(0).text()).toBe('Any Author');
});
- it('displays the project authors', () => {
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdownItems()).toHaveLength(authors.length + 1);
- });
+ it('displays the project authors', async () => {
+ await nextTick();
+ expect(findDropdownItems()).toHaveLength(authors.length + 1);
});
- it('has the correct props', () => {
+ it('has the correct props', async () => {
const [{ avatar_url, username }] = authors;
const result = {
avatarUrl: avatar_url,
@@ -168,15 +162,13 @@ describe('Author Select', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ currentAuthor });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result));
- });
+ await nextTick();
+ expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result));
});
- it("display the author's name", () => {
- return wrapper.vm.$nextTick().then(() => {
- expect(findDropdownItems().at(1).text()).toBe(currentAuthor);
- });
+ it("display the author's name", async () => {
+ await nextTick();
+ expect(findDropdownItems().at(1).text()).toBe(currentAuthor);
});
it('passes selected author to redirectPath', () => {
diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js
index 7989a6f3d74..18e7f2e0f6e 100644
--- a/spec/frontend/projects/compare/components/app_spec.js
+++ b/spec/frontend/projects/compare/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CompareApp from '~/projects/compare/components/app.vue';
import RevisionCard from '~/projects/compare/components/revision_card.vue';
import { appDefaultProps as defaultProps } from './mock_data';
@@ -91,7 +92,7 @@ describe('CompareApp component', () => {
project,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTargetRevisionCard().props('selectedProject')).toEqual(
expect.objectContaining(project),
@@ -106,7 +107,7 @@ describe('CompareApp component', () => {
revision,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findSourceRevisionCard().props('paramsBranch')).toBe(revision);
});
@@ -125,7 +126,7 @@ describe('CompareApp component', () => {
it('swaps revisions when clicked', async () => {
findSwapRevisionsButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTargetRevisionCard().props('paramsBranch')).toBe(defaultProps.paramsTo);
expect(findSourceRevisionCard().props('paramsBranch')).toBe(defaultProps.paramsFrom);
diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
index 27a7a32ebca..98aec347e4b 100644
--- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import RepoDropdown from '~/projects/compare/components/repo_dropdown.vue';
import { revisionCardDefaultProps as defaultProps } from './mock_data';
@@ -39,7 +40,7 @@ describe('RepoDropdown component', () => {
it('does not emit `changeTargetProject` event', async () => {
wrapper.vm.emitTargetProject('foo');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('changeTargetProject')).toBeUndefined();
});
});
@@ -67,13 +68,13 @@ describe('RepoDropdown component', () => {
it('updates the hidden input value when onClick method is triggered', async () => {
const repoId = '1';
wrapper.vm.onClick({ id: repoId });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findHiddenInput().attributes('value')).toBe(repoId);
});
it('emits `selectProject` event when another target project is selected', async () => {
findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('selectProject')[0][0]).toEqual({
direction: 'from',
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
index eb80d57fb3c..102f95f65da 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RevisionDropdown from '~/projects/compare/components/revision_dropdown_legacy.vue';
@@ -105,7 +106,7 @@ describe('RevisionDropdown component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ branches: ['some-branch'] });
- await wrapper.vm.$nextTick();
+ await nextTick();
findFirstGlDropdownItem().vm.$emit('click');
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
index 118bb68585e..c8a90848492 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
@@ -141,7 +142,7 @@ describe('RevisionDropdown component', () => {
it('emits `selectRevision` event when another revision is selected', async () => {
createComponent();
wrapper.vm.branches = ['some-branch'];
- await wrapper.vm.$nextTick();
+ await nextTick();
findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click');
diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
index e1e1aac09aa..b8f9951bbfc 100644
--- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
@@ -49,16 +49,17 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
- title="You are about to permanently delete this project"
+ title=""
variant="danger"
>
- <p>
- This project is
- <strong>
- NOT
- </strong>
- a fork, and has the following:
- </p>
+ <h4
+ class="gl-alert-title"
+ data-testid="delete-alert-title"
+ >
+
+ You are about to delete this project containing:
+
+ </h4>
<ul>
<li>
@@ -77,25 +78,17 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
4 stars
</li>
</ul>
- After a project is permanently deleted, it
- <strong>
- cannot be recovered
- </strong>
- . Permanently deleting this project will
- <strong>
- immediately delete
- </strong>
- its repositories and
+ This project is
<strong>
- all related resources
+ NOT
</strong>
- , including issues, merge requests etc.
+ a fork. This process deletes the project repository and all related resources.
</gl-alert-stub>
<p
class="gl-mb-1"
>
- Please type the following to confirm:
+ Enter the following to confirm:
</p>
<p>
diff --git a/spec/frontend/projects/components/project_delete_button_spec.js b/spec/frontend/projects/components/project_delete_button_spec.js
index bb6021fadda..a3bc4931eb3 100644
--- a/spec/frontend/projects/components/project_delete_button_spec.js
+++ b/spec/frontend/projects/components/project_delete_button_spec.js
@@ -50,7 +50,12 @@ describe('Project remove modal', () => {
it('passes confirmPhrase and formPath props to the shared delete button', () => {
expect(findSharedDeleteButton().props()).toEqual({
confirmPhrase: defaultProps.confirmPhrase,
+ forksCount: defaultProps.forksCount,
formPath: defaultProps.formPath,
+ isFork: defaultProps.isFork,
+ issuesCount: defaultProps.issuesCount,
+ mergeRequestsCount: defaultProps.mergeRequestsCount,
+ starsCount: defaultProps.starsCount,
});
});
});
diff --git a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
index dd54db7dc0a..2d1039a8743 100644
--- a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
@@ -34,13 +34,63 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
ok-variant="danger"
title-class="gl-text-red-500"
>
- Delete project. Are you ABSOLUTELY SURE?
+ Are you absolutely sure?
<div>
+ <gl-alert-stub
+ class="gl-mb-5"
+ dismisslabel="Dismiss"
+ primarybuttonlink=""
+ primarybuttontext=""
+ secondarybuttonlink=""
+ secondarybuttontext=""
+ title=""
+ variant="danger"
+ >
+ <h4
+ class="gl-alert-title"
+ data-testid="delete-alert-title"
+ >
+
+ You are about to delete this project containing:
+
+ </h4>
+
+ <ul>
+ <li>
+ <gl-sprintf-stub
+ message="1 issue"
+ />
+ </li>
+
+ <li>
+ <gl-sprintf-stub
+ message="2 merge requests"
+ />
+ </li>
+
+ <li>
+ <gl-sprintf-stub
+ message="3 forks"
+ />
+ </li>
+
+ <li>
+ <gl-sprintf-stub
+ message="4 stars"
+ />
+ </li>
+ </ul>
+
+ <gl-sprintf-stub
+ data-testid="delete-alert-body"
+ message="This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources."
+ />
+ </gl-alert-stub>
<p
class="gl-mb-1"
>
- Please type the following to confirm:
+ Enter the following to confirm:
</p>
<p>
diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js
index 3e491584670..45c39ee91d8 100644
--- a/spec/frontend/projects/components/shared/delete_button_spec.js
+++ b/spec/frontend/projects/components/shared/delete_button_spec.js
@@ -12,15 +12,25 @@ describe('Project remove modal', () => {
const findConfirmButton = () => wrapper.find('.js-modal-action-primary');
const findAuthenticityTokenInput = () => findFormElement().find('input[name=authenticity_token]');
const findModal = () => wrapper.find(GlModal);
+ const findTitle = () => wrapper.find('[data-testid="delete-alert-title"]');
+ const findAlertBody = () => wrapper.find('[data-testid="delete-alert-body"]');
const defaultProps = {
confirmPhrase: 'foo',
formPath: 'some/path',
+ isFork: false,
+ issuesCount: 1,
+ mergeRequestsCount: 2,
+ forksCount: 3,
+ starsCount: 4,
};
- const createComponent = (data = {}, stubs = {}) => {
+ const createComponent = (data = {}, stubs = {}, props = {}) => {
wrapper = shallowMount(SharedDeleteButton, {
- propsData: defaultProps,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
data: () => data,
stubs: {
GlModal: stubComponent(GlModal, {
@@ -88,4 +98,20 @@ describe('Project remove modal', () => {
expect(findFormElement().element.submit).toHaveBeenCalled();
});
});
+
+ describe('when project is a fork', () => {
+ beforeEach(() => {
+ createComponent({}, {}, { isFork: true });
+ });
+
+ it('matches the fork title', () => {
+ expect(findTitle().text()).toEqual('You are about to delete this forked project containing:');
+ });
+
+ it('matches the fork body', () => {
+ expect(findAlertBody().attributes().message).toEqual(
+ 'This process deletes the project repository and all related resources.',
+ );
+ });
+ });
});
diff --git a/spec/frontend/projects/new/components/deployment_target_select_spec.js b/spec/frontend/projects/new/components/deployment_target_select_spec.js
new file mode 100644
index 00000000000..8fe4c5f1230
--- /dev/null
+++ b/spec/frontend/projects/new/components/deployment_target_select_spec.js
@@ -0,0 +1,82 @@
+import { GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { mockTracking } from 'helpers/tracking_helper';
+import DeploymentTargetSelect from '~/projects/new/components/deployment_target_select.vue';
+import {
+ DEPLOYMENT_TARGET_SELECTIONS,
+ DEPLOYMENT_TARGET_LABEL,
+ DEPLOYMENT_TARGET_EVENT,
+ NEW_PROJECT_FORM,
+} from '~/projects/new/constants';
+
+describe('Deployment target select', () => {
+ let wrapper;
+ let trackingSpy;
+
+ const findFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findSelect = () => wrapper.findComponent(GlFormSelect);
+
+ const createdWrapper = () => {
+ wrapper = shallowMount(DeploymentTargetSelect, {
+ stubs: {
+ GlFormSelect,
+ },
+ });
+ };
+
+ const createForm = () => {
+ setFixtures(`
+ <form id="${NEW_PROJECT_FORM}">
+ </form>
+ `);
+ };
+
+ beforeEach(() => {
+ createForm();
+ createdWrapper();
+
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the correct label', () => {
+ expect(findFormGroup().attributes('label')).toBe('Project deployment target (optional)');
+ });
+
+ it('renders a select with the disabled default option', () => {
+ expect(findSelect().find('option').text()).toBe('Select the deployment target');
+ expect(findSelect().find('option').attributes('disabled')).toBe('disabled');
+ });
+
+ describe.each`
+ selectedTarget | formSubmitted | eventSent
+ ${null} | ${true} | ${false}
+ ${DEPLOYMENT_TARGET_SELECTIONS[0]} | ${false} | ${false}
+ ${DEPLOYMENT_TARGET_SELECTIONS[0]} | ${true} | ${true}
+ `('Snowplow tracking event', ({ selectedTarget, formSubmitted, eventSent }) => {
+ beforeEach(() => {
+ findSelect().vm.$emit('input', selectedTarget);
+
+ if (formSubmitted) {
+ const form = document.getElementById(NEW_PROJECT_FORM);
+ form.dispatchEvent(new Event('submit'));
+ }
+ });
+
+ if (eventSent) {
+ it(`is sent, when the the selectedTarget is ${selectedTarget} and the formSubmitted is ${formSubmitted} `, () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, DEPLOYMENT_TARGET_EVENT, {
+ label: DEPLOYMENT_TARGET_LABEL,
+ property: selectedTarget,
+ });
+ });
+ } else {
+ it(`is not sent, when the the selectedTarget is ${selectedTarget} and the formSubmitted is ${formSubmitted} `, () => {
+ expect(trackingSpy).toHaveBeenCalledTimes(0);
+ });
+ }
+ });
+});
diff --git a/spec/frontend/projects/new/components/new_project_url_select_spec.js b/spec/frontend/projects/new/components/new_project_url_select_spec.js
index 258fa7636d4..921f5b74278 100644
--- a/spec/frontend/projects/new/components/new_project_url_select_spec.js
+++ b/spec/frontend/projects/new/components/new_project_url_select_spec.js
@@ -6,9 +6,10 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+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 { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import eventHub from '~/projects/new/event_hub';
@@ -94,13 +95,14 @@ describe('NewProjectUrlSelect component', () => {
const clickDropdownItem = async () => {
wrapper.findComponent(GlDropdownItem).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const showDropdown = async () => {
findDropdown().vm.$emit('shown');
await wrapper.vm.$apollo.queries.currentUser.refetch();
jest.runOnlyPendingTimers();
+ await waitForPromises();
};
afterEach(() => {
@@ -235,8 +237,7 @@ describe('NewProjectUrlSelect component', () => {
};
wrapper = mountComponent({ search: 'no matches', queryResponse, mountFn: mount });
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await waitForPromises();
expect(wrapper.find('li').text()).toBe('No matches found');
});
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 574756322c7..9c94925c817 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlTabs, GlTab } from '@gitlab/ui';
import { merge } from 'lodash';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
@@ -99,7 +100,7 @@ describe('ProjectsPipelinesChartsApp', () => {
tabs.vm.$emit('input', 1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(tabs.attributes('value')).toBe('1');
});
@@ -115,7 +116,7 @@ describe('ProjectsPipelinesChartsApp', () => {
tabs.vm.$emit('input', 0);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(updateHistory).not.toHaveBeenCalled();
});
@@ -183,7 +184,7 @@ describe('ProjectsPipelinesChartsApp', () => {
popstateHandler();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findGlTabs().attributes('value')).toBe('1');
});
diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
index 9adc6dba51e..cafb3f231bd 100644
--- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
@@ -1,6 +1,6 @@
-import { GlSegmentedControl } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { GlSegmentedControl } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import CiCdAnalyticsAreaChart from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue';
import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue';
import { transformedAreaChartData, chartOptions } from '../mock_data';
@@ -29,12 +29,15 @@ const DEFAULT_PROPS = {
describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', () => {
let wrapper;
- const createWrapper = (props = {}) =>
- shallowMount(CiCdAnalyticsCharts, {
+ const createWrapper = (props = {}, slots = {}) =>
+ shallowMountExtended(CiCdAnalyticsCharts, {
propsData: {
...DEFAULT_PROPS,
...props,
},
+ scopedSlots: {
+ ...slots,
+ },
});
afterEach(() => {
@@ -44,20 +47,20 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
}
});
- describe('segmented control', () => {
- let segmentedControl;
+ const findMetricsSlot = () => wrapper.findByTestId('metrics-slot');
+ const findSegmentedControl = () => wrapper.findComponent(GlSegmentedControl);
+ describe('segmented control', () => {
beforeEach(() => {
wrapper = createWrapper();
- segmentedControl = wrapper.find(GlSegmentedControl);
});
it('should default to the first chart', () => {
- expect(segmentedControl.props('checked')).toBe(0);
+ expect(findSegmentedControl().props('checked')).toBe(0);
});
it('should use the title and index as values', () => {
- const options = segmentedControl.props('options');
+ const options = findSegmentedControl().props('options');
expect(options).toHaveLength(3);
expect(options).toEqual([
{
@@ -76,7 +79,7 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
});
it('should select a different chart on change', async () => {
- segmentedControl.vm.$emit('input', 1);
+ findSegmentedControl().vm.$emit('input', 1);
const chart = wrapper.find(CiCdAnalyticsAreaChart);
@@ -91,4 +94,24 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
wrapper = createWrapper({ charts: [] });
expect(wrapper.find(CiCdAnalyticsAreaChart).exists()).toBe(false);
});
+
+ describe('slots', () => {
+ beforeEach(() => {
+ wrapper = createWrapper(
+ {},
+ {
+ metrics: '<div data-testid="metrics-slot">selected chart: {{props.selectedChart}}</div>',
+ },
+ );
+ });
+
+ it('renders a metrics slot', async () => {
+ const selectedChart = 1;
+ findSegmentedControl().vm.$emit('input', selectedChart);
+
+ await nextTick();
+
+ expect(findMetricsSlot().text()).toBe(`selected chart: ${selectedChart}`);
+ });
+ });
});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
index 6ef49390c47..3c91b913e67 100644
--- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
@@ -1,7 +1,9 @@
import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql';
@@ -10,8 +12,7 @@ import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_a
import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
const projectPath = 'gitlab-org/gitlab';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => {
let wrapper;
@@ -25,14 +26,15 @@ describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => {
return createMockApollo(requestHandlers);
}
- beforeEach(() => {
+ beforeEach(async () => {
wrapper = shallowMount(PipelineCharts, {
provide: {
projectPath,
},
- localVue,
apolloProvider: createMockApolloProvider(),
});
+
+ await waitForPromises();
});
afterEach(() => {
diff --git a/spec/frontend/projects/project_find_file_spec.js b/spec/frontend/projects/project_find_file_spec.js
index 9c1000039b1..eec54dd04bc 100644
--- a/spec/frontend/projects/project_find_file_spec.js
+++ b/spec/frontend/projects/project_find_file_spec.js
@@ -1,6 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
import ProjectFindFile from '~/projects/project_find_file';
@@ -53,7 +54,7 @@ describe('ProjectFindFile', () => {
{ path: 'folde?rC/fil#F.txt', escaped: 'folde%3FrC/fil%23F.txt' },
];
- beforeEach((done) => {
+ beforeEach(() => {
// Create a mock adapter for stubbing axios API requests
mock = new MockAdapter(axios);
@@ -64,7 +65,7 @@ describe('ProjectFindFile', () => {
);
getProjectFindFileInstance(); // This triggers a load / axios call + subsequent render in the constructor
- setImmediate(done);
+ return waitForPromises();
});
afterEach(() => {
diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
index 0c5bbe2a115..0a05832ceb6 100644
--- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
+++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
@@ -1,6 +1,7 @@
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
@@ -121,7 +122,7 @@ describe('projects/settings/components/shared_runners', () => {
expect(isToggleLoading()).toBe(false);
findSharedRunnersToggle().vm.$emit('change', true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(isToggleLoading()).toBe(true);
await waitForPromises();
diff --git a/spec/frontend/projects/settings/components/transfer_project_form_spec.js b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
index f7ce7c6f840..85b09ced024 100644
--- a/spec/frontend/projects/settings/components/transfer_project_form_spec.js
+++ b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
@@ -1,4 +1,7 @@
-import { namespaces } from 'jest/vue_shared/components/namespace_select/mock_data';
+import {
+ groupNamespaces,
+ userNamespaces,
+} from 'jest/vue_shared/components/namespace_select/mock_data';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import TransferProjectForm from '~/projects/settings/components/transfer_project_form.vue';
import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
@@ -13,7 +16,8 @@ describe('Transfer project form', () => {
const createComponent = () =>
shallowMountExtended(TransferProjectForm, {
propsData: {
- namespaces,
+ userNamespaces,
+ groupNamespaces,
confirmButtonText,
confirmationPhrase,
},
@@ -43,7 +47,7 @@ describe('Transfer project form', () => {
});
describe('with a selected namespace', () => {
- const [selectedItem] = namespaces.group;
+ const [selectedItem] = groupNamespaces;
beforeEach(() => {
findNamespaceSelect().vm.$emit('select', selectedItem);
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index 875c58583df..57e515723e5 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
@@ -139,7 +139,7 @@ describe('ServiceDeskSetting', () => {
input.setValue('abc_A.');
input.trigger('blur');
- await wrapper.vm.$nextTick();
+ await nextTick();
const errorText = wrapper.find('.invalid-feedback');
expect(errorText.exists()).toBe(true);
diff --git a/spec/frontend/prometheus_alerts/components/reset_key_spec.js b/spec/frontend/prometheus_alerts/components/reset_key_spec.js
index edf5297cc6a..dc5fdb1dffc 100644
--- a/spec/frontend/prometheus_alerts/components/reset_key_spec.js
+++ b/spec/frontend/prometheus_alerts/components/reset_key_spec.js
@@ -1,6 +1,7 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import ResetKey from '~/prometheus_alerts/components/reset_key.vue';
@@ -45,37 +46,31 @@ describe('ResetKey', () => {
expect(vm.find('.js-reset-auth-key').text()).toEqual('Reset key');
});
- it('reset updates key', () => {
+ it('reset updates key', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find(GlModal).vm.$emit('ok');
- return vm.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(vm.vm.authorizationKey).toEqual('newToken');
- expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
- });
+ await nextTick();
+ await waitForPromises();
+ expect(vm.vm.authorizationKey).toEqual('newToken');
+ expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
- it('reset key failure shows error', () => {
+ it('reset key failure shows error', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(500);
vm.find(GlModal).vm.$emit('ok');
- return vm.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(vm.find('#authorization-key').attributes('value')).toEqual(
- propsData.initialAuthorizationKey,
- );
-
- expect(document.querySelector('.flash-container').innerText.trim()).toEqual(
- 'Failed to reset key. Please try again.',
- );
- });
+ await nextTick();
+ await waitForPromises();
+ expect(vm.find('#authorization-key').attributes('value')).toEqual(
+ propsData.initialAuthorizationKey,
+ );
+
+ expect(document.querySelector('.flash-container').innerText.trim()).toEqual(
+ 'Failed to reset key. Please try again.',
+ );
});
});
@@ -92,14 +87,13 @@ describe('ResetKey', () => {
expect(vm.find('#authorization-key').attributes('value')).toEqual('');
});
- it('Generate key button triggers key change', () => {
+ it('Generate key button triggers key change', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find('.js-reset-auth-key').vm.$emit('click');
- return waitForPromises().then(() => {
- expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
- });
+ await waitForPromises();
+ expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
});
});
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index a703dc0a66f..ee74e28ba23 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -1,4 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import PANEL_STATE from '~/prometheus_metrics/constants';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
@@ -132,7 +133,7 @@ describe('PrometheusMetrics', () => {
mock.restore();
});
- it('should show loader animation while response is being loaded and hide it when request is complete', (done) => {
+ it('should show loader animation while response is being loaded and hide it when request is complete', async () => {
mockSuccess();
prometheusMetrics.loadActiveMetrics();
@@ -140,34 +141,31 @@ describe('PrometheusMetrics', () => {
expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeFalsy();
expect(axios.get).toHaveBeenCalledWith(prometheusMetrics.activeMetricsEndpoint);
- setImmediate(() => {
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- done();
- });
+ await waitForPromises();
+
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
});
- it('should show empty state if response failed to load', (done) => {
+ it('should show empty state if response failed to load', async () => {
mockError();
prometheusMetrics.loadActiveMetrics();
- setImmediate(() => {
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
- done();
- });
+ await waitForPromises();
+
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
+ expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
});
- it('should populate metrics list once response is loaded', (done) => {
+ it('should populate metrics list once response is loaded', async () => {
jest.spyOn(prometheusMetrics, 'populateActiveMetrics').mockImplementation();
mockSuccess();
prometheusMetrics.loadActiveMetrics();
- setImmediate(() => {
- expect(prometheusMetrics.populateActiveMetrics).toHaveBeenCalledWith(metrics);
- done();
- });
+ await waitForPromises();
+
+ expect(prometheusMetrics.populateActiveMetrics).toHaveBeenCalledWith(metrics);
});
});
});
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index b486992ac4b..e1fc60f0d92 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem, GlDropdown, GlIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { merge, last } from 'lodash';
@@ -20,8 +21,7 @@ import {
} from '~/ref/constants';
import createStore from '~/ref/stores/';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Ref selector component', () => {
const fixtures = { branches, tags, commit };
@@ -52,7 +52,6 @@ describe('Ref selector component', () => {
stubs: {
GlSearchBoxByType: true,
},
- localVue,
store: createStore(),
},
mountOverrides,
@@ -138,19 +137,19 @@ describe('Ref selector component', () => {
findSearchBox().vm.$emit('input', newQuery);
};
- const selectFirstBranch = () => {
+ const selectFirstBranch = async () => {
findFirstBranchDropdownItem().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
- const selectFirstTag = () => {
+ const selectFirstTag = async () => {
findFirstTagDropdownItem().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
- const selectFirstCommit = () => {
+ const selectFirstCommit = async () => {
findFirstCommitDropdownItem().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const waitForRequests = ({ andClearMocks } = { andClearMocks: false }) =>
@@ -220,12 +219,11 @@ describe('Ref selector component', () => {
return waitForRequests();
});
- it('renders the updated ref name', () => {
+ it('renders the updated ref name', async () => {
wrapper.setProps({ value: updatedRef });
- return localVue.nextTick().then(() => {
- expect(findButtonContent().text()).toBe(updatedRef);
- });
+ await nextTick();
+ expect(findButtonContent().text()).toBe(updatedRef);
});
});
@@ -547,9 +545,8 @@ describe('Ref selector component', () => {
await selectFirstBranch();
- return localVue.nextTick().then(() => {
- expect(findButtonContent().text()).toBe(fixtures.branches[0].name);
- });
+ await nextTick();
+ expect(findButtonContent().text()).toBe(fixtures.branches[0].name);
});
it("updates the v-model binding with the branch's name", async () => {
@@ -567,9 +564,8 @@ describe('Ref selector component', () => {
await selectFirstTag();
- return localVue.nextTick().then(() => {
- expect(findButtonContent().text()).toBe(fixtures.tags[0].name);
- });
+ await nextTick();
+ expect(findButtonContent().text()).toBe(fixtures.tags[0].name);
});
it("updates the v-model binding with the tag's name", async () => {
@@ -587,9 +583,8 @@ describe('Ref selector component', () => {
await selectFirstCommit();
- return localVue.nextTick().then(() => {
- expect(findButtonContent().text()).toBe(fixtures.commit.id);
- });
+ await nextTick();
+ expect(findButtonContent().text()).toBe(fixtures.commit.id);
});
it("updates the v-model binding with the commit's full SHA", async () => {
diff --git a/spec/frontend/related_issues/components/related_issuable_input_spec.js b/spec/frontend/related_issues/components/related_issuable_input_spec.js
index 79b228454f4..7d11e3cffb0 100644
--- a/spec/frontend/related_issues/components/related_issuable_input_spec.js
+++ b/spec/frontend/related_issues/components/related_issuable_input_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import RelatedIssuableInput from '~/related_issues/components/related_issuable_input.vue';
import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants';
@@ -82,7 +83,7 @@ describe('RelatedIssuableInput', () => {
wrapper.find('li').trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(document.activeElement).toBe(wrapper.find({ ref: 'input' }).element);
});
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index 029d720f7b9..0a0a683b56d 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -3,6 +3,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { merge } from 'lodash';
import Vuex from 'vuex';
+import { nextTick } from 'vue';
import originalRelease from 'test_fixtures/api/releases/release.json';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
@@ -71,7 +72,7 @@ describe('Release edit/new component', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.element.querySelectorAll('input').forEach((input) => jest.spyOn(input, 'focus'));
};
diff --git a/spec/frontend/releases/components/app_index_apollo_client_spec.js b/spec/frontend/releases/components/app_index_apollo_client_spec.js
index 32bbfd386f5..9881ef9bc9f 100644
--- a/spec/frontend/releases/components/app_index_apollo_client_spec.js
+++ b/spec/frontend/releases/components/app_index_apollo_client_spec.js
@@ -1,9 +1,10 @@
import { cloneDeep } from 'lodash';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import originalAllReleasesQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/all_releases.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import allReleasesQuery from 'shared_queries/releases/all_releases.query.graphql';
import createFlash from '~/flash';
import { historyPushState } from '~/lib/utils/common_utils';
@@ -141,7 +142,8 @@ describe('app_index_apollo_client.vue', () => {
});
});
- it(`${toDescription(loadingIndicator)} render a loading indicator`, () => {
+ it(`${toDescription(loadingIndicator)} render a loading indicator`, async () => {
+ await waitForPromises();
expect(findLoadingIndicator().exists()).toBe(loadingIndicator);
});
@@ -294,7 +296,7 @@ describe('app_index_apollo_client.vue', () => {
mockQueryParams = { after };
findPagination().vm.$emit('next', after);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(queryMock.mock.calls).toEqual([
[expect.objectContaining({ before })],
@@ -319,7 +321,7 @@ describe('app_index_apollo_client.vue', () => {
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();
+ await nextTick();
expect(queryMock.mock.calls).toEqual([
[expect.objectContaining({ sort: DEFAULT_SORT })],
@@ -335,7 +337,7 @@ describe('app_index_apollo_client.vue', () => {
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();
+ await nextTick();
expect(queryMock.mock.calls).toEqual([
[expect.objectContaining({ sort: DEFAULT_SORT })],
@@ -368,7 +370,7 @@ describe('app_index_apollo_client.vue', () => {
findSort().vm.$emit('input', CREATED_ASC);
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it(`resets the page's "${paramName}" pagination cursor when the sort is changed`, () => {
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index a60b9bda66a..41c9746a363 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -3,6 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import oneReleaseQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/one_release.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import ReleaseShowApp from '~/releases/components/app_show.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
@@ -111,12 +112,13 @@ describe('Release show component', () => {
});
describe('when the component has successfully loaded the release', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const apolloProvider = createMockApollo([
[oneReleaseQuery, jest.fn().mockResolvedValueOnce(oneReleaseQueryResponse)],
]);
createComponent({ apolloProvider });
+ await waitForPromises();
});
expectNoLoadingIndicator();
@@ -125,12 +127,13 @@ describe('Release show component', () => {
});
describe('when the request succeeded, but the returned "project" key was null', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const apolloProvider = createMockApollo([
[oneReleaseQuery, jest.fn().mockResolvedValueOnce({ data: { project: null } })],
]);
createComponent({ apolloProvider });
+ await waitForPromises();
});
expectNoLoadingIndicator();
@@ -139,7 +142,7 @@ describe('Release show component', () => {
});
describe('when the request succeeded, but the returned "project.release" key was null', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const apolloProvider = createMockApollo([
[
oneReleaseQuery,
@@ -148,6 +151,7 @@ describe('Release show component', () => {
]);
createComponent({ apolloProvider });
+ await waitForPromises();
});
expectNoLoadingIndicator();
@@ -156,12 +160,13 @@ describe('Release show component', () => {
});
describe('when an error occurs while loading the release', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const apolloProvider = createMockApollo([
[oneReleaseQuery, jest.fn().mockRejectedValueOnce('An error occurred!')],
]);
createComponent({ apolloProvider });
+ await waitForPromises();
});
expectNoLoadingIndicator();
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index 839d127e00f..c0f7738bec5 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import originalRelease from 'test_fixtures/api/releases/release.json';
import * as commonUtils from '~/lib/utils/common_utils';
@@ -6,8 +7,7 @@ import { ENTER_KEY } from '~/lib/utils/keys';
import AssetLinksForm from '~/releases/components/asset_links_form.vue';
import { ASSET_LINK_TYPE, DEFAULT_ASSET_LINK_TYPE } from '~/releases/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Release edit component', () => {
let wrapper;
@@ -52,7 +52,6 @@ describe('Release edit component', () => {
});
wrapper = mount(AssetLinksForm, {
- localVue,
store,
});
};
diff --git a/spec/frontend/releases/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js
index 973428257b7..f0d02884305 100644
--- a/spec/frontend/releases/components/evidence_block_spec.js
+++ b/spec/frontend/releases/components/evidence_block_spec.js
@@ -1,5 +1,6 @@
import { GlLink, GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import originalRelease from 'test_fixtures/api/releases/release.json';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
@@ -51,12 +52,11 @@ describe('Evidence Block', () => {
expect(wrapper.find('.js-short').text()).toBe(truncateSha(release.evidences[0].sha));
});
- it('renders the long sha after expansion', () => {
+ it('renders the long sha after expansion', async () => {
wrapper.find('.js-text-expander-prepend').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.js-expanded').text()).toBe(release.evidences[0].sha);
- });
+ await nextTick();
+ expect(wrapper.find('.js-expanded').text()).toBe(release.evidences[0].sha);
});
});
diff --git a/spec/frontend/releases/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js
index f645dc309d7..b095e9e1d78 100644
--- a/spec/frontend/releases/components/release_block_footer_spec.js
+++ b/spec/frontend/releases/components/release_block_footer_spec.js
@@ -1,6 +1,7 @@
import { GlLink, GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
+import { nextTick } from 'vue';
import originalRelease from 'test_fixtures/api/releases/release.json';
import { trimText } from 'helpers/text_helper';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
@@ -14,7 +15,7 @@ describe('Release block footer', () => {
let wrapper;
let release;
- const factory = (props = {}) => {
+ const factory = async (props = {}) => {
wrapper = mount(ReleaseBlockFooter, {
propsData: {
...convertObjectPropsToCamelCase(release, { deep: true }),
@@ -22,7 +23,7 @@ describe('Release block footer', () => {
},
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
diff --git a/spec/frontend/releases/components/release_block_milestone_info_spec.js b/spec/frontend/releases/components/release_block_milestone_info_spec.js
index 146b2cc7490..84a0080965b 100644
--- a/spec/frontend/releases/components/release_block_milestone_info_spec.js
+++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js
@@ -1,5 +1,6 @@
import { GlProgressBar, GlLink, GlBadge, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import originalRelease from 'test_fixtures/api/releases/release.json';
import { trimText } from 'helpers/text_helper';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
@@ -12,12 +13,12 @@ describe('Release block milestone info', () => {
let wrapper;
let milestones;
- const factory = (props) => {
+ const factory = async (props) => {
wrapper = mount(ReleaseBlockMilestoneInfo, {
propsData: props,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
@@ -105,10 +106,10 @@ describe('Release block milestone info', () => {
return factory({ milestones: lotsOfMilestones });
});
- const clickShowMoreFewerButton = () => {
+ const clickShowMoreFewerButton = async () => {
milestoneListContainer().find(GlButton).trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const milestoneListText = () => trimText(milestoneListContainer().text());
@@ -117,19 +118,16 @@ describe('Release block milestone info', () => {
expect(milestoneListText()).toContain(`Milestones ${abbreviatedListString} • show 10 more`);
});
- it('renders all milestones when "show more" is clicked', () =>
- clickShowMoreFewerButton().then(() => {
- expect(milestoneListText()).toContain(`Milestones ${fullListString} • show fewer`);
- }));
+ it('renders all milestones when "show more" is clicked', async () => {
+ await clickShowMoreFewerButton();
+ expect(milestoneListText()).toContain(`Milestones ${fullListString} • show fewer`);
+ });
- it('returns to the original view when "show fewer" is clicked', () =>
- clickShowMoreFewerButton()
- .then(clickShowMoreFewerButton)
- .then(() => {
- expect(milestoneListText()).toContain(
- `Milestones ${abbreviatedListString} • show 10 more`,
- );
- }));
+ it('returns to the original view when "show fewer" is clicked', async () => {
+ await clickShowMoreFewerButton();
+ await clickShowMoreFewerButton();
+ expect(milestoneListText()).toContain(`Milestones ${abbreviatedListString} • show 10 more`);
+ });
});
const expectAllZeros = () => {
diff --git a/spec/frontend/releases/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js
index a847c32b8f1..c4910ae9b2f 100644
--- a/spec/frontend/releases/components/release_block_spec.js
+++ b/spec/frontend/releases/components/release_block_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import $ from 'jquery';
+import { nextTick } from 'vue';
import originalRelease from 'test_fixtures/api/releases/release.json';
import * as commonUtils from '~/lib/utils/common_utils';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -13,7 +14,7 @@ describe('Release block', () => {
let wrapper;
let release;
- const factory = (releaseProp, featureFlags = {}) => {
+ const factory = async (releaseProp, featureFlags = {}) => {
wrapper = mount(ReleaseBlock, {
propsData: {
release: releaseProp,
@@ -25,7 +26,7 @@ describe('Release block', () => {
},
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const milestoneListLabel = () => wrapper.find('.js-milestone-list-label');
diff --git a/spec/frontend/releases/components/releases_pagination_spec.js b/spec/frontend/releases/components/releases_pagination_spec.js
index 2d08f72ad8b..b8c69b0ea70 100644
--- a/spec/frontend/releases/components/releases_pagination_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_spec.js
@@ -1,5 +1,6 @@
import { GlKeysetPagination } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { historyPushState } from '~/lib/utils/common_utils';
import ReleasesPagination from '~/releases/components/releases_pagination.vue';
@@ -11,8 +12,7 @@ jest.mock('~/lib/utils/common_utils', () => ({
historyPushState: jest.fn(),
}));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('~/releases/components/releases_pagination.vue', () => {
let wrapper;
@@ -39,7 +39,6 @@ describe('~/releases/components/releases_pagination.vue', () => {
},
featureFlags: {},
}),
- localVue,
});
};
diff --git a/spec/frontend/releases/components/releases_sort_spec.js b/spec/frontend/releases/components/releases_sort_spec.js
index b16f80b9c73..7774532bc12 100644
--- a/spec/frontend/releases/components/releases_sort_spec.js
+++ b/spec/frontend/releases/components/releases_sort_spec.js
@@ -1,12 +1,12 @@
import { GlSorting, GlSortingItem } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import ReleasesSort from '~/releases/components/releases_sort.vue';
import createStore from '~/releases/stores';
import createIndexModule from '~/releases/stores/modules/index';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('~/releases/components/releases_sort.vue', () => {
let wrapper;
@@ -30,7 +30,6 @@ describe('~/releases/components/releases_sort.vue', () => {
stubs: {
GlSortingItem,
},
- localVue,
});
};
diff --git a/spec/frontend/releases/components/tag_field_exsting_spec.js b/spec/frontend/releases/components/tag_field_exsting_spec.js
index 294538086b4..f45a28392b7 100644
--- a/spec/frontend/releases/components/tag_field_exsting_spec.js
+++ b/spec/frontend/releases/components/tag_field_exsting_spec.js
@@ -1,5 +1,6 @@
import { GlFormInput } from '@gitlab/ui';
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
import createStore from '~/releases/stores';
@@ -7,8 +8,7 @@ import createEditNewModule from '~/releases/stores/modules/edit_new';
const TEST_TAG_NAME = 'test-tag-name';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('releases/components/tag_field_existing', () => {
let store;
@@ -17,7 +17,6 @@ describe('releases/components/tag_field_existing', () => {
const createComponent = (mountFn = shallowMount) => {
wrapper = mountFn(TagFieldExisting, {
store,
- localVue,
});
};
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index 0f416e46dba..c13b513f87e 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -1,6 +1,6 @@
import { GlDropdownItem } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { __ } from '~/locale';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
@@ -153,7 +153,7 @@ describe('releases/components/tag_field_new', () => {
* Should be passed either 'shown' or 'hidden'
*/
const expectValidationMessageToBe = async (state) => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTagNameFormGroup().element).toHaveClass(
state === 'shown' ? 'is-invalid' : 'is-valid',
diff --git a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js b/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
index 794deca42ac..ddabb7194cb 100644
--- a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
+++ b/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
@@ -1,3 +1,4 @@
+import { GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
@@ -29,7 +30,7 @@ describe('CustomMetricsForm', () => {
});
};
- const findIsNewBadge = () => wrapper.find({ ref: 'accessibility-issue-is-new-badge' });
+ const findIsNewBadge = () => wrapper.findComponent(GlBadge);
beforeEach(() => {
mountComponent(issue);
@@ -37,7 +38,6 @@ describe('CustomMetricsForm', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
it('Displays the issue message', () => {
@@ -52,7 +52,7 @@ describe('CustomMetricsForm', () => {
.find({ ref: 'accessibility-issue-learn-more' })
.attributes('href');
- expect(learnMoreUrl).toEqual(issue.learnMoreUrl);
+ expect(learnMoreUrl).toBe(issue.learnMoreUrl);
});
});
@@ -69,7 +69,7 @@ describe('CustomMetricsForm', () => {
.find({ ref: 'accessibility-issue-learn-more' })
.attributes('href');
- expect(learnMoreUrl).toEqual('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
+ expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
});
});
@@ -86,7 +86,7 @@ describe('CustomMetricsForm', () => {
.find({ ref: 'accessibility-issue-learn-more' })
.attributes('href');
- expect(learnMoreUrl).toEqual('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
+ expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
});
});
@@ -96,7 +96,7 @@ describe('CustomMetricsForm', () => {
});
it('Renders the new badge', () => {
- expect(findIsNewBadge().exists()).toEqual(true);
+ expect(findIsNewBadge().exists()).toBe(true);
});
});
@@ -106,7 +106,7 @@ describe('CustomMetricsForm', () => {
});
it('Does not render the new badge', () => {
- expect(findIsNewBadge().exists()).toEqual(false);
+ expect(findIsNewBadge().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
index b716d54c9fc..34b1cdd92bc 100644
--- a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
+++ b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
@@ -1,22 +1,20 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue';
import { getStoreConfig } from '~/reports/accessibility_report/store';
import { mockReport } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Grouped accessibility reports app', () => {
- const Component = localVue.extend(GroupedAccessibilityReportsApp);
let wrapper;
let mockStore;
const mountComponent = () => {
- wrapper = mount(Component, {
+ wrapper = mount(GroupedAccessibilityReportsApp, {
store: mockStore,
- localVue,
propsData: {
endpoint: 'endpoint.json',
},
diff --git a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
index 685a1c50a46..1f923f41274 100644
--- a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
+++ b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import CodequalityIssueBody from '~/reports/codequality_report/components/codequality_issue_body.vue';
import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue';
@@ -6,8 +7,7 @@ import { getStoreConfig } from '~/reports/codequality_report/store';
import { STATUS_NOT_FOUND } from '~/reports/constants';
import { parsedReportIssues } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Grouped code quality reports app', () => {
let wrapper;
@@ -22,7 +22,6 @@ describe('Grouped code quality reports app', () => {
const mountComponent = (props = {}) => {
wrapper = mount(GroupedCodequalityReportsApp, {
store: mockStore,
- localVue,
propsData: {
...PATHS,
...props,
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index 39932b62dbb..f9eb6dd05f3 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import reportSection from '~/reports/components/report_section.vue';
@@ -71,16 +71,12 @@ describe('Report section', () => {
const issues = hasIssues ? 'has issues' : 'has no issues';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isCollapsible}, if the report ${issues} and ${open}`, (done) => {
+ it(`is ${isCollapsible}, if the report ${issues} and ${open}`, async () => {
vm.hasIssues = hasIssues;
vm.alwaysOpen = alwaysOpen;
- Vue.nextTick()
- .then(() => {
- expect(vm.isCollapsible).toBe(isCollapsible);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.isCollapsible).toBe(isCollapsible);
});
});
});
@@ -97,16 +93,12 @@ describe('Report section', () => {
const issues = isCollapsed ? 'is collapsed' : 'is not collapsed';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isExpanded}, if the report ${issues} and ${open}`, (done) => {
+ it(`is ${isExpanded}, if the report ${issues} and ${open}`, async () => {
vm.isCollapsed = isCollapsed;
vm.alwaysOpen = alwaysOpen;
- Vue.nextTick()
- .then(() => {
- expect(vm.isExpanded).toBe(isExpanded);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.isExpanded).toBe(isExpanded);
});
});
});
@@ -148,79 +140,55 @@ describe('Report section', () => {
describe('toggleCollapsed', () => {
const hiddenCss = { display: 'none' };
- it('toggles issues', (done) => {
+ it('toggles issues', async () => {
vm.$el.querySelector('button').click();
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse');
-
- vm.$el.querySelector('button').click();
- })
- .then(Vue.nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
+ expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse');
+
+ vm.$el.querySelector('button').click();
+
+ await nextTick();
+ expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss);
+ expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand');
});
- it('is always expanded, if always-open is set to true', (done) => {
+ it('is always expanded, if always-open is set to true', async () => {
vm.alwaysOpen = true;
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button')).toBeNull();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
+ expect(vm.$el.querySelector('button')).toBeNull();
});
});
});
describe('snowplow events', () => {
- it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', (done) => {
+ it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', async () => {
createComponent({ hasIssues: true, shouldEmitToggleEvent: true });
expect(wrapper.emitted().toggleEvent).toBeUndefined();
findCollapseButton().trigger('click');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.emitted().toggleEvent).toHaveLength(1);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.emitted().toggleEvent).toHaveLength(1);
});
- it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', (done) => {
+ it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', async () => {
createComponent({ hasIssues: true });
expect(wrapper.emitted().toggleEvent).toBeUndefined();
findCollapseButton().trigger('click');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.emitted().toggleEvent).toBeUndefined();
});
- it('does not emit an event if always-open is set to true', (done) => {
+ it('does not emit an event if always-open is set to true', async () => {
createComponent({ alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true });
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.emitted().toggleEvent).toBeUndefined();
});
});
diff --git a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
index 2f6f62ca1d3..8a854a92ad7 100644
--- a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
@@ -1,13 +1,13 @@
import { GlBadge, GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
import TestIssueBody from '~/reports/grouped_test_report/components/test_issue_body.vue';
import { failedIssue, successIssue } from '../../mock_data/mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test issue body', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('Test issue body', () => {
wrapper = extendedWrapper(
shallowMount(TestIssueBody, {
store,
- localVue,
propsData: {
issue,
},
diff --git a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
index c60c1f7b63c..90edb27d1d6 100644
--- a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import Api from '~/api';
import GroupedTestReportsApp from '~/reports/grouped_test_report/grouped_test_reports_app.vue';
@@ -14,8 +15,7 @@ import resolvedFailures from '../mock_data/resolved_failures.json';
jest.mock('~/api.js');
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Grouped test reports app', () => {
const endpoint = 'endpoint.json';
@@ -27,7 +27,6 @@ describe('Grouped test reports app', () => {
const mountComponent = ({ props = { pipelinePath } } = {}) => {
wrapper = mount(GroupedTestReportsApp, {
store: mockStore,
- localVue,
propsData: {
endpoint,
headBlobPath,
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index d3b60ec3768..109e5cef49b 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -1,8 +1,8 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -12,10 +12,10 @@ import BlobButtonGroup from '~/repository/components/blob_button_group.vue';
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import BlobEdit from '~/repository/components/blob_edit.vue';
import ForkSuggestion from '~/repository/components/fork_suggestion.vue';
-import { loadViewer, viewerProps } from '~/repository/components/blob_viewers';
+import { loadViewer } from '~/repository/components/blob_viewers';
import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';
import EmptyViewer from '~/repository/components/blob_viewers/empty_viewer.vue';
-import SourceViewer from '~/vue_shared/components/source_viewer.vue';
+import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue';
import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
import { redirectTo } from '~/lib/utils/url_utility';
import { isLoggedIn } from '~/lib/utils/common_utils';
@@ -36,11 +36,10 @@ jest.mock('~/lib/utils/common_utils');
let wrapper;
let mockResolver;
-const localVue = createLocalVue();
const mockAxios = new MockAdapter(axios);
const createComponent = async (mockData = {}, mountFn = shallowMount) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const {
blob = simpleViewerMock,
@@ -51,6 +50,7 @@ const createComponent = async (mockData = {}, mountFn = shallowMount) => {
createMergeRequestIn = userPermissionsMock.createMergeRequestIn,
isBinary,
inject = {},
+ highlightJs = true,
} = mockData;
const project = {
@@ -75,11 +75,17 @@ const createComponent = async (mockData = {}, mountFn = shallowMount) => {
wrapper = extendedWrapper(
mountFn(BlobContentViewer, {
- localVue,
apolloProvider: fakeApollo,
propsData: propsMock,
mixins: [{ data: () => ({ ref: refMock }) }],
- provide: { ...inject },
+ provide: {
+ targetBranch: 'test',
+ originalBranch: 'default-ref',
+ ...inject,
+ glFeatures: {
+ highlightJs,
+ },
+ },
}),
);
@@ -100,7 +106,6 @@ describe('Blob content viewer component', () => {
const findForkSuggestion = () => wrapper.findComponent(ForkSuggestion);
beforeEach(() => {
- gon.features = { highlightJs: true };
isLoggedIn.mockReturnValue(true);
});
@@ -138,6 +143,15 @@ describe('Blob content viewer component', () => {
});
describe('legacy viewers', () => {
+ it('loads a legacy viewer when a the fileType is text and the highlightJs feature is turned off', async () => {
+ await createComponent({
+ blob: { ...simpleViewerMock, fileType: 'text', highlightJs: false },
+ });
+
+ expect(mockAxios.history.get).toHaveLength(1);
+ expect(mockAxios.history.get[0].url).toEqual('some_file.js?format=json&viewer=simple');
+ });
+
it('loads a legacy viewer when a viewer component is not available', async () => {
await createComponent({ blob: { ...simpleViewerMock, fileType: 'unknown' } });
@@ -203,44 +217,39 @@ describe('Blob content viewer component', () => {
describe('Blob viewer', () => {
afterEach(() => {
loadViewer.mockRestore();
- viewerProps.mockRestore();
});
it('does not render a BlobContent component if a Blob viewer is available', async () => {
loadViewer.mockReturnValue(() => true);
await createComponent({ blob: richViewerMock });
-
+ await waitForPromises();
expect(findBlobContent().exists()).toBe(false);
});
it.each`
- viewer | loadViewerReturnValue | viewerPropsReturnValue
- ${'empty'} | ${EmptyViewer} | ${{}}
- ${'download'} | ${DownloadViewer} | ${{ filePath: '/some/file/path', fileName: 'test.js', fileSize: 100 }}
- ${'text'} | ${SourceViewer} | ${{ content: 'test', autoDetect: true }}
- `(
- 'renders viewer component for $viewer files',
- async ({ viewer, loadViewerReturnValue, viewerPropsReturnValue }) => {
- loadViewer.mockReturnValue(loadViewerReturnValue);
- viewerProps.mockReturnValue(viewerPropsReturnValue);
-
- createComponent({
- blob: {
- ...simpleViewerMock,
- fileType: 'null',
- simpleViewer: {
- ...simpleViewerMock.simpleViewer,
- fileType: viewer,
- },
+ viewer | loadViewerReturnValue
+ ${'empty'} | ${EmptyViewer}
+ ${'download'} | ${DownloadViewer}
+ ${'text'} | ${SourceViewer}
+ `('renders viewer component for $viewer files', async ({ viewer, loadViewerReturnValue }) => {
+ loadViewer.mockReturnValue(loadViewerReturnValue);
+
+ createComponent({
+ blob: {
+ ...simpleViewerMock,
+ fileType: 'null',
+ simpleViewer: {
+ ...simpleViewerMock.simpleViewer,
+ fileType: viewer,
},
- });
+ },
+ });
- await nextTick();
+ await waitForPromises();
- expect(loadViewer).toHaveBeenCalledWith(viewer);
- expect(wrapper.findComponent(loadViewerReturnValue).exists()).toBe(true);
- },
- );
+ expect(loadViewer).toHaveBeenCalledWith(viewer, false);
+ expect(wrapper.findComponent(loadViewerReturnValue).exists()).toBe(true);
+ });
});
describe('BlobHeader action slot', () => {
@@ -354,6 +363,19 @@ describe('Blob content viewer component', () => {
});
describe('blob info query', () => {
+ it.each`
+ highlightJs | shouldFetchRawText
+ ${true} | ${true}
+ ${false} | ${false}
+ `(
+ 'calls blob info query with shouldFetchRawText: $shouldFetchRawText when highlightJs (feature flag): $highlightJs',
+ async ({ highlightJs, shouldFetchRawText }) => {
+ await createComponent({ highlightJs });
+
+ expect(mockResolver).toHaveBeenCalledWith(expect.objectContaining({ shouldFetchRawText }));
+ },
+ );
+
it('is called with originalBranch value if the prop has a value', async () => {
await createComponent({ inject: { originalBranch: 'some-branch' } });
diff --git a/spec/frontend/repository/components/blob_controls_spec.js b/spec/frontend/repository/components/blob_controls_spec.js
index 03e389ea5cb..6da1861ea7c 100644
--- a/spec/frontend/repository/components/blob_controls_spec.js
+++ b/spec/frontend/repository/components/blob_controls_spec.js
@@ -1,6 +1,6 @@
-import { createLocalVue } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
+
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import BlobControls from '~/repository/components/blob_controls.vue';
@@ -16,10 +16,8 @@ let router;
let wrapper;
let mockResolver;
-const localVue = createLocalVue();
-
const createComponent = async () => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const project = { ...blobControlsDataMock };
const projectPath = 'some/project';
@@ -31,7 +29,6 @@ const createComponent = async () => {
mockResolver = jest.fn().mockResolvedValue({ data: { project } });
wrapper = shallowMountExtended(BlobControls, {
- localVue,
router,
apolloProvider: createMockApollo([[blobControlsQuery, mockResolver]]),
propsData: { projectPath },
diff --git a/spec/frontend/repository/components/blob_viewers/download_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/download_viewer_spec.js
index c71b2b3c55c..5fe25ced302 100644
--- a/spec/frontend/repository/components/blob_viewers/download_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_viewers/download_viewer_spec.js
@@ -6,42 +6,33 @@ import DownloadViewer from '~/repository/components/blob_viewers/download_viewer
describe('Text Viewer', () => {
let wrapper;
- const DEFAULT_PROPS = {
- fileName: 'file_name.js',
- filePath: '/some/file/path',
- fileSize: 2269674,
+ const DEFAULT_BLOB_DATA = {
+ name: 'file_name.js',
+ rawPath: '/some/file/path',
+ rawSize: 2269674,
};
- const createComponent = (props = {}) => {
+ const createComponent = (blobData = {}) => {
wrapper = shallowMount(DownloadViewer, {
propsData: {
- ...DEFAULT_PROPS,
- ...props,
+ blob: {
+ ...DEFAULT_BLOB_DATA,
+ ...blobData,
+ },
},
});
};
- it('renders component', () => {
- createComponent();
-
- const { fileName, filePath, fileSize } = DEFAULT_PROPS;
- expect(wrapper.props()).toMatchObject({
- fileName,
- filePath,
- fileSize,
- });
- });
-
it('renders download human readable file size text', () => {
createComponent();
- const downloadText = `Download (${numberToHumanSize(DEFAULT_PROPS.fileSize)})`;
+ const downloadText = `Download (${numberToHumanSize(DEFAULT_BLOB_DATA.rawSize)})`;
expect(wrapper.text()).toBe(downloadText);
});
it('renders download text', () => {
createComponent({
- fileSize: 0,
+ rawSize: 0,
});
expect(wrapper.text()).toBe('Download');
@@ -49,13 +40,13 @@ describe('Text Viewer', () => {
it('renders download link', () => {
createComponent();
- const { filePath, fileName } = DEFAULT_PROPS;
+ const { rawPath, name } = DEFAULT_BLOB_DATA;
expect(wrapper.findComponent(GlLink).attributes()).toMatchObject({
rel: 'nofollow',
target: '_blank',
- href: filePath,
- download: fileName,
+ href: rawPath,
+ download: name,
});
});
diff --git a/spec/frontend/repository/components/blob_viewers/image_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/image_viewer_spec.js
index 6735dddf51e..c23de0efdfd 100644
--- a/spec/frontend/repository/components/blob_viewers/image_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_viewers/image_viewer_spec.js
@@ -4,13 +4,13 @@ import ImageViewer from '~/repository/components/blob_viewers/image_viewer.vue';
describe('Image Viewer', () => {
let wrapper;
- const propsData = {
- url: 'some/image.png',
- alt: 'image.png',
+ const DEFAULT_BLOB_DATA = {
+ rawPath: 'some/image.png',
+ name: 'image.png',
};
const createComponent = () => {
- wrapper = shallowMount(ImageViewer, { propsData });
+ wrapper = shallowMount(ImageViewer, { propsData: { blob: DEFAULT_BLOB_DATA } });
};
const findImage = () => wrapper.find('[data-testid="image"]');
@@ -19,7 +19,7 @@ describe('Image Viewer', () => {
createComponent();
expect(findImage().exists()).toBe(true);
- expect(findImage().attributes('src')).toBe(propsData.url);
- expect(findImage().attributes('alt')).toBe(propsData.alt);
+ expect(findImage().attributes('src')).toBe(DEFAULT_BLOB_DATA.rawPath);
+ expect(findImage().attributes('alt')).toBe(DEFAULT_BLOB_DATA.name);
});
});
diff --git a/spec/frontend/repository/components/blob_viewers/lfs_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/lfs_viewer_spec.js
new file mode 100644
index 00000000000..5caeb85834d
--- /dev/null
+++ b/spec/frontend/repository/components/blob_viewers/lfs_viewer_spec.js
@@ -0,0 +1,41 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import LfsViewer from '~/repository/components/blob_viewers/lfs_viewer.vue';
+
+describe('LFS Viewer', () => {
+ let wrapper;
+
+ const DEFAULT_BLOB_DATA = {
+ name: 'file_name.js',
+ rawPath: '/some/file/path',
+ };
+
+ const createComponent = () => {
+ wrapper = shallowMount(LfsViewer, {
+ propsData: { blob: { ...DEFAULT_BLOB_DATA } },
+ stubs: { GlSprintf },
+ });
+ };
+
+ const findLink = () => wrapper.findComponent(GlLink);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ it('renders the correct text', () => {
+ expect(wrapper.text()).toBe(
+ 'This content could not be displayed because it is stored in LFS. You can download it instead.',
+ );
+ });
+
+ it('renders download link', () => {
+ const { rawPath, name } = DEFAULT_BLOB_DATA;
+
+ expect(findLink().attributes()).toMatchObject({
+ target: '_blank',
+ href: rawPath,
+ download: name,
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js
index fd910002529..10eea691335 100644
--- a/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js
@@ -6,10 +6,12 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('PDF Viewer', () => {
let wrapper;
- const defaultPropsData = { url: 'some/pdf_blob.pdf' };
+ const DEFAULT_BLOB_DATA = { rawPath: 'some/pdf_blob.pdf' };
- const createComponent = (fileSize = 999) => {
- wrapper = shallowMountExtended(Component, { propsData: { ...defaultPropsData, fileSize } });
+ const createComponent = (rawSize = 999) => {
+ wrapper = shallowMountExtended(Component, {
+ propsData: { blob: { ...DEFAULT_BLOB_DATA, rawSize } },
+ });
};
const findPDFViewer = () => wrapper.findComponent(PdfViewer);
@@ -20,7 +22,7 @@ describe('PDF Viewer', () => {
createComponent();
expect(findPDFViewer().exists()).toBe(true);
- expect(findPDFViewer().props('pdf')).toBe(defaultPropsData.url);
+ expect(findPDFViewer().props('pdf')).toBe(DEFAULT_BLOB_DATA.rawPath);
});
describe('Too large', () => {
diff --git a/spec/frontend/repository/components/blob_viewers/video_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/video_viewer_spec.js
index 34448c03b31..2e79a1496ce 100644
--- a/spec/frontend/repository/components/blob_viewers/video_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_viewers/video_viewer_spec.js
@@ -4,10 +4,10 @@ import VideoViewer from '~/repository/components/blob_viewers/video_viewer.vue';
describe('Video Viewer', () => {
let wrapper;
- const propsData = { url: 'some/video.mp4' };
+ const DEFAULT_BLOB_DATA = { rawPath: 'some/video.mp4' };
const createComponent = () => {
- wrapper = shallowMountExtended(VideoViewer, { propsData });
+ wrapper = shallowMountExtended(VideoViewer, { propsData: { blob: { ...DEFAULT_BLOB_DATA } } });
};
const findVideo = () => wrapper.findByTestId('video');
@@ -16,7 +16,7 @@ describe('Video Viewer', () => {
createComponent();
expect(findVideo().exists()).toBe(true);
- expect(findVideo().attributes('src')).toBe(propsData.url);
+ expect(findVideo().attributes('src')).toBe(DEFAULT_BLOB_DATA.rawPath);
expect(findVideo().attributes('controls')).not.toBeUndefined();
});
});
diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js
index ad2cbd70187..0e300291d05 100644
--- a/spec/frontend/repository/components/breadcrumbs_spec.js
+++ b/spec/frontend/repository/components/breadcrumbs_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
import NewDirectoryModal from '~/repository/components/new_directory_modal.vue';
@@ -79,7 +80,7 @@ describe('Repository breadcrumbs component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlDropdown).exists()).toBe(false);
});
@@ -106,7 +107,7 @@ describe('Repository breadcrumbs component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
@@ -125,7 +126,7 @@ describe('Repository breadcrumbs component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findUploadBlobModal().exists()).toBe(true);
});
@@ -149,7 +150,7 @@ describe('Repository breadcrumbs component', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findNewDirectoryModal().exists()).toBe(true);
});
diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js
index fe05a981845..bb710c3a96c 100644
--- a/spec/frontend/repository/components/last_commit_spec.js
+++ b/spec/frontend/repository/components/last_commit_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import LastCommit from '~/repository/components/last_commit.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -63,7 +64,7 @@ describe('Repository last commit component', () => {
`('$label when loading icon $loading is true', async ({ loading }) => {
factory(createCommitData(), loading);
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find(GlLoadingIcon).exists()).toBe(loading);
});
@@ -71,7 +72,7 @@ describe('Repository last commit component', () => {
it('renders commit widget', async () => {
factory();
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.element).toMatchSnapshot();
});
@@ -79,7 +80,7 @@ describe('Repository last commit component', () => {
it('renders short commit ID', async () => {
factory();
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('[data-testid="last-commit-id-label"]').text()).toEqual('12345678');
});
@@ -87,7 +88,7 @@ describe('Repository last commit component', () => {
it('hides pipeline components when pipeline does not exist', async () => {
factory(createCommitData({ pipeline: null }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.js-commit-pipeline').exists()).toBe(false);
});
@@ -95,7 +96,7 @@ describe('Repository last commit component', () => {
it('renders pipeline components', async () => {
factory();
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.js-commit-pipeline').exists()).toBe(true);
});
@@ -103,7 +104,7 @@ describe('Repository last commit component', () => {
it('hides author component when author does not exist', async () => {
factory(createCommitData({ author: null }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.js-user-link').exists()).toBe(false);
expect(vm.find(UserAvatarLink).exists()).toBe(false);
@@ -112,7 +113,7 @@ describe('Repository last commit component', () => {
it('does not render description expander when description is null', async () => {
factory(createCommitData({ descriptionHtml: null }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.text-expander').exists()).toBe(false);
expect(vm.find('.commit-row-description').exists()).toBe(false);
@@ -121,11 +122,11 @@ describe('Repository last commit component', () => {
it('expands commit description when clicking expander', async () => {
factory(createCommitData({ descriptionHtml: 'Test description' }));
- await vm.vm.$nextTick();
+ await nextTick();
vm.find('.text-expander').vm.$emit('click');
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.commit-row-description').isVisible()).toBe(true);
expect(vm.find('.text-expander').classes('open')).toBe(true);
@@ -134,7 +135,7 @@ describe('Repository last commit component', () => {
it('strips the first newline of the description', async () => {
factory(createCommitData({ descriptionHtml: '&#x000A;Update ADOPTERS.md' }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.commit-row-description').html()).toBe(
'<pre class="commit-row-description gl-mb-3">Update ADOPTERS.md</pre>',
@@ -144,7 +145,7 @@ describe('Repository last commit component', () => {
it('renders the signature HTML as returned by the backend', async () => {
factory(createCommitData({ signatureHtml: '<button>Verified</button>' }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.element).toMatchSnapshot();
});
@@ -152,7 +153,7 @@ describe('Repository last commit component', () => {
it('sets correct CSS class if the commit message is empty', async () => {
factory(createCommitData({ message: '' }));
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find('.item-title').classes()).toContain(emptyMessageClass);
});
diff --git a/spec/frontend/repository/components/preview/index_spec.js b/spec/frontend/repository/components/preview/index_spec.js
index 2490258a048..0d9bfc62ed5 100644
--- a/spec/frontend/repository/components/preview/index_spec.js
+++ b/spec/frontend/repository/components/preview/index_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { handleLocationHash } from '~/lib/utils/common_utils';
import Preview from '~/repository/components/preview/index.vue';
@@ -28,7 +29,7 @@ describe('Repository file preview component', () => {
vm.destroy();
});
- it('renders file HTML', () => {
+ it('renders file HTML', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
@@ -38,12 +39,11 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ readme: { html: '<div class="blob">test</div>' } });
- return vm.vm.$nextTick(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(vm.element).toMatchSnapshot();
});
- it('handles hash after render', () => {
+ it('handles hash after render', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
@@ -53,15 +53,11 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ readme: { html: '<div class="blob">test</div>' } });
- return vm.vm
- .$nextTick()
- .then(vm.vm.$nextTick())
- .then(() => {
- expect(handleLocationHash).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(handleLocationHash).toHaveBeenCalled();
});
- it('renders loading icon', () => {
+ it('renders loading icon', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
@@ -71,8 +67,7 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ loading: 1 });
- return vm.vm.$nextTick(() => {
- expect(vm.find(GlLoadingIcon).exists()).toBe(true);
- });
+ await nextTick();
+ expect(vm.find(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js
index 2cd88944f81..07c151ad935 100644
--- a/spec/frontend/repository/components/table/index_spec.js
+++ b/spec/frontend/repository/components/table/index_spec.js
@@ -1,5 +1,6 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Table from '~/repository/components/table/index.vue';
import TableRow from '~/repository/components/table/row.vue';
@@ -86,18 +87,17 @@ describe('Repository table component', () => {
${'/'} | ${'main'}
${'app/assets'} | ${'main'}
${'/'} | ${'test'}
- `('renders table caption for $ref in $path', ({ path, ref }) => {
+ `('renders table caption for $ref in $path', async ({ path, ref }) => {
factory({ path });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ ref });
- return vm.vm.$nextTick(() => {
- expect(vm.find('.table').attributes('aria-label')).toEqual(
- `Files, directories, and submodules in the path ${path} for commit reference ${ref}`,
- );
- });
+ await nextTick();
+ expect(vm.find('.table').attributes('aria-label')).toEqual(
+ `Files, directories, and submodules in the path ${path} for commit reference ${ref}`,
+ );
});
it('shows loading icon', () => {
@@ -140,7 +140,7 @@ describe('Repository table component', () => {
showMoreButton().vm.$emit('click');
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.emitted('showMore')).toHaveLength(1);
});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 440baa72a3c..22570b2d6ed 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, GlIntersectionObserver } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import { nextTick } from 'vue';
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';
@@ -53,7 +54,7 @@ describe('Repository table row component', () => {
vm.destroy();
});
- it('renders table row', () => {
+ it('renders table row', async () => {
factory({
id: '1',
sha: '123',
@@ -62,12 +63,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(vm.element).toMatchSnapshot();
});
- it('renders a symlink table row', () => {
+ it('renders a symlink table row', async () => {
factory({
id: '1',
sha: '123',
@@ -77,12 +77,11 @@ describe('Repository table row component', () => {
mode: FILE_SYMLINK_MODE,
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(vm.element).toMatchSnapshot();
});
- it('renders table row for path with special character', () => {
+ it('renders table row for path with special character', async () => {
factory({
id: '1',
sha: '123',
@@ -91,9 +90,8 @@ describe('Repository table row component', () => {
currentPath: 'test$',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(vm.element).toMatchSnapshot();
});
it('renders a gl-hover-load directive', () => {
@@ -116,7 +114,7 @@ describe('Repository table row component', () => {
${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
${'blob'} | ${RouterLinkStub} | ${'RouterLink'}
${'commit'} | ${'a'} | ${'hyperlink'}
- `('renders a $componentName for type $type', ({ type, component }) => {
+ `('renders a $componentName for type $type', async ({ type, component }) => {
factory({
id: '1',
sha: '123',
@@ -125,16 +123,15 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find(component).exists()).toBe(true);
- });
+ await nextTick();
+ expect(vm.find(component).exists()).toBe(true);
});
it.each`
path
${'test#'}
${'Änderungen'}
- `('renders link for $path', ({ path }) => {
+ `('renders link for $path', async ({ path }) => {
factory({
id: '1',
sha: '123',
@@ -143,14 +140,13 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find({ ref: 'link' }).props('to')).toEqual({
- path: `/-/tree/main/${encodeURIComponent(path)}`,
- });
+ await nextTick();
+ expect(vm.find({ ref: 'link' }).props('to')).toEqual({
+ path: `/-/tree/main/${encodeURIComponent(path)}`,
});
});
- it('renders link for directory with hash', () => {
+ it('renders link for directory with hash', async () => {
factory({
id: '1',
sha: '123',
@@ -159,12 +155,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find('.tree-item-link').props('to')).toEqual({ path: '/-/tree/main/test%23' });
- });
+ await nextTick();
+ expect(vm.find('.tree-item-link').props('to')).toEqual({ path: '/-/tree/main/test%23' });
});
- it('renders commit ID for submodule', () => {
+ it('renders commit ID for submodule', async () => {
factory({
id: '1',
sha: '123',
@@ -173,12 +168,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find('.commit-sha').text()).toContain('1');
- });
+ await nextTick();
+ expect(vm.find('.commit-sha').text()).toContain('1');
});
- it('renders link with href', () => {
+ it('renders link with href', async () => {
factory({
id: '1',
sha: '123',
@@ -188,12 +182,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find('a').attributes('href')).toEqual('https://test.com');
- });
+ await nextTick();
+ expect(vm.find('a').attributes('href')).toEqual('https://test.com');
});
- it('renders LFS badge', () => {
+ it('renders LFS badge', async () => {
factory({
id: '1',
sha: '123',
@@ -203,12 +196,11 @@ describe('Repository table row component', () => {
lfsOid: '1',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find(GlBadge).exists()).toBe(true);
- });
+ await nextTick();
+ expect(vm.find(GlBadge).exists()).toBe(true);
});
- it('renders commit and web links with href for submodule', () => {
+ it('renders commit and web links with href for submodule', async () => {
factory({
id: '1',
sha: '123',
@@ -219,13 +211,12 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find('a').attributes('href')).toEqual('https://test.com');
- expect(vm.find(GlLink).attributes('href')).toEqual('https://test.com/commit');
- });
+ await nextTick();
+ expect(vm.find('a').attributes('href')).toEqual('https://test.com');
+ expect(vm.find(GlLink).attributes('href')).toEqual('https://test.com/commit');
});
- it('renders lock icon', () => {
+ it('renders lock icon', async () => {
factory({
id: '1',
sha: '123',
@@ -234,10 +225,9 @@ describe('Repository table row component', () => {
currentPath: '/',
});
- return vm.vm.$nextTick().then(() => {
- expect(vm.find(GlIcon).exists()).toBe(true);
- expect(vm.find(GlIcon).props('name')).toBe('lock');
- });
+ await nextTick();
+ expect(vm.find(GlIcon).exists()).toBe(true);
+ expect(vm.find(GlIcon).props('name')).toBe('lock');
});
it('renders loading icon when path is loading', () => {
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 00ad1fc05f6..9d3a5394df8 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
@@ -50,7 +51,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ entries: { blobs: [{ name: 'README.md' }] } });
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.find(FilePreview).exists()).toBe(true);
});
@@ -60,7 +61,7 @@ describe('Repository table component', () => {
jest.spyOn(vm.vm, 'fetchFiles').mockImplementation(() => {});
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.vm.fetchFiles).toHaveBeenCalled();
expect(resetRequestedCommits).toHaveBeenCalled();
@@ -111,7 +112,7 @@ describe('Repository table component', () => {
it('is changes hasShowMore to false when "showMore" event is emitted', async () => {
findFileTable().vm.$emit('showMore');
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.vm.hasShowMore).toBe(false);
});
@@ -119,7 +120,7 @@ describe('Repository table component', () => {
it('changes clickedShowMore when "showMore" event is emitted', async () => {
findFileTable().vm.$emit('showMore');
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.vm.clickedShowMore).toBe(true);
});
@@ -140,7 +141,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ fetchCounter: 5, clickedShowMore: false });
- await vm.vm.$nextTick();
+ await nextTick();
expect(vm.vm.hasShowMore).toBe(false);
});
@@ -161,7 +162,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ entries: { blobs }, pagesLoaded });
- await vm.vm.$nextTick();
+ await nextTick();
expect(findFileTable().props('hasMore')).toBe(limitReached);
});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 6b8b0752485..bf024baa627 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -2,6 +2,7 @@ import { GlModal, GlFormInput, GlFormTextarea, GlToggle, GlAlert } from '@gitlab
import { shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -113,7 +114,7 @@ describe('UploadBlobModal', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ target: 'Not main' });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findMrToggle().exists()).toBe(true);
});
@@ -202,7 +203,7 @@ describe('UploadBlobModal', () => {
wrapper.vm.uploadFile = jest.fn();
wrapper.vm.replaceFile = jest.fn();
wrapper.vm.submitForm();
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const submitRequest = async () => {
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
index a5ee17ba672..5a6551cb94a 100644
--- a/spec/frontend/repository/mock_data.js
+++ b/spec/frontend/repository/mock_data.js
@@ -5,16 +5,20 @@ export const simpleViewerMock = {
rawSize: 123,
rawTextBlob: 'raw content',
fileType: 'text',
+ language: 'javascript',
path: 'some_file.js',
webPath: 'some_file.js',
editBlobPath: 'some_file.js/edit',
ideEditPath: 'some_file.js/ide/edit',
forkAndEditPath: 'some_file.js/fork/edit',
ideForkAndEditPath: 'some_file.js/fork/ide',
+ environmentFormattedExternalUrl: '',
+ environmentExternalUrlForRouteMap: '',
canModifyBlob: true,
canCurrentUserPushToBranch: true,
archived: false,
storedExternally: false,
+ externalStorageUrl: '',
externalStorage: 'lfs',
rawPath: 'some_file.js',
replacePath: 'some_file.js/replace',
@@ -46,6 +50,7 @@ export const userPermissionsMock = {
};
export const projectMock = {
+ __typename: 'Project',
id: '1234',
userPermissions: userPermissionsMock,
pathLocks: {
diff --git a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
index ad0bce5c9af..ff6a632a4f8 100644
--- a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
+++ b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -18,8 +19,7 @@ jest.mock('~/runner/sentry_utils');
const mockRunnerGraphqlId = runnerData.data.runner.id;
const mockRunnerId = `${getIdFromGraphQLId(mockRunnerGraphqlId)}`;
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('AdminRunnerEditApp', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('AdminRunnerEditApp', () => {
const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
wrapper = mountFn(AdminRunnerEditApp, {
- localVue,
apolloProvider: createMockApollo([[getRunnerQuery, mockRunnerQuery]]),
propsData: {
runnerId: mockRunnerId,
@@ -55,10 +54,11 @@ describe('AdminRunnerEditApp', () => {
expect(mockRunnerQuery).toHaveBeenCalledWith({ id: mockRunnerGraphqlId });
});
- it('displays the runner id', async () => {
+ it('displays the runner id and creation date', async () => {
await createComponentWithApollo({ mountFn: mount });
- expect(findRunnerHeader().text()).toContain(`Runner #${mockRunnerId} created`);
+ expect(findRunnerHeader().text()).toContain(`Runner #${mockRunnerId}`);
+ expect(findRunnerHeader().text()).toContain('created');
});
it('displays the runner type and status', async () => {
@@ -76,7 +76,7 @@ describe('AdminRunnerEditApp', () => {
it('error is reported to sentry', () => {
expect(captureException).toHaveBeenCalledWith({
- error: new Error('Network error: Error!'),
+ error: new Error('Error!'),
component: 'AdminRunnerEditApp',
});
});
diff --git a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
new file mode 100644
index 00000000000..4b651961112
--- /dev/null
+++ b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
@@ -0,0 +1,146 @@
+import Vue from 'vue';
+import { mount, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import RunnerHeader from '~/runner/components/runner_header.vue';
+import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
+import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
+import getRunnerQuery from '~/runner/graphql/get_runner.query.graphql';
+import AdminRunnerShowApp from '~/runner/admin_runner_show/admin_runner_show_app.vue';
+import { captureException } from '~/runner/sentry_utils';
+
+import { runnerData } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+const mockRunner = runnerData.data.runner;
+const mockRunnerGraphqlId = mockRunner.id;
+const mockRunnerId = `${getIdFromGraphQLId(mockRunnerGraphqlId)}`;
+
+Vue.use(VueApollo);
+
+describe('AdminRunnerShowApp', () => {
+ let wrapper;
+ let mockRunnerQuery;
+
+ const findRunnerHeader = () => wrapper.findComponent(RunnerHeader);
+ const findRunnerEditButton = () => wrapper.findComponent(RunnerEditButton);
+ const findRunnerPauseButton = () => wrapper.findComponent(RunnerPauseButton);
+
+ const mockRunnerQueryResult = (runner = {}) => {
+ mockRunnerQuery = jest.fn().mockResolvedValue({
+ data: {
+ runner: { ...mockRunner, ...runner },
+ },
+ });
+ };
+
+ const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(AdminRunnerShowApp, {
+ apolloProvider: createMockApollo([[getRunnerQuery, mockRunnerQuery]]),
+ propsData: {
+ runnerId: mockRunnerId,
+ ...props,
+ },
+ });
+
+ return waitForPromises();
+ };
+
+ afterEach(() => {
+ mockRunnerQuery.mockReset();
+ wrapper.destroy();
+ });
+
+ describe('When showing runner details', () => {
+ beforeEach(async () => {
+ mockRunnerQueryResult();
+
+ await createComponent({ mountFn: mount });
+ });
+
+ it('expect GraphQL ID to be requested', async () => {
+ expect(mockRunnerQuery).toHaveBeenCalledWith({ id: mockRunnerGraphqlId });
+ });
+
+ it('displays the runner header', async () => {
+ expect(findRunnerHeader().text()).toContain(`Runner #${mockRunnerId}`);
+ });
+
+ it('displays the runner edit and pause buttons', async () => {
+ expect(findRunnerEditButton().exists()).toBe(true);
+ expect(findRunnerPauseButton().exists()).toBe(true);
+ });
+
+ it('shows basic runner details', async () => {
+ const expected = `Description Instance runner
+ Last contact Never contacted
+ Version 1.0.0
+ IP Address 127.0.0.1
+ Configuration Runs untagged jobs
+ Maximum job timeout None
+ Tags None`.replace(/\s+/g, ' ');
+
+ expect(wrapper.text().replace(/\s+/g, ' ')).toContain(expected);
+ });
+
+ describe('when runner cannot be updated', () => {
+ beforeEach(async () => {
+ mockRunnerQueryResult({
+ userPermissions: {
+ updateRunner: false,
+ },
+ });
+
+ await createComponent({
+ mountFn: mount,
+ });
+ });
+
+ it('does not display the runner edit and pause buttons', () => {
+ expect(findRunnerEditButton().exists()).toBe(false);
+ expect(findRunnerPauseButton().exists()).toBe(false);
+ });
+ });
+
+ describe('when runner does not have an edit url ', () => {
+ beforeEach(async () => {
+ mockRunnerQueryResult({
+ editAdminUrl: null,
+ });
+
+ await createComponent({
+ mountFn: mount,
+ });
+ });
+
+ it('does not display the runner edit button', () => {
+ expect(findRunnerEditButton().exists()).toBe(false);
+ expect(findRunnerPauseButton().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('When there is an error', () => {
+ beforeEach(async () => {
+ mockRunnerQuery = jest.fn().mockRejectedValueOnce(new Error('Error!'));
+ await createComponent();
+ });
+
+ it('error is reported to sentry', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error('Error!'),
+ component: 'AdminRunnerShowApp',
+ });
+ });
+
+ it('error is shown to the user', () => {
+ expect(createAlert).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index 42be691ba4c..995f0cf7ba1 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -1,9 +1,13 @@
+import Vue from 'vue';
import { GlLink } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ extendedWrapper,
+ shallowMountExtended,
+ mountExtended,
+} from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -46,8 +50,7 @@ jest.mock('~/lib/utils/url_utility', () => ({
updateHistory: jest.fn(),
}));
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('AdminRunnersApp', () => {
let wrapper;
@@ -65,22 +68,19 @@ describe('AdminRunnersApp', () => {
const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
const findFilteredSearch = () => wrapper.findComponent(FilteredSearch);
- const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
const handlers = [
[getRunnersQuery, mockRunnersQuery],
[getRunnersCountQuery, mockRunnersCountQuery],
];
- wrapper = extendedWrapper(
- mountFn(AdminRunnersApp, {
- localVue,
- apolloProvider: createMockApollo(handlers),
- propsData: {
- registrationToken: mockRegistrationToken,
- ...props,
- },
- }),
- );
+ wrapper = mountFn(AdminRunnersApp, {
+ apolloProvider: createMockApollo(handlers),
+ propsData: {
+ registrationToken: mockRegistrationToken,
+ ...props,
+ },
+ });
};
beforeEach(async () => {
@@ -98,7 +98,7 @@ describe('AdminRunnersApp', () => {
});
it('shows total runner counts', async () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
@@ -129,7 +129,7 @@ describe('AdminRunnersApp', () => {
return Promise.resolve({ data: { runners: { count } } });
});
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
@@ -157,7 +157,7 @@ describe('AdminRunnersApp', () => {
return Promise.resolve({ data: { runners: { count } } });
});
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
@@ -175,7 +175,7 @@ describe('AdminRunnersApp', () => {
});
it('runner item links to the runner admin page', async () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
@@ -198,7 +198,7 @@ describe('AdminRunnersApp', () => {
});
it('sets tokens in the filtered search', () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
expect(findFilteredSearch().props('tokens')).toEqual([
expect.objectContaining({
@@ -281,6 +281,7 @@ describe('AdminRunnersApp', () => {
},
});
createComponent();
+ await waitForPromises();
});
it('shows a message for no results', async () => {
@@ -289,9 +290,10 @@ describe('AdminRunnersApp', () => {
});
describe('when runners query fails', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockRunnersQuery = jest.fn().mockRejectedValue(new Error('Error!'));
createComponent();
+ await waitForPromises();
});
it('error is shown to the user', async () => {
@@ -300,17 +302,18 @@ describe('AdminRunnersApp', () => {
it('error is reported to sentry', async () => {
expect(captureException).toHaveBeenCalledWith({
- error: new Error('Network error: Error!'),
+ error: new Error('Error!'),
component: 'AdminRunnersApp',
});
});
});
describe('Pagination', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockRunnersQuery = jest.fn().mockResolvedValue(runnersDataPaginated);
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
+ await waitForPromises();
});
it('more pages can be selected', () => {
diff --git a/spec/frontend/runner/components/cells/link_cell_spec.js b/spec/frontend/runner/components/cells/link_cell_spec.js
new file mode 100644
index 00000000000..a59a0eaa5d8
--- /dev/null
+++ b/spec/frontend/runner/components/cells/link_cell_spec.js
@@ -0,0 +1,72 @@
+import { GlLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import LinkCell from '~/runner/components/cells/link_cell.vue';
+
+describe('LinkCell', () => {
+ let wrapper;
+
+ const findGlLink = () => wrapper.find(GlLink);
+ const findSpan = () => wrapper.find('span');
+
+ const createComponent = ({ props = {}, ...options } = {}) => {
+ wrapper = shallowMountExtended(LinkCell, {
+ propsData: {
+ ...props,
+ },
+ ...options,
+ });
+ };
+
+ it('when an href is provided, renders a link', () => {
+ createComponent({ props: { href: '/url' } });
+ expect(findGlLink().exists()).toBe(true);
+ });
+
+ it('when an href is not provided, renders no link', () => {
+ createComponent();
+ expect(findGlLink().exists()).toBe(false);
+ });
+
+ describe.each`
+ href | findContent
+ ${null} | ${findSpan}
+ ${'/url'} | ${findGlLink}
+ `('When href is $href', ({ href, findContent }) => {
+ const content = 'My Text';
+ const attrs = { foo: 'bar' };
+ const listeners = {
+ click: jest.fn(),
+ };
+
+ beforeEach(() => {
+ createComponent({
+ props: { href },
+ slots: {
+ default: content,
+ },
+ attrs,
+ listeners,
+ });
+ });
+
+ afterAll(() => {
+ listeners.click.mockReset();
+ });
+
+ it('Renders content', () => {
+ expect(findContent().text()).toBe(content);
+ });
+
+ it('Passes attributes', () => {
+ expect(findContent().attributes()).toMatchObject(attrs);
+ });
+
+ it('Passes event listeners', () => {
+ expect(listeners.click).toHaveBeenCalledTimes(0);
+
+ findContent().vm.$emit('click');
+
+ expect(listeners.click).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
index 4233d86c24c..dcb0af67784 100644
--- a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -1,7 +1,7 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { createAlert } from '~/flash';
@@ -9,11 +9,12 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { captureException } from '~/runner/sentry_utils';
import RunnerActionCell from '~/runner/components/cells/runner_actions_cell.vue';
+import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
+import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
import RunnerDeleteModal from '~/runner/components/runner_delete_modal.vue';
import getGroupRunnersQuery from '~/runner/graphql/get_group_runners.query.graphql';
import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
-import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
import { runnersData } from '../../mock_data';
const mockRunner = runnersData.data.runners.nodes[0];
@@ -21,8 +22,7 @@ const mockRunner = runnersData.data.runners.nodes[0];
const getRunnersQueryName = getRunnersQuery.definitions[0].name.value;
const getGroupRunnersQueryName = getGroupRunnersQuery.definitions[0].name.value;
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
jest.mock('~/flash');
jest.mock('~/runner/sentry_utils');
@@ -32,44 +32,37 @@ describe('RunnerTypeCell', () => {
const mockToastShow = jest.fn();
const runnerDeleteMutationHandler = jest.fn();
- const runnerActionsUpdateMutationHandler = jest.fn();
- const findEditBtn = () => wrapper.findByTestId('edit-runner');
- const findToggleActiveBtn = () => wrapper.findByTestId('toggle-active-runner');
+ const findEditBtn = () => wrapper.findComponent(RunnerEditButton);
+ const findRunnerPauseBtn = () => wrapper.findComponent(RunnerPauseButton);
const findRunnerDeleteModal = () => wrapper.findComponent(RunnerDeleteModal);
const findDeleteBtn = () => wrapper.findByTestId('delete-runner');
const getTooltip = (w) => getBinding(w.element, 'gl-tooltip')?.value;
const createComponent = (runner = {}, options) => {
- wrapper = extendedWrapper(
- shallowMount(RunnerActionCell, {
- propsData: {
- runner: {
- id: mockRunner.id,
- shortSha: mockRunner.shortSha,
- editAdminUrl: mockRunner.editAdminUrl,
- userPermissions: mockRunner.userPermissions,
- active: mockRunner.active,
- ...runner,
- },
+ wrapper = shallowMountExtended(RunnerActionCell, {
+ propsData: {
+ runner: {
+ id: mockRunner.id,
+ shortSha: mockRunner.shortSha,
+ editAdminUrl: mockRunner.editAdminUrl,
+ userPermissions: mockRunner.userPermissions,
+ active: mockRunner.active,
+ ...runner,
},
- localVue,
- apolloProvider: createMockApollo([
- [runnerDeleteMutation, runnerDeleteMutationHandler],
- [runnerActionsUpdateMutation, runnerActionsUpdateMutationHandler],
- ]),
- directives: {
- GlTooltip: createMockDirective(),
- GlModal: createMockDirective(),
- },
- mocks: {
- $toast: {
- show: mockToastShow,
- },
+ },
+ apolloProvider: createMockApollo([[runnerDeleteMutation, runnerDeleteMutationHandler]]),
+ directives: {
+ GlTooltip: createMockDirective(),
+ GlModal: createMockDirective(),
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
},
- ...options,
- }),
- );
+ },
+ ...options,
+ });
};
beforeEach(() => {
@@ -80,21 +73,11 @@ describe('RunnerTypeCell', () => {
},
},
});
-
- runnerActionsUpdateMutationHandler.mockResolvedValue({
- data: {
- runnerUpdate: {
- runner: mockRunner,
- errors: [],
- },
- },
- });
});
afterEach(() => {
mockToastShow.mockReset();
runnerDeleteMutationHandler.mockReset();
- runnerActionsUpdateMutationHandler.mockReset();
wrapper.destroy();
});
@@ -126,116 +109,14 @@ describe('RunnerTypeCell', () => {
});
});
- describe('Toggle active action', () => {
- 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(() => {
- createComponent({ active: isActive });
- });
-
- it(`Displays a ${icon} button`, () => {
- expect(findToggleActiveBtn().props('loading')).toBe(false);
- expect(findToggleActiveBtn().props('icon')).toBe(icon);
- expect(getTooltip(findToggleActiveBtn())).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(getTooltip(findToggleActiveBtn())).toBe('');
- expect(findToggleActiveBtn().attributes('aria-label')).toBe('');
- });
-
- describe(`When clicking on the ${icon} button`, () => {
- it(`The apollo mutation to set active to ${newActiveValue} is called`, async () => {
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(0);
-
- await findToggleActiveBtn().vm.$emit('click');
-
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(1);
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledWith({
- input: {
- id: mockRunner.id,
- active: newActiveValue,
- },
- });
- });
-
- it('The button does not have a loading state after the mutation occurs', async () => {
- await findToggleActiveBtn().vm.$emit('click');
-
- expect(findToggleActiveBtn().props('loading')).toBe(true);
-
- await waitForPromises();
-
- expect(findToggleActiveBtn().props('loading')).toBe(false);
- });
- });
-
- describe('When update fails', () => {
- describe('On a network error', () => {
- const mockErrorMsg = 'Update error!';
-
- beforeEach(async () => {
- runnerActionsUpdateMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
-
- await findToggleActiveBtn().vm.$emit('click');
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`Network error: ${mockErrorMsg}`),
- component: 'RunnerActionsCell',
- });
- });
-
- it('error is shown to the user', () => {
- expect(createAlert).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('On a validation error', () => {
- const mockErrorMsg = 'Runner not found!';
- const mockErrorMsg2 = 'User not allowed!';
-
- beforeEach(async () => {
- runnerActionsUpdateMutationHandler.mockResolvedValue({
- data: {
- runnerUpdate: {
- runner: mockRunner,
- errors: [mockErrorMsg, mockErrorMsg2],
- },
- },
- });
-
- await findToggleActiveBtn().vm.$emit('click');
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
- component: 'RunnerActionsCell',
- });
- });
+ describe('Pause action', () => {
+ it('Renders a compact pause button', () => {
+ createComponent();
- it('error is shown to the user', () => {
- expect(createAlert).toHaveBeenCalledTimes(1);
- });
- });
- });
+ expect(findRunnerPauseBtn().props('compact')).toBe(true);
});
- it('Does not render the runner toggle active button when user cannot update', () => {
+ it('Does not render the runner pause button when user cannot update', () => {
createComponent({
userPermissions: {
...mockRunner.userPermissions,
@@ -243,7 +124,7 @@ describe('RunnerTypeCell', () => {
},
});
- expect(findToggleActiveBtn().exists()).toBe(false);
+ expect(findRunnerPauseBtn().exists()).toBe(false);
});
});
@@ -308,8 +189,9 @@ describe('RunnerTypeCell', () => {
});
describe('When delete is clicked', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findRunnerDeleteModal().vm.$emit('primary');
+ await waitForPromises();
});
it('The delete mutation is called correctly', () => {
@@ -324,7 +206,8 @@ describe('RunnerTypeCell', () => {
expect(getTooltip(findDeleteBtn())).toBe('');
});
- it('The toast notification is shown', () => {
+ it('The toast notification is shown', async () => {
+ await waitForPromises();
expect(mockToastShow).toHaveBeenCalledTimes(1);
expect(mockToastShow).toHaveBeenCalledWith(
expect.stringContaining(`#${getIdFromGraphQLId(mockRunner.id)} (${mockRunner.shortSha})`),
@@ -336,15 +219,16 @@ describe('RunnerTypeCell', () => {
describe('On a network error', () => {
const mockErrorMsg = 'Delete error!';
- beforeEach(() => {
+ beforeEach(async () => {
runnerDeleteMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
findRunnerDeleteModal().vm.$emit('primary');
+ await waitForPromises();
});
it('error is reported to sentry', () => {
expect(captureException).toHaveBeenCalledWith({
- error: new Error(`Network error: ${mockErrorMsg}`),
+ error: new Error(mockErrorMsg),
component: 'RunnerActionsCell',
});
});
@@ -362,7 +246,7 @@ describe('RunnerTypeCell', () => {
const mockErrorMsg = 'Runner not found!';
const mockErrorMsg2 = 'User not allowed!';
- beforeEach(() => {
+ beforeEach(async () => {
runnerDeleteMutationHandler.mockResolvedValue({
data: {
runnerDelete: {
@@ -372,6 +256,7 @@ describe('RunnerTypeCell', () => {
});
findRunnerDeleteModal().vm.$emit('primary');
+ await waitForPromises();
});
it('error is reported to sentry', () => {
diff --git a/spec/frontend/runner/components/registration/registration_dropdown_spec.js b/spec/frontend/runner/components/registration/registration_dropdown_spec.js
index d18d2bec18e..da8ef7c3af0 100644
--- a/spec/frontend/runner/components/registration/registration_dropdown_spec.js
+++ b/spec/frontend/runner/components/registration/registration_dropdown_spec.js
@@ -1,9 +1,11 @@
import { GlDropdown, GlDropdownItem, GlDropdownForm } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount, createWrapper } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount, shallowMount, createWrapper } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
@@ -73,8 +75,7 @@ describe('RegistrationDropdown', () => {
});
describe('When the dropdown item is clicked', () => {
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const requestHandlers = [
[getRunnerPlatformsQuery, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
@@ -84,10 +85,9 @@ describe('RegistrationDropdown', () => {
const findModalInBody = () =>
createWrapper(document.body).find('[data-testid="runner-instructions-modal"]');
- beforeEach(() => {
+ beforeEach(async () => {
createComponent(
{
- localVue,
// Mock load modal contents from API
apolloProvider: createMockApollo(requestHandlers),
// Use `attachTo` to find the modal
@@ -96,7 +96,8 @@ describe('RegistrationDropdown', () => {
mount,
);
- findRegistrationInstructionsDropdownItem().trigger('click');
+ await findRegistrationInstructionsDropdownItem().trigger('click');
+ await waitForPromises();
});
afterEach(() => {
diff --git a/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js
index e75decddf70..d2deb49a5f7 100644
--- a/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js
+++ b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js
@@ -1,6 +1,7 @@
import { GlDropdownItem, GlLoadingIcon, GlToast, GlModal } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -14,9 +15,8 @@ import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
jest.mock('~/flash');
jest.mock('~/runner/sentry_utils');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-localVue.use(GlToast);
+Vue.use(VueApollo);
+Vue.use(GlToast);
const mockNewToken = 'NEW_TOKEN';
const modalID = 'token-reset-modal';
@@ -34,7 +34,6 @@ describe('RegistrationTokenResetDropdownItem', () => {
const createComponent = ({ props, provide = {} } = {}) => {
wrapper = shallowMount(RegistrationTokenResetDropdownItem, {
- localVue,
provide,
propsData: {
type: INSTANCE_TYPE,
@@ -163,10 +162,10 @@ describe('RegistrationTokenResetDropdownItem', () => {
await waitForPromises();
expect(createAlert).toHaveBeenLastCalledWith({
- message: `Network error: ${mockErrorMsg}`,
+ message: mockErrorMsg,
});
expect(captureException).toHaveBeenCalledWith({
- error: new Error(`Network error: ${mockErrorMsg}`),
+ error: new Error(mockErrorMsg),
component: 'RunnerRegistrationTokenReset',
});
});
diff --git a/spec/frontend/runner/components/registration/registration_token_spec.js b/spec/frontend/runner/components/registration/registration_token_spec.js
index f53ae165344..6b9708cc525 100644
--- a/spec/frontend/runner/components/registration/registration_token_spec.js
+++ b/spec/frontend/runner/components/registration/registration_token_spec.js
@@ -1,7 +1,7 @@
import { nextTick } from 'vue';
import { GlToast } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { createLocalVue } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RegistrationToken from '~/runner/components/registration/registration_token.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
@@ -25,15 +25,13 @@ describe('RegistrationToken', () => {
const createComponent = ({ props = {}, withGlToast = true } = {}) => {
const localVue = withGlToast ? vueWithGlToast() : undefined;
- wrapper = extendedWrapper(
- shallowMount(RegistrationToken, {
- propsData: {
- value: mockToken,
- ...props,
- },
- localVue,
- }),
- );
+ wrapper = shallowMountExtended(RegistrationToken, {
+ propsData: {
+ value: mockToken,
+ ...props,
+ },
+ localVue,
+ });
showToast = wrapper.vm.$toast ? jest.spyOn(wrapper.vm.$toast, 'show') : null;
};
diff --git a/spec/frontend/runner/components/runner_assigned_item_spec.js b/spec/frontend/runner/components/runner_assigned_item_spec.js
new file mode 100644
index 00000000000..c6156c16d4a
--- /dev/null
+++ b/spec/frontend/runner/components/runner_assigned_item_spec.js
@@ -0,0 +1,53 @@
+import { GlAvatar } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
+
+const mockHref = '/group/project';
+const mockName = 'Project';
+const mockFullName = 'Group / Project';
+const mockAvatarUrl = '/avatar.png';
+
+describe('RunnerAssignedItem', () => {
+ let wrapper;
+
+ const findAvatar = () => wrapper.findByTestId('item-avatar');
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMountExtended(RunnerAssignedItem, {
+ propsData: {
+ href: mockHref,
+ name: mockName,
+ fullName: mockFullName,
+ avatarUrl: mockAvatarUrl,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Shows an avatar', () => {
+ const avatar = findAvatar();
+
+ expect(avatar.attributes('href')).toBe(mockHref);
+ expect(avatar.findComponent(GlAvatar).props()).toMatchObject({
+ alt: mockName,
+ entityName: mockName,
+ src: mockAvatarUrl,
+ shape: 'rect',
+ size: 48,
+ });
+ });
+
+ it('Shows an item link', () => {
+ const groupFullName = wrapper.findByText(mockFullName);
+
+ expect(groupFullName.attributes('href')).toBe(mockHref);
+ });
+});
diff --git a/spec/frontend/runner/components/runner_details_spec.js b/spec/frontend/runner/components/runner_details_spec.js
new file mode 100644
index 00000000000..6bf4a52a799
--- /dev/null
+++ b/spec/frontend/runner/components/runner_details_spec.js
@@ -0,0 +1,189 @@
+import { GlSprintf, GlIntersperse, GlTab } from '@gitlab/ui';
+import { createWrapper, ErrorWrapper } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { useFakeDate } from 'helpers/fake_date';
+import { ACCESS_LEVEL_REF_PROTECTED, ACCESS_LEVEL_NOT_PROTECTED } from '~/runner/constants';
+
+import RunnerDetails from '~/runner/components/runner_details.vue';
+import RunnerDetail from '~/runner/components/runner_detail.vue';
+import RunnerGroups from '~/runner/components/runner_groups.vue';
+import RunnersJobs from '~/runner/components/runner_jobs.vue';
+import RunnerTags from '~/runner/components/runner_tags.vue';
+import RunnerTag from '~/runner/components/runner_tag.vue';
+
+import { runnerData, runnerWithGroupData } from '../mock_data';
+
+const mockRunner = runnerData.data.runner;
+const mockGroupRunner = runnerWithGroupData.data.runner;
+
+describe('RunnerDetails', () => {
+ let wrapper;
+ const mockNow = '2021-01-15T12:00:00Z';
+ const mockOneHourAgo = '2021-01-15T11:00:00Z';
+
+ useFakeDate(mockNow);
+
+ /**
+ * Find the definition (<dd>) that corresponds to this term (<dt>)
+ * @param {string} dtLabel - Label for this value
+ * @returns Wrapper
+ */
+ const findDd = (dtLabel) => {
+ const dt = wrapper.findByText(dtLabel).element;
+ const dd = dt.nextElementSibling;
+ if (dt.tagName === 'DT' && dd.tagName === 'DD') {
+ return createWrapper(dd, {});
+ }
+ return ErrorWrapper(dtLabel);
+ };
+
+ const findDetailGroups = () => wrapper.findComponent(RunnerGroups);
+ const findRunnersJobs = () => wrapper.findComponent(RunnersJobs);
+ const findJobCountBadge = () => wrapper.findByTestId('job-count-badge');
+
+ const createComponent = ({ props = {}, mountFn = shallowMountExtended, stubs } = {}) => {
+ wrapper = mountFn(RunnerDetails, {
+ propsData: {
+ ...props,
+ },
+ stubs: {
+ RunnerDetail,
+ ...stubs,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('when no runner is present, no contents are shown', () => {
+ createComponent({
+ props: {
+ runner: null,
+ },
+ });
+
+ expect(wrapper.text()).toBe('');
+ });
+
+ describe('Details tab', () => {
+ describe.each`
+ field | runner | expectedValue
+ ${'Description'} | ${{ description: 'My runner' }} | ${'My runner'}
+ ${'Description'} | ${{ description: null }} | ${'None'}
+ ${'Last contact'} | ${{ contactedAt: mockOneHourAgo }} | ${'1 hour ago'}
+ ${'Last contact'} | ${{ contactedAt: null }} | ${'Never contacted'}
+ ${'Version'} | ${{ version: '12.3' }} | ${'12.3'}
+ ${'Version'} | ${{ version: null }} | ${'None'}
+ ${'IP Address'} | ${{ ipAddress: '127.0.0.1' }} | ${'127.0.0.1'}
+ ${'IP Address'} | ${{ ipAddress: null }} | ${'None'}
+ ${'Configuration'} | ${{ accessLevel: ACCESS_LEVEL_REF_PROTECTED, runUntagged: true }} | ${'Protected, Runs untagged jobs'}
+ ${'Configuration'} | ${{ accessLevel: ACCESS_LEVEL_REF_PROTECTED, runUntagged: false }} | ${'Protected'}
+ ${'Configuration'} | ${{ accessLevel: ACCESS_LEVEL_NOT_PROTECTED, runUntagged: true }} | ${'Runs untagged jobs'}
+ ${'Configuration'} | ${{ accessLevel: ACCESS_LEVEL_NOT_PROTECTED, runUntagged: false }} | ${'None'}
+ ${'Maximum job timeout'} | ${{ maximumTimeout: null }} | ${'None'}
+ ${'Maximum job timeout'} | ${{ maximumTimeout: 0 }} | ${'0 seconds'}
+ ${'Maximum job timeout'} | ${{ maximumTimeout: 59 }} | ${'59 seconds'}
+ ${'Maximum job timeout'} | ${{ maximumTimeout: 10 * 60 + 5 }} | ${'10 minutes 5 seconds'}
+ `('"$field" field', ({ field, runner, expectedValue }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: {
+ ...mockRunner,
+ ...runner,
+ },
+ },
+ stubs: {
+ GlIntersperse,
+ GlSprintf,
+ TimeAgo,
+ },
+ });
+ });
+
+ it(`displays expected value "${expectedValue}"`, () => {
+ expect(findDd(field).text()).toBe(expectedValue);
+ });
+ });
+
+ describe('"Tags" field', () => {
+ const stubs = { RunnerTags, RunnerTag };
+
+ it('displays expected value "tag-1 tag-2"', () => {
+ createComponent({
+ props: {
+ runner: { ...mockRunner, tagList: ['tag-1', 'tag-2'] },
+ },
+ stubs,
+ });
+
+ expect(findDd('Tags').text().replace(/\s+/g, ' ')).toBe('tag-1 tag-2');
+ });
+
+ it('displays "None" when runner has no tags', () => {
+ createComponent({
+ props: {
+ runner: { ...mockRunner, tagList: [] },
+ },
+ stubs,
+ });
+
+ expect(findDd('Tags').text().replace(/\s+/g, ' ')).toBe('None');
+ });
+ });
+
+ describe('Group runners', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: mockGroupRunner,
+ },
+ });
+ });
+
+ it('Shows a group runner details', () => {
+ expect(findDetailGroups().props('runner')).toEqual(mockGroupRunner);
+ });
+ });
+ });
+
+ describe('Jobs tab', () => {
+ const stubs = { GlTab };
+
+ it('without a runner, shows no jobs', () => {
+ createComponent({
+ props: { runner: null },
+ stubs,
+ });
+
+ expect(findJobCountBadge().exists()).toBe(false);
+ expect(findRunnersJobs().exists()).toBe(false);
+ });
+
+ it('without a job count, shows no jobs count', () => {
+ createComponent({
+ props: {
+ runner: { ...mockRunner, jobCount: undefined },
+ },
+ stubs,
+ });
+
+ expect(findJobCountBadge().exists()).toBe(false);
+ });
+
+ it('with a job count, shows jobs count', () => {
+ const runner = { ...mockRunner, jobCount: 3 };
+
+ createComponent({
+ props: { runner },
+ stubs,
+ });
+
+ expect(findJobCountBadge().text()).toBe('3');
+ expect(findRunnersJobs().props('runner')).toBe(runner);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_edit_button_spec.js b/spec/frontend/runner/components/runner_edit_button_spec.js
new file mode 100644
index 00000000000..428c1ef07e9
--- /dev/null
+++ b/spec/frontend/runner/components/runner_edit_button_spec.js
@@ -0,0 +1,41 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+describe('RunnerEditButton', () => {
+ let wrapper;
+
+ const getTooltipValue = () => getBinding(wrapper.element, 'gl-tooltip').value;
+
+ const createComponent = ({ attrs = {}, mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(RunnerEditButton, {
+ attrs,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays Edit text', () => {
+ expect(wrapper.attributes('aria-label')).toBe('Edit');
+ });
+
+ it('Displays Edit tooltip', () => {
+ expect(getTooltipValue()).toBe('Edit');
+ });
+
+ it('Renders a link and adds an href attribute', () => {
+ createComponent({ attrs: { href: '/edit' }, mountFn: mount });
+
+ expect(wrapper.element.tagName).toBe('A');
+ expect(wrapper.attributes('href')).toBe('/edit');
+ });
+});
diff --git a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
index 5ab0db019a3..fda96e5918e 100644
--- a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -1,6 +1,5 @@
import { GlFilteredSearch, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import { statusTokenConfig } from '~/runner/components/search_tokens/status_token_config';
import TagToken from '~/runner/components/search_tokens/tag_token.vue';
@@ -29,27 +28,25 @@ describe('RunnerList', () => {
};
const createComponent = ({ props = {}, options = {} } = {}) => {
- wrapper = extendedWrapper(
- shallowMount(RunnerFilteredSearchBar, {
- propsData: {
- namespace: 'runners',
- tokens: [],
- value: {
- runnerType: null,
- filters: [],
- sort: mockDefaultSort,
- },
- ...props,
+ wrapper = shallowMountExtended(RunnerFilteredSearchBar, {
+ propsData: {
+ namespace: 'runners',
+ tokens: [],
+ value: {
+ runnerType: null,
+ filters: [],
+ sort: mockDefaultSort,
},
- stubs: {
- FilteredSearch,
- GlFilteredSearch,
- GlDropdown,
- GlDropdownItem,
- },
- ...options,
- }),
- );
+ ...props,
+ },
+ stubs: {
+ FilteredSearch,
+ GlFilteredSearch,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ ...options,
+ });
};
beforeEach(() => {
diff --git a/spec/frontend/runner/components/runner_groups_spec.js b/spec/frontend/runner/components/runner_groups_spec.js
new file mode 100644
index 00000000000..b83733b9972
--- /dev/null
+++ b/spec/frontend/runner/components/runner_groups_spec.js
@@ -0,0 +1,67 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import RunnerGroups from '~/runner/components/runner_groups.vue';
+import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
+
+import { runnerData, runnerWithGroupData } from '../mock_data';
+
+const mockInstanceRunner = runnerData.data.runner;
+const mockGroupRunner = runnerWithGroupData.data.runner;
+const mockGroup = mockGroupRunner.groups.nodes[0];
+
+describe('RunnerGroups', () => {
+ let wrapper;
+
+ const findHeading = () => wrapper.find('h3');
+ const findRunnerAssignedItems = () => wrapper.findAllComponents(RunnerAssignedItem);
+
+ const createComponent = ({ runner = mockGroupRunner, mountFn = shallowMountExtended } = {}) => {
+ wrapper = mountFn(RunnerGroups, {
+ propsData: {
+ runner,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Shows a heading', () => {
+ createComponent();
+
+ expect(findHeading().text()).toBe('Assigned Group');
+ });
+
+ describe('When there is a group runner', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('Shows a project', () => {
+ createComponent();
+
+ const item = findRunnerAssignedItems().at(0);
+ const { webUrl, name, fullName, avatarUrl } = mockGroup;
+
+ expect(item.props()).toMatchObject({
+ href: webUrl,
+ name,
+ fullName,
+ avatarUrl,
+ });
+ });
+ });
+
+ describe('When there are no groups', () => {
+ beforeEach(() => {
+ createComponent({
+ runner: mockInstanceRunner,
+ });
+ });
+
+ it('Shows a "None" label', () => {
+ expect(wrapper.findByText('None').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_header_spec.js b/spec/frontend/runner/components/runner_header_spec.js
index 50699df3a44..8799c218b06 100644
--- a/spec/frontend/runner/components/runner_header_spec.js
+++ b/spec/frontend/runner/components/runner_header_spec.js
@@ -1,5 +1,5 @@
import { GlSprintf } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { GROUP_TYPE, STATUS_ONLINE } from '~/runner/constants';
import { TYPE_CI_RUNNER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
@@ -18,9 +18,10 @@ describe('RunnerHeader', () => {
const findRunnerTypeBadge = () => wrapper.findComponent(RunnerTypeBadge);
const findRunnerStatusBadge = () => wrapper.findComponent(RunnerStatusBadge);
+ const findRunnerLockedIcon = () => wrapper.findByTestId('lock-icon');
const findTimeAgo = () => wrapper.findComponent(TimeAgo);
- const createComponent = ({ runner = {}, mountFn = shallowMount } = {}) => {
+ const createComponent = ({ runner = {}, options = {}, mountFn = shallowMountExtended } = {}) => {
wrapper = mountFn(RunnerHeader, {
propsData: {
runner: {
@@ -32,6 +33,7 @@ describe('RunnerHeader', () => {
GlSprintf,
TimeAgo,
},
+ ...options,
});
};
@@ -41,24 +43,24 @@ describe('RunnerHeader', () => {
it('displays the runner status', () => {
createComponent({
- mountFn: mount,
+ mountFn: mountExtended,
runner: {
status: STATUS_ONLINE,
},
});
- expect(findRunnerStatusBadge().text()).toContain(`online`);
+ expect(findRunnerStatusBadge().text()).toContain('online');
});
it('displays the runner type', () => {
createComponent({
- mountFn: mount,
+ mountFn: mountExtended,
runner: {
runnerType: GROUP_TYPE,
},
});
- expect(findRunnerTypeBadge().text()).toContain(`group`);
+ expect(findRunnerTypeBadge().text()).toContain('group');
});
it('displays the runner id', () => {
@@ -68,7 +70,18 @@ describe('RunnerHeader', () => {
},
});
- expect(wrapper.text()).toContain(`Runner #99`);
+ expect(wrapper.text()).toContain('Runner #99');
+ });
+
+ it('displays the runner locked icon', () => {
+ createComponent({
+ runner: {
+ locked: true,
+ },
+ mountFn: mountExtended,
+ });
+
+ expect(findRunnerLockedIcon().exists()).toBe(true);
});
it('displays the runner creation time', () => {
@@ -78,7 +91,7 @@ describe('RunnerHeader', () => {
expect(findTimeAgo().props('time')).toBe(mockRunner.createdAt);
});
- it('does not display runner creation time if createdAt missing', () => {
+ it('does not display runner creation time if "createdAt" is missing', () => {
createComponent({
runner: {
id: convertToGraphQLId(TYPE_CI_RUNNER, 99),
@@ -86,8 +99,21 @@ describe('RunnerHeader', () => {
},
});
- expect(wrapper.text()).toContain(`Runner #99`);
+ expect(wrapper.text()).toContain('Runner #99');
expect(wrapper.text()).not.toMatch(/created .+/);
expect(findTimeAgo().exists()).toBe(false);
});
+
+ it('displays actions in a slot', () => {
+ createComponent({
+ options: {
+ slots: {
+ actions: '<div data-testid="actions-content">My Actions</div>',
+ },
+ mountFn: mountExtended,
+ },
+ });
+
+ expect(wrapper.findByTestId('actions-content').text()).toBe('My Actions');
+ });
});
diff --git a/spec/frontend/runner/components/runner_jobs_spec.js b/spec/frontend/runner/components/runner_jobs_spec.js
new file mode 100644
index 00000000000..97339056370
--- /dev/null
+++ b/spec/frontend/runner/components/runner_jobs_spec.js
@@ -0,0 +1,156 @@
+import { GlSkeletonLoading } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+import RunnerJobs from '~/runner/components/runner_jobs.vue';
+import RunnerJobsTable from '~/runner/components/runner_jobs_table.vue';
+import RunnerPagination from '~/runner/components/runner_pagination.vue';
+import { captureException } from '~/runner/sentry_utils';
+import { I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '~/runner/constants';
+
+import getRunnerJobsQuery from '~/runner/graphql/get_runner_jobs.query.graphql';
+
+import { runnerData, runnerJobsData } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+const mockRunner = runnerData.data.runner;
+const mockRunnerWithJobs = runnerJobsData.data.runner;
+const mockJobs = mockRunnerWithJobs.jobs.nodes;
+
+Vue.use(VueApollo);
+
+describe('RunnerJobs', () => {
+ let wrapper;
+ let mockRunnerJobsQuery;
+
+ const findGlSkeletonLoading = () => wrapper.findComponent(GlSkeletonLoading);
+ const findRunnerJobsTable = () => wrapper.findComponent(RunnerJobsTable);
+ const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
+
+ const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
+ wrapper = mountFn(RunnerJobs, {
+ apolloProvider: createMockApollo([[getRunnerJobsQuery, mockRunnerJobsQuery]]),
+ propsData: {
+ runner: mockRunner,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockRunnerJobsQuery = jest.fn();
+ });
+
+ afterEach(() => {
+ mockRunnerJobsQuery.mockReset();
+ wrapper.destroy();
+ });
+
+ it('Requests runner jobs', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(mockRunnerJobsQuery).toHaveBeenCalledTimes(1);
+ expect(mockRunnerJobsQuery).toHaveBeenCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_JOBS_PAGE_SIZE,
+ });
+ });
+
+ describe('When there are jobs assigned', () => {
+ beforeEach(async () => {
+ mockRunnerJobsQuery.mockResolvedValueOnce(runnerJobsData);
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows jobs', () => {
+ const jobs = findRunnerJobsTable().props('jobs');
+
+ expect(jobs).toHaveLength(mockJobs.length);
+ expect(jobs[0]).toMatchObject(mockJobs[0]);
+ });
+
+ describe('When "Next" page is clicked', () => {
+ beforeEach(async () => {
+ findRunnerPagination().vm.$emit('input', { page: 2, after: 'AFTER_CURSOR' });
+
+ await waitForPromises();
+ });
+
+ it('A new page is requested', () => {
+ expect(mockRunnerJobsQuery).toHaveBeenCalledTimes(2);
+ expect(mockRunnerJobsQuery).toHaveBeenLastCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_JOBS_PAGE_SIZE,
+ after: 'AFTER_CURSOR',
+ });
+ });
+ });
+ });
+
+ describe('When loading', () => {
+ it('shows loading indicator and no other content', () => {
+ createComponent();
+
+ expect(findGlSkeletonLoading().exists()).toBe(true);
+ expect(findRunnerJobsTable().exists()).toBe(false);
+ expect(findRunnerPagination().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('When there are no jobs', () => {
+ beforeEach(async () => {
+ mockRunnerJobsQuery.mockResolvedValueOnce({
+ data: {
+ runner: {
+ id: mockRunner.id,
+ projectCount: 0,
+ jobs: {
+ nodes: [],
+ pageInfo: {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ },
+ },
+ },
+ });
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows a "None" label', () => {
+ expect(wrapper.text()).toBe(I18N_NO_JOBS_FOUND);
+ });
+ });
+
+ describe('When an error occurs', () => {
+ beforeEach(async () => {
+ mockRunnerJobsQuery.mockRejectedValue(new Error('Error!'));
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('shows an error', () => {
+ expect(createAlert).toHaveBeenCalled();
+ });
+
+ it('reports an error', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ component: 'RunnerJobs',
+ error: expect.any(Error),
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_jobs_table_spec.js b/spec/frontend/runner/components/runner_jobs_table_spec.js
new file mode 100644
index 00000000000..5f4905ad2a8
--- /dev/null
+++ b/spec/frontend/runner/components/runner_jobs_table_spec.js
@@ -0,0 +1,119 @@
+import { GlTableLite } from '@gitlab/ui';
+import {
+ extendedWrapper,
+ shallowMountExtended,
+ mountExtended,
+} from 'helpers/vue_test_utils_helper';
+import { __, s__ } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import RunnerJobsTable from '~/runner/components/runner_jobs_table.vue';
+import { useFakeDate } from 'helpers/fake_date';
+import { runnerJobsData } from '../mock_data';
+
+const mockJobs = runnerJobsData.data.runner.jobs.nodes;
+
+describe('RunnerJobsTable', () => {
+ let wrapper;
+ const mockNow = '2021-01-15T12:00:00Z';
+ const mockOneHourAgo = '2021-01-15T11:00:00Z';
+
+ useFakeDate(mockNow);
+
+ const findTable = () => wrapper.findComponent(GlTableLite);
+ const findHeaders = () => wrapper.findAll('th');
+ const findRows = () => wrapper.findAll('[data-testid^="job-row-"]');
+ const findCell = ({ field }) =>
+ extendedWrapper(findRows().at(0).find(`[data-testid="td-${field}"]`));
+
+ const createComponent = ({ props = {} } = {}, mountFn = shallowMountExtended) => {
+ wrapper = mountFn(RunnerJobsTable, {
+ propsData: {
+ jobs: mockJobs,
+ ...props,
+ },
+ stubs: {
+ GlTableLite,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Sets job id as a row key', () => {
+ createComponent();
+
+ expect(findTable().attributes('primarykey')).toBe('id');
+ });
+
+ describe('Table data', () => {
+ beforeEach(() => {
+ createComponent({}, mountExtended);
+ });
+
+ it('Displays headers', () => {
+ const headerLabels = findHeaders().wrappers.map((w) => w.text());
+
+ expect(headerLabels).toEqual([
+ s__('Job|Status'),
+ __('Job'),
+ __('Project'),
+ __('Commit'),
+ s__('Job|Finished at'),
+ s__('Runners|Tags'),
+ ]);
+ });
+
+ it('Displays a list of jobs', () => {
+ expect(findRows()).toHaveLength(1);
+ });
+
+ it('Displays details of a job', () => {
+ const { id, detailedStatus, pipeline, shortSha, commitPath } = mockJobs[0];
+
+ expect(findCell({ field: 'status' }).text()).toMatchInterpolatedText(detailedStatus.text);
+
+ expect(findCell({ field: 'job' }).text()).toContain(`#${getIdFromGraphQLId(id)}`);
+ expect(findCell({ field: 'job' }).find('a').attributes('href')).toBe(
+ detailedStatus.detailsPath,
+ );
+
+ expect(findCell({ field: 'project' }).text()).toBe(pipeline.project.name);
+ expect(findCell({ field: 'project' }).find('a').attributes('href')).toBe(
+ pipeline.project.webUrl,
+ );
+
+ expect(findCell({ field: 'commit' }).text()).toBe(shortSha);
+ expect(findCell({ field: 'commit' }).find('a').attributes('href')).toBe(commitPath);
+ });
+ });
+
+ describe('Table data formatting', () => {
+ let mockJobsCopy;
+
+ beforeEach(() => {
+ mockJobsCopy = [
+ {
+ ...mockJobs[0],
+ },
+ ];
+ });
+
+ it('Formats finishedAt time', () => {
+ mockJobsCopy[0].finishedAt = mockOneHourAgo;
+
+ createComponent({ props: { jobs: mockJobsCopy } }, mountExtended);
+
+ expect(findCell({ field: 'finished_at' }).text()).toBe('1 hour ago');
+ });
+
+ it('Formats tags', () => {
+ mockJobsCopy[0].tags = ['tag-1', 'tag-2'];
+
+ createComponent({ props: { jobs: mockJobsCopy } }, mountExtended);
+
+ expect(findCell({ field: 'tags' }).text()).toMatchInterpolatedText('tag-1 tag-2');
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index 452430b7237..42d6ecca09e 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -1,8 +1,13 @@
import { GlTable, GlSkeletonLoader } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ extendedWrapper,
+ shallowMountExtended,
+ mountExtended,
+} from 'helpers/vue_test_utils_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerList from '~/runner/components/runner_list.vue';
+import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
+import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
import { runnersData } from '../mock_data';
const mockRunners = runnersData.data.runners.nodes;
@@ -18,20 +23,18 @@ describe('RunnerList', () => {
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,
- },
- }),
- );
+ const createComponent = ({ props = {} } = {}, mountFn = shallowMountExtended) => {
+ wrapper = mountFn(RunnerList, {
+ propsData: {
+ runners: mockRunners,
+ activeRunnersCount: mockActiveRunnersCount,
+ ...props,
+ },
+ });
};
beforeEach(() => {
- createComponent({}, mount);
+ createComponent({}, mountExtended);
});
afterEach(() => {
@@ -43,9 +46,9 @@ describe('RunnerList', () => {
expect(headerLabels).toEqual([
'Status',
- 'Runner ID',
+ 'Runner',
'Version',
- 'IP Address',
+ 'IP',
'Jobs',
'Tags',
'Last contact',
@@ -54,7 +57,7 @@ describe('RunnerList', () => {
});
it('Sets runner id as a row key', () => {
- createComponent({}, shallowMount);
+ createComponent({});
expect(findTable().attributes('primary-key')).toBe('id');
});
@@ -89,8 +92,9 @@ describe('RunnerList', () => {
// Actions
const actions = findCell({ fieldKey: 'actions' });
- expect(actions.findByTestId('edit-runner').exists()).toBe(true);
- expect(actions.findByTestId('toggle-active-runner').exists()).toBe(true);
+ expect(actions.findComponent(RunnerEditButton).exists()).toBe(true);
+ expect(actions.findComponent(RunnerPauseButton).exists()).toBe(true);
+ expect(actions.findByTestId('delete-runner').exists()).toBe(true);
});
describe('Table data formatting', () => {
@@ -107,7 +111,7 @@ describe('RunnerList', () => {
it('Formats job counts', () => {
mockRunnersCopy[0].jobCount = 1;
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
+ createComponent({ props: { runners: mockRunnersCopy } }, mountExtended);
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1');
});
@@ -115,7 +119,7 @@ describe('RunnerList', () => {
it('Formats large job counts', () => {
mockRunnersCopy[0].jobCount = 1000;
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
+ createComponent({ props: { runners: mockRunnersCopy } }, mountExtended);
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000');
});
@@ -123,7 +127,7 @@ describe('RunnerList', () => {
it('Formats large job counts with a plus symbol', () => {
mockRunnersCopy[0].jobCount = 1001;
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
+ createComponent({ props: { runners: mockRunnersCopy } }, mountExtended);
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000+');
});
@@ -143,13 +147,13 @@ describe('RunnerList', () => {
});
it('when there are no runners, shows an skeleton loader', () => {
- createComponent({ props: { runners: [], loading: true } }, mount);
+ createComponent({ props: { runners: [], loading: true } }, mountExtended);
expect(findSkeletonLoader().exists()).toBe(true);
});
it('when there are runners, shows a busy indicator skeleton loader', () => {
- createComponent({ props: { loading: true } }, mount);
+ createComponent({ props: { loading: true } }, mountExtended);
expect(findSkeletonLoader().exists()).toBe(false);
});
diff --git a/spec/frontend/runner/components/runner_pagination_spec.js b/spec/frontend/runner/components/runner_pagination_spec.js
index 59feb32dd2a..ecd6e6bd7f9 100644
--- a/spec/frontend/runner/components/runner_pagination_spec.js
+++ b/spec/frontend/runner/components/runner_pagination_spec.js
@@ -104,7 +104,6 @@ describe('RunnerPagination', () => {
expect(wrapper.emitted('input')[0]).toEqual([
{
- before: mockStartCursor,
page: 1,
},
]);
diff --git a/spec/frontend/runner/components/runner_pause_button_spec.js b/spec/frontend/runner/components/runner_pause_button_spec.js
new file mode 100644
index 00000000000..278f3dec2ee
--- /dev/null
+++ b/spec/frontend/runner/components/runner_pause_button_spec.js
@@ -0,0 +1,239 @@
+import Vue from 'vue';
+import { GlButton } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
+import runnerToggleActiveMutation from '~/runner/graphql/runner_toggle_active.mutation.graphql';
+import waitForPromises from 'helpers/wait_for_promises';
+import { captureException } from '~/runner/sentry_utils';
+import { createAlert } from '~/flash';
+
+import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
+import { runnersData } from '../mock_data';
+
+const mockRunner = runnersData.data.runners.nodes[0];
+
+Vue.use(VueApollo);
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+describe('RunnerPauseButton', () => {
+ let wrapper;
+ let runnerToggleActiveHandler;
+
+ const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip').value;
+ const findBtn = () => wrapper.findComponent(GlButton);
+
+ const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
+ const { runner, ...propsData } = props;
+
+ wrapper = mountFn(RunnerPauseButton, {
+ propsData: {
+ runner: {
+ id: mockRunner.id,
+ active: mockRunner.active,
+ ...runner,
+ },
+ ...propsData,
+ },
+ apolloProvider: createMockApollo([[runnerToggleActiveMutation, runnerToggleActiveHandler]]),
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ const clickAndWait = async () => {
+ findBtn().vm.$emit('click');
+ await waitForPromises();
+ };
+
+ beforeEach(() => {
+ runnerToggleActiveHandler = jest.fn().mockImplementation(({ input }) => {
+ return Promise.resolve({
+ data: {
+ runnerUpdate: {
+ runner: {
+ id: input.id,
+ active: input.active,
+ },
+ errors: [],
+ },
+ },
+ });
+ });
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Pause/Resume action', () => {
+ describe.each`
+ runnerState | icon | content | isActive | newActiveValue
+ ${'paused'} | ${'play'} | ${'Resume'} | ${false} | ${true}
+ ${'active'} | ${'pause'} | ${'Pause'} | ${true} | ${false}
+ `('When the runner is $runnerState', ({ icon, content, isActive, newActiveValue }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: {
+ active: isActive,
+ },
+ },
+ });
+ });
+
+ it(`Displays a ${icon} button`, () => {
+ expect(findBtn().props('loading')).toBe(false);
+ expect(findBtn().props('icon')).toBe(icon);
+ expect(findBtn().text()).toBe(content);
+ });
+
+ it('Does not display redundant text for screen readers', () => {
+ expect(findBtn().attributes('aria-label')).toBe(undefined);
+ });
+
+ describe(`Before the ${icon} button is clicked`, () => {
+ it('The mutation has not been called', () => {
+ expect(runnerToggleActiveHandler).toHaveBeenCalledTimes(0);
+ });
+ });
+
+ describe(`Immediately after the ${icon} button is clicked`, () => {
+ beforeEach(async () => {
+ findBtn().vm.$emit('click');
+ });
+
+ it('The button has a loading state', async () => {
+ expect(findBtn().props('loading')).toBe(true);
+ });
+
+ it('The stale tooltip is removed', async () => {
+ expect(getTooltip()).toBe('');
+ });
+ });
+
+ describe(`After clicking on the ${icon} button`, () => {
+ beforeEach(async () => {
+ await clickAndWait();
+ });
+
+ it(`The mutation to that sets active to ${newActiveValue} is called`, async () => {
+ expect(runnerToggleActiveHandler).toHaveBeenCalledTimes(1);
+ expect(runnerToggleActiveHandler).toHaveBeenCalledWith({
+ input: {
+ id: mockRunner.id,
+ active: newActiveValue,
+ },
+ });
+ });
+
+ it('The button does not have a loading state', () => {
+ expect(findBtn().props('loading')).toBe(false);
+ });
+ });
+
+ describe('When update fails', () => {
+ describe('On a network error', () => {
+ const mockErrorMsg = 'Update error!';
+
+ beforeEach(async () => {
+ runnerToggleActiveHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
+
+ await clickAndWait();
+ });
+
+ it('error is reported to sentry', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(mockErrorMsg),
+ component: 'RunnerPauseButton',
+ });
+ });
+
+ it('error is shown to the user', () => {
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('On a validation error', () => {
+ const mockErrorMsg = 'Runner not found!';
+ const mockErrorMsg2 = 'User not allowed!';
+
+ beforeEach(async () => {
+ runnerToggleActiveHandler.mockResolvedValueOnce({
+ data: {
+ runnerUpdate: {
+ runner: {
+ id: mockRunner.id,
+ active: isActive,
+ },
+ errors: [mockErrorMsg, mockErrorMsg2],
+ },
+ },
+ });
+
+ await clickAndWait();
+ });
+
+ it('error is reported to sentry', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
+ component: 'RunnerPauseButton',
+ });
+ });
+
+ it('error is shown to the user', () => {
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+ });
+ });
+
+ describe('When displaying a compact button for an active runner', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: {
+ active: true,
+ },
+ compact: true,
+ },
+ mountFn: mountExtended,
+ });
+ });
+
+ it('Displays no text', () => {
+ expect(findBtn().text()).toBe('');
+
+ // Note: Use <template v-if> to ensure rendering a
+ // text-less button. Ensure we don't send even empty an
+ // content slot to prevent a distorted/rectangular button.
+ expect(wrapper.find('.gl-button-text').exists()).toBe(false);
+ });
+
+ it('Display correctly for screen readers', () => {
+ expect(findBtn().attributes('aria-label')).toBe('Pause');
+ expect(getTooltip()).toBe('Pause');
+ });
+
+ describe('Immediately after the button is clicked', () => {
+ beforeEach(async () => {
+ findBtn().vm.$emit('click');
+ });
+
+ it('The button has a loading state', async () => {
+ expect(findBtn().props('loading')).toBe(true);
+ });
+
+ it('The stale tooltip is removed', async () => {
+ expect(getTooltip()).toBe('');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_projects_spec.js b/spec/frontend/runner/components/runner_projects_spec.js
new file mode 100644
index 00000000000..68a2130d6d9
--- /dev/null
+++ b/spec/frontend/runner/components/runner_projects_spec.js
@@ -0,0 +1,193 @@
+import { GlSkeletonLoading } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+import { sprintf } from '~/locale';
+import {
+ I18N_ASSIGNED_PROJECTS,
+ I18N_NONE,
+ RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+} from '~/runner/constants';
+import RunnerProjects from '~/runner/components/runner_projects.vue';
+import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
+import RunnerPagination from '~/runner/components/runner_pagination.vue';
+import { captureException } from '~/runner/sentry_utils';
+
+import getRunnerProjectsQuery from '~/runner/graphql/get_runner_projects.query.graphql';
+
+import { runnerData, runnerProjectsData } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+const mockRunner = runnerData.data.runner;
+const mockRunnerWithProjects = runnerProjectsData.data.runner;
+const mockProjects = mockRunnerWithProjects.projects.nodes;
+
+Vue.use(VueApollo);
+
+describe('RunnerProjects', () => {
+ let wrapper;
+ let mockRunnerProjectsQuery;
+
+ const findHeading = () => wrapper.find('h3');
+ const findGlSkeletonLoading = () => wrapper.findComponent(GlSkeletonLoading);
+ const findRunnerAssignedItems = () => wrapper.findAllComponents(RunnerAssignedItem);
+ const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
+
+ const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
+ wrapper = mountFn(RunnerProjects, {
+ apolloProvider: createMockApollo([[getRunnerProjectsQuery, mockRunnerProjectsQuery]]),
+ propsData: {
+ runner: mockRunner,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockRunnerProjectsQuery = jest.fn();
+ });
+
+ afterEach(() => {
+ mockRunnerProjectsQuery.mockReset();
+ wrapper.destroy();
+ });
+
+ it('Requests runner projects', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1);
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ });
+ });
+
+ describe('When there are projects assigned', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockResolvedValueOnce(runnerProjectsData);
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows a heading', async () => {
+ const expected = sprintf(I18N_ASSIGNED_PROJECTS, { projectCount: mockProjects.length });
+
+ expect(findHeading().text()).toBe(expected);
+ });
+
+ it('Shows projects', () => {
+ expect(findRunnerAssignedItems().length).toBe(mockProjects.length);
+ });
+
+ it('Shows a project', () => {
+ const item = findRunnerAssignedItems().at(0);
+ const { webUrl, name, nameWithNamespace, avatarUrl } = mockProjects[0];
+
+ expect(item.props()).toMatchObject({
+ href: webUrl,
+ name,
+ fullName: nameWithNamespace,
+ avatarUrl,
+ });
+ });
+
+ describe('When "Next" page is clicked', () => {
+ beforeEach(async () => {
+ findRunnerPagination().vm.$emit('input', { page: 3, after: 'AFTER_CURSOR' });
+
+ await waitForPromises();
+ });
+
+ it('A new page is requested', () => {
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(2);
+ expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ after: 'AFTER_CURSOR',
+ });
+ });
+
+ it('When "Prev" page is clicked, the previous page is requested', async () => {
+ findRunnerPagination().vm.$emit('input', { page: 2, before: 'BEFORE_CURSOR' });
+
+ await waitForPromises();
+
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(3);
+ expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({
+ id: mockRunner.id,
+ last: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ before: 'BEFORE_CURSOR',
+ });
+ });
+ });
+ });
+
+ describe('When loading', () => {
+ it('shows loading indicator and no other content', () => {
+ createComponent();
+
+ expect(findGlSkeletonLoading().exists()).toBe(true);
+
+ expect(wrapper.findByText(I18N_NONE).exists()).toBe(false);
+ expect(findRunnerAssignedItems().length).toBe(0);
+
+ expect(findRunnerPagination().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('When there are no projects', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockResolvedValueOnce({
+ data: {
+ runner: {
+ id: mockRunner.id,
+ projectCount: 0,
+ projects: {
+ nodes: [],
+ pageInfo: {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ },
+ },
+ },
+ });
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows a "None" label', () => {
+ expect(wrapper.findByText(I18N_NONE).exists()).toBe(true);
+ });
+ });
+
+ describe('When an error occurs', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockRejectedValue(new Error('Error!'));
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('shows an error', () => {
+ expect(createAlert).toHaveBeenCalled();
+ });
+
+ it('reports an error', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ component: 'RunnerProjects',
+ error: expect.any(Error),
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_type_tabs_spec.js b/spec/frontend/runner/components/runner_type_tabs_spec.js
index 4871d9c470a..9da5d842d8f 100644
--- a/spec/frontend/runner/components/runner_type_tabs_spec.js
+++ b/spec/frontend/runner/components/runner_type_tabs_spec.js
@@ -1,7 +1,7 @@
import { GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
-import { INSTANCE_TYPE, GROUP_TYPE } from '~/runner/constants';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
const mockSearch = { runnerType: null, filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' };
@@ -13,6 +13,7 @@ describe('RunnerTypeTabs', () => {
findTabs()
.filter((tab) => tab.attributes('active') === 'true')
.at(0);
+ const getTabsTitles = () => findTabs().wrappers.map((tab) => tab.text());
const createComponent = ({ props, ...options } = {}) => {
wrapper = shallowMount(RunnerTypeTabs, {
@@ -35,13 +36,18 @@ describe('RunnerTypeTabs', () => {
wrapper.destroy();
});
- it('Renders options to filter runners', () => {
- expect(findTabs().wrappers.map((tab) => tab.text())).toEqual([
- 'All',
- 'Instance',
- 'Group',
- 'Project',
- ]);
+ it('Renders all options to filter runners by default', () => {
+ expect(getTabsTitles()).toEqual(['All', 'Instance', 'Group', 'Project']);
+ });
+
+ it('Renders fewer options to filter runners', () => {
+ createComponent({
+ props: {
+ runnerTypes: [GROUP_TYPE, PROJECT_TYPE],
+ },
+ });
+
+ expect(getTabsTitles()).toEqual(['All', 'Group', 'Project']);
});
it('"All" is selected by default', () => {
diff --git a/spec/frontend/runner/components/runner_update_form_spec.js b/spec/frontend/runner/components/runner_update_form_spec.js
index ebb2e67d1e2..8b76be396ef 100644
--- a/spec/frontend/runner/components/runner_update_form_spec.js
+++ b/spec/frontend/runner/components/runner_update_form_spec.js
@@ -1,9 +1,8 @@
+import Vue, { nextTick } from 'vue';
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 { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert, VARIANT_SUCCESS } from '~/flash';
import RunnerUpdateForm from '~/runner/components/runner_update_form.vue';
@@ -23,8 +22,7 @@ jest.mock('~/runner/sentry_utils');
const mockRunner = runnerData.data.runner;
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('RunnerUpdateForm', () => {
let wrapper;
@@ -61,16 +59,13 @@ describe('RunnerUpdateForm', () => {
});
const createComponent = ({ props } = {}) => {
- wrapper = extendedWrapper(
- mount(RunnerUpdateForm, {
- localVue,
- propsData: {
- runner: mockRunner,
- ...props,
- },
- apolloProvider: createMockApollo([[runnerUpdateMutation, runnerUpdateHandler]]),
- }),
- );
+ wrapper = mountExtended(RunnerUpdateForm, {
+ propsData: {
+ runner: mockRunner,
+ ...props,
+ },
+ apolloProvider: createMockApollo([[runnerUpdateMutation, runnerUpdateHandler]]),
+ });
};
const expectToHaveSubmittedRunnerContaining = (submittedRunner) => {
@@ -126,8 +121,21 @@ describe('RunnerUpdateForm', () => {
it('Updates runner with no changes', async () => {
await submitFormAndWait();
- // Some fields are not submitted
- const { ipAddress, runnerType, createdAt, status, ...submitted } = mockRunner;
+ // Some read-only fields are not submitted
+ const {
+ __typename,
+ ipAddress,
+ runnerType,
+ createdAt,
+ status,
+ editAdminUrl,
+ contactedAt,
+ userPermissions,
+ version,
+ groups,
+ jobCount,
+ ...submitted
+ } = mockRunner;
expectToHaveSubmittedRunnerContaining(submitted);
});
@@ -239,11 +247,11 @@ describe('RunnerUpdateForm', () => {
await submitFormAndWait();
expect(createAlert).toHaveBeenLastCalledWith({
- message: `Network error: ${mockErrorMsg}`,
+ message: mockErrorMsg,
});
expect(captureException).toHaveBeenCalledWith({
component: 'RunnerUpdateForm',
- error: new Error(`Network error: ${mockErrorMsg}`),
+ error: new Error(mockErrorMsg),
});
expect(findSubmitDisabledAttr()).toBeUndefined();
});
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index 034b7848f35..7cb1f49d4f7 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -1,15 +1,19 @@
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
import { GlLink } from '@gitlab/ui';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ extendedWrapper,
+ shallowMountExtended,
+ mountExtended,
+} from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory } from '~/lib/utils/url_utility';
+import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerList from '~/runner/components/runner_list.vue';
import RunnerStats from '~/runner/components/stat/runner_stats.vue';
@@ -22,6 +26,7 @@ import {
DEFAULT_SORT,
INSTANCE_TYPE,
GROUP_TYPE,
+ PROJECT_TYPE,
PARAM_KEY_STATUS,
STATUS_ACTIVE,
RUNNER_PAGE_SIZE,
@@ -33,8 +38,7 @@ import { captureException } from '~/runner/sentry_utils';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import { groupRunnersData, groupRunnersDataPaginated, groupRunnersCountData } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const mockGroupFullPath = 'group1';
const mockRegistrationToken = 'AABBCC';
@@ -54,6 +58,7 @@ describe('GroupRunnersApp', () => {
const findRunnerStats = () => wrapper.findComponent(RunnerStats);
const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
+ const findRunnerTypeTabs = () => wrapper.findComponent(RunnerTypeTabs);
const findRunnerList = () => wrapper.findComponent(RunnerList);
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
const findRunnerPaginationPrev = () =>
@@ -62,14 +67,18 @@ describe('GroupRunnersApp', () => {
const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
const findFilteredSearch = () => wrapper.findComponent(FilteredSearch);
- const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ const mockCountQueryResult = (count) =>
+ Promise.resolve({
+ data: { group: { id: groupRunnersCountData.data.group.id, runners: { count } } },
+ });
+
+ const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
const handlers = [
[getGroupRunnersQuery, mockGroupRunnersQuery],
[getGroupRunnersCountQuery, mockGroupRunnersCountQuery],
];
wrapper = mountFn(GroupRunnersApp, {
- localVue,
apolloProvider: createMockApollo(handlers),
propsData: {
registrationToken: mockRegistrationToken,
@@ -91,7 +100,7 @@ describe('GroupRunnersApp', () => {
});
it('shows total runner counts', async () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
@@ -102,6 +111,44 @@ describe('GroupRunnersApp', () => {
expect(stats).toMatch('Stale runners 2');
});
+ it('shows the runner tabs with a runner count for each type', async () => {
+ mockGroupRunnersCountQuery.mockImplementation(({ type }) => {
+ switch (type) {
+ case GROUP_TYPE:
+ return mockCountQueryResult(2);
+ case PROJECT_TYPE:
+ return mockCountQueryResult(1);
+ default:
+ return mockCountQueryResult(4);
+ }
+ });
+
+ createComponent({ mountFn: mountExtended });
+ await waitForPromises();
+
+ expect(findRunnerTypeTabs().text()).toMatchInterpolatedText('All 4 Group 2 Project 1');
+ });
+
+ it('shows the runner tabs with a formatted runner count', async () => {
+ mockGroupRunnersCountQuery.mockImplementation(({ type }) => {
+ switch (type) {
+ case GROUP_TYPE:
+ return mockCountQueryResult(2000);
+ case PROJECT_TYPE:
+ return mockCountQueryResult(1000);
+ default:
+ return mockCountQueryResult(3000);
+ }
+ });
+
+ createComponent({ mountFn: mountExtended });
+ await waitForPromises();
+
+ expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
+ 'All 3,000 Group 2,000 Project 1,000',
+ );
+ });
+
it('shows the runner setup instructions', () => {
expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
expect(findRegistrationDropdown().props('type')).toBe(GROUP_TYPE);
@@ -116,7 +163,7 @@ describe('GroupRunnersApp', () => {
const { webUrl, node } = groupRunnersData.data.group.runners.edges[0];
const { id, shortSha } = node;
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
await waitForPromises();
@@ -136,7 +183,7 @@ describe('GroupRunnersApp', () => {
});
it('sets tokens in the filtered search', () => {
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
const tokens = findFilteredSearch().props('tokens');
@@ -215,11 +262,13 @@ describe('GroupRunnersApp', () => {
mockGroupRunnersQuery = jest.fn().mockResolvedValue({
data: {
group: {
+ id: '1',
runners: { nodes: [] },
},
},
});
createComponent();
+ await waitForPromises();
});
it('shows a message for no results', async () => {
@@ -228,9 +277,10 @@ describe('GroupRunnersApp', () => {
});
describe('when runners query fails', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockGroupRunnersQuery = jest.fn().mockRejectedValue(new Error('Error!'));
createComponent();
+ await waitForPromises();
});
it('error is shown to the user', async () => {
@@ -239,17 +289,18 @@ describe('GroupRunnersApp', () => {
it('error is reported to sentry', async () => {
expect(captureException).toHaveBeenCalledWith({
- error: new Error('Network error: Error!'),
+ error: new Error('Error!'),
component: 'GroupRunnersApp',
});
});
});
describe('Pagination', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockGroupRunnersQuery = jest.fn().mockResolvedValue(groupRunnersDataPaginated);
- createComponent({ mountFn: mount });
+ createComponent({ mountFn: mountExtended });
+ await waitForPromises();
});
it('more pages can be selected', () => {
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
index 9c430e205ea..d80caa47752 100644
--- a/spec/frontend/runner/mock_data.js
+++ b/spec/frontend/runner/mock_data.js
@@ -5,6 +5,9 @@ import runnersData from 'test_fixtures/graphql/runner/get_runners.query.graphql.
import runnersCountData from 'test_fixtures/graphql/runner/get_runners_count.query.graphql.json';
import runnersDataPaginated from 'test_fixtures/graphql/runner/get_runners.query.graphql.paginated.json';
import runnerData from 'test_fixtures/graphql/runner/get_runner.query.graphql.json';
+import runnerWithGroupData from 'test_fixtures/graphql/runner/get_runner.query.graphql.with_group.json';
+import runnerProjectsData from 'test_fixtures/graphql/runner/get_runner_projects.query.graphql.json';
+import runnerJobsData from 'test_fixtures/graphql/runner/get_runner_jobs.query.graphql.json';
// Group queries
import groupRunnersData from 'test_fixtures/graphql/runner/get_group_runners.query.graphql.json';
@@ -12,10 +15,13 @@ import groupRunnersCountData from 'test_fixtures/graphql/runner/get_group_runner
import groupRunnersDataPaginated from 'test_fixtures/graphql/runner/get_group_runners.query.graphql.paginated.json';
export {
- runnerData,
+ runnersData,
runnersCountData,
runnersDataPaginated,
- runnersData,
+ runnerData,
+ runnerWithGroupData,
+ runnerProjectsData,
+ runnerJobsData,
groupRunnersData,
groupRunnersCountData,
groupRunnersDataPaginated,
diff --git a/spec/frontend/runner/utils_spec.js b/spec/frontend/runner/utils_spec.js
new file mode 100644
index 00000000000..3fa9784ecdf
--- /dev/null
+++ b/spec/frontend/runner/utils_spec.js
@@ -0,0 +1,65 @@
+import { formatJobCount, tableField, getPaginationVariables } from '~/runner/utils';
+
+describe('~/runner/utils', () => {
+ describe('formatJobCount', () => {
+ it('formats a number', () => {
+ expect(formatJobCount(1)).toBe('1');
+ expect(formatJobCount(99)).toBe('99');
+ });
+
+ it('formats a large count', () => {
+ expect(formatJobCount(1000)).toBe('1,000');
+ expect(formatJobCount(1001)).toBe('1,000+');
+ });
+
+ it('returns an empty string for non-numeric values', () => {
+ expect(formatJobCount(undefined)).toBe('');
+ expect(formatJobCount(null)).toBe('');
+ expect(formatJobCount('number')).toBe('');
+ });
+ });
+
+ describe('tableField', () => {
+ it('a field with options', () => {
+ expect(tableField({ key: 'name' })).toEqual({
+ key: 'name',
+ label: '',
+ tdAttr: { 'data-testid': 'td-name' },
+ thClass: expect.any(Array),
+ });
+ });
+
+ it('a field with a label', () => {
+ const label = 'A field name';
+
+ expect(tableField({ key: 'name', label })).toMatchObject({
+ label,
+ });
+ });
+
+ it('a field with custom classes', () => {
+ const mockClasses = ['foo', 'bar'];
+
+ expect(tableField({ thClasses: mockClasses })).toMatchObject({
+ thClass: expect.arrayContaining(mockClasses),
+ });
+ });
+ });
+
+ describe('getPaginationVariables', () => {
+ const after = 'AFTER_CURSOR';
+ const before = 'BEFORE_CURSOR';
+
+ it.each`
+ case | pagination | pageSize | variables
+ ${'next page'} | ${{ after }} | ${undefined} | ${{ after, first: 10 }}
+ ${'prev page'} | ${{ before }} | ${undefined} | ${{ before, last: 10 }}
+ ${'first page'} | ${{}} | ${undefined} | ${{ first: 10 }}
+ ${'next page with N items'} | ${{ after }} | ${20} | ${{ after, first: 20 }}
+ ${'prev page with N items'} | ${{ before }} | ${20} | ${{ before, last: 20 }}
+ ${'first page with N items'} | ${{}} | ${20} | ${{ first: 20 }}
+ `('navigates to $case', ({ pagination, pageSize, variables }) => {
+ expect(getPaginationVariables(pagination, pageSize)).toEqual(variables);
+ });
+ });
+});
diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
index 3713e1d414f..a377ddae0eb 100644
--- a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
@@ -1,11 +1,11 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue';
import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('ConfidentialityFilter', () => {
let wrapper;
@@ -25,7 +25,6 @@ describe('ConfidentialityFilter', () => {
});
wrapper = shallowMount(ConfidentialityFilter, {
- localVue,
store,
});
};
diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js
index 4c81312e479..39d5ee581ec 100644
--- a/spec/frontend/search/sidebar/components/radio_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js
@@ -1,13 +1,13 @@
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
import { confidentialFilterData } from '~/search/sidebar/constants/confidential_filter_data';
import { stateFilterData } from '~/search/sidebar/constants/state_filter_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('RadioFilter', () => {
let wrapper;
@@ -30,7 +30,6 @@ describe('RadioFilter', () => {
});
wrapper = shallowMount(RadioFilter, {
- localVue,
store,
propsData: {
...defaultProps,
diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js
index 08ce57b206b..5d8ecd8733a 100644
--- a/spec/frontend/search/sidebar/components/status_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/status_filter_spec.js
@@ -1,11 +1,11 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
import StatusFilter from '~/search/sidebar/components/status_filter.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('StatusFilter', () => {
let wrapper;
@@ -25,7 +25,6 @@ describe('StatusFilter', () => {
});
wrapper = shallowMount(StatusFilter, {
- localVue,
store,
});
};
diff --git a/spec/frontend/search/sort/components/app_spec.js b/spec/frontend/search/sort/components/app_spec.js
index 5806d6b51d2..04520a3e704 100644
--- a/spec/frontend/search/sort/components/app_spec.js
+++ b/spec/frontend/search/sort/components/app_spec.js
@@ -1,12 +1,12 @@
import { GlButtonGroup, GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY, MOCK_SORT_OPTIONS } from 'jest/search/mock_data';
import GlobalSearchSort from '~/search/sort/components/app.vue';
import { SORT_DIRECTION_UI } from '~/search/sort/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GlobalSearchSort', () => {
let wrapper;
@@ -30,7 +30,6 @@ describe('GlobalSearchSort', () => {
});
wrapper = shallowMount(GlobalSearchSort, {
- localVue,
store,
propsData: {
...defaultProps,
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index cbdf7f53913..963577fa763 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -32,7 +32,7 @@ const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
const autoDevopsPath = '/autoDevopsPath';
const gitlabCiHistoryPath = 'test/historyPath';
-const projectPath = 'namespace/project';
+const projectFullPath = 'namespace/project';
useLocalStorageSpy();
@@ -54,7 +54,7 @@ describe('App component', () => {
upgradePath,
autoDevopsHelpPagePath,
autoDevopsPath,
- projectPath,
+ projectFullPath,
glFeatures: {
secureVulnerabilityTraining,
},
@@ -274,11 +274,11 @@ describe('App component', () => {
describe('Auto DevOps enabled alert', () => {
describe.each`
- context | autoDevopsEnabled | localStorageValue | shouldRender
- ${'enabled'} | ${true} | ${null} | ${true}
- ${'enabled, alert dismissed on other project'} | ${true} | ${['foo/bar']} | ${true}
- ${'enabled, alert dismissed on this project'} | ${true} | ${[projectPath]} | ${false}
- ${'not enabled'} | ${false} | ${null} | ${false}
+ context | autoDevopsEnabled | localStorageValue | shouldRender
+ ${'enabled'} | ${true} | ${null} | ${true}
+ ${'enabled, alert dismissed on other project'} | ${true} | ${['foo/bar']} | ${true}
+ ${'enabled, alert dismissed on this project'} | ${true} | ${[projectFullPath]} | ${false}
+ ${'not enabled'} | ${false} | ${null} | ${false}
`('given Auto DevOps is $context', ({ autoDevopsEnabled, localStorageValue, shouldRender }) => {
beforeEach(() => {
if (localStorageValue !== null) {
@@ -302,11 +302,11 @@ describe('App component', () => {
describe('dismissing', () => {
describe.each`
- dismissedProjects | expectedWrittenValue
- ${null} | ${[projectPath]}
- ${[]} | ${[projectPath]}
- ${['foo/bar']} | ${['foo/bar', projectPath]}
- ${[projectPath]} | ${[projectPath]}
+ dismissedProjects | expectedWrittenValue
+ ${null} | ${[projectFullPath]}
+ ${[]} | ${[projectFullPath]}
+ ${['foo/bar']} | ${['foo/bar', projectFullPath]}
+ ${[projectFullPath]} | ${[projectFullPath]}
`(
'given dismissed projects $dismissedProjects',
({ dismissedProjects, expectedWrittenValue }) => {
diff --git a/spec/frontend/security_configuration/components/feature_card_spec.js b/spec/frontend/security_configuration/components/feature_card_spec.js
index 0eca2c27075..2b74be19480 100644
--- a/spec/frontend/security_configuration/components/feature_card_spec.js
+++ b/spec/frontend/security_configuration/components/feature_card_spec.js
@@ -113,7 +113,6 @@ describe('FeatureCard component', () => {
context | available | configured | expectedStatus
${'a configured feature'} | ${true} | ${true} | ${'Enabled'}
${'an unconfigured feature'} | ${true} | ${false} | ${'Not enabled'}
- ${'an available feature with unknown status'} | ${true} | ${undefined} | ${''}
${'an unavailable feature'} | ${false} | ${false} | ${'Available with Ultimate'}
${'an unavailable feature with unknown status'} | ${false} | ${undefined} | ${'Available with Ultimate'}
`('given $context', ({ available, configured, expectedStatus }) => {
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index 578248e696f..18c9ada6bde 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -1,14 +1,26 @@
+import * as Sentry from '@sentry/browser';
import { GlAlert, GlLink, GlToggle, GlCard, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import {
+ TRACK_TOGGLE_TRAINING_PROVIDER_ACTION,
+ TRACK_TOGGLE_TRAINING_PROVIDER_LABEL,
+} from '~/security_configuration/constants';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
+import securityTrainingProvidersQuery from '~/security_configuration/graphql/security_training_providers.query.graphql';
import configureSecurityTrainingProvidersMutation from '~/security_configuration/graphql/configure_security_training_providers.mutation.graphql';
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import waitForPromises from 'helpers/wait_for_promises';
import {
+ dismissUserCalloutResponse,
+ dismissUserCalloutErrorResponse,
securityTrainingProviders,
- createMockResolvers,
+ securityTrainingProvidersResponse,
+ updateSecurityTrainingProvidersResponse,
+ updateSecurityTrainingProvidersErrorResponse,
testProjectPath,
textProviderIds,
} from '../mock_data';
@@ -19,14 +31,28 @@ describe('TrainingProviderList component', () => {
let wrapper;
let apolloProvider;
- const createApolloProvider = ({ resolvers } = {}) => {
- apolloProvider = createMockApollo([], createMockResolvers({ resolvers }));
+ const createApolloProvider = ({ handlers = [] } = {}) => {
+ const defaultHandlers = [
+ [
+ securityTrainingProvidersQuery,
+ jest.fn().mockResolvedValue(securityTrainingProvidersResponse),
+ ],
+ [
+ configureSecurityTrainingProvidersMutation,
+ jest.fn().mockResolvedValue(updateSecurityTrainingProvidersResponse),
+ ],
+ ];
+
+ // make sure we don't have any duplicate handlers to avoid 'Request handler already defined for query` errors
+ const mergedHandlers = [...new Map([...defaultHandlers, ...handlers])];
+
+ apolloProvider = createMockApollo(mergedHandlers);
};
const createComponent = () => {
wrapper = shallowMount(TrainingProviderList, {
provide: {
- projectPath: testProjectPath,
+ projectFullPath: testProjectPath,
},
apolloProvider,
});
@@ -42,27 +68,49 @@ describe('TrainingProviderList component', () => {
const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findErrorAlert = () => wrapper.findComponent(GlAlert);
- const toggleFirstProvider = () => findFirstToggle().vm.$emit('change');
+ const toggleFirstProvider = () => findFirstToggle().vm.$emit('change', textProviderIds[0]);
afterEach(() => {
wrapper.destroy();
apolloProvider = null;
});
- describe('with a successful response', () => {
+ describe('when loading', () => {
beforeEach(() => {
- createApolloProvider();
+ const pendingHandler = () => new Promise(() => {});
+
+ createApolloProvider({
+ handlers: [[securityTrainingProvidersQuery, pendingHandler]],
+ });
createComponent();
});
- describe('when loading', () => {
- it('shows the loader', () => {
- expect(findLoader().exists()).toBe(true);
- });
+ it('shows the loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
- it('does not show the cards', () => {
- expect(findCards().exists()).toBe(false);
+ it('does not show the cards', () => {
+ expect(findCards().exists()).toBe(false);
+ });
+ });
+
+ describe('with a successful response', () => {
+ beforeEach(() => {
+ createApolloProvider({
+ handlers: [
+ [dismissUserCalloutMutation, jest.fn().mockResolvedValue(dismissUserCalloutResponse)],
+ ],
+ resolvers: {
+ Mutation: {
+ configureSecurityTrainingProviders: () => ({
+ errors: [],
+ securityTrainingProviders: [],
+ }),
+ },
+ },
});
+
+ createComponent();
});
describe('basic structure', () => {
@@ -104,9 +152,9 @@ describe('TrainingProviderList component', () => {
beforeEach(async () => {
jest.spyOn(apolloProvider.defaultClient, 'mutate');
- await waitForMutationToBeLoaded();
+ await waitForQueryToBeLoaded();
- toggleFirstProvider();
+ await toggleFirstProvider();
});
it.each`
@@ -124,10 +172,78 @@ describe('TrainingProviderList component', () => {
expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith(
expect.objectContaining({
mutation: configureSecurityTrainingProvidersMutation,
- variables: { input: { enabledProviders: textProviderIds, fullPath: testProjectPath } },
+ variables: {
+ input: {
+ providerId: textProviderIds[0],
+ isEnabled: true,
+ isPrimary: false,
+ projectPath: testProjectPath,
+ },
+ },
}),
);
});
+
+ it('dismisses the callout when the feature gets first enabled', async () => {
+ // wait for configuration update mutation to complete
+ await waitForMutationToBeLoaded();
+
+ // both the config and dismiss mutations have been called
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledTimes(2);
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenNthCalledWith(
+ 2,
+ expect.objectContaining({
+ mutation: dismissUserCalloutMutation,
+ variables: {
+ input: {
+ featureName: 'security_training_feature_promotion',
+ },
+ },
+ }),
+ );
+
+ toggleFirstProvider();
+ await waitForMutationToBeLoaded();
+
+ // the config mutation has been called again but not the dismiss mutation
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledTimes(3);
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenNthCalledWith(
+ 3,
+ expect.objectContaining({
+ mutation: configureSecurityTrainingProvidersMutation,
+ }),
+ );
+ });
+ });
+
+ describe('metrics', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('tracks when a provider gets toggled', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ toggleFirstProvider();
+
+ // Note: Ideally we also want to test that the tracking event is called correctly when a
+ // provider gets disabled, but that's a bit tricky to do with the current implementation
+ // Once https://gitlab.com/gitlab-org/gitlab/-/issues/348985 and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79492
+ // are merged this will be much easer to do and should be tackled then.
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, {
+ property: securityTrainingProviders[0].id,
+ label: TRACK_TOGGLE_TRAINING_PROVIDER_LABEL,
+ extra: {
+ providerIsEnabled: true,
+ },
+ });
+ });
});
});
@@ -142,11 +258,7 @@ describe('TrainingProviderList component', () => {
describe('when fetching training providers', () => {
beforeEach(async () => {
createApolloProvider({
- resolvers: {
- Query: {
- securityTrainingProviders: jest.fn().mockReturnValue(new Error()),
- },
- },
+ handlers: [[securityTrainingProvidersQuery, jest.fn().mockRejectedValue()]],
});
createComponent();
@@ -165,10 +277,43 @@ describe('TrainingProviderList component', () => {
describe('when storing training provider configurations', () => {
beforeEach(async () => {
createApolloProvider({
+ handlers: [
+ [
+ configureSecurityTrainingProvidersMutation,
+ jest.fn().mockReturnValue(updateSecurityTrainingProvidersErrorResponse),
+ ],
+ ],
+ });
+ createComponent();
+
+ await waitForQueryToBeLoaded();
+ toggleFirstProvider();
+ await waitForMutationToBeLoaded();
+ });
+
+ it('shows an non-dismissible error alert', () => {
+ expectErrorAlertToExist();
+ });
+
+ it('shows an error description', () => {
+ expect(findErrorAlert().text()).toBe(TrainingProviderList.i18n.configMutationErrorMessage);
+ });
+ });
+
+ describe.each`
+ errorType | mutationHandler
+ ${'backend error'} | ${jest.fn().mockReturnValue(dismissUserCalloutErrorResponse)}
+ ${'network error'} | ${jest.fn().mockRejectedValue()}
+ `('when dismissing the callout and a "$errorType" happens', ({ mutationHandler }) => {
+ beforeEach(async () => {
+ jest.spyOn(Sentry, 'captureException').mockImplementation();
+
+ createApolloProvider({
+ handlers: [[dismissUserCalloutMutation, mutationHandler]],
resolvers: {
Mutation: {
configureSecurityTrainingProviders: () => ({
- errors: ['something went wrong!'],
+ errors: [],
securityTrainingProviders: [],
}),
},
@@ -178,15 +323,14 @@ describe('TrainingProviderList component', () => {
await waitForQueryToBeLoaded();
toggleFirstProvider();
- await waitForMutationToBeLoaded();
});
- it('shows an non-dismissible error alert', () => {
- expectErrorAlertToExist();
- });
+ it('logs the error to sentry', async () => {
+ expect(Sentry.captureException).not.toHaveBeenCalled();
- it('shows an error description', () => {
- expect(findErrorAlert().text()).toBe(TrainingProviderList.i18n.configMutationErrorMessage);
+ await waitForMutationToBeLoaded();
+
+ expect(Sentry.captureException).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
index a35fded72fb..ff44acfc4f9 100644
--- a/spec/frontend/security_configuration/components/upgrade_banner_spec.js
+++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
@@ -1,15 +1,22 @@
import { GlBanner } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import UpgradeBanner, {
+ SECURITY_UPGRADE_BANNER,
+ UPGRADE_OR_FREE_TRIAL,
+} from '~/security_configuration/components/upgrade_banner.vue';
const upgradePath = '/upgrade';
describe('UpgradeBanner component', () => {
let wrapper;
let closeSpy;
+ let primarySpy;
+ let trackingSpy;
const createComponent = (propsData) => {
closeSpy = jest.fn();
+ primarySpy = jest.fn();
wrapper = shallowMountExtended(UpgradeBanner, {
provide: {
@@ -18,43 +25,83 @@ describe('UpgradeBanner component', () => {
propsData,
listeners: {
close: closeSpy,
+ primary: primarySpy,
},
});
};
const findGlBanner = () => wrapper.findComponent(GlBanner);
+ const expectTracking = (action, label) => {
+ return expect(trackingSpy).toHaveBeenCalledWith(undefined, action, {
+ label,
+ property: SECURITY_UPGRADE_BANNER,
+ });
+ };
+
beforeEach(() => {
- createComponent();
+ trackingSpy = mockTracking(undefined, undefined, jest.spyOn);
});
afterEach(() => {
wrapper.destroy();
+ unmockTracking();
});
- it('passes the expected props to GlBanner', () => {
- expect(findGlBanner().props()).toMatchObject({
- title: UpgradeBanner.i18n.title,
- buttonText: UpgradeBanner.i18n.buttonText,
- buttonLink: upgradePath,
+ describe('when the component renders', () => {
+ it('tracks an event', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ createComponent();
+
+ expectTracking('render', SECURITY_UPGRADE_BANNER);
});
});
- it('renders the list of benefits', () => {
- const wrapperText = wrapper.text();
+ describe('when ready', () => {
+ beforeEach(() => {
+ createComponent();
+ trackingSpy.mockClear();
+ });
- expect(wrapperText).toContain('Immediately begin risk analysis and remediation');
- expect(wrapperText).toContain('statistics in the merge request');
- expect(wrapperText).toContain('statistics across projects');
- expect(wrapperText).toContain('Runtime security metrics');
- expect(wrapperText).toContain('More scan types, including Container Scanning,');
- });
+ it('passes the expected props to GlBanner', () => {
+ expect(findGlBanner().props()).toMatchObject({
+ title: UpgradeBanner.i18n.title,
+ buttonText: UpgradeBanner.i18n.buttonText,
+ buttonLink: upgradePath,
+ });
+ });
- it(`re-emits GlBanner's close event`, () => {
- expect(closeSpy).not.toHaveBeenCalled();
+ it('renders the list of benefits', () => {
+ const wrapperText = wrapper.text();
- wrapper.findComponent(GlBanner).vm.$emit('close');
+ expect(wrapperText).toContain('Immediately begin risk analysis and remediation');
+ expect(wrapperText).toContain('statistics in the merge request');
+ expect(wrapperText).toContain('statistics across projects');
+ expect(wrapperText).toContain('Runtime security metrics');
+ expect(wrapperText).toContain('More scan types, including Container Scanning,');
+ });
+
+ describe('when user interacts', () => {
+ it(`re-emits GlBanner's close event & tracks an event`, () => {
+ expect(closeSpy).not.toHaveBeenCalled();
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ wrapper.findComponent(GlBanner).vm.$emit('close');
+
+ expect(closeSpy).toHaveBeenCalledTimes(1);
+ expectTracking('dismiss_banner', SECURITY_UPGRADE_BANNER);
+ });
- expect(closeSpy).toHaveBeenCalledTimes(1);
+ it(`re-emits GlBanner's primary event & tracks an event`, () => {
+ expect(primarySpy).not.toHaveBeenCalled();
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ wrapper.findComponent(GlBanner).vm.$emit('primary');
+
+ expect(primarySpy).toHaveBeenCalledTimes(1);
+ expectTracking('click_button', UPGRADE_OR_FREE_TRIAL);
+ });
+ });
});
});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index 37ecce3886d..b042e870467 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -9,6 +9,7 @@ export const securityTrainingProviders = [
description: 'Interactive developer security education',
url: 'https://www.example.org/security/training',
isEnabled: false,
+ isPrimary: false,
},
{
id: textProviderIds[1],
@@ -16,24 +17,62 @@ export const securityTrainingProviders = [
description: 'Security training with guide and learning pathways.',
url: 'https://www.vendornametwo.com/',
isEnabled: true,
+ isPrimary: false,
},
];
export const securityTrainingProvidersResponse = {
data: {
- securityTrainingProviders,
+ project: {
+ id: 1,
+ securityTrainingProviders,
+ },
+ },
+};
+
+export const dismissUserCalloutResponse = {
+ data: {
+ userCalloutCreate: {
+ errors: [],
+ userCallout: {
+ dismissedAt: '2022-02-02T04:36:57Z',
+ featureName: 'SECURITY_TRAINING_FEATURE_PROMOTION',
+ },
+ },
+ },
+};
+
+export const dismissUserCalloutErrorResponse = {
+ data: {
+ userCalloutCreate: {
+ errors: ['Something went wrong'],
+ userCallout: {
+ dismissedAt: '',
+ featureName: 'SECURITY_TRAINING_FEATURE_PROMOTION',
+ },
+ },
},
};
-const defaultMockResolvers = {
- Query: {
- securityTrainingProviders() {
- return securityTrainingProviders;
+export const updateSecurityTrainingProvidersResponse = {
+ data: {
+ securityTrainingUpdate: {
+ errors: [],
+ training: {
+ id: 101,
+ name: 'Acme',
+ isEnabled: true,
+ isPrimary: false,
+ },
},
},
};
-export const createMockResolvers = ({ resolvers: customMockResolvers = {} } = {}) => ({
- ...defaultMockResolvers,
- ...customMockResolvers,
-});
+export const updateSecurityTrainingProvidersErrorResponse = {
+ data: {
+ securityTrainingUpdate: {
+ errors: ['something went wrong!'],
+ training: null,
+ },
+ },
+};
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 350055cb935..f57b9418be5 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -10,7 +10,7 @@ exports[`EmptyStateComponent should render content 1`] = `
<h1 class=\\"gl-font-size-h-display gl-line-height-36 h4\\">
Getting started with serverless
</h1>
- <p class=\\"gl-mt-3\\">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 class=\\"gl-mt-3\\">Serverless was <gl-link-stub target=\\"_blank\\" href=\\"https://about.gitlab.com/releases/2021/09/22/gitlab-14-3-released/#gitlab-serverless\\">deprecated</gl-link-stub>. But if you opt to use it, you must install Knative in your Kubernetes cluster first. <gl-link-stub href=\\"/help\\">Learn more.</gl-link-stub>
</p>
<div class=\\"gl-display-flex gl-flex-wrap gl-justify-content-center\\">
<!---->
diff --git a/spec/frontend/serverless/components/function_details_spec.js b/spec/frontend/serverless/components/function_details_spec.js
index d2b8de71e01..0c9b2498589 100644
--- a/spec/frontend/serverless/components/function_details_spec.js
+++ b/spec/frontend/serverless/components/function_details_spec.js
@@ -1,17 +1,16 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import functionDetailsComponent from '~/serverless/components/function_details.vue';
import { createStore } from '~/serverless/store';
describe('functionDetailsComponent', () => {
- let localVue;
let component;
let store;
beforeEach(() => {
- localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
store = createStore({ clustersPath: '/clusters', helpPath: '/help' });
});
@@ -33,7 +32,6 @@ describe('functionDetailsComponent', () => {
it('has a name, description, URL, and no pods loaded', () => {
component = shallowMount(functionDetailsComponent, {
- localVue,
store,
propsData: {
func: serviceStub,
@@ -58,7 +56,6 @@ describe('functionDetailsComponent', () => {
serviceStub.podcount = 1;
component = shallowMount(functionDetailsComponent, {
- localVue,
store,
propsData: {
func: serviceStub,
@@ -73,7 +70,6 @@ describe('functionDetailsComponent', () => {
serviceStub.podcount = 3;
component = shallowMount(functionDetailsComponent, {
- localVue,
store,
propsData: {
func: serviceStub,
@@ -88,7 +84,6 @@ describe('functionDetailsComponent', () => {
serviceStub.description = null;
component = shallowMount(functionDetailsComponent, {
- localVue,
store,
propsData: {
func: serviceStub,
diff --git a/spec/frontend/serverless/components/functions_spec.js b/spec/frontend/serverless/components/functions_spec.js
index 01dd512c5d3..846fd63e918 100644
--- a/spec/frontend/serverless/components/functions_spec.js
+++ b/spec/frontend/serverless/components/functions_spec.js
@@ -1,5 +1,6 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLoadingIcon, GlAlert, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
@@ -15,17 +16,16 @@ describe('functionsComponent', () => {
let component;
let store;
- let localVue;
let axiosMock;
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
axiosMock.onGet(statusPath).reply(200);
- localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
store = createStore({});
+ component = shallowMount(functionsComponent, { store, stubs: { GlSprintf } });
});
afterEach(() => {
@@ -33,23 +33,26 @@ describe('functionsComponent', () => {
axiosMock.restore();
});
- it('should render empty state when Knative is not installed', () => {
- store.dispatch('receiveFunctionsSuccess', { knative_installed: false });
- component = shallowMount(functionsComponent, { localVue, store });
+ it('should render deprecation notice', () => {
+ expect(component.findComponent(GlAlert).text()).toBe(
+ 'Serverless was deprecated in GitLab 14.3.',
+ );
+ });
+
+ it('should render empty state when Knative is not installed', async () => {
+ await store.dispatch('receiveFunctionsSuccess', { knative_installed: false });
- expect(component.find(EmptyState).exists()).toBe(true);
+ expect(component.findComponent(EmptyState).exists()).toBe(true);
});
- it('should render a loading component', () => {
- store.dispatch('requestFunctionsLoading');
- component = shallowMount(functionsComponent, { localVue, store });
+ it('should render a loading component', async () => {
+ await store.dispatch('requestFunctionsLoading');
- expect(component.find(GlLoadingIcon).exists()).toBe(true);
+ expect(component.findComponent(GlLoadingIcon).exists()).toBe(true);
});
- it('should render empty state when there is no function data', () => {
- store.dispatch('receiveFunctionsNoDataSuccess', { knative_installed: true });
- component = shallowMount(functionsComponent, { localVue, store });
+ it('should render empty state when there is no function data', async () => {
+ await store.dispatch('receiveFunctionsNoDataSuccess', { knative_installed: true });
expect(
component.vm.$el
@@ -62,27 +65,22 @@ describe('functionsComponent', () => {
);
});
- it('should render functions and a loader when functions are partially fetched', () => {
- store.dispatch('receiveFunctionsPartial', {
+ it('should render functions and a loader when functions are partially fetched', async () => {
+ await store.dispatch('receiveFunctionsPartial', {
...mockServerlessFunctions,
knative_installed: 'checking',
});
- component = shallowMount(functionsComponent, { localVue, store });
-
expect(component.find('.js-functions-wrapper').exists()).toBe(true);
expect(component.find('.js-functions-loader').exists()).toBe(true);
});
- it('should render the functions list', () => {
+ it('should render the functions list', async () => {
store = createStore({ clustersPath: 'clustersPath', helpPath: 'helpPath', statusPath });
- component = shallowMount(functionsComponent, { localVue, store });
-
- component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions);
+ await component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions);
- return component.vm.$nextTick().then(() => {
- expect(component.find(EnvironmentRow).exists()).toBe(true);
- });
+ await nextTick();
+ expect(component.findComponent(EnvironmentRow).exists()).toBe(true);
});
});
diff --git a/spec/frontend/serverless/survey_banner_spec.js b/spec/frontend/serverless/survey_banner_spec.js
deleted file mode 100644
index 4682c2328c3..00000000000
--- a/spec/frontend/serverless/survey_banner_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { GlBanner } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Cookies from 'js-cookie';
-import SurveyBanner from '~/serverless/survey_banner.vue';
-
-describe('Knative survey banner', () => {
- let wrapper;
-
- function mountBanner() {
- wrapper = shallowMount(SurveyBanner, {
- propsData: {
- surveyUrl: 'http://somesurvey.com/',
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('should render the banner when the cookie is absent', () => {
- jest.spyOn(Cookies, 'get').mockReturnValue(undefined);
- mountBanner();
-
- expect(Cookies.get).toHaveBeenCalled();
- expect(wrapper.find(GlBanner).exists()).toBe(true);
- });
-
- it('should close the banner and set a cookie when close button is clicked', () => {
- jest.spyOn(Cookies, 'get').mockReturnValue(undefined);
- jest.spyOn(Cookies, 'set');
- mountBanner();
-
- expect(wrapper.find(GlBanner).exists()).toBe(true);
- wrapper.find(GlBanner).vm.$emit('close');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(Cookies.set).toHaveBeenCalledWith('hide_serverless_survey', 'true', { expires: 3650 });
- expect(wrapper.find(GlBanner).exists()).toBe(false);
- });
- });
-
- it('should not render the banner when the cookie is set', () => {
- jest.spyOn(Cookies, 'get').mockReturnValue('true');
- mountBanner();
-
- expect(Cookies.get).toHaveBeenCalled();
- expect(wrapper.find(GlBanner).exists()).toBe(false);
- });
-});
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 0c6ed998747..c105810e11c 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
@@ -1,5 +1,6 @@
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import * as UserApi from '~/api/user_api';
import EmojiPicker from '~/emoji/components/picker.vue';
@@ -48,7 +49,7 @@ describe('SetStatusModalWrapper', () => {
const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox);
const findClearStatusAtMessage = () => wrapper.find('[data-testid="clear-status-at-message"]');
- const initModal = ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
+ const initModal = async ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
const modal = findModal();
// mock internal emoji methods
wrapper.vm.showEmojiMenu = jest.fn();
@@ -57,7 +58,7 @@ describe('SetStatusModalWrapper', () => {
if (mockOnUpdateFailure) wrapper.vm.onUpdateFail = jest.fn();
modal.vm.$emit('shown');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
afterEach(() => {
@@ -207,7 +208,7 @@ describe('SetStatusModalWrapper', () => {
it('clicking "removeStatus" clears the emoji and message fields', async () => {
findModal().vm.$emit('secondary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findFormField('message').element.value).toBe('');
expect(findFormField('emoji').element.value).toBe('');
@@ -215,7 +216,7 @@ describe('SetStatusModalWrapper', () => {
it('clicking "setStatus" submits the user status', async () => {
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
// set the availability status
findAvailabilityCheckbox().vm.$emit('input', true);
@@ -224,7 +225,7 @@ describe('SetStatusModalWrapper', () => {
wrapper.find('[data-testid="thirtyMinutes"]').vm.$emit('click');
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
const commonParams = {
emoji: defaultEmoji,
@@ -246,7 +247,7 @@ describe('SetStatusModalWrapper', () => {
it('calls the "onUpdateSuccess" handler', async () => {
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled();
});
@@ -262,7 +263,7 @@ describe('SetStatusModalWrapper', () => {
it('displays a toast success message', async () => {
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect($toast.show).toHaveBeenCalledWith('Status updated');
});
@@ -279,7 +280,7 @@ describe('SetStatusModalWrapper', () => {
it('calls the "onUpdateFail" handler', async () => {
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.onUpdateFail).toHaveBeenCalled();
});
@@ -295,7 +296,7 @@ describe('SetStatusModalWrapper', () => {
it('flashes an error message', async () => {
findModal().vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(createFlash).toHaveBeenCalledWith({
message: "Sorry, we weren't able to set your status. Please try again later.",
diff --git a/spec/frontend/settings_panels_spec.js b/spec/frontend/settings_panels_spec.js
index 6b739617b97..3a62cd703ab 100644
--- a/spec/frontend/settings_panels_spec.js
+++ b/spec/frontend/settings_panels_spec.js
@@ -24,6 +24,20 @@ describe('Settings Panels', () => {
expect(isExpanded(panel)).toBe(true);
});
+
+ it('should expand panel containing linked hash', () => {
+ window.location.hash = '#group_description';
+
+ const panel = document.querySelector('#js-general-settings');
+ // Our test environment automatically expands everything so we need to clear that out first
+ panel.classList.remove('expanded');
+
+ expect(isExpanded(panel)).toBe(false);
+
+ initSettingsPanels();
+
+ expect(isExpanded(panel)).toBe(true);
+ });
});
it('does not change the text content of triggers', () => {
diff --git a/spec/frontend/sidebar/assignees_realtime_spec.js b/spec/frontend/sidebar/assignees_realtime_spec.js
index ecf33d6de37..2249a1c08b8 100644
--- a/spec/frontend/sidebar/assignees_realtime_spec.js
+++ b/spec/frontend/sidebar/assignees_realtime_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
@@ -7,8 +8,7 @@ import SidebarMediator from '~/sidebar/sidebar_mediator';
import getIssueAssigneesQuery from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql';
import Mock, { issuableQueryResponse, subscriptionNullResponse } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Assignees Realtime', () => {
let wrapper;
@@ -38,7 +38,6 @@ describe('Assignees Realtime', () => {
mediator,
},
apolloProvider: fakeApollo,
- localVue,
});
};
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index b3a67f18f82..a4474ead956 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -1,5 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import UsersMockHelper from 'helpers/user_mock_data_helper';
import Assignee from '~/sidebar/components/assignees/assignees.vue';
@@ -59,7 +60,7 @@ describe('Assignee component', () => {
expect(componentTextNoUsers).toContain('assign yourself');
});
- it('emits the assign-self event when "assign yourself" is clicked', () => {
+ it('emits the assign-self event when "assign yourself" is clicked', async () => {
createWrapper({
...getDefaultProps(),
editable: true,
@@ -68,9 +69,8 @@ describe('Assignee component', () => {
jest.spyOn(wrapper.vm, '$emit');
wrapper.find('[data-testid="assign-yourself"]').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('assign-self')).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted('assign-self')).toBeTruthy();
});
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
index 07da4acef8c..def46255994 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -1,6 +1,7 @@
import { GlSearchBoxByType, GlDropdown } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -23,8 +24,7 @@ const updateIssueAssigneesMutationSuccess = jest
.mockResolvedValue(updateIssueAssigneesMutationResponse);
const mockError = jest.fn().mockRejectedValue('Error!');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const initialAssignees = [
{
@@ -59,7 +59,6 @@ describe('Sidebar assignees widget', () => {
[updateIssueAssigneesMutation, updateIssueAssigneesMutationHandler],
]);
wrapper = shallowMount(SidebarAssigneesWidget, {
- localVue,
apolloProvider: fakeApollo,
propsData: {
iid: '1',
@@ -138,9 +137,17 @@ describe('Sidebar assignees widget', () => {
createComponent();
await waitForPromises();
- expect(findAssignees().props('users')).toEqual(
- issuableQueryResponse.data.workspace.issuable.assignees.nodes,
- );
+ expect(findAssignees().props('users')).toEqual([
+ {
+ id: 'gid://gitlab/User/2',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
+ name: 'Jacki Kub',
+ username: 'francina.skiles',
+ webUrl: '/franc',
+ status: null,
+ },
+ ]);
});
it('renders an error when issuable query is rejected', async () => {
@@ -196,7 +203,7 @@ describe('Sidebar assignees widget', () => {
{
assignees: [
{
- __typename: 'User',
+ __typename: 'UserCore',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
id: 'gid://gitlab/User/1',
@@ -322,9 +329,10 @@ describe('Sidebar assignees widget', () => {
});
describe('when user is not signed in', () => {
- beforeEach(() => {
+ beforeEach(async () => {
gon.current_username = undefined;
createComponent();
+ await waitForPromises();
});
it('passes signedIn prop as false to IssuableAssignees', () => {
@@ -353,6 +361,7 @@ describe('Sidebar assignees widget', () => {
describe('when making changes to participants list', () => {
beforeEach(async () => {
createComponent();
+ await waitForPromises();
});
it('passes falsy `isDirty` prop to editable item if no changes to selected users were made', () => {
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
index 84b192aaf41..c870bbecd76 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
describe('boards sidebar remove issue', () => {
@@ -71,7 +72,7 @@ describe('boards sidebar remove issue', () => {
createComponent({ canUpdate: true, slots });
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(findCollapsed().isVisible()).toBe(false);
expect(findExpanded().isVisible()).toBe(true);
@@ -82,14 +83,14 @@ describe('boards sidebar remove issue', () => {
beforeEach(async () => {
createComponent({ canUpdate: true });
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('hides expanded section and displays collapsed section', async () => {
expect(findExpanded().isVisible()).toBe(true);
document.body.click();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCollapsed().isVisible()).toBe(true);
expect(findExpanded().isVisible()).toBe(false);
@@ -101,7 +102,7 @@ describe('boards sidebar remove issue', () => {
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted().open.length).toBe(1);
});
@@ -111,7 +112,7 @@ describe('boards sidebar remove issue', () => {
findEditButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.vm.collapse({ emitEvent: false });
diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
index c72c23a3a60..90aae85e1ca 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import UsersMockHelper from 'helpers/user_mock_data_helper';
import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue';
@@ -84,10 +85,10 @@ describe('UncollapsedAssigneeList component', () => {
});
describe('when more button is clicked', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findMoreButton().trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows "show less" label', () => {
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
index 707215d0739..1de71e52264 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
@@ -1,5 +1,6 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -15,8 +16,7 @@ import { issueConfidentialityResponse } from '../../mock_data';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Sidebar Confidentiality Widget', () => {
let wrapper;
@@ -32,7 +32,6 @@ describe('Sidebar Confidentiality Widget', () => {
fakeApollo = createMockApollo([[issueConfidentialQuery, confidentialQueryHandler]]);
wrapper = shallowMount(SidebarConfidentialityWidget, {
- localVue,
apolloProvider: fakeApollo,
provide: {
canUpdate: true,
diff --git a/spec/frontend/sidebar/components/mock_data.js b/spec/frontend/sidebar/components/mock_data.js
index 70c3f8a3012..a9a00b3cfdf 100644
--- a/spec/frontend/sidebar/components/mock_data.js
+++ b/spec/frontend/sidebar/components/mock_data.js
@@ -1,6 +1,7 @@
export const getIssueCrmContactsQueryResponse = {
data: {
issue: {
+ __typename: 'Issue',
id: 'gid://gitlab/Issue/123',
customerRelationsContacts: {
nodes: [
@@ -37,6 +38,7 @@ export const issueCrmContactsUpdateNullResponse = {
export const issueCrmContactsUpdateResponse = {
data: {
issueCrmContactsUpdated: {
+ __typename: 'Issue',
id: 'gid://gitlab/Issue/123',
customerRelationsContacts: {
nodes: [
diff --git a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
index 859e63b3df6..338ecf944f3 100644
--- a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
+++ b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import { stripTypenames } from 'helpers/graphql_helpers';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Participants from '~/sidebar/components/participants/participants.vue';
@@ -66,9 +67,11 @@ describe('Sidebar Participants Widget', () => {
});
it('passes participants to child component', () => {
- expect(findParticipants().props('participants')).toEqual(
+ const participantsWithoutTypename = stripTypenames(
epicParticipantsResponse().data.workspace.issuable.participants.nodes,
);
+
+ expect(findParticipants().props('participants')).toEqual(participantsWithoutTypename);
});
});
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
index 6116bc68927..5d80a221d8e 100644
--- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -97,14 +97,14 @@ describe('SidebarSeverity', () => {
});
});
- it('shows error alert when severity update fails ', () => {
+ it('shows error alert when severity update fails ', async () => {
const errorMsg = 'Something went wrong';
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValueOnce(errorMsg);
findCriticalSeverityDropdownItem().vm.$emit('click');
- setImmediate(() => {
- expect(createFlash).toHaveBeenCalled();
- });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
});
it('shows loading icon while updating', async () => {
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
index d7471d99477..3ddd41c0bd4 100644
--- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
@@ -8,9 +8,9 @@ import {
GlLoadingIcon,
} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-
import createMockApollo from 'helpers/mock_apollo_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -37,8 +37,6 @@ import {
jest.mock('~/flash');
-const localVue = createLocalVue();
-
describe('SidebarDropdownWidget', () => {
let wrapper;
let mockApollo;
@@ -78,7 +76,7 @@ describe('SidebarDropdownWidget', () => {
// It then emits `shown` event in a watcher for `visible`
// Hence we need both of these:
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const waitForApollo = async () => {
@@ -108,7 +106,7 @@ describe('SidebarDropdownWidget', () => {
projectMilestonesSpy = jest.fn().mockResolvedValue(mockProjectMilestonesResponse),
currentMilestoneSpy = jest.fn().mockResolvedValue(noCurrentMilestoneResponse),
} = {}) => {
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
mockApollo = createMockApollo([
[projectMilestonesQuery, projectMilestonesSpy],
[projectIssueMilestoneQuery, currentMilestoneSpy],
@@ -117,7 +115,6 @@ describe('SidebarDropdownWidget', () => {
wrapper = extendedWrapper(
mount(SidebarDropdownWidget, {
- localVue,
provide: { canUpdate: true },
apolloProvider: mockApollo,
propsData: {
@@ -354,7 +351,7 @@ describe('SidebarDropdownWidget', () => {
});
it(`calls createFlash with "${expectedMsg}"`, async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(createFlash).toHaveBeenCalledWith({
message: expectedMsg,
captureError: true,
@@ -377,7 +374,7 @@ describe('SidebarDropdownWidget', () => {
findSearchBox().vm.$emit('input', 'non existing milestones');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdownText().text()).toBe('No milestone found');
});
@@ -482,7 +479,7 @@ describe('SidebarDropdownWidget', () => {
it('sends a projectMilestones query with the entered search term "foo"', async () => {
findSearchBox().vm.$emit('input', mockSearchTerm);
- await wrapper.vm.$nextTick();
+ await nextTick();
// Account for debouncing
jest.runAllTimers();
diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js
index 64d143615a0..2b17e6dd6c3 100644
--- a/spec/frontend/sidebar/components/time_tracking/report_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { getAllByRole, getByRole } from '@testing-library/dom';
-import { shallowMount, createLocalVue, mount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -13,8 +14,7 @@ import { getIssueTimelogsQueryResponse, getMrTimelogsQueryResponse } from './moc
jest.mock('~/flash');
describe('Issuable Time Tracking Report', () => {
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
let wrapper;
let fakeApollo;
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -37,7 +37,6 @@ describe('Issuable Time Tracking Report', () => {
issuableType,
},
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 eb202a8cfcc..835e700e63c 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { stubTransition } from 'helpers/stub_transition';
import { createMockDirective } from 'helpers/vue_mock_directive';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
@@ -161,7 +162,7 @@ describe('Issuable Time Tracker', () => {
it('should show the correct tooltip text', async () => {
expect(findByTestId('timeTrackingComparisonPane').exists()).toBe(true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findComparisonMeter()).toBe('Time remaining: 26h 23m');
});
@@ -179,7 +180,7 @@ describe('Issuable Time Tracker', () => {
},
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('should display the human readable version of time estimated', () => {
@@ -282,7 +283,7 @@ describe('Issuable Time Tracker', () => {
},
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('should not show the "Help" pane by default', () => {
@@ -292,19 +293,19 @@ describe('Issuable Time Tracker', () => {
it('should show the "Help" pane when help button is clicked', async () => {
findHelpButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findByTestId('helpPane').exists()).toBe(true);
});
it('should not show the "Help" pane when help button is clicked and then closed', async () => {
findHelpButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findByTestId('helpPane').exists()).toBe(true);
findCloseHelpButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findByTestId('helpPane').exists()).toBe(false);
});
@@ -315,7 +316,7 @@ describe('Issuable Time Tracker', () => {
it('refetches issuableTimeTracking query when eventHub emits `timeTracker:refresh` event', async () => {
SidebarEventHub.$emit('timeTracker:refresh');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(issuableTimeTrackingRefetchSpy).toHaveBeenCalled();
});
diff --git a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
index 23f1753c4bf..ea931782d1e 100644
--- a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
+++ b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
@@ -1,6 +1,6 @@
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -103,7 +103,7 @@ describe('Sidebar Todo Widget', () => {
});
it('sets default tooltip title', () => {
- expect(wrapper.find(GlIcon).attributes('title')).toBe('Add a to do');
+ expect(wrapper.find(GlButton).attributes('title')).toBe('Add a to do');
});
it('when user has a to do', async () => {
@@ -113,13 +113,13 @@ describe('Sidebar Todo Widget', () => {
await waitForPromises();
expect(wrapper.find(GlIcon).props('name')).toBe('todo-done');
- expect(wrapper.find(GlIcon).attributes('title')).toBe('Mark as done');
+ expect(wrapper.find(GlButton).attributes('title')).toBe('Mark as done');
});
it('emits `todoUpdated` event on click on icon', async () => {
wrapper.find(GlIcon).vm.$emit('click', event);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('todoUpdated')).toEqual([[false]]);
});
});
diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
index 1673425947e..971744edb0f 100644
--- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import createFlash from '~/flash';
import { createStore as createMrStore } from '~/mr_notes/stores';
import createStore from '~/notes/stores';
@@ -118,15 +119,13 @@ describe('EditFormButtons', () => {
});
it('resets loading', async () => {
- await wrapper.vm.$nextTick().then(() => {
- expect(findLockToggle().props('loading')).toBe(false);
- });
+ await nextTick();
+ expect(findLockToggle().props('loading')).toBe(false);
});
- it('emits close form', () => {
- return wrapper.vm.$nextTick().then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
- });
+ it('emits close form', async () => {
+ await nextTick();
+ expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
});
it('does not flash an error message', () => {
@@ -153,15 +152,13 @@ describe('EditFormButtons', () => {
});
it('resets loading', async () => {
- await wrapper.vm.$nextTick().then(() => {
- expect(findLockToggle().props('loading')).toBe(false);
- });
+ await nextTick();
+ expect(findLockToggle().props('loading')).toBe(false);
});
- it('emits close form', () => {
- return wrapper.vm.$nextTick().then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
- });
+ it('emits close form', async () => {
+ await nextTick();
+ expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
});
it('calls flash with the correct message', () => {
diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
index 1743e114bb0..7bf7e563a01 100644
--- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
+++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { createStore as createMrStore } from '~/mr_notes/stores';
@@ -80,13 +81,12 @@ describe('IssuableLockForm', () => {
});
describe('when not editable', () => {
- it('does not display the edit form when opened if not editable', () => {
+ it('does not display the edit form when opened if not editable', async () => {
expect(findEditForm().exists()).toBe(false);
findSidebarCollapseIcon().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditForm().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findEditForm().exists()).toBe(false);
});
});
@@ -102,13 +102,12 @@ describe('IssuableLockForm', () => {
});
describe("when 'Edit' is clicked", () => {
- it('displays the edit form when editable', () => {
+ it('displays the edit form when editable', async () => {
expect(findEditForm().exists()).toBe(false);
findEditLink().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditForm().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findEditForm().exists()).toBe(true);
});
it('tracks the event ', () => {
@@ -123,13 +122,12 @@ describe('IssuableLockForm', () => {
});
describe('When sidebar is collapsed', () => {
- it('displays the edit form when opened', () => {
+ it('displays the edit form when opened', async () => {
expect(findEditForm().exists()).toBe(false);
findSidebarCollapseIcon().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditForm().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findEditForm().exists()).toBe(true);
});
it('renders a tooltip with the lock status text', () => {
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index 42e89a3ba84..30972484a08 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -276,6 +276,7 @@ export const epicParticipantsResponse = () => ({
participants: {
nodes: [
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
@@ -332,6 +333,7 @@ export const issuableQueryResponse = {
assignees: {
nodes: [
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
@@ -389,7 +391,7 @@ export const updateIssueAssigneesMutationResponse = {
assignees: {
nodes: [
{
- __typename: 'User',
+ __typename: 'UserCore',
id: 'gid://gitlab/User/1',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
@@ -414,6 +416,7 @@ export const subscriptionNullResponse = {
};
const mockUser1 = {
+ __typename: 'UserCore',
id: 'gid://gitlab/User/1',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
@@ -424,6 +427,7 @@ const mockUser1 = {
};
export const mockUser2 = {
+ __typename: 'UserCore',
id: 'gid://gitlab/User/4',
avatarUrl: '/avatar2',
name: 'rookie',
@@ -470,6 +474,7 @@ export const projectMembersResponse = {
{
id: 'user-4',
user: {
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
@@ -503,6 +508,7 @@ export const groupMembersResponse = {
{
id: 'user-3',
user: {
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
@@ -535,6 +541,7 @@ export const participantsQueryResponse = {
mockUser1,
mockUser1,
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
@@ -546,6 +553,7 @@ export const participantsQueryResponse = {
},
},
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/3',
avatarUrl: '/avatar',
name: 'John Doe',
diff --git a/spec/frontend/sidebar/participants_spec.js b/spec/frontend/sidebar/participants_spec.js
index 94cdbe7f2ef..356628849d9 100644
--- a/spec/frontend/sidebar/participants_spec.js
+++ b/spec/frontend/sidebar/participants_spec.js
@@ -1,6 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import Participants from '~/sidebar/components/participants/participants.vue';
const PARTICIPANT = {
@@ -77,7 +77,7 @@ describe('Participants', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('when only showing visible participants, shows an avatar only for each participant under the limit', () => {
+ it('when only showing visible participants, shows an avatar only for each participant under the limit', async () => {
const numberOfLessParticipants = 2;
wrapper = mountComponent({
loading: false,
@@ -91,12 +91,11 @@ describe('Participants', () => {
isShowingMoreParticipants: false,
});
- return Vue.nextTick().then(() => {
- expect(wrapper.findAll('.participants-author')).toHaveLength(numberOfLessParticipants);
- });
+ await nextTick();
+ expect(wrapper.findAll('.participants-author')).toHaveLength(numberOfLessParticipants);
});
- it('when only showing all participants, each has an avatar', () => {
+ it('when only showing all participants, each has an avatar', async () => {
wrapper = mountComponent({
loading: false,
participants: PARTICIPANT_LIST,
@@ -109,9 +108,8 @@ describe('Participants', () => {
isShowingMoreParticipants: true,
});
- return Vue.nextTick().then(() => {
- expect(wrapper.findAll('.participants-author')).toHaveLength(PARTICIPANT_LIST.length);
- });
+ await nextTick();
+ expect(wrapper.findAll('.participants-author')).toHaveLength(PARTICIPANT_LIST.length);
});
it('does not have more participants link when they can all be shown', () => {
@@ -126,7 +124,7 @@ describe('Participants', () => {
expect(getMoreParticipantsButton().exists()).toBe(false);
});
- it('when too many participants, has more participants link to show more', () => {
+ it('when too many participants, has more participants link to show more', async () => {
wrapper = mountComponent({
loading: false,
participants: PARTICIPANT_LIST,
@@ -139,12 +137,11 @@ describe('Participants', () => {
isShowingMoreParticipants: false,
});
- return Vue.nextTick().then(() => {
- expect(getMoreParticipantsButton().text()).toBe('+ 1 more');
- });
+ await nextTick();
+ expect(getMoreParticipantsButton().text()).toBe('+ 1 more');
});
- it('when too many participants and already showing them, has more participants link to show less', () => {
+ it('when too many participants and already showing them, has more participants link to show less', async () => {
wrapper = mountComponent({
loading: false,
participants: PARTICIPANT_LIST,
@@ -157,9 +154,8 @@ describe('Participants', () => {
isShowingMoreParticipants: true,
});
- return Vue.nextTick().then(() => {
- expect(getMoreParticipantsButton().text()).toBe('- show less');
- });
+ await nextTick();
+ expect(getMoreParticipantsButton().text()).toBe('- show less');
});
it('clicking more participants link emits event', () => {
@@ -176,7 +172,7 @@ describe('Participants', () => {
expect(wrapper.vm.isShowingMoreParticipants).toBe(true);
});
- it('clicking on participants icon emits `toggleSidebar` event', () => {
+ it('clicking on participants icon emits `toggleSidebar` event', async () => {
wrapper = mountComponent({
loading: false,
participants: PARTICIPANT_LIST,
@@ -187,11 +183,9 @@ describe('Participants', () => {
wrapper.find('.sidebar-collapsed-icon').trigger('click');
- return Vue.nextTick(() => {
- expect(spy).toHaveBeenCalledWith('toggleSidebar');
-
- spy.mockRestore();
- });
+ await nextTick();
+ expect(spy).toHaveBeenCalledWith('toggleSidebar');
+ spy.mockRestore();
});
});
diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js
index dc121dcb897..5f77e21c1f8 100644
--- a/spec/frontend/sidebar/sidebar_assignees_spec.js
+++ b/spec/frontend/sidebar/sidebar_assignees_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import axios from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import Assigness from '~/sidebar/components/assignees/assignees.vue';
import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue';
@@ -74,16 +75,15 @@ describe('sidebar assignees', () => {
expect(mediator.store.assignees.length).toBe(1);
});
- it('hides assignees until fetched', () => {
+ it('hides assignees until fetched', async () => {
createComponent();
expect(wrapper.find(Assigness).exists()).toBe(false);
wrapper.vm.store.isFetching.assignees = false;
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(Assigness).exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(Assigness).exists()).toBe(true);
});
describe('when realTimeIssueSidebar is turned on', () => {
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js
index d9972ae75c3..7bb7b18adf8 100644
--- a/spec/frontend/sidebar/sidebar_move_issue_spec.js
+++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js
@@ -1,5 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
+import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
@@ -77,15 +78,14 @@ describe('SidebarMoveIssue', () => {
expect(test.sidebarMoveIssue.$dropdownToggle.data('deprecatedJQueryDropdown')).toBeTruthy();
});
- it('escapes html from project name', (done) => {
+ it('escapes html from project name', async () => {
test.$toggleButton.dropdown('toggle');
- setImmediate(() => {
- expect(test.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual(
- '&lt;img src=x onerror=alert(document.domain)&gt; foo / bar',
- );
- done();
- });
+ await waitForPromises();
+
+ expect(test.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual(
+ '&lt;img src=x onerror=alert(document.domain)&gt; foo / bar',
+ );
});
});
@@ -101,20 +101,20 @@ describe('SidebarMoveIssue', () => {
expect(test.$confirmButton.hasClass('is-loading')).toBe(true);
});
- it('should remove loading state from confirm button on failure', (done) => {
+ it('should remove loading state from confirm button on failure', async () => {
jest.spyOn(test.mediator, 'moveIssue').mockReturnValue(Promise.reject());
test.mediator.setMoveToProjectId(7);
test.sidebarMoveIssue.onConfirmClicked();
expect(test.mediator.moveIssue).toHaveBeenCalled();
+
// Wait for the move issue request to fail
- setImmediate(() => {
- expect(createFlash).toHaveBeenCalled();
- expect(test.$confirmButton.prop('disabled')).toBeFalsy();
- expect(test.$confirmButton.hasClass('is-loading')).toBe(false);
- done();
- });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
+ expect(test.$confirmButton.prop('disabled')).toBeFalsy();
+ expect(test.$confirmButton.hasClass('is-loading')).toBe(false);
});
it('should not move the issue with id=0', () => {
@@ -127,35 +127,33 @@ describe('SidebarMoveIssue', () => {
});
});
- it('should set moveToProjectId on dropdown item "No project" click', (done) => {
+ it('should set moveToProjectId on dropdown item "No project" click', async () => {
jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {});
// Open the dropdown
test.$toggleButton.dropdown('toggle');
// Wait for the autocomplete request to finish
- setImmediate(() => {
- test.$content.find('.js-move-issue-dropdown-item').eq(0).trigger('click');
+ await waitForPromises();
- expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
- expect(test.$confirmButton.prop('disabled')).toBeTruthy();
- done();
- });
+ test.$content.find('.js-move-issue-dropdown-item').eq(0).trigger('click');
+
+ expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
+ expect(test.$confirmButton.prop('disabled')).toBeTruthy();
});
- it('should set moveToProjectId on dropdown item click', (done) => {
+ it('should set moveToProjectId on dropdown item click', async () => {
jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {});
// Open the dropdown
test.$toggleButton.dropdown('toggle');
// Wait for the autocomplete request to finish
- setImmediate(() => {
- test.$content.find('.js-move-issue-dropdown-item').eq(1).trigger('click');
+ await waitForPromises();
- expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
- expect(test.$confirmButton.attr('disabled')).toBe(undefined);
- done();
- });
+ test.$content.find('.js-move-issue-dropdown-item').eq(1).trigger('click');
+
+ expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
+ expect(test.$confirmButton.attr('disabled')).toBe(undefined);
});
});
diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js
index 6829e688c65..9316268d2ad 100644
--- a/spec/frontend/sidebar/todo_spec.js
+++ b/spec/frontend/sidebar/todo_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue';
const defaultProps = {
@@ -49,13 +50,12 @@ describe('SidebarTodo', () => {
);
describe('template', () => {
- it('emits `toggleTodo` event when clicked on button', () => {
+ it('emits `toggleTodo` event when clicked on button', async () => {
createComponent();
wrapper.find('button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().toggleTodo).toBeTruthy();
- });
+ await nextTick();
+ expect(wrapper.emitted().toggleTodo).toBeTruthy();
});
it('renders component container element with proper data attributes', () => {
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 80a8b8ec489..61424fa1eb2 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -1,7 +1,8 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import { merge } from 'lodash';
-import { nextTick } from 'vue';
+
import VueApollo, { ApolloMutation } from 'vue-apollo';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -78,8 +79,7 @@ const getApiData = ({
blobActions: [],
});
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('Snippet Edit app', () => {
useFakeDate();
@@ -141,7 +141,6 @@ describe('Snippet Edit app', () => {
wrapper = shallowMount(SnippetEditApp, {
apolloProvider,
- localVue,
stubs: {
ApolloMutation,
FormFooterActions,
@@ -330,6 +329,7 @@ describe('Snippet Edit app', () => {
mutateSpy.mockRejectedValue(TEST_API_ERROR);
await createComponentAndSubmit();
+ await nextTick();
});
it('should not redirect', () => {
@@ -339,7 +339,7 @@ describe('Snippet Edit app', () => {
it('should flash', () => {
// Apollo automatically wraps the resolver's error in a NetworkError
expect(createFlash).toHaveBeenCalledWith({
- message: `Can't update snippet: Network error: ${TEST_API_ERROR.message}`,
+ message: `Can't update snippet: ${TEST_API_ERROR.message}`,
});
});
@@ -349,7 +349,7 @@ describe('Snippet Edit app', () => {
// eslint-disable-next-line no-console
expect(console.error).toHaveBeenCalledWith(
'[gitlab] unexpected error while updating snippet',
- expect.objectContaining({ message: `Network error: ${TEST_API_ERROR.message}` }),
+ expect.objectContaining({ message: `${TEST_API_ERROR.message}` }),
);
});
});
diff --git a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js
index 2693b26aeae..8174ba5c693 100644
--- a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { times } from 'lodash';
+import { nextTick } from 'vue';
import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
import {
@@ -193,7 +194,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => {
it('emits an action when content changes again', async () => {
triggerBlobUpdate(0, { content });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getLastActions()).toEqual([testEntries.updated.diff]);
});
diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js
index 172089f9ee6..c395112e313 100644
--- a/spec/frontend/snippets/components/snippet_blob_view_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js
@@ -86,21 +86,17 @@ describe('Blob Embeddable', () => {
expect(wrapper.find(RichViewer).exists()).toBe(true);
});
- it('correctly switches viewer type', () => {
+ it('correctly switches viewer type', async () => {
createComponent();
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
wrapper.vm.switchViewer(RichViewerMock.type);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.find(RichViewer).exists()).toBe(true);
- wrapper.vm.switchViewer(SimpleViewerMock.type);
- })
- .then(() => {
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(RichViewer).exists()).toBe(true);
+ await wrapper.vm.switchViewer(SimpleViewerMock.type);
+
+ expect(wrapper.find(SimpleViewer).exists()).toBe(true);
});
it('passes information about render error down to blob header', () => {
@@ -191,22 +187,18 @@ describe('Blob Embeddable', () => {
});
describe('switchViewer()', () => {
- it('switches to the passed viewer', () => {
+ it('switches to the passed viewer', async () => {
createComponent();
wrapper.vm.switchViewer(RichViewerMock.type);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
- expect(wrapper.find(RichViewer).exists()).toBe(true);
-
- wrapper.vm.switchViewer(SimpleViewerMock.type);
- })
- .then(() => {
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
- });
+
+ await nextTick();
+ expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
+ expect(wrapper.find(RichViewer).exists()).toBe(true);
+
+ await wrapper.vm.switchViewer(SimpleViewerMock.type);
+ expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
+ expect(wrapper.find(SimpleViewer).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index daa9d6345b0..1b9d170556b 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -2,6 +2,7 @@ import { GlButton, GlModal, GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
@@ -245,7 +246,7 @@ describe('Snippet header component', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ canCreateSnippet: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findButtonsAsModel()).toEqual(
expect.arrayContaining([
@@ -348,33 +349,31 @@ describe('Snippet header component', () => {
describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
useMockLocationHelper();
- const createDeleteSnippet = (snippetProps = {}) => {
+ const createDeleteSnippet = async (snippetProps = {}) => {
createComponent({
snippetProps,
});
wrapper.vm.closeDeleteModal = jest.fn();
wrapper.vm.deleteSnippet();
- return wrapper.vm.$nextTick();
+ await nextTick();
};
- it('redirects to dashboard/snippets for personal snippet', () => {
- return createDeleteSnippet().then(() => {
- expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
- expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`);
- });
+ it('redirects to dashboard/snippets for personal snippet', async () => {
+ await createDeleteSnippet();
+ expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
+ expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`);
});
- it('redirects to project snippets for project snippet', () => {
+ it('redirects to project snippets for project snippet', async () => {
const fullPath = 'foo/bar';
- return createDeleteSnippet({
+ await createDeleteSnippet({
project: {
fullPath,
},
- }).then(() => {
- expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
- expect(window.location.pathname).toBe(`${fullPath}/-/snippets`);
});
+ expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
+ expect(window.location.pathname).toBe(`${fullPath}/-/snippets`);
});
});
});
diff --git a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
index 7a8834933e0..f6b29e98e5f 100644
--- a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlDropdownItem, GlFormInput, GlFormTextarea } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
import { mergeRequestMeta, mergeRequestTemplates } from '../mock_data';
@@ -38,11 +39,11 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
const findGlFormTextAreaDescription = () => wrapper.find(GlFormTextarea);
- beforeEach(() => {
+ beforeEach(async () => {
buildWrapper();
buildMocks();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
diff --git a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
index 3a336f6a230..bf3f8b7f571 100644
--- a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js
@@ -1,6 +1,7 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import axios from '~/lib/utils/axios_utils';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
@@ -50,14 +51,14 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
const findEditMetaControls = () => wrapper.find(EditMetaControls);
const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
- beforeEach(() => {
+ beforeEach(async () => {
localStorage.setItem(MR_META_LOCAL_STORAGE_KEY);
buildMockAxios();
buildWrapper();
buildMockRefs();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -77,7 +78,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
findLocalStorageSync().vm.$emit('input', localStorageMeta);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEditMetaControls().props()).toEqual(localStorageMeta);
});
@@ -134,13 +135,13 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
it('sets the currentTemplate on the changeTemplate event', async () => {
findEditMetaControls().vm.$emit('changeTemplate', template1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEditMetaControls().props().currentTemplate).toBe(template1);
findEditMetaControls().vm.$emit('changeTemplate', null);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEditMetaControls().props().currentTemplate).toBe(null);
});
@@ -148,7 +149,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
it('updates the description on the changeTemplate event', async () => {
findEditMetaControls().vm.$emit('changeTemplate', template1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEditMetaControls().props().description).toEqual(template1.content);
});
@@ -164,7 +165,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => {
findEditMetaControls().vm.$emit('updateSettings', newMeta);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLocalStorageSync().props('value')).toEqual(newMeta);
});
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
index eb056469603..6571d295c36 100644
--- a/spec/frontend/static_site_editor/pages/home_spec.js
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import EditArea from '~/static_site_editor/components/edit_area.vue';
import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
@@ -29,8 +30,6 @@ import {
imageRoot,
} from '../mock_data';
-const localVue = createLocalVue();
-
describe('static_site_editor/pages/home', () => {
let wrapper;
let store;
@@ -78,7 +77,6 @@ describe('static_site_editor/pages/home', () => {
const buildWrapper = (data = {}) => {
wrapper = shallowMount(Home, {
- localVue,
store,
mocks: {
$apollo,
@@ -182,7 +180,7 @@ describe('static_site_editor/pages/home', () => {
});
describe('when preparing submission', () => {
- it('calls the show method when the edit-area submit event is emitted', () => {
+ it('calls the show method when the edit-area submit event is emitted', async () => {
buildWrapper();
const mockInstance = { show: jest.fn() };
@@ -190,9 +188,8 @@ describe('static_site_editor/pages/home', () => {
findEditArea().vm.$emit('submit', { content });
- return wrapper.vm.$nextTick().then(() => {
- expect(mockInstance.show).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(mockInstance.show).toHaveBeenCalled();
});
});
@@ -203,13 +200,13 @@ describe('static_site_editor/pages/home', () => {
.mockRejectedValueOnce(new Error(submitChangesError));
};
- beforeEach(() => {
+ beforeEach(async () => {
setupMutateMock();
buildWrapper({ content });
findEditMetaModal().vm.$emit('primary', mergeRequestMeta);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays submit changes error message', () => {
@@ -224,12 +221,11 @@ describe('static_site_editor/pages/home', () => {
expect(mutateMock).toHaveBeenCalled();
});
- it('hides submit changes error message when dismiss button is clicked', () => {
+ it('hides submit changes error message when dismiss button is clicked', async () => {
findSubmitChangesError().vm.$emit('dismiss');
- return wrapper.vm.$nextTick().then(() => {
- expect(findSubmitChangesError().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findSubmitChangesError().exists()).toBe(false);
});
});
@@ -237,7 +233,7 @@ describe('static_site_editor/pages/home', () => {
const newContent = `new ${content}`;
const formattedMarkdown = `formatted ${content}`;
- beforeEach(() => {
+ beforeEach(async () => {
mutateMock.mockResolvedValueOnce(hasSubmittedChangesMutationPayload).mockResolvedValueOnce({
data: {
submitContentChanges: savedContentMeta,
@@ -252,7 +248,7 @@ describe('static_site_editor/pages/home', () => {
findEditMetaModal().vm.$emit('primary', mergeRequestMeta);
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('dispatches hasSubmittedChanges mutation', () => {
diff --git a/spec/frontend/terraform/components/states_table_actions_spec.js b/spec/frontend/terraform/components/states_table_actions_spec.js
index fbe55306f37..a6c80b95af4 100644
--- a/spec/frontend/terraform/components/states_table_actions_spec.js
+++ b/spec/frontend/terraform/components/states_table_actions_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlModal, GlSprintf } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -9,8 +10,7 @@ import lockStateMutation from '~/terraform/graphql/mutations/lock_state.mutation
import removeStateMutation from '~/terraform/graphql/mutations/remove_state.mutation.graphql';
import unlockStateMutation from '~/terraform/graphql/mutations/unlock_state.mutation.graphql';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('StatesTableActions', () => {
let lockResponse;
@@ -58,20 +58,19 @@ describe('StatesTableActions', () => {
);
};
- const createComponent = (propsData = defaultProps) => {
+ const createComponent = async (propsData = defaultProps) => {
const apolloProvider = createMockApolloProvider();
toast = jest.fn();
wrapper = shallowMount(StateActions, {
apolloProvider,
- localVue,
propsData,
mocks: { $toast: { show: toast } },
stubs: { GlDropdown, GlModal, GlSprintf },
});
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const findActionsDropdown = () => wrapper.findComponent(GlDropdown);
diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js
index 100e577f514..fa9c8320b4f 100644
--- a/spec/frontend/terraform/components/states_table_spec.js
+++ b/spec/frontend/terraform/components/states_table_spec.js
@@ -1,5 +1,6 @@
-import { GlIcon, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
+import { GlBadge, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useFakeDate } from 'helpers/fake_date';
import StatesTable from '~/terraform/components/states_table.vue';
import StateActions from '~/terraform/components/states_table_actions.vue';
@@ -106,9 +107,9 @@ describe('StatesTable', () => {
],
};
- const createComponent = (propsData = defaultProps) => {
+ const createComponent = async (propsData = defaultProps) => {
wrapper = mount(StatesTable, { propsData });
- return wrapper.vm.$nextTick();
+ await nextTick();
};
const findActions = () => wrapper.findAll(StateActions);
@@ -138,7 +139,7 @@ describe('StatesTable', () => {
const toolTip = state.find(GlTooltip);
expect(state.text()).toContain(name);
- expect(state.find(GlIcon).exists()).toBe(locked);
+ expect(state.find(GlBadge).exists()).toBe(locked);
expect(state.find(GlLoadingIcon).exists()).toBe(loading);
expect(toolTip.exists()).toBe(locked);
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
index 8e565df81ae..c8b4cd564d9 100644
--- a/spec/frontend/terraform/components/terraform_list_spec.js
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -8,8 +9,7 @@ import StatesTable from '~/terraform/components/states_table.vue';
import TerraformList from '~/terraform/components/terraform_list.vue';
import getStatesQuery from '~/terraform/graphql/queries/get_states.query.graphql';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('TerraformList', () => {
let wrapper;
@@ -45,7 +45,6 @@ describe('TerraformList', () => {
const apolloProvider = createMockApollo([[getStatesQuery, statsQueryResponse]], mockResolvers);
wrapper = shallowMount(TerraformList, {
- localVue,
apolloProvider,
propsData,
stubs: {
@@ -100,6 +99,7 @@ describe('TerraformList', () => {
nodes: states,
count: states.length,
pageInfo: {
+ __typename: 'PageInfo',
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'prev',
diff --git a/spec/frontend/toggles/index_spec.js b/spec/frontend/toggles/index_spec.js
new file mode 100644
index 00000000000..575b1b6080c
--- /dev/null
+++ b/spec/frontend/toggles/index_spec.js
@@ -0,0 +1,149 @@
+import { createWrapper } from '@vue/test-utils';
+import { GlToggle } from '@gitlab/ui';
+import { initToggle } from '~/toggles';
+
+// Selectors
+const TOGGLE_WRAPPER_CLASS = '.gl-toggle-wrapper';
+const TOGGLE_LABEL_CLASS = '.gl-toggle-label';
+const CHECKED_CLASS = '.is-checked';
+const DISABLED_CLASS = '.is-disabled';
+const LOADING_CLASS = '.toggle-loading';
+const HELP_TEXT_SELECTOR = '[data-testid="toggle-help"]';
+
+// Toggle settings
+const toggleClassName = 'js-custom-toggle-class';
+const toggleLabel = 'Toggle label';
+
+describe('toggles/index.js', () => {
+ let instance;
+ let toggleWrapper;
+
+ const createRootEl = (dataAttrs) => {
+ const dataset = {
+ label: toggleLabel,
+ ...dataAttrs,
+ };
+ const el = document.createElement('span');
+ el.classList.add(toggleClassName);
+
+ Object.entries(dataset).forEach(([key, value]) => {
+ el.dataset[key] = value;
+ });
+
+ document.body.appendChild(el);
+
+ return el;
+ };
+
+ const initToggleWithOptions = (options = {}) => {
+ const el = createRootEl(options);
+ instance = initToggle(el);
+ toggleWrapper = document.querySelector(TOGGLE_WRAPPER_CLASS);
+ };
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ instance = null;
+ toggleWrapper = null;
+ });
+
+ describe('initToggle', () => {
+ describe('default state', () => {
+ beforeEach(() => {
+ initToggleWithOptions();
+ });
+
+ it('attaches a GlToggle to the element', async () => {
+ expect(toggleWrapper).not.toBe(null);
+ expect(toggleWrapper.querySelector(TOGGLE_LABEL_CLASS).textContent).toBe(toggleLabel);
+ });
+
+ it('passes CSS classes down to GlToggle', () => {
+ expect(toggleWrapper.className).toContain(toggleClassName);
+ });
+
+ it('is not checked', () => {
+ expect(toggleWrapper.querySelector(CHECKED_CLASS)).toBe(null);
+ });
+
+ it('is enabled', () => {
+ expect(toggleWrapper.querySelector(DISABLED_CLASS)).toBe(null);
+ });
+
+ it('is not loading', () => {
+ expect(toggleWrapper.querySelector(LOADING_CLASS)).toBe(null);
+ });
+
+ it('emits "change" event when value changes', () => {
+ const wrapper = createWrapper(instance);
+ const event = 'change';
+ const listener = jest.fn();
+
+ instance.$on(event, listener);
+
+ expect(listener).toHaveBeenCalledTimes(0);
+
+ wrapper.find(GlToggle).vm.$emit(event, true);
+
+ expect(listener).toHaveBeenCalledTimes(1);
+ expect(listener).toHaveBeenLastCalledWith(true);
+
+ wrapper.find(GlToggle).vm.$emit(event, false);
+
+ expect(listener).toHaveBeenCalledTimes(2);
+ expect(listener).toHaveBeenLastCalledWith(false);
+ });
+ });
+
+ describe('with custom options', () => {
+ const name = 'toggle-name';
+ const help = 'Help text';
+ const foo = 'bar';
+
+ beforeEach(() => {
+ initToggleWithOptions({
+ name,
+ isChecked: true,
+ disabled: true,
+ isLoading: true,
+ help,
+ labelPosition: 'hidden',
+ foo,
+ });
+ toggleWrapper = document.querySelector(TOGGLE_WRAPPER_CLASS);
+ });
+
+ it('sets the custom name', () => {
+ const input = toggleWrapper.querySelector('input[type="hidden"]');
+
+ expect(input.name).toBe(name);
+ });
+
+ it('is checked', () => {
+ expect(toggleWrapper.querySelector(CHECKED_CLASS)).not.toBe(null);
+ });
+
+ it('is disabled', () => {
+ expect(toggleWrapper.querySelector(DISABLED_CLASS)).not.toBe(null);
+ });
+
+ it('is loading', () => {
+ expect(toggleWrapper.querySelector(LOADING_CLASS)).not.toBe(null);
+ });
+
+ it('sets the custom help text', () => {
+ expect(toggleWrapper.querySelector(HELP_TEXT_SELECTOR).textContent).toBe(help);
+ });
+
+ it('hides the label', () => {
+ expect(
+ toggleWrapper.querySelector(TOGGLE_LABEL_CLASS).classList.contains('gl-sr-only'),
+ ).toBe(true);
+ });
+
+ it('passes custom dataset to the wrapper', () => {
+ expect(toggleWrapper.dataset.foo).toBe('bar');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/token_access/token_access_spec.js b/spec/frontend/token_access/token_access_spec.js
index c4e29a52f1c..5aaeebd5af4 100644
--- a/spec/frontend/token_access/token_access_spec.js
+++ b/spec/frontend/token_access/token_access_spec.js
@@ -1,5 +1,5 @@
import { GlToggle, GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -22,9 +22,8 @@ import {
const projectPath = 'root/my-repo';
const error = new Error('Error');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
jest.mock('~/flash');
@@ -52,7 +51,6 @@ describe('TokenAccess component', () => {
const createComponent = (requestHandlers, mountFn = shallowMountExtended) => {
wrapper = mountFn(TokenAccess, {
- localVue,
provide: {
fullPath: projectPath,
},
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index 9b703b74a1a..eef352a72ff 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -1,5 +1,6 @@
import { GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Tooltips from '~/tooltips/components/tooltips.vue';
@@ -46,7 +47,7 @@ describe('tooltips/components/tooltips.vue', () => {
it('attaches tooltips to the targets specified', async () => {
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).props('target')).toBe(target);
});
@@ -56,7 +57,7 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).exists()).toBe(false);
});
@@ -65,7 +66,7 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.vm.addTooltips([target]);
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAll(GlTooltip)).toHaveLength(1);
});
@@ -73,7 +74,7 @@ describe('tooltips/components/tooltips.vue', () => {
it('sets tooltip content from title attribute', async () => {
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).text()).toBe(target.getAttribute('title'));
});
@@ -85,7 +86,7 @@ describe('tooltips/components/tooltips.vue', () => {
});
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title'));
});
@@ -94,7 +95,7 @@ describe('tooltips/components/tooltips.vue', () => {
const config = { show: true };
target = createTooltipTarget();
wrapper.vm.addTooltips([target], config);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).props()).toMatchObject(config);
});
@@ -110,7 +111,7 @@ describe('tooltips/components/tooltips.vue', () => {
target = createTooltipTarget({ [attribute]: value });
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).props(prop)).toBe(value);
},
@@ -124,10 +125,10 @@ describe('tooltips/components/tooltips.vue', () => {
it('removes all tooltips when elements is nil', async () => {
wrapper.vm.addTooltips([createTooltipTarget(), createTooltipTarget()]);
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.vm.dispose();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allTooltips()).toHaveLength(0);
});
@@ -136,10 +137,10 @@ describe('tooltips/components/tooltips.vue', () => {
const target = createTooltipTarget();
wrapper.vm.addTooltips([target, createTooltipTarget()]);
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.vm.dispose(target);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allTooltips()).toHaveLength(1);
});
@@ -154,13 +155,13 @@ describe('tooltips/components/tooltips.vue', () => {
const target = createTooltipTarget();
wrapper.vm.addTooltips([target, createTooltipTarget()]);
- await wrapper.vm.$nextTick();
+ await nextTick();
triggerMutate(document.body, {
entry: { removedNodes: [target] },
options: { childList: true },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(allTooltips()).toHaveLength(1);
});
@@ -175,7 +176,7 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.vm.triggerEvent(target, event);
@@ -195,14 +196,14 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.vm.addTooltips([target]);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).text()).toBe(currentTitle);
target.setAttribute('title', newTitle);
wrapper.vm.fixTitle(target);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlTooltip).text()).toBe(newTitle);
});
@@ -225,7 +226,7 @@ describe('tooltips/components/tooltips.vue', () => {
buildWrapper();
wrapper.vm.addTooltips([createTooltipTarget()]);
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.findComponent(GlTooltip).vm.$emit('hidden');
expect(wrapper.emitted('hidden')).toHaveLength(1);
diff --git a/spec/frontend/tooltips/index_spec.js b/spec/frontend/tooltips/index_spec.js
index 9c03ca8f4c9..198a0315ef7 100644
--- a/spec/frontend/tooltips/index_spec.js
+++ b/spec/frontend/tooltips/index_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import {
add,
initTooltips,
@@ -57,7 +58,7 @@ describe('tooltips/index.js', () => {
triggerEvent(target);
- await tooltipsApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
@@ -69,7 +70,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
triggerEvent(target, 'click');
- await tooltipsApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
@@ -83,7 +84,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
add([target], { title: 'custom title' });
- await tooltipsApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('custom title');
@@ -97,13 +98,13 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
triggerEvent(target);
- await tooltipsApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
dispose([target]);
- await tooltipsApp.$nextTick();
+ await nextTick();
expect(document.querySelector('.gl-tooltip')).toBe(null);
});
@@ -122,7 +123,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
- await tooltipsApp.$nextTick();
+ await nextTick();
jest.spyOn(tooltipsApp, 'triggerEvent');
@@ -137,7 +138,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
- await tooltipsApp.$nextTick();
+ await nextTick();
jest.spyOn(tooltipsApp, 'fixTitle');
diff --git a/spec/frontend/user_lists/components/add_user_modal_spec.js b/spec/frontend/user_lists/components/add_user_modal_spec.js
index c9ad40ed228..cd04836a8c4 100644
--- a/spec/frontend/user_lists/components/add_user_modal_spec.js
+++ b/spec/frontend/user_lists/components/add_user_modal_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import AddUserModal from '~/user_lists/components/add_user_modal.vue';
describe('Add User Modal', () => {
@@ -30,7 +31,7 @@ describe('Add User Modal', () => {
it('should clear the input after emitting', async () => {
click('confirm-add-user-ids');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('#add-user-ids').element.value).toBe('');
});
@@ -42,7 +43,7 @@ describe('Add User Modal', () => {
it('should clear the input after cancelling', async () => {
click('cancel-add-user-ids');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('#add-user-ids').element.value).toBe('');
});
diff --git a/spec/frontend/user_lists/components/edit_user_list_spec.js b/spec/frontend/user_lists/components/edit_user_list_spec.js
index bd71a677a24..7cafe5e1f56 100644
--- a/spec/frontend/user_lists/components/edit_user_list_spec.js
+++ b/spec/frontend/user_lists/components/edit_user_list_spec.js
@@ -1,6 +1,6 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
@@ -13,8 +13,7 @@ import { userList } from '../../feature_flags/mock_data';
jest.mock('~/api');
jest.mock('~/lib/utils/url_utility');
-const localVue = createLocalVue(Vue);
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('user_lists/components/edit_user_list', () => {
let wrapper;
@@ -30,7 +29,6 @@ describe('user_lists/components/edit_user_list', () => {
destroy();
wrapper = mount(EditUserList, {
- localVue,
store: createStore({ projectId: '1', userListIid: '2' }),
provide: {
userListsDocsPath: '/docs/user_lists',
@@ -79,11 +77,11 @@ describe('user_lists/components/edit_user_list', () => {
});
describe('update', () => {
- beforeEach(() => {
+ beforeEach(async () => {
Api.fetchFeatureFlagUserList.mockResolvedValue({ data: userList });
factory();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('should link to the documentation', () => {
@@ -101,11 +99,11 @@ describe('user_lists/components/edit_user_list', () => {
});
describe('success', () => {
- beforeEach(() => {
+ beforeEach(async () => {
Api.updateFeatureFlagUserList.mockResolvedValue({ data: userList });
setInputValue('test');
clickSave();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('should create a user list with the entered name', () => {
@@ -141,7 +139,7 @@ describe('user_lists/components/edit_user_list', () => {
it('should dismiss the error if dismiss is clicked', async () => {
alert.find('button').trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(alert.exists()).toBe(false);
});
diff --git a/spec/frontend/user_lists/components/new_user_list_spec.js b/spec/frontend/user_lists/components/new_user_list_spec.js
index a81e8912714..5eb44970fe4 100644
--- a/spec/frontend/user_lists/components/new_user_list_spec.js
+++ b/spec/frontend/user_lists/components/new_user_list_spec.js
@@ -1,6 +1,6 @@
import { GlAlert } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
@@ -12,8 +12,7 @@ import { userList } from '../../feature_flags/mock_data';
jest.mock('~/api');
jest.mock('~/lib/utils/url_utility');
-const localVue = createLocalVue(Vue);
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('user_lists/components/new_user_list', () => {
let wrapper;
@@ -24,7 +23,6 @@ describe('user_lists/components/new_user_list', () => {
beforeEach(() => {
wrapper = mount(NewUserList, {
- localVue,
store: createStore({ projectId: '1' }),
provide: {
featureFlagsPath: '/feature_flags',
@@ -45,11 +43,11 @@ describe('user_lists/components/new_user_list', () => {
describe('create', () => {
describe('success', () => {
- beforeEach(() => {
+ beforeEach(async () => {
Api.createFeatureFlagUserList.mockResolvedValue({ data: userList });
setInputValue('test');
click('save-user-list');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('should create a user list with the entered name', () => {
@@ -84,7 +82,7 @@ describe('user_lists/components/new_user_list', () => {
it('should dismiss the error when the dismiss button is clicked', async () => {
alert.find('button').trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(alert.exists()).toBe(false);
});
diff --git a/spec/frontend/user_lists/components/user_list_spec.js b/spec/frontend/user_lists/components/user_list_spec.js
index f016b5091d9..88dad06938b 100644
--- a/spec/frontend/user_lists/components/user_list_spec.js
+++ b/spec/frontend/user_lists/components/user_list_spec.js
@@ -1,7 +1,7 @@
import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { uniq } from 'lodash';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Api from '~/api';
import UserList from '~/user_lists/components/user_list.vue';
@@ -57,12 +57,12 @@ describe('User List', () => {
describe('success', () => {
let userIds;
- beforeEach(() => {
+ beforeEach(async () => {
userIds = parseUserIds(userList.user_xids);
Api.fetchFeatureFlagUserList.mockResolvedValueOnce({ data: userList });
factory();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('requests the user list on mount', () => {
@@ -101,10 +101,10 @@ describe('User List', () => {
beforeEach(async () => {
Api.updateFeatureFlagUserList.mockResolvedValue(userList);
click('add-users');
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.find('#add-user-ids').setValue(`${stringifyUserIds(newIds)},`);
click('confirm-add-user-ids');
- await wrapper.vm.$nextTick();
+ await nextTick();
[[, { user_xids: receivedUserIds }]] = Api.updateFeatureFlagUserList.mock.calls;
parsedReceivedUserIds = parseUserIds(receivedUserIds);
});
@@ -140,7 +140,7 @@ describe('User List', () => {
beforeEach(async () => {
Api.updateFeatureFlagUserList.mockResolvedValue(userList);
click('delete-user-id');
- await wrapper.vm.$nextTick();
+ await nextTick();
[[, { user_xids: receivedUserIds }]] = Api.updateFeatureFlagUserList.mock.calls;
});
@@ -159,11 +159,11 @@ describe('User List', () => {
describe('error', () => {
const findAlert = () => wrapper.find(GlAlert);
- beforeEach(() => {
+ beforeEach(async () => {
Api.fetchFeatureFlagUserList.mockRejectedValue();
factory();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays the alert message', () => {
@@ -175,18 +175,18 @@ describe('User List', () => {
const alert = findAlert();
alert.find('button').trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(alert.exists()).toBe(false);
});
});
describe('empty list', () => {
- beforeEach(() => {
+ beforeEach(async () => {
Api.fetchFeatureFlagUserList.mockResolvedValueOnce({ data: { ...userList, user_xids: '' } });
factory();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('displays an empty state', () => {
diff --git a/spec/frontend/user_lists/components/user_lists_spec.js b/spec/frontend/user_lists/components/user_lists_spec.js
index 7a33c6faac9..10742c029c1 100644
--- a/spec/frontend/user_lists/components/user_lists_spec.js
+++ b/spec/frontend/user_lists/components/user_lists_spec.js
@@ -1,7 +1,7 @@
import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { within } from '@testing-library/dom';
import { mount, createWrapper } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
@@ -82,7 +82,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
factory();
await waitForPromises();
- await Vue.nextTick();
+ await nextTick();
emptyState = wrapper.findComponent(GlEmptyState);
});
@@ -130,7 +130,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
factory();
jest.spyOn(store, 'dispatch');
- await Vue.nextTick();
+ await nextTick();
table = wrapper.findComponent(UserListsTable);
});
@@ -171,7 +171,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
Api.fetchFeatureFlagUserLists.mockRejectedValue();
factory();
- await Vue.nextTick();
+ await nextTick();
});
it('should render error state', () => {
diff --git a/spec/frontend/user_lists/components/user_lists_table_spec.js b/spec/frontend/user_lists/components/user_lists_table_spec.js
index 7f4d510a39c..63587703392 100644
--- a/spec/frontend/user_lists/components/user_lists_table_spec.js
+++ b/spec/frontend/user_lists/components/user_lists_table_spec.js
@@ -1,6 +1,7 @@
import { GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import * as timeago from 'timeago.js';
+import { nextTick } from 'vue';
import UserListsTable from '~/user_lists/components/user_lists_table.vue';
import { userList } from '../../feature_flags/mock_data';
@@ -56,43 +57,40 @@ describe('User Lists Table', () => {
});
describe('delete button', () => {
- it('should display the confirmation modal', () => {
+ it('should display the confirmation modal', async () => {
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.`);
- });
+ await nextTick();
+ expect(modal.text()).toContain(`Delete ${userList.name}?`);
+ expect(modal.text()).toContain(`User list ${userList.name} will be removed.`);
});
});
describe('confirmation modal', () => {
let modal;
- beforeEach(() => {
+ beforeEach(async () => {
modal = wrapper.find(GlModal);
wrapper.find('button').trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('should emit delete with list on confirmation', () => {
+ it('should emit delete with list on confirmation', async () => {
modal.find('[data-testid="modal-confirm"]').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]);
- });
+ await nextTick();
+ expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]);
});
- it('should not emit delete with list when not confirmed', () => {
+ it('should not emit delete with list when not confirmed', async () => {
modal.find('button').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('delete')).toBeUndefined();
- });
+ await nextTick();
+ expect(wrapper.emitted('delete')).toBeUndefined();
});
});
});
diff --git a/spec/frontend/vue_alerts_spec.js b/spec/frontend/vue_alerts_spec.js
index 30be606292f..1952eea4a01 100644
--- a/spec/frontend/vue_alerts_spec.js
+++ b/spec/frontend/vue_alerts_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import { nextTick } from 'vue';
import { setHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import initVueAlerts from '~/vue_alerts';
@@ -75,10 +75,9 @@ describe('VueAlerts', () => {
});
describe('when dismissed', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findAlertDismiss(findAlerts()[0]).click();
-
- return Vue.nextTick();
+ await nextTick();
});
it('hides the alert', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js b/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js
index 1aeb080aa04..82526af7afa 100644
--- a/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import MrCollapsibleSection from '~/vue_merge_request_widget/components/mr_collapsible_extension.vue';
describe('Merge Request Collapsible Extension', () => {
@@ -46,9 +47,9 @@ describe('Merge Request Collapsible Extension', () => {
});
describe('onClick', () => {
- beforeEach(() => {
+ beforeEach(async () => {
wrapper.find('button').trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('rendes the provided slot', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js
index e7c10ab4c2d..8a42e2e2ce7 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import MrWidgetAuthor from '~/vue_merge_request_widget/components/mr_widget_author.vue';
window.gl = window.gl || {};
@@ -50,7 +51,7 @@ describe('MrWidgetAuthor', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('img').attributes('src')).toBe('no_avatar.png');
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
index 3e111cd308a..631aef412a6 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlCollapse, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import MrCollapsibleSection from '~/vue_merge_request_widget/components/mr_widget_expandable_section.vue';
describe('MrWidgetExpanableSection', () => {
@@ -43,9 +44,9 @@ describe('MrWidgetExpanableSection', () => {
});
describe('when collapse section is open', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findButton().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders button with collapse text', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js
index f55d313a719..c0a30a5093d 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js
@@ -1,6 +1,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
@@ -152,23 +153,18 @@ describe('MemoryUsage', () => {
});
describe('loadMetrics', () => {
- const returnServicePromise = () =>
- new Promise((resolve) => {
- resolve({
- data: metricsMockData,
- });
+ it('should load metrics data using MRWidgetService', async () => {
+ jest.spyOn(MRWidgetService, 'fetchMetrics').mockResolvedValue({
+ data: metricsMockData,
});
-
- it('should load metrics data using MRWidgetService', (done) => {
- jest.spyOn(MRWidgetService, 'fetchMetrics').mockReturnValue(returnServicePromise(true));
jest.spyOn(vm, 'computeGraphData').mockImplementation(() => {});
vm.loadMetrics();
- setImmediate(() => {
- expect(MRWidgetService.fetchMetrics).toHaveBeenCalledWith(url);
- expect(vm.computeGraphData).toHaveBeenCalledWith(metrics, deployment_time);
- done();
- });
+
+ await waitForPromises();
+
+ expect(MRWidgetService.fetchMetrics).toHaveBeenCalledWith(url);
+ expect(vm.computeGraphData).toHaveBeenCalledWith(metrics, deployment_time);
});
});
});
@@ -184,7 +180,7 @@ describe('MemoryUsage', () => {
vm.hasMetrics = false;
vm.loadFailed = false;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined();
expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined();
@@ -203,7 +199,7 @@ describe('MemoryUsage', () => {
vm.loadFailed = false;
vm.memoryMetrics = metricsMockData.metrics.memory_values[0].values;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(el.querySelector('.memory-graph-container')).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics);
done();
@@ -215,7 +211,7 @@ describe('MemoryUsage', () => {
vm.hasMetrics = false;
vm.loadFailed = true;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed);
@@ -228,7 +224,7 @@ describe('MemoryUsage', () => {
vm.hasMetrics = false;
vm.loadFailed = false;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable);
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
index a124008b36a..98297630792 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
@@ -16,7 +16,7 @@ exports[`PipelineFailed should render error message with a disabled merge button
class="bold"
>
<gl-sprintf-stub
- message="The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
+ message="Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
/>
</span>
</div>
diff --git a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
index c30f6f1dfd1..c0add94e6ed 100644
--- a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
const testCommitMessage = 'Test commit message';
@@ -46,16 +47,15 @@ describe('Commits edit component', () => {
expect(findTextarea().element.value).toBe(testCommitMessage);
});
- it('emits an input event and receives changed value', () => {
+ it('emits an input event and receives changed value', async () => {
const changedCommitMessage = 'Changed commit message';
findTextarea().element.value = changedCommitMessage;
findTextarea().trigger('input');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().input[0]).toEqual([changedCommitMessage]);
- expect(findTextarea().element.value).toBe(changedCommitMessage);
- });
+ await nextTick();
+ expect(wrapper.emitted().input[0]).toEqual([changedCommitMessage]);
+ expect(findTextarea().element.value).toBe(changedCommitMessage);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js b/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
new file mode 100644
index 00000000000..0e1c38437f0
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
@@ -0,0 +1,78 @@
+import { shallowMount } from '@vue/test-utils';
+import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
+import { trimText } from 'helpers/text_helper';
+
+describe('MergeFailedPipelineConfirmationDialog', () => {
+ let wrapper;
+
+ const GlModal = {
+ template: `
+ <div>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>
+ `,
+ methods: {
+ hide: jest.fn(),
+ },
+ };
+
+ const createComponent = () => {
+ wrapper = shallowMount(MergeFailedPipelineConfirmationDialog, {
+ propsData: {
+ visible: true,
+ },
+ stubs: {
+ GlModal,
+ },
+ attachTo: document.body,
+ });
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findMergeBtn = () => wrapper.find('[data-testid="merge-unverified-changes"]');
+ const findCancelBtn = () => wrapper.find('[data-testid="merge-cancel-btn"]');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render informational text explaining why merging immediately can be dangerous', () => {
+ expect(trimText(wrapper.text())).toContain(
+ 'The latest pipeline for this merge request did not succeed. The latest changes are unverified. Are you sure you want to attempt to merge?',
+ );
+ });
+
+ it('should emit the mergeWithFailedPipeline event', () => {
+ findMergeBtn().vm.$emit('click');
+
+ expect(wrapper.emitted('mergeWithFailedPipeline')).toBeTruthy();
+ });
+
+ it('when the cancel button is clicked should emit cancel and call hide', () => {
+ jest.spyOn(findModal().vm, 'hide');
+
+ findCancelBtn().vm.$emit('click');
+
+ expect(wrapper.emitted('cancel')).toBeTruthy();
+ expect(findModal().vm.hide).toHaveBeenCalled();
+ });
+
+ it('should emit cancel when the hide event is emitted', () => {
+ findModal().vm.$emit('hide');
+
+ expect(wrapper.emitted('cancel')).toBeTruthy();
+ });
+
+ it('when modal is shown it will focus the cancel button', () => {
+ jest.spyOn(findCancelBtn().element, 'focus');
+
+ findModal().vm.$emit('shown');
+
+ expect(findCancelBtn().element.focus).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
index 52a56af454f..7387ed2d5e9 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -185,7 +186,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
describe('methods', () => {
describe('cancelAutomaticMerge', () => {
- it('should set flag and call service then tell main component to update the widget with data', (done) => {
+ it('should set flag and call service then tell main component to update the widget with data', async () => {
factory({
...defaultMrProps(),
});
@@ -201,20 +202,20 @@ describe('MRWidgetAutoMergeEnabled', () => {
);
wrapper.vm.cancelAutomaticMerge();
- setImmediate(() => {
- expect(wrapper.vm.isCancellingAutoMerge).toBeTruthy();
- if (mergeRequestWidgetGraphql) {
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- } else {
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- }
- done();
- });
+
+ await waitForPromises();
+
+ expect(wrapper.vm.isCancellingAutoMerge).toBeTruthy();
+ if (mergeRequestWidgetGraphql) {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ } else {
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ }
});
});
describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', (done) => {
+ it('should set flag and call service then request main component to update the widget', async () => {
factory({
...defaultMrProps(),
});
@@ -227,14 +228,14 @@ describe('MRWidgetAutoMergeEnabled', () => {
);
wrapper.vm.removeSourceBranch();
- setImmediate(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(wrapper.vm.service.merge).toHaveBeenCalledWith({
- sha,
- auto_merge_strategy: MWPS_MERGE_STRATEGY,
- should_remove_source_branch: true,
- });
- done();
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(wrapper.vm.service.merge).toHaveBeenCalledWith({
+ sha,
+ auto_merge_strategy: MWPS_MERGE_STRATEGY,
+ should_remove_source_branch: true,
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
index 4c763f40cbe..663fabb761c 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
@@ -1,5 +1,6 @@
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
const commits = [
@@ -51,11 +52,10 @@ describe('Commits message dropdown component', () => {
expect(findFirstDropdownElement().text()).toContain('Commit 1');
});
- it('should emit a commit title on selecting commit', () => {
+ it('should emit a commit title on selecting commit', async () => {
findFirstDropdownElement().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().input[0]).toEqual(['Update test.txt']);
- });
+ await nextTick();
+ expect(wrapper.emitted().input[0]).toEqual(['Update test.txt']);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
index 4d05e732f48..2796403b7d0 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+import { nextTick } from 'vue';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
describe('Commits header component', () => {
@@ -58,15 +59,14 @@ describe('Commits header component', () => {
expect(findCommitToggle().attributes('aria-label')).toBe('Expand');
});
- it('has a chevron-right icon', () => {
+ it('has a chevron-right icon', async () => {
createComponent();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ expanded: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(findCommitToggle().props('icon')).toBe('chevron-right');
- });
+ await nextTick();
+ expect(findCommitToggle().props('icon')).toBe('chevron-right');
});
describe('when squash is disabled', () => {
@@ -118,25 +118,19 @@ describe('Commits header component', () => {
wrapper.setData({ expanded: true });
});
- it('toggle has aria-label equal to collapse', (done) => {
- wrapper.vm.$nextTick(() => {
- expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
- done();
- });
+ it('toggle has aria-label equal to collapse', async () => {
+ await nextTick();
+ expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
});
- it('has a chevron-down icon', (done) => {
- wrapper.vm.$nextTick(() => {
- expect(findCommitToggle().props('icon')).toBe('chevron-down');
- done();
- });
+ it('has a chevron-down icon', async () => {
+ await nextTick();
+ expect(findCommitToggle().props('icon')).toBe('chevron-down');
});
- it('has a collapse text', (done) => {
- wrapper.vm.$nextTick(() => {
- expect(findHeaderWrapper().text()).toBe('Collapse');
- done();
- });
+ it('has a collapse text', async () => {
+ await nextTick();
+ expect(findHeaderWrapper().text()).toBe('Collapse');
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index ec222e66a97..9dcde3e4f33 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { removeBreakLine } from 'helpers/text_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -20,7 +21,7 @@ describe('MRWidgetConflicts', () => {
const resolveConflictsBtnText = 'Resolve conflicts';
const mergeLocallyBtnText = 'Merge locally';
- function createComponent(propsData = {}) {
+ async function createComponent(propsData = {}) {
wrapper = extendedWrapper(
shallowMount(ConflictsComponent, {
propsData,
@@ -55,7 +56,7 @@ describe('MRWidgetConflicts', () => {
});
}
- return wrapper.vm.$nextTick();
+ await nextTick();
}
afterEach(() => {
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 e0f1f091129..7d86e453bc7 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
@@ -1,6 +1,7 @@
import { getByRole } from '@testing-library/dom';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
import modalEventHub from '~/projects/commit/event_hub';
import mergedComponent from '~/vue_merge_request_widget/components/states/mr_widget_merged.vue';
@@ -127,7 +128,7 @@ describe('MRWidgetMerged', () => {
describe('methods', () => {
describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', (done) => {
+ it('should set flag and call service then request main component to update the widget', async () => {
jest.spyOn(vm.service, 'removeSourceBranch').mockReturnValue(
new Promise((resolve) => {
resolve({
@@ -139,14 +140,14 @@ describe('MRWidgetMerged', () => {
);
vm.removeSourceBranch();
- setImmediate(() => {
- const args = eventHub.$emit.mock.calls[0];
-
- expect(vm.isMakingRequest).toEqual(true);
- expect(args[0]).toEqual('MRWidgetUpdateRequested');
- expect(args[1]).not.toThrow();
- done();
- });
+
+ await waitForPromises();
+
+ const args = eventHub.$emit.mock.calls[0];
+
+ expect(vm.isMakingRequest).toEqual(true);
+ expect(args[0]).toEqual('MRWidgetUpdateRequested');
+ expect(args[1]).not.toThrow();
});
});
});
@@ -200,7 +201,7 @@ describe('MRWidgetMerged', () => {
it('hides button to copy commit SHA if SHA does not exist', (done) => {
vm.mr.mergeCommitSha = null;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(selectors.copyMergeShaButton).toBe(null);
expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
done();
@@ -216,7 +217,7 @@ describe('MRWidgetMerged', () => {
it('should not show source branch deleted text', (done) => {
vm.mr.sourceBranchRemoved = false;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
done();
});
@@ -226,7 +227,7 @@ describe('MRWidgetMerged', () => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.sourceBranchRemoved = false;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(vm.$el.innerText).toContain('The source branch is being deleted');
expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
done();
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
index e6b2e9fa176..e16c897a49b 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
@@ -1,6 +1,11 @@
import { shallowMount } from '@vue/test-utils';
+import simplePoll from '~/lib/utils/simple_poll';
import MrWidgetMerging from '~/vue_merge_request_widget/components/states/mr_widget_merging.vue';
+jest.mock('~/lib/utils/simple_poll', () =>
+ jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
+);
+
describe('MRWidgetMerging', () => {
let wrapper;
@@ -11,6 +16,10 @@ describe('MRWidgetMerging', () => {
mr: {
targetBranchPath: '/branch-path',
targetBranch: 'branch',
+ transitionStateMachine() {},
+ },
+ service: {
+ poll: jest.fn().mockResolvedValue(),
},
},
stubs: {
@@ -46,4 +55,20 @@ describe('MRWidgetMerging', () => {
expect(wrapper.find('a').attributes('href')).toBe('/branch-path');
});
+
+ describe('initiateMergePolling', () => {
+ it('should call simplePoll', () => {
+ wrapper.vm.initiateMergePolling();
+
+ expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 });
+ });
+
+ it('should call handleMergePolling', () => {
+ jest.spyOn(wrapper.vm, 'handleMergePolling').mockImplementation(() => {});
+
+ wrapper.vm.initiateMergePolling();
+
+ expect(wrapper.vm.handleMergePolling).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
index 936d673768c..ddce07954ab 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
@@ -1,9 +1,10 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import MissingBranchComponent from '~/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue';
let wrapper;
-function factory(sourceBranchRemoved, mergeRequestWidgetGraphql) {
+async function factory(sourceBranchRemoved, mergeRequestWidgetGraphql) {
wrapper = shallowMount(MissingBranchComponent, {
propsData: {
mr: { sourceBranchRemoved },
@@ -19,7 +20,7 @@ function factory(sourceBranchRemoved, mergeRequestWidgetGraphql) {
wrapper.setData({ state: { sourceBranchExists: !sourceBranchRemoved } });
}
- return wrapper.vm.$nextTick();
+ await nextTick();
}
describe('MRWidgetMissingBranch', () => {
@@ -40,7 +41,7 @@ describe('MRWidgetMissingBranch', () => {
async ({ sourceBranchRemoved, branchName }) => {
await factory(sourceBranchRemoved, mergeRequestWidgetGraphql);
- expect(wrapper.find('[data-testid="missingBranchName"]').text()).toContain(branchName);
+ expect(wrapper.find('[data-testid="widget-content"]').text()).toContain(branchName);
},
);
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
index 2c04905d3a9..c7c0b69425d 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import NothingToMerge from '~/vue_merge_request_widget/components/states/nothing_to_merge.vue';
describe('NothingToMerge', () => {
@@ -20,7 +20,7 @@ describe('NothingToMerge', () => {
it('should not show new blob link if there is no link available', () => {
vm.mr.newBlobPath = null;
- Vue.nextTick(() => {
+ nextTick(() => {
expect(vm.$el.querySelector('[data-testid="createFileButton"]')).toEqual(null);
});
});
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 f4ecebbb40c..78585ed75bc 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
@@ -1,12 +1,14 @@
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import { GlSprintf } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
import simplePoll from '~/lib/utils/simple_poll';
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
+import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -61,6 +63,11 @@ const createTestService = () => ({
});
let wrapper;
+
+const findMergeButton = () => wrapper.find('[data-testid="merge-button"]');
+const findPipelineFailedConfirmModal = () =>
+ wrapper.findComponent(MergeFailedPipelineConfirmationDialog);
+
const createComponent = (customConfig = {}, mergeRequestWidgetGraphql = false) => {
wrapper = shallowMount(ReadyToMerge, {
propsData: {
@@ -132,33 +139,13 @@ describe('ReadyToMerge', () => {
});
});
- describe('mergeButtonVariant', () => {
+ describe('Merge Button Variant', () => {
it('defaults to confirm class', () => {
createComponent({
mr: { availableAutoMergeStrategies: [] },
});
- expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
- });
-
- it('returns confirm class for success status', () => {
- createComponent({
- mr: { availableAutoMergeStrategies: [], pipeline: true },
- });
-
- expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
- });
-
- it('returns confirm class for pending status', () => {
- createComponent();
-
- expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
- });
-
- it('returns danger class for failed status', () => {
- createComponent({ mr: { hasCI: true } });
-
- expect(wrapper.vm.mergeButtonVariant).toEqual('danger');
+ expect(findMergeButton().attributes('variant')).toBe('confirm');
});
});
@@ -196,7 +183,7 @@ describe('ReadyToMerge', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isMergingImmediately: true });
- await Vue.nextTick();
+ await nextTick();
expect(wrapper.vm.mergeButtonText).toEqual('Merge in progress');
});
@@ -266,7 +253,7 @@ describe('ReadyToMerge', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isMakingRequest: true });
- await Vue.nextTick();
+ await nextTick();
expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
});
@@ -275,110 +262,86 @@ describe('ReadyToMerge', () => {
describe('methods', () => {
describe('handleMergeButtonClick', () => {
- const returnPromise = (status) =>
- new Promise((resolve) => {
- resolve({
- data: {
- status,
- },
- });
- });
+ const response = (status) => ({
+ data: {
+ status,
+ },
+ });
- it('should handle merge when pipeline succeeds', (done) => {
+ it('should handle merge when pipeline succeeds', async () => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest
.spyOn(wrapper.vm.service, 'merge')
- .mockReturnValue(returnPromise('merge_when_pipeline_succeeds'));
+ .mockResolvedValue(response('merge_when_pipeline_succeeds'));
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ removeSourceBranch: false });
wrapper.vm.handleMergeButtonClick(true);
- setImmediate(() => {
- expect(wrapper.vm.isMakingRequest).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
- transition: 'start-auto-merge',
- });
+ await waitForPromises();
- const params = wrapper.vm.service.merge.mock.calls[0][0];
-
- expect(params).toEqual(
- expect.objectContaining({
- sha: wrapper.vm.mr.sha,
- commit_message: wrapper.vm.mr.commitMessage,
- should_remove_source_branch: false,
- auto_merge_strategy: 'merge_when_pipeline_succeeds',
- }),
- );
- done();
+ expect(wrapper.vm.isMakingRequest).toBeTruthy();
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
+ transition: 'start-auto-merge',
});
+
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
+
+ expect(params).toEqual(
+ expect.objectContaining({
+ sha: wrapper.vm.mr.sha,
+ commit_message: wrapper.vm.mr.commitMessage,
+ should_remove_source_branch: false,
+ auto_merge_strategy: 'merge_when_pipeline_succeeds',
+ }),
+ );
});
- it('should handle merge failed', (done) => {
+ it('should handle merge failed', async () => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(returnPromise('failed'));
+ jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('failed'));
wrapper.vm.handleMergeButtonClick(false, true);
- setImmediate(() => {
- expect(wrapper.vm.isMakingRequest).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
+ await waitForPromises();
- const params = wrapper.vm.service.merge.mock.calls[0][0];
+ expect(wrapper.vm.isMakingRequest).toBeTruthy();
+ expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
- expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.auto_merge_strategy).toBeUndefined();
- done();
- });
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
+
+ expect(params.should_remove_source_branch).toBeTruthy();
+ expect(params.auto_merge_strategy).toBeUndefined();
});
- it('should handle merge action accepted case', (done) => {
+ it('should handle merge action accepted case', async () => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(returnPromise('success'));
- jest.spyOn(wrapper.vm, 'initiateMergePolling').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('success'));
+ jest.spyOn(wrapper.vm.mr, 'transitionStateMachine');
wrapper.vm.handleMergeButtonClick();
expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
transition: 'start-merge',
});
- setImmediate(() => {
- expect(wrapper.vm.isMakingRequest).toBeTruthy();
- expect(wrapper.vm.initiateMergePolling).toHaveBeenCalled();
-
- const params = wrapper.vm.service.merge.mock.calls[0][0];
+ await waitForPromises();
- expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.auto_merge_strategy).toBeUndefined();
- done();
+ expect(wrapper.vm.isMakingRequest).toBeTruthy();
+ expect(wrapper.vm.mr.transitionStateMachine).toHaveBeenCalledWith({
+ transition: 'start-merge',
});
- });
- });
-
- describe('initiateMergePolling', () => {
- it('should call simplePoll', () => {
- createComponent();
-
- wrapper.vm.initiateMergePolling();
-
- expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 });
- });
- it('should call handleMergePolling', () => {
- createComponent();
-
- jest.spyOn(wrapper.vm, 'handleMergePolling').mockImplementation(() => {});
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
- wrapper.vm.initiateMergePolling();
-
- expect(wrapper.vm.handleMergePolling).toHaveBeenCalled();
+ expect(params.should_remove_source_branch).toBeTruthy();
+ expect(params.auto_merge_strategy).toBeUndefined();
});
});
@@ -396,20 +359,17 @@ describe('ReadyToMerge', () => {
});
describe('handleRemoveBranchPolling', () => {
- const returnPromise = (state) =>
- new Promise((resolve) => {
- resolve({
- data: {
- source_branch_exists: state,
- },
- });
- });
+ const response = (state) => ({
+ data: {
+ source_branch_exists: state,
+ },
+ });
- it('should call start and stop polling when MR merged', (done) => {
+ it('should call start and stop polling when MR merged', async () => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'poll').mockReturnValue(returnPromise(false));
+ jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(false));
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
@@ -422,28 +382,27 @@ describe('ReadyToMerge', () => {
spc = true;
},
);
- setImmediate(() => {
- expect(wrapper.vm.service.poll).toHaveBeenCalled();
- const args = eventHub.$emit.mock.calls[0];
+ await waitForPromises();
- expect(args[0]).toEqual('MRWidgetUpdateRequested');
- expect(args[1]).toBeDefined();
- args[1]();
+ expect(wrapper.vm.service.poll).toHaveBeenCalled();
- expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
+ const args = eventHub.$emit.mock.calls[0];
- expect(cpc).toBeFalsy();
- expect(spc).toBeTruthy();
+ expect(args[0]).toEqual('MRWidgetUpdateRequested');
+ expect(args[1]).toBeDefined();
+ args[1]();
- done();
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
+
+ expect(cpc).toBeFalsy();
+ expect(spc).toBeTruthy();
});
- it('should continue polling until MR is merged', (done) => {
+ it('should continue polling until MR is merged', async () => {
createComponent();
- jest.spyOn(wrapper.vm.service, 'poll').mockReturnValue(returnPromise(true));
+ jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(true));
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
@@ -456,12 +415,11 @@ describe('ReadyToMerge', () => {
spc = true;
},
);
- setImmediate(() => {
- expect(cpc).toBeTruthy();
- expect(spc).toBeFalsy();
- done();
- });
+ await waitForPromises();
+
+ expect(cpc).toBeTruthy();
+ expect(spc).toBeFalsy();
});
});
});
@@ -710,7 +668,7 @@ describe('ReadyToMerge', () => {
commitsWithoutMergeCommits: {},
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findCommitEditElements().length).toBe(2);
});
@@ -794,4 +752,24 @@ describe('ReadyToMerge', () => {
});
});
});
+
+ describe('Merge button when pipeline has failed', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
+ });
+ });
+
+ it('should display the correct merge text', () => {
+ expect(findMergeButton().text()).toBe('Merge...');
+ });
+
+ it('should display confirmation modal when merge button is clicked', async () => {
+ expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: false });
+
+ await findMergeButton().vm.$emit('click');
+
+ expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: true });
+ });
+ });
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
index 6abdbd11f5e..6ea2e8675d3 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
@@ -1,16 +1,13 @@
import { GlFormCheckbox, GlLink } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
import { SQUASH_BEFORE_MERGE } from '~/vue_merge_request_widget/i18n';
-const localVue = createLocalVue();
-
describe('Squash before merge component', () => {
let wrapper;
const createComponent = (props) => {
- wrapper = shallowMount(localVue.extend(SquashBeforeMerge), {
- localVue,
+ wrapper = shallowMount(SquashBeforeMerge, {
propsData: {
...props,
},
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 4070ca8d8dc..4998147c6b6 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,4 +1,5 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
import toast from '~/vue_shared/plugins/global_toast';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -47,7 +48,7 @@ describe('Wip', () => {
};
describe('handleRemoveDraft', () => {
- it('should make a request to service and handle response', (done) => {
+ it('should make a request to service and handle response', async () => {
const vm = createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
@@ -60,12 +61,12 @@ describe('Wip', () => {
);
vm.handleRemoveDraft();
- setImmediate(() => {
- expect(vm.isMakingRequest).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- expect(toast).toHaveBeenCalledWith('Marked as ready. Merging is now allowed.');
- done();
- });
+
+ await waitForPromises();
+
+ expect(vm.isMakingRequest).toBeTruthy();
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ expect(toast).toHaveBeenCalledWith('Marked as ready. Merging is now allowed.');
});
});
});
@@ -91,13 +92,12 @@ describe('Wip', () => {
);
});
- it('should not show removeWIP button is user cannot update MR', (done) => {
+ it('should not show removeWIP button is user cannot update MR', async () => {
vm.mr.removeWIPPath = '';
- Vue.nextTick(() => {
- expect(el.querySelector('.js-remove-draft')).toEqual(null);
- done();
- });
+ await nextTick();
+
+ expect(el.querySelector('.js-remove-draft')).toEqual(null);
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
index 9048975875a..b7c22b403aa 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
@@ -1,6 +1,7 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
import MrWidgetExpanableSection from '~/vue_merge_request_widget/components/mr_widget_expandable_section.vue';
@@ -39,15 +40,14 @@ describe('MrWidgetTerraformConainer', () => {
});
describe('when data is loading', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mockPollingApi(200, plans, {});
- return mountWrapper().then(() => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ loading: true });
- return wrapper.vm.$nextTick();
- });
+ await mountWrapper();
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ loading: true });
+ await nextTick();
});
it('diplays loading skeleton', () => {
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 31ade17e50a..a285d26f404 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,7 @@
import { mount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { visitUrl } from '~/lib/utils/url_utility';
import {
CREATED,
@@ -20,6 +22,11 @@ import {
jest.mock('~/flash');
jest.mock('~/lib/utils/url_utility');
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
+ return {
+ confirmAction: jest.fn(),
+ };
+});
describe('DeploymentAction component', () => {
let wrapper;
@@ -51,6 +58,7 @@ describe('DeploymentAction component', () => {
afterEach(() => {
wrapper.destroy();
+ confirmAction.mockReset();
});
describe('actions do not appear when conditions are unmet', () => {
@@ -95,16 +103,6 @@ describe('DeploymentAction component', () => {
'$configConst action',
({ configConst, computedDeploymentStatus, displayConditionChanges, finderFn, endpoint }) => {
describe(`${configConst} action`, () => {
- const confirmAction = () => {
- jest.spyOn(window, 'confirm').mockReturnValueOnce(true);
- finderFn().trigger('click');
- };
-
- const rejectAction = () => {
- jest.spyOn(window, 'confirm').mockReturnValueOnce(false);
- finderFn().trigger('click');
- };
-
beforeEach(() => {
factory({
propsData: {
@@ -125,13 +123,18 @@ describe('DeploymentAction component', () => {
describe('should show a confirm dialog but not call executeInlineAction when declined', () => {
beforeEach(() => {
executeActionSpy.mockResolvedValueOnce();
- rejectAction();
+ confirmAction.mockResolvedValueOnce(false);
+ finderFn().trigger('click');
});
it('should show the confirm dialog', () => {
- expect(window.confirm).toHaveBeenCalled();
- expect(window.confirm).toHaveBeenCalledWith(
+ expect(confirmAction).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalledWith(
actionButtonMocks[configConst].confirmMessage,
+ {
+ primaryBtnVariant: actionButtonMocks[configConst].buttonVariant,
+ primaryBtnText: actionButtonMocks[configConst].buttonText,
+ },
);
});
@@ -143,13 +146,18 @@ describe('DeploymentAction component', () => {
describe('should show a confirm dialog and call executeInlineAction when accepted', () => {
beforeEach(() => {
executeActionSpy.mockResolvedValueOnce();
- confirmAction();
+ confirmAction.mockResolvedValueOnce(true);
+ finderFn().trigger('click');
});
it('should show the confirm dialog', () => {
- expect(window.confirm).toHaveBeenCalled();
- expect(window.confirm).toHaveBeenCalledWith(
+ expect(confirmAction).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalledWith(
actionButtonMocks[configConst].confirmMessage,
+ {
+ primaryBtnVariant: actionButtonMocks[configConst].buttonVariant,
+ primaryBtnText: actionButtonMocks[configConst].buttonText,
+ },
);
});
@@ -164,11 +172,15 @@ describe('DeploymentAction component', () => {
describe('response includes redirect_url', () => {
const url = '/root/example';
- beforeEach(() => {
+ beforeEach(async () => {
executeActionSpy.mockResolvedValueOnce({
data: { redirect_url: url },
});
- confirmAction();
+
+ await waitForPromises();
+
+ confirmAction.mockResolvedValueOnce(true);
+ finderFn().trigger('click');
});
it('calls visit url with the redirect_url', () => {
@@ -178,9 +190,13 @@ describe('DeploymentAction component', () => {
});
describe('it should call the executeAction method ', () => {
- beforeEach(() => {
+ beforeEach(async () => {
jest.spyOn(wrapper.vm, 'executeAction').mockImplementation();
- confirmAction();
+
+ await waitForPromises();
+
+ confirmAction.mockResolvedValueOnce(true);
+ finderFn().trigger('click');
});
it('calls with the expected arguments', () => {
@@ -193,9 +209,13 @@ describe('DeploymentAction component', () => {
});
describe('when executeInlineAction errors', () => {
- beforeEach(() => {
+ beforeEach(async () => {
executeActionSpy.mockRejectedValueOnce();
- confirmAction();
+
+ await waitForPromises();
+
+ confirmAction.mockResolvedValueOnce(true);
+ finderFn().trigger('click');
});
it('should call createFlash with error message', () => {
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js b/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js
index 2083dc88681..e98b1160ae4 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js
@@ -9,6 +9,7 @@ const actionButtonMocks = {
[STOPPING]: {
actionName: STOPPING,
buttonText: 'Stop environment',
+ buttonVariant: 'danger',
busyText: 'This environment is being deployed',
confirmMessage: 'Are you sure you want to stop this environment?',
errorMessage: 'Something went wrong while stopping this environment. Please try again.',
@@ -16,6 +17,7 @@ const actionButtonMocks = {
[DEPLOYING]: {
actionName: DEPLOYING,
buttonText: 'Deploy',
+ buttonVariant: 'confirm',
busyText: 'This environment is being deployed',
confirmMessage: 'Are you sure you want to deploy this environment?',
errorMessage: 'Something went wrong while deploying this environment. Please try again.',
@@ -23,6 +25,7 @@ const actionButtonMocks = {
[REDEPLOYING]: {
actionName: REDEPLOYING,
buttonText: 'Re-deploy',
+ buttonVariant: 'confirm',
busyText: 'This environment is being re-deployed',
confirmMessage: 'Are you sure you want to re-deploy this environment?',
errorMessage: 'Something went wrong while deploying this environment. Please try again.',
diff --git a/spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js b/spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js
new file mode 100644
index 00000000000..a9fe29a484a
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js
@@ -0,0 +1,125 @@
+import MockAdapter from 'axios-mock-adapter';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { trimText } from 'helpers/text_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
+import extensionsContainer from '~/vue_merge_request_widget/components/extensions/container';
+import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
+import accessibilityExtension from '~/vue_merge_request_widget/extensions/accessibility';
+import httpStatusCodes from '~/lib/utils/http_status';
+import { accessibilityReportResponseErrors, accessibilityReportResponseSuccess } from './mock_data';
+
+describe('Accessibility extension', () => {
+ let wrapper;
+ let mock;
+
+ registerExtension(accessibilityExtension);
+
+ const endpoint = '/root/repo/-/merge_requests/4/accessibility_reports.json';
+
+ const mockApi = (statusCode, data) => {
+ mock.onGet(endpoint).reply(statusCode, data);
+ };
+
+ const findToggleCollapsedButton = () => wrapper.findByTestId('toggle-button');
+ const findAllExtensionListItems = () => wrapper.findAllByTestId('extension-list-item');
+
+ const createComponent = () => {
+ wrapper = mountExtended(extensionsContainer, {
+ propsData: {
+ mr: {
+ accessibilityReportPath: endpoint,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ describe('summary', () => {
+ it('displays loading text', () => {
+ mockApi(httpStatusCodes.OK, accessibilityReportResponseErrors);
+
+ createComponent();
+
+ expect(wrapper.text()).toBe('Accessibility scanning results are being parsed');
+ });
+
+ it('displays failed loading text', async () => {
+ mockApi(httpStatusCodes.INTERNAL_SERVER_ERROR);
+
+ createComponent();
+
+ await waitForPromises();
+
+ expect(wrapper.text()).toBe('Accessibility scanning failed loading results');
+ });
+
+ it('displays detected errors', async () => {
+ mockApi(httpStatusCodes.OK, accessibilityReportResponseErrors);
+
+ createComponent();
+
+ await waitForPromises();
+
+ expect(wrapper.text()).toBe(
+ 'Accessibility scanning detected 8 issues for the source branch only',
+ );
+ });
+
+ it('displays no detected errors', async () => {
+ mockApi(httpStatusCodes.OK, accessibilityReportResponseSuccess);
+
+ createComponent();
+
+ await waitForPromises();
+
+ expect(wrapper.text()).toBe(
+ 'Accessibility scanning detected no issues for the source branch only',
+ );
+ });
+ });
+
+ describe('expanded data', () => {
+ beforeEach(async () => {
+ mockApi(httpStatusCodes.OK, accessibilityReportResponseErrors);
+
+ createComponent();
+
+ await waitForPromises();
+
+ findToggleCollapsedButton().trigger('click');
+
+ await waitForPromises();
+ });
+
+ it('displays all report list items', async () => {
+ expect(findAllExtensionListItems()).toHaveLength(10);
+ });
+
+ it('displays report list item formatted', () => {
+ const text = {
+ newError: trimText(findAllExtensionListItems().at(0).text()),
+ resolvedError: findAllExtensionListItems().at(3).text(),
+ existingError: trimText(findAllExtensionListItems().at(8).text()),
+ };
+
+ expect(text.newError).toBe(
+ 'New The accessibility scanning found an error of the following type: WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1 Learn more Message: Iframe element requires a non-empty title attribute that identifies the frame.',
+ );
+ expect(text.resolvedError).toBe(
+ 'The accessibility scanning found an error of the following type: WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2 Learn more Message: Img element is the only content of the link, but is missing alt text. The alt text should describe the purpose of the link.',
+ );
+ expect(text.existingError).toBe(
+ 'The accessibility scanning found an error of the following type: WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1 Learn more Message: Iframe element requires a non-empty title attribute that identifies the frame.',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js b/spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js
new file mode 100644
index 00000000000..06dc93d101f
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js
@@ -0,0 +1,137 @@
+export const accessibilityReportResponseErrors = {
+ status: 'failed',
+ new_errors: [
+ {
+ code: 'WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1',
+ type: 'error',
+ type_code: 1,
+ message: 'Iframe element requires a non-empty title attribute that identifies the frame.',
+ context:
+ '<iframe height="0" width="0" style="display: none; visibility: hidden;" src="//10421980.fls.doubleclick.net/activityi;src=10421980;type=count0;cat=globa0;ord=6271888671448;gtm=2wg1c0;auiddc=40010797.1642181125;u1=undefined;u2=undefined;u3=undefined;u...',
+ selector: 'html > body > iframe:nth-child(42)',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.',
+ context:
+ '<form class="challenge-form" id="challenge-form" action="/users/sign_in?__cf_chl_jschl_tk__=xoagAHj9DXTTDveypAmMkakkNQgeWc6LmZA53YyDeSg-1642181129-0-gaNycGzNB1E" method="POST" enctype="application/x-www-form-urlencoded">\n <input type="hidden" name...',
+ selector: '#challenge-form',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1',
+ type: 'error',
+ type_code: 1,
+ message: 'Iframe element requires a non-empty title attribute that identifies the frame.',
+ context: '<iframe style="display: none;"></iframe>',
+ selector: 'html > body > iframe',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ ],
+ resolved_errors: [
+ {
+ code: 'WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1',
+ type: 'error',
+ type_code: 1,
+ message: 'Iframe element requires a non-empty title attribute that identifies the frame.',
+ context:
+ '<iframe height="0" width="0" style="display: none; visibility: hidden;" src="//10421980.fls.doubleclick.net/activityi;src=10421980;type=count0;cat=globa0;ord=6722452746146;gtm=2wg1a0;auiddc=716711306.1642082367;u1=undefined;u2=undefined;u3=undefined;...',
+ selector: 'html > body > iframe:nth-child(42)',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.',
+ context:
+ '<form class="challenge-form" id="challenge-form" action="/users/sign_in?__cf_chl_jschl_tk__=vDKZT2hjxWCstlWz2wtxsLdqLF79rM4IsoxzMgY6Lfw-1642082370-0-gaNycGzNB2U" method="POST" enctype="application/x-www-form-urlencoded">\n <input type="hidden" name...',
+ selector: '#challenge-form',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ ],
+ existing_errors: [
+ {
+ code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'Img element is the only content of the link, but is missing alt text. The alt text should describe the purpose of the link.',
+ context: '<a href="/" data-nav="logo">\n<img src="/images/icons/logos/...</a>',
+ selector: '#navigation-mobile > header > a',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H37',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.',
+ context: '<img src="/images/icons/slp-hamburger.svg" class="slp-inline-block slp-mr-8">',
+ selector: '#slpMobileNavActive > img',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H37',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.',
+ context: '<img src="/images/icons/slp-caret-down.svg">',
+ selector: '#navigation-mobile > div:nth-child(2) > div:nth-child(2) > button > div > img',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H37',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.',
+ context: '<img src="/images/icons/slp-caret-down.svg">',
+ selector: '#navigation-mobile > div:nth-child(2) > div:nth-child(3) > button > div > img',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ {
+ code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H37',
+ type: 'error',
+ type_code: 1,
+ message:
+ 'Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.',
+ context: '<img src="/images/icons/slp-caret-down.svg">',
+ selector: '#navigation-mobile > div:nth-child(2) > div:nth-child(4) > button > div > img',
+ runner: 'htmlcs',
+ runner_extras: {},
+ },
+ ],
+ summary: {
+ total: 8,
+ resolved: 2,
+ errored: 8,
+ },
+};
+
+export const accessibilityReportResponseSuccess = {
+ status: 'success',
+ new_errors: [],
+ resolved_errors: [],
+ existing_errors: [],
+ summary: {
+ total: 0,
+ resolved: 0,
+ errored: 0,
+ },
+};
diff --git a/spec/frontend/vue_shared/alert_details/alert_details_spec.js b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
index 221beed744b..7ee6e29e6de 100644
--- a/spec/frontend/vue_shared/alert_details/alert_details_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
@@ -2,6 +2,7 @@ import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { joinPaths } from '~/lib/utils/url_utility';
@@ -216,17 +217,16 @@ describe('AlertDetails', () => {
expect(findCreateIncidentBtn().exists()).toBe(false);
});
- it('should display "Create incident" button when incident doesn\'t exist yet', () => {
+ it('should display "Create incident" button when incident doesn\'t exist yet', async () => {
const issue = null;
mountComponent({
mountMethod: mount,
data: { alert: { ...mockAlert, issue } },
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findViewIncidentBtn().exists()).toBe(false);
- expect(findCreateIncidentBtn().exists()).toBe(true);
- });
+ await nextTick();
+ expect(findViewIncidentBtn().exists()).toBe(false);
+ expect(findCreateIncidentBtn().exists()).toBe(true);
});
it('calls `$apollo.mutate` with `createIssueQuery`', () => {
diff --git a/spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js b/spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js
index 87ad5e36564..12c5c190e26 100644
--- a/spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
import SidebarTodo from '~/vue_shared/alert_details/components/sidebar/sidebar_todo.vue';
import createAlertTodoMutation from '~/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql';
@@ -57,7 +58,7 @@ describe('Alert Details Sidebar To Do', () => {
});
it('renders a button for adding a To-Do', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findToDoButton().text()).toBe('Add a to do');
});
@@ -66,7 +67,7 @@ describe('Alert Details Sidebar To Do', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
findToDoButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: createAlertTodoMutation,
@@ -88,7 +89,7 @@ describe('Alert Details Sidebar To Do', () => {
});
it('renders a Mark As Done button when todo is present', async () => {
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findToDoButton().text()).toBe('Mark as done');
});
@@ -97,7 +98,7 @@ describe('Alert Details Sidebar To Do', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
findToDoButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: todoMarkDoneMutation,
diff --git a/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
index b5a61a4adc1..1216681038f 100644
--- a/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
import AlertMetrics from '~/vue_shared/alert_details/components/alert_metrics.vue';
@@ -53,7 +54,7 @@ describe('Alert Metrics', () => {
mountComponent({ props: { dashboardUrl: 'metrics.url' } });
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findEmptyState().exists()).toBe(false);
expect(findChart().exists()).toBe(true);
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 3fc13243bce..ba3b0335a8e 100644
--- a/spec/frontend/vue_shared/alert_details/alert_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
@@ -1,4 +1,5 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { nextTick } from 'vue';
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';
@@ -121,7 +122,7 @@ describe('AlertManagementStatus', () => {
it('emits an error when triggered a second time', async () => {
await selectFirstStatusOption();
- await wrapper.vm.$nextTick();
+ await nextTick();
await selectFirstStatusOption();
// Should emit two errors [0,1]
expect(wrapper.emitted('alert-error').length > 1).toBe(true);
@@ -175,17 +176,18 @@ describe('AlertManagementStatus', () => {
jest.spyOn(Tracking, 'event');
});
- it('should not track alert status updates when the tracking options do not exist', () => {
+ it('should not track alert status updates when the tracking options do not exist', async () => {
mountComponent({});
Tracking.event.mockClear();
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
findFirstStatusOption().vm.$emit('click');
- setImmediate(() => {
- expect(Tracking.event).not.toHaveBeenCalled();
- });
+
+ await nextTick();
+
+ expect(Tracking.event).not.toHaveBeenCalled();
});
- it('should track alert status updates when the tracking options exist', () => {
+ it('should track alert status updates when the tracking options exist', async () => {
const trackAlertStatusUpdateOptions = {
category: 'Alert Management',
action: 'update_alert_status',
@@ -195,11 +197,12 @@ describe('AlertManagementStatus', () => {
Tracking.event.mockClear();
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
findFirstStatusOption().vm.$emit('click');
+
+ await nextTick();
+
const status = findFirstStatusOption().text();
- setImmediate(() => {
- const { category, action, label } = trackAlertStatusUpdateOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property: status });
- });
+ const { category, action, label } = trackAlertStatusUpdateOptions;
+ expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property: status });
});
});
});
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 29e0eee2c9a..29569734621 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
@@ -1,6 +1,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SidebarAssignee from '~/vue_shared/alert_details/components/sidebar/sidebar_assignee.vue';
import SidebarAssignees from '~/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue';
@@ -112,7 +113,7 @@ describe('Alert Details Sidebar Assignees', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isDropdownSearching: false });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdown().text()).toBe('Unassigned');
});
@@ -126,7 +127,7 @@ describe('Alert Details Sidebar Assignees', () => {
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isDropdownSearching: false });
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
@@ -139,7 +140,7 @@ describe('Alert Details Sidebar Assignees', () => {
});
});
- it('emits an error when request contains error messages', () => {
+ it('emits an error when request contains error messages', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ isDropdownSearching: false });
@@ -153,15 +154,11 @@ describe('Alert Details Sidebar Assignees', () => {
};
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(errorMutationResult);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
- SideBarAssigneeItem.vm.$emit('update-alert-assignees');
- })
- .then(() => {
- expect(wrapper.emitted('alert-error')).toBeDefined();
- });
+
+ await nextTick();
+ const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
+ await SideBarAssigneeItem.vm.$emit('update-alert-assignees');
+ expect(wrapper.emitted('alert-error')).toBeDefined();
});
it('stops updating and cancels loading when the request fails', () => {
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 b00a20dab1a..a3adbcf8d3a 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,4 +1,5 @@
import { GlDropdown, GlLoadingIcon } from '@gitlab/ui';
+import { nextTick } from 'vue';
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';
@@ -75,7 +76,7 @@ describe('Alert Details Sidebar Status', () => {
loading: false,
});
findAlertStatus().vm.$emit('handle-updating', true);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findStatusLoadingIcon().exists()).toBe(true);
});
diff --git a/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap b/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
index 06753044e93..fbf3d17fd64 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
+++ b/spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap
@@ -6,7 +6,7 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
class="file-content code js-syntax-highlight"
>
<div
- class="line-numbers"
+ class="line-numbers gl-pt-0!"
>
<a
class="diff-line-num js-line-number"
@@ -56,7 +56,7 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
class="blob-content"
>
<pre
- class="code highlight"
+ class="code highlight gl-p-0! gl-display-flex"
>
<code
data-blob-hash="foo-bar"
diff --git a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
index 3277aab43f0..663ebd3e12f 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
@@ -1,16 +1,21 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants';
import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
+import LineHighlighter from '~/blob/line_highlighter';
+
+jest.mock('~/blob/line_highlighter');
describe('Blob Simple Viewer component', () => {
let wrapper;
const contentMock = `<span id="LC1">First</span>\n<span id="LC2">Second</span>\n<span id="LC3">Third</span>`;
const blobHash = 'foo-bar';
- function createComponent(content = contentMock, isRawContent = false) {
+ function createComponent(content = contentMock, isRawContent = false, glFeatures = {}) {
wrapper = shallowMount(SimpleViewer, {
provide: {
blobHash,
+ glFeatures,
},
propsData: {
content,
@@ -25,6 +30,20 @@ describe('Blob Simple Viewer component', () => {
wrapper.destroy();
});
+ describe('refactorBlobViewer feature flag', () => {
+ it('loads the LineHighlighter if refactorBlobViewer is enabled', () => {
+ createComponent('', false, { refactorBlobViewer: true });
+
+ expect(LineHighlighter).toHaveBeenCalled();
+ });
+
+ it('does not load the LineHighlighter if refactorBlobViewer is disabled', () => {
+ createComponent('', false, { refactorBlobViewer: false });
+
+ expect(LineHighlighter).not.toHaveBeenCalled();
+ });
+ });
+
it('does not fail if content is empty', () => {
const spy = jest.spyOn(window.console, 'error');
createComponent('');
@@ -69,7 +88,7 @@ describe('Blob Simple Viewer component', () => {
expect(linetoBeHighlighted.classes()).toContain(HIGHLIGHT_CLASS_NAME);
});
- it('switches highlighting when another line is selected', () => {
+ it('switches highlighting when another line is selected', async () => {
const currentlyHighlighted = wrapper.find('#LC2');
const hash = '#LC3';
const linetoBeHighlighted = wrapper.find(hash);
@@ -78,11 +97,10 @@ describe('Blob Simple Viewer component', () => {
wrapper.vm.scrollToLine(hash);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.highlightedLine).toBe(linetoBeHighlighted.element);
- expect(currentlyHighlighted.classes()).not.toContain(HIGHLIGHT_CLASS_NAME);
- expect(linetoBeHighlighted.classes()).toContain(HIGHLIGHT_CLASS_NAME);
- });
+ await nextTick();
+ expect(wrapper.vm.highlightedLine).toBe(linetoBeHighlighted.element);
+ expect(currentlyHighlighted.classes()).not.toContain(HIGHLIGHT_CLASS_NAME);
+ expect(linetoBeHighlighted.classes()).toContain(HIGHLIGHT_CLASS_NAME);
});
});
});
diff --git a/spec/frontend/vue_shared/components/chronic_duration_input_spec.js b/spec/frontend/vue_shared/components/chronic_duration_input_spec.js
index 083a5f60d1d..6932a812287 100644
--- a/spec/frontend/vue_shared/components/chronic_duration_input_spec.js
+++ b/spec/frontend/vue_shared/components/chronic_duration_input_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ChronicDurationInput from '~/vue_shared/components/chronic_duration_input.vue';
const MOCK_VALUE = 2 * 3600 + 20 * 60;
@@ -48,7 +49,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
describe('change', () => {
const createAndDispatch = async (initialValue, humanReadableInput) => {
createComponent({ value: initialValue });
- await wrapper.vm.$nextTick();
+ await nextTick();
textElement.value = humanReadableInput;
textElement.dispatchEvent(new Event('input'));
};
@@ -118,7 +119,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits valid with user input', async () => {
textElement.value = '1m10s';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('valid')).toEqual([
[{ valid: true, feedback: '' }],
@@ -133,7 +134,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
textElement.value = '';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('valid')).toEqual([
[{ valid: true, feedback: '' }],
@@ -151,7 +152,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits invalid with user input', async () => {
textElement.value = 'gobbledygook';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('valid')).toEqual([
[{ valid: true, feedback: '' }],
@@ -186,7 +187,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits valid with updated value', async () => {
wrapper.setProps({ value: MOCK_VALUE });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('valid')).toEqual([
[{ valid: null, feedback: '' }],
@@ -210,7 +211,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits valid when input is integer', async () => {
textElement.value = '2hr20min';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toEqual([[MOCK_VALUE]]);
expect(wrapper.emitted('valid')).toEqual([
@@ -228,7 +229,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits valid when input is decimal', async () => {
textElement.value = '1.5s';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toEqual([[1.5]]);
expect(wrapper.emitted('valid')).toEqual([
@@ -252,7 +253,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits valid when input is integer', async () => {
textElement.value = '2hr20min';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toEqual([[MOCK_VALUE]]);
expect(wrapper.emitted('valid')).toEqual([
@@ -270,7 +271,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('emits invalid when input is decimal', async () => {
textElement.value = '1.5s';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('change')).toBeUndefined();
expect(wrapper.emitted('valid')).toEqual([
@@ -318,7 +319,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ value: MOCK_VALUE });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(textElement.value).toBe('2 hrs 20 mins');
expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
@@ -329,7 +330,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('passes user input to parent via v-model', async () => {
textElement.value = '2hr20min';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findComponent(ChronicDurationInput).props('value')).toBe(MOCK_VALUE);
expect(textElement.value).toBe('2hr20min');
@@ -377,7 +378,7 @@ describe('vue_shared/components/chronic_duration_input', () => {
it('creates form data with user-specified value', async () => {
textElement.value = '1m10s';
textElement.dispatchEvent(new Event('input'));
- await wrapper.vm.$nextTick();
+ await nextTick();
const formData = new FormData(wrapper.find('[data-testid=myForm]').element);
const iter = formData.entries();
diff --git a/spec/frontend/vue_shared/components/confirm_fork_modal_spec.js b/spec/frontend/vue_shared/components/confirm_fork_modal_spec.js
new file mode 100644
index 00000000000..1cde92cf522
--- /dev/null
+++ b/spec/frontend/vue_shared/components/confirm_fork_modal_spec.js
@@ -0,0 +1,80 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ConfirmForkModal, { i18n } from '~/vue_shared/components/confirm_fork_modal.vue';
+
+describe('vue_shared/components/confirm_fork_modal', () => {
+ let wrapper = null;
+
+ const forkPath = '/fake/fork/path';
+ const modalId = 'confirm-fork-modal';
+ const defaultProps = { modalId, forkPath };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findModalProp = (prop) => findModal().props(prop);
+ const findModalActionProps = () => findModalProp('actionPrimary');
+
+ const createComponent = (props = {}) =>
+ shallowMountExtended(ConfirmForkModal, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('visible = false', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('sets the visible prop to `false`', () => {
+ expect(findModalProp('visible')).toBe(false);
+ });
+
+ it('sets the modal title', () => {
+ const title = findModalProp('title');
+ expect(title).toBe(i18n.title);
+ });
+
+ it('sets the modal id', () => {
+ const fakeModalId = findModalProp('modalId');
+ expect(fakeModalId).toBe(modalId);
+ });
+
+ it('has the fork path button', () => {
+ const modalProps = findModalActionProps();
+ expect(modalProps.text).toBe(i18n.btnText);
+ expect(modalProps.attributes.variant).toBe('confirm');
+ });
+
+ it('sets the correct fork path', () => {
+ const modalProps = findModalActionProps();
+ expect(modalProps.attributes.href).toBe(forkPath);
+ });
+
+ it('has the fork message', () => {
+ expect(findModal().text()).toContain(i18n.message);
+ });
+ });
+
+ describe('visible = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ visible: true });
+ });
+
+ it('sets the visible prop to `true`', () => {
+ expect(findModalProp('visible')).toBe(true);
+ });
+
+ it('emits the `change` event if the modal is hidden', () => {
+ expect(wrapper.emitted('change')).toBeUndefined();
+
+ findModal().vm.$emit('change', false);
+
+ expect(wrapper.emitted('change')).toEqual([[false]]);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
index 33667a1bb71..d4b6b987c69 100644
--- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
+++ b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
+import { nextTick } from 'vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import {
defaultTimeRanges,
@@ -29,26 +30,23 @@ describe('DateTimePicker', () => {
wrapper.destroy();
});
- it('renders dropdown toggle button with selected text', () => {
+ it('renders dropdown toggle button with selected text', async () => {
createComponent();
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toBe(defaultTimeRange.label);
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toBe(defaultTimeRange.label);
});
- it('renders dropdown toggle button with selected text and utc label', () => {
+ it('renders dropdown toggle button with selected text and utc label', async () => {
createComponent({ utc: true });
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toContain(defaultTimeRange.label);
- expect(dropdownToggle().text()).toContain('UTC');
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toContain(defaultTimeRange.label);
+ expect(dropdownToggle().text()).toContain('UTC');
});
- it('renders dropdown with 2 custom time range inputs', () => {
+ it('renders dropdown with 2 custom time range inputs', async () => {
createComponent();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('input').length).toBe(2);
- });
+ await nextTick();
+ expect(wrapper.findAll('input').length).toBe(2);
});
describe('renders label with h/m/s truncated if possible', () => {
@@ -80,33 +78,30 @@ describe('DateTimePicker', () => {
label: '2019-10-10 00:00:01 to 2019-10-10 00:00:01 UTC',
},
].forEach(({ start, end, utc, label }) => {
- it(`for start ${start}, end ${end}, and utc ${utc}, label is ${label}`, () => {
+ it(`for start ${start}, end ${end}, and utc ${utc}, label is ${label}`, async () => {
createComponent({
value: { start, end },
utc,
});
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toBe(label);
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toBe(label);
});
});
});
- it(`renders dropdown with ${optionsCount} (default) items in quick range`, () => {
+ it(`renders dropdown with ${optionsCount} (default) items in quick range`, async () => {
createComponent();
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(findQuickRangeItems().length).toBe(optionsCount);
- });
+ await nextTick();
+ expect(findQuickRangeItems().length).toBe(optionsCount);
});
- it('renders dropdown with a default quick range item selected', () => {
+ it('renders dropdown with a default quick range item selected', async () => {
createComponent();
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.dropdown-item.active').exists()).toBe(true);
- expect(wrapper.find('.dropdown-item.active').text()).toBe(defaultTimeRange.label);
- });
+ await nextTick();
+ expect(wrapper.find('.dropdown-item.active').exists()).toBe(true);
+ expect(wrapper.find('.dropdown-item.active').text()).toBe(defaultTimeRange.label);
});
it('renders a disabled apply button on wrong input', () => {
@@ -118,74 +113,63 @@ describe('DateTimePicker', () => {
});
describe('user input', () => {
- const fillInputAndBlur = (input, val) => {
+ const fillInputAndBlur = async (input, val) => {
wrapper.find(input).setValue(val);
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find(input).trigger('blur');
- return wrapper.vm.$nextTick();
- });
+ await nextTick();
+ wrapper.find(input).trigger('blur');
+ await nextTick();
};
- beforeEach(() => {
+ beforeEach(async () => {
createComponent();
- return wrapper.vm.$nextTick();
+ await nextTick();
});
- it('displays inline error message if custom time range inputs are invalid', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01abc')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-10abc'))
- .then(() => {
- expect(wrapper.findAll('.invalid-feedback').length).toBe(2);
- });
+ it('displays inline error message if custom time range inputs are invalid', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01abc');
+ await fillInputAndBlur('#custom-time-to', '2019-10-10abc');
+ expect(wrapper.findAll('.invalid-feedback').length).toBe(2);
});
- it('keeps apply button disabled with invalid custom time range inputs', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01abc')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-09-19'))
- .then(() => {
- expect(applyButtonElement().getAttribute('disabled')).toBe('disabled');
- });
+ it('keeps apply button disabled with invalid custom time range inputs', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01abc');
+ await fillInputAndBlur('#custom-time-to', '2019-09-19');
+ expect(applyButtonElement().getAttribute('disabled')).toBe('disabled');
});
- it('enables apply button with valid custom time range inputs', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-19'))
- .then(() => {
- expect(applyButtonElement().getAttribute('disabled')).toBeNull();
- });
+ it('enables apply button with valid custom time range inputs', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01');
+ await fillInputAndBlur('#custom-time-to', '2019-10-19');
+ expect(applyButtonElement().getAttribute('disabled')).toBeNull();
});
describe('when "apply" is clicked', () => {
- it('emits iso dates', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-19 00:00:00'))
- .then(() => {
- applyButtonElement().click();
-
- expect(wrapper.emitted().input).toHaveLength(1);
- expect(wrapper.emitted().input[0]).toEqual([
- {
- end: '2019-10-19T00:00:00Z',
- start: '2019-10-01T00:00:00Z',
- },
- ]);
- });
+ it('emits iso dates', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00');
+ await fillInputAndBlur('#custom-time-to', '2019-10-19 00:00:00');
+ applyButtonElement().click();
+
+ expect(wrapper.emitted().input).toHaveLength(1);
+ expect(wrapper.emitted().input[0]).toEqual([
+ {
+ end: '2019-10-19T00:00:00Z',
+ start: '2019-10-01T00:00:00Z',
+ },
+ ]);
});
- it('emits iso dates, for dates without time of day', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-19'))
- .then(() => {
- applyButtonElement().click();
-
- expect(wrapper.emitted().input).toHaveLength(1);
- expect(wrapper.emitted().input[0]).toEqual([
- {
- end: '2019-10-19T00:00:00Z',
- start: '2019-10-01T00:00:00Z',
- },
- ]);
- });
+ it('emits iso dates, for dates without time of day', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01');
+ await fillInputAndBlur('#custom-time-to', '2019-10-19');
+ applyButtonElement().click();
+
+ expect(wrapper.emitted().input).toHaveLength(1);
+ expect(wrapper.emitted().input[0]).toEqual([
+ {
+ end: '2019-10-19T00:00:00Z',
+ start: '2019-10-01T00:00:00Z',
+ },
+ ]);
});
describe('when timezone is different', () => {
@@ -196,52 +180,46 @@ describe('DateTimePicker', () => {
timezoneMock.unregister();
});
- it('emits iso dates', () => {
- return fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00')
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00'))
- .then(() => {
- applyButtonElement().click();
-
- expect(wrapper.emitted().input).toHaveLength(1);
- expect(wrapper.emitted().input[0]).toEqual([
- {
- start: '2019-10-01T07:00:00Z',
- end: '2019-10-19T19:00:00Z',
- },
- ]);
- });
+ it('emits iso dates', async () => {
+ await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00');
+ await fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00');
+ applyButtonElement().click();
+
+ expect(wrapper.emitted().input).toHaveLength(1);
+ expect(wrapper.emitted().input[0]).toEqual([
+ {
+ start: '2019-10-01T07:00:00Z',
+ end: '2019-10-19T19:00:00Z',
+ },
+ ]);
});
- it('emits iso dates with utc format', () => {
+ it('emits iso dates with utc format', async () => {
wrapper.setProps({ utc: true });
- return wrapper.vm
- .$nextTick()
- .then(() => fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00'))
- .then(() => fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00'))
- .then(() => {
- applyButtonElement().click();
-
- expect(wrapper.emitted().input).toHaveLength(1);
- expect(wrapper.emitted().input[0]).toEqual([
- {
- start: '2019-10-01T00:00:00Z',
- end: '2019-10-19T12:00:00Z',
- },
- ]);
- });
+ await nextTick();
+ await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00');
+ await fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00');
+ applyButtonElement().click();
+
+ expect(wrapper.emitted().input).toHaveLength(1);
+ expect(wrapper.emitted().input[0]).toEqual([
+ {
+ start: '2019-10-01T00:00:00Z',
+ end: '2019-10-19T12:00:00Z',
+ },
+ ]);
});
});
});
- it('unchecks quick range when text is input is clicked', () => {
+ it('unchecks quick range when text is input is clicked', async () => {
const findActiveItems = () =>
findQuickRangeItems().filter((w) => w.classes().includes('active'));
expect(findActiveItems().length).toBe(1);
- return fillInputAndBlur('#custom-time-from', '2019-10-01').then(() => {
- expect(findActiveItems().length).toBe(0);
- });
+ await fillInputAndBlur('#custom-time-from', '2019-10-01');
+ expect(findActiveItems().length).toBe(0);
});
it('emits dates in an object when a is clicked', () => {
@@ -257,16 +235,14 @@ describe('DateTimePicker', () => {
});
});
- it('hides the popover with cancel button', () => {
+ it('hides the popover with cancel button', async () => {
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- cancelButton().trigger('click');
+ await nextTick();
+ cancelButton().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(dropdownMenu().classes('show')).toBe(false);
- });
- });
+ await nextTick();
+ expect(dropdownMenu().classes('show')).toBe(false);
});
});
@@ -293,7 +269,7 @@ describe('DateTimePicker', () => {
jest.spyOn(Date, 'now').mockImplementation(() => MOCK_NOW);
});
- it('renders dropdown with a label in the quick range', () => {
+ it('renders dropdown with a label in the quick range', async () => {
createComponent({
value: {
duration: { seconds: 60 * 5 },
@@ -301,12 +277,11 @@ describe('DateTimePicker', () => {
options: otherTimeRanges,
});
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toBe('5 minutes');
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toBe('5 minutes');
});
- it('renders dropdown with a label in the quick range and utc label', () => {
+ it('renders dropdown with a label in the quick range and utc label', async () => {
createComponent({
value: {
duration: { seconds: 60 * 5 },
@@ -315,12 +290,11 @@ describe('DateTimePicker', () => {
options: otherTimeRanges,
});
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toBe('5 minutes UTC');
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toBe('5 minutes UTC');
});
- it('renders dropdown with quick range items', () => {
+ it('renders dropdown with quick range items', async () => {
createComponent({
value: {
duration: { seconds: 60 * 2 },
@@ -328,31 +302,29 @@ describe('DateTimePicker', () => {
options: otherTimeRanges,
});
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- const items = findQuickRangeItems();
+ await nextTick();
+ const items = findQuickRangeItems();
- expect(items.length).toBe(Object.keys(otherTimeRanges).length);
- expect(items.at(0).text()).toBe('1 minute');
- expect(items.at(0).classes()).not.toContain('active');
+ expect(items.length).toBe(Object.keys(otherTimeRanges).length);
+ expect(items.at(0).text()).toBe('1 minute');
+ expect(items.at(0).classes()).not.toContain('active');
- expect(items.at(1).text()).toBe('2 minutes');
- expect(items.at(1).classes()).toContain('active');
+ expect(items.at(1).text()).toBe('2 minutes');
+ expect(items.at(1).classes()).toContain('active');
- expect(items.at(2).text()).toBe('5 minutes');
- expect(items.at(2).classes()).not.toContain('active');
- });
+ expect(items.at(2).text()).toBe('5 minutes');
+ expect(items.at(2).classes()).not.toContain('active');
});
- it('renders dropdown with a label not in the quick range', () => {
+ it('renders dropdown with a label not in the quick range', async () => {
createComponent({
value: {
duration: { seconds: 60 * 4 },
},
});
dropdownToggle().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(dropdownToggle().text()).toBe('2020-01-23 19:56:00 to 2020-01-23 20:00:00');
- });
+ await nextTick();
+ expect(dropdownToggle().text()).toBe('2020-01-23 19:56:00 to 2020-01-23 20:00:00');
});
});
});
diff --git a/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js b/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js
index b812ced72c9..59653a0ec13 100644
--- a/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js
+++ b/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DeployBoardInstance from '~/vue_shared/components/deployment_instance.vue';
import { folder } from './mock_data';
@@ -28,17 +29,15 @@ describe('Deploy Board Instance', () => {
expect(wrapper.attributes('title')).toEqual('This is a pod');
});
- it('should render a div without tooltip data', (done) => {
+ it('should render a div without tooltip data', async () => {
wrapper = createComponent({
status: 'deploying',
tooltipText: '',
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.classes('deployment-instance-deploying')).toBe(true);
- expect(wrapper.attributes('title')).toEqual('');
- done();
- });
+ await nextTick();
+ expect(wrapper.classes('deployment-instance-deploying')).toBe(true);
+ expect(wrapper.attributes('title')).toEqual('');
});
it('should have a log path computed with a pod name as a parameter', () => {
@@ -58,15 +57,13 @@ describe('Deploy Board Instance', () => {
wrapper.destroy();
});
- it('should render a div with canary class when stable prop is provided as false', (done) => {
+ it('should render a div with canary class when stable prop is provided as false', async () => {
wrapper = createComponent({
stable: false,
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.classes('deployment-instance-canary')).toBe(true);
- done();
- });
+ await nextTick();
+ expect(wrapper.classes('deployment-instance-canary')).toBe(true);
});
});
@@ -75,17 +72,15 @@ describe('Deploy Board Instance', () => {
wrapper.destroy();
});
- it('should not be a link without a logsPath prop', (done) => {
+ it('should not be a link without a logsPath prop', async () => {
wrapper = createComponent({
stable: false,
logsPath: '',
});
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.computedLogPath).toBeNull();
- expect(wrapper.vm.isLink).toBeFalsy();
- done();
- });
+ await nextTick();
+ expect(wrapper.vm.computedLogPath).toBeNull();
+ expect(wrapper.vm.isLink).toBeFalsy();
});
it('should render a link without href if path is not passed', () => {
diff --git a/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js b/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
index 984a28c93d6..353d493add9 100644
--- a/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
+++ b/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
@@ -39,4 +39,72 @@ describe('Design note pin component', () => {
createComponent({ position: null });
expect(wrapper.element).toMatchSnapshot();
});
+
+ it('applies `on-image` class when isOnImage is true', () => {
+ createComponent({ isOnImage: true });
+
+ expect(wrapper.find('.on-image').exists()).toBe(true);
+ });
+
+ it('applies `draft` class when isDraft is true', () => {
+ createComponent({ isDraft: true });
+
+ expect(wrapper.find('.draft').exists()).toBe(true);
+ });
+
+ describe('size', () => {
+ it('is `sm` it applies `small` class', () => {
+ createComponent({ size: 'sm' });
+ expect(wrapper.find('.small').exists()).toBe(true);
+ });
+
+ it('is `md` it applies no size class', () => {
+ createComponent({ size: 'md' });
+ expect(wrapper.find('.small').exists()).toBe(false);
+ expect(wrapper.find('.medium').exists()).toBe(false);
+ });
+
+ it('throws when passed any other value except `sm` or `md`', () => {
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+
+ createComponent({ size: 'lg' });
+
+ // eslint-disable-next-line no-console
+ expect(console.error).toHaveBeenCalled();
+ });
+ });
+
+ describe('ariaLabel', () => {
+ describe('when value is passed', () => {
+ it('overrides default aria-label', () => {
+ const ariaLabel = 'Aria Label';
+
+ createComponent({ ariaLabel });
+
+ const button = wrapper.find('button');
+
+ expect(button.attributes('aria-label')).toBe(ariaLabel);
+ });
+ });
+
+ describe('when no value is passed', () => {
+ it('shows new note label as aria-label when label is absent', () => {
+ createComponent({ label: null });
+
+ const button = wrapper.find('button');
+
+ expect(button.attributes('aria-label')).toBe('Comment form position');
+ });
+
+ it('shows label position as aria-label when label is present', () => {
+ const label = 1;
+
+ createComponent({ label, isNewNote: false });
+
+ const button = wrapper.find('button');
+
+ expect(button.attributes('aria-label')).toBe(`Comment '${label}' position`);
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
index 68e3ee11a0d..69964b2687d 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
@@ -26,27 +26,25 @@ describe('DiffViewer', () => {
vm.$destroy();
});
- it('renders image diff', (done) => {
+ it('renders image diff', async () => {
window.gon = {
relative_url_root: '',
};
createComponent({ ...requiredProps, projectPath: '' });
- setImmediate(() => {
- expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
- `//-/raw/DEF/${RED_BOX_IMAGE_URL}`,
- );
+ await nextTick();
- expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
- `//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`,
- );
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
+ `//-/raw/DEF/${RED_BOX_IMAGE_URL}`,
+ );
- done();
- });
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
+ `//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`,
+ );
});
- it('renders fallback download diff display', (done) => {
+ it('renders fallback download diff display', async () => {
createComponent({
...requiredProps,
diffViewerMode: 'added',
@@ -54,22 +52,18 @@ describe('DiffViewer', () => {
oldPath: 'testold.abc',
});
- setImmediate(() => {
- expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain(
- 'testold.abc',
- );
+ await nextTick();
- expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
+ expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain('testold.abc');
- expect(vm.$el.querySelector('.added .file-info').textContent.trim()).toContain('test.abc');
- expect(vm.$el.querySelector('.added .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
+ expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
+ 'Download',
+ );
- done();
- });
+ expect(vm.$el.querySelector('.added .file-info').textContent.trim()).toContain('test.abc');
+ expect(vm.$el.querySelector('.added .btn.btn-default').textContent.trim()).toContain(
+ 'Download',
+ );
});
describe('renamed file', () => {
diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
index 8deb466b33c..d0fa8b8dacb 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { compileToFunctions } from 'vue-template-compiler';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
@@ -51,60 +51,53 @@ describe('ImageDiffViewer', () => {
wrapper.destroy();
});
- it('renders image diff for replaced', (done) => {
+ it('renders image diff for replaced', async () => {
createComponent({ ...allProps });
- vm.$nextTick(() => {
- const metaInfoElements = vm.$el.querySelectorAll('.image-info');
+ await nextTick();
+ const metaInfoElements = vm.$el.querySelectorAll('.image-info');
- expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
- expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
- expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('2-up');
- expect(vm.$el.querySelector('.view-modes-menu li:nth-child(2)').textContent.trim()).toBe(
- 'Swipe',
- );
+ expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('2-up');
+ expect(vm.$el.querySelector('.view-modes-menu li:nth-child(2)').textContent.trim()).toBe(
+ 'Swipe',
+ );
- expect(vm.$el.querySelector('.view-modes-menu li:nth-child(3)').textContent.trim()).toBe(
- 'Onion skin',
- );
+ expect(vm.$el.querySelector('.view-modes-menu li:nth-child(3)').textContent.trim()).toBe(
+ 'Onion skin',
+ );
- expect(metaInfoElements.length).toBe(2);
- expect(metaInfoElements[0]).toHaveText('2.00 KiB');
- expect(metaInfoElements[1]).toHaveText('1.00 KiB');
-
- done();
- });
+ expect(metaInfoElements.length).toBe(2);
+ expect(metaInfoElements[0]).toHaveText('2.00 KiB');
+ expect(metaInfoElements[1]).toHaveText('1.00 KiB');
});
- it('renders image diff for new', (done) => {
+ it('renders image diff for new', async () => {
createComponent({ ...allProps, diffMode: 'new', oldPath: '' });
- setImmediate(() => {
- const metaInfoElement = vm.$el.querySelector('.image-info');
+ await nextTick();
- expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
- expect(metaInfoElement).toHaveText('1.00 KiB');
+ const metaInfoElement = vm.$el.querySelector('.image-info');
- done();
- });
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+ expect(metaInfoElement).toHaveText('1.00 KiB');
});
- it('renders image diff for deleted', (done) => {
+ it('renders image diff for deleted', async () => {
createComponent({ ...allProps, diffMode: 'deleted', newPath: '' });
- setImmediate(() => {
- const metaInfoElement = vm.$el.querySelector('.image-info');
+ await nextTick();
- expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
- expect(metaInfoElement).toHaveText('2.00 KiB');
+ const metaInfoElement = vm.$el.querySelector('.image-info');
- done();
- });
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
+ expect(metaInfoElement).toHaveText('2.00 KiB');
});
- it('renders image diff for renamed', (done) => {
+ it('renders image diff for renamed', async () => {
vm = new Vue({
components: {
imageDiffViewer,
@@ -130,69 +123,56 @@ describe('ImageDiffViewer', () => {
`),
}).$mount();
- setImmediate(() => {
- const metaInfoElement = vm.$el.querySelector('.image-info');
+ await nextTick();
- expect(vm.$el.querySelector('img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
- expect(vm.$el.querySelector('.overlay')).not.toBe(null);
+ const metaInfoElement = vm.$el.querySelector('.image-info');
- expect(metaInfoElement).toHaveText('2.00 KiB');
+ expect(vm.$el.querySelector('img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+ expect(vm.$el.querySelector('.overlay')).not.toBe(null);
- done();
- });
+ expect(metaInfoElement).toHaveText('2.00 KiB');
});
describe('swipeMode', () => {
- beforeEach((done) => {
+ beforeEach(() => {
createComponent({ ...requiredProps });
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
- it('switches to Swipe Mode', (done) => {
+ it('switches to Swipe Mode', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(2)').click();
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('Swipe');
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('Swipe');
});
});
describe('onionSkin', () => {
- beforeEach((done) => {
+ beforeEach(() => {
createComponent({ ...requiredProps });
- setImmediate(() => {
- done();
- });
+ return nextTick();
});
- it('switches to Onion Skin Mode', (done) => {
+ it('switches to Onion Skin Mode', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe(
- 'Onion skin',
- );
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe(
+ 'Onion skin',
+ );
});
- it('has working drag handler', (done) => {
+ it('has working drag handler', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
- vm.$nextTick(() => {
- dragSlider(vm.$el.querySelector('.dragger'), document, 20);
+ await nextTick();
+ dragSlider(vm.$el.querySelector('.dragger'), document, 20);
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.dragger').style.left).toBe('20px');
- expect(vm.$el.querySelector('.added.frame').style.opacity).toBe('0.2');
- done();
- });
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.dragger').style.left).toBe('20px');
+ expect(vm.$el.querySelector('.added.frame').style.opacity).toBe('0.2');
});
});
});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
index b8d3cbebe16..549388c1a5c 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
@@ -1,5 +1,5 @@
import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import {
TRANSITION_LOAD_START,
@@ -126,15 +126,14 @@ describe('Renamed Diff Viewer', () => {
store = null;
});
- it('calls the switchToFullDiffFromRenamedFile action when the method is triggered', () => {
+ it('calls the switchToFullDiffFromRenamedFile action when the method is triggered', async () => {
store.dispatch.mockResolvedValue();
wrapper.vm.switchToFull();
- return wrapper.vm.$nextTick().then(() => {
- expect(store.dispatch).toHaveBeenCalledWith('diffs/switchToFullDiffFromRenamedFile', {
- diffFile,
- });
+ await nextTick();
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/switchToFullDiffFromRenamedFile', {
+ diffFile,
});
});
@@ -144,7 +143,7 @@ describe('Renamed Diff Viewer', () => {
${STATE_ERRORED} | ${'mockRejectedValue'} | ${'rejected'}
`(
'moves through the correct states during a $resolution request',
- ({ after, resolvePromise }) => {
+ async ({ after, resolvePromise }) => {
store.dispatch[resolvePromise]();
expect(wrapper.vm.state).toEqual(STATE_IDLING);
@@ -153,16 +152,9 @@ describe('Renamed Diff Viewer', () => {
expect(wrapper.vm.state).toEqual(STATE_LOADING);
- return (
- wrapper.vm
- // This tick is needed for when the action (promise) finishes
- .$nextTick()
- // This tick waits for the state change in the promise .then/.catch to bubble into the component
- .then(() => wrapper.vm.$nextTick())
- .then(() => {
- expect(wrapper.vm.state).toEqual(after);
- })
- );
+ await nextTick(); // This tick is needed for when the action (promise) finishes
+ await nextTick(); // This tick waits for the state change in the promise .then/.catch to bubble into the component
+ expect(wrapper.vm.state).toEqual(after);
},
);
});
diff --git a/spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js
index 194681a6138..4b32fbffebe 100644
--- a/spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlSprintf } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import Component from '~/vue_shared/components/dismissible_feedback_alert.vue';
@@ -64,7 +65,7 @@ describe('Dismissible Feedback Alert', () => {
it('should not show the alert once dismissed', async () => {
localStorage.setItem(STORAGE_DISMISSAL_KEY, 'true');
createFullComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().exists()).toBe(false);
});
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
index ec553c52236..b32dbeb8852 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DropdownSearchInputComponent from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
describe('DropdownSearchInputComponent', () => {
@@ -36,16 +37,15 @@ describe('DropdownSearchInputComponent', () => {
expect(findInputEl().attributes('placeholder')).toBe(defaultProps.placeholderText);
});
- it('focuses input element when focused property equals true', () => {
+ it('focuses input element when focused property equals true', async () => {
const inputEl = findInputEl().element;
jest.spyOn(inputEl, 'focus');
wrapper.setProps({ focused: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(inputEl.focus).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(inputEl.focus).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
index b3af5fd3feb..084d0559665 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DropdownWidget from '~/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue';
describe('DropdownWidget component', () => {
@@ -53,7 +54,7 @@ describe('DropdownWidget component', () => {
describe('when dropdown is open', () => {
beforeEach(async () => {
findDropdown().vm.$emit('show');
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('emits search event when typing in search box', () => {
@@ -69,7 +70,7 @@ describe('DropdownWidget component', () => {
it('emits set-option event when clicking on an option', async () => {
wrapper.findAll('[data-testid="unselected-option"]').at(1).trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('set-option')).toEqual([[wrapper.props().options[1]]]);
});
diff --git a/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js
index 996df34f2ff..c34041f9305 100644
--- a/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
import { UP_KEY_CODE, DOWN_KEY_CODE, TAB_KEY_CODE } from '~/lib/utils/keycodes';
@@ -53,7 +54,7 @@ describe('DropdownKeyboardNavigation', () => {
it('should $emit @change with the default index when max changes', async () => {
wrapper.setProps({ max: 20 });
- await wrapper.vm.$nextTick();
+ await nextTick();
// The first @change`call happens on created() so we test for the second [1]
expect(wrapper.emitted('change')[1]).toStrictEqual([MOCK_DEFAULT_INDEX]);
});
diff --git a/spec/frontend/vue_shared/components/expand_button_spec.js b/spec/frontend/vue_shared/components/expand_button_spec.js
index 7874658cc0f..87d6ed6b21f 100644
--- a/spec/frontend/vue_shared/components/expand_button_spec.js
+++ b/spec/frontend/vue_shared/components/expand_button_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import ExpandButton from '~/vue_shared/components/expand_button.vue';
const text = {
@@ -66,9 +66,9 @@ describe('Expand button', () => {
});
describe('on click', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
expanderPrependEl().trigger('click');
- Vue.nextTick(done);
+ await nextTick();
});
afterEach(() => {
@@ -85,7 +85,7 @@ describe('Expand button', () => {
});
describe('when short text is provided', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
factory({
slots: {
expanded: `<p>${text.expanded}</p>`,
@@ -94,7 +94,7 @@ describe('Expand button', () => {
});
expanderPrependEl().trigger('click');
- Vue.nextTick(done);
+ await nextTick();
});
it('only renders expanded text', () => {
@@ -110,31 +110,29 @@ describe('Expand button', () => {
});
describe('append button', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
expanderPrependEl().trigger('click');
- Vue.nextTick(done);
+ await nextTick();
});
- it('clicking hides itself and shows prepend', () => {
+ it('clicking hides itself and shows prepend', async () => {
expect(expanderAppendEl().isVisible()).toBe(true);
expanderAppendEl().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(expanderPrependEl().isVisible()).toBe(true);
- });
+ await nextTick();
+ expect(expanderPrependEl().isVisible()).toBe(true);
});
- it('clicking hides expanded text', () => {
+ it('clicking hides expanded text', async () => {
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
- });
+ await nextTick();
+ expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
});
describe('when short text is provided', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
factory({
slots: {
expanded: `<p>${text.expanded}</p>`,
@@ -143,16 +141,15 @@ describe('Expand button', () => {
});
expanderPrependEl().trigger('click');
- Vue.nextTick(done);
+ await nextTick();
});
- it('clicking reveals short text', () => {
+ it('clicking reveals short text', async () => {
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
- });
+ await nextTick();
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
});
});
});
diff --git a/spec/frontend/vue_shared/components/file_finder/index_spec.js b/spec/frontend/vue_shared/components/file_finder/index_spec.js
index 181fc4017a3..921091c5b84 100644
--- a/spec/frontend/vue_shared/components/file_finder/index_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js
@@ -1,6 +1,5 @@
import Mousetrap from 'mousetrap';
-import Vue from 'vue';
-import waitForPromises from 'helpers/wait_for_promises';
+import Vue, { nextTick } from 'vue';
import { file } from 'jest/ide/helpers';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import FindFileComponent from '~/vue_shared/components/file_finder/index.vue';
@@ -31,7 +30,7 @@ describe('File finder item spec', () => {
});
describe('with entries', () => {
- beforeEach((done) => {
+ beforeEach(() => {
createComponent({
files: [
{
@@ -48,7 +47,7 @@ describe('File finder item spec', () => {
],
});
- setImmediate(done);
+ return nextTick();
});
it('renders list of blobs', () => {
@@ -57,68 +56,48 @@ describe('File finder item spec', () => {
expect(vm.$el.textContent).not.toContain('folder');
});
- it('filters entries', (done) => {
+ it('filters entries', async () => {
vm.searchText = 'index';
- setImmediate(() => {
- expect(vm.$el.textContent).toContain('index.js');
- expect(vm.$el.textContent).not.toContain('component.js');
+ await nextTick();
- done();
- });
+ expect(vm.$el.textContent).toContain('index.js');
+ expect(vm.$el.textContent).not.toContain('component.js');
});
- it('shows clear button when searchText is not empty', (done) => {
+ it('shows clear button when searchText is not empty', async () => {
vm.searchText = 'index';
- setImmediate(() => {
- expect(vm.$el.querySelector('.dropdown-input').classList).toContain('has-value');
- expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden');
+ await nextTick();
- done();
- });
+ expect(vm.$el.querySelector('.dropdown-input').classList).toContain('has-value');
+ expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden');
});
- it('clear button resets searchText', (done) => {
+ it('clear button resets searchText', async () => {
vm.searchText = 'index';
- waitForPromises()
- .then(() => {
- vm.clearSearchInput();
- })
- .then(waitForPromises)
- .then(() => {
- expect(vm.searchText).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ vm.clearSearchInput();
+
+ expect(vm.searchText).toBe('');
});
- it('clear button focuses search input', (done) => {
+ it('clear button focuses search input', async () => {
jest.spyOn(vm.$refs.searchInput, 'focus').mockImplementation(() => {});
vm.searchText = 'index';
- waitForPromises()
- .then(() => {
- vm.clearSearchInput();
- })
- .then(waitForPromises)
- .then(() => {
- expect(vm.$refs.searchInput.focus).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ vm.clearSearchInput();
+
+ await nextTick();
+
+ expect(vm.$refs.searchInput.focus).toHaveBeenCalled();
});
describe('listShowCount', () => {
- it('returns 1 when no filtered entries exist', (done) => {
+ it('returns 1 when no filtered entries exist', () => {
vm.searchText = 'testing 123';
- setImmediate(() => {
- expect(vm.listShowCount).toBe(1);
-
- done();
- });
+ expect(vm.listShowCount).toBe(1);
});
it('returns entries length when not filtered', () => {
@@ -131,26 +110,18 @@ describe('File finder item spec', () => {
expect(vm.listHeight).toBe(55);
});
- it('returns 33 when entries dont exist', (done) => {
+ it('returns 33 when entries dont exist', () => {
vm.searchText = 'testing 123';
- setImmediate(() => {
- expect(vm.listHeight).toBe(33);
-
- done();
- });
+ expect(vm.listHeight).toBe(33);
});
});
describe('filteredBlobsLength', () => {
- it('returns length of filtered blobs', (done) => {
+ it('returns length of filtered blobs', () => {
vm.searchText = 'index';
- setImmediate(() => {
- expect(vm.filteredBlobsLength).toBe(1);
-
- done();
- });
+ expect(vm.filteredBlobsLength).toBe(1);
});
});
@@ -158,7 +129,7 @@ describe('File finder item spec', () => {
it('renders less DOM nodes if not visible by utilizing v-if', async () => {
vm.visible = false;
- await waitForPromises();
+ await nextTick();
expect(vm.$el).toBeInstanceOf(Comment);
});
@@ -166,33 +137,24 @@ describe('File finder item spec', () => {
describe('watches', () => {
describe('searchText', () => {
- it('resets focusedIndex when updated', (done) => {
+ it('resets focusedIndex when updated', async () => {
vm.focusedIndex = 1;
vm.searchText = 'test';
- setImmediate(() => {
- expect(vm.focusedIndex).toBe(0);
+ await nextTick();
- done();
- });
+ expect(vm.focusedIndex).toBe(0);
});
});
describe('visible', () => {
- it('resets searchText when changed to false', (done) => {
+ it('resets searchText when changed to false', async () => {
vm.searchText = 'test';
- vm.visible = true;
-
- waitForPromises()
- .then(() => {
- vm.visible = false;
- })
- .then(waitForPromises)
- .then(() => {
- expect(vm.searchText).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ vm.visible = false;
+
+ await nextTick();
+
+ expect(vm.searchText).toBe('');
});
});
});
@@ -216,7 +178,7 @@ describe('File finder item spec', () => {
});
describe('onKeyup', () => {
- it('opens file on enter key', (done) => {
+ it('opens file on enter key', async () => {
const event = new CustomEvent('keyup');
event.keyCode = ENTER_KEY_CODE;
@@ -224,14 +186,12 @@ describe('File finder item spec', () => {
vm.$refs.searchInput.dispatchEvent(event);
- setImmediate(() => {
- expect(vm.openFile).toHaveBeenCalledWith(vm.files[0]);
+ await nextTick();
- done();
- });
+ expect(vm.openFile).toHaveBeenCalledWith(vm.files[0]);
});
- it('closes file finder on esc key', (done) => {
+ it('closes file finder on esc key', async () => {
const event = new CustomEvent('keyup');
event.keyCode = ESC_KEY_CODE;
@@ -239,11 +199,9 @@ describe('File finder item spec', () => {
vm.$refs.searchInput.dispatchEvent(event);
- setImmediate(() => {
- expect(vm.$emit).toHaveBeenCalledWith('toggle', false);
+ await nextTick();
- done();
- });
+ expect(vm.$emit).toHaveBeenCalledWith('toggle', false);
});
});
@@ -310,34 +268,26 @@ describe('File finder item spec', () => {
});
describe('keyboard shortcuts', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
createComponent();
jest.spyOn(vm, 'toggle').mockImplementation(() => {});
- vm.$nextTick(done);
+ await nextTick();
});
- it('calls toggle on `t` key press', (done) => {
+ it('calls toggle on `t` key press', async () => {
Mousetrap.trigger('t');
- vm.$nextTick()
- .then(() => {
- expect(vm.toggle).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.toggle).toHaveBeenCalled();
});
- it('calls toggle on `mod+p` key press', (done) => {
+ it('calls toggle on `mod+p` key press', async () => {
Mousetrap.trigger('mod+p');
- vm.$nextTick()
- .then(() => {
- expect(vm.toggle).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.toggle).toHaveBeenCalled();
});
it('always allows `mod+p` to trigger toggle', () => {
diff --git a/spec/frontend/vue_shared/components/file_finder/item_spec.js b/spec/frontend/vue_shared/components/file_finder/item_spec.js
index 1a4a97efb95..b69c33055c1 100644
--- a/spec/frontend/vue_shared/components/file_finder/item_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/item_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import createComponent from 'helpers/vue_mount_component_helper';
import { file } from 'jest/ide/helpers';
import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
@@ -37,14 +37,11 @@ describe('File finder item spec', () => {
expect(vm.$el.classList).toContain('is-focused');
});
- it('does not have is-focused class when not focused', (done) => {
+ it('does not have is-focused class when not focused', async () => {
vm.focused = false;
- vm.$nextTick(() => {
- expect(vm.$el.classList).not.toContain('is-focused');
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.classList).not.toContain('is-focused');
});
});
@@ -53,24 +50,18 @@ describe('File finder item spec', () => {
expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
});
- it('renders when a changed file', (done) => {
+ it('renders when a changed file', async () => {
vm.file.changed = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
});
- it('renders when a temp file', (done) => {
+ it('renders when a temp file', async () => {
vm.file.tempFile = true;
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
+ await nextTick();
+ expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
});
});
@@ -85,56 +76,52 @@ describe('File finder item spec', () => {
describe('path', () => {
let el;
- beforeEach((done) => {
+ beforeEach(async () => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-path');
- vm.$nextTick(done);
+ nextTick();
});
it('highlights text', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
- it('adds ellipsis to long text', (done) => {
+ it('adds ellipsis to long text', async () => {
vm.file.path = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
- vm.$nextTick(() => {
- expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
- done();
- });
+ await nextTick();
+ expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
});
});
describe('name', () => {
let el;
- beforeEach((done) => {
+ beforeEach(async () => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-name');
- vm.$nextTick(done);
+ await nextTick();
});
it('highlights text', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
- it('does not add ellipsis to long text', (done) => {
+ it('does not add ellipsis to long text', async () => {
vm.file.name = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
- vm.$nextTick(() => {
- expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
- done();
- });
+ await nextTick();
+ expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
index 4e9eac2dde2..575e8a73050 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -8,6 +8,7 @@ import {
} from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
import { SortDirection } from '~/vue_shared/components/filtered_search_bar/constants';
@@ -172,7 +173,7 @@ describe('FilteredSearchBarRoot', () => {
recentSearches: [{ foo: 'bar' }, 'foo'],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.filteredRecentSearches).toHaveLength(1);
expect(wrapper.vm.filteredRecentSearches[0]).toEqual({ foo: 'bar' });
@@ -188,7 +189,7 @@ describe('FilteredSearchBarRoot', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.filteredRecentSearches).toHaveLength(2);
expect(uniqueTokens).toHaveBeenCalled();
@@ -199,7 +200,7 @@ describe('FilteredSearchBarRoot', () => {
recentSearchesStorageKey: '',
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.filteredRecentSearches).not.toBeDefined();
});
@@ -208,7 +209,7 @@ describe('FilteredSearchBarRoot', () => {
describe('watchers', () => {
describe('filterValue', () => {
- it('emits component event `onFilter` with empty array and false when filter was never selected', () => {
+ it('emits component event `onFilter` with empty array and false when filter was never selected', async () => {
wrapper = createComponent({ initialFilterValue: [tokenValueEmpty] });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -217,12 +218,11 @@ describe('FilteredSearchBarRoot', () => {
filterValue: [tokenValueEmpty],
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('onFilter')[0]).toEqual([[], false]);
- });
+ await nextTick();
+ expect(wrapper.emitted('onFilter')[0]).toEqual([[], false]);
});
- it('emits component event `onFilter` with empty array and true when initially selected filter value was cleared', () => {
+ it('emits component event `onFilter` with empty array and true when initially selected filter value was cleared', async () => {
wrapper = createComponent({ initialFilterValue: [tokenValueLabel] });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -231,9 +231,8 @@ describe('FilteredSearchBarRoot', () => {
filterValue: [tokenValueEmpty],
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('onFilter')[0]).toEqual([[], true]);
- });
+ await nextTick();
+ expect(wrapper.emitted('onFilter')[0]).toEqual([[], true]);
});
});
});
@@ -336,7 +335,7 @@ describe('FilteredSearchBarRoot', () => {
filterValue: mockFilters,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('calls `uniqueTokens` on `filterValue` prop to remove duplicates', () => {
@@ -395,7 +394,7 @@ describe('FilteredSearchBarRoot', () => {
});
describe('template', () => {
- beforeEach(() => {
+ beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -404,7 +403,7 @@ describe('FilteredSearchBarRoot', () => {
recentSearches: mockHistoryItems,
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders gl-filtered-search component', () => {
@@ -439,7 +438,7 @@ describe('FilteredSearchBarRoot', () => {
const wrapperFullMount = createComponent({ sortOptions: mockSortOptions, shallow: false });
wrapperFullMount.vm.recentSearchesStore.addRecentSearch(mockHistoryItems[0]);
- await wrapperFullMount.vm.$nextTick();
+ await nextTick();
const searchHistoryItemsEl = wrapperFullMount.findAll(
'.gl-search-box-by-click-menu .gl-search-box-by-click-history-item',
@@ -462,7 +461,7 @@ describe('FilteredSearchBarRoot', () => {
wrapperFullMount.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
- await wrapperFullMount.vm.$nextTick();
+ await nextTick();
expect(wrapperFullMount.find(GlDropdownItem).text()).toBe('Membership := Direct');
@@ -480,7 +479,7 @@ describe('FilteredSearchBarRoot', () => {
wrapperFullMount.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
- await wrapperFullMount.vm.$nextTick();
+ await nextTick();
expect(wrapperFullMount.find(GlDropdownItem).text()).toBe('Membership := exclude');
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 5865c6a41b8..87066b70023 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
@@ -6,6 +6,7 @@ import {
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -167,7 +168,7 @@ describe('AuthorToken', () => {
const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
it('renders base-token component', () => {
@@ -185,23 +186,22 @@ describe('AuthorToken', () => {
});
});
- it('renders token item when value is selected', () => {
+ it('renders token item when value is selected', async () => {
wrapper = createComponent({
value: { data: mockAuthors[0].username },
data: { authors: mockAuthors },
stubs: { Portal: true },
});
- return wrapper.vm.$nextTick(() => {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ await nextTick();
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
- expect(tokenSegments).toHaveLength(3); // Author, =, "Administrator"
+ expect(tokenSegments).toHaveLength(3); // Author, =, "Administrator"
- const tokenValue = tokenSegments.at(2);
+ const tokenValue = tokenSegments.at(2);
- expect(tokenValue.findComponent(GlAvatar).props('src')).toBe(mockAuthors[0].avatar_url);
- expect(tokenValue.text()).toBe(mockAuthors[0].name); // "Administrator"
- });
+ 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 () => {
@@ -220,7 +220,7 @@ describe('AuthorToken', () => {
stubs: { Portal: true },
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url);
@@ -236,7 +236,7 @@ describe('AuthorToken', () => {
],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url);
});
@@ -268,7 +268,7 @@ describe('AuthorToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
@@ -323,7 +323,7 @@ describe('AuthorToken', () => {
it('does not show current user while searching', async () => {
wrapper.findComponent(BaseToken).vm.handleInput({ data: 'foo' });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
});
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 84f0151d9db..dd9bf2ff598 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
@@ -1,5 +1,6 @@
-import { GlFilteredSearchToken } from '@gitlab/ui';
+import { GlFilteredSearchToken, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import {
mockRegularLabel,
mockLabels,
@@ -61,13 +62,10 @@ const mockProps = {
getActiveTokenValue: (labels, data) => labels.find((label) => label.title === data),
};
-function createComponent({
- props = { ...mockProps },
- stubs = defaultStubs,
- slots = defaultSlots,
-} = {}) {
+function createComponent({ props = {}, stubs = defaultStubs, slots = defaultSlots } = {}) {
return mount(BaseToken, {
propsData: {
+ ...mockProps,
...props,
},
provide: {
@@ -83,15 +81,7 @@ function createComponent({
describe('BaseToken', () => {
let wrapper;
- beforeEach(() => {
- wrapper = createComponent({
- props: {
- ...mockProps,
- value: { data: `"${mockRegularLabel.title}"` },
- suggestions: mockLabels,
- },
- });
- });
+ const findGlFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken);
afterEach(() => {
wrapper.destroy();
@@ -99,21 +89,25 @@ describe('BaseToken', () => {
describe('data', () => {
it('calls `getRecentlyUsedSuggestions` to populate `recentSuggestions` when `recentSuggestionsStorageKey` is defined', () => {
+ wrapper = createComponent();
+
expect(getRecentlyUsedSuggestions).toHaveBeenCalledWith(mockStorageKey);
});
});
describe('computed', () => {
describe('activeTokenValue', () => {
- it('calls `getActiveTokenValue` when it is provided', async () => {
+ it('calls `getActiveTokenValue` when it is provided', () => {
const mockGetActiveTokenValue = jest.fn();
- wrapper.setProps({
- getActiveTokenValue: mockGetActiveTokenValue,
+ wrapper = createComponent({
+ props: {
+ value: { data: `"${mockRegularLabel.title}"` },
+ suggestions: mockLabels,
+ getActiveTokenValue: mockGetActiveTokenValue,
+ },
});
- await wrapper.vm.$nextTick();
-
expect(mockGetActiveTokenValue).toHaveBeenCalledTimes(1);
expect(mockGetActiveTokenValue).toHaveBeenCalledWith(
mockLabels,
@@ -125,33 +119,19 @@ describe('BaseToken', () => {
describe('watch', () => {
describe('active', () => {
- let wrapperWithTokenActive;
-
beforeEach(() => {
- wrapperWithTokenActive = createComponent({
+ wrapper = createComponent({
props: {
- ...mockProps,
value: { data: `"${mockRegularLabel.title}"` },
active: true,
},
});
});
- afterEach(() => {
- wrapperWithTokenActive.destroy();
- });
-
it('emits `fetch-suggestions` event on the component when value of this prop is changed to false and `suggestions` array is empty', async () => {
- wrapperWithTokenActive.setProps({
- active: false,
- });
-
- await wrapperWithTokenActive.vm.$nextTick();
+ await wrapper.setProps({ active: false });
- expect(wrapperWithTokenActive.emitted('fetch-suggestions')).toBeTruthy();
- expect(wrapperWithTokenActive.emitted('fetch-suggestions')).toEqual([
- [`"${mockRegularLabel.title}"`],
- ]);
+ expect(wrapper.emitted('fetch-suggestions')).toEqual([[`"${mockRegularLabel.title}"`]]);
});
});
});
@@ -161,17 +141,15 @@ describe('BaseToken', () => {
const mockTokenValue = mockLabels[0];
it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => {
+ wrapper = createComponent({ props: { suggestions: mockLabels } });
+
wrapper.vm.handleTokenValueSelected(mockTokenValue.title);
expect(setTokenValueToRecentlyUsed).toHaveBeenCalledWith(mockStorageKey, mockTokenValue);
});
- it('does not add token from preloadedSuggestions', async () => {
- wrapper.setProps({
- preloadedSuggestions: [mockTokenValue],
- });
-
- await wrapper.vm.$nextTick();
+ it('does not add token from preloadedSuggestions', () => {
+ wrapper = createComponent({ props: { preloadedSuggestions: [mockTokenValue] } });
wrapper.vm.handleTokenValueSelected(mockTokenValue.title);
@@ -182,58 +160,60 @@ describe('BaseToken', () => {
describe('template', () => {
it('renders gl-filtered-search-token component', () => {
- const wrapperWithNoStubs = createComponent({
- stubs: {},
- });
- const glFilteredSearchToken = wrapperWithNoStubs.find(GlFilteredSearchToken);
-
- expect(glFilteredSearchToken.exists()).toBe(true);
- expect(glFilteredSearchToken.props('config')).toEqual(mockProps.config);
+ wrapper = createComponent({ stubs: {} });
- wrapperWithNoStubs.destroy();
+ expect(findGlFilteredSearchToken().props('config')).toEqual(mockProps.config);
});
it('renders `view-token` slot when present', () => {
+ wrapper = createComponent();
+
expect(wrapper.find('.js-view-token').exists()).toBe(true);
});
it('renders `view` slot when present', () => {
+ wrapper = createComponent();
+
expect(wrapper.find('.js-view').exists()).toBe(true);
});
- describe('events', () => {
- let wrapperWithNoStubs;
-
- afterEach(() => {
- wrapperWithNoStubs.destroy();
+ it('renders loading spinner when loading', () => {
+ wrapper = createComponent({
+ props: {
+ active: true,
+ config: mockLabelToken,
+ suggestionsLoading: true,
+ },
+ stubs: { Portal: true },
});
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ describe('events', () => {
describe('when activeToken has been selected', () => {
beforeEach(() => {
- wrapperWithNoStubs = createComponent({
- props: {
- ...mockProps,
- getActiveTokenValue: () => ({ title: '' }),
- suggestionsLoading: true,
- },
+ wrapper = createComponent({
+ props: { getActiveTokenValue: () => ({ title: '' }) },
stubs: { Portal: true },
});
});
+
it('does not emit `fetch-suggestions` event on component after a delay when component emits `input` event', async () => {
jest.useFakeTimers();
- wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' });
- await wrapperWithNoStubs.vm.$nextTick();
+ findGlFilteredSearchToken().vm.$emit('input', { data: 'foo' });
+ await nextTick();
jest.runAllTimers();
- expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toEqual([['']]);
+ expect(wrapper.emitted('fetch-suggestions')).toEqual([['']]);
});
});
describe('when activeToken has not been selected', () => {
beforeEach(() => {
- wrapperWithNoStubs = createComponent({
+ wrapper = createComponent({
stubs: { Portal: true },
});
});
@@ -241,38 +221,27 @@ describe('BaseToken', () => {
it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => {
jest.useFakeTimers();
- wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' });
- await wrapperWithNoStubs.vm.$nextTick();
+ findGlFilteredSearchToken().vm.$emit('input', { data: 'foo' });
+ await nextTick();
jest.runAllTimers();
- expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy();
- expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
+ expect(wrapper.emitted('fetch-suggestions')[2]).toEqual(['foo']);
});
describe('when search is started with a quote', () => {
- it('emits `fetch-suggestions` with filtered value', async () => {
- jest.useFakeTimers();
-
- wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo' });
- await wrapperWithNoStubs.vm.$nextTick();
+ it('emits `fetch-suggestions` with filtered value', () => {
+ findGlFilteredSearchToken().vm.$emit('input', { data: '"foo' });
- jest.runAllTimers();
-
- expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
+ expect(wrapper.emitted('fetch-suggestions')[2]).toEqual(['foo']);
});
});
describe('when search starts and ends with a quote', () => {
- it('emits `fetch-suggestions` with filtered value', async () => {
- jest.useFakeTimers();
-
- wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo"' });
- await wrapperWithNoStubs.vm.$nextTick();
-
- jest.runAllTimers();
+ it('emits `fetch-suggestions` with filtered value', () => {
+ findGlFilteredSearchToken().vm.$emit('input', { data: '"foo"' });
- expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
+ expect(wrapper.emitted('fetch-suggestions')[2]).toEqual(['foo']);
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index cd8be765fb5..7a7db434052 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -6,6 +6,7 @@ import {
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
@@ -115,7 +116,7 @@ describe('BranchToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
}
beforeEach(async () => {
@@ -127,7 +128,7 @@ describe('BranchToken', () => {
branches: mockBranches,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders gl-filtered-search-token component', () => {
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 ed9ac7c271e..b163563cea4 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
@@ -6,6 +6,7 @@ import {
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -129,7 +130,7 @@ describe('EmojiToken', () => {
emojis: mockEmojis,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders gl-filtered-search-token component', () => {
@@ -152,7 +153,7 @@ describe('EmojiToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
@@ -171,7 +172,7 @@ describe('EmojiToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
@@ -186,7 +187,7 @@ describe('EmojiToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
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 b9af71ad8a7..52df27c2d00 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
@@ -5,6 +5,7 @@ import {
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import {
mockRegularLabel,
@@ -150,7 +151,7 @@ describe('LabelToken', () => {
labels: mockLabels,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders base-token component', () => {
@@ -182,7 +183,7 @@ describe('LabelToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
@@ -201,7 +202,7 @@ describe('LabelToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
index c0d8b5fd139..de9ec863dd5 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
@@ -6,6 +6,7 @@ import {
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -31,7 +32,7 @@ const defaultStubs = {
function createComponent(options = {}) {
const {
- config = mockMilestoneToken,
+ config = { ...mockMilestoneToken, shouldSkipSort: true },
value = { data: '' },
active = false,
stubs = defaultStubs,
@@ -67,6 +68,27 @@ describe('MilestoneToken', () => {
describe('methods', () => {
describe('fetchMilestones', () => {
+ describe('when config.shouldSkipSort is true', () => {
+ beforeEach(() => {
+ wrapper.vm.config.shouldSkipSort = true;
+ });
+
+ afterEach(() => {
+ wrapper.vm.config.shouldSkipSort = false;
+ });
+ it('does not call sortMilestonesByDueDate', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchMilestones').mockResolvedValue({
+ data: mockMilestones,
+ });
+
+ wrapper.vm.fetchMilestones();
+
+ await waitForPromises();
+
+ expect(sortMilestonesByDueDate).toHaveBeenCalledTimes(0);
+ });
+ });
+
it('calls `config.fetchMilestones` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchMilestones');
@@ -76,10 +98,11 @@ describe('MilestoneToken', () => {
});
it('sets response to `milestones` when request is successful', () => {
+ wrapper.vm.config.shouldSkipSort = false;
+
jest.spyOn(wrapper.vm.config, 'fetchMilestones').mockResolvedValue({
data: mockMilestones,
});
-
wrapper.vm.fetchMilestones();
return waitForPromises().then(() => {
@@ -127,7 +150,7 @@ describe('MilestoneToken', () => {
milestones: mockMilestones,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('renders gl-filtered-search-token component', () => {
@@ -150,7 +173,7 @@ describe('MilestoneToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
@@ -169,7 +192,7 @@ describe('MilestoneToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
@@ -184,7 +207,7 @@ describe('MilestoneToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+ await nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
index b2f246a5985..8be21b35414 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
@@ -1,5 +1,6 @@
import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
@@ -31,7 +32,7 @@ describe('ReleaseToken', () => {
it('renders release value', async () => {
wrapper = createComponent({ value: { data: id } });
- await wrapper.vm.$nextTick();
+ await nextTick();
const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
diff --git a/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap b/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap
deleted file mode 100644
index 370b6eb01bc..00000000000
--- a/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap
+++ /dev/null
@@ -1,54 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`gfm_autocomplete/utils emojis config shows the emoji name and icon in the menu item 1`] = `"raised_hands <gl-emoji data-name=\\"raised_hands\\"></gl-emoji>"`;
-
-exports[`gfm_autocomplete/utils issues config shows the iid and title in the menu item within a project context 1`] = `"<small>123456</small> Project context issue title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
-
-exports[`gfm_autocomplete/utils issues config shows the reference and title in the menu item within a group context 1`] = `"<small>gitlab#987654</small> Group context issue title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
-
-exports[`gfm_autocomplete/utils labels config shows the title in the menu item 1`] = `
-"
- <span class=\\"dropdown-label-box\\" style=\\"background: #123456;\\"></span>
- bug &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"
-`;
-
-exports[`gfm_autocomplete/utils members config shows an avatar character, name, parent name, and count in the menu item for a group 1`] = `
-"
- <div class=\\"gl-display-flex gl-align-items-center\\">
- <div class=\\"gl-avatar gl-avatar-s32 gl-flex-shrink-0 gl-rounded-small
- gl-display-flex gl-align-items-center gl-justify-content-center\\" aria-hidden=\\"true\\">
- G</div>
- <div class=\\"gl-line-height-normal gl-ml-4\\">
- <div>1-1s &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt; (2)</div>
- <div class=\\"gl-text-gray-700\\">GitLab Support Team</div>
- </div>
-
- </div>
- "
-`;
-
-exports[`gfm_autocomplete/utils members config shows the avatar, name and username in the menu item for a user 1`] = `
-"
- <div class=\\"gl-display-flex gl-align-items-center\\">
- <img class=\\"gl-avatar gl-avatar-s32 gl-flex-shrink-0 gl-avatar-circle\\" src=\\"/uploads/-/system/user/avatar/123456/avatar.png\\" alt=\\"\\" />
- <div class=\\"gl-line-height-normal gl-ml-4\\">
- <div>My Name &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;</div>
- <div class=\\"gl-text-gray-700\\">@myusername</div>
- </div>
-
- </div>
- "
-`;
-
-exports[`gfm_autocomplete/utils merge requests config shows the iid and title in the menu item within a project context 1`] = `"<small>123456</small> Project context merge request title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
-
-exports[`gfm_autocomplete/utils merge requests config shows the reference and title in the menu item within a group context 1`] = `"<small>gitlab!456789</small> Group context merge request title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
-
-exports[`gfm_autocomplete/utils milestones config shows the title in the menu item 1`] = `"13.2 &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
-
-exports[`gfm_autocomplete/utils quick actions config shows the name, aliases, params and description in the menu item 1`] = `
-"<div>/unlabel <small>(or /remove_label)</small> <small>~label1 ~\\"label 2\\"</small></div>
- <div><small><em>Remove all or specific label(s)</em></small></div>"
-`;
-
-exports[`gfm_autocomplete/utils snippets config shows the id and title in the menu item 1`] = `"<small>123456</small> Snippet title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
diff --git a/spec/frontend/vue_shared/components/gfm_autocomplete/gfm_autocomplete_spec.js b/spec/frontend/vue_shared/components/gfm_autocomplete/gfm_autocomplete_spec.js
deleted file mode 100644
index b4002fdf4ec..00000000000
--- a/spec/frontend/vue_shared/components/gfm_autocomplete/gfm_autocomplete_spec.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import Tribute from '@gitlab/tributejs';
-import { shallowMount } from '@vue/test-utils';
-import GfmAutocomplete from '~/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue';
-
-describe('GfmAutocomplete', () => {
- let wrapper;
-
- describe('tribute', () => {
- const mentions = '/gitlab-org/gitlab-test/-/autocomplete_sources/members?type=Issue&type_id=1';
-
- beforeEach(() => {
- wrapper = shallowMount(GfmAutocomplete, {
- propsData: {
- dataSources: {
- mentions,
- },
- },
- slots: {
- default: ['<input/>'],
- },
- });
- });
-
- it('is set to tribute instance variable', () => {
- expect(wrapper.vm.tribute instanceof Tribute).toBe(true);
- });
-
- it('contains the slot input element', () => {
- wrapper.find('input').setValue('@');
-
- expect(wrapper.vm.tribute.current.element).toBe(wrapper.find('input').element);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js b/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js
deleted file mode 100644
index 7ec3fbd4e3b..00000000000
--- a/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js
+++ /dev/null
@@ -1,427 +0,0 @@
-import { escape, last } from 'lodash';
-import { GfmAutocompleteType, tributeConfig } from '~/vue_shared/components/gfm_autocomplete/utils';
-
-describe('gfm_autocomplete/utils', () => {
- describe('emojis config', () => {
- const emojisConfig = tributeConfig[GfmAutocompleteType.Emojis].config;
- const emoji = 'raised_hands';
-
- it('uses : as the trigger', () => {
- expect(emojisConfig.trigger).toBe(':');
- });
-
- it('searches using the emoji name', () => {
- expect(emojisConfig.lookup(emoji)).toBe(emoji);
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(emojisConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the emoji name and icon in the menu item', () => {
- expect(emojisConfig.menuItemTemplate({ original: emoji })).toMatchSnapshot();
- });
-
- it('inserts the emoji name on autocomplete selection', () => {
- expect(emojisConfig.selectTemplate({ original: emoji })).toBe(`:${emoji}:`);
- });
- });
-
- describe('issues config', () => {
- const issuesConfig = tributeConfig[GfmAutocompleteType.Issues].config;
- const groupContextIssue = {
- iid: 987654,
- reference: 'gitlab#987654',
- title: "Group context issue title <script>alert('hi')</script>",
- };
- const projectContextIssue = {
- id: null,
- iid: 123456,
- time_estimate: 0,
- title: "Project context issue title <script>alert('hi')</script>",
- };
-
- it('uses # as the trigger', () => {
- expect(issuesConfig.trigger).toBe('#');
- });
-
- it('searches using both the iid and title', () => {
- expect(issuesConfig.lookup(projectContextIssue)).toBe(
- `${projectContextIssue.iid}${projectContextIssue.title}`,
- );
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(issuesConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the reference and title in the menu item within a group context', () => {
- expect(issuesConfig.menuItemTemplate({ original: groupContextIssue })).toMatchSnapshot();
- });
-
- it('shows the iid and title in the menu item within a project context', () => {
- expect(issuesConfig.menuItemTemplate({ original: projectContextIssue })).toMatchSnapshot();
- });
-
- it('inserts the reference on autocomplete selection within a group context', () => {
- expect(issuesConfig.selectTemplate({ original: groupContextIssue })).toBe(
- groupContextIssue.reference,
- );
- });
-
- it('inserts the iid on autocomplete selection within a project context', () => {
- expect(issuesConfig.selectTemplate({ original: projectContextIssue })).toBe(
- `#${projectContextIssue.iid}`,
- );
- });
- });
-
- describe('labels config', () => {
- const labelsConfig = tributeConfig[GfmAutocompleteType.Labels].config;
- const labelsFilter = tributeConfig[GfmAutocompleteType.Labels].filterValues;
- const label = {
- color: '#123456',
- textColor: '#FFFFFF',
- title: `bug <script>alert('hi')</script>`,
- type: 'GroupLabel',
- };
- const singleWordLabel = {
- color: '#456789',
- textColor: '#DDD',
- title: `bug`,
- type: 'GroupLabel',
- };
- const numericalLabel = {
- color: '#abcdef',
- textColor: '#AAA',
- title: 123456,
- type: 'ProjectLabel',
- };
-
- it('uses ~ as the trigger', () => {
- expect(labelsConfig.trigger).toBe('~');
- });
-
- it('searches using `title`', () => {
- expect(labelsConfig.lookup).toBe('title');
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(labelsConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the title in the menu item', () => {
- expect(labelsConfig.menuItemTemplate({ original: label })).toMatchSnapshot();
- });
-
- it('inserts the title on autocomplete selection', () => {
- expect(labelsConfig.selectTemplate({ original: singleWordLabel })).toBe(
- `~${escape(singleWordLabel.title)}`,
- );
- });
-
- it('inserts the title enclosed with quotes on autocomplete selection when the title is numerical', () => {
- expect(labelsConfig.selectTemplate({ original: numericalLabel })).toBe(
- `~"${escape(numericalLabel.title)}"`,
- );
- });
-
- it('inserts the title enclosed with quotes on autocomplete selection when the title contains multiple words', () => {
- expect(labelsConfig.selectTemplate({ original: label })).toBe(`~"${escape(label.title)}"`);
- });
-
- describe('filter', () => {
- const collection = [label, singleWordLabel, { ...numericalLabel, set: true }];
-
- describe('/label quick action', () => {
- describe('when the line starts with `/label`', () => {
- it('shows labels that are not currently selected', () => {
- const fullText = '/label ~';
- const selectionStart = 8;
-
- expect(labelsFilter({ collection, fullText, selectionStart })).toEqual([
- collection[0],
- collection[1],
- ]);
- });
- });
-
- describe('when the line does not start with `/label`', () => {
- it('shows all labels', () => {
- const fullText = '~';
- const selectionStart = 1;
-
- expect(labelsFilter({ collection, fullText, selectionStart })).toEqual(collection);
- });
- });
- });
-
- describe('/unlabel quick action', () => {
- describe('when the line starts with `/unlabel`', () => {
- it('shows labels that are currently selected', () => {
- const fullText = '/unlabel ~';
- const selectionStart = 10;
-
- expect(labelsFilter({ collection, fullText, selectionStart })).toEqual([collection[2]]);
- });
- });
-
- describe('when the line does not start with `/unlabel`', () => {
- it('shows all labels', () => {
- const fullText = '~';
- const selectionStart = 1;
-
- expect(labelsFilter({ collection, fullText, selectionStart })).toEqual(collection);
- });
- });
- });
- });
- });
-
- describe('members config', () => {
- const membersConfig = tributeConfig[GfmAutocompleteType.Members].config;
- const membersFilter = tributeConfig[GfmAutocompleteType.Members].filterValues;
- const userMember = {
- type: 'User',
- username: 'myusername',
- name: "My Name <script>alert('hi')</script>",
- avatar_url: '/uploads/-/system/user/avatar/123456/avatar.png',
- availability: null,
- };
- const groupMember = {
- type: 'Group',
- username: 'gitlab-com/support/1-1s',
- name: "GitLab.com / GitLab Support Team / 1-1s <script>alert('hi')</script>",
- avatar_url: null,
- count: 2,
- mentionsDisabled: null,
- };
-
- it('uses @ as the trigger', () => {
- expect(membersConfig.trigger).toBe('@');
- });
-
- it('inserts the username on autocomplete selection', () => {
- expect(membersConfig.fillAttr).toBe('username');
- });
-
- it('searches using both the name and username for a user', () => {
- expect(membersConfig.lookup(userMember)).toBe(`${userMember.name}${userMember.username}`);
- });
-
- it('searches using only its own name and not its ancestors for a group', () => {
- expect(membersConfig.lookup(groupMember)).toBe(last(groupMember.name.split(' / ')));
- });
-
- it('limits the items in the autocomplete menu to 10', () => {
- expect(membersConfig.menuItemLimit).toBe(10);
- });
-
- it('shows the avatar, name and username in the menu item for a user', () => {
- expect(membersConfig.menuItemTemplate({ original: userMember })).toMatchSnapshot();
- });
-
- it('shows an avatar character, name, parent name, and count in the menu item for a group', () => {
- expect(membersConfig.menuItemTemplate({ original: groupMember })).toMatchSnapshot();
- });
-
- describe('filter', () => {
- const assignees = [userMember.username];
- const collection = [userMember, groupMember];
-
- describe('/assign quick action', () => {
- describe('when the line starts with `/assign`', () => {
- it('shows members that are not currently selected', () => {
- const fullText = '/assign @';
- const selectionStart = 9;
-
- expect(membersFilter({ assignees, collection, fullText, selectionStart })).toEqual([
- collection[1],
- ]);
- });
- });
-
- describe('when the line does not start with `/assign`', () => {
- it('shows all labels', () => {
- const fullText = '@';
- const selectionStart = 1;
-
- expect(membersFilter({ assignees, collection, fullText, selectionStart })).toEqual(
- collection,
- );
- });
- });
- });
-
- describe('/unassign quick action', () => {
- describe('when the line starts with `/unassign`', () => {
- it('shows members that are currently selected', () => {
- const fullText = '/unassign @';
- const selectionStart = 11;
-
- expect(membersFilter({ assignees, collection, fullText, selectionStart })).toEqual([
- collection[0],
- ]);
- });
- });
-
- describe('when the line does not start with `/unassign`', () => {
- it('shows all members', () => {
- const fullText = '@';
- const selectionStart = 1;
-
- expect(membersFilter({ assignees, collection, fullText, selectionStart })).toEqual(
- collection,
- );
- });
- });
- });
- });
- });
-
- describe('merge requests config', () => {
- const mergeRequestsConfig = tributeConfig[GfmAutocompleteType.MergeRequests].config;
- const groupContextMergeRequest = {
- iid: 456789,
- reference: 'gitlab!456789',
- title: "Group context merge request title <script>alert('hi')</script>",
- };
- const projectContextMergeRequest = {
- id: null,
- iid: 123456,
- time_estimate: 0,
- title: "Project context merge request title <script>alert('hi')</script>",
- };
-
- it('uses ! as the trigger', () => {
- expect(mergeRequestsConfig.trigger).toBe('!');
- });
-
- it('searches using both the iid and title', () => {
- expect(mergeRequestsConfig.lookup(projectContextMergeRequest)).toBe(
- `${projectContextMergeRequest.iid}${projectContextMergeRequest.title}`,
- );
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(mergeRequestsConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the reference and title in the menu item within a group context', () => {
- expect(
- mergeRequestsConfig.menuItemTemplate({ original: groupContextMergeRequest }),
- ).toMatchSnapshot();
- });
-
- it('shows the iid and title in the menu item within a project context', () => {
- expect(
- mergeRequestsConfig.menuItemTemplate({ original: projectContextMergeRequest }),
- ).toMatchSnapshot();
- });
-
- it('inserts the reference on autocomplete selection within a group context', () => {
- expect(mergeRequestsConfig.selectTemplate({ original: groupContextMergeRequest })).toBe(
- groupContextMergeRequest.reference,
- );
- });
-
- it('inserts the iid on autocomplete selection within a project context', () => {
- expect(mergeRequestsConfig.selectTemplate({ original: projectContextMergeRequest })).toBe(
- `!${projectContextMergeRequest.iid}`,
- );
- });
- });
-
- describe('milestones config', () => {
- const milestonesConfig = tributeConfig[GfmAutocompleteType.Milestones].config;
- const milestone = {
- id: null,
- iid: 49,
- title: "13.2 <script>alert('hi')</script>",
- };
-
- it('uses % as the trigger', () => {
- expect(milestonesConfig.trigger).toBe('%');
- });
-
- it('searches using the title', () => {
- expect(milestonesConfig.lookup).toBe('title');
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(milestonesConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the title in the menu item', () => {
- expect(milestonesConfig.menuItemTemplate({ original: milestone })).toMatchSnapshot();
- });
-
- it('inserts the title on autocomplete selection', () => {
- expect(milestonesConfig.selectTemplate({ original: milestone })).toBe(
- `%"${escape(milestone.title)}"`,
- );
- });
- });
-
- describe('quick actions config', () => {
- const quickActionsConfig = tributeConfig[GfmAutocompleteType.QuickActions].config;
- const quickAction = {
- name: 'unlabel',
- aliases: ['remove_label'],
- description: 'Remove all or specific label(s)',
- warning: '',
- icon: '',
- params: ['~label1 ~"label 2"'],
- };
-
- it('uses / as the trigger', () => {
- expect(quickActionsConfig.trigger).toBe('/');
- });
-
- it('inserts the name on autocomplete selection', () => {
- expect(quickActionsConfig.fillAttr).toBe('name');
- });
-
- it('searches using both the name and aliases', () => {
- expect(quickActionsConfig.lookup(quickAction)).toBe(
- `${quickAction.name}${quickAction.aliases.join(', /')}`,
- );
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(quickActionsConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the name, aliases, params and description in the menu item', () => {
- expect(quickActionsConfig.menuItemTemplate({ original: quickAction })).toMatchSnapshot();
- });
- });
-
- describe('snippets config', () => {
- const snippetsConfig = tributeConfig[GfmAutocompleteType.Snippets].config;
- const snippet = {
- id: 123456,
- title: "Snippet title <script>alert('hi')</script>",
- };
-
- it('uses $ as the trigger', () => {
- expect(snippetsConfig.trigger).toBe('$');
- });
-
- it('inserts the id on autocomplete selection', () => {
- expect(snippetsConfig.fillAttr).toBe('id');
- });
-
- it('searches using both the id and title', () => {
- expect(snippetsConfig.lookup(snippet)).toBe(`${snippet.id}${snippet.title}`);
- });
-
- it('limits the number of rendered items to 100', () => {
- expect(snippetsConfig.menuItemLimit).toBe(100);
- });
-
- it('shows the id and title in the menu item', () => {
- expect(snippetsConfig.menuItemTemplate({ original: snippet })).toMatchSnapshot();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/gl_countdown_spec.js b/spec/frontend/vue_shared/components/gl_countdown_spec.js
index 82d18c7fd3f..0d1d42082ab 100644
--- a/spec/frontend/vue_shared/components/gl_countdown_spec.js
+++ b/spec/frontend/vue_shared/components/gl_countdown_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
@@ -17,38 +17,34 @@ describe('GlCountdown', () => {
});
describe('when there is time remaining', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
vm = mountComponent(Component, {
endDateString: '2000-01-01T01:02:03Z',
});
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
it('displays remaining time', () => {
expect(vm.$el.textContent).toContain('01:02:03');
});
- it('updates remaining time', (done) => {
+ it('updates remaining time', async () => {
now = '2000-01-01T00:00:01Z';
jest.advanceTimersByTime(1000);
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.textContent).toContain('01:02:02');
- done();
- })
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.textContent).toContain('01:02:02');
});
});
describe('when there is no time remaining', () => {
- beforeEach((done) => {
+ beforeEach(async () => {
vm = mountComponent(Component, {
endDateString: '1900-01-01T00:00:00Z',
});
- Vue.nextTick().then(done).catch(done.fail);
+ await nextTick();
});
it('displays 00:00:00', () => {
diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
index b837a998cd6..c0a6588833e 100644
--- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
+++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
@@ -1,6 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
@@ -118,7 +118,7 @@ describe('GlModalVuex', () => {
expect(actions.hide).toHaveBeenCalledTimes(1);
});
- it('calls bootstrap show when isVisible changes', (done) => {
+ it('calls bootstrap show when isVisible changes', async () => {
state.isVisible = false;
factory();
@@ -126,16 +126,11 @@ describe('GlModalVuex', () => {
state.isVisible = true;
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, TEST_MODAL_ID);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, TEST_MODAL_ID);
});
- it('calls bootstrap hide when isVisible changes', (done) => {
+ it('calls bootstrap hide when isVisible changes', async () => {
state.isVisible = true;
factory();
@@ -143,13 +138,8 @@ describe('GlModalVuex', () => {
state.isVisible = false;
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(rootEmit).toHaveBeenCalledWith(BV_HIDE_MODAL, TEST_MODAL_ID);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(rootEmit).toHaveBeenCalledWith(BV_HIDE_MODAL, TEST_MODAL_ID);
});
it.each(['ok', 'cancel'])(
diff --git a/spec/frontend/vue_shared/components/help_popover_spec.js b/spec/frontend/vue_shared/components/help_popover_spec.js
index 30c6fa04032..597fb63d95c 100644
--- a/spec/frontend/vue_shared/components/help_popover_spec.js
+++ b/spec/frontend/vue_shared/components/help_popover_spec.js
@@ -9,59 +9,117 @@ describe('HelpPopover', () => {
const findQuestionButton = () => wrapper.find(GlButton);
const findPopover = () => wrapper.find(GlPopover);
- const buildWrapper = (options = {}) => {
+
+ const createComponent = ({ props, ...opts } = {}) => {
wrapper = mount(HelpPopover, {
propsData: {
options: {
title,
content,
- ...options,
},
+ ...props,
},
+ ...opts,
});
};
- beforeEach(() => {
- buildWrapper();
- });
-
afterEach(() => {
wrapper.destroy();
});
- it('renders a link button with an icon question', () => {
- expect(findQuestionButton().props()).toMatchObject({
- icon: 'question',
- variant: 'link',
+ describe('with title and content', () => {
+ beforeEach(() => {
+ createComponent();
});
- });
- it('renders popover that uses the question button as target', () => {
- expect(findPopover().props().target()).toBe(findQuestionButton().vm.$el);
- });
+ it('renders a link button with an icon question', () => {
+ expect(findQuestionButton().props()).toMatchObject({
+ icon: 'question',
+ variant: 'link',
+ });
+ });
- it('allows rendering title with HTML tags', () => {
- expect(findPopover().find('strong').exists()).toBe(true);
- });
+ it('renders popover that uses the question button as target', () => {
+ expect(findPopover().props().target()).toBe(findQuestionButton().vm.$el);
+ });
- it('allows rendering content with HTML tags', () => {
- expect(findPopover().find('b').exists()).toBe(true);
+ it('shows title and content', () => {
+ expect(findPopover().html()).toContain(title);
+ expect(findPopover().html()).toContain(content);
+ });
+
+ it('allows rendering title with HTML tags', () => {
+ expect(findPopover().find('strong').exists()).toBe(true);
+ });
+
+ it('allows rendering content with HTML tags', () => {
+ expect(findPopover().find('b').exists()).toBe(true);
+ });
});
describe('without title', () => {
- it('does not render title', () => {
- buildWrapper({ title: null });
+ beforeEach(() => {
+ createComponent({
+ props: {
+ options: {
+ title: null,
+ content,
+ },
+ },
+ });
+ });
+
+ it('does not show title', () => {
+ expect(findPopover().html()).not.toContain(title);
+ });
- expect(findPopover().find('span').exists()).toBe(false);
+ it('shows content', () => {
+ expect(findPopover().html()).toContain(content);
});
});
- it('binds other popover options to the popover instance', () => {
+ describe('with other options', () => {
const placement = 'bottom';
- wrapper.destroy();
- buildWrapper({ placement });
+ beforeEach(() => {
+ createComponent({
+ props: {
+ options: {
+ placement,
+ },
+ },
+ });
+ });
+
+ it('options bind to the popover', () => {
+ expect(findPopover().props().placement).toBe(placement);
+ });
+ });
+
+ describe('with custom slots', () => {
+ const titleSlot = '<h1>title</h1>';
+ const defaultSlot = '<strong>content</strong>';
- expect(findPopover().props().placement).toBe(placement);
+ beforeEach(() => {
+ createComponent({
+ slots: {
+ title: titleSlot,
+ default: defaultSlot,
+ },
+ });
+ });
+
+ it('shows title slot', () => {
+ expect(findPopover().html()).toContain(titleSlot);
+ });
+
+ it('shows default content slot', () => {
+ expect(findPopover().html()).toContain(defaultSlot);
+ });
+
+ it('overrides title and content from options', () => {
+ expect(findPopover().html()).not.toContain(title);
+ expect(findPopover().html()).toContain(content);
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/local_storage_sync_spec.js b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
index 4c5a0c1e601..dac633fe6c8 100644
--- a/spec/frontend/vue_shared/components/local_storage_sync_spec.js
+++ b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
describe('Local Storage Sync', () => {
@@ -49,7 +50,7 @@ describe('Local Storage Sync', () => {
it.each('foo', 3, true, ['foo', 'bar'], { foo: 'bar' })(
'saves updated value to localStorage',
- (newValue) => {
+ async (newValue) => {
createComponent({
props: {
storageKey,
@@ -59,9 +60,8 @@ describe('Local Storage Sync', () => {
wrapper.setProps({ value: newValue });
- return wrapper.vm.$nextTick().then(() => {
- expect(localStorage.getItem(storageKey)).toBe(String(newValue));
- });
+ await nextTick();
+ expect(localStorage.getItem(storageKey)).toBe(String(newValue));
},
);
@@ -109,7 +109,7 @@ describe('Local Storage Sync', () => {
expect(localStorage.getItem(storageKey)).toBe(savedValue);
});
- it('updating the value updates localStorage', () => {
+ it('updating the value updates localStorage', async () => {
createComponent({
props: {
storageKey,
@@ -122,9 +122,8 @@ describe('Local Storage Sync', () => {
value: newValue,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(localStorage.getItem(storageKey)).toBe(newValue);
- });
+ await nextTick();
+ expect(localStorage.getItem(storageKey)).toBe(newValue);
});
it('persists the value by default', async () => {
@@ -137,7 +136,7 @@ describe('Local Storage Sync', () => {
});
wrapper.setProps({ value: persistedValue });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(localStorage.getItem(storageKey)).toBe(persistedValue);
});
@@ -151,7 +150,7 @@ describe('Local Storage Sync', () => {
});
wrapper.setProps({ persist: false, value: notPersistedValue });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(localStorage.getItem(storageKey)).not.toBe(notPersistedValue);
});
});
@@ -172,7 +171,7 @@ describe('Local Storage Sync', () => {
${{ foo: 'bar' }} | ${'{"foo":"bar"}'}
`('given $value', ({ value, serializedValue }) => {
describe('is a new value', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createComponent({
props: {
storageKey,
@@ -183,7 +182,7 @@ describe('Local Storage Sync', () => {
wrapper.setProps({ value });
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('serializes the value correctly to localStorage', () => {
@@ -253,7 +252,7 @@ describe('Local Storage Sync', () => {
value,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(localStorage.getItem(storageKey)).toBe(value);
@@ -261,7 +260,7 @@ describe('Local Storage Sync', () => {
clear: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(localStorage.getItem(storageKey)).toBe(null);
});
diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js
index 0d90ca7f1f6..c7ad47b6ef7 100644
--- a/spec/frontend/vue_shared/components/markdown/field_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_spec.js
@@ -1,10 +1,10 @@
-import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
const markdownPreviewPath = `${TEST_HOST}/preview`;
const markdownDocsPath = `${TEST_HOST}/docs`;
@@ -12,8 +12,8 @@ const textareaValue = 'testing\n123';
const uploadsPath = 'test/uploads';
function assertMarkdownTabs(isWrite, writeLink, previewLink, wrapper) {
- expect(writeLink.element.parentNode.classList.contains('active')).toBe(isWrite);
- expect(previewLink.element.parentNode.classList.contains('active')).toBe(!isWrite);
+ expect(writeLink.element.children[0].classList.contains('active')).toBe(isWrite);
+ expect(previewLink.element.children[0].classList.contains('active')).toBe(!isWrite);
expect(wrapper.find('.md-preview-holder').element.style.display).toBe(isWrite ? 'none' : '');
}
@@ -29,14 +29,13 @@ describe('Markdown field component', () => {
afterEach(() => {
subject.destroy();
- subject = null;
axiosMock.restore();
});
function createSubject(lines = []) {
// We actually mount a wrapper component so that we can force Vue to rerender classes in order to test a regression
// caused by mixing Vanilla JS and Vue.
- subject = mount(
+ subject = mountExtended(
{
components: {
MarkdownField,
@@ -63,12 +62,17 @@ describe('Markdown field component', () => {
textareaValue,
lines,
},
+ provide: {
+ glFeatures: {
+ contactsAutocomplete: true,
+ },
+ },
},
);
}
- const getPreviewLink = () => subject.find('.nav-links .js-preview-link');
- const getWriteLink = () => subject.find('.nav-links .js-write-link');
+ const getPreviewLink = () => subject.findByTestId('preview-tab');
+ const getWriteLink = () => subject.findByTestId('write-tab');
const getMarkdownButton = () => subject.find('.js-md');
const getAllMarkdownButtons = () => subject.findAll('.js-md');
const getVideo = () => subject.find('video');
@@ -100,115 +104,100 @@ describe('Markdown field component', () => {
axiosMock.onPost(markdownPreviewPath).reply(200, { body: previewHTML });
});
- it('sets preview link as active', () => {
+ it('sets preview link as active', async () => {
previewLink = getPreviewLink();
- previewLink.trigger('click');
+ previewLink.vm.$emit('click', { target: {} });
- return subject.vm.$nextTick().then(() => {
- expect(previewLink.element.parentNode.classList.contains('active')).toBeTruthy();
- });
+ await nextTick();
+ expect(previewLink.element.children[0].classList.contains('active')).toBe(true);
});
- it('shows preview loading text', () => {
+ it('shows preview loading text', async () => {
previewLink = getPreviewLink();
- previewLink.trigger('click');
+ previewLink.vm.$emit('click', { target: {} });
- return subject.vm.$nextTick(() => {
- expect(subject.find('.md-preview-holder').element.textContent.trim()).toContain(
- 'Loading…',
- );
- });
+ await nextTick();
+ expect(subject.find('.md-preview-holder').element.textContent.trim()).toContain('Loading…');
});
- it('renders markdown preview and GFM', () => {
+ it('renders markdown preview and GFM', async () => {
const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
previewLink = getPreviewLink();
- previewLink.trigger('click');
+ previewLink.vm.$emit('click', { target: {} });
- return axios.waitFor(markdownPreviewPath).then(() => {
- expect(subject.find('.md-preview-holder').element.innerHTML).toContain(previewHTML);
- expect(renderGFMSpy).toHaveBeenCalled();
- });
+ await axios.waitFor(markdownPreviewPath);
+ expect(subject.find('.md-preview-holder').element.innerHTML).toContain(previewHTML);
+ expect(renderGFMSpy).toHaveBeenCalled();
});
- it('calls video.pause() on comment input when isSubmitting is changed to true', () => {
+ it('calls video.pause() on comment input when isSubmitting is changed to true', async () => {
previewLink = getPreviewLink();
- previewLink.trigger('click');
+ previewLink.vm.$emit('click', { target: {} });
- let callPause;
+ await axios.waitFor(markdownPreviewPath);
+ const video = getVideo();
+ const callPause = jest.spyOn(video.element, 'pause').mockImplementation(() => true);
- return axios
- .waitFor(markdownPreviewPath)
- .then(() => {
- const video = getVideo();
- callPause = jest.spyOn(video.element, 'pause').mockImplementation(() => true);
+ subject.setProps({ isSubmitting: true });
- subject.setProps({ isSubmitting: true });
-
- return subject.vm.$nextTick();
- })
- .then(() => {
- expect(callPause).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(callPause).toHaveBeenCalled();
});
it('clicking already active write or preview link does nothing', async () => {
writeLink = getWriteLink();
previewLink = getPreviewLink();
- writeLink.trigger('click');
- await subject.vm.$nextTick();
+ writeLink.vm.$emit('click', { target: {} });
+ await nextTick();
assertMarkdownTabs(true, writeLink, previewLink, subject);
- writeLink.trigger('click');
- await subject.vm.$nextTick();
+ writeLink.vm.$emit('click', { target: {} });
+ await nextTick();
assertMarkdownTabs(true, writeLink, previewLink, subject);
- previewLink.trigger('click');
- await subject.vm.$nextTick();
+ previewLink.vm.$emit('click', { target: {} });
+ await nextTick();
assertMarkdownTabs(false, writeLink, previewLink, subject);
- previewLink.trigger('click');
- await subject.vm.$nextTick();
+ previewLink.vm.$emit('click', { target: {} });
+ await nextTick();
assertMarkdownTabs(false, writeLink, previewLink, subject);
});
});
describe('markdown buttons', () => {
- it('converts single words', () => {
+ it('converts single words', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 7);
const markdownButton = getMarkdownButton();
markdownButton.trigger('click');
- return subject.vm.$nextTick(() => {
- expect(textarea.value).toContain('**testing**');
- });
+ await nextTick();
+ expect(textarea.value).toContain('**testing**');
});
- it('converts a line', () => {
+ it('converts a line', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 0);
const markdownButton = getAllMarkdownButtons().wrappers[5];
markdownButton.trigger('click');
- return subject.vm.$nextTick(() => {
- expect(textarea.value).toContain('- testing');
- });
+ await nextTick();
+ expect(textarea.value).toContain('- testing');
});
- it('converts multiple lines', () => {
+ it('converts multiple lines', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 50);
const markdownButton = getAllMarkdownButtons().wrappers[5];
markdownButton.trigger('click');
- return subject.vm.$nextTick(() => {
- expect(textarea.value).toContain('- testing\n- 123');
- });
+ await nextTick();
+ expect(textarea.value).toContain('- testing\n- 123');
});
});
@@ -229,7 +218,7 @@ describe('Markdown field component', () => {
// Do something to trigger rerendering the class
subject.setProps({ wrapperClasses: 'foo' });
- await subject.vm.$nextTick();
+ await nextTick();
});
it('should have rerendered classes and kept gfm-form', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index fec6abc9639..93ce3935fab 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -1,20 +1,25 @@
-import { shallowMount } from '@vue/test-utils';
import $ from 'jquery';
+import { nextTick } from 'vue';
+import { GlTabs } from '@gitlab/ui';
import HeaderComponent from '~/vue_shared/components/markdown/header.vue';
import ToolbarButton from '~/vue_shared/components/markdown/toolbar_button.vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('Markdown field header component', () => {
let wrapper;
const createWrapper = (props) => {
- wrapper = shallowMount(HeaderComponent, {
+ wrapper = shallowMountExtended(HeaderComponent, {
propsData: {
previewMarkdown: false,
...props,
},
+ stubs: { GlTabs },
});
};
+ const findWriteTab = () => wrapper.findByTestId('write-tab');
+ const findPreviewTab = () => wrapper.findByTestId('preview-tab');
const findToolbarButtons = () => wrapper.findAll(ToolbarButton);
const findToolbarButtonByProp = (prop, value) =>
findToolbarButtons()
@@ -33,7 +38,6 @@ describe('Markdown field header component', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('markdown header buttons', () => {
@@ -74,30 +78,29 @@ describe('Markdown field header component', () => {
});
});
- it('renders `write` link as active when previewMarkdown is false', () => {
- expect(wrapper.find('li:nth-child(1)').classes()).toContain('active');
+ it('activates `write` tab when previewMarkdown is false', () => {
+ expect(findWriteTab().attributes('active')).toBe('true');
+ expect(findPreviewTab().attributes('active')).toBeUndefined();
});
- it('renders `preview` link as active when previewMarkdown is true', () => {
+ it('activates `preview` tab when previewMarkdown is true', () => {
createWrapper({ previewMarkdown: true });
- expect(wrapper.find('li:nth-child(2)').classes()).toContain('active');
+ expect(findWriteTab().attributes('active')).toBeUndefined();
+ expect(findPreviewTab().attributes('active')).toBe('true');
});
- it('emits toggle markdown event when clicking preview', () => {
- wrapper.find('.js-preview-link').trigger('click');
+ it('emits toggle markdown event when clicking preview tab', async () => {
+ const eventData = { target: {} };
+ findPreviewTab().vm.$emit('click', eventData);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.emitted('preview-markdown').length).toEqual(1);
+ await nextTick();
+ expect(wrapper.emitted('preview-markdown').length).toEqual(1);
- wrapper.find('.js-write-link').trigger('click');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('write-markdown').length).toEqual(1);
- });
+ findWriteTab().vm.$emit('click', eventData);
+
+ await nextTick();
+ expect(wrapper.emitted('write-markdown').length).toEqual(1);
});
it('does not emit toggle markdown event when triggered from another form', () => {
@@ -112,12 +115,10 @@ describe('Markdown field header component', () => {
});
it('blurs preview link after click', () => {
- const link = wrapper.find('li:nth-child(2) button');
- jest.spyOn(HTMLElement.prototype, 'blur').mockImplementation();
-
- link.trigger('click');
+ const target = { blur: jest.fn() };
+ findPreviewTab().vm.$emit('click', { target });
- expect(link.element.blur).toHaveBeenCalled();
+ expect(target.blur).toHaveBeenCalled();
});
it('renders markdown table template', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
index 9bc2aad1895..9944267cf24 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ApplySuggestion from '~/vue_shared/components/markdown/apply_suggestion.vue';
import SuggestionDiffHeader from '~/vue_shared/components/markdown/suggestion_diff_header.vue';
@@ -103,15 +104,14 @@ describe('Suggestion Diff component', () => {
expect(wrapper.text()).toContain('Applying suggestion...');
});
- it('when callback of apply is called, hides loading', () => {
+ it('when callback of apply is called, hides loading', async () => {
const [callback] = wrapper.emitted().apply[0];
callback();
- return wrapper.vm.$nextTick().then(() => {
- expect(findApplyButton().exists()).toBe(true);
- expect(findLoading().exists()).toBe(false);
- });
+ await nextTick();
+ expect(findApplyButton().exists()).toBe(true);
+ expect(findLoading().exists()).toBe(false);
});
});
diff --git a/spec/frontend/vue_shared/components/markdown/suggestions_spec.js b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
index 6fcac2df0b6..8f4235cfe41 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import SuggestionsComponent from '~/vue_shared/components/markdown/suggestions.vue';
const MOCK_DATA = {
@@ -51,7 +51,7 @@ describe('Suggestion component', () => {
let vm;
let diffTable;
- beforeEach((done) => {
+ beforeEach(async () => {
const Component = Vue.extend(SuggestionsComponent);
vm = new Component({
@@ -62,7 +62,7 @@ describe('Suggestion component', () => {
jest.spyOn(vm, 'renderSuggestions').mockImplementation(() => {});
vm.renderSuggestions();
- Vue.nextTick(done);
+ await nextTick();
});
describe('mounted', () => {
diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
index adb72c3ef85..b57efc88d57 100644
--- a/spec/frontend/vue_shared/components/modal_copy_button_spec.js
+++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
@@ -1,4 +1,5 @@
import { shallowMount, createWrapper } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
@@ -20,7 +21,7 @@ describe('modal copy button', () => {
});
describe('clipboard', () => {
- it('should fire a `success` event on click', () => {
+ it('should fire a `success` event on click', async () => {
const root = createWrapper(wrapper.vm.$root);
document.execCommand = jest.fn(() => true);
window.getSelection = jest.fn(() => ({
@@ -29,20 +30,18 @@ describe('modal copy button', () => {
}));
wrapper.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().success).not.toBeEmpty();
- expect(document.execCommand).toHaveBeenCalledWith('copy');
- expect(root.emitted(BV_HIDE_TOOLTIP)).toEqual([['test-id']]);
- });
+ await nextTick();
+ expect(wrapper.emitted().success).not.toBeEmpty();
+ expect(document.execCommand).toHaveBeenCalledWith('copy');
+ expect(root.emitted(BV_HIDE_TOOLTIP)).toEqual([['test-id']]);
});
- it("should propagate the clipboard error event if execCommand doesn't work", () => {
+ it("should propagate the clipboard error event if execCommand doesn't work", async () => {
document.execCommand = jest.fn(() => false);
wrapper.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().error).not.toBeEmpty();
- expect(document.execCommand).toHaveBeenCalledWith('copy');
- });
+ await nextTick();
+ expect(wrapper.emitted().error).not.toBeEmpty();
+ expect(document.execCommand).toHaveBeenCalledWith('copy');
});
});
});
diff --git a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
deleted file mode 100644
index 566ca1817f2..00000000000
--- a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { GlDropdown } from '@gitlab/ui';
-import { getByText } from '@testing-library/dom';
-import { shallowMount } from '@vue/test-utils';
-import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
-
-describe('MultiSelectDropdown Component', () => {
- it('renders items slot', () => {
- const wrapper = shallowMount(MultiSelectDropdown, {
- propsData: {
- text: '',
- headerText: '',
- },
- slots: {
- items: '<p>Test</p>',
- },
- });
- expect(getByText(wrapper.element, 'Test')).toBeDefined();
- });
-
- it('renders search slot', () => {
- const wrapper = shallowMount(MultiSelectDropdown, {
- propsData: {
- text: '',
- headerText: '',
- },
- slots: {
- search: '<p>Search</p>',
- },
- stubs: {
- GlDropdown,
- },
- });
- expect(getByText(wrapper.element, 'Search')).toBeDefined();
- });
-});
diff --git a/spec/frontend/vue_shared/components/namespace_select/mock_data.js b/spec/frontend/vue_shared/components/namespace_select/mock_data.js
index c9d96672e85..cfd521c67cb 100644
--- a/spec/frontend/vue_shared/components/namespace_select/mock_data.js
+++ b/spec/frontend/vue_shared/components/namespace_select/mock_data.js
@@ -1,11 +1,6 @@
-export const group = [
+export const groupNamespaces = [
{ id: 1, name: 'Group 1', humanName: 'Group 1' },
{ id: 2, name: 'Subgroup 1', humanName: 'Group 1 / Subgroup 1' },
];
-export const user = [{ id: 3, name: 'User namespace 1', humanName: 'User namespace 1' }];
-
-export const namespaces = {
- group,
- user,
-};
+export const userNamespaces = [{ id: 3, name: 'User namespace 1', humanName: 'User namespace 1' }];
diff --git a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
index 8f07f63993d..c11b20a692e 100644
--- a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
+++ b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
@@ -1,9 +1,15 @@
-import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import NamespaceSelect, {
i18n,
+ EMPTY_NAMESPACE_ID,
} from '~/vue_shared/components/namespace_select/namespace_select.vue';
-import { user, group, namespaces } from './mock_data';
+import { userNamespaces, groupNamespaces } from './mock_data';
+
+const FLAT_NAMESPACES = [...groupNamespaces, ...userNamespaces];
+const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
+const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
describe('Namespace Select', () => {
let wrapper;
@@ -11,71 +17,115 @@ describe('Namespace Select', () => {
const createComponent = (props = {}) =>
shallowMountExtended(NamespaceSelect, {
propsData: {
- data: namespaces,
+ userNamespaces,
+ groupNamespaces,
...props,
},
+ stubs: {
+ // We have to "full" mount GlDropdown so that slot children will render
+ GlDropdown,
+ },
});
const wrappersText = (arr) => arr.wrappers.map((w) => w.text());
- const flatNamespaces = () => [...group, ...user];
const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDropdownAttributes = (attr) => findDropdown().attributes(attr);
- const selectedDropdownItemText = () => findDropdownAttributes('text');
+ const findDropdownText = () => findDropdown().props('text');
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findDropdownItemsTexts = () => findDropdownItems().wrappers.map((x) => x.text());
const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
-
- beforeEach(() => {
- wrapper = createComponent();
- });
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const search = (term) => findSearchBox().vm.$emit('input', term);
afterEach(() => {
wrapper.destroy();
});
- it('renders the dropdown', () => {
- expect(findDropdown().exists()).toBe(true);
- });
+ describe('default', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
- it('renders each dropdown item', () => {
- const items = findDropdownItems().wrappers;
- expect(items).toHaveLength(flatNamespaces().length);
- });
+ it('renders the dropdown', () => {
+ expect(findDropdown().exists()).toBe(true);
+ });
- it('renders the human name for each item', () => {
- const dropdownItems = wrappersText(findDropdownItems());
- const flatNames = flatNamespaces().map(({ humanName }) => humanName);
- expect(dropdownItems).toEqual(flatNames);
- });
+ it('renders each dropdown item', () => {
+ expect(findDropdownItemsTexts()).toEqual(FLAT_NAMESPACES.map((x) => x.humanName));
+ });
+
+ it('renders default dropdown text', () => {
+ expect(findDropdownText()).toBe(i18n.DEFAULT_TEXT);
+ });
+
+ it('splits group and user namespaces', () => {
+ const headers = findSectionHeaders();
+ expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
+ });
- it('sets the initial dropdown text', () => {
- expect(selectedDropdownItemText()).toBe(i18n.DEFAULT_TEXT);
+ it('does not render wrapper as full width', () => {
+ expect(findDropdown().attributes('block')).toBeUndefined();
+ });
});
- it('splits group and user namespaces', () => {
- const headers = findSectionHeaders();
- expect(headers).toHaveLength(2);
- expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
+ it('with defaultText, it overrides dropdown text', () => {
+ const textOverride = 'Select an option';
+
+ wrapper = createComponent({ defaultText: textOverride });
+
+ expect(findDropdownText()).toBe(textOverride);
});
- it('sets the dropdown to full width', () => {
- expect(findDropdownAttributes('block')).toBeUndefined();
+ it('with includeHeaders=false, hides group/user headers', () => {
+ wrapper = createComponent({ includeHeaders: false });
+
+ expect(findSectionHeaders()).toHaveLength(0);
+ });
+ it('with fullWidth=true, sets the dropdown to full width', () => {
wrapper = createComponent({ fullWidth: true });
- expect(findDropdownAttributes('block')).not.toBeUndefined();
- expect(findDropdownAttributes('block')).toBe('true');
+ expect(findDropdown().attributes('block')).toBe('true');
+ });
+
+ describe('with search', () => {
+ it.each`
+ term | includeEmptyNamespace | expectedItems
+ ${''} | ${false} | ${[...groupNamespaces, ...userNamespaces]}
+ ${'sub'} | ${false} | ${[groupNamespaces[1]]}
+ ${'User'} | ${false} | ${[...userNamespaces]}
+ ${'User'} | ${true} | ${[...userNamespaces]}
+ ${'namespace'} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...userNamespaces]}
+ `(
+ 'with term=$term and includeEmptyNamespace=$includeEmptyNamespace, should show $expectedItems.length',
+ async ({ term, includeEmptyNamespace, expectedItems }) => {
+ wrapper = createComponent({
+ includeEmptyNamespace,
+ emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
+ });
+
+ search(term);
+
+ await nextTick();
+
+ const expected = expectedItems.map((x) => x.humanName);
+
+ expect(findDropdownItemsTexts()).toEqual(expected);
+ },
+ );
});
describe('with a selected namespace', () => {
const selectedGroupIndex = 1;
- const selectedItem = group[selectedGroupIndex];
+ const selectedItem = groupNamespaces[selectedGroupIndex];
beforeEach(() => {
+ wrapper = createComponent();
+
findDropdownItems().at(selectedGroupIndex).vm.$emit('click');
});
it('sets the dropdown text', () => {
- expect(selectedDropdownItemText()).toBe(selectedItem.humanName);
+ expect(findDropdownText()).toBe(selectedItem.humanName);
});
it('emits the `select` event when a namespace is selected', () => {
@@ -83,4 +133,37 @@ describe('Namespace Select', () => {
expect(wrapper.emitted('select')).toEqual([args]);
});
});
+
+ describe('with an empty namespace option', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ includeEmptyNamespace: true,
+ emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
+ });
+ });
+
+ it('includes the empty namespace', () => {
+ const first = findDropdownItems().at(0);
+
+ expect(first.text()).toBe(EMPTY_NAMESPACE_TITLE);
+ });
+
+ it('emits the `select` event when a namespace is selected', () => {
+ findDropdownItems().at(0).vm.$emit('click');
+
+ expect(wrapper.emitted('select')).toEqual([[EMPTY_NAMESPACE_ITEM]]);
+ });
+
+ it.each`
+ desc | term | shouldShow
+ ${'should hide empty option'} | ${'group'} | ${false}
+ ${'should show empty option'} | ${'Empty'} | ${true}
+ `('when search for $term, $desc', async ({ term, shouldShow }) => {
+ search(term);
+
+ await nextTick();
+
+ expect(findDropdownItemsTexts().includes(EMPTY_NAMESPACE_TITLE)).toBe(shouldShow);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
index 835759b1f20..accbf14572d 100644
--- a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
+++ b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
@@ -1,5 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
describe('Issue Warning Component', () => {
@@ -64,7 +65,7 @@ describe('Issue Warning Component', () => {
expect(findConfidentialBlock().exists()).toBe(true);
expect(findConfidentialBlock().element).toMatchSnapshot();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findConfidentialBlock(wrapper).text()).toContain('This is a confidential issue.');
});
@@ -154,15 +155,15 @@ describe('Issue Warning Component', () => {
noteableType: 'Epic',
});
- await wrapperLocked.vm.$nextTick();
+ await nextTick();
expect(findLockedBlock(wrapperLocked).text()).toContain('This epic is locked.');
- await wrapperConfidential.vm.$nextTick();
+ await nextTick();
expect(findConfidentialBlock(wrapperConfidential).text()).toContain(
'This is a confidential epic.',
);
- await wrapperLockedAndConfidential.vm.$nextTick();
+ await nextTick();
expect(findLockedAndConfidentialBlock(wrapperLockedAndConfidential).text()).toContain(
'This epic is confidential and locked.',
);
@@ -179,15 +180,15 @@ describe('Issue Warning Component', () => {
noteableType: 'MergeRequest',
});
- await wrapperLocked.vm.$nextTick();
+ await nextTick();
expect(findLockedBlock(wrapperLocked).text()).toContain('This merge request is locked.');
- await wrapperConfidential.vm.$nextTick();
+ await nextTick();
expect(findConfidentialBlock(wrapperConfidential).text()).toContain(
'This is a confidential merge request.',
);
- await wrapperLockedAndConfidential.vm.$nextTick();
+ await nextTick();
expect(findLockedAndConfidentialBlock(wrapperLockedAndConfidential).text()).toContain(
'This merge request is confidential and locked.',
);
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index b330b4f5657..36050a42da7 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlBadge, GlPagination, GlTabs, GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Tracking from '~/tracking';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
@@ -219,21 +220,21 @@ describe('AlertManagementEmptyState', () => {
it('returns prevPage button', async () => {
findPagination().vm.$emit('input', 3);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPagination().findAll('.page-item').at(0).text()).toBe('Prev');
});
it('returns prevPage number', async () => {
findPagination().vm.$emit('input', 3);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.previousPage).toBe(2);
});
it('returns 0 when it is the first page', async () => {
findPagination().vm.$emit('input', 1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.previousPage).toBe(0);
});
});
@@ -242,7 +243,7 @@ describe('AlertManagementEmptyState', () => {
it('returns nextPage button', async () => {
findPagination().vm.$emit('input', 3);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findPagination().findAll('.page-item').at(1).text()).toBe('Next');
});
@@ -257,14 +258,14 @@ describe('AlertManagementEmptyState', () => {
});
findPagination().vm.$emit('input', 1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.nextPage).toBe(2);
});
it('returns `null` when currentPage is already last page', async () => {
findStatusTabs().vm.$emit('input', 1);
findPagination().vm.$emit('input', 1);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.nextPage).toBeNull();
});
});
@@ -319,7 +320,7 @@ describe('AlertManagementEmptyState', () => {
searchTerm,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.filteredSearchValue).toEqual([searchTerm]);
});
diff --git a/spec/frontend/vue_shared/components/pikaday_spec.js b/spec/frontend/vue_shared/components/pikaday_spec.js
deleted file mode 100644
index fed4ce5e696..00000000000
--- a/spec/frontend/vue_shared/components/pikaday_spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { GlDatepicker } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import datePicker from '~/vue_shared/components/pikaday.vue';
-
-describe('datePicker', () => {
- let wrapper;
-
- const buildWrapper = (propsData = {}) => {
- wrapper = shallowMount(datePicker, {
- propsData,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
- it('should emit newDateSelected when GlDatePicker emits the input event', () => {
- const minDate = new Date();
- const maxDate = new Date();
- const selectedDate = new Date();
- const theDate = selectedDate.toISOString().slice(0, 10);
-
- buildWrapper({ minDate, maxDate, selectedDate });
-
- expect(wrapper.find(GlDatepicker).props()).toMatchObject({
- minDate,
- maxDate,
- value: selectedDate,
- });
- wrapper.find(GlDatepicker).vm.$emit('input', selectedDate);
- expect(wrapper.emitted('newDateSelected')[0][0]).toBe(theDate);
- });
- it('should emit the hidePicker event when GlDatePicker emits the close event', () => {
- buildWrapper();
-
- wrapper.find(GlDatepicker).vm.$emit('close');
-
- expect(wrapper.emitted('hidePicker')).toHaveLength(1);
- });
-});
diff --git a/spec/frontend/vue_shared/components/project_avatar/default_spec.js b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
index 84dad2374cb..d042db6051c 100644
--- a/spec/frontend/vue_shared/components/project_avatar/default_spec.js
+++ b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { projectData } from 'jest/ide/mock_data';
import { TEST_HOST } from 'spec/test_constants';
@@ -19,7 +19,7 @@ describe('ProjectAvatarDefault component', () => {
vm.$destroy();
});
- it('renders identicon if project has no avatar_url', (done) => {
+ it('renders identicon if project has no avatar_url', async () => {
const expectedText = getFirstCharacterCapitalized(projectData.name);
vm.project = {
@@ -27,18 +27,14 @@ describe('ProjectAvatarDefault component', () => {
avatar_url: null,
};
- vm.$nextTick()
- .then(() => {
- const identiconEl = vm.$el.querySelector('.identicon');
+ await nextTick();
+ const identiconEl = vm.$el.querySelector('.identicon');
- expect(identiconEl).not.toBe(null);
- expect(identiconEl.textContent.trim()).toEqual(expectedText);
- })
- .then(done)
- .catch(done.fail);
+ expect(identiconEl).not.toBe(null);
+ expect(identiconEl.textContent.trim()).toEqual(expectedText);
});
- it('renders avatar image if project has avatar_url', (done) => {
+ it('renders avatar image if project has avatar_url', async () => {
const avatarUrl = `${TEST_HOST}/images/home/nasa.svg`;
vm.project = {
@@ -46,13 +42,9 @@ describe('ProjectAvatarDefault component', () => {
avatar_url: avatarUrl,
};
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.avatar')).not.toBeNull();
- expect(vm.$el.querySelector('.identicon')).toBeNull();
- expect(vm.$el.querySelector('img')).toHaveAttr('src', avatarUrl);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(vm.$el.querySelector('.avatar')).not.toBeNull();
+ expect(vm.$el.querySelector('.identicon')).toBeNull();
+ expect(vm.$el.querySelector('img')).toHaveAttr('src', avatarUrl);
});
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
index 34cee10392d..379e60c1b2d 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
@@ -1,7 +1,7 @@
import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { head } from 'lodash';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
@@ -77,39 +77,36 @@ describe('ProjectSelector component', () => {
expect(vm.$emit).toHaveBeenCalledWith('projectClicked', head(searchResults));
});
- it(`shows a "no results" message if showNoResultsMessage === true`, () => {
+ it(`shows a "no results" message if showNoResultsMessage === true`, async () => {
wrapper.setProps({ showNoResultsMessage: true });
- return vm.$nextTick().then(() => {
- const noResultsEl = wrapper.find('.js-no-results-message');
+ await nextTick();
+ const noResultsEl = wrapper.find('.js-no-results-message');
- expect(noResultsEl.exists()).toBe(true);
- expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search');
- });
+ expect(noResultsEl.exists()).toBe(true);
+ expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search');
});
- it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, () => {
+ it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, async () => {
wrapper.setProps({ showMinimumSearchQueryMessage: true });
- return vm.$nextTick().then(() => {
- const minimumSearchEl = wrapper.find('.js-minimum-search-query-message');
+ await nextTick();
+ const minimumSearchEl = wrapper.find('.js-minimum-search-query-message');
- expect(minimumSearchEl.exists()).toBe(true);
- expect(trimText(minimumSearchEl.text())).toEqual('Enter at least three characters to search');
- });
+ expect(minimumSearchEl.exists()).toBe(true);
+ expect(trimText(minimumSearchEl.text())).toEqual('Enter at least three characters to search');
});
- it(`shows a error message if showSearchErrorMessage === true`, () => {
+ it(`shows a error message if showSearchErrorMessage === true`, async () => {
wrapper.setProps({ showSearchErrorMessage: true });
- return vm.$nextTick().then(() => {
- const errorMessageEl = wrapper.find('.js-search-error-message');
+ await nextTick();
+ const errorMessageEl = wrapper.find('.js-search-error-message');
- expect(errorMessageEl.exists()).toBe(true);
- expect(trimText(errorMessageEl.text())).toEqual(
- 'Something went wrong, unable to search projects',
- );
- });
+ expect(errorMessageEl.exists()).toBe(true);
+ expect(trimText(errorMessageEl.text())).toEqual(
+ 'Something went wrong, unable to search projects',
+ );
});
describe('the search results legend', () => {
@@ -121,7 +118,7 @@ describe('ProjectSelector component', () => {
${2} | ${3} | ${'Showing 2 of 3 projects'}
`(
'is "$expected" given $count results are showing out of $total',
- ({ count, total, expected }) => {
+ async ({ count, total, expected }) => {
search('gitlab ui');
wrapper.setProps({
@@ -129,9 +126,8 @@ describe('ProjectSelector component', () => {
totalResults: total,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(findLegendText()).toBe(expected);
- });
+ await nextTick();
+ expect(findLegendText()).toBe(expected);
},
);
diff --git a/spec/frontend/vue_shared/components/registry/list_item_spec.js b/spec/frontend/vue_shared/components/registry/list_item_spec.js
index ca4bf0b0652..1b93292e37b 100644
--- a/spec/frontend/vue_shared/components/registry/list_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/list_item_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import component from '~/vue_shared/components/registry/list_item.vue';
describe('list item', () => {
@@ -70,10 +71,10 @@ describe('list item', () => {
it('are visible when details is shown', async () => {
mountComponent({}, slotMocks);
- await wrapper.vm.$nextTick();
+ await nextTick();
findToggleDetailsButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
slotNames.forEach((name) => {
expect(findDetailsSlot(name).exists()).toBe(true);
});
@@ -90,7 +91,7 @@ describe('list item', () => {
describe('details toggle button', () => {
it('is visible when at least one details slot exists', async () => {
mountComponent({}, { 'details-foo': '<span></span>' });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findToggleDetailsButton().exists()).toBe(true);
});
diff --git a/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js b/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
index 40f0c0f29f2..7536df24ac6 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
+++ b/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import $ from 'jquery';
-import Vue from 'vue';
+import { nextTick } from 'vue';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
jest.mock('~/lib/utils/common_utils', () => ({
@@ -35,7 +35,7 @@ describe('Resizable Chart Container', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('updates the slot width and height props', () => {
+ it('updates the slot width and height props', async () => {
const width = 1920;
const height = 1080;
@@ -44,13 +44,12 @@ describe('Resizable Chart Container', () => {
$(document).trigger('content.resize');
- return Vue.nextTick().then(() => {
- const widthNode = wrapper.find('.slot > .width');
- const heightNode = wrapper.find('.slot > .height');
+ await nextTick();
+ const widthNode = wrapper.find('.slot > .width');
+ const heightNode = wrapper.find('.slot > .height');
- expect(parseInt(widthNode.text(), 10)).toEqual(width);
- expect(parseInt(heightNode.text(), 10)).toEqual(height);
- });
+ expect(parseInt(widthNode.text(), 10)).toEqual(width);
+ expect(parseInt(heightNode.text(), 10)).toEqual(height);
});
it('calls onResize on manual resize', () => {
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
index e74a867ec97..0da9939e97f 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
@@ -77,8 +77,7 @@ describe('RunnerInstructionsModal component', () => {
runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions);
createComponent();
-
- await nextTick();
+ await waitForPromises();
});
afterEach(() => {
@@ -113,13 +112,15 @@ describe('RunnerInstructionsModal component', () => {
});
});
- it('binary instructions are shown', () => {
+ it('binary instructions are shown', async () => {
+ await waitForPromises();
const instructions = findBinaryInstructions().text();
expect(instructions).toBe(installInstructions);
});
- it('register command is shown with a replaced token', () => {
+ it('register command is shown with a replaced token', async () => {
+ await waitForPromises();
const instructions = findRegisterCommand().text();
expect(instructions).toBe(
@@ -130,7 +131,7 @@ describe('RunnerInstructionsModal component', () => {
describe('when a register token is not shown', () => {
beforeEach(async () => {
createComponent({ props: { registrationToken: undefined } });
- await nextTick();
+ await waitForPromises();
});
it('register command is shown without a defined registration token', () => {
@@ -198,16 +199,17 @@ describe('RunnerInstructionsModal component', () => {
expect(findSkeletonLoader().exists()).toBe(true);
expect(findGlLoadingIcon().exists()).toBe(false);
- await nextTick(); // wait for platforms
+ await nextTick();
+ jest.runOnlyPendingTimers();
+ await nextTick();
+ await nextTick();
expect(findGlLoadingIcon().exists()).toBe(true);
});
it('once loaded, should not show a loading state', async () => {
createComponent();
-
- await nextTick(); // wait for platforms
- await nextTick(); // wait for architectures
+ await waitForPromises();
expect(findSkeletonLoader().exists()).toBe(false);
expect(findGlLoadingIcon().exists()).toBe(false);
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
index 23f8d6afcb5..9a95a838291 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -22,9 +22,9 @@ describe('RunnerInstructions component', () => {
wrapper.destroy();
});
- it('should show the "Show Runner installation instructions" button', () => {
+ it('should show the "Show runner installation instructions" button', () => {
expect(findModalButton().exists()).toBe(true);
- expect(findModalButton().text()).toBe('Show Runner installation instructions');
+ expect(findModalButton().text()).toBe('Show runner installation instructions');
});
it('should not render the modal once mounted', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
deleted file mode 100644
index 79e41ed0c9e..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-import CollapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
-
-describe('CollapsedCalendarIcon', () => {
- let wrapper;
-
- const defaultProps = {
- containerClass: 'test-class',
- text: 'text',
- tooltipText: 'tooltip text',
- showIcon: false,
- };
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = shallowMount(CollapsedCalendarIcon, {
- propsData: { ...defaultProps, ...props },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findGlIcon = () => wrapper.findComponent(GlIcon);
- const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip');
-
- it('adds class to container', () => {
- expect(wrapper.classes()).toContain(defaultProps.containerClass);
- });
-
- it('does not render calendar icon when showIcon is false', () => {
- expect(findGlIcon().exists()).toBe(false);
- });
-
- it('renders calendar icon when showIcon is true', () => {
- createComponent({
- props: { showIcon: true },
- });
-
- expect(findGlIcon().exists()).toBe(true);
- });
-
- it('renders text', () => {
- expect(wrapper.text()).toBe(defaultProps.text);
- });
-
- it('renders tooltipText as tooltip', () => {
- expect(getTooltip().value).toBe(defaultProps.tooltipText);
- });
-
- it('emits click event when container is clicked', async () => {
- wrapper.trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('click')[0]).toBeDefined();
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
deleted file mode 100644
index 263d1e9d947..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import DatePicker from '~/vue_shared/components/pikaday.vue';
-import SidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
-
-describe('SidebarDatePicker', () => {
- let wrapper;
-
- const createComponent = (propsData = {}, data = {}) => {
- wrapper = mount(SidebarDatePicker, {
- propsData,
- data: () => data,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findDatePicker = () => wrapper.findComponent(DatePicker);
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findEditButton = () => wrapper.find('.title .btn-blank');
- const findRemoveButton = () => wrapper.find('.value-content .btn-blank');
- const findSidebarToggle = () => wrapper.find('.title .gutter-toggle');
- const findValueContent = () => wrapper.find('.value-content');
-
- it('should emit toggleCollapse when collapsed toggle sidebar is clicked', () => {
- createComponent();
-
- wrapper.find('.issuable-sidebar-header .gutter-toggle').trigger('click');
-
- expect(wrapper.emitted('toggleCollapse')).toEqual([[]]);
- });
-
- it('should render collapsed-calendar-icon', () => {
- createComponent();
-
- expect(wrapper.find('.sidebar-collapsed-icon').exists()).toBe(true);
- });
-
- it('should render value when not editing', () => {
- createComponent();
-
- expect(findValueContent().exists()).toBe(true);
- });
-
- it('should render None if there is no selectedDate', () => {
- createComponent();
-
- expect(findValueContent().text()).toBe('None');
- });
-
- it('should render date-picker when editing', () => {
- createComponent({}, { editing: true });
-
- expect(findDatePicker().exists()).toBe(true);
- });
-
- it('should render label', () => {
- const label = 'label';
- createComponent({ label });
- expect(wrapper.find('.title').text()).toBe(label);
- });
-
- it('should render loading-icon when isLoading', () => {
- createComponent({ isLoading: true });
- expect(findLoadingIcon().exists()).toBe(true);
- });
-
- describe('editable', () => {
- beforeEach(() => {
- createComponent({ editable: true });
- });
-
- it('should render edit button', () => {
- expect(findEditButton().text()).toBe('Edit');
- });
-
- it('should enable editing when edit button is clicked', async () => {
- findEditButton().trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.editing).toBe(true);
- });
- });
-
- it('should render date if selectedDate', () => {
- createComponent({ selectedDate: new Date('07/07/2017') });
-
- expect(wrapper.find('.value-content strong').text()).toBe('Jul 7, 2017');
- });
-
- describe('selectedDate and editable', () => {
- beforeEach(() => {
- createComponent({ selectedDate: new Date('07/07/2017'), editable: true });
- });
-
- it('should render remove button if selectedDate and editable', () => {
- expect(findRemoveButton().text()).toBe('remove');
- });
-
- it('should emit saveDate with null when remove button is clicked', () => {
- findRemoveButton().trigger('click');
-
- expect(wrapper.emitted('saveDate')).toEqual([[null]]);
- });
- });
-
- describe('showToggleSidebar', () => {
- beforeEach(() => {
- createComponent({ showToggleSidebar: true });
- });
-
- it('should render toggle-sidebar when showToggleSidebar', () => {
- expect(findSidebarToggle().exists()).toBe(true);
- });
-
- it('should emit toggleCollapse when toggle sidebar is clicked', () => {
- findSidebarToggle().trigger('click');
-
- expect(wrapper.emitted('toggleCollapse')).toEqual([[]]);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
index 5336ecc614c..f213e37cbc1 100644
--- a/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
@@ -10,6 +10,7 @@ import {
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import axios from '~/lib/utils/axios_utils';
import IssuableMoveDropdown from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue';
@@ -74,7 +75,7 @@ describe('IssuableMoveDropdown', () => {
searchKey: 'foo',
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.fetchProjects).toHaveBeenCalledWith('foo');
});
@@ -151,7 +152,7 @@ describe('IssuableMoveDropdown', () => {
selectedProject,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isSelectedProject(project)).toBe(returnValue);
},
@@ -164,7 +165,7 @@ describe('IssuableMoveDropdown', () => {
selectedProject: null,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isSelectedProject(mockProjects[0])).toBe(false);
});
@@ -218,7 +219,7 @@ describe('IssuableMoveDropdown', () => {
projectsListLoading: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdownEl().find(GlLoadingIcon).exists()).toBe(true);
});
@@ -231,7 +232,7 @@ describe('IssuableMoveDropdown', () => {
selectedProject: mockProjects[0],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const dropdownItems = wrapper.findAll(GlDropdownItem);
@@ -251,7 +252,7 @@ describe('IssuableMoveDropdown', () => {
});
// Wait for `searchKey` watcher to run.
- await wrapper.vm.$nextTick();
+ await nextTick();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -260,7 +261,7 @@ describe('IssuableMoveDropdown', () => {
projectsListLoading: false,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const dropdownContentEl = wrapper.find('[data-testid="content"]');
@@ -276,7 +277,7 @@ describe('IssuableMoveDropdown', () => {
projectsListLoadFailed: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const dropdownContentEl = wrapper.find('[data-testid="content"]');
@@ -295,7 +296,7 @@ describe('IssuableMoveDropdown', () => {
selectedProject: mockProjects[0],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(
wrapper.find('[data-testid="footer"]').find(GlButton).attributes('disabled'),
@@ -352,7 +353,7 @@ describe('IssuableMoveDropdown', () => {
projects: mockProjects,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.findAll(GlDropdownItem).at(0).vm.$emit('click', mockEvent);
@@ -366,7 +367,7 @@ describe('IssuableMoveDropdown', () => {
selectedProject: mockProjects[0],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.find('[data-testid="footer"]').find(GlButton).vm.$emit('click');
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
index c4ed975e746..c05513a6d5f 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
@@ -1,6 +1,6 @@
import { GlIcon, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
@@ -71,13 +71,12 @@ describe('DropdownButton', () => {
expect(dropdownTextEl.text()).toBe('Label');
});
- it('renders provided button text element', () => {
+ it('renders provided button text element', async () => {
store.state.dropdownButtonText = 'Custom label';
const dropdownTextEl = findDropdownText();
- return wrapper.vm.$nextTick().then(() => {
- expect(dropdownTextEl.text()).toBe('Custom label');
- });
+ await nextTick();
+ expect(dropdownTextEl.text()).toBe('Custom label');
});
it('renders chevron icon element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
index 0eff6a1dace..0673ffee22b 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
@@ -1,6 +1,6 @@
import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue';
@@ -42,7 +42,7 @@ describe('DropdownContentsCreateView', () => {
expect(wrapper.vm.disableCreate).toBe(true);
});
- it('returns `true` when `labelCreateInProgress` is true', () => {
+ it('returns `true` when `labelCreateInProgress` is true', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -51,12 +51,11 @@ describe('DropdownContentsCreateView', () => {
});
wrapper.vm.$store.dispatch('requestCreateLabel');
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.disableCreate).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.vm.disableCreate).toBe(true);
});
- it('returns `false` when label title and color is defined and create request is not already in progress', () => {
+ it('returns `false` when label title and color is defined and create request is not already in progress', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
@@ -64,9 +63,8 @@ describe('DropdownContentsCreateView', () => {
selectedColor: '#ff0000',
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.disableCreate).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.vm.disableCreate).toBe(false);
});
});
@@ -101,7 +99,7 @@ describe('DropdownContentsCreateView', () => {
});
describe('handleCreateClick', () => {
- it('calls action `createLabel` with object containing `labelTitle` & `selectedColor`', () => {
+ it('calls action `createLabel` with object containing `labelTitle` & `selectedColor`', async () => {
jest.spyOn(wrapper.vm, 'createLabel').mockImplementation();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -112,14 +110,13 @@ describe('DropdownContentsCreateView', () => {
wrapper.vm.handleCreateClick();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.createLabel).toHaveBeenCalledWith(
- expect.objectContaining({
- title: 'Foo',
- color: '#ff0000',
- }),
- );
- });
+ await nextTick();
+ expect(wrapper.vm.createLabel).toHaveBeenCalledWith(
+ expect.objectContaining({
+ title: 'Foo',
+ color: '#ff0000',
+ }),
+ );
});
});
});
@@ -169,25 +166,22 @@ describe('DropdownContentsCreateView', () => {
});
});
- it('renders color input element', () => {
+ it('renders color input element', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
selectedColor: '#ff0000',
});
- return wrapper.vm.$nextTick(() => {
- const colorPreviewEl = wrapper.find(
- '.color-input-container > .dropdown-label-color-preview',
- );
- const colorInputEl = wrapper.find('.color-input-container').find(GlFormInput);
+ await nextTick();
+ const colorPreviewEl = wrapper.find('.color-input-container > .dropdown-label-color-preview');
+ const colorInputEl = wrapper.find('.color-input-container').find(GlFormInput);
- expect(colorPreviewEl.exists()).toBe(true);
- expect(colorPreviewEl.attributes('style')).toContain('background-color');
- expect(colorInputEl.exists()).toBe(true);
- expect(colorInputEl.attributes('placeholder')).toBe('Use custom color #FF0000');
- expect(colorInputEl.attributes('value')).toBe('#ff0000');
- });
+ expect(colorPreviewEl.exists()).toBe(true);
+ expect(colorPreviewEl.attributes('style')).toContain('background-color');
+ expect(colorInputEl.exists()).toBe(true);
+ expect(colorInputEl.attributes('placeholder')).toBe('Use custom color #FF0000');
+ expect(colorInputEl.attributes('value')).toBe('#ff0000');
});
it('renders create button element', () => {
@@ -197,15 +191,14 @@ describe('DropdownContentsCreateView', () => {
expect(createBtnEl.text()).toContain('Create');
});
- it('shows gl-loading-icon within create button element when `labelCreateInProgress` is `true`', () => {
+ it('shows gl-loading-icon within create button element when `labelCreateInProgress` is `true`', async () => {
wrapper.vm.$store.dispatch('requestCreateLabel');
- return wrapper.vm.$nextTick(() => {
- const loadingIconEl = wrapper.find('.dropdown-actions').find(GlLoadingIcon);
+ await nextTick();
+ const loadingIconEl = wrapper.find('.dropdown-actions').find(GlLoadingIcon);
- expect(loadingIconEl.exists()).toBe(true);
- expect(loadingIconEl.isVisible()).toBe(true);
- });
+ expect(loadingIconEl.exists()).toBe(true);
+ expect(loadingIconEl.isVisible()).toBe(true);
});
it('renders cancel button element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index 93a0e2f75bb..42202db4935 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -6,7 +6,7 @@ import {
GlLink,
} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue';
@@ -114,7 +114,7 @@ describe('DropdownContentsLabelsView', () => {
wrapper.vm.$store.dispatch('receiveLabelsSuccess', labels);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.showNoMatchingResultsMessage).toBe(returnValue);
},
@@ -249,7 +249,7 @@ describe('DropdownContentsLabelsView', () => {
expect(wrapper.vm.toggleDropdownContents).toHaveBeenCalled();
});
- it('calls action `scrollIntoViewIfNeeded` in next tick when any key is pressed', () => {
+ it('calls action `scrollIntoViewIfNeeded` in next tick when any key is pressed', async () => {
jest.spyOn(wrapper.vm, 'scrollIntoViewIfNeeded').mockImplementation();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -261,9 +261,8 @@ describe('DropdownContentsLabelsView', () => {
keyCode: DOWN_KEY_CODE,
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.scrollIntoViewIfNeeded).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.vm.scrollIntoViewIfNeeded).toHaveBeenCalled();
});
});
@@ -294,15 +293,14 @@ describe('DropdownContentsLabelsView', () => {
expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true);
});
- it('renders gl-loading-icon component when `labelsFetchInProgress` prop is true', () => {
+ it('renders gl-loading-icon component when `labelsFetchInProgress` prop is true', async () => {
wrapper.vm.$store.dispatch('requestLabels');
- return wrapper.vm.$nextTick(() => {
- const loadingIconEl = findLoadingIcon();
+ await nextTick();
+ const loadingIconEl = findLoadingIcon();
- expect(loadingIconEl.exists()).toBe(true);
- expect(loadingIconEl.attributes('class')).toContain('labels-fetch-loading');
- });
+ expect(loadingIconEl.exists()).toBe(true);
+ expect(loadingIconEl.attributes('class')).toContain('labels-fetch-loading');
});
it('renders dropdown title element', () => {
@@ -339,47 +337,44 @@ describe('DropdownContentsLabelsView', () => {
expect(wrapper.findAll(LabelItem)).toHaveLength(mockLabels.length);
});
- it('renders label element with `highlight` set to true when value of `currentHighlightItem` is more than -1', () => {
+ it('renders label element with `highlight` set to true when value of `currentHighlightItem` is more than -1', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
currentHighlightItem: 0,
});
- return wrapper.vm.$nextTick(() => {
- const labelItemEl = findDropdownContent().find(LabelItem);
+ await nextTick();
+ const labelItemEl = findDropdownContent().find(LabelItem);
- expect(labelItemEl.attributes('highlight')).toBe('true');
- });
+ expect(labelItemEl.attributes('highlight')).toBe('true');
});
- it('renders element containing "No matching results" when `searchKey` does not match with any label', () => {
+ it('renders element containing "No matching results" when `searchKey` does not match with any label', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
searchKey: 'abc',
});
- return wrapper.vm.$nextTick(() => {
- const noMatchEl = findDropdownContent().find('li');
+ await nextTick();
+ const noMatchEl = findDropdownContent().find('li');
- expect(noMatchEl.isVisible()).toBe(true);
- expect(noMatchEl.text()).toContain('No matching results');
- });
+ expect(noMatchEl.isVisible()).toBe(true);
+ expect(noMatchEl.text()).toContain('No matching results');
});
- it('renders empty content while loading', () => {
+ it('renders empty content while loading', async () => {
wrapper.vm.$store.state.labelsFetchInProgress = true;
- return wrapper.vm.$nextTick(() => {
- const dropdownContent = findDropdownContent();
- const loadingIcon = findLoadingIcon();
+ await nextTick();
+ const dropdownContent = findDropdownContent();
+ const loadingIcon = findLoadingIcon();
- expect(dropdownContent.exists()).toBe(true);
- expect(dropdownContent.isVisible()).toBe(true);
- expect(loadingIcon.exists()).toBe(true);
- expect(loadingIcon.isVisible()).toBe(true);
- });
+ expect(dropdownContent.exists()).toBe(true);
+ expect(dropdownContent.isVisible()).toBe(true);
+ expect(loadingIcon.exists()).toBe(true);
+ expect(loadingIcon.isVisible()).toBe(true);
});
it('renders footer list items', () => {
@@ -393,14 +388,13 @@ describe('DropdownContentsLabelsView', () => {
expect(manageLabelsLink.text()).toBe('Manage labels');
});
- it('does not render "Create label" footer link when `state.allowLabelCreate` is `false`', () => {
+ it('does not render "Create label" footer link when `state.allowLabelCreate` is `false`', async () => {
wrapper.vm.$store.state.allowLabelCreate = false;
- return wrapper.vm.$nextTick(() => {
- const createLabelLink = findDropdownFooter().findAll(GlLink).at(0);
+ await nextTick();
+ const createLabelLink = findDropdownFooter().findAll(GlLink).at(0);
- expect(createLabelLink.text()).not.toBe('Create label');
- });
+ expect(createLabelLink.text()).not.toBe('Create label');
});
it('does not render footer list items when `state.variant` is "standalone"', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
index 110c1d1b7eb..84e9f3f41c3 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
@@ -1,6 +1,6 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
@@ -47,14 +47,13 @@ describe('DropdownTitle', () => {
expect(editBtnEl.text()).toBe('Edit');
});
- it('renders loading icon element when `labelsSelectInProgress` prop is true', () => {
+ it('renders loading icon element when `labelsSelectInProgress` prop is true', async () => {
wrapper.setProps({
labelsSelectInProgress: true,
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
});
});
});
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
index a7f9391cb5f..c6400320dea 100644
--- 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
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import DropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
@@ -42,7 +43,7 @@ describe('DropdownValueCollapsedComponent', () => {
wrapper.trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('onValueClick')[0]).toBeDefined();
});
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 4b0ba075eda..31819d0e2f7 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
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
@@ -139,27 +139,26 @@ describe('LabelsSelectRoot', () => {
${'embedded'} | ${'is-embedded'}
`(
'renders component root element with CSS class `$cssClass` when `state.variant` is "$variant"',
- ({ variant, cssClass }) => {
+ async ({ variant, cssClass }) => {
createComponent({
...mockConfig,
variant,
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.classes()).toContain(cssClass);
- });
+ await nextTick();
+ expect(wrapper.classes()).toContain(cssClass);
},
);
it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', async () => {
createComponent();
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true);
});
it('renders `dropdown-title` component', async () => {
createComponent();
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(wrapper.find(DropdownTitle).exists()).toBe(true);
});
@@ -167,7 +166,7 @@ describe('LabelsSelectRoot', () => {
createComponent(mockConfig, {
default: 'None',
});
- await wrapper.vm.$nextTick;
+ await nextTick;
const valueComp = wrapper.find(DropdownValue);
@@ -178,14 +177,14 @@ describe('LabelsSelectRoot', () => {
it('renders `dropdown-button` component when `showDropdownButton` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownButton');
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(wrapper.find(DropdownButton).exists()).toBe(true);
});
it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownContents');
- await wrapper.vm.$nextTick;
+ await nextTick;
expect(wrapper.find(DropdownContents).exists()).toBe(true);
});
@@ -198,22 +197,20 @@ describe('LabelsSelectRoot', () => {
wrapper.vm.$store.dispatch('toggleDropdownContents');
});
- it('set direction when out of viewport', () => {
+ it('set direction when out of viewport', async () => {
isInViewport.mockImplementation(() => false);
wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(true);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(true);
});
- it('does not set direction when inside of viewport', () => {
+ it('does not set direction when inside of viewport', async () => {
isInViewport.mockImplementation(() => true);
wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
});
},
);
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
index a4199bb3e27..67e1a3ce932 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
@@ -117,9 +117,15 @@ describe('LabelsSelectRoot', () => {
it('renders dropdown value component when query labels is resolved', () => {
expect(findDropdownValue().exists()).toBe(true);
- expect(findDropdownValue().props('selectedLabels')).toEqual(
- issuableLabelsQueryResponse.data.workspace.issuable.labels.nodes,
- );
+ expect(findDropdownValue().props('selectedLabels')).toEqual([
+ {
+ color: '#330066',
+ description: null,
+ id: 'gid://gitlab/ProjectLabel/1',
+ title: 'Label1',
+ textColor: '#000000',
+ },
+ ]);
});
it('emits `onLabelRemove` event on dropdown value label remove event', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
index 6ef54ce37ce..49224fb915c 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
@@ -96,6 +96,7 @@ export const workspaceLabelsQueryResponse = {
labels: {
nodes: [
{
+ __typename: 'Label',
color: '#330066',
description: null,
id: 'gid://gitlab/ProjectLabel/1',
@@ -103,6 +104,7 @@ export const workspaceLabelsQueryResponse = {
textColor: '#000000',
},
{
+ __typename: 'Label',
color: '#2f7b2e',
description: null,
id: 'gid://gitlab/ProjectLabel/2',
@@ -125,6 +127,7 @@ export const issuableLabelsQueryResponse = {
labels: {
nodes: [
{
+ __typename: 'Label',
color: '#330066',
description: null,
id: 'gid://gitlab/ProjectLabel/1',
diff --git a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
index a6c9bda1aa2..267a467059d 100644
--- a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import ToggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
describe('ToggleSidebar', () => {
@@ -38,7 +39,7 @@ describe('ToggleSidebar', () => {
createComponent({ mountFn: mount });
findGlButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.emitted('toggle')[0]).toBeDefined();
});
diff --git a/spec/frontend/vue_shared/components/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
index 094d8d42a47..2010bac7060 100644
--- a/spec/frontend/vue_shared/components/source_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
@@ -1,8 +1,10 @@
import hljs from 'highlight.js/lib/core';
+import { GlLoadingIcon } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import SourceViewer from '~/vue_shared/components/source_viewer.vue';
+import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue';
+import { ROUGE_TO_HLJS_LANGUAGE_MAP } from '~/vue_shared/components/source_viewer/constants';
import LineNumbers from '~/vue_shared/components/line_numbers.vue';
import waitForPromises from 'helpers/wait_for_promises';
@@ -12,42 +14,50 @@ const router = new VueRouter();
describe('Source Viewer component', () => {
let wrapper;
+ const language = 'docker';
+ const mappedLanguage = ROUGE_TO_HLJS_LANGUAGE_MAP[language];
const content = `// Some source code`;
+ const DEFAULT_BLOB_DATA = { language, rawTextBlob: content };
const highlightedContent = `<span data-testid='test-highlighted' id='LC1'>${content}</span><span id='LC2'></span>`;
- const language = 'javascript';
- hljs.highlight.mockImplementation(() => ({ value: highlightedContent }));
- hljs.highlightAuto.mockImplementation(() => ({ value: highlightedContent }));
-
- const createComponent = async (props = {}) => {
+ const createComponent = async (blob = {}) => {
wrapper = shallowMountExtended(SourceViewer, {
router,
- propsData: { content, language, ...props },
+ propsData: { blob: { ...DEFAULT_BLOB_DATA, ...blob } },
});
await waitForPromises();
};
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findLineNumbers = () => wrapper.findComponent(LineNumbers);
const findHighlightedContent = () => wrapper.findByTestId('test-highlighted');
const findFirstLine = () => wrapper.find('#LC1');
- beforeEach(() => createComponent());
+ beforeEach(() => {
+ hljs.highlight.mockImplementation(() => ({ value: highlightedContent }));
+ hljs.highlightAuto.mockImplementation(() => ({ value: highlightedContent }));
+
+ return createComponent();
+ });
afterEach(() => wrapper.destroy());
describe('highlight.js', () => {
it('registers the language definition', async () => {
- const languageDefinition = await import(`highlight.js/lib/languages/${language}`);
+ const languageDefinition = await import(`highlight.js/lib/languages/${mappedLanguage}`);
- expect(hljs.registerLanguage).toHaveBeenCalledWith(language, languageDefinition.default);
+ expect(hljs.registerLanguage).toHaveBeenCalledWith(
+ mappedLanguage,
+ languageDefinition.default,
+ );
});
it('highlights the content', () => {
- expect(hljs.highlight).toHaveBeenCalledWith(content, { language });
+ expect(hljs.highlight).toHaveBeenCalledWith(content, { language: mappedLanguage });
});
- describe('auto-detect enabled', () => {
- beforeEach(() => createComponent({ autoDetect: true }));
+ describe('auto-detects if a language cannot be loaded', () => {
+ beforeEach(() => createComponent({ language: 'some_unknown_language' }));
it('highlights the content with auto-detection', () => {
expect(hljs.highlightAuto).toHaveBeenCalledWith(content);
@@ -56,6 +66,13 @@ describe('Source Viewer component', () => {
});
describe('rendering', () => {
+ it('renders a loading icon if no highlighted content is available yet', async () => {
+ hljs.highlight.mockImplementation(() => ({ value: null }));
+ await createComponent();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
it('renders Line Numbers', () => {
expect(findLineNumbers().props('lines')).toBe(1);
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/utils_spec.js b/spec/frontend/vue_shared/components/source_viewer/utils_spec.js
new file mode 100644
index 00000000000..937c3b26c67
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer/utils_spec.js
@@ -0,0 +1,13 @@
+import { wrapLines } from '~/vue_shared/components/source_viewer/utils';
+
+describe('Wrap lines', () => {
+ it.each`
+ input | output
+ ${'line 1'} | ${'<span id="LC1" class="line">line 1</span>'}
+ ${'line 1\nline 2'} | ${`<span id="LC1" class="line">line 1</span>\n<span id="LC2" class="line">line 2</span>`}
+ ${'<span class="hljs-code">line 1\nline 2</span>'} | ${`<span id="LC1" class="hljs-code">line 1\n<span id="LC2" class="line">line 2</span></span>`}
+ ${'<span class="hljs-code">```bash'} | ${'<span id="LC1" class="hljs-code">```bash'}
+ `('returns lines wrapped in spans containing line numbers', ({ input, output }) => {
+ expect(wrapLines(input)).toBe(output);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/split_button_spec.js b/spec/frontend/vue_shared/components/split_button_spec.js
index ad11e6519c4..4965969bc3e 100644
--- a/spec/frontend/vue_shared/components/split_button_spec.js
+++ b/spec/frontend/vue_shared/components/split_button_spec.js
@@ -1,6 +1,7 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import SplitButton from '~/vue_shared/components/split_button.vue';
const mockActionItems = [
@@ -27,15 +28,15 @@ describe('SplitButton', () => {
const findDropdown = () => wrapper.find(GlDropdown);
const findDropdownItem = (index = 0) => findDropdown().findAll(GlDropdownItem).at(index);
- const selectItem = (index) => {
+ const selectItem = async (index) => {
findDropdownItem(index).vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
- const clickToggleButton = () => {
+ const clickToggleButton = async () => {
findDropdown().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
it('fails for empty actionItems', () => {
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
index 0f1e118d44c..a613b325462 100644
--- a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
+++ b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
@@ -6,6 +6,7 @@ exports[`Upload dropzone component correctly overrides description and drop mess
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -86,6 +87,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -170,6 +172,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -254,6 +257,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -339,6 +343,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -424,6 +429,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
@@ -509,6 +515,7 @@ exports[`Upload dropzone component when no slot provided renders default dropzon
>
<button
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ type="button"
>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-text-center gl-flex-direction-column"
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
index b3cdbccb271..21e9b401215 100644
--- a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
+++ b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
jest.mock('~/flash');
@@ -15,6 +16,7 @@ describe('Upload dropzone component', () => {
const findDropzoneArea = () => wrapper.find('[data-testid="dropzone-area"]');
const findIcon = () => wrapper.find(GlIcon);
const findUploadText = () => wrapper.find('[data-testid="upload-text"]').text();
+ const findFileInput = () => wrapper.find('input[type="file"]');
function createComponent({ slots = {}, data = {}, props = {} } = {}) {
wrapper = shallowMount(UploadDropzone, {
@@ -84,47 +86,40 @@ describe('Upload dropzone component', () => {
${'contains text'} | ${mockDragEvent({ types: ['text'] })}
${'contains files and text'} | ${mockDragEvent({ types: ['Files', 'text'] })}
${'contains files'} | ${mockDragEvent({ types: ['Files'] })}
- `('renders correct template when drag event $description', ({ eventPayload }) => {
+ `('renders correct template when drag event $description', async ({ eventPayload }) => {
createComponent();
wrapper.trigger('dragenter', eventPayload);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
- it('renders correct template when dragging stops', () => {
+ it('renders correct template when dragging stops', async () => {
createComponent();
wrapper.trigger('dragenter');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.trigger('dragleave');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+
+ await nextTick();
+ wrapper.trigger('dragleave');
+
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
});
describe('when dropping', () => {
- it('emits upload event', () => {
+ it('emits upload event', async () => {
createComponent();
const mockFile = { name: 'test', type: 'image/jpg' };
const mockEvent = mockDragEvent({ files: [mockFile] });
wrapper.trigger('dragenter', mockEvent);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.trigger('drop', mockEvent);
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted().change[0]).toEqual([[mockFile]]);
- });
+
+ await nextTick();
+ wrapper.trigger('drop', mockEvent);
+
+ await nextTick();
+ expect(wrapper.emitted().change[0]).toEqual([[mockFile]]);
});
});
@@ -203,4 +198,60 @@ describe('Upload dropzone component', () => {
expect(wrapper.element).toMatchSnapshot();
});
+
+ describe('file input form name', () => {
+ it('applies inputFieldName as file input name', () => {
+ createComponent({ props: { inputFieldName: 'test_field_name' } });
+ expect(findFileInput().attributes('name')).toBe('test_field_name');
+ });
+
+ it('uses default file input name if no inputFieldName provided', () => {
+ createComponent();
+ expect(findFileInput().attributes('name')).toBe('upload_file');
+ });
+ });
+
+ describe('updates file input files value', () => {
+ // NOTE: the component assigns dropped files from the drop event to the
+ // input.files property. There's a restriction that nothing but a FileList
+ // can be assigned to this property. While FileList can't be created
+ // manually: it has no constructor. And currently there's no good workaround
+ // for jsdom. So we have to stub the file input in vm.$refs to ensure that
+ // the files property is updated. This enforces following tests to know a
+ // bit too much about the SUT internals See this thread for more details on
+ // FileList in jsdom: https://github.com/jsdom/jsdom/issues/1272
+ function stubFileInputOnWrapper() {
+ const fakeFileInput = { files: [] };
+ wrapper.vm.$refs.fileUpload = fakeFileInput;
+ }
+
+ it('assigns dragged files to the input files property', async () => {
+ const mockFile = { name: 'test', type: 'image/jpg' };
+ const mockEvent = mockDragEvent({ files: [mockFile] });
+ createComponent({ props: { shouldUpdateInputOnFileDrop: true } });
+ stubFileInputOnWrapper();
+
+ wrapper.trigger('dragenter', mockEvent);
+ await nextTick();
+ wrapper.trigger('drop', mockEvent);
+ await nextTick();
+
+ expect(wrapper.vm.$refs.fileUpload.files).toEqual([mockFile]);
+ });
+
+ it('throws an error when multiple files are dropped on a single file input dropzone', async () => {
+ const mockFile = { name: 'test', type: 'image/jpg' };
+ const mockEvent = mockDragEvent({ files: [mockFile, mockFile] });
+ createComponent({ props: { shouldUpdateInputOnFileDrop: true, singleFileSelection: true } });
+ stubFileInputOnWrapper();
+
+ wrapper.trigger('dragenter', mockEvent);
+ await nextTick();
+ wrapper.trigger('drop', mockEvent);
+ await nextTick();
+
+ expect(wrapper.vm.$refs.fileUpload.files).toEqual([]);
+ expect(wrapper.emitted('error')).toHaveLength(1);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
index 1d15da491cd..66bb234aef6 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'spec/test_constants';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
@@ -142,14 +143,13 @@ describe('UserAvatarList', () => {
expect(links.length).toEqual(props.items.length);
});
- it('with collapse clicked, it renders avatars up to breakpoint', () => {
+ it('with collapse clicked, it renders avatars up to breakpoint', async () => {
clickButton();
- return wrapper.vm.$nextTick(() => {
- const links = wrapper.findAll(UserAvatarLink);
+ await nextTick();
+ const links = wrapper.findAll(UserAvatarLink);
- expect(links.length).toEqual(TEST_BREAKPOINT);
- });
+ expect(links.length).toEqual(TEST_BREAKPOINT);
});
});
});
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index 8994e16e517..411a15e1c74 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -104,14 +104,14 @@ describe('User select dropdown', () => {
createComponent({ participantsQueryHandler: mockError });
await waitForPromises();
- expect(wrapper.emitted('error')).toEqual([[], []]);
+ expect(wrapper.emitted('error')).toEqual([[]]);
});
it('emits an `error` event if search query was rejected', async () => {
createComponent({ searchQueryHandler: mockError });
await waitForSearch();
- expect(wrapper.emitted('error')).toEqual([[], []]);
+ expect(wrapper.emitted('error')).toEqual([[]]);
});
it('renders current user if they are not in participants or assignees', async () => {
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 659d93d6597..5589cbfd08f 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -4,6 +4,7 @@ import { nextTick } from 'vue';
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';
+import ConfirmForkModal from '~/vue_shared/components/confirm_fork_modal.vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
@@ -13,6 +14,7 @@ const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/main/-/';
const TEST_GITPOD_URL = 'https://gitpod.test/';
const TEST_USER_PREFERENCES_GITPOD_PATH = '/-/profile/preferences#user_gitpod_enabled';
const TEST_USER_PROFILE_ENABLE_GITPOD_PATH = '/-/profile?user%5Bgitpod_enabled%5D=true';
+const forkPath = '/some/fork/path';
const ACTION_EDIT = {
href: TEST_EDIT_URL,
@@ -74,6 +76,7 @@ describe('Web IDE link component', () => {
editUrl: TEST_EDIT_URL,
webIdeUrl: TEST_WEB_IDE_URL,
gitpodUrl: TEST_GITPOD_URL,
+ forkPath,
...props,
},
stubs: {
@@ -96,6 +99,7 @@ describe('Web IDE link component', () => {
const findActionsButton = () => wrapper.find(ActionsButton);
const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
const findModal = () => wrapper.findComponent(GlModal);
+ const findForkConfirmModal = () => wrapper.findComponent(ConfirmForkModal);
it.each([
{
@@ -213,7 +217,7 @@ describe('Web IDE link component', () => {
findLocalStorageSync().vm.$emit('input', ACTION_GITPOD.key);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key);
});
@@ -223,7 +227,7 @@ describe('Web IDE link component', () => {
findActionsButton().vm.$emit('select', ACTION_GITPOD.key);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key);
expect(findLocalStorageSync().props('value')).toBe(ACTION_GITPOD.key);
@@ -231,16 +235,28 @@ describe('Web IDE link component', () => {
});
describe('edit actions', () => {
- it.each([
+ const testActions = [
{
- props: { showWebIdeButton: true, showEditButton: false },
+ props: {
+ showWebIdeButton: true,
+ showEditButton: false,
+ forkPath,
+ forkModalId: 'edit-modal',
+ },
expectedEventPayload: 'ide',
},
{
- props: { showWebIdeButton: false, showEditButton: true },
+ props: {
+ showWebIdeButton: false,
+ showEditButton: true,
+ forkPath,
+ forkModalId: 'webide-modal',
+ },
expectedEventPayload: 'simple',
},
- ])(
+ ];
+
+ it.each(testActions)(
'emits the correct event when an action handler is called',
async ({ props, expectedEventPayload }) => {
createComponent({ ...props, needsToFork: true, disableForkModal: true });
@@ -250,6 +266,29 @@ describe('Web IDE link component', () => {
expect(wrapper.emitted('edit')).toEqual([[expectedEventPayload]]);
},
);
+
+ it.each(testActions)('renders the fork confirmation modal', async ({ props }) => {
+ createComponent({ ...props, needsToFork: true });
+
+ expect(findForkConfirmModal().exists()).toBe(true);
+ expect(findForkConfirmModal().props()).toEqual({
+ visible: false,
+ forkPath,
+ modalId: props.forkModalId,
+ });
+ });
+
+ it.each(testActions)('opens the modal when the button is clicked', async ({ props }) => {
+ createComponent({ ...props, needsToFork: true }, mountExtended);
+
+ await findActionsButton().trigger('click');
+
+ expect(findForkConfirmModal().props()).toEqual({
+ visible: true,
+ forkPath,
+ modalId: props.forkModalId,
+ });
+ });
});
describe('when Gitpod is not enabled', () => {
diff --git a/spec/frontend/vue_shared/directives/track_event_spec.js b/spec/frontend/vue_shared/directives/track_event_spec.js
index b3f94d0242a..4bf84b06246 100644
--- a/spec/frontend/vue_shared/directives/track_event_spec.js
+++ b/spec/frontend/vue_shared/directives/track_event_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import Tracking from '~/tracking';
import TrackEvent from '~/vue_shared/directives/track_event';
@@ -31,7 +31,7 @@ describe('Error Tracking directive', () => {
expect(Tracking.event).not.toHaveBeenCalled();
});
- it('should track event on click if tracking info provided', () => {
+ it('should track event on click if tracking info provided', async () => {
const trackingOptions = {
category: 'Tracking',
action: 'click_trackable_btn',
@@ -43,9 +43,8 @@ describe('Error Tracking directive', () => {
wrapper.setData({ trackingOptions });
const { category, action, label, property, value } = trackingOptions;
- return wrapper.vm.$nextTick(() => {
- button.trigger('click');
- expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property, value });
- });
+ await nextTick();
+ button.trigger('click');
+ expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property, value });
});
});
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js
index 0f33a3d1122..7dfeced571a 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import IssuableBulkEditSidebar from '~/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue';
const createComponent = ({ expanded = true } = {}) =>
@@ -48,7 +49,7 @@ describe('IssuableBulkEditSidebar', () => {
expanded,
});
- await wrappeCustom.vm.$nextTick();
+ await nextTick();
expect(document.querySelector('.layout-page').classList.contains(layoutPageClass)).toBe(
true,
@@ -78,7 +79,7 @@ describe('IssuableBulkEditSidebar', () => {
expanded,
});
- await wrappeCustom.vm.$nextTick();
+ await nextTick();
expect(wrappeCustom.classes()).toContain(layoutPageClass);
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
index e38a80e7734..65eb42ef053 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
@@ -1,4 +1,5 @@
import { GlLink, GlLabel, GlIcon, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { useFakeDate } from 'helpers/fake_date';
import { shallowMountExtended as shallowMount } from 'helpers/vue_test_utils_helper';
import IssuableItem from '~/vue_shared/issuable/list/components/issuable_item.vue';
@@ -9,7 +10,6 @@ import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
const createComponent = ({
issuableSymbol = '#',
issuable = mockIssuable,
- enableLabelPermalinks = true,
showCheckbox = true,
slots = {},
} = {}) =>
@@ -17,7 +17,6 @@ const createComponent = ({
propsData: {
issuableSymbol,
issuable,
- enableLabelPermalinks,
showDiscussions: true,
showCheckbox,
},
@@ -76,7 +75,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.authorId).toBe(returnValue);
},
@@ -100,7 +99,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isIssuableUrlExternal).toBe(returnValue);
},
@@ -122,7 +121,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.labels).toEqual(mockLabels);
});
@@ -135,7 +134,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.labels).toEqual([]);
});
@@ -211,23 +210,13 @@ describe('IssuableItem', () => {
});
describe('labelTarget', () => {
- it('returns target string for a provided label param when `enableLabelPermalinks` is true', () => {
+ it('returns target string for a provided label param', () => {
wrapper = createComponent();
expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe(
'?label_name[]=Documentation%20Update',
);
});
-
- it('returns string "#" for a provided label param when `enableLabelPermalinks` is false', async () => {
- wrapper = createComponent({
- enableLabelPermalinks: false,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe('#');
- });
});
});
@@ -248,7 +237,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const titleEl = wrapper.find('[data-testid="issuable-title"]');
@@ -264,7 +253,7 @@ describe('IssuableItem', () => {
showCheckbox: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlFormCheckbox).exists()).toBe(true);
expect(wrapper.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
@@ -273,7 +262,7 @@ describe('IssuableItem', () => {
checked: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(GlFormCheckbox).attributes('checked')).toBe('true');
});
@@ -286,7 +275,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('[data-testid="issuable-title"]').find(GlLink).attributes('target')).toBe(
'_blank',
@@ -301,7 +290,7 @@ describe('IssuableItem', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
index 14e93108447..64823cd4c6c 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
@@ -2,6 +2,7 @@ import { GlAlert, GlKeysetPagination, GlSkeletonLoading, GlPagination } from '@g
import { shallowMount } from '@vue/test-utils';
import VueDraggable from 'vuedraggable';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import IssuableItem from '~/vue_shared/issuable/list/components/issuable_item.vue';
@@ -77,7 +78,7 @@ describe('IssuableListRoot', () => {
currentPage,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.skeletonItemCount).toBe(returnValue);
},
@@ -96,7 +97,7 @@ describe('IssuableListRoot', () => {
issuables,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
@@ -104,7 +105,7 @@ describe('IssuableListRoot', () => {
checkedIssuables,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.allIssuablesChecked).toBe(returnValue);
},
@@ -119,7 +120,7 @@ describe('IssuableListRoot', () => {
checkedIssuables: mockCheckedIssuables,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.bulkEditIssuables).toHaveLength(mIssuables.length);
});
@@ -137,7 +138,7 @@ describe('IssuableListRoot', () => {
issuables: [mockIssuables[0]],
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(Object.keys(wrapper.vm.checkedIssuables)).toHaveLength(1);
expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
@@ -160,7 +161,7 @@ describe('IssuableListRoot', () => {
urlParams,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(global.window.location.href).toBe(
`${TEST_HOST}/?state=${urlParams.state}&sort=${urlParams.sort}&page=${urlParams.page}&search=${urlParams.search}`,
@@ -192,7 +193,7 @@ describe('IssuableListRoot', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.issuableChecked(mockIssuables[0])).toBe(true);
});
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
index 5723e2da586..27985895c62 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
@@ -1,5 +1,6 @@
import { GlTab, GlBadge } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { mount, shallowMount } from '@vue/test-utils';
import { setLanguage } from 'helpers/locale_helper';
import IssuableTabs from '~/vue_shared/issuable/list/components/issuable_tabs.vue';
@@ -10,17 +11,18 @@ const createComponent = ({
tabs = mockIssuableListProps.tabs,
tabCounts = mockIssuableListProps.tabCounts,
currentTab = mockIssuableListProps.currentTab,
+ truncateCounts = false,
+ mountFn = shallowMount,
} = {}) =>
- mount(IssuableTabs, {
+ mountFn(IssuableTabs, {
propsData: {
tabs,
tabCounts,
currentTab,
+ truncateCounts,
},
slots: {
- 'nav-actions': `
- <button class="js-new-issuable">New issuable</button>
- `,
+ 'nav-actions': `<button class="js-new-issuable">New issuable</button>`,
},
});
@@ -29,7 +31,6 @@ describe('IssuableTabs', () => {
beforeEach(() => {
setLanguage('en');
- wrapper = createComponent();
});
afterEach(() => {
@@ -40,60 +41,71 @@ describe('IssuableTabs', () => {
const findAllGlBadges = () => wrapper.findAllComponents(GlBadge);
const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
- describe('methods', () => {
- describe('isTabActive', () => {
- it.each`
- tabName | currentTab | returnValue
- ${'opened'} | ${'opened'} | ${true}
- ${'opened'} | ${'closed'} | ${false}
- `(
- 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
- async ({ tabName, currentTab, returnValue }) => {
- wrapper.setProps({
- currentTab,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
- },
- );
- });
+ describe('tabs', () => {
+ it.each`
+ currentTab | returnValue
+ ${'opened'} | ${'true'}
+ ${'closed'} | ${undefined}
+ `(
+ 'when "$currentTab" is the selected tab, the Open tab is active=$returnValue',
+ ({ currentTab, returnValue }) => {
+ wrapper = createComponent({ currentTab });
+
+ const openTab = findAllGlTabs().at(0);
+
+ expect(openTab.attributes('active')).toBe(returnValue);
+ },
+ );
});
describe('template', () => {
it('renders gl-tab for each tab within `tabs` array', () => {
- const tabsEl = findAllGlTabs();
+ wrapper = createComponent();
+
+ const tabs = findAllGlTabs();
- expect(tabsEl.exists()).toBe(true);
- expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
+ expect(tabs).toHaveLength(mockIssuableListProps.tabs.length);
});
- it('renders gl-badge component within a tab', () => {
+ it('renders gl-badge component within a tab', async () => {
+ wrapper = createComponent({ mountFn: mount });
+ await nextTick();
+
const badges = findAllGlBadges();
// Does not render `All` badge since it has an undefined count
expect(badges).toHaveLength(2);
- expect(badges.at(0).text()).toBe('5,000');
+ expect(badges.at(0).text()).toBe('5,678');
expect(badges.at(1).text()).toBe(`${mockIssuableListProps.tabCounts.closed}`);
});
it('renders contents for slot "nav-actions"', () => {
- const buttonEl = wrapper.find('button.js-new-issuable');
+ wrapper = createComponent();
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.text()).toBe('New issuable');
+ const button = wrapper.find('button.js-new-issuable');
+
+ expect(button.text()).toBe('New issuable');
+ });
+ });
+
+ describe('counts', () => {
+ it('can display as truncated', async () => {
+ wrapper = createComponent({ truncateCounts: true, mountFn: mount });
+ await nextTick();
+
+ expect(findAllGlBadges().at(0).text()).toBe('5.7k');
});
});
describe('events', () => {
it('gl-tab component emits `click` event on `click` event', () => {
- const tabEl = findAllGlTabs().at(0);
+ wrapper = createComponent();
+
+ const openTab = findAllGlTabs().at(0);
- tabEl.vm.$emit('click', 'opened');
+ openTab.vm.$emit('click', 'opened');
- expect(wrapper.emitted('click')).toBeTruthy();
- expect(wrapper.emitted('click')[0]).toEqual(['opened']);
+ expect(wrapper.emitted('click')).toEqual([['opened']]);
});
});
});
diff --git a/spec/frontend/vue_shared/issuable/list/mock_data.js b/spec/frontend/vue_shared/issuable/list/mock_data.js
index cfc7937b412..8640f4a2cd5 100644
--- a/spec/frontend/vue_shared/issuable/list/mock_data.js
+++ b/spec/frontend/vue_shared/issuable/list/mock_data.js
@@ -133,7 +133,7 @@ export const mockTabs = [
];
export const mockTabCounts = {
- opened: 5000,
+ opened: 5678,
closed: 0,
all: undefined,
};
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
index 41bacf18a68..1a93838b03f 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useFakeDate } from 'helpers/fake_date';
import IssuableBody from '~/vue_shared/issuable/show/components/issuable_body.vue';
@@ -68,7 +69,7 @@ describe('IssuableBody', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.isUpdated).toBe(returnValue);
},
@@ -90,13 +91,13 @@ describe('IssuableBody', () => {
editFormVisible: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
wrapper.setProps({
editFormVisible: false,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.initTaskList).toHaveBeenCalled();
});
@@ -182,7 +183,7 @@ describe('IssuableBody', () => {
editFormVisible: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const editFormEl = wrapper.find(IssuableEditForm);
expect(editFormEl.exists()).toBe(true);
@@ -221,7 +222,7 @@ describe('IssuableBody', () => {
editFormVisible: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const issuableEditForm = wrapper.find(IssuableEditForm);
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
index 051ffd27af4..b79dc0bf976 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
@@ -1,6 +1,7 @@
import { GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import IssuableEditForm from '~/vue_shared/issuable/show/components/issuable_edit_form.vue';
import IssuableEventHub from '~/vue_shared/issuable/show/event_hub';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
@@ -35,6 +36,7 @@ describe('IssuableEditForm', () => {
beforeEach(() => {
wrapper = createComponent();
+ gon.features = { markdownContinueLists: true };
});
afterEach(() => {
@@ -52,7 +54,7 @@ describe('IssuableEditForm', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.title).toBe('Foo');
expect(wrapper.vm.description).toBe('Foobar');
@@ -67,7 +69,7 @@ describe('IssuableEditForm', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.title).toBe('');
expect(wrapper.vm.description).toBe('');
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
index 41735923957..1cdd709159f 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlAvatarLabeled } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import IssuableHeader from '~/vue_shared/issuable/show/components/issuable_header.vue';
@@ -78,7 +79,7 @@ describe('IssuableHeader', () => {
blocked: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const blockedEl = wrapper.findByTestId('blocked');
@@ -91,7 +92,7 @@ describe('IssuableHeader', () => {
confidential: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const confidentialEl = wrapper.findByTestId('confidential');
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
index cb418371760..93de6dbe306 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import IssuableTitle from '~/vue_shared/issuable/show/components/issuable_title.vue';
@@ -64,7 +65,7 @@ describe('IssuableTitle', () => {
},
});
- await wrapperWithTitle.vm.$nextTick();
+ await nextTick();
const titleEl = wrapperWithTitle.find('h2');
expect(titleEl.exists()).toBe(true);
@@ -90,7 +91,7 @@ describe('IssuableTitle', () => {
stickyTitleVisible: true,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
const stickyHeaderEl = wrapper.find('[data-testid="header"]');
expect(stickyHeaderEl.exists()).toBe(true);
diff --git a/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
index 788ba70ddc0..47bf3c8ed83 100644
--- a/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
@@ -1,5 +1,6 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Cookies from 'js-cookie';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import IssuableSidebarRoot from '~/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue';
@@ -69,7 +70,10 @@ describe('IssuableSidebarRoot', () => {
it('updates "collapsed_gutter" cookie value and layout classes', async () => {
await findToggleSidebarButton().trigger('click');
- expect(Cookies.set).toHaveBeenCalledWith(USER_COLLAPSED_GUTTER_COOKIE, true);
+ expect(Cookies.set).toHaveBeenCalledWith(USER_COLLAPSED_GUTTER_COOKIE, true, {
+ expires: 365,
+ secure: false,
+ });
assertPageLayoutClasses({ isExpanded: false });
});
});
@@ -88,7 +92,7 @@ describe('IssuableSidebarRoot', () => {
jest.spyOn(bp, 'isDesktop').mockReturnValue(breakpoint === 'lg' || breakpoint === 'xl');
window.dispatchEvent(new Event('resize'));
- await wrapper.vm.$nextTick();
+ await nextTick();
assertPageLayoutClasses({ isExpanded: isExpandedValue });
},
diff --git a/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js b/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
index 2d51f6dbeeb..c90131fea9a 100644
--- a/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
+++ b/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
@@ -37,9 +37,8 @@ describe('Welcome page', () => {
const link = wrapper.find('a');
link.trigger('click');
await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
- });
+ await nextTick();
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
});
it('renders footer slot if provided', () => {
diff --git a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
index facbd51168c..39909e26ef0 100644
--- a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
@@ -16,7 +16,7 @@ jest.mock('~/lib/utils/url_utility');
Vue.use(VueApollo);
-const projectPath = 'namespace/project';
+const projectFullPath = 'namespace/project';
describe('ManageViaMr component', () => {
let wrapper;
@@ -40,7 +40,7 @@ describe('ManageViaMr component', () => {
wrapper = extendedWrapper(
mount(ManageViaMr, {
provide: {
- projectPath,
+ projectFullPath,
},
propsData: {
feature: {
@@ -65,7 +65,7 @@ describe('ManageViaMr component', () => {
// the ones available in the current test context.
const supportedReportTypes = Object.entries(featureToMutationMap).map(
([featureType, { getMutationPayload, mutationId }]) => {
- const { mutation, variables: mutationVariables } = getMutationPayload(projectPath);
+ const { mutation, variables: mutationVariables } = getMutationPayload(projectFullPath);
return [humanize(featureType), featureType, mutation, mutationId, mutationVariables];
},
);
diff --git a/spec/frontend/vue_shared/security_reports/mock_data.js b/spec/frontend/vue_shared/security_reports/mock_data.js
index 2b1513bb0f8..dac9accbbf5 100644
--- a/spec/frontend/vue_shared/security_reports/mock_data.js
+++ b/spec/frontend/vue_shared/security_reports/mock_data.js
@@ -324,7 +324,9 @@ export const secretDetectionDiffSuccessMock = {
export const securityReportMergeRequestDownloadPathsQueryNoArtifactsResponse = {
project: {
+ id: 'project-1',
mergeRequest: {
+ id: 'mr-1',
headPipeline: {
id: 'gid://gitlab/Ci::Pipeline/176',
jobs: {
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index 12034346aba..945727cd664 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlDrawer, GlInfiniteScroll } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -12,8 +13,7 @@ jest.mock('~/whats_new/utils/get_drawer_body_height', () => ({
getDrawerBodyHeight: jest.fn().mockImplementation(() => MOCK_DRAWER_BODY_HEIGHT),
}));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('App', () => {
let wrapper;
@@ -46,7 +46,6 @@ describe('App', () => {
});
wrapper = mount(App, {
- localVue,
store,
propsData: buildProps(),
directives: {
@@ -68,7 +67,7 @@ describe('App', () => {
{ title: 'Whats New Drawer', url: 'www.url.com', release: 3.11 },
];
wrapper.vm.$store.state.drawerBodyHeight = MOCK_DRAWER_BODY_HEIGHT;
- await wrapper.vm.$nextTick();
+ await nextTick();
};
afterEach(() => {
@@ -109,7 +108,7 @@ describe('App', () => {
it.each([true, false])('passes open property', async (openState) => {
wrapper.vm.$store.state.open = openState;
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getDrawer().props('open')).toBe(openState);
});
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index 9741a193258..a98722bc465 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -34,3 +34,17 @@ export const updateWorkItemMutationResponse = {
},
},
};
+
+export const projectWorkItemTypesQueryResponse = {
+ data: {
+ workspace: {
+ id: '1',
+ workItemTypes: {
+ nodes: [
+ { id: 'work-item-1', name: 'Issue' },
+ { id: 'work-item-2', name: 'Incident' },
+ ],
+ },
+ },
+ },
+};
diff --git a/spec/frontend/work_items/pages/create_work_item_spec.js b/spec/frontend/work_items/pages/create_work_item_spec.js
index 71e153d30c3..b9fef0eaa6a 100644
--- a/spec/frontend/work_items/pages/create_work_item_spec.js
+++ b/spec/frontend/work_items/pages/create_work_item_spec.js
@@ -1,12 +1,14 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { GlAlert } from '@gitlab/ui';
+import { GlAlert, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
import ItemTitle from '~/work_items/components/item_title.vue';
import { resolvers } from '~/work_items/graphql/resolvers';
+import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
+import { projectWorkItemTypesQueryResponse } from '../mock_data';
Vue.use(VueApollo);
@@ -14,13 +16,20 @@ describe('Create work item component', () => {
let wrapper;
let fakeApollo;
+ const querySuccessHandler = jest.fn().mockResolvedValue(projectWorkItemTypesQueryResponse);
+
const findAlert = () => wrapper.findComponent(GlAlert);
const findTitleInput = () => wrapper.findComponent(ItemTitle);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+
const findCreateButton = () => wrapper.find('[data-testid="create-button"]');
const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
+ const findContent = () => wrapper.find('[data-testid="content"]');
+ const findLoadingTypesIcon = () => wrapper.find('[data-testid="loading-types"]');
- const createComponent = ({ data = {} } = {}) => {
- fakeApollo = createMockApollo([], resolvers);
+ const createComponent = ({ data = {}, props = {}, queryHandler = querySuccessHandler } = {}) => {
+ fakeApollo = createMockApollo([[projectWorkItemTypesQuery, queryHandler]], resolvers);
wrapper = shallowMount(CreateWorkItem, {
apolloProvider: fakeApollo,
data() {
@@ -28,12 +37,18 @@ describe('Create work item component', () => {
...data,
};
},
+ propsData: {
+ ...props,
+ },
mocks: {
$router: {
go: jest.fn(),
push: jest.fn(),
},
},
+ provide: {
+ fullPath: 'full-path',
+ },
});
};
@@ -54,40 +69,141 @@ describe('Create work item component', () => {
expect(findCreateButton().props('disabled')).toBe(true);
});
- it('redirects to the previous page on Cancel button click', () => {
+ describe('when displayed on a separate route', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('redirects to the previous page on Cancel button click', () => {
+ findCancelButton().vm.$emit('click');
+
+ expect(wrapper.vm.$router.go).toHaveBeenCalledWith(-1);
+ });
+
+ it('redirects to the work item page on successful mutation', async () => {
+ findTitleInput().vm.$emit('title-input', 'Test title');
+
+ wrapper.find('form').trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.vm.$router.push).toHaveBeenCalled();
+ });
+
+ it('adds right margin for create button', () => {
+ expect(findCreateButton().classes()).toContain('gl-mr-3');
+ });
+
+ it('does not add right margin for cancel button', () => {
+ expect(findCancelButton().classes()).not.toContain('gl-mr-3');
+ });
+
+ it('does not add padding for content', () => {
+ expect(findContent().classes('gl-px-5')).toBe(false);
+ });
+ });
+
+ describe('when displayed in a modal', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ isModal: true,
+ },
+ });
+ });
+
+ it('emits `closeModal` event on Cancel button click', () => {
+ findCancelButton().vm.$emit('click');
+
+ expect(wrapper.emitted('closeModal')).toEqual([[]]);
+ });
+
+ it('emits `onCreate` on successful mutation', async () => {
+ const mockTitle = 'Test title';
+ findTitleInput().vm.$emit('title-input', 'Test title');
+
+ wrapper.find('form').trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.emitted('onCreate')).toEqual([[mockTitle]]);
+ });
+
+ it('does not right margin for create button', () => {
+ expect(findCreateButton().classes()).not.toContain('gl-mr-3');
+ });
+
+ it('adds right margin for cancel button', () => {
+ expect(findCancelButton().classes()).toContain('gl-mr-3');
+ });
+
+ it('adds padding for content', () => {
+ expect(findContent().classes('gl-px-5')).toBe(true);
+ });
+ });
+
+ it('displays a loading icon inside dropdown when work items query is loading', () => {
createComponent();
- findCancelButton().vm.$emit('click');
- expect(wrapper.vm.$router.go).toHaveBeenCalledWith(-1);
+ expect(findLoadingTypesIcon().exists()).toBe(true);
+ });
+
+ it('displays an alert when work items query is rejected', async () => {
+ createComponent({ queryHandler: jest.fn().mockRejectedValue('Houston, we have a problem') });
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toContain('fetching work item types');
+ });
+
+ describe('when work item types are fetched', () => {
+ beforeEach(() => {
+ createComponent();
+ return waitForPromises();
+ });
+
+ it('displays a list of work item types', () => {
+ expect(findDropdownItems()).toHaveLength(2);
+ expect(findDropdownItems().at(0).text()).toContain('Issue');
+ });
+
+ it('selects a work item type on click', async () => {
+ expect(findDropdown().props('text')).toBe('Type');
+ findDropdownItems().at(0).vm.$emit('click');
+ await nextTick();
+
+ expect(findDropdown().props('text')).toBe('Issue');
+ });
});
it('hides the alert on dismissing the error', async () => {
createComponent({ data: { error: true } });
+
expect(findAlert().exists()).toBe(true);
findAlert().vm.$emit('dismiss');
await nextTick();
+
expect(findAlert().exists()).toBe(false);
});
+ it('displays an initial title if passed', () => {
+ const initialTitle = 'Initial Title';
+ createComponent({
+ props: { initialTitle },
+ });
+ expect(findTitleInput().props('initialTitle')).toBe(initialTitle);
+ });
+
describe('when title input field has a text', () => {
- beforeEach(async () => {
+ beforeEach(() => {
const mockTitle = 'Test title';
createComponent();
- await findTitleInput().vm.$emit('title-input', mockTitle);
+ findTitleInput().vm.$emit('title-input', mockTitle);
});
it('renders a non-disabled Create button', () => {
expect(findCreateButton().props('disabled')).toBe(false);
});
- it('redirects to the work item page on successful mutation', async () => {
- wrapper.find('form').trigger('submit');
- await waitForPromises();
-
- expect(wrapper.vm.$router.push).toHaveBeenCalled();
- });
-
// TODO: write a proper test here when we have a backend implementation
it.todo('shows an alert on mutation error');
});
diff --git a/spec/frontend/work_items/pages/work_item_root_spec.js b/spec/frontend/work_items/pages/work_item_root_spec.js
index ea26b2b4fb3..d0e40680b55 100644
--- a/spec/frontend/work_items/pages/work_item_root_spec.js
+++ b/spec/frontend/work_items/pages/work_item_root_spec.js
@@ -23,7 +23,11 @@ describe('Work items root component', () => {
const findTitle = () => wrapper.findComponent(ItemTitle);
const createComponent = ({ queryResponse = workItemQueryResponse } = {}) => {
- fakeApollo = createMockApollo([], resolvers);
+ fakeApollo = createMockApollo([], resolvers, {
+ possibleTypes: {
+ LocalWorkItemWidget: ['LocalTitleWidget'],
+ },
+ });
fakeApollo.clients.defaultClient.cache.writeQuery({
query: workItemQuery,
variables: {
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
index 6017c9d9dbb..c583b5a5d4f 100644
--- a/spec/frontend/work_items/router_spec.js
+++ b/spec/frontend/work_items/router_spec.js
@@ -15,6 +15,16 @@ describe('Work items router', () => {
wrapper = mount(App, {
router,
+ provide: {
+ fullPath: 'full-path',
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ workItemTypes: {},
+ },
+ },
+ },
});
};
diff --git a/spec/frontend/work_items_hierarchy/components/app_spec.js b/spec/frontend/work_items_hierarchy/components/app_spec.js
new file mode 100644
index 00000000000..092e9c90553
--- /dev/null
+++ b/spec/frontend/work_items_hierarchy/components/app_spec.js
@@ -0,0 +1,63 @@
+import { nextTick } from 'vue';
+import { createLocalVue, mount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import { GlBanner } from '@gitlab/ui';
+import App from '~/work_items_hierarchy/components/app.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('WorkItemsHierarchy App', () => {
+ let wrapper;
+ const createComponent = (props = {}, data = {}) => {
+ wrapper = extendedWrapper(
+ mount(App, {
+ localVue,
+ provide: {
+ illustrationPath: '/foo.svg',
+ licensePlan: 'free',
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('survey banner', () => {
+ it('shows when the banner is visible', () => {
+ createComponent({}, { bannerVisible: true });
+
+ expect(wrapper.find(GlBanner).exists()).toBe(true);
+ });
+
+ it('hide when close is called', async () => {
+ createComponent({}, { bannerVisible: true });
+
+ wrapper.findByTestId('close-icon').trigger('click');
+
+ await nextTick();
+
+ expect(wrapper.find(GlBanner).exists()).toBe(false);
+ });
+ });
+
+ describe('Unavailable structure', () => {
+ it.each`
+ licensePlan | visible
+ ${'free'} | ${true}
+ ${'premium'} | ${true}
+ ${'ultimate'} | ${false}
+ `('visibility is $visible when plan is $licensePlan', ({ licensePlan, visible }) => {
+ createComponent({ licensePlan });
+
+ expect(wrapper.findByTestId('unavailable-structure').exists()).toBe(visible);
+ });
+ });
+});
diff --git a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
new file mode 100644
index 00000000000..74774e38d6b
--- /dev/null
+++ b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
@@ -0,0 +1,118 @@
+import { createLocalVue, mount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import { GlBadge } from '@gitlab/ui';
+import Hierarchy from '~/work_items_hierarchy/components/hierarchy.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RESPONSE from '~/work_items_hierarchy/static_response';
+import { workItemTypes } from '~/work_items_hierarchy/constants';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('WorkItemsHierarchy Hierarchy', () => {
+ let wrapper;
+
+ const workItemsFromResponse = (response) => {
+ return response.reduce(
+ (itemTypes, item) => {
+ const key = item.available ? 'available' : 'unavailable';
+ itemTypes[key].push({
+ ...item,
+ ...workItemTypes[item.type],
+ nestedTypes: item.nestedTypes
+ ? item.nestedTypes.map((type) => workItemTypes[type])
+ : null,
+ });
+ return itemTypes;
+ },
+ { available: [], unavailable: [] },
+ );
+ };
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ mount(Hierarchy, {
+ localVue,
+ propsData: {
+ workItemTypes: props.workItemTypes,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('available structure', () => {
+ let items = [];
+
+ beforeEach(() => {
+ items = workItemsFromResponse(RESPONSE.ultimate).available;
+ createComponent({ workItemTypes: items });
+ });
+
+ it('renders all work items', () => {
+ expect(wrapper.findAllByTestId('work-item-wrapper')).toHaveLength(items.length);
+ });
+
+ it('does not render badges', () => {
+ expect(wrapper.find(GlBadge).exists()).toBe(false);
+ });
+ });
+
+ describe('unavailable structure', () => {
+ let items = [];
+
+ beforeEach(() => {
+ items = workItemsFromResponse(RESPONSE.premium).unavailable;
+ createComponent({ workItemTypes: items });
+ });
+
+ it('renders all work items', () => {
+ expect(wrapper.findAllByTestId('work-item-wrapper')).toHaveLength(items.length);
+ });
+
+ it('renders license badges for all work items', () => {
+ expect(wrapper.findAll(GlBadge)).toHaveLength(items.length);
+ });
+
+ it('does not render svg icon for linking', () => {
+ expect(wrapper.findByTestId('hierarchy-rounded-arrow-tail').exists()).toBe(false);
+ expect(wrapper.findByTestId('level-up-icon').exists()).toBe(false);
+ });
+ });
+
+ describe('nested work items', () => {
+ describe.each`
+ licensePlan | arrowTailVisible | levelUpIconVisible | arrowDownIconVisible
+ ${'ultimate'} | ${true} | ${true} | ${true}
+ ${'premium'} | ${false} | ${false} | ${true}
+ ${'free'} | ${false} | ${false} | ${false}
+ `(
+ 'when $licensePlan license',
+ ({ licensePlan, arrowTailVisible, levelUpIconVisible, arrowDownIconVisible }) => {
+ let items = [];
+ beforeEach(() => {
+ items = workItemsFromResponse(RESPONSE[licensePlan]).available;
+ createComponent({ workItemTypes: items });
+ });
+
+ it(`${arrowTailVisible ? 'render' : 'does not render'} arrow tail svg`, () => {
+ expect(wrapper.findByTestId('hierarchy-rounded-arrow-tail').exists()).toBe(
+ arrowTailVisible,
+ );
+ });
+
+ it(`${levelUpIconVisible ? 'render' : 'does not render'} arrow tail svg`, () => {
+ expect(wrapper.findByTestId('level-up-icon').exists()).toBe(levelUpIconVisible);
+ });
+
+ it(`${arrowDownIconVisible ? 'render' : 'does not render'} arrow tail svg`, () => {
+ expect(wrapper.findByTestId('arrow-down-icon').exists()).toBe(arrowDownIconVisible);
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/work_items_hierarchy/hierarchy_util_spec.js b/spec/frontend/work_items_hierarchy/hierarchy_util_spec.js
new file mode 100644
index 00000000000..9042fa27d16
--- /dev/null
+++ b/spec/frontend/work_items_hierarchy/hierarchy_util_spec.js
@@ -0,0 +1,16 @@
+import { inferLicensePlan } from '~/work_items_hierarchy/hierarchy_util';
+import { LICENSE_PLAN } from '~/work_items_hierarchy/constants';
+
+describe('inferLicensePlan', () => {
+ it.each`
+ epics | subEpics | licensePlan
+ ${true} | ${true} | ${LICENSE_PLAN.ULTIMATE}
+ ${true} | ${false} | ${LICENSE_PLAN.PREMIUM}
+ ${false} | ${false} | ${LICENSE_PLAN.FREE}
+ `(
+ 'returns $licensePlan when epic is $epics and sub-epic is $subEpics',
+ ({ epics, subEpics, licensePlan }) => {
+ expect(inferLicensePlan({ hasEpics: epics, hasSubEpics: subEpics })).toBe(licensePlan);
+ },
+ );
+});
diff --git a/spec/frontend/zen_mode_spec.js b/spec/frontend/zen_mode_spec.js
index 13f221fd9d9..44684619fae 100644
--- a/spec/frontend/zen_mode_spec.js
+++ b/spec/frontend/zen_mode_spec.js
@@ -45,6 +45,8 @@ describe('ZenMode', () => {
// Set this manually because we can't actually scroll the window
zen.scroll_position = 456;
+
+ gon.features = { markdownContinueLists: true };
});
describe('enabling dropzone', () => {
diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js
index 5f1a5b0d048..aad9b9e526c 100644
--- a/spec/frontend_integration/ide/ide_integration_spec.js
+++ b/spec/frontend_integration/ide/ide_integration_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { setTestTimeout } from 'helpers/timeout';
import waitForPromises from 'helpers/wait_for_promises';
import { waitForText } from 'helpers/wait_for_text';
@@ -134,7 +135,7 @@ describe('WebIDE', () => {
describe('when editor position changes', () => {
beforeEach(async () => {
editor.setPosition({ lineNumber: 4, column: 10 });
- await vm.$nextTick();
+ await nextTick();
});
it('shows new line position', () => {
@@ -145,7 +146,7 @@ describe('WebIDE', () => {
it('updates after rename', async () => {
await ideHelper.renameFile('README.md', 'READMEZ.txt');
await ideHelper.waitForEditorModelChange(editor);
- await vm.$nextTick();
+ await nextTick();
expect(statusBar).toHaveText('1:1');
expect(statusBar).toHaveText('plaintext');
@@ -166,7 +167,7 @@ describe('WebIDE', () => {
await ideHelper.closeFile('README.md');
await ideHelper.openFile('README.md');
await ideHelper.waitForMonacoEditor();
- await vm.$nextTick();
+ await nextTick();
expect(statusBar).toHaveText('4:10');
expect(statusBar).toHaveText('markdown');
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
index faf19104731..514f63a6f5a 100644
--- a/spec/graphql/features/authorization_spec.rb
+++ b/spec/graphql/features/authorization_spec.rb
@@ -326,7 +326,7 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
let!(:other_project) { create(:project, :private) }
let!(:visible_issues) { create_list(:issue, 2, project: visible_project) }
let!(:other_issues) { create_list(:issue, 2, project: other_project) }
- let!(:user) { visible_project.owner }
+ let!(:user) { visible_project.first_owner }
let(:issue_type) do
type_factory do |type|
diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb
index 0b53c633077..2d83edca363 100644
--- a/spec/graphql/graphql_triggers_spec.rb
+++ b/spec/graphql/graphql_triggers_spec.rb
@@ -17,4 +17,18 @@ RSpec.describe GraphqlTriggers do
GraphqlTriggers.issuable_assignees_updated(issue)
end
end
+
+ describe '.issuable_title_updated' do
+ it 'triggers the issuableTitleUpdated subscription' do
+ work_item = create(:work_item)
+
+ expect(GitlabSchema.subscriptions).to receive(:trigger).with(
+ 'issuableTitleUpdated',
+ { issuable_id: work_item.to_gid },
+ work_item
+ ).and_call_original
+
+ GraphqlTriggers.issuable_title_updated(work_item)
+ end
+ end
end
diff --git a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
index 8ec99070c91..ea5e21ec4b8 100644
--- a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+++ b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Mutations::AlertManagement::Alerts::Todo::Create do
let_it_be(:alert) { create(:alert_management_alert) }
let_it_be(:project) { alert.project }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:args) { { project_path: project.full_path, iid: alert.iid } }
diff --git a/spec/graphql/mutations/ci/runner/delete_spec.rb b/spec/graphql/mutations/ci/runner/delete_spec.rb
index 9f30c95edd5..b53ee30f826 100644
--- a/spec/graphql/mutations/ci/runner/delete_spec.rb
+++ b/spec/graphql/mutations/ci/runner/delete_spec.rb
@@ -11,9 +11,7 @@ RSpec.describe Mutations::Ci::Runner::Delete do
let(:current_ctx) { { current_user: user } }
let(:mutation_params) do
- {
- id: runner.to_global_id
- }
+ { id: runner.to_global_id }
end
specify { expect(described_class).to require_graphql_authorizations(:delete_runner) }
@@ -57,6 +55,10 @@ RSpec.describe Mutations::Ci::Runner::Delete do
it 'deletes runner' do
mutation_params[:id] = project_runner.to_global_id
+ expect_next_instance_of(::Ci::UnregisterRunnerService, project_runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
expect { subject }.to change { Ci::Runner.count }.by(-1)
expect(subject[:errors]).to be_empty
end
@@ -73,6 +75,9 @@ RSpec.describe Mutations::Ci::Runner::Delete do
it 'does not delete project runner' do
mutation_params[:id] = two_projects_runner.to_global_id
+ allow_next_instance_of(::Ci::UnregisterRunnerService) do |service|
+ expect(service).not_to receive(:execute).once
+ end
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
@@ -84,6 +89,10 @@ RSpec.describe Mutations::Ci::Runner::Delete do
let(:current_ctx) { { current_user: admin_user } }
it 'deletes runner' do
+ expect_next_instance_of(::Ci::UnregisterRunnerService, runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
expect { subject }.to change { Ci::Runner.count }.by(-1)
expect(subject[:errors]).to be_empty
end
diff --git a/spec/graphql/mutations/issues/create_spec.rb b/spec/graphql/mutations/issues/create_spec.rb
index 825d04ff827..e3094e84703 100644
--- a/spec/graphql/mutations/issues/create_spec.rb
+++ b/spec/graphql/mutations/issues/create_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe Mutations::Issues::Create do
end
context 'when creating an issue as owner' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
before do
mutation_params.merge!(special_params)
diff --git a/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb b/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb
new file mode 100644
index 00000000000..07b4a5509b2
--- /dev/null
+++ b/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::ProjectPipelineCountsResolver do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
+ let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') }
+ let_it_be(:sha_pipeline) { create(:ci_pipeline, :running, project: project, sha: 'deadbeef') }
+ let_it_be(:on_demand_dast_scan) { create(:ci_pipeline, :success, project: project, source: 'ondemand_dast_scan') }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ describe '#resolve' do
+ it 'counts pipelines' do
+ expect(resolve_pipeline_counts).to have_attributes(
+ all: 6,
+ finished: 3,
+ running: 1,
+ pending: 2
+ )
+ end
+
+ it 'counts by ref' do
+ expect(resolve_pipeline_counts(ref: "awesome-feature")).to have_attributes(
+ all: 1,
+ finished: 0,
+ running: 0,
+ pending: 1
+ )
+ end
+
+ it 'counts by sha' do
+ expect(resolve_pipeline_counts(sha: "deadbeef")).to have_attributes(
+ all: 1,
+ finished: 0,
+ running: 1,
+ pending: 0
+ )
+ end
+
+ it 'counts by source' do
+ expect(resolve_pipeline_counts(source: "ondemand_dast_scan")).to have_attributes(
+ all: 1,
+ finished: 1,
+ running: 0,
+ pending: 0
+ )
+ end
+ end
+
+ def resolve_pipeline_counts(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb
new file mode 100644
index 00000000000..53b673e255b
--- /dev/null
+++ b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::RunnerJobsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:irrelevant_pipeline) { create(:ci_pipeline, project: project) }
+
+ let!(:build_one) { create(:ci_build, :success, name: 'Build One', runner: runner, pipeline: pipeline) }
+ let!(:build_two) { create(:ci_build, :success, name: 'Build Two', runner: runner, pipeline: pipeline) }
+ let!(:build_three) { create(:ci_build, :failed, name: 'Build Three', runner: runner, pipeline: pipeline) }
+ let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
+
+ let(:args) { {} }
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ subject { resolve_jobs(args) }
+
+ describe '#resolve' do
+ context 'with authorized user', :enable_admin_mode do
+ let(:current_user) { create(:user, :admin) }
+
+ context 'with statuses argument' do
+ let(:args) { { statuses: [Types::Ci::JobStatusEnum.coerce_isolated_input('SUCCESS')] } }
+
+ it { is_expected.to contain_exactly(build_one, build_two) }
+ end
+
+ context 'without statuses argument' do
+ it { is_expected.to contain_exactly(build_one, build_two, build_three) }
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ private
+
+ def resolve_jobs(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: runner, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index df6490df915..9251fbf24d9 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -43,34 +43,99 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
# Only thing we can do is to verify that args from the resolver is correctly transformed to params of the Finder and we return the Finder's result back.
describe 'Allowed query arguments' do
let(:finder) { instance_double(::Ci::RunnersFinder) }
- let(:args) do
- {
- active: true,
- status: 'active',
- type: :instance_type,
- tag_list: ['active_runner'],
- search: 'abc',
- sort: :contacted_asc
- }
+
+ context 'with active filter' do
+ let(:args) do
+ {
+ active: true,
+ status: 'active',
+ type: :instance_type,
+ tag_list: ['active_runner'],
+ search: 'abc',
+ sort: :contacted_asc
+ }
+ end
+
+ let(:expected_params) do
+ {
+ active: true,
+ status_status: 'active',
+ type_type: :instance_type,
+ tag_name: ['active_runner'],
+ preload: { tag_name: nil },
+ search: 'abc',
+ sort: 'contacted_asc'
+ }
+ end
+
+ it 'calls RunnersFinder with expected arguments' do
+ expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return([:execute_return_value])
+
+ expect(subject.items.to_a).to eq([:execute_return_value])
+ end
+ end
+
+ context 'with both active and paused filter' do
+ let(:args) do
+ {
+ active: true,
+ paused: true
+ }
+ end
+
+ let(:expected_params) do
+ {
+ active: false,
+ preload: { tag_name: nil }
+ }
+ end
+
+ it 'calls RunnersFinder with expected arguments' do
+ expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return([:execute_return_value])
+
+ expect(subject.items.to_a).to eq([:execute_return_value])
+ end
end
- let(:expected_params) do
- {
- active: true,
- status_status: 'active',
- type_type: :instance_type,
- tag_name: ['active_runner'],
- preload: { tag_name: nil },
- search: 'abc',
- sort: 'contacted_asc'
- }
+ context 'with paused filter' do
+ let(:args) do
+ { paused: true }
+ end
+
+ let(:expected_params) do
+ {
+ active: false,
+ preload: { tag_name: nil }
+ }
+ end
+
+ it 'calls RunnersFinder with expected arguments' do
+ expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return([:execute_return_value])
+
+ expect(subject.items.to_a).to eq([:execute_return_value])
+ end
end
- it 'calls RunnersFinder with expected arguments' do
- allow(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
- allow(finder).to receive(:execute).once.and_return([:execute_return_value])
+ context 'with neither paused or active filters' do
+ let(:args) do
+ {}
+ end
+
+ let(:expected_params) do
+ {
+ preload: { tag_name: nil }
+ }
+ end
+
+ it 'calls RunnersFinder with expected arguments' do
+ expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(subject.items.to_a).to eq([:execute_return_value])
+ end
end
end
end
diff --git a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
index 9b54d466681..866f4ce7b5a 100644
--- a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
+++ b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
describe '#resolve' do
let(:agent) { create(:cluster_agent) }
- let(:user) { create(:user, maintainer_projects: [agent.project]) }
+ let(:user) { create(:user, developer_projects: [agent.project]) }
let(:ctx) { Hash(current_user: user) }
let!(:matching_token1) { create(:cluster_agent_token, agent: agent, last_used_at: 5.days.ago) }
@@ -33,7 +33,11 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
end
context 'user does not have permission' do
- let(:user) { create(:user, developer_projects: [agent.project]) }
+ let(:user) { create(:user) }
+
+ before do
+ agent.project.add_reporter(user)
+ end
it { is_expected.to be_empty }
end
diff --git a/spec/graphql/resolvers/clusters/agents_resolver_spec.rb b/spec/graphql/resolvers/clusters/agents_resolver_spec.rb
index 70f40748e1d..152d7fa22c4 100644
--- a/spec/graphql/resolvers/clusters/agents_resolver_spec.rb
+++ b/spec/graphql/resolvers/clusters/agents_resolver_spec.rb
@@ -15,10 +15,14 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do
describe '#resolve' do
let_it_be(:project) { create(:project) }
- let_it_be(:maintainer) { create(:user, maintainer_projects: [project]) }
- let_it_be(:developer) { create(:user, developer_projects: [project]) }
+ let_it_be(:maintainer) { create(:user, developer_projects: [project]) }
+ let_it_be(:reporter) { create(:user) }
let_it_be(:agents) { create_list(:cluster_agent, 2, project: project) }
+ before do
+ project.add_reporter(reporter)
+ end
+
let(:ctx) { { current_user: current_user } }
subject { resolve_agents }
@@ -32,7 +36,7 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do
end
context 'the current user does not have access to clusters' do
- let(:current_user) { developer }
+ let(:current_user) { reporter }
it 'returns an empty result' do
expect(subject).to be_empty
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index 1d0eac30a23..e4eaeb9bc3c 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -321,7 +321,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
describe 'sorting' do
- let(:mrs) do
+ let_it_be(:mrs) do
[
merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4,
merge_request_3, merge_request_2, merge_request_1
@@ -363,28 +363,44 @@ RSpec.describe Resolvers::MergeRequestsResolver do
def merged_at(mr)
nils_last(mr.metrics.merged_at)
end
+ end
+
+ context 'when sorting by closed at' do
+ before do
+ merge_request_1.metrics.update!(latest_closed_at: 10.days.ago)
+ merge_request_3.metrics.update!(latest_closed_at: 5.days.ago)
+ end
+
+ it 'sorts merge requests ascending' do
+ expect(resolve_mr(project, sort: :closed_at_asc))
+ .to match_array(mrs)
+ .and be_sorted(->(mr) { [closed_at(mr), -mr.id] })
+ end
+
+ it 'sorts merge requests descending' do
+ expect(resolve_mr(project, sort: :closed_at_desc))
+ .to match_array(mrs)
+ .and be_sorted(->(mr) { [-closed_at(mr), -mr.id] })
+ end
+
+ def closed_at(mr)
+ nils_last(mr.metrics.latest_closed_at)
+ end
+ end
+
+ context 'when sorting by title' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:mr1) { create(:merge_request, :unique_branches, title: 'foo', source_project: project) }
+ let_it_be(:mr2) { create(:merge_request, :unique_branches, title: 'bar', source_project: project) }
+ let_it_be(:mr3) { create(:merge_request, :unique_branches, title: 'baz', source_project: project) }
+ let_it_be(:mr4) { create(:merge_request, :unique_branches, title: 'Baz 2', source_project: project) }
+
+ it 'sorts issues ascending' do
+ expect(resolve_mr(project, sort: :title_asc).to_a).to eq [mr2, mr3, mr4, mr1]
+ end
- context 'when sorting by closed at' do
- before do
- merge_request_1.metrics.update!(latest_closed_at: 10.days.ago)
- merge_request_3.metrics.update!(latest_closed_at: 5.days.ago)
- end
-
- it 'sorts merge requests ascending' do
- expect(resolve_mr(project, sort: :closed_at_asc))
- .to match_array(mrs)
- .and be_sorted(->(mr) { [closed_at(mr), -mr.id] })
- end
-
- it 'sorts merge requests descending' do
- expect(resolve_mr(project, sort: :closed_at_desc))
- .to match_array(mrs)
- .and be_sorted(->(mr) { [-closed_at(mr), -mr.id] })
- end
-
- def closed_at(mr)
- nils_last(mr.metrics.latest_closed_at)
- end
+ it 'sorts issues descending' do
+ expect(resolve_mr(project, sort: :title_desc).to_a).to eq [mr1, mr4, mr3, mr2]
end
end
end
diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb
index d6acb31d4e3..c8ee489a034 100644
--- a/spec/graphql/resolvers/package_details_resolver_spec.rb
+++ b/spec/graphql/resolvers/package_details_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::PackageDetailsResolver do
include GraphqlHelpers
let_it_be_with_reload(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:package) { create(:composer_package, project: project) }
describe '#resolve' do
diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
index d48d4d8ae01..892dc641201 100644
--- a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
+++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
@@ -8,15 +8,16 @@ RSpec.describe Resolvers::PackagePipelinesResolver do
let_it_be_with_reload(:package) { create(:package) }
let_it_be(:pipelines) { create_list(:ci_pipeline, 3, project: package.project) }
- let(:user) { package.project.owner }
+ let(:user) { package.project.first_owner }
let(:args) { {} }
describe '#resolve' do
subject { resolve(described_class, obj: package, args: args, ctx: { current_user: user }) }
before do
- package.pipelines = pipelines
- package.save!
+ pipelines.each do |pipeline|
+ create(:package_build_info, package: package, pipeline: pipeline)
+ end
end
it { is_expected.to contain_exactly(*pipelines) }
diff --git a/spec/graphql/resolvers/recent_boards_resolver_spec.rb b/spec/graphql/resolvers/recent_boards_resolver_spec.rb
new file mode 100644
index 00000000000..1afdcd42b4f
--- /dev/null
+++ b/spec/graphql/resolvers/recent_boards_resolver_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::RecentBoardsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+
+ shared_examples_for 'group and project recent boards resolver' do
+ let_it_be(:board1) { create(:board, name: 'One', resource_parent: board_parent) }
+ let_it_be(:board2) { create(:board, name: 'Two', resource_parent: board_parent) }
+
+ before do
+ [board1, board2].each { |board| visit_board(board, board_parent) }
+ end
+
+ it 'calls ::Boards::VisitsFinder' do
+ expect_any_instance_of(::Boards::VisitsFinder) do |finder|
+ expect(finder).to receive(:latest)
+ end
+
+ resolve_recent_boards
+ end
+
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new { resolve_recent_boards }
+
+ board3 = create(:board, resource_parent: board_parent)
+ visit_board(board3, board_parent)
+
+ expect { resolve_recent_boards(args: {}) }.not_to exceed_query_limit(control)
+ end
+
+ it 'returns most recent visited boards' do
+ expect(resolve_recent_boards).to match_array [board2, board1]
+ end
+
+ it 'returns a set number of boards' do
+ stub_const('Board::RECENT_BOARDS_SIZE', 1)
+
+ expect(resolve_recent_boards).to match_array [board2]
+ end
+ end
+
+ describe '#resolve' do
+ context 'when there is no parent' do
+ let_it_be(:board_parent) { nil }
+
+ it 'returns none if parent is nil' do
+ expect(resolve_recent_boards).to eq(Board.none)
+ end
+ end
+
+ context 'when project boards' do
+ let_it_be(:board_parent) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) }
+
+ it_behaves_like 'group and project recent boards resolver'
+ end
+
+ context 'when group boards' do
+ let_it_be(:board_parent) { create(:group) }
+
+ it_behaves_like 'group and project recent boards resolver'
+ end
+ end
+
+ def resolve_recent_boards(args: {})
+ resolve(described_class, obj: board_parent, args: args, ctx: { current_user: user })
+ end
+
+ def visit_board(board, parent)
+ if parent.is_a?(Group)
+ create(:board_group_recent_visit, group: parent, board: board, user: user)
+ else
+ create(:board_project_recent_visit, project: parent, board: board, user: user)
+ end
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_counts_type_spec.rb b/spec/graphql/types/ci/pipeline_counts_type_spec.rb
new file mode 100644
index 00000000000..7fdb286d253
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_counts_type_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PipelineCounts'] do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
+ let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') }
+ let_it_be(:sha_pipeline) { create(:ci_pipeline, :running, project: project, sha: 'deadbeef') }
+ let_it_be(:on_demand_dast_scan) { create(:ci_pipeline, :success, project: project, source: 'ondemand_dast_scan') }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ specify { expect(described_class.graphql_name).to eq('PipelineCounts') }
+
+ it 'has the expected fields' do
+ expected_fields = %w[
+ all
+ finished
+ pending
+ running
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+
+ shared_examples 'pipeline counts query' do |args: "", expected_counts:|
+ let_it_be(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelineCounts#{args} {
+ all
+ finished
+ pending
+ running
+ }
+ }
+ }
+ )
+ end
+
+ subject { GitlabSchema.execute(query, context: { current_user: current_user }).as_json }
+
+ it 'returns pipeline counts' do
+ actual_counts = subject.dig('data', 'project', 'pipelineCounts')
+
+ expect(actual_counts).to eq(expected_counts)
+ end
+ end
+
+ it_behaves_like "pipeline counts query", args: "", expected_counts: {
+ "all" => 6,
+ "finished" => 3,
+ "pending" => 2,
+ "running" => 1
+ }
+
+ it_behaves_like "pipeline counts query", args: '(ref: "awesome-feature")', expected_counts: {
+ "all" => 1,
+ "finished" => 0,
+ "pending" => 1,
+ "running" => 0
+ }
+
+ it_behaves_like "pipeline counts query", args: '(sha: "deadbeef")', expected_counts: {
+ "all" => 1,
+ "finished" => 0,
+ "pending" => 0,
+ "running" => 1
+ }
+
+ it_behaves_like "pipeline counts query", args: '(source: "ondemand_dast_scan")', expected_counts: {
+ "all" => 1,
+ "finished" => 1,
+ "pending" => 0,
+ "running" => 0
+ }
+end
diff --git a/spec/graphql/types/ci/runner_type_spec.rb b/spec/graphql/types/ci/runner_type_spec.rb
index 43d8b585d6b..7697cd0ef79 100644
--- a/spec/graphql/types/ci/runner_type_spec.rb
+++ b/spec/graphql/types/ci/runner_type_spec.rb
@@ -9,9 +9,10 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
it 'contains attributes related to a runner' do
expected_fields = %w[
- id description created_at contacted_at maximum_timeout access_level active status
+ id description created_at contacted_at maximum_timeout access_level active paused status
version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url edit_admin_url user_permissions executor_name
+ groups projects jobs token_expires_at
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/clusters/agent_activity_event_type_spec.rb b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
index 7773bad749d..cae75485846 100644
--- a/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['ClusterAgentActivityEvent'] do
let(:fields) { %i[recorded_at kind level user agent_token] }
it { expect(described_class.graphql_name).to eq('ClusterAgentActivityEvent') }
- it { expect(described_class).to require_graphql_authorizations(:admin_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
it { expect(described_class).to have_graphql_fields(fields) }
end
diff --git a/spec/graphql/types/clusters/agent_token_type_spec.rb b/spec/graphql/types/clusters/agent_token_type_spec.rb
index 3f0720cb4b5..1ca6d690c80 100644
--- a/spec/graphql/types/clusters/agent_token_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_token_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ClusterAgentToken'] do
it { expect(described_class.graphql_name).to eq('ClusterAgentToken') }
- it { expect(described_class).to require_graphql_authorizations(:admin_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
it { expect(described_class).to have_graphql_fields(fields) }
end
diff --git a/spec/graphql/types/clusters/agent_type_spec.rb b/spec/graphql/types/clusters/agent_type_spec.rb
index a1e5952bf73..3f4faccf15d 100644
--- a/spec/graphql/types/clusters/agent_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ClusterAgent'] do
it { expect(described_class.graphql_name).to eq('ClusterAgent') }
- it { expect(described_class).to require_graphql_authorizations(:admin_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
it { expect(described_class).to have_graphql_fields(fields) }
end
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb
index 4efa3018dad..e7e69cfad9e 100644
--- a/spec/graphql/types/global_id_type_spec.rb
+++ b/spec/graphql/types/global_id_type_spec.rb
@@ -191,7 +191,7 @@ RSpec.describe Types::GlobalIDType do
describe 'executing against the schema' do
let(:query_result) do
- context = { current_user: issue.project.owner }
+ context = { current_user: issue.project.first_owner }
variables = { 'id' => gid }
run_with_clean_state(query, context: context, variables: variables).to_h
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 0ba322a100a..82703948cea 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe GitlabSchema.types['Group'] do
dependency_proxy_blob_count dependency_proxy_total_size
dependency_proxy_image_prefix dependency_proxy_image_ttl_policy
shared_runners_setting timelogs organizations contacts work_item_types
+ recent_issue_boards
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/issuable_type_spec.rb b/spec/graphql/types/issuable_type_spec.rb
index 992a58f524b..cb18bbe2eab 100644
--- a/spec/graphql/types/issuable_type_spec.rb
+++ b/spec/graphql/types/issuable_type_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['Issuable'] do
it 'returns possible types' do
- expect(described_class.possible_types).to include(Types::IssueType, Types::MergeRequestType)
+ expect(described_class.possible_types).to include(Types::IssueType, Types::MergeRequestType, Types::WorkItemType)
end
describe '.resolve_type' do
@@ -16,6 +16,10 @@ RSpec.describe GitlabSchema.types['Issuable'] do
expect(described_class.resolve_type(build(:merge_request), {})).to eq(Types::MergeRequestType)
end
+ it 'resolves work items' do
+ expect(described_class.resolve_type(build(:work_item), {})).to eq(Types::WorkItemType)
+ end
+
it 'raises an error for invalid types' do
expect { described_class.resolve_type(build(:user), {}) }.to raise_error 'Unsupported issuable type'
end
diff --git a/spec/graphql/types/member_interface_spec.rb b/spec/graphql/types/member_interface_spec.rb
index 11fd09eb335..8ecaaa46bed 100644
--- a/spec/graphql/types/member_interface_spec.rb
+++ b/spec/graphql/types/member_interface_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Types::MemberInterface do
updated_at
expires_at
user
+ merge_request_interaction
]
expect(described_class).to have_graphql_fields(*expected_fields)
@@ -40,4 +41,16 @@ RSpec.describe Types::MemberInterface do
end
end
end
+
+ describe '#merge_request_interaction' do
+ subject { described_class.fields['mergeRequestInteraction'] }
+
+ it 'returns the correct type' do
+ is_expected.to have_graphql_type(Types::UserMergeRequestInteractionType)
+ end
+
+ it 'has the correct arguments' do
+ expect(subject.arguments).to have_key('id')
+ end
+ end
end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 961e12288d4..7433d465b38 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe GitlabSchema.types['Project'] do
only_allow_merge_if_pipeline_succeeds request_access_enabled
only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled
namespace group statistics repository merge_requests merge_request issues
- issue milestones pipelines removeSourceBranchAfterMerge sentryDetailedError snippets
+ issue milestones pipelines removeSourceBranchAfterMerge pipeline_counts sentryDetailedError snippets
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
@@ -35,6 +35,7 @@ RSpec.describe GitlabSchema.types['Project'] do
pipeline_analytics squash_read_only sast_ci_configuration
cluster_agent cluster_agents agent_configurations
ci_template timelogs merge_commit_template squash_commit_template work_item_types
+ recent_issue_boards ci_config_path_or_default
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -299,6 +300,8 @@ RSpec.describe GitlabSchema.types['Project'] do
:merged_before,
:created_after,
:created_before,
+ :updated_after,
+ :updated_before,
:author_username,
:assignee_username,
:reviewer_username,
@@ -309,6 +312,13 @@ RSpec.describe GitlabSchema.types['Project'] do
end
end
+ describe 'pipelineCounts field' do
+ subject { described_class.fields['pipelineCounts'] }
+
+ it { is_expected.to have_graphql_type(Types::Ci::PipelineCountsType) }
+ it { is_expected.to have_graphql_resolver(Resolvers::Ci::ProjectPipelineCountsResolver) }
+ end
+
describe 'snippets field' do
subject { described_class.fields['snippets'] }
diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb
index 8d845e5d814..565341d15b9 100644
--- a/spec/graphql/types/repository/blob_type_spec.rb
+++ b/spec/graphql/types/repository/blob_type_spec.rb
@@ -29,6 +29,8 @@ RSpec.describe Types::Repository::BlobType do
:blame_path,
:history_path,
:permalink_path,
+ :environment_formatted_external_url,
+ :environment_external_url_for_route_map,
:code_owners,
:simple_viewer,
:rich_viewer,
@@ -39,7 +41,8 @@ RSpec.describe Types::Repository::BlobType do
:ide_edit_path,
:external_storage_url,
:fork_and_edit_path,
- :ide_fork_and_edit_path
+ :ide_fork_and_edit_path,
+ :language
)
end
end
diff --git a/spec/graphql/types/root_storage_statistics_type_spec.rb b/spec/graphql/types/root_storage_statistics_type_spec.rb
index 4fef8f6eafd..7818be6ee02 100644
--- a/spec/graphql/types/root_storage_statistics_type_spec.rb
+++ b/spec/graphql/types/root_storage_statistics_type_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] do
it 'has all the required fields' do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :wiki_size, :snippets_size,
- :pipeline_artifacts_size, :uploads_size)
+ :pipeline_artifacts_size, :uploads_size, :dependency_proxy_size)
end
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
diff --git a/spec/graphql/types/subscription_type_spec.rb b/spec/graphql/types/subscription_type_spec.rb
index bf933945a31..593795de004 100644
--- a/spec/graphql/types/subscription_type_spec.rb
+++ b/spec/graphql/types/subscription_type_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe GitlabSchema.types['Subscription'] do
expected_fields = %i[
issuable_assignees_updated
issue_crm_contacts_updated
+ issuable_title_updated
]
expect(described_class).to have_graphql_fields(*expected_fields).only
diff --git a/spec/graphql/types/user_preferences_type_spec.rb b/spec/graphql/types/user_preferences_type_spec.rb
new file mode 100644
index 00000000000..fac45443290
--- /dev/null
+++ b/spec/graphql/types/user_preferences_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::UserPreferencesType do
+ specify { expect(described_class.graphql_name).to eq('UserPreferences') }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ issues_sort
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index 4e3f442dc71..a2fc8f4c954 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -67,14 +67,14 @@ RSpec.describe GitlabSchema.types['User'] do
)
end
- subject { GitlabSchema.execute(query, context: { current_user: current_user }).as_json.dig('data', 'user', 'name') }
+ subject(:user_name) { GitlabSchema.execute(query, context: { current_user: current_user }).as_json.dig('data', 'user', 'name') }
context 'user requests' do
let(:current_user) { user }
context 'a user' do
it 'returns name' do
- expect(subject).to eq('John Smith')
+ expect(user_name).to eq('John Smith')
end
end
@@ -85,21 +85,39 @@ RSpec.describe GitlabSchema.types['User'] do
let(:current_user) { nil }
it 'returns `****`' do
- expect(subject).to eq('****')
+ expect(user_name).to eq('****')
end
end
- it 'returns `****` for a regular user' do
- expect(subject).to eq('****')
+ context 'when the requester is not a project member' do
+ it 'returns `Project bot` for a non project member in a public project' do
+ expect(user_name).to eq('Project bot')
+ end
+
+ context 'in a private project' do
+ let(:project) { create(:project, :private) }
+
+ it 'returns `****` for a non project member in a private project' do
+ expect(user_name).to eq('****')
+ end
+ end
end
- context 'when requester is a project maintainer' do
+ context 'with a project member' do
before do
- project.add_maintainer(user)
+ project.add_guest(user)
+ end
+
+ it 'returns `Project bot` for a project member' do
+ expect(user_name).to eq('Project bot')
end
- it 'returns name' do
- expect(subject).to eq('Project bot')
+ context 'in a private project' do
+ let(:project) { create(:project, :private) }
+
+ it 'returns `Project bot` for a project member in a private project' do
+ expect(user_name).to eq('Project bot')
+ end
end
end
end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 8c2b4b16075..e6a2e3f8211 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -289,7 +289,7 @@ RSpec.describe ApplicationHelper do
it 'returns paths for autocomplete_sources_controller' do
sources = helper.autocomplete_data_sources(project, noteable_type)
- expect(sources.keys).to match_array([:members, :issues, :mergeRequests, :labels, :milestones, :commands, :snippets])
+ expect(sources.keys).to match_array([:members, :issues, :mergeRequests, :labels, :milestones, :commands, :snippets, :contacts])
sources.keys.each do |key|
expect(sources[key]).not_to be_nil
end
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index e722f301522..169b1c75995 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -46,6 +46,15 @@ RSpec.describe ApplicationSettingsHelper do
expect(helper.visible_attributes).to include(:deactivate_dormant_users)
end
+ it 'contains rate limit parameters' do
+ expect(helper.visible_attributes).to include(*%i(
+ issues_create_limit notes_create_limit project_export_limit
+ project_download_export_limit project_export_limit project_import_limit
+ raw_blob_request_limit group_export_limit group_download_export_limit
+ group_import_limit users_get_by_id_limit user_email_lookup_limit
+ ))
+ end
+
context 'when GitLab.com' do
before do
allow(Gitlab).to receive(:com?).and_return(true)
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index 7190f2fcd4a..192e48f43e5 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -146,11 +146,52 @@ RSpec.describe AvatarsHelper do
describe '#avatar_icon_for_user' do
let(:user) { create(:user, avatar: File.open(uploaded_image_temp_path)) }
+ shared_examples 'blocked or unconfirmed user with avatar' do
+ context 'when the viewer is not an admin' do
+ let!(:viewing_user) { create(:user) }
+
+ it 'returns the default avatar' do
+ expect(helper.avatar_icon_for_user(user, current_user: viewing_user).to_s)
+ .to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
+ end
+ end
+
+ context 'when the viewer is an admin', :enable_admin_mode do
+ let!(:viewing_user) { create(:user, :admin) }
+
+ it 'returns the default avatar when the user is not passed' do
+ expect(helper.avatar_icon_for_user(user).to_s)
+ .to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
+ end
+
+ it 'returns the user avatar when the user is passed' do
+ expect(helper.avatar_icon_for_user(user, current_user: viewing_user).to_s)
+ .to eq(user.avatar.url)
+ end
+ end
+ end
+
context 'with a user object passed' do
it 'returns a relative URL for the avatar' do
expect(helper.avatar_icon_for_user(user).to_s)
.to eq(user.avatar.url)
end
+
+ context 'when the user is blocked' do
+ before do
+ user.block!
+ end
+
+ it_behaves_like 'blocked or unconfirmed user with avatar'
+ end
+
+ context 'when the user is unconfirmed' do
+ before do
+ user.update!(confirmed_at: nil)
+ end
+
+ it_behaves_like 'blocked or unconfirmed user with avatar'
+ end
end
context 'without a user object passed' do
@@ -171,7 +212,7 @@ RSpec.describe AvatarsHelper do
end
it 'returns a generic avatar' do
- expect(helper.gravatar_icon(user_email)).to match_asset_path('no_avatar.png')
+ expect(helper.gravatar_icon(user_email)).to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
end
end
@@ -181,7 +222,7 @@ RSpec.describe AvatarsHelper do
end
it 'returns a generic avatar when email is blank' do
- expect(helper.gravatar_icon('')).to match_asset_path('no_avatar.png')
+ expect(helper.gravatar_icon('')).to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
end
it 'returns a valid Gravatar URL' do
@@ -428,7 +469,7 @@ RSpec.describe AvatarsHelper do
subject { helper.avatar_without_link(resource, options) }
context 'with users' do
- let(:resource) { user }
+ let(:resource) { user.namespace }
it 'displays user avatar' do
is_expected.to eq tag(
diff --git a/spec/helpers/bizible_helper_spec.rb b/spec/helpers/bizible_helper_spec.rb
new file mode 100644
index 00000000000..b82211d51ec
--- /dev/null
+++ b/spec/helpers/bizible_helper_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe BizibleHelper do
+ describe '#bizible_enabled?' do
+ before do
+ stub_config(extra: { bizible: SecureRandom.uuid })
+ end
+
+ context 'when bizible is disabled' do
+ before do
+ allow(helper).to receive(:bizible_enabled?).and_return(false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when bizible is enabled' do
+ before do
+ allow(helper).to receive(:bizible_enabled?).and_return(true)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ subject(:bizible_enabled?) { helper.bizible_enabled? }
+
+ context 'with ecomm_instrumentation feature flag disabled' do
+ before do
+ stub_feature_flags(ecomm_instrumentation: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'with ecomm_instrumentation feature flag enabled' do
+ context 'when no id is set' do
+ before do
+ stub_config(extra: {})
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+ end
+end
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index b15569f03c7..b844cc2e22b 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -88,6 +88,17 @@ RSpec.describe Ci::PipelineEditorHelper do
end
end
+ context 'with a project with no repository' do
+ let(:project) { create(:project) }
+
+ it 'returns pipeline editor data' do
+ expect(pipeline_editor_data).to include({
+ "pipeline_etag" => '',
+ "total-branches" => 0
+ })
+ end
+ end
+
context 'with a non-default branch name' do
let(:user) { create(:user) }
diff --git a/spec/helpers/clusters_helper_spec.rb b/spec/helpers/clusters_helper_spec.rb
index 51f111917d1..18d233fcd63 100644
--- a/spec/helpers/clusters_helper_spec.rb
+++ b/spec/helpers/clusters_helper_spec.rb
@@ -93,8 +93,9 @@ RSpec.describe ClustersHelper do
end
context 'user has no permissions to create a cluster' do
- it 'displays that user can\t add cluster' do
+ it 'displays that user can\'t add cluster' do
expect(subject[:can_add_cluster]).to eq("false")
+ expect(subject[:can_admin_cluster]).to eq("false")
end
end
@@ -105,6 +106,7 @@ RSpec.describe ClustersHelper do
it 'displays that the user can add cluster' do
expect(subject[:can_add_cluster]).to eq("true")
+ expect(subject[:can_admin_cluster]).to eq("true")
end
end
@@ -150,6 +152,10 @@ RSpec.describe ClustersHelper do
it 'displays kas address' do
expect(subject[:kas_address]).to eq(Gitlab::Kas.external_url)
end
+
+ it 'displays GitLab version' do
+ expect(subject[:gitlab_version]).to eq(Gitlab.version_info)
+ end
end
describe '#js_cluster_new' do
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index d8a97b93bc9..6a854a65920 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -15,6 +15,22 @@ RSpec.describe InviteMembersHelper do
helper.extend(Gitlab::Experimentation::ControllerConcern)
end
+ describe '#common_invite_group_modal_data' do
+ it 'has expected common attributes' do
+ attributes = {
+ id: project.id,
+ name: project.name,
+ default_access_level: Gitlab::Access::GUEST,
+ invalid_groups: project.related_group_ids,
+ help_link: help_page_url('user/permissions'),
+ is_project: 'true',
+ access_levels: ProjectMember.access_level_roles.to_json
+ }
+
+ expect(helper.common_invite_group_modal_data(project, ProjectMember, 'true')).to include(attributes)
+ end
+ end
+
describe '#common_invite_modal_dataset' do
it 'has expected common attributes' do
attributes = {
@@ -155,4 +171,28 @@ RSpec.describe InviteMembersHelper do
end
end
end
+
+ describe '#group_select_data' do
+ let_it_be(:group) { create(:group) }
+
+ context 'when sharing with groups outside the hierarchy is disabled' do
+ before do
+ group.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: true)
+ end
+
+ it 'provides the correct attributes' do
+ expect(helper.group_select_data(group)).to eq({ groups_filter: 'descendant_groups', parent_id: group.id })
+ end
+ end
+
+ context 'when sharing with groups outside the hierarchy is enabled' do
+ before do
+ group.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: false)
+ end
+
+ it 'returns an empty hash' do
+ expect(helper.group_select_data(project.group)).to eq({})
+ end
+ end
+ end
end
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index 6b05bab7432..768ce5975c1 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -72,6 +72,37 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
].to_json
expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
+
+ context 'when no issuable_template parameter or default template is present' do
+ it 'does not select a template' do
+ expect(helper.selected_template(project)).to be(nil)
+ end
+ end
+
+ context 'when an issuable_template parameter has been provided' do
+ before do
+ allow(helper).to receive(:params).and_return({ issuable_template: 'another_issue_template' })
+ end
+
+ it 'selects the issuable template' do
+ expect(helper.selected_template(project)).to eq('another_issue_template')
+ end
+ end
+
+ context 'when there is a default template' do
+ let(:templates) do
+ {
+ "" => [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "default", id: "default", project_id: project.id }
+ ]
+ }
+ end
+
+ it 'selects the default template' do
+ expect(helper.selected_template(project)).to eq('default')
+ end
+ end
end
context 'when there are not templates in the project' do
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index fa19395ebc7..ed50a4daae8 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -133,13 +133,13 @@ RSpec.describe IssuablesHelper do
it 'returns navigation with badges' do
expect(helper.issuables_state_counter_text(:issues, :opened, true))
- .to eq('<span>Open</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">42</span>')
+ .to eq('<span>Open</span> <span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex">42</span>')
expect(helper.issuables_state_counter_text(:issues, :closed, true))
- .to eq('<span>Closed</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">42</span>')
+ .to eq('<span>Closed</span> <span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex">42</span>')
expect(helper.issuables_state_counter_text(:merge_requests, :merged, true))
- .to eq('<span>Merged</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">42</span>')
+ .to eq('<span>Merged</span> <span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex">42</span>')
expect(helper.issuables_state_counter_text(:merge_requests, :all, true))
- .to eq('<span>All</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">42</span>')
+ .to eq('<span>All</span> <span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex">42</span>')
end
end
@@ -171,7 +171,7 @@ RSpec.describe IssuablesHelper do
it 'returns truncated count' do
expect(helper.issuables_state_counter_text(:issues, :opened, true))
- .to eq('<span>Open</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">1.1k</span>')
+ .to eq('<span>Open</span> <span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge gl-display-none gl-sm-display-inline-flex">1.1k</span>')
end
end
end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 065ac526ae4..2f57657736d 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -300,6 +300,7 @@ RSpec.describe IssuesHelper do
has_any_issues: project_issues(project).exists?.to_s,
import_csv_issues_path: '#',
initial_email: project.new_issuable_address(current_user, 'issue'),
+ initial_sort: current_user&.user_preference&.issues_sort,
is_anonymous_search_disabled: 'true',
is_issue_repositioning_disabled: 'true',
is_project: 'true',
@@ -342,8 +343,6 @@ RSpec.describe IssuesHelper do
describe '#group_issues_list_data' do
let(:group) { create(:group) }
let(:current_user) { double.as_null_object }
- let(:issues) { [] }
- let(:projects) { [] }
it 'returns expected result' do
allow(helper).to receive(:current_user).and_return(current_user)
@@ -351,20 +350,23 @@ RSpec.describe IssuesHelper do
allow(helper).to receive(:image_path).and_return('#')
allow(helper).to receive(:url_for).and_return('#')
+ assign(:has_issues, false)
+ assign(:has_projects, true)
+
expected = {
autocomplete_award_emojis_path: autocomplete_award_emojis_path,
calendar_path: '#',
empty_state_svg_path: '#',
full_path: group.full_path,
- has_any_issues: issues.to_a.any?.to_s,
- has_any_projects: any_projects?(projects).to_s,
+ has_any_issues: false.to_s,
+ has_any_projects: true.to_s,
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
rss_path: '#',
sign_in_path: new_user_session_path
}
- expect(helper.group_issues_list_data(group, current_user, issues, projects)).to include(expected)
+ expect(helper.group_issues_list_data(group, current_user)).to include(expected)
end
end
diff --git a/spec/helpers/listbox_helper_spec.rb b/spec/helpers/listbox_helper_spec.rb
new file mode 100644
index 00000000000..8935d69d4f7
--- /dev/null
+++ b/spec/helpers/listbox_helper_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ListboxHelper do
+ subject do
+ tag = helper.gl_redirect_listbox_tag(items, selected, html_options)
+ Nokogiri::HTML.fragment(tag).children.first
+ end
+
+ before do
+ allow(helper).to receive(:sprite_icon).with(
+ 'chevron-down',
+ css_class: 'gl-button-icon dropdown-chevron gl-icon'
+ ).and_return('<span class="icon"></span>'.html_safe)
+ end
+
+ let(:selected) { 'bar' }
+ let(:html_options) { {} }
+ let(:items) do
+ [
+ { value: 'foo', text: 'Foo' },
+ { value: 'bar', text: 'Bar' }
+ ]
+ end
+
+ describe '#gl_redirect_listbox_tag' do
+ it 'creates root element with expected classes' do
+ expect(subject.classes).to include(*%w[
+ dropdown
+ b-dropdown
+ gl-new-dropdown
+ btn-group
+ js-redirect-listbox
+ ])
+ end
+
+ it 'sets data attributes for items and selected' do
+ expect(subject.attributes['data-items'].value).to eq(items.to_json)
+ expect(subject.attributes['data-selected'].value).to eq(selected)
+ end
+
+ it 'adds styled button' do
+ expect(subject.at_css('button').classes).to include(*%w[
+ btn
+ dropdown-toggle
+ btn-default
+ btn-md
+ gl-button
+ gl-dropdown-toggle
+ ])
+ end
+
+ it 'sets button text to selected item' do
+ expect(subject.at_css('button').content).to eq('Bar')
+ end
+
+ context 'given html_options' do
+ let(:html_options) { { class: 'test-class', data: { qux: 'qux' } } }
+
+ it 'applies them to the root element' do
+ expect(subject.attributes['data-qux'].value).to eq('qux')
+ expect(subject.classes).to include('test-class')
+ end
+ end
+
+ context 'when selected does not match any item' do
+ let(:selected) { 'qux' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError, /cannot find qux/)
+ end
+ end
+ end
+end
diff --git a/spec/helpers/projects/cluster_agents_helper_spec.rb b/spec/helpers/projects/cluster_agents_helper_spec.rb
index 632544797ee..d94a5fa9f8a 100644
--- a/spec/helpers/projects/cluster_agents_helper_spec.rb
+++ b/spec/helpers/projects/cluster_agents_helper_spec.rb
@@ -5,22 +5,29 @@ require 'spec_helper'
RSpec.describe Projects::ClusterAgentsHelper do
describe '#js_cluster_agent_details_data' do
let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+ let(:user_can_admin_vulerability) { true }
let(:agent_name) { 'agent-name' }
- subject { helper.js_cluster_agent_details_data(agent_name, project) }
-
- it 'returns name' do
- expect(subject[:agent_name]).to eq(agent_name)
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper)
+ .to receive(:can?)
+ .with(current_user, :admin_vulnerability, project)
+ .and_return(user_can_admin_vulerability)
end
- it 'returns project path' do
- expect(subject[:project_path]).to eq(project.full_path)
- end
+ subject { helper.js_cluster_agent_details_data(agent_name, project) }
- it 'returns string contants' do
- expect(subject[:activity_empty_state_image]).to be_kind_of(String)
- expect(subject[:empty_state_svg_path]).to be_kind_of(String)
- end
+ it {
+ is_expected.to match({
+ agent_name: agent_name,
+ project_path: project.full_path,
+ activity_empty_state_image: kind_of(String),
+ empty_state_svg_path: kind_of(String),
+ can_admin_vulnerability: "true"
+ })
+ }
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index cc443afee6e..604ce0fe0c1 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -345,6 +345,14 @@ RSpec.describe ProjectsHelper do
expect(link).not_to include(user.name)
end
end
+
+ context 'when user is nil' do
+ it 'returns "(deleted)"' do
+ link = helper.link_to_member(project, nil)
+
+ expect(link).to eq("(deleted)")
+ end
+ end
end
describe 'default_clone_protocol' do
@@ -1018,4 +1026,26 @@ RSpec.describe ProjectsHelper do
end
end
end
+
+ describe '#import_from_bitbucket_message' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'as a user' do
+ it 'returns a link to contact an administrator' do
+ allow(user).to receive(:admin?).and_return(false)
+
+ expect(helper.import_from_bitbucket_message).to have_text('To enable importing projects from Bitbucket, ask your GitLab administrator to configure OAuth integration')
+ end
+ end
+
+ context 'as an administrator' do
+ it 'returns a link to configure bitbucket' do
+ allow(user).to receive(:admin?).and_return(true)
+
+ expect(helper.import_from_bitbucket_message).to have_text('To enable importing projects from Bitbucket, as administrator you need to configure OAuth integration')
+ end
+ end
+ end
end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 40cfdafc9ac..78cc1dcee01 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -658,4 +658,152 @@ RSpec.describe SearchHelper do
expect(search_sort_options).to eq(mock_created_sort)
end
end
+
+ describe '#header_search_context' do
+ let(:user) { create(:user) }
+ let(:can_download) { false }
+
+ let(:for_group) { false }
+ let(:group) { nil }
+ let(:group_metadata) { nil }
+
+ let(:for_project) { false }
+ let(:project) { nil }
+ let(:project_metadata) { nil }
+
+ let(:scope) { nil }
+ let(:code_search) { false }
+ let(:ref) { nil }
+ let(:for_snippets) { false }
+
+ let(:search_context) do
+ instance_double(Gitlab::SearchContext,
+ group: group,
+ group_metadata: group_metadata,
+ project: project,
+ project_metadata: project_metadata,
+ scope: scope,
+ ref: ref)
+ end
+
+ before do
+ allow(self).to receive(:search_context).and_return(search_context)
+ allow(self).to receive(:current_user).and_return(user)
+ allow(self).to receive(:can?).and_return(can_download)
+
+ allow(search_context).to receive(:for_group?).and_return(for_group)
+ allow(search_context).to receive(:for_project?).and_return(for_project)
+
+ allow(search_context).to receive(:code_search?).and_return(code_search)
+ allow(search_context).to receive(:for_snippets?).and_return(for_snippets)
+ end
+
+ context 'group data' do
+ let(:group) { create(:group) }
+ let(:group_metadata) { { group_path: group.path, issues_path: "/issues" } }
+ let(:scope) { 'issues' }
+ let(:code_search) { true }
+
+ context 'when for_group? is true' do
+ let(:for_group) { true }
+
+ it 'adds the :group and :group_metadata correctly to hash' do
+ expect(header_search_context[:group]).to eq({ id: group.id, name: group.name })
+ expect(header_search_context[:group_metadata]).to eq(group_metadata)
+ end
+
+ it 'adds scope and code_search? correctly to hash' do
+ expect(header_search_context[:scope]).to eq(scope)
+ expect(header_search_context[:code_search]).to eq(code_search)
+ end
+ end
+
+ context 'when for_group? is false' do
+ let(:for_group) { false }
+
+ it 'does not add the :group and :group_metadata to hash' do
+ expect(header_search_context[:group]).to eq(nil)
+ expect(header_search_context[:group_metadata]).to eq(nil)
+ end
+
+ it 'does not add scope and code_search? to hash' do
+ expect(header_search_context[:scope]).to eq(nil)
+ expect(header_search_context[:code_search]).to eq(nil)
+ end
+ end
+ end
+
+ context 'project data' do
+ let(:project) { create(:project) }
+ let(:project_metadata) { { project_path: project.path, issues_path: "/issues" } }
+ let(:scope) { 'issues' }
+ let(:code_search) { true }
+
+ context 'when for_project? is true' do
+ let(:for_project) { true }
+
+ it 'adds the :project and :project_metadata correctly to hash' do
+ expect(header_search_context[:project]).to eq({ id: project.id, name: project.name })
+ expect(header_search_context[:project_metadata]).to eq(project_metadata)
+ end
+
+ it 'adds scope and code_search? correctly to hash' do
+ expect(header_search_context[:scope]).to eq(scope)
+ expect(header_search_context[:code_search]).to eq(code_search)
+ end
+ end
+
+ context 'when for_project? is false' do
+ let(:for_project) { false }
+
+ it 'does not add the :project and :project_metadata to hash' do
+ expect(header_search_context[:project]).to eq(nil)
+ expect(header_search_context[:project_metadata]).to eq(nil)
+ end
+
+ it 'does not add scope and code_search? to hash' do
+ expect(header_search_context[:scope]).to eq(nil)
+ expect(header_search_context[:code_search]).to eq(nil)
+ end
+ end
+ end
+
+ context 'ref data' do
+ let(:ref) { 'test-branch' }
+
+ context 'when user can? download project data' do
+ let(:can_download) { true }
+
+ it 'adds the :ref correctly to hash' do
+ expect(header_search_context[:ref]).to eq(ref)
+ end
+ end
+
+ context 'when user cannot download project data' do
+ let(:can_download) { false }
+
+ it 'does not add the :ref to hash' do
+ expect(header_search_context[:ref]).to eq(nil)
+ end
+ end
+ end
+
+ context 'snippets' do
+ context 'when for_snippets? is true' do
+ let(:for_snippets) { true }
+
+ it 'adds :for_snippets correctly to hash' do
+ expect(header_search_context[:for_snippets]).to eq(for_snippets)
+ end
+ end
+
+ context 'when for_snippets? is false' do
+ let(:for_snippets) { false }
+
+ it 'adds :for_snippets correctly to hash' do
+ expect(header_search_context[:for_snippets]).to eq(for_snippets)
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/ssh_keys_helper_spec.rb b/spec/helpers/ssh_keys_helper_spec.rb
index 1aa604f19be..522331090e4 100644
--- a/spec/helpers/ssh_keys_helper_spec.rb
+++ b/spec/helpers/ssh_keys_helper_spec.rb
@@ -17,9 +17,9 @@ RSpec.describe SshKeysHelper do
end
it 'returns only allowed algorithms' do
- expect(ssh_key_allowed_algorithms).to match('ed25519')
- stub_application_setting(ed25519_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
- expect(ssh_key_allowed_algorithms).not_to match('ed25519')
+ expect(ssh_key_allowed_algorithms).to match('rsa')
+ stub_application_setting(rsa_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
+ expect(ssh_key_allowed_algorithms).not_to match('rsa')
end
end
end
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index d0646b30161..82b78ed831c 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -50,4 +50,87 @@ RSpec.describe StorageHelper do
expect(helper.storage_counters_details(namespace_stats)).to eq(message)
end
end
+
+ describe "storage_enforcement_banner" do
+ let_it_be_with_refind(:current_user) { create(:user) }
+ let_it_be(:free_group) { create(:group) }
+ let_it_be(:paid_group) { create(:group) }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ allow(Gitlab).to receive(:com?).and_return(true)
+ allow(paid_group).to receive(:paid?).and_return(true)
+ end
+
+ describe "#storage_enforcement_banner_info" do
+ it 'returns nil when namespace is not free' do
+ expect(storage_enforcement_banner_info(paid_group)).to be(nil)
+ end
+
+ it 'returns nil when storage_enforcement_date is not set' do
+ allow(free_group).to receive(:storage_enforcement_date).and_return(nil)
+
+ expect(storage_enforcement_banner_info(free_group)).to be(nil)
+ end
+
+ it 'returns a hash when storage_enforcement_date is set' do
+ storage_enforcement_date = Date.today + 30
+ allow(free_group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+
+ expect(storage_enforcement_banner_info(free_group)).to eql({
+ text: "From #{storage_enforcement_date} storage limits will apply to this namespace. View and manage your usage in <strong>Group Settings &gt; Usage quotas</strong>.",
+ variant: 'warning',
+ callouts_feature_name: 'storage_enforcement_banner_second_enforcement_threshold',
+ callouts_path: '/-/users/group_callouts',
+ learn_more_link: '<a rel="noopener noreferrer" target="_blank" href="/help//">Learn more.</a>'
+ })
+ end
+
+ context 'when storage_enforcement_date is set and dismissed callout exists' do
+ before do
+ create(:group_callout,
+ user: current_user,
+ group_id: free_group.id,
+ feature_name: 'storage_enforcement_banner_second_enforcement_threshold')
+ storage_enforcement_date = Date.today + 30
+ allow(free_group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ end
+
+ it { expect(storage_enforcement_banner_info(free_group)).to be(nil) }
+ end
+
+ context 'callouts_feature_name' do
+ let(:days_from_now) { 45 }
+
+ subject do
+ storage_enforcement_date = Date.today + days_from_now
+ allow(free_group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+
+ storage_enforcement_banner_info(free_group)[:callouts_feature_name]
+ end
+
+ it 'returns first callouts_feature_name' do
+ is_expected.to eq('storage_enforcement_banner_first_enforcement_threshold')
+ end
+
+ context 'returns second callouts_feature_name' do
+ let(:days_from_now) { 20 }
+
+ it { is_expected.to eq('storage_enforcement_banner_second_enforcement_threshold') }
+ end
+
+ context 'returns third callouts_feature_name' do
+ let(:days_from_now) { 13 }
+
+ it { is_expected.to eq('storage_enforcement_banner_third_enforcement_threshold') }
+ end
+
+ context 'returns fourth callouts_feature_name' do
+ let(:days_from_now) { 3 }
+
+ it { is_expected.to eq('storage_enforcement_banner_fourth_enforcement_threshold') }
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index f338eddedfd..dd5707e2aff 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe TabHelper do
end
it 'creates an active tab with item_active = true' do
- expect(helper.gl_tab_link_to('Link', '/url', { item_active: true })).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url', { item_active: true })).to match(/<a class=".*active gl-tab-nav-item-active.*"/)
end
context 'when on the active page' do
@@ -54,7 +54,7 @@ RSpec.describe TabHelper do
end
it 'creates an active tab' do
- expect(helper.gl_tab_link_to('Link', '/url')).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url')).to match(/<a class=".*active gl-tab-nav-item-active.*"/)
end
it 'creates an inactive tab with item_active = false' do
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 2b55319c70c..82f4ae596e1 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -11,6 +11,20 @@ RSpec.describe UsersHelper do
badges.reject { |badge| badge[:text] == 'Is using seat' }
end
+ describe 'display_public_email?' do
+ let_it_be(:user) { create(:user, :public_email) }
+
+ subject { helper.display_public_email?(user) }
+
+ it { is_expected.to be true }
+
+ context 'when user public email is blank' do
+ let_it_be(:user) { create(:user, public_email: '') }
+
+ it { is_expected.to be false }
+ end
+ end
+
describe '#user_link' do
subject { helper.user_link(user) }
@@ -122,7 +136,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(blocked_user)
- expect(filter_ee_badges(badges)).to eq([text: "Blocked", variant: "danger"])
+ expect(filter_ee_badges(badges)).to match_array([text: "Blocked", variant: "danger"])
end
end
@@ -132,7 +146,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(blocked_pending_approval_user)
- expect(filter_ee_badges(badges)).to eq([text: 'Pending approval', variant: 'info'])
+ expect(filter_ee_badges(badges)).to match_array([text: 'Pending approval', variant: 'info'])
end
end
@@ -142,7 +156,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(banned_user)
- expect(filter_ee_badges(badges)).to eq([text: 'Banned', variant: 'danger'])
+ expect(filter_ee_badges(badges)).to match_array([text: 'Banned', variant: 'danger'])
end
end
@@ -152,7 +166,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(admin_user)
- expect(filter_ee_badges(badges)).to eq([text: "Admin", variant: "success"])
+ expect(filter_ee_badges(badges)).to match_array([text: "Admin", variant: "success"])
end
end
@@ -162,7 +176,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(external_user)
- expect(filter_ee_badges(badges)).to eq([text: "External", variant: "secondary"])
+ expect(filter_ee_badges(badges)).to match_array([text: "External", variant: "secondary"])
end
end
@@ -170,7 +184,7 @@ RSpec.describe UsersHelper do
it 'returns the "It\'s You" badge' do
badges = helper.user_badges_in_admin_section(user)
- expect(filter_ee_badges(badges)).to eq([text: "It's you!", variant: "muted"])
+ expect(filter_ee_badges(badges)).to match_array([text: "It's you!", variant: "muted"])
end
end
@@ -180,7 +194,7 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(user)
- expect(badges).to eq([
+ expect(badges).to match_array([
{ text: "Blocked", variant: "danger" },
{ text: "Admin", variant: "success" },
{ text: "External", variant: "secondary" }
@@ -188,6 +202,16 @@ RSpec.describe UsersHelper do
end
end
+ context 'with a locked user', time_travel_to: '2020-02-25 10:30:45 -0700' do
+ it 'returns the "Locked" badge' do
+ locked_user = create(:user, locked_at: DateTime.parse('2020-02-25 10:30:00 -0700'))
+
+ badges = helper.user_badges_in_admin_section(locked_user)
+
+ expect(filter_ee_badges(badges)).to match_array([text: "Locked", variant: "warning"])
+ end
+ end
+
context 'get badges for normal user' do
it 'returns no badges' do
user = create(:user)
diff --git a/spec/initializers/google_api_client_spec.rb b/spec/initializers/google_api_client_spec.rb
new file mode 100644
index 00000000000..0ed82d7debe
--- /dev/null
+++ b/spec/initializers/google_api_client_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# Extracted from https://github.com/googleapis/google-api-ruby-client/blob/main/google-apis-core/spec/google/apis/core/http_command_spec.rb
+
+require 'spec_helper'
+require 'google/apis/core/base_service'
+
+RSpec.describe Google::Apis::Core::HttpCommand do # rubocop:disable RSpec/FilePath
+ context('with a successful response') do
+ let(:client) { Google::Apis::Core::BaseService.new('', '').client }
+ let(:command) { Google::Apis::Core::HttpCommand.new(:get, 'https://www.googleapis.com/zoo/animals') }
+
+ before do
+ stub_request(:get, 'https://www.googleapis.com/zoo/animals').to_return(body: %(Hello world))
+ end
+
+ it 'returns the response body if block not present' do
+ result = command.execute(client)
+ expect(result).to eql 'Hello world'
+ end
+
+ it 'calls block if present' do
+ expect { |b| command.execute(client, &b) }.to yield_with_args('Hello world', nil)
+ end
+
+ it 'retries with max elapsed_time and retries' do
+ expect(Retriable).to receive(:retriable).with(
+ tries: Google::Apis::RequestOptions.default.retries + 1,
+ max_elapsed_time: 3600,
+ base_interval: 1,
+ multiplier: 2,
+ on: described_class::RETRIABLE_ERRORS).and_call_original
+ allow(Retriable).to receive(:retriable).and_call_original
+
+ command.execute(client)
+ end
+ end
+end
diff --git a/spec/initializers/net_http_patch_spec.rb b/spec/initializers/net_http_patch_spec.rb
index e5205abbed2..d6b003d84fa 100644
--- a/spec/initializers/net_http_patch_spec.rb
+++ b/spec/initializers/net_http_patch_spec.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
+
require 'fast_spec_helper'
+require_relative '../../config/initializers/net_http_patch'
+
RSpec.describe 'Net::HTTP patch proxy user and password encoding' do
let(:net_http) { Net::HTTP.new('hostname.example') }
diff --git a/spec/lib/api/entities/basic_project_details_spec.rb b/spec/lib/api/entities/basic_project_details_spec.rb
index dc7c4fdce4e..8419eb0a932 100644
--- a/spec/lib/api/entities/basic_project_details_spec.rb
+++ b/spec/lib/api/entities/basic_project_details_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe API::Entities::BasicProjectDetails do
let_it_be(:project) { create(:project) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
subject(:output) { described_class.new(project, current_user: current_user).as_json }
diff --git a/spec/lib/api/entities/deployment_extended_spec.rb b/spec/lib/api/entities/deployment_extended_spec.rb
new file mode 100644
index 00000000000..733c47362be
--- /dev/null
+++ b/spec/lib/api/entities/deployment_extended_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::DeploymentExtended do
+ describe '#as_json' do
+ subject { described_class.new(deployment).as_json }
+
+ let(:deployment) { create(:deployment) }
+
+ it 'includes fields from deployment entity' do
+ is_expected.to include(:id, :iid, :ref, :sha, :created_at, :updated_at, :user, :environment, :deployable, :status)
+ end
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 2277bd78e86..b2d4a3094af 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -76,6 +76,12 @@ RSpec.describe API::Helpers do
expect(subject.find_project(non_existing_id)).to be_nil
end
end
+
+ context 'when project id is not provided' do
+ it 'returns nil' do
+ expect(subject.find_project(nil)).to be_nil
+ end
+ end
end
context 'when ID is used as an argument' do
@@ -160,7 +166,7 @@ RSpec.describe API::Helpers do
describe '#find_project!' do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner}
+ let(:user) { project.first_owner}
before do
allow(subject).to receive(:current_user).and_return(user)
diff --git a/spec/lib/backup/database_spec.rb b/spec/lib/backup/database_spec.rb
index f57037d5652..4345778ba92 100644
--- a/spec/lib/backup/database_spec.rb
+++ b/spec/lib/backup/database_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe Backup::Database do
let(:progress) { StringIO.new }
let(:output) { progress.string }
+ before do
+ allow(Gitlab::TaskHelpers).to receive(:ask_to_continue)
+ end
+
describe '#restore' do
let(:cmd) { %W[#{Gem.ruby} -e $stdout.puts(1)] }
let(:data) { Rails.root.join("spec/fixtures/pages_empty.tar.gz").to_s }
@@ -20,7 +24,7 @@ RSpec.describe Backup::Database do
let(:data) { Rails.root.join("spec/fixtures/pages_empty.tar.gz").to_s }
it 'returns successfully' do
- expect(subject.restore).to eq([])
+ subject.restore
expect(output).to include("Restoring PostgreSQL database")
expect(output).to include("[DONE]")
@@ -42,7 +46,8 @@ RSpec.describe Backup::Database do
let(:cmd) { %W[#{Gem.ruby} -e $stderr.write("#{noise}#{visible_error}")] }
it 'filters out noise from errors' do
- expect(subject.restore).to eq([visible_error])
+ subject.restore
+
expect(output).to include("ERRORS")
expect(output).not_to include(noise)
expect(output).to include(visible_error)
diff --git a/spec/lib/backup/gitaly_backup_spec.rb b/spec/lib/backup/gitaly_backup_spec.rb
index cd0d984fbdb..6bf4f833c1f 100644
--- a/spec/lib/backup/gitaly_backup_spec.rb
+++ b/spec/lib/backup/gitaly_backup_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Backup::GitalyBackup do
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)
+ personal_snippet = create(:personal_snippet, :repository, author: project.first_owner)
expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything).and_call_original
@@ -122,8 +122,8 @@ RSpec.describe Backup::GitalyBackup do
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) }
+ let_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
def copy_bundle_to_backup_path(bundle_name, destination)
FileUtils.mkdir_p(File.join(Gitlab.config.backup.path, 'repositories', File.dirname(destination)))
diff --git a/spec/lib/backup/gitaly_rpc_backup_spec.rb b/spec/lib/backup/gitaly_rpc_backup_spec.rb
index 14f9d27ca6e..4829d51ac9d 100644
--- a/spec/lib/backup/gitaly_rpc_backup_spec.rb
+++ b/spec/lib/backup/gitaly_rpc_backup_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Backup::GitalyRpcBackup do
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)
+ personal_snippet = create(:personal_snippet, :repository, author: project.first_owner)
subject.start(:create)
subject.enqueue(project, Gitlab::GlRepository::PROJECT)
@@ -75,8 +75,8 @@ RSpec.describe Backup::GitalyRpcBackup do
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) }
+ let_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
def copy_bundle_to_backup_path(bundle_name, destination)
FileUtils.mkdir_p(File.join(Gitlab.config.backup.path, 'repositories', File.dirname(destination)))
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index 31cc3012eb1..ac693ad8b98 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -12,6 +12,11 @@ RSpec.describe Backup::Manager do
before do
allow(progress).to receive(:puts)
allow(progress).to receive(:print)
+ FileUtils.mkdir_p('tmp/tests/public/uploads')
+ end
+
+ after do
+ FileUtils.rm_rf('tmp/tests/public/uploads', secure: true)
end
describe '#pack' do
@@ -409,7 +414,7 @@ RSpec.describe Backup::Manager do
# the Fog mock only knows about directories we create explicitly
connection = ::Fog::Storage.new(Gitlab.config.backup.upload.connection.symbolize_keys)
- connection.directories.create(key: Gitlab.config.backup.upload.remote_directory)
+ connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) # rubocop:disable Rails/SaveBang
end
context 'target path' do
@@ -455,7 +460,7 @@ RSpec.describe Backup::Manager do
}
)
- connection.directories.create(key: Gitlab.config.backup.upload.remote_directory)
+ connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) # rubocop:disable Rails/SaveBang
end
context 'with SSE-S3 without using storage_options' do
@@ -521,7 +526,7 @@ RSpec.describe Backup::Manager do
)
connection = ::Fog::Storage.new(Gitlab.config.backup.upload.connection.symbolize_keys)
- connection.directories.create(key: Gitlab.config.backup.upload.remote_directory)
+ connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) # rubocop:disable Rails/SaveBang
end
it 'does not attempt to set ACL' do
diff --git a/spec/lib/backup/repositories_spec.rb b/spec/lib/backup/repositories_spec.rb
index f3830da344b..0b29a25360d 100644
--- a/spec/lib/backup/repositories_spec.rb
+++ b/spec/lib/backup/repositories_spec.rb
@@ -6,8 +6,17 @@ RSpec.describe Backup::Repositories do
let(:progress) { spy(:stdout) }
let(:parallel_enqueue) { true }
let(:strategy) { spy(:strategy, parallel_enqueue?: parallel_enqueue) }
-
- subject { described_class.new(progress, strategy: strategy) }
+ let(:max_concurrency) { 1 }
+ let(:max_storage_concurrency) { 1 }
+
+ subject do
+ described_class.new(
+ progress,
+ strategy: strategy,
+ max_concurrency: max_concurrency,
+ max_storage_concurrency: max_storage_concurrency
+ )
+ end
describe '#dump' do
let_it_be(:projects) { create_list(:project, 5, :repository) }
@@ -15,9 +24,9 @@ RSpec.describe Backup::Repositories do
RSpec.shared_examples 'creates repository bundles' do
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)
+ personal_snippet = create(:personal_snippet, :repository, author: project.first_owner)
- subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ subject.dump
expect(strategy).to have_received(:start).with(:create)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
@@ -51,38 +60,40 @@ RSpec.describe Backup::Repositories do
end
expect(strategy).to receive(:finish!)
- subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ subject.dump
end
describe 'command failure' do
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)
+ expect { subject.dump }.to raise_error(IOError)
end
it 'project query raises an error' do
allow(Project).to receive_message_chain(:includes, :find_each).and_raise(ActiveRecord::StatementTimeout)
- expect { subject.dump(max_concurrency: 1, max_storage_concurrency: 1) }.to raise_error(ActiveRecord::StatementTimeout)
+ expect { subject.dump }.to raise_error(ActiveRecord::StatementTimeout)
end
end
it 'avoids N+1 database queries' do
control_count = ActiveRecord::QueryRecorder.new do
- subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ subject.dump
end.count
create_list(:project, 2, :repository)
expect do
- subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ subject.dump
end.not_to exceed_query_limit(control_count)
end
end
context 'concurrency with a strategy without parallel enqueueing support' do
let(:parallel_enqueue) { false }
+ let(:max_concurrency) { 2 }
+ let(:max_storage_concurrency) { 2 }
it 'enqueues all projects sequentially' do
expect(Thread).not_to receive(:new)
@@ -93,13 +104,14 @@ RSpec.describe Backup::Repositories do
end
expect(strategy).to receive(:finish!)
- subject.dump(max_concurrency: 2, max_storage_concurrency: 2)
+ subject.dump
end
end
[4, 10].each do |max_storage_concurrency|
context "max_storage_concurrency #{max_storage_concurrency}", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/241701' do
let(:storage_keys) { %w[default test_second_storage] }
+ let(:max_storage_concurrency) { max_storage_concurrency }
before do
allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(storage_keys)
@@ -116,54 +128,58 @@ RSpec.describe Backup::Repositories do
end
expect(strategy).to receive(:finish!)
- subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
+ subject.dump
end
- it 'creates the expected number of threads with extra max concurrency' do
- expect(Thread).to receive(:new)
- .exactly(storage_keys.length * (max_storage_concurrency + 1)).times
- .and_call_original
+ context 'with extra max concurrency' do
+ let(:max_concurrency) { 3 }
- expect(strategy).to receive(:start).with(:create)
- projects.each do |project|
- expect(strategy).to receive(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
- end
- expect(strategy).to receive(:finish!)
+ it 'creates the expected number of threads' do
+ expect(Thread).to receive(:new)
+ .exactly(storage_keys.length * (max_storage_concurrency + 1)).times
+ .and_call_original
- subject.dump(max_concurrency: 3, max_storage_concurrency: max_storage_concurrency)
+ expect(strategy).to receive(:start).with(:create)
+ projects.each do |project|
+ expect(strategy).to receive(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
+ end
+ expect(strategy).to receive(:finish!)
+
+ subject.dump
+ end
end
describe 'command failure' do
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)
+ expect { subject.dump }.to raise_error(IOError)
end
it 'project query raises an error' do
allow(Project).to receive_message_chain(:for_repository_storage, :includes, :find_each).and_raise(ActiveRecord::StatementTimeout)
- expect { subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency) }.to raise_error(ActiveRecord::StatementTimeout)
+ expect { subject.dump }.to raise_error(ActiveRecord::StatementTimeout)
end
context 'misconfigured storages' do
let(:storage_keys) { %w[test_second_storage] }
it 'raises an error' do
- expect { subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency) }.to raise_error(Backup::Error, 'repositories.storages in gitlab.yml is misconfigured')
+ expect { subject.dump }.to raise_error(Backup::Error, 'repositories.storages in gitlab.yml is misconfigured')
end
end
end
it 'avoids N+1 database queries' do
control_count = ActiveRecord::QueryRecorder.new do
- subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
+ subject.dump
end.count
create_list(:project, 2, :repository)
expect do
- subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
+ subject.dump
end.not_to exceed_query_limit(control_count)
end
end
@@ -172,8 +188,8 @@ RSpec.describe Backup::Repositories do
describe '#restore' do
let_it_be(:project) { create(:project) }
- 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_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
it 'calls enqueue for each repository type', :aggregate_failures do
subject.restore
diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb
index 24d13bdb42c..036817834d5 100644
--- a/spec/lib/banzai/filter/external_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_link_filter_spec.rb
@@ -71,6 +71,13 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter do
expect(doc.to_html).to eq(expected)
end
+
+ it 'adds rel and target attributes to improperly formatted protocols' do
+ doc = filter %q(<p><a target="_blank" href="http:evil.com">Reverse Tabnabbing</a></p>)
+ expected = %q(<p><a target="_blank" href="http:evil.com" rel="nofollow noreferrer noopener">Reverse Tabnabbing</a></p>)
+
+ expect(doc.to_html).to eq(expected)
+ end
end
context 'for links with a username' do
diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
index b3523a25116..c493cb77c98 100644
--- a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
@@ -515,7 +515,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter do
enable_design_management(enabled)
end
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:enabled) { true }
let(:matches) { Issue.link_reference_pattern.match(input_text) }
let(:extras) { subject.object_link_text_extras(issue, matches) }
diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
index 6e90f4457fa..91c644cb16a 100644
--- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
+++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
@@ -91,6 +91,12 @@ RSpec.describe Banzai::Filter::TableOfContentsFilter do
# ExternalLinkFilter (see https://gitlab.com/gitlab-org/gitlab/issues/26210)
expect(doc.css('h1 a').first.attr('href')).to eq "##{CGI.escape('한글')}"
end
+
+ it 'limits header href length with 255 characters' do
+ doc = filter(header(1, 'a' * 500))
+
+ expect(doc.css('h1 a').first.attr('href')).to eq "##{'a' * 255}"
+ end
end
end
diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb
index e64ab5dfce3..8f69480c65f 100644
--- a/spec/lib/banzai/object_renderer_spec.rb
+++ b/spec/lib/banzai/object_renderer_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Banzai::ObjectRenderer do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:renderer) do
described_class.new(
default_project: project,
diff --git a/spec/lib/bitbucket_server/representation/repo_spec.rb b/spec/lib/bitbucket_server/representation/repo_spec.rb
index 7a773f47ca5..5de4360bbd0 100644
--- a/spec/lib/bitbucket_server/representation/repo_spec.rb
+++ b/spec/lib/bitbucket_server/representation/repo_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
"slug": "rouge",
"id": 1,
"name": "rouge",
+ "description": "Rogue Repo",
"scmId": "git",
"state": "AVAILABLE",
"statusMessage": "Available",
@@ -17,7 +18,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
"key": "TEST",
"id": 1,
"name": "test",
- "description": "Test",
+ "description": "Test Project",
"public": false,
"type": "NORMAL",
"links": {
@@ -73,7 +74,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
end
describe '#description' do
- it { expect(subject.description).to eq('Test') }
+ it { expect(subject.description).to eq('Rogue Repo') }
end
describe '#full_name' do
diff --git a/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
index 80607485b6e..50c54a7b47f 100644
--- a/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
+++ b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
@@ -8,12 +8,15 @@ RSpec.describe BulkImports::Common::Extractors::GraphqlExtractor do
let(:response) { double(original_hash: { 'data' => { 'foo' => 'bar' }, 'page_info' => {} }) }
let(:options) do
{
- query: double(
- to_s: 'test',
- variables: {},
- data_path: %w[data foo],
- page_info_path: %w[data page_info]
- )
+ query:
+ double(
+ new: double(
+ to_s: 'test',
+ variables: {},
+ data_path: %w[data foo],
+ page_info_path: %w[data page_info]
+ )
+ )
}
end
diff --git a/spec/lib/bulk_imports/common/graphql/get_members_query_spec.rb b/spec/lib/bulk_imports/common/graphql/get_members_query_spec.rb
new file mode 100644
index 00000000000..e3a7335a238
--- /dev/null
+++ b/spec/lib/bulk_imports/common/graphql/get_members_query_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Graphql::GetMembersQuery do
+ let(:entity) { create(:bulk_import_entity, :group_entity) }
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:query) { described_class.new(context: context) }
+
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
+
+ expect(result[:errors]).to be_empty
+ end
+
+ describe '#data_path' do
+ it 'returns data path' do
+ expected = %w[data portable members nodes]
+
+ expect(query.data_path).to eq(expected)
+ end
+ end
+
+ describe '#page_info_path' do
+ it 'returns pagination information path' do
+ expected = %w[data portable members page_info]
+
+ expect(query.page_info_path).to eq(expected)
+ end
+ end
+
+ describe '#to_s' do
+ context 'when entity is group' do
+ it 'queries group & group members' do
+ expect(query.to_s).to include('group')
+ expect(query.to_s).to include('groupMembers')
+ end
+ end
+
+ context 'when entity is project' do
+ let(:entity) { create(:bulk_import_entity, :project_entity) }
+
+ it 'queries project & project members' do
+ expect(query.to_s).to include('project')
+ expect(query.to_s).to include('projectMembers')
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb
new file mode 100644
index 00000000000..b769aa4af5a
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::LfsObjectsPipeline do
+ let_it_be(:portable) { create(:project) }
+ let_it_be(:oid) { 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' }
+
+ let(:tmpdir) { Dir.mktmpdir }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test') }
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let(:lfs_dir_path) { tmpdir }
+ let(:lfs_json_file_path) { File.join(lfs_dir_path, 'lfs_objects.json')}
+ let(:lfs_file_path) { File.join(lfs_dir_path, oid)}
+
+ subject(:pipeline) { described_class.new(context) }
+
+ before do
+ FileUtils.mkdir_p(lfs_dir_path)
+ FileUtils.touch(lfs_json_file_path)
+ FileUtils.touch(lfs_file_path)
+ File.write(lfs_json_file_path, { oid => [0, 1, 2, nil] }.to_json )
+
+ allow(Dir).to receive(:mktmpdir).with('bulk_imports').and_return(tmpdir)
+ end
+
+ after do
+ FileUtils.remove_entry(tmpdir) if Dir.exist?(tmpdir)
+ end
+
+ describe '#run' do
+ it 'imports lfs objects into destination project and removes tmpdir' do
+ allow(pipeline)
+ .to receive(:extract)
+ .and_return(BulkImports::Pipeline::ExtractedData.new(data: [lfs_json_file_path, lfs_file_path]))
+
+ pipeline.run
+
+ expect(portable.lfs_objects.count).to eq(1)
+ expect(portable.lfs_objects_projects.count).to eq(4)
+ expect(Dir.exist?(tmpdir)).to eq(false)
+ end
+ end
+
+ describe '#extract' do
+ it 'downloads & extracts lfs objects filepaths' do
+ download_service = instance_double("BulkImports::FileDownloadService")
+ decompression_service = instance_double("BulkImports::FileDecompressionService")
+ extraction_service = instance_double("BulkImports::ArchiveExtractionService")
+
+ expect(BulkImports::FileDownloadService)
+ .to receive(:new)
+ .with(
+ configuration: context.configuration,
+ relative_url: "/#{entity.pluralized_name}/test/export_relations/download?relation=lfs_objects",
+ tmpdir: tmpdir,
+ filename: 'lfs_objects.tar.gz')
+ .and_return(download_service)
+ expect(BulkImports::FileDecompressionService).to receive(:new).with(tmpdir: tmpdir, filename: 'lfs_objects.tar.gz').and_return(decompression_service)
+ expect(BulkImports::ArchiveExtractionService).to receive(:new).with(tmpdir: tmpdir, filename: 'lfs_objects.tar').and_return(extraction_service)
+
+ expect(download_service).to receive(:execute)
+ expect(decompression_service).to receive(:execute)
+ expect(extraction_service).to receive(:execute)
+
+ extracted_data = pipeline.extract(context)
+
+ expect(extracted_data.data).to contain_exactly(lfs_json_file_path, lfs_file_path)
+ end
+ end
+
+ describe '#load' do
+ before do
+ allow(pipeline)
+ .to receive(:extract)
+ .and_return(BulkImports::Pipeline::ExtractedData.new(data: [lfs_json_file_path, lfs_file_path]))
+ end
+
+ context 'when file path is lfs json' do
+ it 'returns' do
+ filepath = File.join(tmpdir, 'lfs_objects.json')
+
+ allow(Gitlab::Json).to receive(:parse).with(filepath).and_return({})
+
+ expect { pipeline.load(context, filepath) }.not_to change { portable.lfs_objects.count }
+ end
+ end
+
+ context 'when file path is tar file' do
+ it 'returns' do
+ filepath = File.join(tmpdir, 'lfs_objects.tar')
+
+ expect { pipeline.load(context, filepath) }.not_to change { portable.lfs_objects.count }
+ end
+ end
+
+ context 'when lfs json read failed' do
+ it 'raises an error' do
+ File.write(lfs_json_file_path, 'invalid json')
+
+ expect { pipeline.load(context, lfs_file_path) }.to raise_error(BulkImports::Error, 'LFS Objects JSON read failed')
+ end
+ end
+
+ context 'when file path is being traversed' do
+ it 'raises an error' do
+ expect { pipeline.load(context, File.join(tmpdir, '..')) }.to raise_error(Gitlab::Utils::PathTraversalAttackError, 'Invalid path')
+ end
+ end
+
+ context 'when file path is not under tmpdir' do
+ it 'returns' do
+ expect { pipeline.load(context, '/home/test.txt') }.to raise_error(StandardError, 'path /home/test.txt is not allowed')
+ end
+ end
+
+ context 'when file path is symlink' do
+ it 'returns' do
+ symlink = File.join(tmpdir, 'symlink')
+
+ FileUtils.ln_s(File.join(tmpdir, lfs_file_path), symlink)
+
+ expect { pipeline.load(context, symlink) }.not_to change { portable.lfs_objects.count }
+ end
+ end
+
+ context 'when path is a directory' do
+ it 'returns' do
+ expect { pipeline.load(context, Dir.tmpdir) }.not_to change { portable.lfs_objects.count }
+ end
+ end
+
+ context 'lfs objects project' do
+ context 'when lfs objects json is invalid' do
+ context 'when oid value is not Array' do
+ it 'does not create lfs objects project' do
+ File.write(lfs_json_file_path, { oid => 'test' }.to_json )
+
+ expect { pipeline.load(context, lfs_file_path) }.not_to change { portable.lfs_objects_projects.count }
+ end
+ end
+
+ context 'when oid value is nil' do
+ it 'does not create lfs objects project' do
+ File.write(lfs_json_file_path, { oid => nil }.to_json )
+
+ expect { pipeline.load(context, lfs_file_path) }.not_to change { portable.lfs_objects_projects.count }
+ end
+ end
+
+ context 'when oid value is not allowed' do
+ it 'does not create lfs objects project' do
+ File.write(lfs_json_file_path, { oid => ['invalid'] }.to_json )
+
+ expect { pipeline.load(context, lfs_file_path) }.not_to change { portable.lfs_objects_projects.count }
+ end
+ end
+
+ context 'when repository type is duplicated' do
+ it 'creates only one lfs objects project' do
+ File.write(lfs_json_file_path, { oid => [0, 0, 1, 1, 2, 2] }.to_json )
+
+ expect { pipeline.load(context, lfs_file_path) }.to change { portable.lfs_objects_projects.count }.by(3)
+ end
+ end
+ end
+
+ context 'when lfs objects project fails to be created' do
+ it 'logs the failure' do
+ allow_next_instance_of(LfsObjectsProject) do |object|
+ allow(object).to receive(:persisted?).and_return(false)
+ end
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:warn)
+ .with(project_id: portable.id,
+ message: 'Failed to save lfs objects project',
+ errors: '', **Gitlab::ApplicationContext.current)
+ .exactly(4).times
+ end
+
+ pipeline.load(context, lfs_file_path)
+ end
+ end
+ end
+ end
+
+ describe '#after_run' do
+ it 'removes tmpdir' do
+ allow(FileUtils).to receive(:remove_entry).and_call_original
+ expect(FileUtils).to receive(:remove_entry).with(tmpdir).and_call_original
+
+ pipeline.after_run(nil)
+
+ expect(Dir.exist?(tmpdir)).to eq(false)
+ end
+
+ context 'when tmpdir does not exist' do
+ it 'does not attempt to remove tmpdir' do
+ FileUtils.remove_entry(tmpdir)
+
+ expect(FileUtils).not_to receive(:remove_entry).with(tmpdir)
+
+ pipeline.after_run(nil)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/pipelines/members_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/members_pipeline_spec.rb
new file mode 100644
index 00000000000..f9b95f79104
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/members_pipeline_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::MembersPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:member_user1) { create(:user, email: 'email1@email.com') }
+ let_it_be(:member_user2) { create(:user, email: 'email2@email.com') }
+ let_it_be(:member_data) do
+ {
+ user_id: member_user1.id,
+ created_by_id: member_user2.id,
+ access_level: 30,
+ created_at: '2020-01-01T00:00:00Z',
+ updated_at: '2020-01-01T00:00:00Z',
+ expires_at: nil
+ }
+ end
+
+ let(:parent) { create(:group) }
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let(:members) { portable.members.map { |m| m.slice(:user_id, :access_level) } }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ def extracted_data(email:, has_next_page: false)
+ data = {
+ 'created_at' => '2020-01-01T00:00:00Z',
+ 'updated_at' => '2020-01-02T00:00:00Z',
+ 'expires_at' => nil,
+ 'access_level' => {
+ 'integer_value' => 30
+ },
+ 'user' => {
+ 'public_email' => email
+ }
+ }
+
+ page_info = {
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? 'cursor' : nil
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info)
+ end
+
+ shared_examples 'members import' do
+ before do
+ portable.members.delete_all
+ end
+
+ describe '#run' do
+ it 'creates memberships for existing users' do
+ first_page = extracted_data(email: member_user1.email, has_next_page: true)
+ last_page = extracted_data(email: member_user2.email)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(first_page, last_page)
+ end
+
+ expect { pipeline.run }.to change(portable.members, :count).by(2)
+
+ expect(members).to contain_exactly(
+ { user_id: member_user1.id, access_level: 30 },
+ { user_id: member_user2.id, access_level: 30 }
+ )
+ end
+ end
+
+ describe '#load' do
+ it 'creates new membership' do
+ expect { subject.load(context, member_data) }.to change(portable.members, :count).by(1)
+
+ member = portable.members.find_by_user_id(member_user1.id)
+
+ expect(member.user).to eq(member_user1)
+ expect(member.created_by).to eq(member_user2)
+ expect(member.access_level).to eq(30)
+ expect(member.created_at).to eq('2020-01-01T00:00:00Z')
+ expect(member.updated_at).to eq('2020-01-01T00:00:00Z')
+ expect(member.expires_at).to eq(nil)
+ end
+
+ context 'when user_id is current user id' do
+ it 'does not create new membership' do
+ data = { user_id: user.id }
+
+ expect { pipeline.load(context, data) }.not_to change(portable.members, :count)
+ end
+ end
+
+ context 'when data is nil' do
+ it 'does not create new membership' do
+ expect { pipeline.load(context, nil) }.not_to change(portable.members, :count)
+ end
+ end
+
+ context 'when user membership already exists with the same access level' do
+ it 'does not create new membership' do
+ portable.members.create!(member_data)
+
+ expect { pipeline.load(context, member_data) }.not_to change(portable.members, :count)
+ end
+ end
+
+ context 'when portable is in a parent group' do
+ let(:tracker) { create(:bulk_import_tracker, entity: entity_with_parent) }
+
+ before do
+ parent.members.create!(member_data)
+ end
+
+ context 'when the same membership exists in parent group' do
+ it 'does not create new membership' do
+ expect { pipeline.load(context, member_data) }.not_to change(portable_with_parent.members, :count)
+ end
+ end
+
+ context 'when membership with higher access level exists in parent group' do
+ it 'creates new direct membership' do
+ data = member_data.merge(access_level: Gitlab::Access::MAINTAINER)
+
+ expect { pipeline.load(context, data) }.to change(portable_with_parent.members, :count)
+
+ member = portable_with_parent.members.find_by_user_id(member_user1.id)
+
+ expect(member.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'when membership with lower access level exists in parent group' do
+ it 'does not create new membership' do
+ data = member_data.merge(access_level: Gitlab::Access::GUEST)
+
+ expect { pipeline.load(context, data) }.not_to change(portable_with_parent.members, :count)
+ end
+ end
+ end
+ end
+ end
+
+ context 'when importing to group' do
+ let(:portable) { create(:group) }
+ let(:portable_with_parent) { create(:group, parent: parent) }
+ let(:entity) { create(:bulk_import_entity, :group_entity, group: portable, bulk_import: bulk_import) }
+ let(:entity_with_parent) { create(:bulk_import_entity, :group_entity, group: portable_with_parent, bulk_import: bulk_import) }
+
+ include_examples 'members import'
+ end
+
+ context 'when importing to project' do
+ let(:portable) { create(:project) }
+ let(:portable_with_parent) { create(:project, namespace: parent) }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, bulk_import: bulk_import) }
+ let(:entity_with_parent) { create(:bulk_import_entity, :project_entity, project: portable_with_parent, bulk_import: bulk_import) }
+
+ include_examples 'members import'
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
index b0f8f74783b..d03b8d8b5b2 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
@@ -3,14 +3,27 @@
require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetGroupQuery do
+ let_it_be(:tracker) { create(:bulk_import_tracker) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:query) { described_class.new(context: context) }
+
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
+
+ expect(result[:errors]).to be_empty
+ end
+
describe '#variables' do
it 'returns query variables based on entity information' do
- entity = double(source_full_path: 'test', bulk_import: nil)
- tracker = double(entity: entity)
- context = BulkImports::Pipeline::Context.new(tracker)
- expected = { full_path: entity.source_full_path }
+ expected = { full_path: tracker.entity.source_full_path }
- expect(described_class.variables(context)).to eq(expected)
+ expect(subject.variables).to eq(expected)
end
end
@@ -18,7 +31,7 @@ RSpec.describe BulkImports::Groups::Graphql::GetGroupQuery do
it 'returns data path' do
expected = %w[data group]
- expect(described_class.data_path).to eq(expected)
+ expect(subject.data_path).to eq(expected)
end
end
@@ -26,7 +39,7 @@ RSpec.describe BulkImports::Groups::Graphql::GetGroupQuery do
it 'returns pagination information path' do
expected = %w[data group page_info]
- expect(described_class.page_info_path).to eq(expected)
+ expect(subject.page_info_path).to eq(expected)
end
end
end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
deleted file mode 100644
index d0c4bb817b2..00000000000
--- a/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Graphql::GetMembersQuery 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 group_members 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 group_members page_info]
-
- expect(described_class.page_info_path).to eq(expected)
- end
- end
-end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb
index 1a7c5a4993c..fe28e3959a0 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb
@@ -3,25 +3,25 @@
require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetProjectsQuery do
- describe '#variables' do
- it 'returns valid variables based on entity information' 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
+ let_it_be(:tracker) { create(:bulk_import_tracker) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:query) { described_class.new(context: context) }
+
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
+
+ expect(result[:errors]).to be_empty
+ end
- context 'with invalid variables' do
- it 'raises an error' do
- expect { GraphQL::Query.new(GitlabSchema, described_class.to_s, variables: 'invalid') }.to raise_error(ArgumentError)
- end
+ context 'with invalid variables' do
+ it 'raises an error' do
+ expect { GraphQL::Query.new(GitlabSchema, subject.to_s, variables: 'invalid') }.to raise_error(ArgumentError)
end
end
@@ -29,7 +29,7 @@ RSpec.describe BulkImports::Groups::Graphql::GetProjectsQuery do
it 'returns data path' do
expected = %w[data group projects nodes]
- expect(described_class.data_path).to eq(expected)
+ expect(subject.data_path).to eq(expected)
end
end
@@ -37,7 +37,7 @@ RSpec.describe BulkImports::Groups::Graphql::GetProjectsQuery do
it 'returns pagination information path' do
expected = %w[data group projects page_info]
- expect(described_class.page_info_path).to eq(expected)
+ expect(subject.page_info_path).to eq(expected)
end
end
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
deleted file mode 100644
index 0126acb320b..00000000000
--- a/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Pipelines::MembersPipeline do
- let_it_be(:member_user1) { create(:user, email: 'email1@email.com') }
- let_it_be(:member_user2) { create(:user, email: 'email2@email.com') }
-
- 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(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
- let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
-
- subject { described_class.new(context) }
-
- describe '#run' do
- it 'maps existing users to the imported group' do
- first_page = extracted_data(email: member_user1.email, has_next_page: true)
- last_page = extracted_data(email: member_user2.email)
-
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor)
- .to receive(:extract)
- .and_return(first_page, last_page)
- end
-
- expect { subject.run }.to change(GroupMember, :count).by(2)
-
- members = group.members.map { |m| m.slice(:user_id, :access_level) }
-
- expect(members).to contain_exactly(
- { user_id: member_user1.id, access_level: 30 },
- { user_id: member_user2.id, access_level: 30 }
- )
- end
- end
-
- describe '#load' do
- it 'does nothing when there is no data' do
- expect { subject.load(context, nil) }.not_to change(GroupMember, :count)
- end
-
- it 'creates the member' do
- data = {
- 'user_id' => member_user1.id,
- 'created_by_id' => member_user2.id,
- 'access_level' => 30,
- 'created_at' => '2020-01-01T00:00:00Z',
- 'updated_at' => '2020-01-01T00:00:00Z',
- 'expires_at' => nil
- }
-
- expect { subject.load(context, data) }.to change(GroupMember, :count).by(1)
-
- member = group.members.last
-
- expect(member.user).to eq(member_user1)
- expect(member.created_by).to eq(member_user2)
- expect(member.access_level).to eq(30)
- expect(member.created_at).to eq('2020-01-01T00:00:00Z')
- expect(member.updated_at).to eq('2020-01-01T00:00:00Z')
- expect(member.expires_at).to eq(nil)
- end
-
- context 'when user_id is current user id' do
- it 'does not create new member' do
- data = { 'user_id' => user.id }
-
- expect { subject.load(context, data) }.not_to change(GroupMember, :count)
- 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::GetMembersQuery
- }
- )
- end
-
- it 'has transformers' do
- expect(described_class.transformers)
- .to contain_exactly(
- { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil },
- { klass: BulkImports::Groups::Transformers::MemberAttributesTransformer, options: nil }
- )
- end
- end
-
- def extracted_data(email:, has_next_page: false)
- data = {
- 'created_at' => '2020-01-01T00:00:00Z',
- 'updated_at' => '2020-01-01T00:00:00Z',
- 'expires_at' => nil,
- 'access_level' => {
- 'integer_value' => 30
- },
- 'user' => {
- 'public_email' => email
- }
- }
-
- page_info = {
- 'has_next_page' => has_next_page,
- 'next_page' => has_next_page ? 'cursor' : nil
- }
-
- BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info)
- end
-end
diff --git a/spec/lib/bulk_imports/groups/stage_spec.rb b/spec/lib/bulk_imports/groups/stage_spec.rb
index 55a8e40f480..b6bb8a7d195 100644
--- a/spec/lib/bulk_imports/groups/stage_spec.rb
+++ b/spec/lib/bulk_imports/groups/stage_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe BulkImports::Groups::Stage do
[
[0, BulkImports::Groups::Pipelines::GroupPipeline],
[1, BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline],
- [1, BulkImports::Groups::Pipelines::MembersPipeline],
+ [1, BulkImports::Common::Pipelines::MembersPipeline],
[1, BulkImports::Common::Pipelines::LabelsPipeline],
[1, BulkImports::Common::Pipelines::MilestonesPipeline],
[1, BulkImports::Common::Pipelines::BadgesPipeline],
diff --git a/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
index af99428e0c1..c8935f71f10 100644
--- a/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
@@ -48,12 +48,12 @@ RSpec.describe BulkImports::Groups::Transformers::MemberAttributesTransformer do
data = member_data(email: user.email)
expect(subject.transform(context, data)).to eq(
- 'access_level' => 30,
- 'user_id' => user.id,
- 'created_by_id' => user.id,
- 'created_at' => '2020-01-01T00:00:00Z',
- 'updated_at' => '2020-01-01T00:00:00Z',
- 'expires_at' => nil
+ access_level: 30,
+ user_id: user.id,
+ created_by_id: user.id,
+ created_at: '2020-01-01T00:00:00Z',
+ updated_at: '2020-01-01T00:00:00Z',
+ expires_at: nil
)
end
@@ -62,12 +62,12 @@ RSpec.describe BulkImports::Groups::Transformers::MemberAttributesTransformer do
data = member_data(email: secondary_email)
expect(subject.transform(context, data)).to eq(
- 'access_level' => 30,
- 'user_id' => user.id,
- 'created_by_id' => user.id,
- 'created_at' => '2020-01-01T00:00:00Z',
- 'updated_at' => '2020-01-01T00:00:00Z',
- 'expires_at' => nil
+ access_level: 30,
+ user_id: user.id,
+ created_by_id: user.id,
+ created_at: '2020-01-01T00:00:00Z',
+ updated_at: '2020-01-01T00:00:00Z',
+ expires_at: nil
)
end
diff --git a/spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb b/spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb
new file mode 100644
index 00000000000..6593aa56506
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Graphql::GetProjectQuery do
+ let_it_be(:tracker) { create(:bulk_import_tracker) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:query) { described_class.new(context: context) }
+
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
+
+ expect(result[:errors]).to be_empty
+ end
+
+ it 'queries project based on source_full_path' do
+ expected = { full_path: tracker.entity.source_full_path }
+
+ expect(subject.variables).to eq(expected)
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb b/spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb
index 4dba81dc0d2..8ed105bc0c9 100644
--- a/spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb
+++ b/spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb
@@ -3,19 +3,29 @@
require 'spec_helper'
RSpec.describe BulkImports::Projects::Graphql::GetRepositoryQuery do
- describe 'query repository based on full_path' do
- let(:entity) { double(source_full_path: 'test', bulk_import: nil) }
- let(:tracker) { double(entity: entity) }
- let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:tracker) { create(:bulk_import_tracker) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
- it 'returns project repository url' do
- expect(described_class.to_s).to include('httpUrlToRepo')
- end
+ subject(:query) { described_class.new(context: context) }
- it 'queries project based on source_full_path' do
- expected = { full_path: entity.source_full_path }
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
- expect(described_class.variables(context)).to eq(expected)
- end
+ expect(result[:errors]).to be_empty
+ end
+
+ it 'returns project repository url' do
+ expect(subject.to_s).to include('httpUrlToRepo')
+ end
+
+ it 'queries project based on source_full_path' do
+ expected = { full_path: tracker.entity.source_full_path }
+
+ expect(subject.variables).to eq(expected)
end
end
diff --git a/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb b/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb
index b680fa5cbfc..1bd4106297d 100644
--- a/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb
+++ b/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb
@@ -3,56 +3,56 @@
require 'spec_helper'
RSpec.describe BulkImports::Projects::Graphql::GetSnippetRepositoryQuery do
- describe 'query repository based on full_path' do
- let_it_be(:entity) { create(:bulk_import_entity) }
- let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
-
- it 'has a valid query' do
- 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
+ let_it_be(:entity) { create(:bulk_import_entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
- it 'returns snippet httpUrlToRepo' do
- expect(described_class.to_s).to include('httpUrlToRepo')
- end
+ subject(:query) { described_class.new(context: context) }
- it 'returns snippet createdAt' do
- expect(described_class.to_s).to include('createdAt')
- end
+ it 'has a valid query' do
+ parsed_query = GraphQL::Query.new(
+ GitlabSchema,
+ query.to_s,
+ variables: query.variables
+ )
+ result = GitlabSchema.static_validator.validate(parsed_query)
- it 'returns snippet title' do
- expect(described_class.to_s).to include('title')
- end
+ expect(result[:errors]).to be_empty
+ end
- describe '.variables' do
- it 'queries project based on source_full_path and pagination' do
- expected = { full_path: entity.source_full_path, cursor: nil, per_page: 500 }
+ it 'returns snippet httpUrlToRepo' do
+ expect(subject.to_s).to include('httpUrlToRepo')
+ end
- expect(described_class.variables(context)).to eq(expected)
- end
+ it 'returns snippet createdAt' do
+ expect(subject.to_s).to include('createdAt')
+ end
+
+ it 'returns snippet title' do
+ expect(subject.to_s).to include('title')
+ end
+
+ describe '.variables' do
+ it 'queries project based on source_full_path and pagination' do
+ expected = { full_path: entity.source_full_path, cursor: nil, per_page: 500 }
+
+ expect(subject.variables).to eq(expected)
end
+ end
- describe '.data_path' do
- it '.data_path returns data path' do
- expected = %w[data project snippets nodes]
+ describe '.data_path' do
+ it '.data_path returns data path' do
+ expected = %w[data project snippets nodes]
- expect(described_class.data_path).to eq(expected)
- end
+ expect(subject.data_path).to eq(expected)
end
+ end
- describe '.page_info_path' do
- it '.page_info_path returns pagination information path' do
- expected = %w[data project snippets page_info]
+ describe '.page_info_path' do
+ it '.page_info_path returns pagination information path' do
+ expected = %w[data project snippets page_info]
- expect(described_class.page_info_path).to eq(expected)
- end
+ expect(subject.page_info_path).to eq(expected)
end
end
end
diff --git a/spec/lib/bulk_imports/projects/stage_spec.rb b/spec/lib/bulk_imports/projects/stage_spec.rb
index 81cbdcae9d1..ef98613dc25 100644
--- a/spec/lib/bulk_imports/projects/stage_spec.rb
+++ b/spec/lib/bulk_imports/projects/stage_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe BulkImports::Projects::Stage do
[4, BulkImports::Projects::Pipelines::ServiceDeskSettingPipeline],
[5, BulkImports::Common::Pipelines::WikiPipeline],
[5, BulkImports::Common::Pipelines::UploadsPipeline],
+ [5, BulkImports::Common::Pipelines::LfsObjectsPipeline],
[5, BulkImports::Projects::Pipelines::AutoDevopsPipeline],
[5, BulkImports::Projects::Pipelines::PipelineSchedulesPipeline],
[6, BulkImports::Common::Pipelines::EntityFinisher]
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index 259d7d5ad13..974c3478ddc 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -5,29 +5,7 @@ require 'spec_helper'
RSpec.describe ContainerRegistry::Client do
using RSpec::Parameterized::TableSyntax
- let(:token) { '12345' }
- let(:options) { { token: token } }
- let(:registry_api_url) { 'http://container-registry' }
- let(:client) { described_class.new(registry_api_url, options) }
- let(:push_blob_headers) do
- {
- 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
- 'Authorization' => "bearer #{token}",
- 'Content-Type' => 'application/octet-stream',
- 'User-Agent' => "GitLab/#{Gitlab::VERSION}"
- }
- end
-
- let(:headers_with_accept_types) do
- {
- 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
- 'Authorization' => "bearer #{token}",
- 'User-Agent' => "GitLab/#{Gitlab::VERSION}"
- }
- end
-
- let(:expected_faraday_headers) { { user_agent: "GitLab/#{Gitlab::VERSION}" } }
- let(:expected_faraday_request_options) { Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS }
+ include_context 'container registry client'
shared_examples 'handling timeouts' do
let(:retry_options) do
@@ -48,14 +26,14 @@ RSpec.describe ContainerRegistry::Client do
retry_block: -> (_, _, _, _) { actual_retries += 1 }
)
- stub_const('ContainerRegistry::Client::RETRY_OPTIONS', retry_options_with_block)
+ stub_const('ContainerRegistry::BaseClient::RETRY_OPTIONS', retry_options_with_block)
expect { subject }.to raise_error(Faraday::ConnectionFailed)
expect(actual_retries).to eq(retry_options_with_block[:max])
end
it 'logs the error' do
- stub_const('ContainerRegistry::Client::RETRY_OPTIONS', retry_options)
+ stub_const('ContainerRegistry::BaseClient::RETRY_OPTIONS', retry_options)
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
@@ -63,7 +41,7 @@ RSpec.describe ContainerRegistry::Client do
.times
.with(
an_instance_of(Faraday::ConnectionFailed),
- class: described_class.name,
+ class: ::ContainerRegistry::BaseClient.name,
url: URI(url)
)
@@ -325,14 +303,14 @@ RSpec.describe ContainerRegistry::Client do
subject { client.supports_tag_delete? }
where(:registry_tags_support_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
- true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
- true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | true
- true | true | [] | true | true
- true | false | [] | true | true
- false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
- false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | false
- false | true | [] | true | false
- false | false | [] | true | false
+ true | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ true | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | true | true
+ true | true | [] | true | true
+ true | false | [] | true | true
+ false | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ false | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | true | false
+ false | true | [] | true | false
+ false | false | [] | true | false
end
with_them do
@@ -366,38 +344,38 @@ RSpec.describe ContainerRegistry::Client do
subject { described_class.supports_tag_delete? }
where(:registry_api_url, :registry_enabled, :registry_tags_support_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
- 'http://sandbox.local' | true | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
- 'http://sandbox.local' | true | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | true
- 'http://sandbox.local' | true | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | true
- 'http://sandbox.local' | true | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | true | false
- 'http://sandbox.local' | false | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- 'http://sandbox.local' | false | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- 'http://sandbox.local' | false | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- 'http://sandbox.local' | false | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- 'http://sandbox.local' | true | true | true | [] | true | true
- 'http://sandbox.local' | true | true | false | [] | true | true
- 'http://sandbox.local' | true | false | true | [] | true | false
- 'http://sandbox.local' | true | false | false | [] | true | false
- 'http://sandbox.local' | false | true | true | [] | false | false
- 'http://sandbox.local' | false | true | false | [] | false | false
- 'http://sandbox.local' | false | false | true | [] | false | false
- 'http://sandbox.local' | false | false | false | [] | false | false
- '' | true | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | true | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | true | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | true | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | false | true | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | false | true | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | false | false | true | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | false | false | false | [ContainerRegistry::Client::REGISTRY_TAG_DELETE_FEATURE] | false | false
- '' | true | true | true | [] | false | false
- '' | true | true | false | [] | false | false
- '' | true | false | true | [] | false | false
- '' | true | false | false | [] | false | false
- '' | false | true | true | [] | false | false
- '' | false | true | false | [] | false | false
- '' | false | false | true | [] | false | false
- '' | false | false | false | [] | false | false
+ 'http://sandbox.local' | true | true | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ 'http://sandbox.local' | true | true | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | true | true
+ 'http://sandbox.local' | true | false | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | true
+ 'http://sandbox.local' | true | false | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | true | false
+ 'http://sandbox.local' | false | true | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | true | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | false | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | false | false | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ 'http://sandbox.local' | true | true | true | [] | true | true
+ 'http://sandbox.local' | true | true | false | [] | true | true
+ 'http://sandbox.local' | true | false | true | [] | true | false
+ 'http://sandbox.local' | true | false | false | [] | true | false
+ 'http://sandbox.local' | false | true | true | [] | false | false
+ 'http://sandbox.local' | false | true | false | [] | false | false
+ 'http://sandbox.local' | false | false | true | [] | false | false
+ 'http://sandbox.local' | false | false | false | [] | false | false
+ '' | true | true | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | true | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | false | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | false | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | true | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | true | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | false | true | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | false | false | false | [described_class::REGISTRY_TAG_DELETE_FEATURE] | false | false
+ '' | true | true | true | [] | false | false
+ '' | true | true | false | [] | false | false
+ '' | true | false | true | [] | false | false
+ '' | true | false | false | [] | false | false
+ '' | false | true | true | [] | false | false
+ '' | false | true | false | [] | false | false
+ '' | false | false | true | [] | false | false
+ '' | false | false | false | [] | false | false
end
with_them do
diff --git a/spec/lib/container_registry/gitlab_api_client_spec.rb b/spec/lib/container_registry/gitlab_api_client_spec.rb
new file mode 100644
index 00000000000..292582a8d83
--- /dev/null
+++ b/spec/lib/container_registry/gitlab_api_client_spec.rb
@@ -0,0 +1,204 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::GitlabApiClient do
+ using RSpec::Parameterized::TableSyntax
+
+ include_context 'container registry client'
+
+ let(:path) { 'namespace/path/to/repository' }
+
+ describe '#supports_gitlab_api?' do
+ subject { client.supports_gitlab_api? }
+
+ where(:registry_gitlab_api_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
+ false | true | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | false | true
+ true | false | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | true | true
+ true | true | [] | true | true
+ true | false | [] | true | true
+ false | true | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | false | true
+ false | false | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | true | false
+ false | true | [] | true | false
+ false | false | [] | true | false
+ end
+
+ with_them do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(is_on_dot_com)
+ stub_registry_gitlab_api_support(registry_gitlab_api_enabled)
+ stub_application_setting(container_registry_features: container_registry_features)
+ end
+
+ it 'returns the expected result' do
+ if expect_registry_to_be_pinged
+ expect(Faraday::Connection).to receive(:new).and_call_original
+ else
+ expect(Faraday::Connection).not_to receive(:new)
+ end
+
+ expect(subject).to be expected_result
+ end
+ end
+
+ context 'with 401 response' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ stub_application_setting(container_registry_features: [])
+ stub_request(:get, "#{registry_api_url}/gitlab/v1/")
+ .to_return(status: 401, body: '')
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#pre_import_repository' do
+ subject { client.pre_import_repository(path) }
+
+ where(:status_code, :expected_result) do
+ 200 | :already_imported
+ 202 | :ok
+ 401 | :unauthorized
+ 404 | :not_found
+ 409 | :already_being_imported
+ 418 | :error
+ 424 | :pre_import_failed
+ 425 | :already_being_imported
+ 429 | :too_many_imports
+ end
+
+ with_them do
+ before do
+ stub_pre_import(path, status_code, pre: true)
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+
+ describe '#import_repository' do
+ subject { client.import_repository(path) }
+
+ where(:status_code, :expected_result) do
+ 200 | :already_imported
+ 202 | :ok
+ 401 | :unauthorized
+ 404 | :not_found
+ 409 | :already_being_imported
+ 418 | :error
+ 424 | :pre_import_failed
+ 425 | :already_being_imported
+ 429 | :too_many_imports
+ end
+
+ with_them do
+ before do
+ stub_pre_import(path, status_code, pre: false)
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+
+ describe '#import_status' do
+ subject { client.import_status(path) }
+
+ before do
+ stub_import_status(path, status)
+ end
+
+ context 'with a status' do
+ let(:status) { 'this_is_a_test' }
+
+ it { is_expected.to eq(status) }
+ end
+
+ context 'with no status' do
+ let(:status) { nil }
+
+ it { is_expected.to eq('error') }
+ end
+ end
+
+ describe '.supports_gitlab_api?' do
+ subject { described_class.supports_gitlab_api? }
+
+ where(:registry_gitlab_api_enabled, :is_on_dot_com, :container_registry_features, :expect_registry_to_be_pinged, :expected_result) do
+ true | true | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | false | true
+ true | false | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | true | true
+ false | true | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | false | true
+ false | false | [described_class::REGISTRY_GITLAB_V1_API_FEATURE] | true | false
+ true | true | [] | true | true
+ true | false | [] | true | true
+ false | true | [] | true | false
+ false | false | [] | true | false
+ end
+
+ with_them do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(is_on_dot_com)
+ stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
+ stub_registry_gitlab_api_support(registry_gitlab_api_enabled)
+ stub_application_setting(container_registry_features: container_registry_features)
+ end
+
+ it 'returns the expected result' do
+ if expect_registry_to_be_pinged
+ expect(Faraday::Connection).to receive(:new).and_call_original
+ else
+ expect(Faraday::Connection).not_to receive(:new)
+ end
+
+ expect(subject).to be expected_result
+ end
+ end
+
+ context 'with the registry disabled' do
+ before do
+ stub_container_registry_config(enabled: false, api_url: 'http://sandbox.local', key: 'spec/fixtures/x509_certificate_pk.key')
+ end
+
+ it 'returns false' do
+ expect(Faraday::Connection).not_to receive(:new)
+
+ expect(subject).to be_falsey
+ end
+ end
+
+ context 'with a blank registry url' do
+ before do
+ stub_container_registry_config(enabled: true, api_url: '', key: 'spec/fixtures/x509_certificate_pk.key')
+ end
+
+ it 'returns false' do
+ expect(Faraday::Connection).not_to receive(:new)
+
+ expect(subject).to be_falsey
+ end
+ end
+ end
+
+ def stub_pre_import(path, status_code, pre:)
+ stub_request(:put, "#{registry_api_url}/gitlab/v1/import/#{path}/?pre=#{pre}")
+ .with(headers: { 'Accept' => described_class::JSON_TYPE })
+ .to_return(status: status_code, body: '')
+ end
+
+ def stub_registry_gitlab_api_support(supported = true)
+ status_code = supported ? 200 : 404
+ stub_request(:get, "#{registry_api_url}/gitlab/v1/")
+ .with(headers: { 'Accept' => described_class::JSON_TYPE })
+ .to_return(status: status_code, body: '')
+ end
+
+ def stub_import_status(path, status)
+ stub_request(:get, "#{registry_api_url}/gitlab/v1/import/#{path}/")
+ .with(headers: { 'Accept' => described_class::JSON_TYPE })
+ .to_return(
+ status: 200,
+ body: { status: status }.to_json,
+ headers: { content_type: 'application/json' }
+ )
+ end
+end
diff --git a/spec/lib/container_registry/migration_spec.rb b/spec/lib/container_registry/migration_spec.rb
new file mode 100644
index 00000000000..ffbbfb249e3
--- /dev/null
+++ b/spec/lib/container_registry/migration_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::Migration do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '.enabled?' do
+ subject { described_class.enabled? }
+
+ it { is_expected.to eq(true) }
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enabled: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '.limit_gitlab_org?' do
+ subject { described_class.limit_gitlab_org? }
+
+ it { is_expected.to eq(true) }
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_limit_gitlab_org: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '.enqueue_waiting_time' do
+ subject { described_class.enqueue_waiting_time }
+
+ where(:slow_enabled, :fast_enabled, :expected_result) do
+ false | false | 1.hour
+ true | false | 6.hours
+ false | true | 0
+ true | true | 0
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(
+ container_registry_migration_phase2_enqueue_speed_slow: slow_enabled,
+ container_registry_migration_phase2_enqueue_speed_fast: fast_enabled
+ )
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+
+ describe '.capacity' do
+ subject { described_class.capacity }
+
+ where(:ff_1_enabled, :ff_10_enabled, :ff_25_enabled, :expected_result) do
+ false | false | false | 0
+ true | false | false | 1
+ true | true | false | 10
+ true | true | true | 25
+ false | true | false | 10
+ false | true | true | 25
+ false | false | true | 25
+ true | false | true | 25
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(
+ container_registry_migration_phase2_capacity_1: ff_1_enabled,
+ container_registry_migration_phase2_capacity_10: ff_10_enabled,
+ container_registry_migration_phase2_capacity_25: ff_25_enabled
+ )
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+
+ describe '.max_tags_count' do
+ let(:value) { 1 }
+
+ before do
+ stub_application_setting(container_registry_import_max_tags_count: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.max_tags_count).to eq(value)
+ end
+ end
+
+ describe '.max_retries' do
+ let(:value) { 1 }
+
+ before do
+ stub_application_setting(container_registry_import_max_retries: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.max_retries).to eq(value)
+ end
+ end
+
+ describe '.start_max_retries' do
+ let(:value) { 1 }
+
+ before do
+ stub_application_setting(container_registry_import_start_max_retries: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.start_max_retries).to eq(value)
+ end
+ end
+
+ describe '.max_step_duration' do
+ let(:value) { 5.minutes }
+
+ before do
+ stub_application_setting(container_registry_import_max_step_duration: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.max_step_duration).to eq(value)
+ end
+ end
+
+ describe '.target_plan_name' do
+ let(:value) { 'free' }
+
+ before do
+ stub_application_setting(container_registry_import_target_plan: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.target_plan_name).to eq(value)
+ end
+ end
+
+ describe '.created_before' do
+ let(:value) { 1.day.ago }
+
+ before do
+ stub_application_setting(container_registry_import_created_before: value)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.created_before).to eq(value)
+ end
+ end
+
+ describe '.target_plan' do
+ let_it_be(:plan) { create(:plan) }
+
+ before do
+ stub_application_setting(container_registry_import_target_plan: plan.name)
+ end
+
+ it 'returns the matching application_setting' do
+ expect(described_class.target_plan).to eq(plan)
+ end
+ end
+end
diff --git a/spec/lib/container_registry/registry_spec.rb b/spec/lib/container_registry/registry_spec.rb
index d6e2b17f53b..c690d96b4f5 100644
--- a/spec/lib/container_registry/registry_spec.rb
+++ b/spec/lib/container_registry/registry_spec.rb
@@ -27,4 +27,14 @@ RSpec.describe ContainerRegistry::Registry do
it { is_expected.to eq(path) }
end
end
+
+ describe '#gitlab_api_client' do
+ subject { registry.gitlab_api_client }
+
+ it 'returns a GitLabApiClient with an import token' do
+ expect(Auth::ContainerRegistryAuthenticationService).to receive(:import_access_token)
+
+ expect(subject).to be_instance_of(ContainerRegistry::GitlabApiClient)
+ end
+ end
end
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index 9b2bb024fa6..5db2fbd923e 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe ExtractsPath do
describe '#assign_ref_vars' do
let(:ref) { sample_commit[:id] }
let(:path) { sample_commit[:line_code_path] }
- let(:params) { { path: path, ref: ref } }
+ let(:params) { ActionController::Parameters.new(path: path, ref: ref) }
it_behaves_like 'assigns ref vars'
@@ -54,7 +54,8 @@ RSpec.describe ExtractsPath do
context 'ref only exists without .atom suffix' do
context 'with a path' do
- let(:params) { { ref: 'v1.0.0.atom', path: 'README.md' } }
+ let(:ref) { 'v1.0.0.atom' }
+ let(:path) { 'README.md' }
it 'renders a 404' do
expect(self).to receive(:render_404)
@@ -64,7 +65,8 @@ RSpec.describe ExtractsPath do
end
context 'without a path' do
- let(:params) { { ref: 'v1.0.0.atom' } }
+ let(:ref) { 'v1.0.0.atom' }
+ let(:path) { nil }
before do
assign_ref_vars
@@ -82,7 +84,8 @@ RSpec.describe ExtractsPath do
context 'ref exists with .atom suffix' do
context 'with a path' do
- let(:params) { { ref: 'master.atom', path: 'README.md' } }
+ let(:ref) { 'master.atom' }
+ let(:path) { 'README.md' }
before do
repository = @project.repository
@@ -102,7 +105,8 @@ RSpec.describe ExtractsPath do
end
context 'without a path' do
- let(:params) { { ref: 'master.atom' } }
+ let(:ref) { 'master.atom' }
+ let(:path) { nil }
before do
repository = @project.repository
@@ -125,7 +129,8 @@ RSpec.describe ExtractsPath do
end
context 'ref and path are nil' do
- let(:params) { { path: nil, ref: nil } }
+ let(:path) { nil }
+ let(:ref) { nil }
it 'does not set commit' do
expect(container.repository).not_to receive(:commit).with('')
@@ -209,8 +214,8 @@ RSpec.describe ExtractsPath do
expect(extract_ref_without_atom('release/app/v1.0.0.atom')).to eq('release/app/v1.0.0')
end
- it 'returns nil if there are no matching refs' do
- expect(extract_ref_without_atom('foo.atom')).to eq(nil)
+ it 'raises an error if there are no matching refs' do
+ expect { extract_ref_without_atom('foo.atom') }.to raise_error(ExtractsRef::InvalidPathError)
end
end
end
diff --git a/spec/lib/extracts_ref_spec.rb b/spec/lib/extracts_ref_spec.rb
index 3cdce150de9..3e9a7499fdd 100644
--- a/spec/lib/extracts_ref_spec.rb
+++ b/spec/lib/extracts_ref_spec.rb
@@ -10,7 +10,8 @@ RSpec.describe ExtractsRef do
let_it_be(:container) { create(:snippet, :repository, author: owner) }
let(:ref) { sample_commit[:id] }
- let(:params) { { path: sample_commit[:line_code_path], ref: ref } }
+ let(:path) { sample_commit[:line_code_path] }
+ let(:params) { ActionController::Parameters.new(path: path, ref: ref) }
before do
ref_names = ['master', 'foo/bar/baz', 'v1.0.0', 'v2.0.0', 'release/app', 'release/app/v1.0.0']
@@ -23,7 +24,8 @@ RSpec.describe ExtractsRef do
it_behaves_like 'assigns ref vars'
context 'ref and path are nil' do
- let(:params) { { path: nil, ref: nil } }
+ let(:ref) { nil }
+ let(:path) { nil }
it 'does not set commit' do
expect(container.repository).not_to receive(:commit).with('')
@@ -33,6 +35,15 @@ RSpec.describe ExtractsRef do
expect(@commit).to be_nil
end
end
+
+ context 'when ref and path have incorrect format' do
+ let(:ref) { { wrong: :format } }
+ let(:path) { { also: :wrong } }
+
+ it 'does not raise an exception' do
+ expect { assign_ref_vars }.not_to raise_error
+ end
+ end
end
it_behaves_like 'extracts refs'
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 8c546390201..5080d21d564 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -728,13 +728,13 @@ RSpec.describe Feature, stub_feature_flags: false do
describe '#targets' do
let(:project) { create(:project) }
let(:group) { create(:group) }
- let(:user_name) { project.owner.username }
+ let(:user_name) { project.first_owner.username }
subject { described_class.new(user: user_name, project: project.full_path, group: group.full_path) }
it 'returns all found targets' do
expect(subject.targets).to be_an(Array)
- expect(subject.targets).to eq([project.owner, project, group])
+ expect(subject.targets).to eq([project.first_owner, project, group])
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 4e172dd32f0..d9fa6b931ad 100644
--- a/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
let(:ce_temp_dir) { Dir.mktmpdir }
let(:ee_temp_dir) { Dir.mktmpdir }
+ let(:timestamp) { Time.current.to_i }
let(:generator_options) { { 'category' => 'Groups::EmailCampaignsController', 'action' => 'click' } }
before do
@@ -12,6 +13,10 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
stub_const("#{described_class}::EE_DIR", ee_temp_dir)
end
+ around do |example|
+ freeze_time { example.run }
+ end
+
after do
FileUtils.rm_rf([ce_temp_dir, ee_temp_dir])
end
@@ -22,16 +27,41 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
end
let(:sample_event_dir) { 'lib/generators/gitlab/snowplow_event_definition_generator' }
+ let(:file_name) { Dir.children(ce_temp_dir).first }
it 'creates CE event definition file using the template' do
sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event.yml'))).load_raw!
described_class.new([], generator_options).invoke_all
- event_definition_path = File.join(ce_temp_dir, 'groups__email_campaigns_controller_click.yml')
+ event_definition_path = File.join(ce_temp_dir, file_name)
expect(::Gitlab::Config::Loader::Yaml.new(File.read(event_definition_path)).load_raw!).to eq(sample_event)
end
+ describe 'generated filename' do
+ it 'includes timestamp' do
+ described_class.new([], generator_options).invoke_all
+
+ expect(file_name).to include(timestamp.to_s)
+ end
+
+ it 'removes special characters' do
+ generator_options = { 'category' => '"`ui:[mavenpackages | t5%348()-=@ ]`"', 'action' => 'click' }
+
+ described_class.new([], generator_options).invoke_all
+
+ expect(file_name).to include('uimavenpackagest')
+ end
+
+ it 'cuts name if longer than 100 characters' do
+ generator_options = { 'category' => 'a' * 100, 'action' => 'click' }
+
+ described_class.new([], generator_options).invoke_all
+
+ expect(file_name.length).to eq(100)
+ end
+ end
+
context 'event definition already exists' do
before do
stub_const('Gitlab::VERSION', '12.11.0-pre')
@@ -44,7 +74,7 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
stub_const('Gitlab::VERSION', '13.11.0-pre')
described_class.new([], generator_options.merge('force' => true)).invoke_all
- event_definition_path = File.join(ce_temp_dir, 'groups__email_campaigns_controller_click.yml')
+ event_definition_path = File.join(ce_temp_dir, file_name)
event_data = ::Gitlab::Config::Loader::Yaml.new(File.read(event_definition_path)).load_raw!
expect(event_data).to eq(sample_event)
@@ -56,13 +86,17 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
end
end
- it 'creates EE event definition file using the template' do
- sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event_ee.yml'))).load_raw!
+ describe 'EE' do
+ let(:file_name) { Dir.children(ee_temp_dir).first }
- described_class.new([], generator_options.merge('ee' => true)).invoke_all
+ it 'creates EE event definition file using the template' do
+ sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event_ee.yml'))).load_raw!
- event_definition_path = File.join(ee_temp_dir, 'groups__email_campaigns_controller_click.yml')
- expect(::Gitlab::Config::Loader::Yaml.new(File.read(event_definition_path)).load_raw!).to eq(sample_event)
+ described_class.new([], generator_options.merge('ee' => true)).invoke_all
+
+ event_definition_path = File.join(ee_temp_dir, file_name)
+ expect(::Gitlab::Config::Loader::Yaml.new(File.read(event_definition_path)).load_raw!).to eq(sample_event)
+ end
end
end
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
index 55ba6e56237..8eb75feaa8d 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
@@ -8,16 +8,17 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher do
let_it_be(:issue_2) { create(:issue, project: project) }
let_it_be(:issue_3) { create(:issue, project: project) }
- let_it_be(:stage_event_1) { create(:cycle_analytics_issue_stage_event, issue_id: issue_1.id, start_event_timestamp: 2.years.ago, end_event_timestamp: 1.year.ago) } # duration: 1 year
- let_it_be(:stage_event_2) { create(:cycle_analytics_issue_stage_event, issue_id: issue_2.id, start_event_timestamp: 5.years.ago, end_event_timestamp: 2.years.ago) } # duration: 3 years
- let_it_be(:stage_event_3) { create(:cycle_analytics_issue_stage_event, issue_id: issue_3.id, start_event_timestamp: 6.years.ago, end_event_timestamp: 3.months.ago) } # duration: 5+ years
-
let_it_be(:stage) { create(:cycle_analytics_project_stage, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production, project: project) }
- let(:params) { {} }
+ let_it_be(:stage_event_1) { create(:cycle_analytics_issue_stage_event, stage_event_hash_id: stage.stage_event_hash_id, project_id: project.id, issue_id: issue_1.id, start_event_timestamp: 2.years.ago, end_event_timestamp: 1.year.ago) } # duration: 1 year
+ let_it_be(:stage_event_2) { create(:cycle_analytics_issue_stage_event, stage_event_hash_id: stage.stage_event_hash_id, project_id: project.id, issue_id: issue_2.id, start_event_timestamp: 5.years.ago, end_event_timestamp: 2.years.ago) } # duration: 3 years
+ let_it_be(:stage_event_3) { create(:cycle_analytics_issue_stage_event, stage_event_hash_id: stage.stage_event_hash_id, project_id: project.id, issue_id: issue_3.id, start_event_timestamp: 6.years.ago, end_event_timestamp: 3.months.ago) } # duration: 5+ years
+
+ let(:params) { { from: 10.years.ago, to: Date.today } }
subject(:records_fetcher) do
- described_class.new(stage: stage, query: Analytics::CycleAnalytics::IssueStageEvent.all, params: params)
+ query_builder = Gitlab::Analytics::CycleAnalytics::Aggregated::BaseQueryBuilder.new(stage: stage, params: params)
+ described_class.new(stage: stage, query: query_builder.build_sorted_query, params: params)
end
shared_examples 'match returned records' do
@@ -123,6 +124,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher do
it 'skips non-existing issue records' do
create(:cycle_analytics_issue_stage_event, {
issue_id: 0, # non-existing id
+ stage_event_hash_id: stage.stage_event_hash_id,
+ project_id: project.id,
start_event_timestamp: 5.months.ago,
end_event_timestamp: 3.months.ago
})
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
index 4fe55ba0c0c..dc46dade87e 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
@@ -43,8 +43,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
end
before do
- issue1.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
- issue2.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue1.metrics.update!(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue2.metrics.update!(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
end
context 'when records are loaded by guest' do
@@ -73,8 +73,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
end
before do
- mr1.metrics.update(merged_at: 3.days.ago)
- mr2.metrics.update(merged_at: 3.days.ago)
+ mr1.metrics.update!(merged_at: 3.days.ago)
+ mr2.metrics.update!(merged_at: 3.days.ago)
end
include_context 'when records are loaded by maintainer'
@@ -95,9 +95,9 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
end
before(:all) do
- issue1.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
- issue2.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
- issue3.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue1.metrics.update!(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue2.metrics.update!(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue3.metrics.update!(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
end
before do
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index 5ecec978017..55f5ae7d7dc 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -125,6 +125,17 @@ RSpec.describe Gitlab::ApplicationContext do
.to include(project: project.full_path, root_namespace: project.full_path_components.first)
end
+ it 'contains known keys' do
+ context = described_class.new(project: project)
+
+ # Make sure all possible keys would be included
+ allow(context).to receive_message_chain(:set_values, :include?).and_return(true)
+
+ # If a newly added key is added to the context hash, we need to list it in
+ # the known keys constant. This spec ensures that we do.
+ expect(context.to_lazy_hash.keys).to contain_exactly(*described_class.known_keys)
+ end
+
describe 'setting the client' do
let_it_be(:remote_ip) { '127.0.0.1' }
let_it_be(:runner) { create(:ci_runner) }
diff --git a/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
new file mode 100644
index 00000000000..f55e1b44936
--- /dev/null
+++ b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Audit::CiRunnerTokenAuthor do
+ describe '.initialize' do
+ subject { described_class.new(audit_event) }
+
+ let(:details) { }
+ let(:audit_event) { instance_double(AuditEvent, details: details, entity_type: 'Project', entity_path: 'd/e') }
+
+ context 'with runner_authentication_token' do
+ let(:details) do
+ { runner_authentication_token: 'abc1234567' }
+ end
+
+ it 'returns CiRunnerTokenAuthor with expected attributes' do
+ is_expected.to have_attributes(id: -1, name: 'Authentication token: abc1234567')
+ end
+ end
+
+ context 'with runner_registration_token' do
+ let(:details) do
+ { runner_registration_token: 'abc1234567' }
+ end
+
+ it 'returns CiRunnerTokenAuthor with expected attributes' do
+ is_expected.to have_attributes(id: -1, name: 'Registration token: abc1234567')
+ end
+ end
+
+ context 'with runner token missing' do
+ let(:details) do
+ {}
+ end
+
+ it 'raises ArgumentError' do
+ expect { subject }.to raise_error ArgumentError, 'Runner token missing'
+ end
+ end
+ end
+
+ describe '#full_path' do
+ subject { author.full_path }
+
+ let(:author) { described_class.new(audit_event) }
+
+ context 'with instance registration token' do
+ let(:audit_event) { instance_double(AuditEvent, details: { runner_registration_token: 'abc1234567' }, entity_type: 'User', entity_path: nil) }
+
+ it 'returns correct url' do
+ is_expected.to eq('/admin/runners')
+ end
+ end
+
+ context 'with group registration token' do
+ let(:audit_event) { instance_double(AuditEvent, details: { runner_registration_token: 'abc1234567' }, entity_type: 'Group', entity_path: 'a/b') }
+
+ it 'returns correct url' do
+ expect(::Gitlab::Routing.url_helpers).to receive(:group_settings_ci_cd_path)
+ .once
+ .with('a/b', { anchor: 'js-runners-settings' })
+ .and_return('/path/to/group/runners')
+
+ is_expected.to eq('/path/to/group/runners')
+ end
+ end
+
+ context 'with project registration token' do
+ let(:audit_event) { instance_double(AuditEvent, details: { runner_registration_token: 'abc1234567' }, entity_type: 'Project', entity_path: project.full_path) }
+ let(:project) { create(:project) }
+
+ it 'returns correct url' do
+ expect(::Gitlab::Routing.url_helpers).to receive(:project_settings_ci_cd_path)
+ .once
+ .with(project, { anchor: 'js-runners-settings' })
+ .and_return('/path/to/project/runners')
+
+ is_expected.to eq('/path/to/project/runners')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/audit/null_author_spec.rb b/spec/lib/gitlab/audit/null_author_spec.rb
index eb80e5faa89..7203a0cd816 100644
--- a/spec/lib/gitlab/audit/null_author_spec.rb
+++ b/spec/lib/gitlab/audit/null_author_spec.rb
@@ -6,13 +6,47 @@ RSpec.describe Gitlab::Audit::NullAuthor do
subject { described_class }
describe '.for' do
+ let(:audit_event) { instance_double(AuditEvent) }
+
it 'returns an DeletedAuthor' do
- expect(subject.for(666, 'Old Hat')).to be_a(Gitlab::Audit::DeletedAuthor)
+ allow(audit_event).to receive(:[]).with(:author_name).and_return('Old Hat')
+ allow(audit_event).to receive(:details).and_return({})
+ allow(audit_event).to receive(:target_type)
+
+ expect(subject.for(666, audit_event)).to be_a(Gitlab::Audit::DeletedAuthor)
end
it 'returns an UnauthenticatedAuthor when id equals -1', :aggregate_failures do
- expect(subject.for(-1, 'Frank')).to be_a(Gitlab::Audit::UnauthenticatedAuthor)
- expect(subject.for(-1, 'Frank')).to have_attributes(id: -1, name: 'Frank')
+ allow(audit_event).to receive(:[]).with(:author_name).and_return('Frank')
+ allow(audit_event).to receive(:details).and_return({})
+ allow(audit_event).to receive(:target_type)
+
+ expect(subject.for(-1, audit_event)).to be_a(Gitlab::Audit::UnauthenticatedAuthor)
+ expect(subject.for(-1, audit_event)).to have_attributes(id: -1, name: 'Frank')
+ end
+
+ it 'returns a CiRunnerTokenAuthor when details contain runner registration token', :aggregate_failures do
+ allow(audit_event).to receive(:[]).with(:author_name).and_return('cde456')
+ allow(audit_event).to receive(:entity_type).and_return('User')
+ allow(audit_event).to receive(:entity_path).and_return('/a/b')
+ allow(audit_event).to receive(:target_type).and_return(::Ci::Runner.name)
+ allow(audit_event).to receive(:details)
+ .and_return({ runner_registration_token: 'cde456', author_name: 'cde456', entity_type: 'User', entity_path: '/a/b' })
+
+ expect(subject.for(-1, audit_event)).to be_a(Gitlab::Audit::CiRunnerTokenAuthor)
+ expect(subject.for(-1, audit_event)).to have_attributes(id: -1, name: 'Registration token: cde456')
+ end
+
+ it 'returns a CiRunnerTokenAuthor when details contain runner authentication token', :aggregate_failures do
+ allow(audit_event).to receive(:[]).with(:author_name).and_return('cde456')
+ allow(audit_event).to receive(:entity_type).and_return('User')
+ allow(audit_event).to receive(:entity_path).and_return('/a/b')
+ allow(audit_event).to receive(:target_type).and_return(::Ci::Runner.name)
+ allow(audit_event).to receive(:details)
+ .and_return({ runner_authentication_token: 'cde456', author_name: 'cde456', entity_type: 'User', entity_path: '/a/b' })
+
+ expect(subject.for(-1, audit_event)).to be_a(Gitlab::Audit::CiRunnerTokenAuthor)
+ expect(subject.for(-1, audit_event)).to have_attributes(id: -1, name: 'Authentication token: cde456')
end
end
diff --git a/spec/lib/gitlab/auth/ldap/user_spec.rb b/spec/lib/gitlab/auth/ldap/user_spec.rb
index e910ac09448..da0bb5fe675 100644
--- a/spec/lib/gitlab/auth/ldap/user_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/user_spec.rb
@@ -53,12 +53,12 @@ RSpec.describe Gitlab::Auth::Ldap::User do
it "finds the user if already existing" do
create(:omniauth_user, extern_uid: 'uid=john smith,ou=people,dc=example,dc=com', provider: 'ldapmain')
- expect { ldap_user.save }.not_to change { User.count }
+ expect { ldap_user.save }.not_to change { User.count } # rubocop:disable Rails/SaveBang
end
it "connects to existing non-ldap user if the email matches" do
existing_user = create(:omniauth_user, email: 'john@example.com', provider: "twitter")
- expect { ldap_user.save }.not_to change { User.count }
+ expect { ldap_user.save }.not_to change { User.count } # rubocop:disable Rails/SaveBang
existing_user.reload
expect(existing_user.ldap_identity.extern_uid).to eql 'uid=john smith,ou=people,dc=example,dc=com'
@@ -67,7 +67,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
it 'connects to existing ldap user if the extern_uid changes' do
existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain')
- expect { ldap_user.save }.not_to change { User.count }
+ expect { ldap_user.save }.not_to change { User.count } # rubocop:disable Rails/SaveBang
existing_user.reload
expect(existing_user.ldap_identity.extern_uid).to eql 'uid=john smith,ou=people,dc=example,dc=com'
@@ -77,7 +77,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
it 'connects to existing ldap user if the extern_uid changes and email address has upper case characters' do
existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain')
- expect { ldap_user_upper_case.save }.not_to change { User.count }
+ expect { ldap_user_upper_case.save }.not_to change { User.count } # rubocop:disable Rails/SaveBang
existing_user.reload
expect(existing_user.ldap_identity.extern_uid).to eql 'uid=john smith,ou=people,dc=example,dc=com'
@@ -89,7 +89,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
existing_user = create(:omniauth_user, email: 'john@example.com', provider: 'twitter')
expect(existing_user.identities.count).to be(1)
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(ldap_user.gl_user.identities.count).to be(2)
# Expect that find_by provider only returns a single instance of an identity and not an Enumerable
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it "creates a new user if not found" do
- expect { ldap_user.save }.to change { User.count }.by(1)
+ expect { ldap_user.save }.to change { User.count }.by(1) # rubocop:disable Rails/SaveBang
end
context 'when signup is disabled' do
@@ -107,7 +107,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it 'creates the user' do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -119,7 +119,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it 'creates and confirms the user anyway' do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
expect(gl_user).to be_confirmed
@@ -132,7 +132,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it 'creates the user' do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -189,7 +189,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -201,7 +201,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).to be_blocked
end
@@ -210,7 +210,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
context 'sign-in' do
before do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
ldap_user.gl_user.activate
end
@@ -220,7 +220,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -232,7 +232,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
it do
- ldap_user.save
+ ldap_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index 7a8e6e77d52..8d36507ec7a 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
create(:omniauth_user, extern_uid: 'my-uid', provider: provider)
stub_omniauth_config(allow_single_sign_on: [provider], external_providers: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_falsey
@@ -83,7 +83,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'creates the user' do
stub_omniauth_config(allow_single_sign_on: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -97,7 +97,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'creates and confirms the user anyway' do
stub_omniauth_config(allow_single_sign_on: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
expect(gl_user).to be_confirmed
@@ -112,7 +112,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'creates the user' do
stub_omniauth_config(allow_single_sign_on: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -121,7 +121,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'marks user as having password_automatically_set' do
stub_omniauth_config(allow_single_sign_on: [provider], external_providers: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
expect(gl_user).to be_password_automatically_set
@@ -131,7 +131,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'provider is marked as external' do
it 'marks user as external' do
stub_omniauth_config(allow_single_sign_on: [provider], external_providers: [provider])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_truthy
end
@@ -141,7 +141,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'does not mark external user as internal' do
create(:omniauth_user, extern_uid: 'my-uid', provider: provider, external: true)
stub_omniauth_config(allow_single_sign_on: [provider], external_providers: ['facebook'])
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_truthy
end
@@ -151,9 +151,9 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'when adding a new OAuth identity' do
it 'does not promote an external user to internal' do
user = create(:user, email: 'john@mail.com', external: true)
- user.identities.create(provider: provider, extern_uid: uid)
+ user.identities.create!(provider: provider, extern_uid: uid)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_truthy
end
@@ -166,7 +166,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it "creates a user from Omniauth" do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
identity = gl_user.identities.first
@@ -181,7 +181,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it "creates a user from Omniauth" do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
identity = gl_user.identities.first
@@ -196,7 +196,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it 'throws an error' do
- expect { oauth_user.save }.to raise_error StandardError
+ expect { oauth_user.save }.to raise_error StandardError # rubocop:disable Rails/SaveBang
end
end
@@ -206,7 +206,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it 'throws an error' do
- expect { oauth_user.save }.to raise_error StandardError
+ expect { oauth_user.save }.to raise_error StandardError # rubocop:disable Rails/SaveBang
end
end
end
@@ -228,7 +228,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
it "adds the OmniAuth identity to the GitLab user account" do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).not_to be_valid
end
@@ -248,7 +248,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
it "adds the OmniAuth identity to the GitLab user account" do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -277,7 +277,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
it "adds the OmniAuth identity to the GitLab user account" do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -337,7 +337,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
before do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
end
it "creates a user with dual LDAP and omniauth identities" do
@@ -376,7 +376,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_email).with(uid, any_args).and_return(nil)
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_email).with(info_hash[:email], any_args).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
end
it 'creates the LDAP identity' do
@@ -392,7 +392,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it "adds the omniauth identity to the LDAP account" do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -414,7 +414,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(nil)
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_email).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array(result_identities(dn, uid))
@@ -426,7 +426,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_email).and_return(nil)
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_dn).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array(result_identities(dn, uid))
@@ -447,7 +447,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it 'does not save the identity' do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array([{ provider: 'twitter', extern_uid: uid }])
@@ -467,7 +467,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it 'creates a user favoring the LDAP username and strips email domain' do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'johndoe'
@@ -510,7 +510,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
before do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
end
it "creates a user with dual LDAP and omniauth identities" do
@@ -549,7 +549,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
it "adds the omniauth identity to the LDAP account" do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -584,7 +584,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -596,7 +596,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).to be_blocked
end
@@ -622,7 +622,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -636,7 +636,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).to be_blocked
end
@@ -654,7 +654,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -668,7 +668,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -678,7 +678,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'sign-in' do
before do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
oauth_user.gl_user.activate
end
@@ -688,7 +688,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -700,7 +700,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -714,7 +714,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -728,7 +728,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end
it do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -791,7 +791,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'when collision with existing user' do
it 'generates the username with a counter' do
- oauth_user.save
+ oauth_user.save # rubocop:disable Rails/SaveBang
oauth_user2 = described_class.new(OmniAuth::AuthHash.new(uid: 'my-uid2', provider: provider, info: { nickname: 'johngitlab-ETC@othermail.com', email: 'john@othermail.com' }))
expect(oauth_user2.gl_user.username).to eq('johngitlab-ETC1')
diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb
index 6f3d6187076..5e9d07a8bf7 100644
--- a/spec/lib/gitlab/auth/request_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb
@@ -21,8 +21,10 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
let_it_be(:session_user) { build(:user) }
it 'returns sessionless user first' do
- allow_any_instance_of(described_class).to receive(:find_sessionless_user).and_return(sessionless_user)
- allow_any_instance_of(described_class).to receive(:find_user_from_warden).and_return(session_user)
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:find_sessionless_user).and_return(sessionless_user)
+ allow(instance).to receive(:find_user_from_warden).and_return(session_user)
+ end
expect(subject.user([:api])).to eq sessionless_user
end
diff --git a/spec/lib/gitlab/auth/saml/user_spec.rb b/spec/lib/gitlab/auth/saml/user_spec.rb
index fd48492f18d..796512bc52b 100644
--- a/spec/lib/gitlab/auth/saml/user_spec.rb
+++ b/spec/lib/gitlab/auth/saml/user_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'and should bind with SAML' do
it 'adds the SAML identity to the existing user' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).to eq existing_user
identity = gl_user.identities.first
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'are defined' do
it 'marks the user as external' do
stub_saml_group_config(%w(Freelancers))
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_truthy
end
@@ -61,7 +61,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'are defined but the user does not belong there' do
it 'does not mark the user as external' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_falsey
end
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'user was external, now should not be' do
it 'makes user internal' do
existing_user.update_attribute('external', true)
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_falsey
end
@@ -86,7 +86,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'creates a user from SAML' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
identity = gl_user.identities.first
@@ -101,7 +101,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'does not throw an error' do
- expect { saml_user.save }.not_to raise_error
+ expect { saml_user.save }.not_to raise_error # rubocop:disable Rails/SaveBang
end
end
@@ -111,7 +111,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'throws an error' do
- expect { saml_user.save }.to raise_error StandardError
+ expect { saml_user.save }.to raise_error StandardError # rubocop:disable Rails/SaveBang
end
end
end
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'are defined' do
it 'marks the user as external' do
stub_saml_group_config(%w(Freelancers))
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_truthy
end
@@ -129,7 +129,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'are defined but the user does not belong there' do
it 'does not mark the user as external' do
stub_saml_group_config(%w(Interns))
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.external).to be_falsey
end
@@ -170,7 +170,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'and no account for the LDAP user' do
it 'creates a user with dual LDAP and SAML identities' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql uid
@@ -230,7 +230,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
{ provider: id.provider, extern_uid: id.extern_uid }
end
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -259,7 +259,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'adds the omniauth identity to the LDAP account' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
@@ -271,9 +271,9 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'saves successfully on subsequent tries, when both identities are present' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
local_saml_user = described_class.new(auth_hash)
- local_saml_user.save
+ local_saml_user.save # rubocop:disable Rails/SaveBang
expect(local_saml_user.gl_user).to be_valid
expect(local_saml_user.gl_user).to be_persisted
@@ -289,7 +289,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
local_hash = OmniAuth::AuthHash.new(uid: dn, provider: provider, info: info_hash)
local_saml_user = described_class.new(local_hash)
- local_saml_user.save
+ local_saml_user.save # rubocop:disable Rails/SaveBang
local_gl_user = local_saml_user.gl_user
expect(local_gl_user).to be_valid
@@ -309,7 +309,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'creates the user' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -321,7 +321,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'creates and confirms the user anyway' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
expect(gl_user).to be_confirmed
@@ -334,7 +334,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'creates the user' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_persisted
end
@@ -353,7 +353,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'does not block the user' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -365,7 +365,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it 'blocks user' do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).to be_blocked
end
@@ -374,7 +374,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
context 'sign-in' do
before do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
saml_user.gl_user.activate
end
@@ -384,7 +384,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
@@ -396,7 +396,7 @@ RSpec.describe Gitlab::Auth::Saml::User do
end
it do
- saml_user.save
+ saml_user.save # rubocop:disable Rails/SaveBang
expect(gl_user).to be_valid
expect(gl_user).not_to be_blocked
end
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 611c70d73a1..706344831b8 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -10,29 +10,29 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
describe 'constants' do
it 'API_SCOPES contains all scopes for API access' do
- expect(subject::API_SCOPES).to eq %i[api read_user read_api]
+ expect(subject::API_SCOPES).to match_array %i[api read_user read_api]
end
it 'ADMIN_SCOPES contains all scopes for ADMIN access' do
- expect(subject::ADMIN_SCOPES).to eq %i[sudo]
+ expect(subject::ADMIN_SCOPES).to match_array %i[sudo]
end
it 'REPOSITORY_SCOPES contains all scopes for REPOSITORY access' do
- expect(subject::REPOSITORY_SCOPES).to eq %i[read_repository write_repository]
+ expect(subject::REPOSITORY_SCOPES).to match_array %i[read_repository write_repository]
end
it 'OPENID_SCOPES contains all scopes for OpenID Connect' do
- expect(subject::OPENID_SCOPES).to eq [:openid]
+ expect(subject::OPENID_SCOPES).to match_array [:openid]
end
it 'DEFAULT_SCOPES contains all default scopes' do
- expect(subject::DEFAULT_SCOPES).to eq [:api]
+ expect(subject::DEFAULT_SCOPES).to match_array [:api]
end
it 'optional_scopes contains all non-default scopes' do
stub_container_registry_config(enabled: true)
- expect(subject.optional_scopes).to eq %i[read_user read_api read_repository write_repository read_registry write_registry sudo openid profile email]
+ expect(subject.optional_scopes).to match_array %i[read_user read_api read_repository write_repository read_registry write_registry sudo openid profile email]
end
end
@@ -40,21 +40,21 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'contains all non-default scopes' do
stub_container_registry_config(enabled: true)
- expect(subject.all_available_scopes).to eq %i[api read_user read_api read_repository write_repository read_registry write_registry sudo]
+ expect(subject.all_available_scopes).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo]
end
it 'contains for non-admin user all non-default scopes without ADMIN access' do
stub_container_registry_config(enabled: true)
user = create(:user, admin: false)
- expect(subject.available_scopes_for(user)).to eq %i[api read_user read_api read_repository write_repository read_registry write_registry]
+ expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry]
end
it 'contains for admin user all non-default scopes with ADMIN access' do
stub_container_registry_config(enabled: true)
user = create(:user, admin: true)
- expect(subject.available_scopes_for(user)).to eq %i[api read_user read_api read_repository write_repository read_registry write_registry sudo]
+ expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry sudo]
end
context 'registry_scopes' do
@@ -156,21 +156,36 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
let(:username) { 'gitlab-ci-token' }
context 'for running build' do
- let!(:build) { create(:ci_build, :running) }
- let(:project) { build.project }
+ let!(:group) { create(:group) }
+ let!(:project) { create(:project, group: group) }
+ let!(:build) { create(:ci_build, :running, project: project) }
it 'recognises user-less build' do
expect(subject).to have_attributes(actor: nil, project: build.project, type: :ci, authentication_abilities: described_class.build_authentication_abilities)
end
it 'recognises user token' do
- build.update(user: create(:user))
+ build.update!(user: create(:user))
+
+ expect(subject).to have_attributes(actor: build.user, project: build.project, type: :build, authentication_abilities: described_class.build_authentication_abilities)
+ end
+
+ it 'recognises project level bot access token' do
+ build.update!(user: create(:user, :project_bot))
+ project.add_maintainer(build.user)
+
+ expect(subject).to have_attributes(actor: build.user, project: build.project, type: :build, authentication_abilities: described_class.build_authentication_abilities)
+ end
+
+ it 'recognises group level bot access token' do
+ build.update!(user: create(:user, :project_bot))
+ group.add_maintainer(build.user)
expect(subject).to have_attributes(actor: build.user, project: build.project, type: :build, authentication_abilities: described_class.build_authentication_abilities)
end
it 'fails with blocked user token' do
- build.update(user: create(:user, :blocked))
+ build.update!(user: create(:user, :blocked))
expect(subject).to have_attributes(auth_failure)
end
@@ -198,7 +213,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'recognizes other ci services' do
project.create_drone_ci_integration(active: true)
- project.drone_ci_integration.update(token: 'token')
+ project.drone_ci_integration.update!(token: 'token', drone_url: generate(:url))
expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: 'ip')).to have_attributes(actor: nil, project: project, type: :ci, authentication_abilities: described_class.build_authentication_abilities)
end
@@ -311,7 +326,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'orphaned token' do
before do
- user.destroy
+ user.destroy!
end
it_behaves_like 'an oauth failure'
@@ -888,7 +903,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'resets failed_attempts when true and password is correct' do
user.failed_attempts = 2
- user.save
+ user.save!
expect do
gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
@@ -917,7 +932,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'does not reset failed_attempts when true and password is correct' do
user.failed_attempts = 2
- user.save
+ user.save!
expect do
gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
diff --git a/spec/lib/gitlab/authorized_keys_spec.rb b/spec/lib/gitlab/authorized_keys_spec.rb
index 1053ae2e325..073cee96ede 100644
--- a/spec/lib/gitlab/authorized_keys_spec.rb
+++ b/spec/lib/gitlab/authorized_keys_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::AuthorizedKeys do
end
describe '#create' do
- subject { authorized_keys.create }
+ subject { authorized_keys.create } # rubocop:disable Rails/SaveBang
context 'authorized_keys file exists' do
before do
diff --git a/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb
new file mode 100644
index 00000000000..1aac5970a77
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb
@@ -0,0 +1,244 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillCiQueuingTables, :migration, schema: 20220208115439 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:ci_cd_settings) { table(:project_ci_cd_settings) }
+ let(:builds) { table(:ci_builds) }
+ let(:queuing_entries) { table(:ci_pending_builds) }
+ let(:tags) { table(:tags) }
+ let(:taggings) { table(:taggings) }
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ let!(:namespace) do
+ namespaces.create!(
+ id: 10,
+ name: 'namespace10',
+ path: 'namespace10',
+ traversal_ids: [10])
+ end
+
+ let!(:other_namespace) do
+ namespaces.create!(
+ id: 11,
+ name: 'namespace11',
+ path: 'namespace11',
+ traversal_ids: [11])
+ end
+
+ let!(:project) do
+ projects.create!(id: 5, namespace_id: 10, name: 'test1', path: 'test1')
+ end
+
+ let!(:ci_cd_setting) do
+ ci_cd_settings.create!(id: 5, project_id: 5, group_runners_enabled: true)
+ end
+
+ let!(:other_project) do
+ projects.create!(id: 7, namespace_id: 11, name: 'test2', path: 'test2')
+ end
+
+ let!(:other_ci_cd_setting) do
+ ci_cd_settings.create!(id: 7, project_id: 7, group_runners_enabled: false)
+ end
+
+ let!(:another_project) do
+ projects.create!(id: 9, namespace_id: 10, name: 'test3', path: 'test3', shared_runners_enabled: false)
+ end
+
+ let!(:ruby_tag) do
+ tags.create!(id: 22, name: 'ruby')
+ end
+
+ let!(:postgres_tag) do
+ tags.create!(id: 23, name: 'postgres')
+ end
+
+ it 'creates ci_pending_builds for all pending builds in range' do
+ builds.create!(id: 50, status: :pending, name: 'test1', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 51, status: :created, name: 'test2', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 52, status: :pending, name: 'test3', project_id: 5, protected: true, type: 'Ci::Build')
+
+ taggings.create!(taggable_id: 52, taggable_type: 'CommitStatus', tag_id: 22)
+ taggings.create!(taggable_id: 52, taggable_type: 'CommitStatus', tag_id: 23)
+
+ builds.create!(id: 60, status: :pending, name: 'test1', project_id: 7, type: 'Ci::Build')
+ builds.create!(id: 61, status: :running, name: 'test2', project_id: 7, protected: true, type: 'Ci::Build')
+ builds.create!(id: 62, status: :pending, name: 'test3', project_id: 7, type: 'Ci::Build')
+
+ taggings.create!(taggable_id: 60, taggable_type: 'CommitStatus', tag_id: 23)
+ taggings.create!(taggable_id: 62, taggable_type: 'CommitStatus', tag_id: 22)
+
+ builds.create!(id: 70, status: :pending, name: 'test1', project_id: 9, protected: true, type: 'Ci::Build')
+ builds.create!(id: 71, status: :failed, name: 'test2', project_id: 9, type: 'Ci::Build')
+ builds.create!(id: 72, status: :pending, name: 'test3', project_id: 9, type: 'Ci::Build')
+
+ taggings.create!(taggable_id: 71, taggable_type: 'CommitStatus', tag_id: 22)
+
+ subject.perform(1, 100)
+
+ expect(queuing_entries.all).to contain_exactly(
+ an_object_having_attributes(
+ build_id: 50,
+ project_id: 5,
+ namespace_id: 10,
+ protected: false,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: [],
+ namespace_traversal_ids: [10]),
+ an_object_having_attributes(
+ build_id: 52,
+ project_id: 5,
+ namespace_id: 10,
+ protected: true,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: match_array([22, 23]),
+ namespace_traversal_ids: [10]),
+ an_object_having_attributes(
+ build_id: 60,
+ project_id: 7,
+ namespace_id: 11,
+ protected: false,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: [23],
+ namespace_traversal_ids: []),
+ an_object_having_attributes(
+ build_id: 62,
+ project_id: 7,
+ namespace_id: 11,
+ protected: false,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: [22],
+ namespace_traversal_ids: []),
+ an_object_having_attributes(
+ build_id: 70,
+ project_id: 9,
+ namespace_id: 10,
+ protected: true,
+ instance_runners_enabled: false,
+ minutes_exceeded: false,
+ tag_ids: [],
+ namespace_traversal_ids: []),
+ an_object_having_attributes(
+ build_id: 72,
+ project_id: 9,
+ namespace_id: 10,
+ protected: false,
+ instance_runners_enabled: false,
+ minutes_exceeded: false,
+ tag_ids: [],
+ namespace_traversal_ids: [])
+ )
+ end
+
+ it 'skips builds that already have ci_pending_builds' do
+ builds.create!(id: 50, status: :pending, name: 'test1', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 51, status: :created, name: 'test2', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 52, status: :pending, name: 'test3', project_id: 5, protected: true, type: 'Ci::Build')
+
+ taggings.create!(taggable_id: 50, taggable_type: 'CommitStatus', tag_id: 22)
+ taggings.create!(taggable_id: 52, taggable_type: 'CommitStatus', tag_id: 23)
+
+ queuing_entries.create!(build_id: 50, project_id: 5, namespace_id: 10)
+
+ subject.perform(1, 100)
+
+ expect(queuing_entries.all).to contain_exactly(
+ an_object_having_attributes(
+ build_id: 50,
+ project_id: 5,
+ namespace_id: 10,
+ protected: false,
+ instance_runners_enabled: false,
+ minutes_exceeded: false,
+ tag_ids: [],
+ namespace_traversal_ids: []),
+ an_object_having_attributes(
+ build_id: 52,
+ project_id: 5,
+ namespace_id: 10,
+ protected: true,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: [23],
+ namespace_traversal_ids: [10])
+ )
+ end
+
+ it 'upserts values in case of conflicts' do
+ builds.create!(id: 50, status: :pending, name: 'test1', project_id: 5, type: 'Ci::Build')
+ queuing_entries.create!(build_id: 50, project_id: 5, namespace_id: 10)
+
+ build = described_class::Ci::Build.find(50)
+ described_class::Ci::PendingBuild.upsert_from_build!(build)
+
+ expect(queuing_entries.all).to contain_exactly(
+ an_object_having_attributes(
+ build_id: 50,
+ project_id: 5,
+ namespace_id: 10,
+ protected: false,
+ instance_runners_enabled: true,
+ minutes_exceeded: false,
+ tag_ids: [],
+ namespace_traversal_ids: [10])
+ )
+ end
+ end
+
+ context 'Ci::Build' do
+ describe '.each_batch' do
+ let(:model) { described_class::Ci::Build }
+
+ before do
+ builds.create!(id: 1, status: :pending, name: 'test1', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 2, status: :pending, name: 'test2', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 3, status: :pending, name: 'test3', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 4, status: :pending, name: 'test4', project_id: 5, type: 'Ci::Build')
+ builds.create!(id: 5, status: :pending, name: 'test5', project_id: 5, type: 'Ci::Build')
+ end
+
+ it 'yields an ActiveRecord::Relation when a block is given' do
+ model.each_batch do |relation|
+ expect(relation).to be_a_kind_of(ActiveRecord::Relation)
+ end
+ end
+
+ it 'yields a batch index as the second argument' do
+ model.each_batch do |_, index|
+ expect(index).to eq(1)
+ end
+ end
+
+ it 'accepts a custom batch size' do
+ amount = 0
+
+ model.each_batch(of: 1) { amount += 1 }
+
+ expect(amount).to eq(5)
+ end
+
+ it 'does not include ORDER BYs in the yielded relations' do
+ model.each_batch do |relation|
+ expect(relation.to_sql).not_to include('ORDER BY')
+ end
+ end
+
+ it 'orders ascending' do
+ ids = []
+
+ model.each_batch(of: 1) { |rel| ids.concat(rel.ids) }
+
+ expect(ids).to eq(ids.sort)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
deleted file mode 100644
index c4013d002b2..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories do
- it_behaves_like 'backfill migration for project repositories', :legacy
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb
new file mode 100644
index 00000000000..b821efcadb0
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdForNamespaceRoute, :migration, schema: 20220120123800 do
+ let(:migration) { described_class.new }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:routes_table) { table(:routes) }
+
+ let(:table_name) { 'routes' }
+ let(:batch_column) { :id }
+ let(:sub_batch_size) { 200 }
+ let(:pause_ms) { 0 }
+
+ let(:namespace1) { namespaces_table.create!(name: 'namespace1', path: 'namespace1', type: 'User') }
+ let(:namespace2) { namespaces_table.create!(name: 'namespace2', path: 'namespace2', type: 'Group') }
+ let(:namespace3) { namespaces_table.create!(name: 'namespace3', path: 'namespace3', type: 'Group') }
+ let(:namespace4) { namespaces_table.create!(name: 'namespace4', path: 'namespace4', type: 'Group') }
+ let(:project1) { projects_table.create!(name: 'project1', namespace_id: namespace1.id) }
+
+ subject(:perform_migration) { migration.perform(1, 10, table_name, batch_column, sub_batch_size, pause_ms) }
+
+ before do
+ routes_table.create!(id: 1, name: 'test1', path: 'test1', source_id: namespace1.id,
+ source_type: namespace1.class.sti_name)
+ routes_table.create!(id: 2, name: 'test2', path: 'test2', source_id: namespace2.id,
+ source_type: namespace2.class.sti_name)
+ routes_table.create!(id: 5, name: 'test3', path: 'test3', source_id: project1.id,
+ source_type: project1.class.sti_name) # should be ignored - project route
+ routes_table.create!(id: 6, name: 'test4', path: 'test4', source_id: non_existing_record_id,
+ source_type: namespace3.class.sti_name) # should be ignored - invalid source_id
+ routes_table.create!(id: 10, name: 'test5', path: 'test5', source_id: namespace3.id,
+ source_type: namespace3.class.sti_name)
+ routes_table.create!(id: 11, name: 'test6', path: 'test6', source_id: namespace4.id,
+ source_type: namespace4.class.sti_name) # should be ignored - outside the scope
+ end
+
+ it 'backfills `type` for the selected records', :aggregate_failures do
+ perform_migration
+
+ expect(routes_table.where.not(namespace_id: nil).pluck(:id)).to match_array([1, 2, 10])
+ end
+
+ it 'tracks timings of queries' do
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { perform_migration }.to change { migration.batch_metrics.timings }
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb
deleted file mode 100644
index ed44b819a97..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectUpdatedAtAfterRepositoryStorageMove, :migration, schema: 20210301200959 do
- let(:projects) { table(:projects) }
- let(:project_repository_storage_moves) { table(:project_repository_storage_moves) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'updates project updated_at column if they were moved to a different repository storage' do
- freeze_time do
- project_1 = projects.create!(id: 1, namespace_id: namespace.id, updated_at: 1.day.ago)
- project_2 = projects.create!(id: 2, namespace_id: namespace.id, updated_at: Time.current)
- original_project_3_updated_at = 2.minutes.from_now
- project_3 = projects.create!(id: 3, namespace_id: namespace.id, updated_at: original_project_3_updated_at)
- original_project_4_updated_at = 10.days.ago
- project_4 = projects.create!(id: 4, namespace_id: namespace.id, updated_at: original_project_4_updated_at)
-
- repository_storage_move_1 = project_repository_storage_moves.create!(project_id: project_1.id, updated_at: 2.hours.ago, source_storage_name: 'default', destination_storage_name: 'default')
- repository_storage_move_2 = project_repository_storage_moves.create!(project_id: project_2.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default')
- project_repository_storage_moves.create!(project_id: project_3.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default')
-
- subject.perform([1, 2, 3, 4, non_existing_record_id])
-
- expect(project_1.reload.updated_at).to eq(repository_storage_move_1.updated_at + 1.second)
- expect(project_2.reload.updated_at).to eq(repository_storage_move_2.updated_at + 1.second)
- expect(project_3.reload.updated_at).to eq(original_project_3_updated_at)
- expect(project_4.reload.updated_at).to eq(original_project_4_updated_at)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb
new file mode 100644
index 00000000000..7b8a466b37c
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillProjectNamespacePerGroupBatchingStrategy, '#next_batch' do
+ let!(:namespaces) { table(:namespaces) }
+ let!(:projects) { table(:projects) }
+ let!(:background_migrations) { table(:batched_background_migrations) }
+
+ let!(:namespace1) { namespaces.create!(name: 'batchtest1', type: 'Group', path: 'batch-test1') }
+ let!(:namespace2) { namespaces.create!(name: 'batchtest2', type: 'Group', parent_id: namespace1.id, path: 'batch-test2') }
+ let!(:namespace3) { namespaces.create!(name: 'batchtest3', type: 'Group', parent_id: namespace2.id, path: 'batch-test3') }
+
+ let!(:project1) { projects.create!(name: 'project1', path: 'project1', namespace_id: namespace1.id, visibility_level: 20) }
+ let!(:project2) { projects.create!(name: 'project2', path: 'project2', namespace_id: namespace2.id, visibility_level: 20) }
+ let!(:project3) { projects.create!(name: 'project3', path: 'project3', namespace_id: namespace3.id, visibility_level: 20) }
+ let!(:project4) { projects.create!(name: 'project4', path: 'project4', namespace_id: namespace3.id, visibility_level: 20) }
+ let!(:batching_strategy) { described_class.new }
+
+ let(:job_arguments) { [namespace1.id, 'up'] }
+
+ context 'when starting on the first batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = batching_strategy.next_batch(:projects, :id, batch_min_value: project1.id, batch_size: 3, job_arguments: job_arguments)
+
+ expect(batch_bounds).to match_array([project1.id, project3.id])
+ end
+ end
+
+ context 'when additional batches remain' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = batching_strategy.next_batch(:projects, :id, batch_min_value: project2.id, batch_size: 3, job_arguments: job_arguments)
+
+ expect(batch_bounds).to match_array([project2.id, project4.id])
+ end
+ end
+
+ context 'when on the final batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = batching_strategy.next_batch(:projects, :id, batch_min_value: project4.id, batch_size: 3, job_arguments: job_arguments)
+
+ expect(batch_bounds).to match_array([project4.id, project4.id])
+ end
+ end
+
+ context 'when no additional batches remain' do
+ it 'returns nil' do
+ batch_bounds = batching_strategy.next_batch(:projects, :id, batch_min_value: project4.id + 1, batch_size: 1, job_arguments: job_arguments)
+
+ expect(batch_bounds).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
index 8febe850e04..39030039125 100644
--- a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
+++ b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when starting on the first batch' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3, job_arguments: nil)
expect(batch_bounds).to eq([namespace1.id, namespace3.id])
end
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when additional batches remain' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3, job_arguments: nil)
expect(batch_bounds).to eq([namespace2.id, namespace4.id])
end
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when on the final batch' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3, job_arguments: nil)
expect(batch_bounds).to eq([namespace4.id, namespace4.id])
end
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when no additional batches remain' do
it 'returns nil' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1, job_arguments: nil)
expect(batch_bounds).to be_nil
end
diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
index d4fc24d0559..90d9bbb42c3 100644
--- a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
+++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
@@ -7,13 +7,14 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
let(:test_table) { table(table_name) }
let(:sub_batch_size) { 1000 }
let(:pause_ms) { 0 }
+ let(:connection) { ApplicationRecord.connection }
let(:helpers) do
ActiveRecord::Migration.new.extend(Gitlab::Database::MigrationHelpers)
end
before do
- ActiveRecord::Base.connection.execute(<<~SQL)
+ connection.execute(<<~SQL)
CREATE TABLE #{table_name}
(
id integer NOT NULL,
@@ -34,12 +35,14 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
after do
# Make sure that the temp table we created is dropped (it is not removed by the database_cleaner)
- ActiveRecord::Base.connection.execute(<<~SQL)
+ connection.execute(<<~SQL)
DROP TABLE IF EXISTS #{table_name};
SQL
end
- subject(:copy_columns) { described_class.new }
+ subject(:copy_columns) { described_class.new(connection: connection) }
+
+ it { expect(described_class).to be < Gitlab::BackgroundMigration::BaseJob }
describe '#perform' do
let(:migration_class) { described_class.name }
diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
deleted file mode 100644
index 68fe8f39f59..00000000000
--- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20210301200959 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:users) { table(:users) }
- let(:scanners) { table(:vulnerability_scanners) }
- let(:identifiers) { table(:vulnerability_identifiers) }
- let(:findings) { table(:vulnerability_occurrences) }
- let(:vulnerability_feedback) { table(:vulnerability_feedback) }
-
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
- let(:user) { users.create!(username: 'john.doe', projects_limit: 5) }
- let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
- let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'baz') }
- let(:sast_report) { 0 }
- let(:dependency_scanning_report) { 1 }
- let(:dast_report) { 3 }
- let(:secret_detection_report) { 4 }
- let(:project_fingerprint) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_1) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_2) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_3) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) }
- let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) }
- let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) }
- let(:expected_uuid_1) do
- Security::VulnerabilityUUID.generate(
- report_type: 'sast',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_1,
- project_id: project.id
- )
- end
-
- let(:expected_uuid_2) do
- Security::VulnerabilityUUID.generate(
- report_type: 'dast',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_2,
- project_id: project.id
- )
- end
-
- let(:expected_uuid_3) do
- Security::VulnerabilityUUID.generate(
- report_type: 'secret_detection',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_3,
- project_id: project.id
- )
- end
-
- let(:finding_creator) do
- -> (report_type, location_fingerprint) do
- findings.create!(
- project_id: project.id,
- primary_identifier_id: identifier.id,
- scanner_id: scanner.id,
- report_type: report_type,
- uuid: SecureRandom.uuid,
- name: 'Foo',
- location_fingerprint: Gitlab::Database::ShaAttribute.serialize(location_fingerprint),
- project_fingerprint: Gitlab::Database::ShaAttribute.serialize(project_fingerprint),
- metadata_version: '1',
- severity: 0,
- confidence: 5,
- raw_metadata: '{}'
- )
- end
- end
-
- let(:feedback_creator) do
- -> (category, project_fingerprint) do
- vulnerability_feedback.create!(
- project_id: project.id,
- author_id: user.id,
- feedback_type: 0,
- category: category,
- project_fingerprint: project_fingerprint
- )
- end
- end
-
- let!(:feedback_1) { feedback_creator.call(finding_1.report_type, project_fingerprint) }
- let!(:feedback_2) { feedback_creator.call(finding_2.report_type, project_fingerprint) }
- let!(:feedback_3) { feedback_creator.call(finding_3.report_type, project_fingerprint) }
- let!(:feedback_4) { feedback_creator.call(finding_1.report_type, 'foo') }
- let!(:feedback_5) { feedback_creator.call(dependency_scanning_report, project_fingerprint) }
-
- subject(:populate_finding_uuids) { described_class.new.perform(feedback_1.id, feedback_5.id) }
-
- before do
- allow(Gitlab::BackgroundMigration::Logger).to receive(:info)
- end
-
- describe '#perform' do
- it 'updates the `finding_uuid` attributes of the feedback records' do
- expect { populate_finding_uuids }.to change { feedback_1.reload.finding_uuid }.from(nil).to(expected_uuid_1)
- .and change { feedback_2.reload.finding_uuid }.from(nil).to(expected_uuid_2)
- .and change { feedback_3.reload.finding_uuid }.from(nil).to(expected_uuid_3)
- .and not_change { feedback_4.reload.finding_uuid }
- .and not_change { feedback_5.reload.finding_uuid }
-
- expect(Gitlab::BackgroundMigration::Logger).to have_received(:info).once
- end
-
- it 'preloads the finding and identifier records to prevent N+1 queries' do
- # Load feedback records(1), load findings(2), load identifiers(3) and finally update feedback records one by one(6)
- expect { populate_finding_uuids }.not_to exceed_query_limit(6)
- end
-
- context 'when setting the `finding_uuid` attribute of a feedback record fails' do
- let(:expected_error) { RuntimeError.new }
-
- before do
- allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
-
- allow_next_found_instance_of(described_class::VulnerabilityFeedback) do |feedback|
- allow(feedback).to receive(:update_column).and_raise(expected_error)
- end
- end
-
- it 'captures the errors and does not crash entirely' do
- expect { populate_finding_uuids }.not_to raise_error
-
- expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).exactly(3).times
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
deleted file mode 100644
index b00eb185b34..00000000000
--- a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20210301200959 do
- let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
- let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
- let!(:issue1) { table(:issues).create!(id: 1, project_id: project.id, service_desk_reply_to: "a@gitlab.com") }
- let!(:issue2) { table(:issues).create!(id: 2, project_id: project.id, service_desk_reply_to: "b@gitlab.com") }
- let(:issue_email_participants) { table(:issue_email_participants) }
-
- describe '#perform' do
- it 'migrates email addresses from service desk issues', :aggregate_failures do
- expect { subject.perform(1, 2) }.to change { issue_email_participants.count }.by(2)
-
- expect(issue_email_participants.find_by(issue_id: 1).email).to eq("a@gitlab.com")
- expect(issue_email_participants.find_by(issue_id: 2).email).to eq("b@gitlab.com")
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_topics_non_private_projects_count_spec.rb b/spec/lib/gitlab/background_migration/populate_topics_non_private_projects_count_spec.rb
new file mode 100644
index 00000000000..e72e3392210
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_topics_non_private_projects_count_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateTopicsNonPrivateProjectsCount, schema: 20220125122640 do
+ it 'correctly populates the non private projects counters' do
+ namespaces = table(:namespaces)
+ projects = table(:projects)
+ topics = table(:topics)
+ project_topics = table(:project_topics)
+
+ group = namespaces.create!(name: 'group', path: 'group')
+ project_public = projects.create!(namespace_id: group.id, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project_internal = projects.create!(namespace_id: group.id, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ project_private = projects.create!(namespace_id: group.id, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ topic_1 = topics.create!(name: 'Topic1')
+ topic_2 = topics.create!(name: 'Topic2')
+ topic_3 = topics.create!(name: 'Topic3')
+ topic_4 = topics.create!(name: 'Topic4')
+ topic_5 = topics.create!(name: 'Topic5')
+ topic_6 = topics.create!(name: 'Topic6')
+ topic_7 = topics.create!(name: 'Topic7')
+ topic_8 = topics.create!(name: 'Topic8')
+
+ project_topics.create!(topic_id: topic_1.id, project_id: project_public.id)
+ project_topics.create!(topic_id: topic_2.id, project_id: project_internal.id)
+ project_topics.create!(topic_id: topic_3.id, project_id: project_private.id)
+ project_topics.create!(topic_id: topic_4.id, project_id: project_public.id)
+ project_topics.create!(topic_id: topic_4.id, project_id: project_internal.id)
+ project_topics.create!(topic_id: topic_5.id, project_id: project_public.id)
+ project_topics.create!(topic_id: topic_5.id, project_id: project_private.id)
+ project_topics.create!(topic_id: topic_6.id, project_id: project_internal.id)
+ project_topics.create!(topic_id: topic_6.id, project_id: project_private.id)
+ project_topics.create!(topic_id: topic_7.id, project_id: project_public.id)
+ project_topics.create!(topic_id: topic_7.id, project_id: project_internal.id)
+ project_topics.create!(topic_id: topic_7.id, project_id: project_private.id)
+ project_topics.create!(topic_id: topic_8.id, project_id: project_public.id)
+
+ subject.perform(topic_1.id, topic_7.id)
+
+ expect(topic_1.reload.non_private_projects_count).to eq(1)
+ expect(topic_2.reload.non_private_projects_count).to eq(1)
+ expect(topic_3.reload.non_private_projects_count).to eq(0)
+ expect(topic_4.reload.non_private_projects_count).to eq(2)
+ expect(topic_5.reload.non_private_projects_count).to eq(1)
+ expect(topic_6.reload.non_private_projects_count).to eq(1)
+ expect(topic_7.reload.non_private_projects_count).to eq(2)
+ expect(topic_8.reload.non_private_projects_count).to eq(0)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb b/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb
new file mode 100644
index 00000000000..a265fa95b23
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateVulnerabilityReads do
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:user) { table(:users).create!(email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let(:sub_batch_size) { 1000 }
+
+ before do
+ vulnerabilities_findings.connection.execute 'ALTER TABLE vulnerability_occurrences DISABLE TRIGGER "trigger_insert_or_update_vulnerability_reads_from_occurrences"'
+ vulnerabilities.connection.execute 'ALTER TABLE vulnerabilities DISABLE TRIGGER "trigger_update_vulnerability_reads_on_vulnerability_update"'
+ vulnerability_issue_links.connection.execute 'ALTER TABLE vulnerability_issue_links DISABLE TRIGGER "trigger_update_has_issues_on_vulnerability_issue_links_update"'
+
+ 10.times.each do |x|
+ vulnerability = create_vulnerability!(
+ project_id: project.id,
+ report_type: 7,
+ author_id: user.id
+ )
+ identifier = table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: Digest::SHA1.hexdigest("#{vulnerability.id}"),
+ name: 'Identifier for UUIDv5')
+
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+ end
+ end
+
+ it 'creates vulnerability_reads for the given records' do
+ described_class.new.perform(vulnerabilities.first.id, vulnerabilities.last.id, sub_batch_size)
+
+ expect(vulnerability_reads.count).to eq(10)
+ end
+
+ it 'does not create new records when records already exists' do
+ described_class.new.perform(vulnerabilities.first.id, vulnerabilities.last.id, sub_batch_size)
+ described_class.new.perform(vulnerabilities.first.id, vulnerabilities.last.id, sub_batch_size)
+
+ expect(vulnerability_reads.count).to eq(10)
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id: nil, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" }, location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location: location,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
index 24259b06469..2c5de448fbc 100644
--- a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
+++ b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = ::Project.minimum(:id)
end_id = ::Project.maximum(:id)
projects_count = ::Project.count
- batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
project_namespaces_count = ::Namespace.where(type: 'Project').count
migration = described_class.new
@@ -39,7 +39,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
- expect { migration.perform(start_id, end_id, nil, 'up') }.to change(Namespace.where(type: 'Project'), :count)
+ expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(Namespace.where(type: 'Project'), :count)
expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
check_projects_in_sync_with(Namespace.where(type: 'Project'))
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = backfilled_namespace_projects.minimum(:id)
end_id = backfilled_namespace_projects.maximum(:id)
group_projects_count = backfilled_namespace_projects.count
- batches_count = (group_projects_count / described_class::BATCH_SIZE.to_f).ceil
+ batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
migration = described_class.new
@@ -66,7 +66,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
expect(group_projects_count).to eq(14)
expect(project_namespaces_in_hierarchy.count).to eq(0)
- migration.perform(start_id, end_id, backfilled_namespace.id, 'up')
+ migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'up')
expect(project_namespaces_in_hierarchy.count).to eq(14)
check_projects_in_sync_with(project_namespaces_in_hierarchy)
@@ -79,7 +79,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = hierarchy1_projects.minimum(:id)
end_id = hierarchy1_projects.maximum(:id)
- described_class.new.perform(start_id, end_id, parent_group1.id, 'up')
+ described_class.new.perform(start_id, end_id, nil, nil, nil, nil, parent_group1.id, 'up')
end
it 'does not duplicate project namespaces' do
@@ -87,7 +87,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
projects_count = ::Project.count
start_id = ::Project.minimum(:id)
end_id = ::Project.maximum(:id)
- batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
project_namespaces = ::Namespace.where(type: 'Project')
migration = described_class.new
@@ -100,7 +100,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
- expect { migration.perform(start_id, end_id, nil, 'up') }.to change(project_namespaces, :count).by(14)
+ expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(project_namespaces, :count).by(14)
expect(projects_count).to eq(project_namespaces.count)
end
@@ -125,7 +125,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
context 'back-fill project namespaces in batches' do
before do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
end
it_behaves_like 'back-fill project namespaces'
@@ -137,7 +137,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = ::Project.minimum(:id)
end_id = ::Project.maximum(:id)
# back-fill first
- described_class.new.perform(start_id, end_id, nil, 'up')
+ described_class.new.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up')
end
shared_examples 'cleanup project namespaces' do
@@ -146,7 +146,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = ::Project.minimum(:id)
end_id = ::Project.maximum(:id)
migration = described_class.new
- batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
expect(projects_count).to be > 0
expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
@@ -154,7 +154,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
- migration.perform(start_id, end_id, nil, 'down')
+ migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'down')
expect(::Project.count).to be > 0
expect(::Namespace.where(type: 'Project').count).to eq(0)
@@ -168,7 +168,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
start_id = backfilled_namespace_projects.minimum(:id)
end_id = backfilled_namespace_projects.maximum(:id)
group_projects_count = backfilled_namespace_projects.count
- batches_count = (group_projects_count / described_class::BATCH_SIZE.to_f).ceil
+ batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
migration = described_class.new
@@ -176,7 +176,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
- migration.perform(start_id, end_id, backfilled_namespace.id, 'down')
+ migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'down')
expect(::Namespace.where(type: 'Project').count).to be > 0
expect(project_namespaces_in_hierarchy.count).to eq(0)
@@ -190,7 +190,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
context 'cleanup project namespaces in batches' do
before do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
end
it_behaves_like 'cleanup project namespaces'
diff --git a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
index 7214225c32c..f6f4a3f6115 100644
--- a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
let!(:unrelated_finding) do
create_finding!(
id: 9999999,
- uuid: "unreleated_finding",
+ uuid: Gitlab::UUID.v5(SecureRandom.hex),
vulnerability_id: nil,
report_type: 1,
location_fingerprint: 'random_location_fingerprint',
diff --git a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb b/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
deleted file mode 100644
index 17fe25c7f71..00000000000
--- a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer, schema: 20210301200959 do
- let(:users) { table(:users) }
- let(:emails) { table(:emails) }
- let(:user_synced_attributes_metadata) { table(:user_synced_attributes_metadata) }
- let(:confirmed_at_2_days_ago) { 2.days.ago }
- let(:confirmed_at_3_days_ago) { 3.days.ago }
- let(:one_year_ago) { 1.year.ago }
-
- let!(:user_needs_migration_1) { users.create!(name: 'user1', email: 'test1@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_needs_migration_2) { users.create!(name: 'user2', email: 'test2@test.com', unconfirmed_email: 'unconfirmed@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_does_not_need_migration) { users.create!(name: 'user3', email: 'test3@test.com', state: 'active', projects_limit: 1) }
- let!(:inactive_user) { users.create!(name: 'user4', email: 'test4@test.com', state: 'blocked', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:alert_bot_user) { users.create!(name: 'user5', email: 'test5@test.com', state: 'active', user_type: 2, projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_has_synced_email) { users.create!(name: 'user6', email: 'test6@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:synced_attributes_metadata_for_user) { user_synced_attributes_metadata.create!(user_id: user_has_synced_email.id, email_synced: true) }
-
- let!(:bad_email_1) { emails.create!(user_id: user_needs_migration_1.id, email: 'other1@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other2@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_3_inactive_user) { emails.create!(user_id: inactive_user.id, email: 'other-inactive@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_4_bot_user) { emails.create!(user_id: alert_bot_user.id, email: 'other-bot@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
-
- let!(:good_email_1) { emails.create!(user_id: user_needs_migration_2.id, email: 'other3@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:good_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other4@test.com', confirmed_at: nil) }
- let!(:good_email_3) { emails.create!(user_id: user_does_not_need_migration.id, email: 'other5@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
-
- let!(:second_email_for_user_with_synced_email) { emails.create!(user_id: user_has_synced_email.id, email: 'other6@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
-
- subject do
- email_ids = [bad_email_1, bad_email_2, good_email_1, good_email_2, good_email_3, second_email_for_user_with_synced_email].map(&:id)
-
- described_class.new.perform(email_ids.min, email_ids.max)
- end
-
- it 'does not change irrelevant email records' do
- subject
-
- expect(good_email_1.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
- expect(good_email_2.reload.confirmed_at).to be_nil
- expect(good_email_3.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
-
- expect(bad_email_3_inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(bad_email_4_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
-
- expect(good_email_1.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(good_email_2.reload.confirmation_sent_at).to be_nil
- expect(good_email_3.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
-
- expect(bad_email_3_inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(bad_email_4_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- end
-
- it 'clears the `unconfirmed_email` field' do
- subject
-
- user_needs_migration_2.reload
- expect(user_needs_migration_2.unconfirmed_email).to be_nil
- end
-
- it 'does not change irrelevant user records' do
- subject
-
- expect(user_does_not_need_migration.reload.confirmed_at).to be_nil
- expect(inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(alert_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(user_has_synced_email.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
-
- expect(user_does_not_need_migration.reload.confirmation_sent_at).to be_nil
- expect(inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(alert_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(user_has_synced_email.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- end
-
- it 'updates confirmation_sent_at column' do
- subject
-
- expect(user_needs_migration_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- expect(user_needs_migration_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
-
- expect(bad_email_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- expect(bad_email_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- end
-
- it 'unconfirms bad email records' do
- subject
-
- expect(bad_email_1.reload.confirmed_at).to be_nil
- expect(bad_email_2.reload.confirmed_at).to be_nil
-
- expect(bad_email_1.reload.confirmation_token).not_to be_nil
- expect(bad_email_2.reload.confirmation_token).not_to be_nil
- end
-
- it 'unconfirms user records' do
- subject
-
- expect(user_needs_migration_1.reload.confirmed_at).to be_nil
- expect(user_needs_migration_2.reload.confirmed_at).to be_nil
-
- expect(user_needs_migration_1.reload.confirmation_token).not_to be_nil
- expect(user_needs_migration_2.reload.confirmation_token).not_to be_nil
- end
-
- context 'enqueued jobs' do
- let(:user_1) { User.find(user_needs_migration_1.id) }
- let(:user_2) { User.find(user_needs_migration_2.id) }
-
- let(:email_1) { Email.find(bad_email_1.id) }
- let(:email_2) { Email.find(bad_email_2.id) }
-
- it 'enqueues the email confirmation and the unconfirm notification mailer jobs' do
- allow(DeviseMailer).to receive(:confirmation_instructions).and_call_original
- allow(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to receive(:unconfirm_notification_email).and_call_original
-
- subject
-
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_1, email_1.confirmation_token)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_2, email_2.confirmation_token)
-
- expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_1)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_1, user_1.confirmation_token)
-
- expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_2)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_2, user_2.confirmation_token)
- end
- end
-end
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 0380ddd9a2e..d2abdb740f8 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -22,8 +22,8 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
data: { project_key: project_key, repo_slug: repo_slug },
credentials: { base_uri: import_url, user: bitbucket_user, password: password }
)
- data.save
- project.save
+ data.save!
+ project.save!
end
describe '#import_repository' do
diff --git a/spec/lib/gitlab/buffered_io_spec.rb b/spec/lib/gitlab/buffered_io_spec.rb
new file mode 100644
index 00000000000..f8896abd46e
--- /dev/null
+++ b/spec/lib/gitlab/buffered_io_spec.rb
@@ -0,0 +1,54 @@
+# rubocop:disable Style/FrozenStringLiteralComment
+require 'spec_helper'
+
+RSpec.describe Gitlab::BufferedIo do
+ describe '#readuntil' do
+ let(:never_ending_tcp_socket) do
+ Class.new do
+ def initialize(*_)
+ @read_counter = 0
+ end
+
+ def setsockopt(*_); end
+
+ def closed?
+ false
+ end
+
+ def close
+ true
+ end
+
+ def to_io
+ StringIO.new('Hello World!')
+ end
+
+ def write_nonblock(data, *_)
+ data.size
+ end
+
+ def read_nonblock(buffer_size, *_)
+ sleep 0.01
+ @read_counter += 1
+
+ raise 'Test did not raise HeaderReadTimeout' if @read_counter > 10
+
+ 'H' * buffer_size
+ end
+ end
+ end
+
+ before do
+ stub_const('Gitlab::BufferedIo::HEADER_READ_TIMEOUT', 0.1)
+ end
+
+ subject(:readuntil) do
+ Gitlab::BufferedIo.new(never_ending_tcp_socket.new).readuntil('a')
+ end
+
+ it 'raises a timeout error' do
+ expect { readuntil }.to raise_error(Gitlab::HTTP::HeaderReadTimeout, /Request timed out after reading headers for 0\.[0-9]+ seconds/)
+ end
+ end
+end
+# rubocop:enable Style/FrozenStringLiteralComment
diff --git a/spec/lib/gitlab/changelog/config_spec.rb b/spec/lib/gitlab/changelog/config_spec.rb
index c410ba4d116..600682d30ad 100644
--- a/spec/lib/gitlab/changelog/config_spec.rb
+++ b/spec/lib/gitlab/changelog/config_spec.rb
@@ -31,6 +31,20 @@ RSpec.describe Gitlab::Changelog::Config do
described_class.from_git(project)
end
+
+ context 'when changelog is empty' do
+ it 'returns the default configuration' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return("")
+
+ expect(described_class)
+ .to receive(:new)
+ .with(project)
+
+ described_class.from_git(project)
+ end
+ end
end
describe '.from_hash' do
diff --git a/spec/lib/gitlab/changelog/release_spec.rb b/spec/lib/gitlab/changelog/release_spec.rb
index d8434821640..defcec5aa65 100644
--- a/spec/lib/gitlab/changelog/release_spec.rb
+++ b/spec/lib/gitlab/changelog/release_spec.rb
@@ -139,6 +139,16 @@ RSpec.describe Gitlab::Changelog::Release do
OUT
end
end
+
+ context 'when template parser raises an error' do
+ before do
+ allow(config).to receive(:template).and_raise(Gitlab::TemplateParser::Error)
+ end
+
+ it 'raises a Changelog error' do
+ expect { release.to_markdown }.to raise_error(Gitlab::Changelog::Error)
+ end
+ end
end
describe '#header_start_position' do
diff --git a/spec/lib/gitlab/checks/branch_check_spec.rb b/spec/lib/gitlab/checks/branch_check_spec.rb
index f503759f3f8..c06d26d1441 100644
--- a/spec/lib/gitlab/checks/branch_check_spec.rb
+++ b/spec/lib/gitlab/checks/branch_check_spec.rb
@@ -40,15 +40,6 @@ RSpec.describe Gitlab::Checks::BranchCheck do
expect { subject.validate! }.not_to raise_error
end
end
-
- context "the feature flag is disabled" do
- it "doesn't prohibit a 40-character hexadecimal branch name" do
- stub_feature_flags(prohibit_hexadecimal_branch_names: false)
- allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e")
-
- expect { subject.validate! }.not_to raise_error
- end
- end
end
context 'protected branches check' do
diff --git a/spec/lib/gitlab/ci/badge/release/latest_release_spec.rb b/spec/lib/gitlab/ci/badge/release/latest_release_spec.rb
new file mode 100644
index 00000000000..36f9f4fb321
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/release/latest_release_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Release::LatestRelease do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_guest(user)
+ create(:release, project: project, released_at: 1.day.ago)
+ end
+
+ subject { described_class.new(project, user) }
+
+ describe '#entity' do
+ it 'describes latest release' do
+ expect(subject.entity).to eq 'Latest Release'
+ end
+ end
+
+ describe '#tag' do
+ it 'returns latest release tag for the project ordered using release_at' do
+ create(:release, tag: "v1.0.0", project: project, released_at: 1.hour.ago)
+ latest_release = create(:release, tag: "v2.0.0", project: project, released_at: Time.current)
+
+ expect(subject.tag).to eq latest_release.tag
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns correct metadata' do
+ expect(subject.metadata.image_url).to include 'release.svg'
+ end
+ end
+
+ describe '#template' do
+ it 'returns correct template' do
+ expect(subject.template.key_text).to eq 'Latest Release'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/release/metadata_spec.rb b/spec/lib/gitlab/ci/badge/release/metadata_spec.rb
new file mode 100644
index 00000000000..d68358f1458
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/release/metadata_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'lib/gitlab/ci/badge/shared/metadata'
+
+RSpec.describe Gitlab::Ci::Badge::Release::Metadata do
+ let(:project) { create(:project) }
+ let(:ref) { 'feature' }
+ let!(:release) { create(:release, tag: ref, project: project) }
+ let(:user) { create(:user) }
+ let(:badge) do
+ Gitlab::Ci::Badge::Release::LatestRelease.new(project, user)
+ end
+
+ let(:metadata) { described_class.new(badge) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ it_behaves_like 'badge metadata'
+
+ describe '#title' do
+ it 'returns latest release title' do
+ expect(metadata.title).to eq 'Latest Release'
+ end
+ end
+
+ describe '#image_url' do
+ it 'returns valid url' do
+ expect(metadata.image_url).to include "/-/badges/release.svg"
+ end
+ end
+
+ describe '#link_url' do
+ it 'returns valid link' do
+ expect(metadata.link_url).to include "/-/releases"
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/release/template_spec.rb b/spec/lib/gitlab/ci/badge/release/template_spec.rb
new file mode 100644
index 00000000000..2b66c296a94
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/release/template_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Release::Template do
+ let(:project) { create(:project) }
+ let(:ref) { 'v1.2.3' }
+ let(:user) { create(:user) }
+ let!(:release) { create(:release, tag: ref, project: project) }
+ let(:badge) { Gitlab::Ci::Badge::Release::LatestRelease.new(project, user) }
+ let(:template) { described_class.new(badge) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ describe '#key_text' do
+ it 'defaults to latest release' do
+ expect(template.key_text).to eq 'Latest Release'
+ end
+
+ it 'returns custom key text' do
+ key_text = 'Test Release'
+ badge = Gitlab::Ci::Badge::Release::LatestRelease.new(project, user, opts: { key_text: key_text })
+
+ expect(described_class.new(badge).key_text).to eq key_text
+ end
+ end
+
+ describe '#value_text' do
+ context 'when a release exists' do
+ it 'returns the tag of the release' do
+ expect(template.value_text).to eq ref
+ end
+ end
+
+ context 'no releases exist' do
+ before do
+ allow(badge).to receive(:tag).and_return(nil)
+ end
+
+ it 'returns string that latest release is none' do
+ expect(template.value_text).to eq 'none'
+ end
+ end
+ end
+
+ describe '#key_width' do
+ it 'returns the default key width' do
+ expect(template.key_width).to eq 90
+ end
+
+ it 'returns custom key width' do
+ key_width = 100
+ badge = Gitlab::Ci::Badge::Release::LatestRelease.new(project, user, opts: { key_width: key_width })
+
+ expect(described_class.new(badge).key_width).to eq key_width
+ end
+ end
+
+ describe '#value_width' do
+ it 'has a fixed value width' do
+ expect(template.value_width).to eq 54
+ end
+ end
+
+ describe '#key_color' do
+ it 'always has the same color' do
+ expect(template.key_color).to eq '#555'
+ end
+ end
+
+ describe '#value_color' do
+ context 'when release exists' do
+ it 'is blue' do
+ expect(template.value_color).to eq '#3076af'
+ end
+ end
+
+ context 'when release does not exist' do
+ before do
+ allow(badge).to receive(:tag).and_return(nil)
+ end
+
+ it 'is red' do
+ expect(template.value_color).to eq '#e05d44'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/artifacts/expire_in_parser_spec.rb b/spec/lib/gitlab/ci/build/artifacts/expire_in_parser_spec.rb
index 0e26a9fa571..889878cf3ef 100644
--- a/spec/lib/gitlab/ci/build/artifacts/expire_in_parser_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/expire_in_parser_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Artifacts::ExpireInParser do
- describe '.validate_duration' do
+ describe '.validate_duration', :request_store do
subject { described_class.validate_duration(value) }
context 'with never' do
@@ -20,14 +20,33 @@ RSpec.describe Gitlab::Ci::Build::Artifacts::ExpireInParser do
context 'with a duration' do
let(:value) { '1 Day' }
+ let(:other_value) { '30 seconds' }
it { is_expected.to be_truthy }
+
+ it 'caches data' do
+ expect(ChronicDuration).to receive(:parse).with(value).once.and_call_original
+ expect(ChronicDuration).to receive(:parse).with(other_value).once.and_call_original
+
+ 2.times do
+ expect(described_class.validate_duration(value)).to eq(86400)
+ expect(described_class.validate_duration(other_value)).to eq(30)
+ end
+ end
end
context 'without a duration' do
let(:value) { 'something' }
it { is_expected.to be_falsy }
+
+ it 'caches data' do
+ expect(ChronicDuration).to receive(:parse).with(value).once.and_call_original
+
+ 2.times do
+ expect(described_class.validate_duration(value)).to be_falsey
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index 532c83f6768..4ac8bf61738 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
@@ -4,14 +4,23 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
describe '#satisfied_by?' do
+ subject { described_class.new(globs).satisfied_by?(pipeline, context) }
+
it_behaves_like 'a glob matching rule' do
let(:pipeline) { build(:ci_pipeline) }
+ let(:context) {}
before do
allow(pipeline).to receive(:modified_paths).and_return(files.keys)
end
+ end
- subject { described_class.new(globs).satisfied_by?(pipeline, nil) }
+ context 'when pipeline is nil' do
+ let(:pipeline) {}
+ let(:context) {}
+ let(:globs) { [] }
+
+ it { is_expected.to be_truthy }
end
context 'when using variable expansion' do
@@ -20,8 +29,6 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
let(:globs) { ['$HELM_DIR/**/*'] }
let(:context) { double('context') }
- subject { described_class.new(globs).satisfied_by?(pipeline, context) }
-
before do
allow(pipeline).to receive(:modified_paths).and_return(modified_paths)
end
@@ -32,6 +39,12 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
it { is_expected.to be_falsey }
end
+ context 'when modified paths are nil' do
+ let(:modified_paths) {}
+
+ it { is_expected.to be_truthy }
+ end
+
context 'when context has the specified variables' do
let(:variables_hash) do
{ 'HELM_DIR' => 'helm' }
diff --git a/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
index 0505b17ea91..e83d4974bb7 100644
--- a/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require_dependency 'active_model'
RSpec.describe Gitlab::Ci::Config::Entry::Include::Rules::Rule do
let(:factory) do
diff --git a/spec/lib/gitlab/ci/config/entry/include/rules_spec.rb b/spec/lib/gitlab/ci/config/entry/include/rules_spec.rb
index c255d6e9dd6..d5988dbbb58 100644
--- a/spec/lib/gitlab/ci/config/entry/include/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/include/rules_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require_dependency 'active_model'
RSpec.describe Gitlab::Ci::Config::Entry::Include::Rules do
let(:factory) do
diff --git a/spec/lib/gitlab/ci/config/entry/include_spec.rb b/spec/lib/gitlab/ci/config/entry/include_spec.rb
index 275cdcddeb0..fd7f85c9298 100644
--- a/spec/lib/gitlab/ci/config/entry/include_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/include_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require_dependency 'active_model'
RSpec.describe ::Gitlab::Ci::Config::Entry::Include do
subject(:include_entry) { described_class.new(config) }
diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
index 9a2a67389fc..b03175cd80f 100644
--- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
@@ -70,6 +70,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Jobs do
it 'reports error' do
expect(entry.errors).to include 'jobs rspec config should implement a script: or a trigger: keyword'
end
+
+ context 'when the job name cannot be cast directly to a symbol' do
+ let(:config) { { true => nil } }
+
+ it 'properly parses the job name without raising a NoMethodError' do
+ expect(entry.errors).to include 'jobs true config should implement a script: or a trigger: keyword'
+ end
+ end
end
context 'when no visible jobs present' do
diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
index 46800055dd9..e5de0fb38e3 100644
--- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'support/helpers/stub_feature_flags'
-require_dependency 'active_model'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Policy do
let(:entry) { described_class.new(config) }
@@ -47,6 +45,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Policy do
end
context 'when using unsafe regexp' do
+ # When removed we could use `require 'fast_spec_helper'` again.
include StubFeatureFlags
let(:config) { ['/^(?!master).+/'] }
@@ -89,7 +88,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Policy do
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
- .to include /policy config should be an array of strings or regexps/
+ .to include /policy config should be an array of strings or regular expressions/
end
end
end
@@ -107,6 +106,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Policy do
end
context 'when using unsafe regexp' do
+ # When removed we could use `require 'fast_spec_helper'` again.
include StubFeatureFlags
let(:config) { { refs: ['/^(?!master).+/'] } }
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 749d1386ed9..daf58aff116 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -55,13 +55,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
}
end
- context 'when deprecated types keyword is defined' do
+ context 'when deprecated types/type keywords are defined' do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:hash) do
{ types: %w(test deploy),
- rspec: { script: 'rspec' } }
+ rspec: { script: 'rspec', type: 'test' } }
end
before do
@@ -69,11 +69,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
end
it 'returns array of types as stages with a warning' do
+ expect(root.jobs_value[:rspec][:stage]).to eq 'test'
expect(root.stages_value).to eq %w[test deploy]
- expect(root.warnings).to match_array(["root `types` is deprecated in 9.0 and will be removed in 15.0."])
+ expect(root.warnings).to match_array([
+ "root `types` is deprecated in 9.0 and will be removed in 15.0.",
+ "jobs:rspec `type` is deprecated in 9.0 and will be removed in 15.0."
+ ])
end
- it 'logs usage of types keyword' do
+ it 'logs usage of keywords' do
expect(Gitlab::AppJsonLogger).to(
receive(:info)
.with(event: 'ci_used_deprecated_keyword',
@@ -350,9 +354,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
root.compose!
end
- context 'when before script is not an array' do
+ context 'when before script is a number' do
let(:hash) do
- { before_script: 'ls' }
+ { before_script: 123 }
end
describe '#valid?' do
@@ -364,7 +368,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
describe '#errors' do
it 'reports errors from child nodes' do
expect(root.errors)
- .to include 'before_script config should be an array containing strings and arrays of strings'
+ .to include 'before_script config should be a string or a nested array of strings up to 10 levels deep'
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/script_spec.rb b/spec/lib/gitlab/ci/config/entry/script_spec.rb
deleted file mode 100644
index 1ddf7881e81..00000000000
--- a/spec/lib/gitlab/ci/config/entry/script_spec.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Config::Entry::Script do
- let(:entry) { described_class.new(config) }
-
- describe 'validations' do
- context 'when entry config value is array of strings' do
- let(:config) { %w(ls pwd) }
-
- describe '#value' do
- it 'returns array of strings' do
- expect(entry.value).to eq config
- end
- end
-
- describe '#errors' do
- it 'does not append errors' do
- expect(entry.errors).to be_empty
- end
- end
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- context 'when entry config value is array of arrays of strings' do
- let(:config) { [['ls'], ['pwd', 'echo 1']] }
-
- describe '#value' do
- it 'returns array of strings' do
- expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
- end
- end
-
- describe '#errors' do
- it 'does not append errors' do
- expect(entry.errors).to be_empty
- end
- end
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- context 'when entry config value is array containing strings and arrays of strings' do
- let(:config) { ['ls', ['pwd', 'echo 1']] }
-
- describe '#value' do
- it 'returns array of strings' do
- expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
- end
- end
-
- describe '#errors' do
- it 'does not append errors' do
- expect(entry.errors).to be_empty
- end
- end
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- context 'when entry value is string' do
- let(:config) { 'ls' }
-
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors)
- .to include 'script config should be an array containing strings and arrays of strings'
- end
- end
-
- describe '#valid?' do
- it 'is not valid' do
- expect(entry).not_to be_valid
- end
- end
- end
-
- context 'when entry value is multi-level nested array' do
- let(:config) { [['ls', ['echo 1']], 'pwd'] }
-
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors)
- .to include 'script config should be an array containing strings and arrays of strings'
- end
- end
-
- describe '#valid?' do
- it 'is not valid' do
- expect(entry).not_to be_valid
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index cebe8984741..f8754d7e124 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -175,27 +175,35 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
end
end
- context "when duplicate 'include' is defined" do
+ context "when duplicate 'include's are defined" do
+ let(:values) do
+ { include: [
+ { 'local' => local_file },
+ { 'local' => local_file }
+ ],
+ image: 'ruby:2.7' }
+ end
+
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when passing max number of files' do
let(:values) do
{ include: [
{ 'local' => local_file },
- { 'local' => local_file }
+ { 'remote' => remote_url }
],
image: 'ruby:2.7' }
end
- it 'raises an exception' do
- expect { subject }.to raise_error(described_class::DuplicateIncludesError)
+ before do
+ stub_const("#{described_class}::MAX_INCLUDES", 2)
end
- context 'when including multiple files from a project' do
- let(:values) do
- { include: { project: project.full_path, file: [local_file, local_file] } }
- end
-
- it 'raises an exception' do
- expect { subject }.to raise_error(described_class::DuplicateIncludesError)
- end
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
end
end
diff --git a/spec/lib/gitlab/ci/config/external/rules_spec.rb b/spec/lib/gitlab/ci/config/external/rules_spec.rb
index 091bd3b07e6..e2bb55f3854 100644
--- a/spec/lib/gitlab/ci/config/external/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/rules_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
let(:context) { double(project: project, sha: project.repository.tree.sha, top_level_worktree_paths: ['Dockerfile']) }
before do
- project.repository.create_file(project.owner, 'Dockerfile', "commit", message: 'test', branch_name: "master")
+ project.repository.create_file(project.first_owner, 'Dockerfile', "commit", message: 'test', branch_name: "master")
end
it { is_expected.to eq(true) }
diff --git a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
index a29471706cc..1cc8b462224 100644
--- a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'support/helpers/stubbed_feature'
-require 'support/helpers/stub_feature_flags'
RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
- include StubFeatureFlags
-
describe '.applies_to?' do
subject { described_class.applies_to?(config) }
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 1b3e8a2ce4a..05ff1f3618b 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -462,7 +462,7 @@ RSpec.describe Gitlab::Ci::Config do
expect(project.repository).to receive(:blob_data_at)
.with('eeff1122', local_location)
- described_class.new(gitlab_ci_yml, project: project, sha: 'eeff1122', user: user)
+ described_class.new(gitlab_ci_yml, project: project, sha: 'eeff1122', user: user, pipeline: pipeline)
end
end
@@ -470,7 +470,7 @@ RSpec.describe Gitlab::Ci::Config do
it 'is using latest SHA on the default branch' do
expect(project.repository).to receive(:root_ref_sha)
- described_class.new(gitlab_ci_yml, project: project, sha: nil, user: user)
+ described_class.new(gitlab_ci_yml, project: project, sha: nil, user: user, pipeline: pipeline)
end
end
end
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index 1e433d7854a..747ff13c840 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -7,9 +7,10 @@ RSpec.describe Gitlab::Ci::Lint do
let_it_be(:user) { create(:user) }
let(:lint) { described_class.new(project: project, current_user: user) }
+ let(:ref) { project.default_branch }
describe '#validate' do
- subject { lint.validate(content, dry_run: dry_run) }
+ subject { lint.validate(content, dry_run: dry_run, ref: ref) }
shared_examples 'content is valid' do
let(:content) do
@@ -251,6 +252,29 @@ RSpec.describe Gitlab::Ci::Lint do
end
end
+ context 'when using a ref other than the default branch' do
+ let(:ref) { 'feature' }
+ let(:content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo 1
+ rules:
+ - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
+ test:
+ stage: test
+ script: echo 2
+ rules:
+ - if: "$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH"
+ YAML
+ end
+
+ it 'includes only jobs that are excluded on the default branch' do
+ expect(subject.jobs.size).to eq(1)
+ expect(subject.jobs[0][:name]).to eq('test')
+ end
+ end
+
it_behaves_like 'sets merged yaml'
include_context 'advanced validations' do
@@ -298,4 +322,102 @@ RSpec.describe Gitlab::Ci::Lint do
end
end
end
+
+ context 'pipeline logger' do
+ let(:counters) do
+ {
+ 'count' => a_kind_of(Numeric),
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
+ }
+ end
+
+ let(:loggable_data) do
+ {
+ 'class' => 'Gitlab::Ci::Pipeline::Logger',
+ 'config_build_context_duration_s' => counters,
+ 'config_build_variables_duration_s' => counters,
+ 'config_compose_duration_s' => counters,
+ 'config_expand_duration_s' => counters,
+ 'config_external_process_duration_s' => counters,
+ 'config_stages_inject_duration_s' => counters,
+ 'config_tags_resolve_duration_s' => counters,
+ 'config_yaml_extend_duration_s' => counters,
+ 'config_yaml_load_duration_s' => counters,
+ 'pipeline_creation_caller' => 'Gitlab::Ci::Lint',
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_persisted' => false,
+ 'pipeline_source' => 'unknown',
+ 'project_id' => project&.id,
+ 'yaml_process_duration_s' => counters
+ }
+ end
+
+ let(:content) do
+ <<~YAML
+ build:
+ script: echo
+ YAML
+ end
+
+ subject(:validate) { lint.validate(content, dry_run: false) }
+
+ before do
+ project&.add_developer(user)
+ end
+
+ context 'when the duration is under the threshold' do
+ it 'does not create a log entry' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ validate
+ end
+ end
+
+ context 'when the durations exceeds the threshold' do
+ let(:timer) do
+ proc do
+ @timer = @timer.to_i + 30
+ end
+ end
+
+ before do
+ allow(Gitlab::Ci::Pipeline::Logger)
+ .to receive(:current_monotonic_time) { timer.call }
+ end
+
+ it 'creates a log entry' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(loggable_data)
+
+ validate
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_pipeline_creation_logger: false)
+ end
+
+ it 'does not create a log entry' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ validate
+ end
+ end
+
+ context 'when project is not provided' do
+ let(:project) { nil }
+
+ let(:project_nil_loggable_data) do
+ loggable_data.except('project_id')
+ end
+
+ it 'creates a log entry without project_id' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(project_nil_loggable_data)
+
+ validate
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index c49673f5a4a..7eec78ff186 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -40,60 +40,142 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
allow(validator_class).to receive(:new).and_call_original
end
- context 'when the validate flag is set as `false`' do
- let(:validate) { false }
+ context 'when enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
- it 'does not run the validation logic' do
- parse_report
+ context 'when the validate flag is set as `true`' do
+ let(:validate) { true }
- expect(validator_class).not_to have_received(:new)
- end
- end
+ it 'instantiates the validator with correct params' do
+ parse_report
- context 'when the validate flag is set as `true`' do
- let(:validate) { true }
- let(:valid?) { false }
+ expect(validator_class).to have_received(:new).with(report.type, {})
+ end
- before do
- allow_next_instance_of(validator_class) do |instance|
- allow(instance).to receive(:valid?).and_return(valid?)
- allow(instance).to receive(:errors).and_return(['foo'])
+ context 'when the report data is valid according to the schema' do
+ let(:valid?) { true }
+
+ before do
+ allow_next_instance_of(validator_class) do |instance|
+ allow(instance).to receive(:valid?).and_return(valid?)
+ allow(instance).to receive(:errors).and_return([])
+ end
+
+ allow(parser).to receive_messages(create_scanner: true, create_scan: true)
+ end
+
+ it 'does not add errors to the report' do
+ expect { parse_report }.not_to change { report.errors }.from([])
+ end
+
+ it 'adds the schema validation status to the report' do
+ parse_report
+
+ expect(report.schema_validation_status).to eq(:valid_schema)
+ end
+
+ it 'keeps the execution flow as normal' do
+ parse_report
+
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
+ end
end
- allow(parser).to receive_messages(create_scanner: true, create_scan: true)
- end
+ context 'when the report data is not valid according to the schema' do
+ let(:valid?) { false }
- it 'instantiates the validator with correct params' do
- parse_report
+ before do
+ allow_next_instance_of(validator_class) do |instance|
+ allow(instance).to receive(:valid?).and_return(valid?)
+ allow(instance).to receive(:errors).and_return(['foo'])
+ end
- expect(validator_class).to have_received(:new).with(report.type, {})
- end
+ allow(parser).to receive_messages(create_scanner: true, create_scan: true)
+ end
+
+ it 'adds errors to the report' do
+ expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }])
+ end
+
+ it 'adds the schema validation status to the report' do
+ parse_report
- context 'when the report data is not valid according to the schema' do
- it 'adds errors to the report' do
- expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }])
+ expect(report.schema_validation_status).to eq(:invalid_schema)
+ end
+
+ it 'does not try to create report entities' do
+ parse_report
+
+ expect(parser).not_to have_received(:create_scanner)
+ expect(parser).not_to have_received(:create_scan)
+ end
end
+ end
+ end
+
+ context 'when enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ context 'when the validate flag is set as `false`' do
+ let(:validate) { false }
- it 'does not try to create report entities' do
+ it 'does not run the validation logic' do
parse_report
- expect(parser).not_to have_received(:create_scanner)
- expect(parser).not_to have_received(:create_scan)
+ expect(validator_class).not_to have_received(:new)
end
end
- context 'when the report data is valid according to the schema' do
- let(:valid?) { true }
+ context 'when the validate flag is set as `true`' do
+ let(:validate) { true }
+ let(:valid?) { false }
- it 'does not add errors to the report' do
- expect { parse_report }.not_to change { report.errors }.from([])
+ before do
+ allow_next_instance_of(validator_class) do |instance|
+ allow(instance).to receive(:valid?).and_return(valid?)
+ allow(instance).to receive(:errors).and_return(['foo'])
+ end
+
+ allow(parser).to receive_messages(create_scanner: true, create_scan: true)
end
- it 'keeps the execution flow as normal' do
+ it 'instantiates the validator with correct params' do
parse_report
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
+ expect(validator_class).to have_received(:new).with(report.type, {})
+ end
+
+ context 'when the report data is not valid according to the schema' do
+ it 'adds errors to the report' do
+ expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }])
+ end
+
+ it 'does not try to create report entities' do
+ parse_report
+
+ expect(parser).not_to have_received(:create_scanner)
+ expect(parser).not_to have_received(:create_scan)
+ end
+ end
+
+ context 'when the report data is valid according to the schema' do
+ let(:valid?) { true }
+
+ it 'does not add errors to the report' do
+ expect { parse_report }.not_to change { report.errors }.from([])
+ end
+
+ it 'keeps the execution flow as normal' do
+ parse_report
+
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
+ 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 4ca8f74e57f..82fa11d5f98 100644
--- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -99,6 +99,19 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
'Some failure'
end
+ context 'and has failure with no message but has system-err' do
+ let(:testcase_content) do
+ <<-EOF.strip_heredoc
+ <failure></failure>
+ <system-err>Some failure</system-err>
+ EOF
+ end
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED,
+ 'Some failure'
+ end
+
context 'and has error' do
let(:testcase_content) { '<error>Some error</error>' }
@@ -107,6 +120,19 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
'Some error'
end
+ context 'and has error with no message but has system-err' do
+ let(:testcase_content) do
+ <<-EOF.strip_heredoc
+ <error></error>
+ <system-err>Some error</system-err>
+ EOF
+ end
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_ERROR,
+ 'Some error'
+ end
+
context 'and has skipped' do
let(:testcase_content) { '<skipped/>' }
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
index 0a592395c3a..375841ce236 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
@@ -47,18 +47,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CreateDeployments do
expect(job.deployment).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create a deployment record' do
- expect { subject }.not_to change { Deployment.count }
-
- expect(job.deployment).to be_nil
- end
- end
end
context 'when a pipeline contains a teardown job' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
index 253928e1a19..6a7d9b58a05 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
@@ -57,18 +57,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
expect(job.persisted_environment).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create any environments' do
- expect { subject }.not_to change { Environment.count }
-
- expect(job.persisted_environment).to be_nil
- end
- end
end
context 'when a pipeline contains a teardown job' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
index 87df5a3e21b..571455d6279 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
@@ -60,18 +60,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups do
expect(job.resource_group).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create any resource groups' do
- expect { subject }.not_to change { Ci::ResourceGroup.count }
-
- expect(job.resource_group).to be_nil
- end
- end
end
context 'when a pipeline does not contain a job that requires a resource group' do
diff --git a/spec/lib/gitlab/ci/pipeline/logger_spec.rb b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
index a488bc184f8..f31361431f2 100644
--- a/spec/lib/gitlab/ci/pipeline/logger_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
@@ -47,13 +47,15 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
end
def loggable_data(count:, db_count: nil)
- keys = %w[
+ database_name = Ci::ApplicationRecord.connection.pool.db_config.name
+
+ keys = %W[
expensive_operation_duration_s
expensive_operation_db_count
expensive_operation_db_primary_count
expensive_operation_db_primary_duration_s
- expensive_operation_db_main_count
- expensive_operation_db_main_duration_s
+ expensive_operation_db_#{database_name}_count
+ expensive_operation_db_#{database_name}_duration_s
]
data = keys.each.with_object({}) do |key, accumulator|
@@ -75,7 +77,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
end
context 'with a single query' do
- let(:operation) { -> { Project.count } }
+ let(:operation) { -> { Ci::Pipeline.count } }
it { is_expected.to eq(operation.call) }
@@ -201,6 +203,35 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
expect(commit).to be_truthy
end
end
+
+ context 'when project is not passed and pipeline is not persisted' do
+ let(:project) {}
+ let(:pipeline) { build(:ci_pipeline) }
+
+ let(:loggable_data) do
+ {
+ 'class' => described_class.name.to_s,
+ 'pipeline_persisted' => false,
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_creation_caller' => 'source',
+ 'pipeline_save_duration_s' => {
+ 'avg' => 60, 'count' => 1, 'max' => 60, 'min' => 60
+ },
+ 'pipeline_creation_duration_s' => {
+ 'avg' => 20, 'count' => 2, 'max' => 30, 'min' => 10
+ }
+ }
+ end
+
+ it 'logs to application.json' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(commit).to be_truthy
+ end
+ end
end
context 'when the feature flag is disabled' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 2f9fcd7caac..49505d397c2 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -411,171 +411,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
describe '#to_resource' do
subject { seed_build.to_resource }
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- context 'when job is Ci::Build' do
- it { is_expected.to be_a(::Ci::Build) }
- it { is_expected.to be_valid }
-
- shared_examples_for 'deployment job' do
- it 'returns a job with deployment' do
- expect { subject }.to change { Environment.count }.by(1)
-
- expect(subject.deployment).not_to be_nil
- expect(subject.deployment.deployable).to eq(subject)
- expect(subject.deployment.environment.name).to eq(expected_environment_name)
- end
- end
-
- shared_examples_for 'non-deployment job' do
- it 'returns a job without deployment' do
- expect(subject.deployment).to be_nil
- end
- end
-
- shared_examples_for 'ensures environment existence' do
- it 'has environment' do
- expect { subject }.to change { Environment.count }.by(1)
-
- expect(subject).to be_has_environment
- expect(subject.environment).to eq(environment_name)
- expect(subject.metadata.expanded_environment_name).to eq(expected_environment_name)
- expect(Environment.exists?(name: expected_environment_name)).to eq(true)
- end
- end
-
- shared_examples_for 'ensures environment inexistence' do
- it 'does not have environment' do
- expect { subject }.not_to change { Environment.count }
-
- expect(subject).not_to be_has_environment
- expect(subject.environment).to be_nil
- expect(subject.metadata&.expanded_environment_name).to be_nil
- expect(Environment.exists?(name: expected_environment_name)).to eq(false)
- end
- end
-
- context 'when job deploys to production' do
- let(:environment_name) { 'production' }
- let(:expected_environment_name) { 'production' }
- let(:attributes) { { name: 'deploy', ref: 'master', environment: 'production' } }
-
- it_behaves_like 'deployment job'
- it_behaves_like 'ensures environment existence'
-
- context 'when create_deployment_in_separate_transaction feature flag is enabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: true)
- end
-
- it 'does not create any deployments nor environments' do
- expect(subject.deployment).to be_nil
- expect(Environment.count).to eq(0)
- expect(Deployment.count).to eq(0)
- end
- end
-
- context 'when the environment name is invalid' do
- let(:attributes) { { name: 'deploy', ref: 'master', environment: '!!!' } }
-
- it 'fails the job with a failure reason and does not create an environment' do
- expect(subject).to be_failed
- expect(subject).to be_environment_creation_failure
- expect(subject.metadata.expanded_environment_name).to be_nil
- expect(Environment.exists?(name: expected_environment_name)).to eq(false)
- end
- end
- end
-
- context 'when job starts a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{pipeline.ref}" }
-
- let(:attributes) do
- {
- name: 'deploy', ref: 'master', environment: environment_name,
- options: { environment: { name: environment_name } }
- }
- end
-
- it_behaves_like 'deployment job'
- it_behaves_like 'ensures environment existence'
- end
-
- context 'when job stops a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{pipeline.ref}" }
-
- let(:attributes) do
- {
- name: 'deploy', ref: 'master', environment: environment_name,
- options: { environment: { name: environment_name, action: 'stop' } }
- }
- end
-
- it 'returns a job without deployment' do
- expect(subject.deployment).to be_nil
- end
-
- it_behaves_like 'non-deployment job'
- it_behaves_like 'ensures environment existence'
- end
-
- context 'when job belongs to a resource group' do
- let(:resource_group) { 'iOS' }
- let(:attributes) { { name: 'rspec', ref: 'master', resource_group_key: resource_group, environment: 'production' }}
-
- it 'returns a job with resource group' do
- expect(subject.resource_group).not_to be_nil
- expect(subject.resource_group.key).to eq('iOS')
- expect(Ci::ResourceGroup.count).to eq(1)
- end
-
- context 'when create_deployment_in_separate_transaction feature flag is enabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: true)
- end
-
- it 'does not create any resource groups' do
- expect(subject.resource_group).to be_nil
- expect(Ci::ResourceGroup.count).to eq(0)
- end
- end
-
- context 'when resource group has $CI_ENVIRONMENT_NAME in it' do
- let(:resource_group) { 'test/$CI_ENVIRONMENT_NAME' }
-
- it 'expands environment name' do
- expect(subject.resource_group.key).to eq('test/production')
- end
- end
- end
- end
-
- context 'when job is a bridge' do
- let(:base_attributes) do
- {
- name: 'rspec', ref: 'master', options: { trigger: 'my/project' }, scheduling_type: :stage
- }
- end
-
- let(:attributes) { base_attributes }
-
- it { is_expected.to be_a(::Ci::Bridge) }
- it { is_expected.to be_valid }
-
- context 'when job belongs to a resource group' do
- let(:attributes) { base_attributes.merge(resource_group_key: 'iOS') }
-
- it 'returns a job with resource group' do
- expect(subject.resource_group).not_to be_nil
- expect(subject.resource_group.key).to eq('iOS')
- end
- end
- end
-
it 'memoizes a resource object' do
expect(subject.object_id).to eq seed_build.to_resource.object_id
end
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
index 3b0eaffc54e..f4b47893805 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
@@ -85,6 +85,9 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
let(:info) { build(:codequality_degradation, :info) }
let(:major_2) { build(:codequality_degradation, :major) }
let(:critical) { build(:codequality_degradation, :critical) }
+ let(:uppercase_major) { build(:codequality_degradation, severity: 'MAJOR') }
+ let(:unknown) { build(:codequality_degradation, severity: 'unknown') }
+
let(:codequality_report) { described_class.new }
before do
@@ -94,6 +97,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
codequality_report.add_degradation(major_2)
codequality_report.add_degradation(info)
codequality_report.add_degradation(critical)
+ codequality_report.add_degradation(unknown)
codequality_report.sort_degradations!
end
@@ -105,8 +109,30 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
major,
major_2,
minor,
- info
+ info,
+ unknown
])
end
+
+ context 'with non-existence and uppercase severities' do
+ let(:other_report) { described_class.new }
+ let(:non_existent) { build(:codequality_degradation, severity: 'non-existent') }
+
+ before do
+ other_report.add_degradation(blocker)
+ other_report.add_degradation(uppercase_major)
+ other_report.add_degradation(minor)
+ other_report.add_degradation(non_existent)
+ end
+
+ it 'sorts unknown last' do
+ expect(other_report.degradations.values).to eq([
+ blocker,
+ uppercase_major,
+ minor,
+ non_existent
+ ])
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/reports/security/finding_key_spec.rb b/spec/lib/gitlab/ci/reports/security/finding_key_spec.rb
index 784c1183320..2320f011cf5 100644
--- a/spec/lib/gitlab/ci/reports/security/finding_key_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/finding_key_spec.rb
@@ -6,36 +6,47 @@ RSpec.describe Gitlab::Ci::Reports::Security::FindingKey do
using RSpec::Parameterized::TableSyntax
describe '#==' do
- where(:location_fp_1, :location_fp_2, :identifier_fp_1, :identifier_fp_2, :equals?) do
- nil | 'different location fp' | 'identifier fp' | 'different identifier fp' | false
- 'location fp' | nil | 'identifier fp' | 'different identifier fp' | false
- 'location fp' | 'different location fp' | nil | 'different identifier fp' | false
- 'location fp' | 'different location fp' | 'identifier fp' | nil | false
- nil | nil | 'identifier fp' | 'identifier fp' | false
- 'location fp' | 'location fp' | nil | nil | false
- nil | nil | nil | nil | false
- 'location fp' | 'different location fp' | 'identifier fp' | 'different identifier fp' | false
- 'location fp' | 'different location fp' | 'identifier fp' | 'identifier fp' | false
- 'location fp' | 'location fp' | 'identifier fp' | 'different identifier fp' | false
- 'location fp' | 'location fp' | 'identifier fp' | 'identifier fp' | true
- end
-
- with_them do
- let(:finding_key_1) do
- build(:ci_reports_security_finding_key,
- location_fingerprint: location_fp_1,
- identifier_fingerprint: identifier_fp_1)
+ context 'when the comparison is done between FindingKey instances' do
+ where(:location_fp_1, :location_fp_2, :identifier_fp_1, :identifier_fp_2, :equals?) do
+ nil | 'different location fp' | 'identifier fp' | 'different identifier fp' | false
+ 'location fp' | nil | 'identifier fp' | 'different identifier fp' | false
+ 'location fp' | 'different location fp' | nil | 'different identifier fp' | false
+ 'location fp' | 'different location fp' | 'identifier fp' | nil | false
+ nil | nil | 'identifier fp' | 'identifier fp' | false
+ 'location fp' | 'location fp' | nil | nil | false
+ nil | nil | nil | nil | false
+ 'location fp' | 'different location fp' | 'identifier fp' | 'different identifier fp' | false
+ 'location fp' | 'different location fp' | 'identifier fp' | 'identifier fp' | false
+ 'location fp' | 'location fp' | 'identifier fp' | 'different identifier fp' | false
+ 'location fp' | 'location fp' | 'identifier fp' | 'identifier fp' | true
end
- let(:finding_key_2) do
- build(:ci_reports_security_finding_key,
- location_fingerprint: location_fp_2,
- identifier_fingerprint: identifier_fp_2)
+ with_them do
+ let(:finding_key_1) do
+ build(:ci_reports_security_finding_key,
+ location_fingerprint: location_fp_1,
+ identifier_fingerprint: identifier_fp_1)
+ end
+
+ let(:finding_key_2) do
+ build(:ci_reports_security_finding_key,
+ location_fingerprint: location_fp_2,
+ identifier_fingerprint: identifier_fp_2)
+ end
+
+ subject { finding_key_1 == finding_key_2 }
+
+ it { is_expected.to be(equals?) }
end
+ end
+
+ context 'when the comparison is not done between FindingKey instances' do
+ let(:finding_key) { build(:ci_reports_security_finding_key) }
+ let(:uuid) { SecureRandom.uuid }
- subject { finding_key_1 == finding_key_2 }
+ subject { finding_key == uuid }
- it { is_expected.to be(equals?) }
+ it { is_expected.to be_falsey }
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
index f8df2266689..8204b104832 100644
--- a/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe '5-Minute-Production-App.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
diff --git a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
index ca6f6872f89..27de8324206 100644
--- a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
index bd701aec8fc..21052f03cb8 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
index 64243f2d205..d88d9782021 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
index 789f694b4b4..b657f73fa77 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project, refind: true) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
@@ -66,6 +66,11 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
expect(build_names).not_to include('review')
end
+ it 'when CI_DEPLOY_FREEZE is present' do
+ create(:ci_variable, project: project, key: 'CI_DEPLOY_FREEZE', value: 'true')
+ expect(build_names).to eq %w(placeholder)
+ end
+
it 'when CANARY_ENABLED' do
create(:ci_variable, project: project, key: 'CANARY_ENABLED', value: 'true')
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
index b9256ece78b..0f97bc06a4e 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:default_branch) { 'main' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
index db9d7496251..a92a8397e96 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
index 4685d843ce0..5e9224cebd9 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Terraform/Base.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
index e35f2eabe8e..0ab81f97f20 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
index 004261bc617..d6c7cd32f79 100644
--- a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 64ef6ecd7f8..6a4be1fa072 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
@@ -276,7 +276,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
with_them do
let(:project) { create(:project, :custom_repo, files: files) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: default_branch ) }
let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
index 3d97b47473d..de94eec09fe 100644
--- a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Flutter.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:pipeline_branch) { 'master' }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
index c7dbbea4622..ebf52e6d65a 100644
--- a/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Kaniko.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:pipeline_branch) { 'master' }
let(:project) { create(:project, :custom_repo, files: { 'Dockerfile' => 'FROM alpine:latest' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index ea954690133..d86a3a67823 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'npm.gitlab-ci.yml' do
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
let(:modified_files) { %w[package.json] }
let(:project) { create(:project, :custom_repo, files: repo_files) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:pipeline_branch) { project.default_branch }
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
diff --git a/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
index 936cd6ac8aa..346ab9f7af7 100644
--- a/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Terraform.gitlab-ci.yml' do
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index fd5d5d6af7f..6c06403adff 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/variables/builder/instance_spec.rb b/spec/lib/gitlab/ci/variables/builder/instance_spec.rb
new file mode 100644
index 00000000000..7abda2bd615
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/builder/instance_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Builder::Instance do
+ let_it_be(:variable) { create(:ci_instance_variable, protected: false) }
+ let_it_be(:protected_variable) { create(:ci_instance_variable, protected: true) }
+
+ let(:builder) { described_class.new }
+
+ describe '#secret_variables' do
+ let(:variable_item) { item(variable) }
+ let(:protected_variable_item) { item(protected_variable) }
+
+ subject do
+ builder.secret_variables(protected_ref: protected_ref)
+ end
+
+ context 'when the ref is protected' do
+ let(:protected_ref) { true }
+
+ it 'contains all the variables' do
+ is_expected.to contain_exactly(variable_item, protected_variable_item)
+ end
+ end
+
+ context 'when the ref is not protected' do
+ let(:protected_ref) { false }
+
+ it 'contains only unprotected variables' do
+ is_expected.to contain_exactly(variable_item)
+ end
+ end
+ end
+
+ def item(variable)
+ Gitlab::Ci::Variables::Collection::Item.fabricate(variable)
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/builder/project_spec.rb b/spec/lib/gitlab/ci/variables/builder/project_spec.rb
new file mode 100644
index 00000000000..b64b6ea98e2
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/builder/project_spec.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Builder::Project do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:builder) { described_class.new(project) }
+
+ describe '#secret_variables' do
+ let(:environment) { '*' }
+ let(:protected_ref) { false }
+
+ let_it_be(:variable) do
+ create(:ci_variable,
+ value: 'secret',
+ project: project)
+ end
+
+ let_it_be(:protected_variable) do
+ create(:ci_variable, :protected,
+ value: 'protected',
+ project: project)
+ end
+
+ let(:variable_item) { item(variable) }
+ let(:protected_variable_item) { item(protected_variable) }
+
+ subject do
+ builder.secret_variables(
+ environment: environment,
+ protected_ref: protected_ref)
+ end
+
+ context 'when the ref is protected' do
+ let(:protected_ref) { true }
+
+ it 'contains all the variables' do
+ is_expected.to contain_exactly(variable_item, protected_variable_item)
+ end
+ end
+
+ context 'when the ref is not protected' do
+ let(:protected_ref) { false }
+
+ it 'contains only the unprotected variables' do
+ is_expected.to contain_exactly(variable_item)
+ end
+ end
+
+ context 'when environment name is specified' do
+ let(:environment) { 'review/name' }
+
+ before do
+ Ci::Variable.update_all(environment_scope: environment_scope)
+ end
+
+ context 'when environment scope is exactly matched' do
+ let(:environment_scope) { 'review/name' }
+
+ it { is_expected.to contain_exactly(variable_item) }
+ end
+
+ context 'when environment scope is matched by wildcard' do
+ let(:environment_scope) { 'review/*' }
+
+ it { is_expected.to contain_exactly(variable_item) }
+ end
+
+ context 'when environment scope does not match' do
+ let(:environment_scope) { 'review/*/special' }
+
+ it { is_expected.not_to contain_exactly(variable_item) }
+ end
+
+ context 'when environment scope has _' do
+ let(:environment_scope) { '*_*' }
+
+ it 'does not treat it as wildcard' do
+ is_expected.not_to contain_exactly(variable_item)
+ end
+ end
+
+ context 'when environment name contains underscore' do
+ let(:environment) { 'foo_bar/test' }
+ let(:environment_scope) { 'foo_bar/*' }
+
+ it 'matches literally for _' do
+ is_expected.to contain_exactly(variable_item)
+ end
+ end
+
+ # The environment name and scope cannot have % at the moment,
+ # but we're considering relaxing it and we should also make sure
+ # it doesn't break in case some data sneaked in somehow as we're
+ # not checking this integrity in database level.
+ context 'when environment scope has %' do
+ let(:environment_scope) { '*%*' }
+
+ it 'does not treat it as wildcard' do
+ is_expected.not_to contain_exactly(variable_item)
+ end
+ end
+
+ context 'when environment name contains a percent' do
+ let(:environment) { 'foo%bar/test' }
+ let(:environment_scope) { 'foo%bar/*' }
+
+ it 'matches literally for _' do
+ is_expected.to contain_exactly(variable_item)
+ end
+ end
+ end
+
+ context 'when variables with the same name have different environment scopes' do
+ let(:environment) { 'review/name' }
+
+ let_it_be(:partially_matched_variable) do
+ create(:ci_variable,
+ key: variable.key,
+ value: 'partial',
+ environment_scope: 'review/*',
+ project: project)
+ end
+
+ let_it_be(:perfectly_matched_variable) do
+ create(:ci_variable,
+ key: variable.key,
+ value: 'prefect',
+ environment_scope: 'review/name',
+ project: project)
+ end
+
+ it 'puts variables matching environment scope more in the end' do
+ variables_collection = Gitlab::Ci::Variables::Collection.new([
+ variable,
+ partially_matched_variable,
+ perfectly_matched_variable
+ ]).to_runner_variables
+
+ expect(subject.to_runner_variables).to eq(variables_collection)
+ end
+ end
+ end
+
+ def item(variable)
+ Gitlab::Ci::Variables::Collection::Item.fabricate(variable)
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 8a87cbe45c1..6e144d62ac0 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -3,10 +3,11 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Variables::Builder do
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
- let_it_be(:user) { project.owner }
- let_it_be(:job) do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, namespace: group) }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:job) do
create(:ci_build,
pipeline: pipeline,
user: user,
@@ -153,7 +154,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
before do
allow(builder).to receive(:predefined_variables) { [var('A', 1), var('B', 1)] }
- allow(project).to receive(:predefined_variables) { [var('B', 2), var('C', 2)] }
+ allow(pipeline.project).to receive(:predefined_variables) { [var('B', 2), var('C', 2)] }
allow(pipeline).to receive(:predefined_variables) { [var('C', 3), var('D', 3)] }
allow(job).to receive(:runner) { double(predefined_variables: [var('D', 4), var('E', 4)]) }
allow(builder).to receive(:kubernetes_variables) { [var('E', 5), var('F', 5)] }
@@ -201,4 +202,240 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
end
end
end
+
+ describe '#user_variables' do
+ context 'with user' do
+ subject { builder.user_variables(user).to_hash }
+
+ let(:expected_variables) do
+ {
+ 'GITLAB_USER_EMAIL' => user.email,
+ 'GITLAB_USER_ID' => user.id.to_s,
+ 'GITLAB_USER_LOGIN' => user.username,
+ 'GITLAB_USER_NAME' => user.name
+ }
+ end
+
+ it { is_expected.to eq(expected_variables) }
+ end
+
+ context 'without user' do
+ subject { builder.user_variables(nil).to_hash }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe '#kubernetes_variables' do
+ let(:service) { double(execute: template) }
+ let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) }
+ let(:template_valid) { true }
+
+ subject { builder.kubernetes_variables(job) }
+
+ before do
+ allow(Ci::GenerateKubeconfigService).to receive(:new).with(job).and_return(service)
+ end
+
+ it { is_expected.to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
+
+ context 'generated config is invalid' do
+ let(:template_valid) { false }
+
+ it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
+ end
+ end
+
+ describe '#deployment_variables' do
+ let(:environment) { 'production' }
+ let(:kubernetes_namespace) { 'namespace' }
+ let(:project_variables) { double }
+
+ subject { builder.deployment_variables(environment: environment, job: job) }
+
+ before do
+ allow(job).to receive(:expanded_kubernetes_namespace)
+ .and_return(kubernetes_namespace)
+
+ allow(project).to receive(:deployment_variables)
+ .with(environment: environment, kubernetes_namespace: kubernetes_namespace)
+ .and_return(project_variables)
+ end
+
+ context 'environment is nil' do
+ let(:environment) { nil }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ shared_examples "secret CI variables" do
+ context 'when ref is branch' do
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: job.ref, project: project)
+ end
+
+ it { is_expected.to contain_exactly(protected_variable_item, unprotected_variable_item) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.to contain_exactly(unprotected_variable_item) }
+ end
+ end
+
+ context 'when ref is tag' do
+ before do
+ job.update!(ref: 'v1.1.0', tag: true)
+ pipeline.update!(ref: 'v1.1.0', tag: true)
+ end
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_tag, project: project, name: 'v*')
+ end
+
+ it { is_expected.to contain_exactly(protected_variable_item, unprotected_variable_item) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.to contain_exactly(unprotected_variable_item) }
+ end
+ end
+
+ context 'when ref is merge request' do
+ let_it_be(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_project: project) }
+ let_it_be(:pipeline) { merge_request.pipelines_for_merge_request.first }
+ let_it_be(:job) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: merge_request.source_branch, project: project)
+ end
+
+ it 'does not return protected variables as it is not supported for merge request pipelines' do
+ is_expected.to contain_exactly(unprotected_variable_item)
+ end
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.to contain_exactly(unprotected_variable_item) }
+ end
+ end
+ end
+
+ describe '#secret_instance_variables' do
+ subject { builder.secret_instance_variables }
+
+ let_it_be(:protected_variable) { create(:ci_instance_variable, protected: true) }
+ let_it_be(:unprotected_variable) { create(:ci_instance_variable, protected: false) }
+
+ let(:protected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable) }
+ let(:unprotected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable) }
+
+ include_examples "secret CI variables"
+ end
+
+ describe '#secret_group_variables' do
+ subject { builder.secret_group_variables(ref: job.git_ref, environment: job.expanded_environment_name) }
+
+ let_it_be(:protected_variable) { create(:ci_group_variable, protected: true, group: group) }
+ let_it_be(:unprotected_variable) { create(:ci_group_variable, protected: false, group: group) }
+
+ let(:protected_variable_item) { protected_variable }
+ let(:unprotected_variable_item) { unprotected_variable }
+
+ include_examples "secret CI variables"
+ end
+
+ describe '#secret_project_variables' do
+ let_it_be(:protected_variable) { create(:ci_variable, protected: true, project: project) }
+ let_it_be(:unprotected_variable) { create(:ci_variable, protected: false, project: project) }
+
+ let(:ref) { job.git_ref }
+ let(:environment) { job.expanded_environment_name }
+
+ subject { builder.secret_project_variables(ref: ref, environment: environment) }
+
+ context 'with ci_variables_builder_memoize_secret_variables disabled' do
+ before do
+ stub_feature_flags(ci_variables_builder_memoize_secret_variables: false)
+ end
+
+ let(:protected_variable_item) { protected_variable }
+ let(:unprotected_variable_item) { unprotected_variable }
+
+ include_examples "secret CI variables"
+ end
+
+ context 'with ci_variables_builder_memoize_secret_variables enabled' do
+ before do
+ stub_feature_flags(ci_variables_builder_memoize_secret_variables: true)
+ end
+
+ let(:protected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable) }
+ let(:unprotected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable) }
+
+ include_examples "secret CI variables"
+
+ context 'variables memoization' do
+ let_it_be(:scoped_variable) { create(:ci_variable, project: project, environment_scope: 'scoped') }
+
+ let(:scoped_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(scoped_variable) }
+
+ context 'with protected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(true)
+
+ expect_next_instance_of(described_class::Project) do |project_variables_builder|
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'production', protected_ref: true)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_project_variables(ref: ref, environment: 'production'))
+ .to contain_exactly(unprotected_variable_item, protected_variable_item)
+ end
+ end
+ end
+
+ context 'with unprotected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(false)
+
+ expect_next_instance_of(described_class::Project) do |project_variables_builder|
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: nil, protected_ref: false)
+ .once
+ .and_call_original
+
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'scoped', protected_ref: false)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_project_variables(ref: 'other', environment: nil))
+ .to contain_exactly(unprotected_variable_item)
+
+ expect(builder.secret_project_variables(ref: 'other', environment: 'scoped'))
+ .to contain_exactly(unprotected_variable_item, scoped_variable_item)
+ end
+ end
+ 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 20af84ce648..5f46607b042 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -9,6 +9,10 @@ module Gitlab
subject { described_class.new(config, user: nil).execute }
+ before do
+ stub_feature_flags(allow_unsafe_ruby_regexp: false)
+ end
+
shared_examples 'returns errors' do |error_message|
it 'adds a message when an error is encountered' do
expect(subject.errors).to include(error_message)
@@ -609,13 +613,13 @@ module Gitlab
context 'when it is an array of integers' do
let(:only) { [1, 1] }
- it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regexps'
+ it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regular expressions using re2 syntax'
end
context 'when it is invalid regex' do
let(:only) { ["/*invalid/"] }
- it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regexps'
+ it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regular expressions using re2 syntax'
end
end
@@ -633,13 +637,13 @@ module Gitlab
context 'when it is an array of integers' do
let(:except) { [1, 1] }
- it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regexps'
+ it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regular expressions using re2 syntax'
end
context 'when it is invalid regex' do
let(:except) { ["/*invalid/"] }
- it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regexps'
+ it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regular expressions using re2 syntax'
end
end
end
@@ -710,16 +714,16 @@ module Gitlab
end
end
- context 'when script is array of arrays of strings' do
+ context 'when script is nested arrays of strings' do
let(:config) do
{
- before_script: [["global script", "echo 1"], ["ls"], "pwd"],
+ before_script: [[["global script"], "echo 1"], "echo 2", ["ls"], "pwd"],
test: { script: ["script"] }
}
end
it "return commands with scripts concatenated" do
- expect(subject[:options][:before_script]).to eq(["global script", "echo 1", "ls", "pwd"])
+ expect(subject[:options][:before_script]).to eq(["global script", "echo 1", "echo 2", "ls", "pwd"])
end
end
end
@@ -737,15 +741,15 @@ module Gitlab
end
end
- context 'when script is array of arrays of strings' do
+ context 'when script is nested arrays of strings' do
let(:config) do
{
- test: { script: [["script"], ["echo 1"], "ls"] }
+ test: { script: [[["script"], "echo 1", "echo 2"], "ls"] }
}
end
it "return commands with scripts concatenated" do
- expect(subject[:options][:script]).to eq(["script", "echo 1", "ls"])
+ expect(subject[:options][:script]).to eq(["script", "echo 1", "echo 2", "ls"])
end
end
end
@@ -790,16 +794,16 @@ module Gitlab
end
end
- context 'when script is array of arrays of strings' do
+ context 'when script is nested arrays of strings' do
let(:config) do
{
- after_script: [["global script", "echo 1"], ["ls"], "pwd"],
+ after_script: [[["global script"], "echo 1"], "echo 2", ["ls"], "pwd"],
test: { script: ["script"] }
}
end
it "return after_script in options" do
- expect(subject[:options][:after_script]).to eq(["global script", "echo 1", "ls", "pwd"])
+ expect(subject[:options][:after_script]).to eq(["global script", "echo 1", "echo 2", "ls", "pwd"])
end
end
end
@@ -2469,40 +2473,16 @@ module Gitlab
it_behaves_like 'returns errors', 'jobs:rspec:tags config should be an array of strings'
end
- context 'returns errors if before_script parameter is invalid' do
- let(:config) { YAML.dump({ before_script: "bundle update", rspec: { script: "test" } }) }
-
- it_behaves_like 'returns errors', 'before_script config should be an array containing strings and arrays of strings'
- end
-
context 'returns errors if job before_script parameter is not an array of strings' do
let(:config) { YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } }) }
- it_behaves_like 'returns errors', 'jobs:rspec:before_script config should be an array containing strings and arrays of strings'
- end
-
- context 'returns errors if job before_script parameter is multi-level nested array of strings' do
- let(:config) { YAML.dump({ rspec: { script: "test", before_script: [["ls", ["pwd"]], "test"] } }) }
-
- it_behaves_like 'returns errors', 'jobs:rspec:before_script config should be an array containing strings and arrays of strings'
- end
-
- context 'returns errors if after_script parameter is invalid' do
- let(:config) { YAML.dump({ after_script: "bundle update", rspec: { script: "test" } }) }
-
- it_behaves_like 'returns errors', 'after_script config should be an array containing strings and arrays of strings'
+ it_behaves_like 'returns errors', 'jobs:rspec:before_script config should be a string or a nested array of strings up to 10 levels deep'
end
context 'returns errors if job after_script parameter is not an array of strings' do
let(:config) { YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } }) }
- it_behaves_like 'returns errors', 'jobs:rspec:after_script config should be an array containing strings and arrays of strings'
- end
-
- context 'returns errors if job after_script parameter is multi-level nested array of strings' do
- let(:config) { YAML.dump({ rspec: { script: "test", after_script: [["ls", ["pwd"]], "test"] } }) }
-
- it_behaves_like 'returns errors', 'jobs:rspec:after_script config should be an array containing strings and arrays of strings'
+ it_behaves_like 'returns errors', 'jobs:rspec:after_script config should be a string or a nested array of strings up to 10 levels deep'
end
context 'returns errors if image parameter is invalid' do
diff --git a/spec/lib/gitlab/cluster/lifecycle_events_spec.rb b/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
index 4ed68d54680..5eea78acd98 100644
--- a/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
+++ b/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'rspec-parameterized'
+require 'spec_helper'
RSpec.describe Gitlab::Cluster::LifecycleEvents do
# we create a new instance to ensure that we do not touch existing hooks
diff --git a/spec/lib/gitlab/config/entry/factory_spec.rb b/spec/lib/gitlab/config/entry/factory_spec.rb
index 260b5cf0ade..be4dfd31651 100644
--- a/spec/lib/gitlab/config/entry/factory_spec.rb
+++ b/spec/lib/gitlab/config/entry/factory_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Config::Entry::Factory do
describe '#create!' do
before do
- stub_const('Script', Class.new(Gitlab::Config::Entry::Node))
- Script.class_eval do
+ stub_const('Commands', Class.new(Gitlab::Config::Entry::Node))
+ Commands.class_eval do
include Gitlab::Config::Entry::Validatable
validations do
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Config::Entry::Factory do
end
end
- let(:entry) { Script }
+ let(:entry) { Commands }
let(:factory) { described_class.new(entry) }
context 'when setting a concrete value' do
diff --git a/spec/lib/gitlab/console_spec.rb b/spec/lib/gitlab/console_spec.rb
new file mode 100644
index 00000000000..f043433b4c5
--- /dev/null
+++ b/spec/lib/gitlab/console_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Console do
+ describe '.welcome!' do
+ context 'when running in the Rails console' do
+ before do
+ allow(Gitlab::Runtime).to receive(:console?).and_return(true)
+ allow(Gitlab::Metrics::BootTimeTracker.instance).to receive(:startup_time).and_return(42)
+ end
+
+ shared_examples 'console messages' do
+ it 'prints system info' do
+ expect($stdout).to receive(:puts).ordered.with(include("--"))
+ expect($stdout).to receive(:puts).ordered.with(include("Ruby:"))
+ expect($stdout).to receive(:puts).ordered.with(include("GitLab:"))
+ expect($stdout).to receive(:puts).ordered.with(include("GitLab Shell:"))
+ expect($stdout).to receive(:puts).ordered.with(include("PostgreSQL:"))
+ expect($stdout).to receive(:puts).ordered.with(include("--"))
+ expect($stdout).not_to receive(:puts).ordered
+
+ described_class.welcome!
+ end
+ end
+
+ # This is to add line coverage, not to actually verify behavior on macOS.
+ context 'on darwin' do
+ before do
+ stub_const('RUBY_PLATFORM', 'x86_64-darwin-19')
+ end
+
+ it_behaves_like 'console messages'
+ end
+
+ it_behaves_like 'console messages'
+ end
+
+ context 'when not running in the Rails console' do
+ before do
+ allow(Gitlab::Runtime).to receive(:console?).and_return(false)
+ end
+
+ it 'does not print anything' do
+ expect($stdout).not_to receive(:puts)
+
+ described_class.welcome!
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb
index 46c33d7b7b2..73540a9b0f3 100644
--- a/spec/lib/gitlab/current_settings_spec.rb
+++ b/spec/lib/gitlab/current_settings_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Gitlab::CurrentSettings do
allow(Gitlab::Runtime).to receive(:rake?).and_return(true)
# For some reason, `allow(described_class).to receive(:connect_to_db?).and_return(false)` causes issues
# during the initialization phase of the test suite, so instead let's mock the internals of it
- allow(ActiveRecord::Base.connection).to receive(:active?).and_return(false)
+ allow(ApplicationSetting.connection).to receive(:active?).and_return(false)
end
context 'and no settings in cache' do
@@ -150,8 +150,8 @@ RSpec.describe Gitlab::CurrentSettings do
it 'fetches the settings from cache' do
# For some reason, `allow(described_class).to receive(:connect_to_db?).and_return(true)` causes issues
# during the initialization phase of the test suite, so instead let's mock the internals of it
- expect(ActiveRecord::Base.connection).not_to receive(:active?)
- expect(ActiveRecord::Base.connection).not_to receive(:cached_table_exists?)
+ expect(ApplicationSetting.connection).not_to receive(:active?)
+ expect(ApplicationSetting.connection).not_to receive(:cached_table_exists?)
expect_any_instance_of(ActiveRecord::MigrationContext).not_to receive(:needs_migration?)
expect(ActiveRecord::QueryRecorder.new { described_class.current_application_settings }.count).to eq(0)
end
@@ -159,8 +159,8 @@ RSpec.describe Gitlab::CurrentSettings do
context 'and no settings in cache' do
before do
- allow(ActiveRecord::Base.connection).to receive(:active?).and_return(true)
- allow(ActiveRecord::Base.connection).to receive(:cached_table_exists?).with('application_settings').and_return(true)
+ allow(ApplicationSetting.connection).to receive(:active?).and_return(true)
+ allow(ApplicationSetting.connection).to receive(:cached_table_exists?).with('application_settings').and_return(true)
end
context 'with RequestStore enabled', :request_store do
@@ -181,7 +181,7 @@ RSpec.describe Gitlab::CurrentSettings do
context 'when ApplicationSettings does not have a primary key' do
before do
- allow(ActiveRecord::Base.connection).to receive(:primary_key).with('application_settings').and_return(nil)
+ allow(ApplicationSetting.connection).to receive(:primary_key).with('application_settings').and_return(nil)
end
it 'raises an exception if ApplicationSettings does not have a primary key' do
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 8053f5261c0..7173ea43450 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -15,6 +15,13 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
let(:stage_summary) { described_class.new(project, **args).data }
+ describe '#identifier' do
+ it 'returns identifiers for each metric' do
+ identifiers = stage_summary.pluck(:identifier)
+ expect(identifiers).to eq(%i[issues commits deploys deployment_frequency])
+ end
+ end
+
describe "#new_issues" do
subject { stage_summary.first }
diff --git a/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb b/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb
index e96862fbc2d..66983733411 100644
--- a/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Database::BackgroundMigration::BatchMetrics do
let(:batch_metrics) { described_class.new }
diff --git a/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb b/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb
index 95863ce3765..c367f4a4493 100644
--- a/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb
@@ -6,7 +6,11 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchOptimizer do
describe '#optimize' do
subject { described_class.new(migration, number_of_jobs: number_of_jobs, ema_alpha: ema_alpha).optimize! }
- let(:migration) { create(:batched_background_migration, batch_size: batch_size, sub_batch_size: 100, interval: 120) }
+ let(:migration_params) { {} }
+ let(:migration) do
+ params = { batch_size: batch_size, sub_batch_size: 100, interval: 120 }.merge(migration_params)
+ create(:batched_background_migration, params)
+ end
let(:batch_size) { 10_000 }
@@ -87,6 +91,17 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchOptimizer do
expect { subject }.to change { migration.reload.batch_size }.to(2_000_000)
end
+
+ context 'when max_batch_size is set' do
+ let(:max_batch_size) { 10000 }
+ let(:migration_params) { { max_batch_size: max_batch_size } }
+
+ it 'caps the batch size at max_batch_size' do
+ mock_efficiency(0.7)
+
+ expect { subject }.to change { migration.reload.batch_size }.to(max_batch_size)
+ end
+ end
end
context 'reaching the lower limit for the batch size' do
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 c4364826ee2..7338ea657b9 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -7,18 +7,85 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
describe 'associations' do
it { is_expected.to belong_to(:batched_migration).with_foreign_key(:batched_background_migration_id) }
+ it { is_expected.to have_many(:batched_job_transition_logs).with_foreign_key(:batched_background_migration_job_id) }
+ end
+
+ describe 'state machine' do
+ let_it_be(:job) { create(:batched_background_migration_job, :failed) }
+
+ context 'when a job is running' do
+ it 'logs the transition' do
+ expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :running, previous_state: :failed } )
+
+ expect { job.run! }.to change(job, :started_at)
+ end
+ end
+
+ context 'when a job succeed' do
+ let(:job) { create(:batched_background_migration_job, :running) }
+
+ it 'logs the transition' do
+ expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :succeeded, previous_state: :running } )
+
+ job.succeed!
+ end
+
+ it 'updates the finished_at' do
+ expect { job.succeed! }.to change(job, :finished_at).from(nil).to(Time)
+ end
+
+ it 'creates a new transition log' do
+ job.succeed!
+
+ transition_log = job.batched_job_transition_logs.first
+
+ expect(transition_log.next_status).to eq('succeeded')
+ expect(transition_log.exception_class).to be_nil
+ expect(transition_log.exception_message).to be_nil
+ end
+ end
+
+ context 'when a job fails' do
+ let(:job) { create(:batched_background_migration_job, :running) }
+
+ it 'logs the transition' do
+ expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :failed, previous_state: :running } )
+
+ job.failure!
+ end
+
+ it 'tracks the exception' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(RuntimeError, { batched_job_id: job.id } )
+
+ job.failure!(error: RuntimeError.new)
+ end
+
+ it 'updates the finished_at' do
+ expect { job.failure! }.to change(job, :finished_at).from(nil).to(Time)
+ end
+
+ it 'creates a new transition log' do
+ job.failure!(error: RuntimeError.new)
+
+ transition_log = job.batched_job_transition_logs.first
+
+ expect(transition_log.next_status).to eq('failed')
+ expect(transition_log.exception_class).to eq('RuntimeError')
+ expect(transition_log.exception_message).to eq('RuntimeError')
+ end
+ end
end
describe 'scopes' do
let_it_be(:fixed_time) { Time.new(2021, 04, 27, 10, 00, 00, 00) }
- let_it_be(:pending_job) { create(:batched_background_migration_job, status: :pending, updated_at: fixed_time) }
- let_it_be(:running_job) { create(:batched_background_migration_job, status: :running, updated_at: fixed_time) }
- let_it_be(:stuck_job) { create(:batched_background_migration_job, status: :pending, updated_at: fixed_time - described_class::STUCK_JOBS_TIMEOUT) }
- let_it_be(:failed_job) { create(:batched_background_migration_job, status: :failed, attempts: 1) }
+ let_it_be(:pending_job) { create(:batched_background_migration_job, :pending, updated_at: fixed_time) }
+ let_it_be(:running_job) { create(:batched_background_migration_job, :running, updated_at: fixed_time) }
+ let_it_be(:stuck_job) { create(:batched_background_migration_job, :pending, updated_at: fixed_time - described_class::STUCK_JOBS_TIMEOUT) }
+ let_it_be(:failed_job) { create(:batched_background_migration_job, :failed, attempts: 1) }
- let!(:max_attempts_failed_job) { create(:batched_background_migration_job, status: :failed, attempts: described_class::MAX_ATTEMPTS) }
- let!(:succeeded_job) { create(:batched_background_migration_job, status: :succeeded) }
+ let!(:max_attempts_failed_job) { create(:batched_background_migration_job, :failed, attempts: described_class::MAX_ATTEMPTS) }
+ let!(:succeeded_job) { create(:batched_background_migration_job, :succeeded) }
before do
travel_to fixed_time
@@ -82,10 +149,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
subject { job.time_efficiency }
let(:migration) { build(:batched_background_migration, interval: 120.seconds) }
- let(:job) { build(:batched_background_migration_job, status: :succeeded, batched_migration: migration) }
+ let(:job) { build(:batched_background_migration_job, :succeeded, batched_migration: migration) }
context 'when job has not yet succeeded' do
- let(:job) { build(:batched_background_migration_job, status: :running) }
+ let(:job) { build(:batched_background_migration_job, :running) }
it 'returns nil' do
expect(subject).to be_nil
@@ -130,7 +197,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
describe '#split_and_retry!' do
- let!(:job) { create(:batched_background_migration_job, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) }
+ let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 10, min_value: 6, max_value: 15, attempts: 3) }
context 'when job can be split' do
before do
@@ -146,7 +213,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
min_value: 6,
max_value: 10,
batch_size: 5,
- status: 'failed',
+ status_name: :failed,
attempts: 0,
started_at: nil,
finished_at: nil,
@@ -160,7 +227,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
min_value: 11,
max_value: 15,
batch_size: 5,
- status: 'failed',
+ status_name: :failed,
attempts: 0,
started_at: nil,
finished_at: nil,
@@ -177,7 +244,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
context 'when job is not failed' do
- let!(:job) { create(:batched_background_migration_job, status: :succeeded) }
+ let!(:job) { create(:batched_background_migration_job, :succeeded) }
it 'raises an exception' do
expect { job.split_and_retry! }.to raise_error 'Only failed jobs can be split'
@@ -185,7 +252,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
context 'when batch size is already 1' do
- let!(:job) { create(:batched_background_migration_job, batch_size: 1, status: :failed) }
+ let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 1) }
it 'raises an exception' do
expect { job.split_and_retry! }.to raise_error 'Job cannot be split further'
@@ -204,7 +271,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
expect(job.batch_size).to eq(5)
expect(job.attempts).to eq(0)
- expect(job.status).to eq('failed')
+ expect(job.status_name).to eq(:failed)
end
end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_transition_log_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_transition_log_spec.rb
new file mode 100644
index 00000000000..c42a0fc5e05
--- /dev/null
+++ b/spec/lib/gitlab/database/background_migration/batched_job_transition_log_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog, type: :model do
+ describe 'associations' do
+ it { is_expected.to belong_to(:batched_job).with_foreign_key(:batched_background_migration_job_id) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:previous_status) }
+ it { is_expected.to validate_presence_of(:next_status) }
+ it { is_expected.to validate_presence_of(:batched_job) }
+ it { is_expected.to validate_length_of(:exception_class).is_at_most(100) }
+ it { is_expected.to validate_length_of(:exception_message).is_at_most(1000) }
+ it { is_expected.to define_enum_for(:previous_status).with_values(%i(pending running failed succeeded)).with_prefix }
+ it { is_expected.to define_enum_for(:next_status).with_values(%i(pending running failed succeeded)).with_prefix }
+ end
+end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
index 04c18a98ee6..bb2c6b9a3ae 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
@@ -96,13 +96,12 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
end
let!(:previous_job) do
- create(:batched_background_migration_job,
+ create(:batched_background_migration_job, :succeeded,
batched_migration: migration,
min_value: event1.id,
max_value: event2.id,
batch_size: 2,
- sub_batch_size: 1,
- status: :succeeded
+ sub_batch_size: 1
)
end
@@ -144,7 +143,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
context 'when migration has failed jobs' do
before do
- previous_job.update!(status: :failed)
+ previous_job.failure!
end
it 'retries the failed job' do
@@ -172,7 +171,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
context 'when migration has stuck jobs' do
before do
- previous_job.update!(status: :running, updated_at: 1.hour.ago - Gitlab::Database::BackgroundMigration::BatchedJob::STUCK_JOBS_TIMEOUT)
+ previous_job.update!(status_event: 'run', updated_at: 1.hour.ago - Gitlab::Database::BackgroundMigration::BatchedJob::STUCK_JOBS_TIMEOUT)
end
it 'retries the stuck job' do
@@ -186,7 +185,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
context 'when migration has possible stuck jobs' do
before do
- previous_job.update!(status: :running, updated_at: 1.hour.from_now - Gitlab::Database::BackgroundMigration::BatchedJob::STUCK_JOBS_TIMEOUT)
+ previous_job.update!(status_event: 'run', updated_at: 1.hour.from_now - Gitlab::Database::BackgroundMigration::BatchedJob::STUCK_JOBS_TIMEOUT)
end
it 'keeps the migration active' do
@@ -201,13 +200,13 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
context 'when the migration has batches to process and failed jobs' do
before do
migration.update!(max_value: event3.id)
- previous_job.update!(status: :failed)
+ previous_job.failure!
end
it 'runs next batch then retries the failed job' do
expect(migration_wrapper).to receive(:perform) do |job_record|
expect(job_record).to eq(job_relation.last)
- job_record.update!(status: :succeeded)
+ job_record.succeed!
end
expect { runner.run_migration_job(migration) }.to change { job_relation.count }.by(1)
@@ -264,12 +263,12 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
it 'runs all jobs inline until finishing the migration' do
expect(migration_wrapper).to receive(:perform) do |job_record|
expect(job_record).to eq(job_relation.first)
- job_record.update!(status: :succeeded)
+ job_record.succeed!
end
expect(migration_wrapper).to receive(:perform) do |job_record|
expect(job_record).to eq(job_relation.last)
- job_record.update!(status: :succeeded)
+ job_record.succeed!
end
expect { runner.run_entire_migration(migration) }.to change { job_relation.count }.by(2)
@@ -330,9 +329,9 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
pause_ms: 0
}
- create(:batched_background_migration_job, common_attributes.merge(status: :succeeded, min_value: 1, max_value: 2))
- create(:batched_background_migration_job, common_attributes.merge(status: :pending, min_value: 3, max_value: 4))
- create(:batched_background_migration_job, common_attributes.merge(status: :failed, min_value: 5, max_value: 6, attempts: 1))
+ create(:batched_background_migration_job, :succeeded, common_attributes.merge(min_value: 1, max_value: 2))
+ create(:batched_background_migration_job, :pending, common_attributes.merge(min_value: 3, max_value: 4))
+ create(:batched_background_migration_job, :failed, common_attributes.merge(min_value: 5, max_value: 6, attempts: 1))
end
it 'completes the migration' do
@@ -359,7 +358,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
context 'when migration fails to complete' do
it 'raises an error' do
- batched_migration.batched_jobs.failed.update_all(attempts: Gitlab::Database::BackgroundMigration::BatchedJob::MAX_ATTEMPTS)
+ batched_migration.batched_jobs.with_status(:failed).update_all(attempts: Gitlab::Database::BackgroundMigration::BatchedJob::MAX_ATTEMPTS)
expect do
runner.finalize(
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 01d61a525e6..ea4ba4dd137 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
context 'when there are failed jobs' do
let(:batched_migration) { create(:batched_background_migration, status: :active, total_tuple_count: 100) }
- let!(:batched_job) { create(:batched_background_migration_job, batched_migration: batched_migration, status: :failed) }
+ let!(:batched_job) { create(:batched_background_migration_job, :failed, batched_migration: batched_migration) }
it 'raises an exception' do
expect { batched_migration.finished! }.to raise_error(ActiveRecord::RecordInvalid)
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
context 'when the jobs are completed' do
let(:batched_migration) { create(:batched_background_migration, status: :active, total_tuple_count: 100) }
- let!(:batched_job) { create(:batched_background_migration_job, batched_migration: batched_migration, status: :succeeded) }
+ let!(:batched_job) { create(:batched_background_migration_job, :succeeded, batched_migration: batched_migration) }
it 'finishes the migration' do
batched_migration.finished!
@@ -64,7 +64,7 @@ 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)
+ create(:batched_background_migration_job, :succeeded, batched_migration: migration1, batch_size: 1000)
end
end
@@ -84,10 +84,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
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)
+ create(:batched_background_migration_job, :succeeded, batched_migration: migration1, batch_size: 1000)
+ create(:batched_background_migration_job, :failed, batched_migration: migration1, batch_size: 200)
+ create(:batched_background_migration_job, :succeeded, batched_migration: migration2, batch_size: 500)
+ create(:batched_background_migration_job, :running, batched_migration: migration2, batch_size: 200)
end
it 'returns totals from successful jobs' do
@@ -268,7 +268,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
subject(:retry_failed_jobs) { batched_migration.retry_failed_jobs! }
context 'when there are failed migration jobs' do
- let!(:batched_background_migration_job) { create(:batched_background_migration_job, batched_migration: batched_migration, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) }
+ let!(:batched_background_migration_job) { create(:batched_background_migration_job, :failed, batched_migration: batched_migration, batch_size: 10, min_value: 6, max_value: 15, attempts: 3) }
before do
allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
@@ -312,9 +312,9 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
let(:batched_migration) { create(:batched_background_migration) }
before do
- create_list(:batched_background_migration_job, 5, status: :succeeded, batch_size: 1_000, batched_migration: batched_migration)
- create_list(:batched_background_migration_job, 1, status: :running, batch_size: 1_000, batched_migration: batched_migration)
- create_list(:batched_background_migration_job, 1, status: :failed, batch_size: 1_000, batched_migration: batched_migration)
+ create_list(:batched_background_migration_job, 5, :succeeded, batch_size: 1_000, batched_migration: batched_migration)
+ create_list(:batched_background_migration_job, 1, :running, batch_size: 1_000, batched_migration: batched_migration)
+ create_list(:batched_background_migration_job, 1, :failed, batch_size: 1_000, batched_migration: batched_migration)
end
it 'sums the batch_size of succeeded jobs' do
@@ -347,7 +347,6 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
let_it_be(:common_attrs) do
{
- status: :succeeded,
batched_migration: migration,
finished_at: end_time
}
@@ -357,7 +356,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
subject { migration.smoothed_time_efficiency(number_of_jobs: 10) }
it 'returns nil' do
- create_list(:batched_background_migration_job, 9, **common_attrs)
+ create_list(:batched_background_migration_job, 9, :succeeded, **common_attrs)
expect(subject).to be_nil
end
@@ -369,6 +368,8 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
subject { migration.smoothed_time_efficiency(number_of_jobs: number_of_jobs) }
+ let!(:jobs) { create_list(:batched_background_migration_job, number_of_jobs, :succeeded, **common_attrs.merge(batched_migration: migration)) }
+
before do
expect(migration).to receive_message_chain(:batched_jobs, :successful_in_execution_order, :reverse_order, :limit, :with_preloads)
.and_return(jobs)
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
index c1183a15e37..4f5536d8771 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
@@ -35,8 +35,6 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
expect(job_instance).to receive(:perform)
expect(job_instance).to receive(:batch_metrics).and_return(test_metrics)
- expect(job_record).to receive(:update!).with(hash_including(attempts: 1, status: :running)).and_call_original
-
freeze_time do
subject
@@ -51,11 +49,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
context 'when running a job that failed previously' do
let!(:job_record) do
- create(:batched_background_migration_job,
+ create(:batched_background_migration_job, :failed,
batched_migration: active_migration,
pause_ms: pause_ms,
attempts: 1,
- status: :failed,
finished_at: 1.hour.ago,
metrics: { 'my_metrics' => 'some_value' }
)
@@ -67,10 +64,6 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
expect(job_instance).to receive(:perform)
expect(job_instance).to receive(:batch_metrics).and_return(updated_metrics)
- expect(job_record).to receive(:update!).with(
- hash_including(attempts: 2, status: :running, finished_at: nil, metrics: {})
- ).and_call_original
-
freeze_time do
subject
@@ -201,4 +194,44 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
it_behaves_like 'an error is raised', RuntimeError.new('Something broke!')
it_behaves_like 'an error is raised', SignalException.new('SIGTERM')
end
+
+ context 'when the batched background migration does not inherit from BaseJob' do
+ let(:migration_class) { Class.new }
+
+ before do
+ stub_const('Gitlab::BackgroundMigration::Foo', migration_class)
+ end
+
+ let(:connection) { double(:connection) }
+ let(:active_migration) { create(:batched_background_migration, :active, job_class_name: 'Foo') }
+ let!(:job_record) { create(:batched_background_migration_job, batched_migration: active_migration) }
+
+ it 'does not pass any argument' do
+ expect(Gitlab::BackgroundMigration::Foo).to receive(:new).with(no_args).and_return(job_instance)
+
+ expect(job_instance).to receive(:perform)
+
+ described_class.new(connection: connection).perform(job_record)
+ end
+ end
+
+ context 'when the batched background migration inherits from BaseJob' do
+ let(:connection) { double(:connection) }
+ let(:active_migration) { create(:batched_background_migration, :active, job_class_name: 'Foo') }
+ let!(:job_record) { create(:batched_background_migration_job, batched_migration: active_migration) }
+
+ let(:migration_class) { Class.new(::Gitlab::BackgroundMigration::BaseJob) }
+
+ before do
+ stub_const('Gitlab::BackgroundMigration::Foo', migration_class)
+ end
+
+ it 'passes the correct connection' do
+ expect(Gitlab::BackgroundMigration::Foo).to receive(:new).with(connection: connection).and_return(job_instance)
+
+ expect(job_instance).to receive(:perform)
+
+ described_class.new(connection: connection).perform(job_record)
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb b/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
index 0844616ee1c..31486240bfa 100644
--- a/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
+++ b/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
@@ -4,10 +4,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::DynamicModelHelpers do
let(:including_class) { Class.new.include(described_class) }
- let(:table_name) { 'projects' }
+ let(:table_name) { Project.table_name }
+ let(:connection) { Project.connection }
describe '#define_batchable_model' do
- subject { including_class.new.define_batchable_model(table_name) }
+ subject { including_class.new.define_batchable_model(table_name, connection: connection) }
it 'is an ActiveRecord model' do
expect(subject.ancestors).to include(ActiveRecord::Base)
@@ -40,7 +41,7 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
it 'iterates table in batches' do
each_batch_size = ->(&block) do
- subject.each_batch(table_name, of: 1) do |batch|
+ subject.each_batch(table_name, connection: connection, of: 1) do |batch|
block.call(batch.size)
end
end
@@ -56,7 +57,7 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
end
it 'raises an error' do
- expect { subject.each_batch(table_name, of: 1) { |batch| batch.size } }
+ expect { subject.each_batch(table_name, connection: connection, of: 1) { |batch| batch.size } }
.to raise_error(RuntimeError, /each_batch should not run inside a transaction/)
end
end
@@ -74,7 +75,7 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
end
it 'iterates table in batch ranges' do
- expect { |b| subject.each_batch_range(table_name, of: 1, &b) }
+ expect { |b| subject.each_batch_range(table_name, connection: connection, of: 1, &b) }
.to yield_successive_args(
[first_project.id, first_project.id],
[second_project.id, second_project.id]
@@ -82,13 +83,13 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
end
it 'yields only one batch if bigger than the table size' do
- expect { |b| subject.each_batch_range(table_name, of: 2, &b) }
+ expect { |b| subject.each_batch_range(table_name, connection: connection, 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)
+ subject.each_batch_range(table_name, connection: connection, scope: ->(table) { table.limit(1) }, of: 1, &b)
end
expect { |b| each_batch_limited.call(&b) }
@@ -102,7 +103,7 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
end
it 'raises an error' do
- expect { subject.each_batch_range(table_name, of: 1) { 1 } }
+ expect { subject.each_batch_range(table_name, connection: connection, of: 1) { 1 } }
.to raise_error(RuntimeError, /each_batch should not run inside a transaction/)
end
end
diff --git a/spec/lib/gitlab/database/each_database_spec.rb b/spec/lib/gitlab/database/each_database_spec.rb
index 9327fc4ff78..d526b3bc1ac 100644
--- a/spec/lib/gitlab/database/each_database_spec.rb
+++ b/spec/lib/gitlab/database/each_database_spec.rb
@@ -4,45 +4,97 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::EachDatabase do
describe '.each_database_connection' do
- let(:expected_connections) do
- Gitlab::Database.database_base_models.map { |name, model| [model.connection, name] }
+ before do
+ allow(Gitlab::Database).to receive(:database_base_models)
+ .and_return({ main: ActiveRecord::Base, ci: Ci::ApplicationRecord }.with_indifferent_access)
end
- it 'yields each connection after connecting SharedModel' do
- expected_connections.each do |connection, _|
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(connection).and_yield
- end
+ it 'yields each connection after connecting SharedModel', :add_ci_connection do
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection)
+ .with(ActiveRecord::Base.connection).ordered.and_yield
- yielded_connections = []
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection)
+ .with(Ci::ApplicationRecord.connection).ordered.and_yield
- described_class.each_database_connection do |connection, name|
- yielded_connections << [connection, name]
- end
-
- expect(yielded_connections).to match_array(expected_connections)
+ expect { |b| described_class.each_database_connection(&b) }
+ .to yield_successive_args(
+ [ActiveRecord::Base.connection, 'main'],
+ [Ci::ApplicationRecord.connection, 'ci']
+ )
end
end
describe '.each_model_connection' do
- let(:model1) { double(connection: double, table_name: 'table1') }
- let(:model2) { double(connection: double, table_name: 'table2') }
+ context 'when the model inherits from SharedModel', :add_ci_connection do
+ let(:model1) { Class.new(Gitlab::Database::SharedModel) }
+ let(:model2) { Class.new(Gitlab::Database::SharedModel) }
- before do
- allow(model1.connection).to receive_message_chain('pool.db_config.name').and_return('name1')
- allow(model2.connection).to receive_message_chain('pool.db_config.name').and_return('name2')
+ before do
+ allow(Gitlab::Database).to receive(:database_base_models)
+ .and_return({ main: ActiveRecord::Base, ci: Ci::ApplicationRecord }.with_indifferent_access)
+ end
+
+ it 'yields each model with SharedModel connected to each database connection' do
+ expect_yielded_models([model1, model2], [
+ { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model1, connection: Ci::ApplicationRecord.connection, name: 'ci' },
+ { model: model2, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ])
+ end
+
+ context 'when the model limits connection names' do
+ before do
+ model1.limit_connection_names = %i[main]
+ model2.limit_connection_names = %i[ci]
+ end
+
+ it 'only yields the model with SharedModel connected to the limited connections' do
+ expect_yielded_models([model1, model2], [
+ { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ])
+ end
+ end
+ end
+
+ context 'when the model does not inherit from SharedModel' do
+ let(:main_model) { Class.new(ActiveRecord::Base) }
+ let(:ci_model) { Class.new(Ci::ApplicationRecord) }
+
+ let(:main_connection) { double(:connection) }
+ let(:ci_connection) { double(:connection) }
+
+ before do
+ allow(main_model).to receive(:connection).and_return(main_connection)
+ allow(ci_model).to receive(:connection).and_return(ci_connection)
+
+ allow(main_connection).to receive_message_chain('pool.db_config.name').and_return('main')
+ allow(ci_connection).to receive_message_chain('pool.db_config.name').and_return('ci')
+ end
+
+ it 'yields each model after connecting SharedModel' do
+ expect_yielded_models([main_model, ci_model], [
+ { model: main_model, connection: main_connection, name: 'main' },
+ { model: ci_model, connection: ci_connection, name: 'ci' }
+ ])
+ end
end
- it 'yields each model after connecting SharedModel' do
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model1.connection).and_yield
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model2.connection).and_yield
+ def expect_yielded_models(models_to_iterate, expected_values)
+ times_yielded = 0
+
+ described_class.each_model_connection(models_to_iterate) do |model, name|
+ expected = expected_values[times_yielded]
- yielded_models = []
+ expect(model).to be(expected[:model])
+ expect(model.connection).to be(expected[:connection])
+ expect(name).to eq(expected[:name])
- described_class.each_model_connection([model1, model2]) do |model, name|
- yielded_models << [model, name]
+ times_yielded += 1
end
- expect(yielded_models).to match_array([[model1, 'name1'], [model2, 'name2']])
+ expect(times_yielded).to eq(expected_values.size)
end
end
end
diff --git a/spec/lib/gitlab/database/gitlab_schema_spec.rb b/spec/lib/gitlab/database/gitlab_schema_spec.rb
index 255efc99ff6..a5a67c2c918 100644
--- a/spec/lib/gitlab/database/gitlab_schema_spec.rb
+++ b/spec/lib/gitlab/database/gitlab_schema_spec.rb
@@ -44,6 +44,8 @@ RSpec.describe Gitlab::Database::GitlabSchema do
'my_schema.ci_builds' | :gitlab_ci
'information_schema.columns' | :gitlab_shared
'audit_events_part_5fc467ac26' | :gitlab_main
+ '_test_gitlab_main_table' | :gitlab_main
+ '_test_gitlab_ci_table' | :gitlab_ci
'_test_my_table' | :gitlab_shared
'pg_attribute' | :gitlab_shared
'my_other_table' | :undefined_my_other_table
diff --git a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
index 796c14c1038..e87c9c20707 100644
--- a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
@@ -2,11 +2,18 @@
require 'spec_helper'
-RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
+RSpec.describe Gitlab::Database::LoadBalancing::Configuration, :request_store do
let(:configuration_hash) { {} }
let(:db_config) { ActiveRecord::DatabaseConfigurations::HashConfig.new('test', 'ci', configuration_hash) }
let(:model) { double(:model, connection_db_config: db_config) }
+ before do
+ # It's confusing to think about these specs with this enabled by default so
+ # we make it disabled by default and just write the specific spec for when
+ # it's enabled
+ stub_feature_flags(force_no_sharing_primary_model: false)
+ end
+
describe '.for_model' do
context 'when load balancing is not configured' do
it 'uses the default settings' do
@@ -233,11 +240,23 @@ RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
end
context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main' do
- it 'the primary connection uses main connection' do
+ before do
stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'main')
+ end
+ it 'the primary connection uses main connection' do
expect(config.primary_connection_specification_name).to eq('ActiveRecord::Base')
end
+
+ context 'when force_no_sharing_primary_model feature flag is enabled' do
+ before do
+ stub_feature_flags(force_no_sharing_primary_model: true)
+ end
+
+ it 'the primary connection uses ci connection' do
+ expect(config.primary_connection_specification_name).to eq('Ci::ApplicationRecord')
+ end
+ end
end
context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=unknown' do
diff --git a/spec/lib/gitlab/database/load_balancing/setup_spec.rb b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
index 953d83d3b48..20519a759b2 100644
--- a/spec/lib/gitlab/database/load_balancing/setup_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
@@ -130,6 +130,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: false,
ff_use_model_load_balancing: nil,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'ci_replica', write: 'ci' }
@@ -140,6 +141,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
request_store_active: false,
ff_use_model_load_balancing: nil,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'ci_replica', write: 'main' }
@@ -150,6 +152,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: false,
ff_use_model_load_balancing: nil,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'main_replica', write: 'main' }
@@ -160,60 +163,77 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
request_store_active: false,
ff_use_model_load_balancing: nil,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'main_replica', write: 'main' }
}
},
- "with FF disabled without RequestStore it uses main" => {
+ "with FF use_model_load_balancing disabled without RequestStore it uses main" => {
env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: false,
ff_use_model_load_balancing: false,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'main_replica', write: 'main' }
}
},
- "with FF enabled without RequestStore sticking of FF does not work, so it fallbacks to use main" => {
+ "with FF use_model_load_balancing enabled without RequestStore sticking of FF does not work, so it fallbacks to use main" => {
env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: false,
ff_use_model_load_balancing: true,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'main_replica', write: 'main' }
}
},
- "with FF disabled with RequestStore it uses main" => {
+ "with FF use_model_load_balancing disabled with RequestStore it uses main" => {
env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: true,
ff_use_model_load_balancing: false,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'main_replica', write: 'main' }
}
},
- "with FF enabled with RequestStore it sticks FF and uses CI connection" => {
+ "with FF use_model_load_balancing enabled with RequestStore it sticks FF and uses CI connection" => {
env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
request_store_active: true,
ff_use_model_load_balancing: true,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'ci_replica', write: 'ci' }
}
},
- "with re-use and FF enabled with RequestStore it sticks FF and uses CI connection for reads" => {
+ "with re-use and ff_use_model_load_balancing enabled and FF force_no_sharing_primary_model disabled with RequestStore it sticks FF and uses CI connection for reads" => {
env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
request_store_active: true,
ff_use_model_load_balancing: true,
+ ff_force_no_sharing_primary_model: false,
expectations: {
main: { read: 'main_replica', write: 'main' },
ci: { read: 'ci_replica', write: 'main' }
}
+ },
+ "with re-use and ff_use_model_load_balancing enabled and FF force_no_sharing_primary_model enabled with RequestStore it sticks FF and uses CI connection for reads" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: true,
+ ff_use_model_load_balancing: true,
+ ff_force_no_sharing_primary_model: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'ci' }
+ }
}
}
end
@@ -243,6 +263,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
around do |example|
if request_store_active
Gitlab::WithRequestStore.with_request_store do
+ stub_feature_flags(force_no_sharing_primary_model: ff_force_no_sharing_primary_model)
RequestStore.clear!
example.run
diff --git a/spec/lib/gitlab/database/loose_foreign_keys_spec.rb b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
index 13f2d31bc32..ed11699e494 100644
--- a/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
+++ b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
@@ -18,6 +18,45 @@ RSpec.describe Gitlab::Database::LooseForeignKeys do
))
end
+ context 'ensure keys are sorted' do
+ it 'does not have any keys that are out of order' do
+ parsed = YAML.parse_file(described_class.loose_foreign_keys_yaml_path)
+ mapping = parsed.children.first
+ table_names = mapping.children.select(&:scalar?).map(&:value)
+ expect(table_names).to eq(table_names.sort), "expected sorted table names in the YAML file"
+ end
+ end
+
+ context 'ensure no duplicates are found' do
+ it 'does not have duplicate tables defined' do
+ # since we use hash to detect duplicate hash keys we need to parse YAML document
+ parsed = YAML.parse_file(described_class.loose_foreign_keys_yaml_path)
+ expect(parsed).to be_document
+ expect(parsed.children).to be_one, "YAML has a single document"
+
+ # require hash
+ mapping = parsed.children.first
+ expect(mapping).to be_mapping, "YAML has a top-level hash"
+
+ # find all scalars with names
+ table_names = mapping.children.select(&:scalar?).map(&:value)
+ expect(table_names).not_to be_empty, "YAML has a non-zero tables defined"
+
+ # expect to not have duplicates
+ expect(table_names).to contain_exactly(*table_names.uniq)
+ end
+
+ it 'does not have duplicate column definitions' do
+ # ignore other modifiers
+ all_definitions = definitions.map do |definition|
+ { from_table: definition.from_table, to_table: definition.to_table, column: definition.column }
+ end
+
+ # expect to not have duplicates
+ expect(all_definitions).to contain_exactly(*all_definitions.uniq)
+ end
+ end
+
describe 'ensuring database integrity' do
def base_models_for(table)
parent_table_schema = Gitlab::Database::GitlabSchema.table_schema(table)
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 7e3de32b965..d71a4f81901 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -14,6 +14,54 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
allow(model).to receive(:puts)
end
+ describe 'overridden dynamic model helpers' do
+ let(:test_table) { '__test_batching_table' }
+
+ before do
+ model.connection.execute(<<~SQL)
+ CREATE TABLE #{test_table} (
+ id integer NOT NULL PRIMARY KEY,
+ name text NOT NULL
+ );
+
+ INSERT INTO #{test_table} (id, name)
+ VALUES (1, 'bob'), (2, 'mary'), (3, 'amy');
+ SQL
+ end
+
+ describe '#define_batchable_model' do
+ it 'defines a batchable model with the migration connection' do
+ expect(model.define_batchable_model(test_table).count).to eq(3)
+ end
+ end
+
+ describe '#each_batch' do
+ before do
+ allow(model).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'calls each_batch with the migration connection' do
+ each_batch_name = ->(&block) do
+ model.each_batch(test_table, of: 2) do |batch|
+ block.call(batch.pluck(:name))
+ end
+ end
+
+ expect { |b| each_batch_name.call(&b) }.to yield_successive_args(%w[bob mary], %w[amy])
+ end
+ end
+
+ describe '#each_batch_range' do
+ before do
+ allow(model).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'calls each_batch with the migration connection' do
+ expect { |b| model.each_batch_range(test_table, of: 2, &b) }.to yield_successive_args([1, 2], [3, 3])
+ end
+ end
+ end
+
describe '#remove_timestamps' do
it 'can remove the default timestamps' do
Gitlab::Database::MigrationHelpers::DEFAULT_TIMESTAMP_COLUMNS.each do |column_name|
@@ -442,6 +490,60 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ describe '#remove_foreign_key_if_exists' do
+ context 'when the foreign key does not exist' do
+ before do
+ allow(model).to receive(:foreign_key_exists?).and_return(false)
+ end
+
+ it 'does nothing' do
+ expect(model).not_to receive(:remove_foreign_key)
+
+ model.remove_foreign_key_if_exists(:projects, :users, column: :user_id)
+ end
+ end
+
+ context 'when the foreign key exists' do
+ before do
+ allow(model).to receive(:foreign_key_exists?).and_return(true)
+ end
+
+ it 'removes the foreign key' do
+ expect(model).to receive(:remove_foreign_key).with(:projects, :users, { column: :user_id })
+
+ model.remove_foreign_key_if_exists(:projects, :users, column: :user_id)
+ end
+
+ context 'when the target table is not given' do
+ it 'passes the options as the second parameter' do
+ expect(model).to receive(:remove_foreign_key).with(:projects, { column: :user_id })
+
+ model.remove_foreign_key_if_exists(:projects, column: :user_id)
+ end
+ end
+
+ context 'when the reverse_lock_order option is given' do
+ it 'requests for lock before removing the foreign key' do
+ expect(model).to receive(:transaction_open?).and_return(true)
+ expect(model).to receive(:execute).with(/LOCK TABLE users, projects/)
+ expect(model).not_to receive(:remove_foreign_key).with(:projects, :users)
+
+ model.remove_foreign_key_if_exists(:projects, :users, column: :user_id, reverse_lock_order: true)
+ end
+
+ context 'when not inside a transaction' do
+ it 'does not lock' do
+ expect(model).to receive(:transaction_open?).and_return(false)
+ expect(model).not_to receive(:execute).with(/LOCK TABLE users, projects/)
+ expect(model).to receive(:remove_foreign_key).with(:projects, :users, { column: :user_id })
+
+ model.remove_foreign_key_if_exists(:projects, :users, column: :user_id, reverse_lock_order: true)
+ end
+ end
+ end
+ end
+ end
+
describe '#add_concurrent_foreign_key' do
before do
allow(model).to receive(:foreign_key_exists?).and_return(false)
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 0abb76b9f8a..96dc3a0fc28 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -299,7 +299,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
before do
allow(Gitlab::BackgroundMigration).to receive(:coordinator_for_database)
- .with('main').and_return(coordinator)
+ .with(tracking_database).and_return(coordinator)
expect(coordinator).to receive(:migration_class_for)
.with(job_class_name).at_least(:once) { job_class }
@@ -403,7 +403,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
context 'when a specific coordinator is given' do
- let(:coordinator) { Gitlab::BackgroundMigration::JobCoordinator.for_tracking_database('main') }
+ let(:coordinator) { Gitlab::BackgroundMigration::JobCoordinator.for_tracking_database(tracking_database) }
it 'uses that coordinator' do
expect(coordinator).to receive(:perform_in).with(10.minutes, 'Class', 'Hello', 'World').and_call_original
@@ -438,6 +438,16 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
it_behaves_like 'helpers that enqueue background migrations', BackgroundMigrationWorker, 'main'
end
+ context 'when the migration is running against the ci database', if: Gitlab::Database.has_config?(:ci) do
+ around do |example|
+ Gitlab::Database::SharedModel.using_connection(::Ci::ApplicationRecord.connection) do
+ example.run
+ end
+ end
+
+ it_behaves_like 'helpers that enqueue background migrations', BackgroundMigration::CiDatabaseWorker, 'ci'
+ end
+
describe '#delete_job_tracking' do
let!(:job_class_name) { 'TestJob' }
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
index c45149d67bf..37efff165c7 100644
--- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
@@ -59,6 +59,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
batch_max_value: 1000,
batch_class_name: 'MyBatchClass',
batch_size: 100,
+ max_batch_size: 10000,
sub_batch_size: 10)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
@@ -71,6 +72,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
max_value: 1000,
batch_class_name: 'MyBatchClass',
batch_size: 100,
+ max_batch_size: 10000,
sub_batch_size: 10,
job_arguments: %w[],
status: 'active',
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
index 902d8e13a63..fd8303c379c 100644
--- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -66,55 +66,43 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
context 'on successful execution' do
subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} }
- it 'records walltime' do
+ it 'records a valid observation', :aggregate_failures do
expect(subject.walltime).not_to be_nil
- end
-
- it 'records success' do
expect(subject.success).to be_truthy
- end
-
- it 'records the migration version' do
expect(subject.version).to eq(migration_version)
- end
-
- it 'records the migration name' do
expect(subject.name).to eq(migration_name)
end
end
context 'upon failure' do
- subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } }
-
- it 'raises the exception' do
- expect { subject }.to raise_error(/something went wrong/)
- end
-
- context 'retrieving observations' do
- subject { instance.observations.first }
-
- before do
- instance.observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' }
- rescue StandardError
- # ignore
- end
+ where(exception: ['something went wrong', SystemStackError, Interrupt])
+ with_them do
let(:instance) { described_class.new(result_dir: result_dir) }
- it 'records walltime' do
- expect(subject.walltime).not_to be_nil
- end
-
- it 'records failure' do
- expect(subject.success).to be_falsey
- end
+ subject(:observe) { instance.observe(version: migration_version, name: migration_name, connection: connection) { raise exception } }
- it 'records the migration version' do
- expect(subject.version).to eq(migration_version)
+ it 'raises the exception' do
+ expect { observe }.to raise_error(exception)
end
- it 'records the migration name' do
- expect(subject.name).to eq(migration_name)
+ context 'retrieving observations' do
+ subject { instance.observations.first }
+
+ before do
+ observe
+ # rubocop:disable Lint/RescueException
+ rescue Exception
+ # rubocop:enable Lint/RescueException
+ # ignore (we expect this exception)
+ end
+
+ it 'records a valid observation', :aggregate_failures do
+ expect(subject.walltime).not_to be_nil
+ expect(subject.success).to be_falsey
+ expect(subject.version).to eq(migration_version)
+ expect(subject.name).to eq(migration_name)
+ end
end
end
end
diff --git a/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb b/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
index 076fb9e8215..50ad77caaf1 100644
--- a/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
+++ b/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigrationProxyLockRetries do
- let(:migration) { double }
+ let(:connection) { ActiveRecord::Base.connection }
+ let(:migration) { double(connection: connection) }
let(:return_value) { double }
let(:class_def) do
Class.new do
@@ -40,6 +41,18 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
expect(result).to eq(return_value)
end
end
+
+ describe '#migration_connection' do
+ subject { class_def.new(migration).migration_connection }
+
+ it 'retrieves actual migration connection from #migration' do
+ expect(migration).to receive(:connection).and_return(return_value)
+
+ result = subject
+
+ expect(result).to eq(return_value)
+ end
+ end
end
describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigratorLockRetries do
@@ -96,7 +109,8 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
context 'with transactions enabled and lock retries enabled' do
let(:receiver) { double('receiver', use_transaction?: true)}
- let(:migration) { double('migration', enable_lock_retries?: true) }
+ let(:migration) { double('migration', migration_connection: connection, enable_lock_retries?: true) }
+ let(:connection) { ActiveRecord::Base.connection }
it 'calls super method' do
p = proc { }
diff --git a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
index 5a19ae6581d..a757cac0a2a 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
subject { described_class.new(observation, directory_path, connection) }
let(:connection) { ActiveRecord::Migration.connection }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:query) { "select date_trunc('day', $1::timestamptz) + $2 * (interval '1 hour')" }
let(:query_binds) { [Time.current, 3] }
let(:directory_path) { Dir.mktmpdir }
diff --git a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
index 7b01e39f5f1..eb66972e5ab 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
subject { described_class.new(observation, directory_path, connection) }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:connection) { ActiveRecord::Migration.connection }
let(:query) { 'select 1' }
let(:directory_path) { Dir.mktmpdir }
diff --git a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
index b26bb8fbe41..f433e25b2ba 100644
--- a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do
subject(:transaction_duration_observer) { described_class.new(observation, directory_path, connection) }
let(:connection) { ActiveRecord::Migration.connection }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-transaction-duration.json" }
let(:transaction_duration) { Gitlab::Json.parse(File.read(log_file)) }
diff --git a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
index e5a8143fcc3..f94a40c93e1 100644
--- a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
+++ b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
@@ -3,59 +3,12 @@
require 'spec_helper'
RSpec.describe 'cross-database foreign keys' do
- # TODO: We are trying to empty out this list in
- # https://gitlab.com/groups/gitlab-org/-/epics/7249 . Once we are done we can
- # keep this test and assert that there are no cross-db foreign keys. We
- # should not be adding anything to this list but should instead only add new
- # loose foreign keys
- # https://docs.gitlab.com/ee/development/database/loose_foreign_keys.html .
+ # Since we don't expect to have any cross-database foreign keys
+ # this is empty. If we will have an entry like
+ # `ci_daily_build_group_report_results.project_id`
+ # should be added.
let(:allowed_cross_database_foreign_keys) do
- %w(
- ci_build_report_results.project_id
- ci_builds.project_id
- ci_builds_metadata.project_id
- ci_daily_build_group_report_results.group_id
- ci_daily_build_group_report_results.project_id
- ci_freeze_periods.project_id
- ci_job_artifacts.project_id
- ci_job_token_project_scope_links.added_by_id
- ci_job_token_project_scope_links.source_project_id
- ci_job_token_project_scope_links.target_project_id
- ci_pending_builds.namespace_id
- ci_pending_builds.project_id
- ci_pipeline_schedules.owner_id
- ci_pipeline_schedules.project_id
- ci_pipelines.merge_request_id
- ci_pipelines.project_id
- ci_project_monthly_usages.project_id
- ci_refs.project_id
- ci_resource_groups.project_id
- ci_runner_namespaces.namespace_id
- ci_runner_projects.project_id
- ci_running_builds.project_id
- ci_sources_pipelines.project_id
- ci_sources_pipelines.source_project_id
- ci_sources_projects.source_project_id
- ci_stages.project_id
- ci_subscriptions_projects.downstream_project_id
- ci_subscriptions_projects.upstream_project_id
- ci_triggers.owner_id
- ci_triggers.project_id
- ci_unit_tests.project_id
- ci_variables.project_id
- dast_profiles_pipelines.ci_pipeline_id
- dast_scanner_profiles_builds.ci_build_id
- dast_site_profiles_builds.ci_build_id
- dast_site_profiles_pipelines.ci_pipeline_id
- external_pull_requests.project_id
- merge_requests.head_pipeline_id
- merge_trains.pipeline_id
- requirements_management_test_reports.build_id
- security_scans.build_id
- vulnerability_feedback.pipeline_id
- vulnerability_occurrence_pipelines.pipeline_id
- vulnerability_statistics.latest_pipeline_id
- ).freeze
+ %w[].freeze
end
def foreign_keys_for(table_name)
diff --git a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
index c41b4eeea10..22a70dc7df0 100644
--- a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
@@ -14,23 +14,41 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
Gitlab::Database::QueryAnalyzer.instance.within { example.run }
end
- shared_examples 'successful examples' do
+ describe 'context and suppress key names' do
+ describe '.context_key' do
+ it 'contains class name' do
+ expect(described_class.context_key)
+ .to eq 'analyzer_prevent_cross_database_modification_context'.to_sym
+ end
+ end
+
+ describe '.suppress_key' do
+ it 'contains class name' do
+ expect(described_class.suppress_key)
+ .to eq 'analyzer_prevent_cross_database_modification_suppressed'.to_sym
+ end
+ end
+ end
+
+ shared_examples 'successful examples' do |model:|
+ let(:model) { model }
+
context 'outside transaction' do
it { expect { run_queries }.not_to raise_error }
end
- context 'within transaction' do
+ context "within #{model} transaction" do
it do
- Project.transaction do
+ model.transaction do
expect { run_queries }.not_to raise_error
end
end
end
- context 'within nested transaction' do
+ context "within nested #{model} transaction" do
it do
- Project.transaction(requires_new: true) do
- Project.transaction(requires_new: true) do
+ model.transaction(requires_new: true) do
+ model.transaction(requires_new: true) do
expect { run_queries }.not_to raise_error
end
end
@@ -38,13 +56,26 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
end
end
+ shared_examples 'cross-database modification errors' do |model:|
+ let(:model) { model }
+
+ context "within #{model} transaction" do
+ it 'raises error' do
+ model.transaction do
+ expect { run_queries }.to raise_error /Cross-database data modification/
+ end
+ end
+ end
+ end
+
context 'when CI and other tables are read in a transaction' do
def run_queries
pipeline.reload
project.reload
end
- include_examples 'successful examples'
+ include_examples 'successful examples', model: Project
+ include_examples 'successful examples', model: Ci::Pipeline
end
context 'when only CI data is modified' do
@@ -53,7 +84,9 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
project.reload
end
- include_examples 'successful examples'
+ include_examples 'successful examples', model: Ci::Pipeline
+
+ include_examples 'cross-database modification errors', model: Project
end
context 'when other data is modified' do
@@ -62,7 +95,9 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
project.touch
end
- include_examples 'successful examples'
+ include_examples 'successful examples', model: Project
+
+ include_examples 'cross-database modification errors', model: Ci::Pipeline
end
context 'when both CI and other data is modified' do
@@ -144,7 +179,9 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
project.save!
end
- include_examples 'successful examples'
+ include_examples 'successful examples', model: Ci::Pipeline
+
+ include_examples 'cross-database modification errors', model: Project
end
describe '.allow_cross_database_modification_within_transaction' do
diff --git a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
index 0282a7af0df..6c32fb3ca17 100644
--- a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
let(:env) { {} }
let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER }
- let(:subject) { described_class.new(env: env, logger: logger, timing_configuration: timing_configuration) }
+ let(:subject) { described_class.new(connection: connection, env: env, logger: logger, timing_configuration: timing_configuration) }
+ let(:connection) { ActiveRecord::Base.retrieve_connection }
let(:timing_configuration) do
[
@@ -67,7 +68,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
WHERE t.relkind = 'r' AND l.mode = 'ExclusiveLock' AND t.relname = '#{Project.table_name}'
"""
- expect(ActiveRecord::Base.connection.execute(check_exclusive_lock_query).to_a).to be_present
+ expect(connection.execute(check_exclusive_lock_query).to_a).to be_present
end
end
@@ -96,8 +97,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
lock_fiber.resume
end
- ActiveRecord::Base.transaction do
- ActiveRecord::Base.connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
+ connection.transaction do
+ connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
lock_acquired = true
end
end
@@ -115,7 +116,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'setting the idle transaction timeout' do
context 'when there is no outer transaction: disable_ddl_transaction! is set in the migration' do
it 'does not disable the idle transaction timeout' do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ allow(connection).to receive(:transaction_open?).and_return(false)
allow(subject).to receive(:run_block_with_lock_timeout).once.and_raise(ActiveRecord::LockWaitTimeout)
allow(subject).to receive(:run_block_with_lock_timeout).once
@@ -127,7 +128,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'when there is outer transaction: disable_ddl_transaction! is not set in the migration' do
it 'disables the idle transaction timeout so the code can sleep and retry' do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(true)
+ allow(connection).to receive(:transaction_open?).and_return(true)
n = 0
allow(subject).to receive(:run_block_with_lock_timeout).twice do
@@ -184,8 +185,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
subject.run(raise_on_exhaustion: true) do
lock_attempts += 1
- ActiveRecord::Base.transaction do
- ActiveRecord::Base.connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
+ connection.transaction do
+ connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
lock_acquired = true
end
end
@@ -199,11 +200,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'when statement timeout is reached' do
it 'raises StatementInvalid error' do
lock_acquired = false
- ActiveRecord::Base.connection.execute("SET statement_timeout='100ms'")
+ connection.execute("SET statement_timeout='100ms'")
expect do
subject.run do
- ActiveRecord::Base.connection.execute("SELECT 1 FROM pg_sleep(0.11)") # 110ms
+ connection.execute("SELECT 1 FROM pg_sleep(0.11)") # 110ms
lock_acquired = true
end
end.to raise_error(ActiveRecord::StatementInvalid)
@@ -216,11 +217,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'restore local database variables' do
it do
- expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW lock_timeout").to_a }
+ expect { subject.run {} }.not_to change { connection.execute("SHOW lock_timeout").to_a }
end
it do
- expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW idle_in_transaction_session_timeout").to_a }
+ expect { subject.run {} }.not_to change { connection.execute("SHOW idle_in_transaction_session_timeout").to_a }
end
end
@@ -228,8 +229,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms
it 'executes `SET lock_timeout` using the configured timeout value in milliseconds' do
- 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("SET lock_timeout TO '15ms'").and_call_original
+ expect(connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
+ expect(connection).to receive(:execute).with("SET lock_timeout TO '15ms'").and_call_original
subject.run { }
end
diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb
index c2c818aa106..6b35ccafabc 100644
--- a/spec/lib/gitlab/database/with_lock_retries_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::WithLockRetries do
let(:env) { {} }
let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER }
- let(:subject) { described_class.new(env: env, logger: logger, allow_savepoints: allow_savepoints, timing_configuration: timing_configuration) }
+ let(:subject) { described_class.new(connection: connection, env: env, logger: logger, allow_savepoints: allow_savepoints, timing_configuration: timing_configuration) }
let(:allow_savepoints) { true }
let(:connection) { ActiveRecord::Base.retrieve_connection }
diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
index f5ea660ee1e..6601b6658d5 100644
--- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
+++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- application_setting.update(allow_local_requests_from_web_hooks_and_services: true)
+ application_setting.update!(allow_local_requests_from_web_hooks_and_services: true)
end
shared_examples 'has prometheus integration' do |server_address|
@@ -181,7 +181,7 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
let(:existing_project) { create(:project, namespace: existing_group) }
before do
- application_setting.update(instance_administrators_group_id: existing_group.id,
+ application_setting.update!(instance_administrators_group_id: existing_group.id,
self_monitoring_project_id: existing_project.id)
end
@@ -195,7 +195,7 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
context 'when local requests from hooks and integrations are not allowed' do
before do
- application_setting.update(allow_local_requests_from_web_hooks_and_services: false)
+ application_setting.update!(allow_local_requests_from_web_hooks_and_services: false)
end
it_behaves_like 'has prometheus integration', 'http://localhost:9090'
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index 5ec7c338a2a..b3b7c81e9e7 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -104,6 +104,34 @@ RSpec.describe Gitlab::Database do
end
end
+ describe '.check_for_non_superuser' do
+ subject { described_class.check_for_non_superuser }
+
+ let(:non_superuser) { Gitlab::Database::PgUser.new(usename: 'foo', usesuper: false ) }
+ let(:superuser) { Gitlab::Database::PgUser.new(usename: 'bar', usesuper: true) }
+
+ it 'prints user details if not superuser' do
+ allow(Gitlab::Database::PgUser).to receive(:find_by).with('usename = CURRENT_USER').and_return(non_superuser)
+
+ expect(Gitlab::AppLogger).to receive(:info).with("Account details: User: \"foo\", UseSuper: (false)")
+
+ subject
+ end
+
+ it 'raises an exception if superuser' do
+ allow(Gitlab::Database::PgUser).to receive(:find_by).with('usename = CURRENT_USER').and_return(superuser)
+
+ expect(Gitlab::AppLogger).to receive(:info).with("Account details: User: \"bar\", UseSuper: (true)")
+ expect { subject }.to raise_error('Error: detected superuser')
+ end
+
+ it 'catches exception if find_by fails' do
+ allow(Gitlab::Database::PgUser).to receive(:find_by).with('usename = CURRENT_USER').and_raise(ActiveRecord::StatementInvalid)
+
+ expect { subject }.to raise_error('User CURRENT_USER not found')
+ end
+ end
+
describe '.check_postgres_version_and_print_warning' do
let(:reflect) { instance_spy(Gitlab::Database::Reflection) }
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 45a49a36fe2..7c1a8f4c3c8 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::Diff::File do
def create_file(file_name, content)
Files::CreateService.new(
project,
- project.owner,
+ project.first_owner,
commit_message: 'Update',
start_branch: branch_name,
branch_name: branch_name,
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Diff::File do
def update_file(file_name, content)
Files::UpdateService.new(
project,
- project.owner,
+ project.first_owner,
commit_message: 'Update',
start_branch: branch_name,
branch_name: branch_name,
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::Diff::File do
def delete_file(file_name)
Files::DeleteService.new(
project,
- project.owner,
+ project.first_owner,
commit_message: 'Update',
start_branch: branch_name,
branch_name: branch_name,
diff --git a/spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb b/spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb
index 7dceb64b776..1414056ad6a 100644
--- a/spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Diff::PositionTracer::ImageStrategy do
include PositionTracerHelpers
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:file_name) { 'test-file' }
let(:new_file_name) { "#{file_name}-new" }
let(:second_file_name) { "#{file_name}-2" }
diff --git a/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb b/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
index c46f476899e..ea56a87dec2 100644
--- a/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::Diff::PositionTracer::LineStrategy, :clean_gitlab_redis_c
include PositionTracerHelpers
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:repository) { project.repository }
let(:file_name) { "test-file" }
let(:new_file_name) { "#{file_name}-new" }
diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb
index fc649812b0a..9b0ea892f91 100644
--- a/spec/lib/gitlab/diff/position_tracer_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::Diff::PositionTracer do
describe 'diffs methods' do
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:old_diff_refs) do
diff_refs(
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
index c0ac40e3249..59b87c5d8e7 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
include_context :email_shared_context
- let_it_be(:user) { create(:user) }
+ let_it_be(:user) { create(:user, email: 'jake@adventuretime.ooo') }
let_it_be(:project) { create(:project, :public, :repository) }
let(:noteable) { note.noteable }
@@ -39,6 +39,43 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
+ context 'when the incoming email is from a different email address' do
+ before do
+ SentNotification.find_by(reply_key: mail_key).update!(recipient: original_recipient)
+ end
+
+ context 'when the issue is not a Service Desk issue' do
+ let(:original_recipient) { create(:user, email: 'john@somethingelse.com') }
+
+ context 'with only one email address' do
+ it 'raises a UserNotFoundError' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
+ end
+ end
+
+ context 'with a secondary verified email address' do
+ let(:verified_email) { 'alan@adventuretime.ooo'}
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub('jake@adventuretime.ooo', verified_email) }
+
+ before do
+ create(:email, :confirmed, user: original_recipient, email: verified_email)
+ end
+
+ it 'does not raise a UserNotFoundError' do
+ expect { receiver.execute }.not_to raise_error(Gitlab::Email::UserNotFoundError)
+ end
+ end
+ end
+
+ context 'when the issue is a Service Desk issue' do
+ let(:original_recipient) { User.support_bot }
+
+ it 'does not raise a UserNotFoundError' do
+ expect { receiver.execute }.not_to raise_error(Gitlab::Email::UserNotFoundError)
+ end
+ end
+ end
+
context 'when no sent notification for the mail key could be found' do
let(:email_raw) { fixture_file('emails/wrong_mail_key.eml') }
diff --git a/spec/lib/gitlab/endpoint_attributes_spec.rb b/spec/lib/gitlab/endpoint_attributes_spec.rb
index 4d4cfed57fa..53f5b302f05 100644
--- a/spec/lib/gitlab/endpoint_attributes_spec.rb
+++ b/spec/lib/gitlab/endpoint_attributes_spec.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require_relative "../../support/matchers/be_request_urgency"
-require_relative "../../../lib/gitlab/endpoint_attributes"
+require_relative '../../support/matchers/be_request_urgency'
+require_relative '../../../lib/gitlab/endpoint_attributes/config'
+require_relative '../../../lib/gitlab/endpoint_attributes'
RSpec.describe Gitlab::EndpointAttributes do
let(:base_controller) do
diff --git a/spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb b/spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb
index 0e72dd7ec5e..38745fe0cde 100644
--- a/spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb
+++ b/spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'rspec-parameterized'
+require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::ContextPayloadGenerator do
subject(:generator) { described_class.new }
diff --git a/spec/lib/gitlab/error_tracking/log_formatter_spec.rb b/spec/lib/gitlab/error_tracking/log_formatter_spec.rb
index 188ccd000a1..15d201401f4 100644
--- a/spec/lib/gitlab/error_tracking/log_formatter_spec.rb
+++ b/spec/lib/gitlab/error_tracking/log_formatter_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::LogFormatter do
let(:exception) { StandardError.new('boom') }
diff --git a/spec/lib/gitlab/event_store/store_spec.rb b/spec/lib/gitlab/event_store/store_spec.rb
index 711e1d5b4d5..94e8f0ff2ff 100644
--- a/spec/lib/gitlab/event_store/store_spec.rb
+++ b/spec/lib/gitlab/event_store/store_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe Gitlab::EventStore::Store do
let(:worker) do
stub_const('EventSubscriber', Class.new).tap do |klass|
klass.class_eval do
- include ApplicationWorker
include Gitlab::EventStore::Subscriber
def handle_event(event)
@@ -23,7 +22,6 @@ RSpec.describe Gitlab::EventStore::Store do
let(:another_worker) do
stub_const('AnotherEventSubscriber', Class.new).tap do |klass|
klass.class_eval do
- include ApplicationWorker
include Gitlab::EventStore::Subscriber
end
end
@@ -32,7 +30,6 @@ RSpec.describe Gitlab::EventStore::Store do
let(:unrelated_worker) do
stub_const('UnrelatedEventSubscriber', Class.new).tap do |klass|
klass.class_eval do
- include ApplicationWorker
include Gitlab::EventStore::Subscriber
end
end
@@ -224,6 +221,26 @@ RSpec.describe Gitlab::EventStore::Store do
store.publish(event)
end
end
+
+ context 'when the event does not have any subscribers' do
+ let(:store) do
+ described_class.new do |s|
+ s.subscribe unrelated_worker, to: another_event_klass
+ end
+ end
+
+ let(:event) { event_klass.new(data: data) }
+
+ it 'returns successfully' do
+ expect { store.publish(event) }.not_to raise_error
+ end
+
+ it 'does not dispatch the event to another subscription' do
+ expect(unrelated_worker).not_to receive(:perform_async)
+
+ store.publish(event)
+ end
+ end
end
describe 'subscriber' do
@@ -233,6 +250,10 @@ RSpec.describe Gitlab::EventStore::Store do
subject { worker_instance.perform(event_name, data) }
+ it 'is a Sidekiq worker' do
+ expect(worker_instance).to be_a(ApplicationWorker)
+ end
+
it 'handles the event' do
expect(worker_instance).to receive(:handle_event).with(instance_of(event.class))
diff --git a/spec/lib/gitlab/experiment/rollout/feature_spec.rb b/spec/lib/gitlab/experiment/rollout/feature_spec.rb
new file mode 100644
index 00000000000..d73757be79b
--- /dev/null
+++ b/spec/lib/gitlab/experiment/rollout/feature_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Experiment::Rollout::Feature, :experiment do
+ subject { described_class.new.for(subject_experiment) }
+
+ let(:subject_experiment) { experiment('namespaced/stub') }
+
+ describe "#enabled?" do
+ before do
+ allow(Feature::Definition).to receive(:get).and_return('_instance_')
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
+ allow(Feature).to receive(:get).and_return(double(state: :on))
+ end
+
+ it "is enabled when all criteria are met" do
+ expect(subject).to be_enabled
+ end
+
+ it "isn't enabled if the feature definition doesn't exist" do
+ expect(Feature::Definition).to receive(:get).with('namespaced_stub').and_return(nil)
+
+ expect(subject).not_to be_enabled
+ end
+
+ it "isn't enabled if we're not in dev or dotcom environments" do
+ expect(Gitlab).to receive(:dev_env_or_com?).and_return(false)
+
+ expect(subject).not_to be_enabled
+ end
+
+ it "isn't enabled if the feature flag state is :off" do
+ expect(Feature).to receive(:get).with('namespaced_stub').and_return(double(state: :off))
+
+ expect(subject).not_to be_enabled
+ end
+ end
+
+ describe "#execute_assignment" do
+ before do
+ allow(Feature).to receive(:enabled?).with('namespaced_stub', any_args).and_return(true)
+ end
+
+ it "uses the default value as specified in the yaml" do
+ expect(Feature).to receive(:enabled?).with(
+ 'namespaced_stub',
+ subject,
+ type: :experiment,
+ default_enabled: :yaml
+ ).and_return(false)
+
+ expect(subject.execute_assignment).to be_nil
+ end
+
+ it "returns an assigned name" do
+ allow(subject).to receive(:behavior_names).and_return([:variant1, :variant2])
+
+ expect(subject.execute_assignment).to eq(:variant2)
+ end
+ end
+
+ describe "#flipper_id" do
+ it "returns the expected flipper id if the experiment doesn't provide one" do
+ subject.instance_variable_set(:@experiment, double(id: '__id__'))
+ expect(subject.flipper_id).to eq('Experiment;__id__')
+ end
+
+ it "lets the experiment provide a flipper id so it can override the default" do
+ allow(subject_experiment).to receive(:flipper_id).and_return('_my_overridden_id_')
+
+ expect(subject.flipper_id).to eq('_my_overridden_id_')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/feature_categories_spec.rb b/spec/lib/gitlab/feature_categories_spec.rb
index daced154a69..477da900d0a 100644
--- a/spec/lib/gitlab/feature_categories_spec.rb
+++ b/spec/lib/gitlab/feature_categories_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::FeatureCategories do
let(:fake_categories) { %w(foo bar) }
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index f1b6a59abf9..ae6ca728573 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -2252,44 +2252,6 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
end
- describe '#clean_stale_repository_files' do
- let(:worktree_id) { 'rebase-1' }
- let(:gitlab_worktree_path) { File.join(repository_path, 'gitlab-worktree', worktree_id) }
- let(:admin_dir) { File.join(repository_path, 'worktrees') }
-
- it 'cleans up the files' do
- create_worktree = %W[git -C #{repository_path} worktree add --detach #{gitlab_worktree_path} master]
- raise 'preparation failed' unless system(*create_worktree, err: '/dev/null')
-
- FileUtils.touch(gitlab_worktree_path, mtime: Time.now - 8.hours)
- # git rev-list --all will fail in git 2.16 if HEAD is pointing to a non-existent object,
- # but the HEAD must be 40 characters long or git will ignore it.
- File.write(File.join(admin_dir, worktree_id, 'HEAD'), Gitlab::Git::BLANK_SHA)
-
- expect(rev_list_all).to be(false)
- repository.clean_stale_repository_files
-
- expect(rev_list_all).to be(true)
- expect(File.exist?(gitlab_worktree_path)).to be_falsey
- end
-
- def rev_list_all
- system(*%W[git -C #{repository_path} rev-list --all], out: '/dev/null', err: '/dev/null')
- end
-
- it 'increments a counter upon an error' do
- expect(repository.gitaly_repository_client).to receive(:cleanup).and_raise(Gitlab::Git::CommandError)
-
- counter = double(:counter)
-
- expect(counter).to receive(:increment)
- expect(Gitlab::Metrics).to receive(:counter).with(:failed_repository_cleanup_total,
- 'Number of failed repository cleanup events').and_return(counter)
-
- repository.clean_stale_repository_files
- end
- end
-
describe '#squash' do
let(:branch_name) { 'fix' }
let(:start_sha) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' }
diff --git a/spec/lib/gitlab/git/wiki_spec.rb b/spec/lib/gitlab/git/wiki_spec.rb
index eb7deb08063..ee0c0e2708e 100644
--- a/spec/lib/gitlab/git/wiki_spec.rb
+++ b/spec/lib/gitlab/git/wiki_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Git::Wiki do
using RSpec::Parameterized::TableSyntax
let(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:project_wiki) { ProjectWiki.new(project, user) }
subject(:wiki) { project_wiki.wiki }
diff --git a/spec/lib/gitlab/git_access_design_spec.rb b/spec/lib/gitlab/git_access_design_spec.rb
index 9fd1f2dcb0c..c90d9802300 100644
--- a/spec/lib/gitlab/git_access_design_spec.rb
+++ b/spec/lib/gitlab/git_access_design_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Gitlab::GitAccessDesign do
include DesignManagementTestHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:protocol) { 'web' }
let(:actor) { user }
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 4bf7994f4dd..d6ef1836ad9 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -1008,11 +1008,6 @@ RSpec.describe Gitlab::GitAccess do
end
end
- it 'cleans up the files' do
- expect(project.repository).to receive(:clean_stale_repository_files).and_call_original
- expect { push_access_check }.not_to raise_error
- end
-
it 'avoids N+1 queries', :request_store do
# Run this once to establish a baseline. Cached queries should get
# cached, so that when we introduce another change we shouldn't see
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index 27e7d446770..f0115aa6b2b 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -2,6 +2,9 @@
require 'spec_helper'
+require 'google/rpc/status_pb'
+require 'google/protobuf/well_known_types'
+
RSpec.describe Gitlab::GitalyClient::OperationService do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
@@ -185,11 +188,16 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
context 'with an exception with the UserMergeBranchError' do
let(:permission_error) do
- GRPC::PermissionDenied.new(
+ new_detailed_error(
+ GRPC::Core::StatusCodes::PERMISSION_DENIED,
"GitLab: You are not allowed to push code to this project.",
- { "grpc-status-details-bin" =>
- "\b\a\x129GitLab: You are not allowed to push code to this project.\x1A\xDE\x01\n/type.googleapis.com/gitaly.UserMergeBranchError\x12\xAA\x01\n\xA7\x01\n1You are not allowed to push code to this project.\x12\x03web\x1A\auser-15\"df15b32277d2c55c6c595845a87109b09c913c556 5d6e0f935ad9240655f64e883cd98fad6f9a17ee refs/heads/master\n" }
- )
+ Gitaly::UserMergeBranchError.new(
+ access_check: Gitaly::AccessCheckError.new(
+ error_message: "You are not allowed to push code to this project.",
+ protocol: "web",
+ user_id: "user-15",
+ changes: "df15b32277d2c55c6c595845a87109b09c913c556 5d6e0f935ad9240655f64e883cd98fad6f9a17ee refs/heads/master\n"
+ )))
end
it 'raises PreRecieveError with the error message' do
@@ -217,6 +225,27 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
expect { subject }.to raise_error(GRPC::PermissionDenied)
end
end
+
+ context 'with ReferenceUpdateError' do
+ let(:reference_update_error) do
+ new_detailed_error(GRPC::Core::StatusCodes::FAILED_PRECONDITION,
+ "some ignored error message",
+ Gitaly::UserMergeBranchError.new(
+ reference_update: Gitaly::ReferenceUpdateError.new(
+ reference_name: "refs/heads/something",
+ old_oid: "1234",
+ new_oid: "6789"
+ )))
+ end
+
+ it 'returns nil' do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_merge_branch).with(kind_of(Enumerator), kind_of(Hash))
+ .and_raise(reference_update_error)
+
+ expect(subject).to be_nil
+ end
+ end
end
describe '#user_ff_branch' do
@@ -478,4 +507,14 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
end
end
end
+
+ def new_detailed_error(error_code, error_message, details)
+ status_error = Google::Rpc::Status.new(
+ code: error_code,
+ message: error_message,
+ details: [Google::Protobuf::Any.pack(details)]
+ )
+
+ GRPC::BadStatus.new(error_code, error_message, { "grpc-status-details-bin" => Google::Rpc::Status.encode(status_error) })
+ 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 e5502a883b5..353726b56f6 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -21,16 +21,6 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
end
- describe '#cleanup' do
- it 'sends a cleanup message' do
- expect_any_instance_of(Gitaly::RepositoryService::Stub)
- .to receive(:cleanup)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
-
- client.cleanup
- end
- end
-
describe '#garbage_collect' do
it 'sends a garbage_collect message' do
expect_any_instance_of(Gitaly::RepositoryService::Stub)
diff --git a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
index a0e78186caa..c8e744ab262 100644
--- a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
@@ -119,123 +119,80 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
.and_return(discussion_id)
end
- context 'when github_importer_use_diff_note_with_suggestions is disabled' do
- before do
- stub_feature_flags(github_importer_use_diff_note_with_suggestions: false)
+ it_behaves_like 'diff notes without suggestion'
+
+ context 'when the note has suggestions' do
+ let(:note_body) do
+ <<~EOB
+ Suggestion:
+ ```suggestion
+ what do you think to do it like this
+ ```
+ EOB
end
- it_behaves_like 'diff notes without suggestion'
+ before do
+ stub_user_finder(user.id, true)
+ end
- context 'when the note has suggestions' do
- let(:note_body) do
- <<~EOB
+ it 'imports the note as diff note' do
+ expect { subject.execute }
+ .to change(DiffNote, :count)
+ .by(1)
+
+ note = project.notes.diff_notes.take
+ expect(note).to be_valid
+ expect(note.noteable_type).to eq('MergeRequest')
+ expect(note.noteable_id).to eq(merge_request.id)
+ expect(note.project_id).to eq(project.id)
+ expect(note.author_id).to eq(user.id)
+ expect(note.system).to eq(false)
+ expect(note.discussion_id).to eq(discussion_id)
+ expect(note.commit_id).to eq('original123abc')
+ expect(note.line_code).to eq(note_representation.line_code)
+ expect(note.type).to eq('DiffNote')
+ expect(note.created_at).to eq(created_at)
+ expect(note.updated_at).to eq(updated_at)
+ expect(note.position.to_h).to eq({
+ base_sha: merge_request.diffs.diff_refs.base_sha,
+ head_sha: merge_request.diffs.diff_refs.head_sha,
+ start_sha: merge_request.diffs.diff_refs.start_sha,
+ new_line: 15,
+ old_line: nil,
+ new_path: file_path,
+ old_path: file_path,
+ position_type: 'text',
+ line_range: nil
+ })
+ expect(note.note)
+ .to eq <<~NOTE
Suggestion:
- ```suggestion
+ ```suggestion:-0+0
what do you think to do it like this
```
- EOB
- end
-
- it 'imports the note' do
- stub_user_finder(user.id, true)
-
- expect { subject.execute }
- .to change(LegacyDiffNote, :count)
- .and not_change(DiffNote, :count)
-
- note = project.notes.diff_notes.take
- expect(note).to be_valid
- expect(note.note)
- .to eq <<~NOTE
- Suggestion:
- ```suggestion:-0+0
- what do you think to do it like this
- ```
- NOTE
- end
- end
- end
-
- context 'when github_importer_use_diff_note_with_suggestions is enabled' do
- before do
- stub_feature_flags(github_importer_use_diff_note_with_suggestions: true)
+ NOTE
end
- it_behaves_like 'diff notes without suggestion'
+ context 'when the note diff file creation fails' do
+ it 'falls back to the LegacyDiffNote' do
+ exception = ::DiffNote::NoteDiffFileCreationError.new('Failed to create diff note file')
- context 'when the note has suggestions' do
- let(:note_body) do
- <<~EOB
- Suggestion:
- ```suggestion
- what do you think to do it like this
- ```
- EOB
- end
+ expect_next_instance_of(::Import::Github::Notes::CreateService) do |service|
+ expect(service)
+ .to receive(:execute)
+ .and_raise(exception)
+ end
- before do
- stub_user_finder(user.id, true)
- end
+ expect(Gitlab::GithubImport::Logger)
+ .to receive(:warn)
+ .with(
+ message: 'Failed to create diff note file',
+ 'error.class': 'DiffNote::NoteDiffFileCreationError'
+ )
- it 'imports the note as diff note' do
expect { subject.execute }
- .to change(DiffNote, :count)
- .by(1)
-
- note = project.notes.diff_notes.take
- expect(note).to be_valid
- expect(note.noteable_type).to eq('MergeRequest')
- expect(note.noteable_id).to eq(merge_request.id)
- expect(note.project_id).to eq(project.id)
- expect(note.author_id).to eq(user.id)
- expect(note.system).to eq(false)
- expect(note.discussion_id).to eq(discussion_id)
- expect(note.commit_id).to eq('original123abc')
- expect(note.line_code).to eq(note_representation.line_code)
- expect(note.type).to eq('DiffNote')
- expect(note.created_at).to eq(created_at)
- expect(note.updated_at).to eq(updated_at)
- expect(note.position.to_h).to eq({
- base_sha: merge_request.diffs.diff_refs.base_sha,
- head_sha: merge_request.diffs.diff_refs.head_sha,
- start_sha: merge_request.diffs.diff_refs.start_sha,
- new_line: 15,
- old_line: nil,
- new_path: file_path,
- old_path: file_path,
- position_type: 'text',
- line_range: nil
- })
- expect(note.note)
- .to eq <<~NOTE
- Suggestion:
- ```suggestion:-0+0
- what do you think to do it like this
- ```
- NOTE
- end
-
- context 'when the note diff file creation fails' do
- it 'falls back to the LegacyDiffNote' do
- exception = ::DiffNote::NoteDiffFileCreationError.new('Failed to create diff note file')
-
- expect_next_instance_of(::Import::Github::Notes::CreateService) do |service|
- expect(service)
- .to receive(:execute)
- .and_raise(exception)
- end
-
- expect(Gitlab::GithubImport::Logger)
- .to receive(:warn)
- .with(
- message: 'Failed to create diff note file',
- 'error.class': 'DiffNote::NoteDiffFileCreationError'
- )
-
- expect { subject.execute }
- .to change(LegacyDiffNote, :count)
- .and not_change(DiffNote, :count)
- end
+ .to change(LegacyDiffNote, :count)
+ .and not_change(DiffNote, :count)
end
end
end
diff --git a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
index 1a25824bc8a..6b3d18f20e9 100644
--- a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
@@ -52,6 +52,12 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
expect { importer.execute }.to change { Release.count }.by(1)
end
+
+ it 'is idempotent' do
+ allow(importer).to receive(:each_release).and_return([github_release])
+ expect { importer.execute }.to change { Release.count }.by(1)
+ expect { importer.execute }.to change { Release.count }.by(0) # Idempotency check
+ end
end
describe '#build_releases' do
@@ -79,6 +85,24 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
expect(release[:description]).to eq('Release for tag 1.0')
end
+
+ it 'does not create releases that have a NULL tag' do
+ null_tag_release = double(
+ name: 'NULL Test',
+ tag_name: nil
+ )
+
+ expect(importer).to receive(:each_release).and_return([null_tag_release])
+ expect(importer.build_releases).to be_empty
+ end
+
+ it 'does not create duplicate release tags' do
+ expect(importer).to receive(:each_release).and_return([github_release, github_release])
+
+ releases = importer.build_releases
+ expect(releases.length).to eq(1)
+ expect(releases[0][:description]).to eq('This is my release')
+ end
end
describe '#build' do
diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
index 58a8fb1b7e4..f2730ba74ec 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -264,8 +264,8 @@ RSpec.describe Gitlab::GithubImport::Importer::RepositoryImporter do
it 'sets the timestamp for when the cloning process finished' do
freeze_time do
expect(project)
- .to receive(:update_column)
- .with(:last_repository_updated_at, Time.zone.now)
+ .to receive(:touch)
+ .with(:last_repository_updated_at)
importer.update_clone_time
end
diff --git a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
index 63834cfdb94..fe3040c102b 100644
--- a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_redis_shared_state do
+RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_redis_cache do
let(:hunk) do
'@@ -1 +1 @@
-Hello
@@ -166,6 +166,23 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
expect(new_discussion_note.discussion_id)
.to eq('SECOND_DISCUSSION_ID')
end
+
+ context 'when cached value does not exist' do
+ it 'falls back to generating a new discussion_id' do
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return('NEW_DISCUSSION_ID')
+
+ reply_note = described_class.from_json_hash(
+ 'note_id' => note.note_id + 1,
+ 'in_reply_to_id' => note.note_id
+ )
+ reply_note.project = project
+ reply_note.merge_request = merge_request
+
+ expect(reply_note.discussion_id).to eq('NEW_DISCUSSION_ID')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gl_repository/identifier_spec.rb b/spec/lib/gitlab/gl_repository/identifier_spec.rb
index e0622e30e7a..0a8559dd800 100644
--- a/spec/lib/gitlab/gl_repository/identifier_spec.rb
+++ b/spec/lib/gitlab/gl_repository/identifier_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::GlRepository::Identifier do
let_it_be(:project) { create(:project) }
- 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_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
describe 'project repository' do
it_behaves_like 'parsing gl_repository identifier' do
diff --git a/spec/lib/gitlab/gl_repository/repo_type_spec.rb b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
index 71a4c693f9d..0ec94563cbb 100644
--- a/spec/lib/gitlab/gl_repository/repo_type_spec.rb
+++ b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
@@ -3,8 +3,8 @@ require 'spec_helper'
RSpec.describe Gitlab::GlRepository::RepoType do
let_it_be(:project) { create(:project) }
- 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_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
let(:project_path) { project.repository.full_path }
let(:wiki_path) { project.wiki.repository.full_path }
diff --git a/spec/lib/gitlab/gon_helper_spec.rb b/spec/lib/gitlab/gon_helper_spec.rb
index b8ed4cf608d..047873d8237 100644
--- a/spec/lib/gitlab/gon_helper_spec.rb
+++ b/spec/lib/gitlab/gon_helper_spec.rb
@@ -6,9 +6,41 @@ RSpec.describe Gitlab::GonHelper do
let(:helper) do
Class.new do
include Gitlab::GonHelper
+
+ def current_user
+ nil
+ end
end.new
end
+ describe '#add_gon_variables' do
+ let(:gon) { double('gon').as_null_object }
+ let(:https) { true }
+
+ before do
+ allow(helper).to receive(:gon).and_return(gon)
+ stub_config_setting(https: https)
+ end
+
+ context 'when HTTPS is enabled' do
+ it 'sets the secure flag to true' do
+ expect(gon).to receive(:secure=).with(true)
+
+ helper.add_gon_variables
+ end
+ end
+
+ context 'when HTTP is enabled' do
+ let(:https) { false }
+
+ it 'sets the secure flag to false' do
+ expect(gon).to receive(:secure=).with(false)
+
+ helper.add_gon_variables
+ end
+ end
+ end
+
describe '#push_frontend_feature_flag' do
before do
skip_feature_flags_yaml_validation
diff --git a/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb b/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb
index 73e25f23848..274cc83a6be 100644
--- a/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe ::Gitlab::Graphql::Authorize::ObjectAuthorization do
describe '#ok?' do
diff --git a/spec/lib/gitlab/graphql/batch_key_spec.rb b/spec/lib/gitlab/graphql/batch_key_spec.rb
index 7b73b27f24b..43e248885c2 100644
--- a/spec/lib/gitlab/graphql/batch_key_spec.rb
+++ b/spec/lib/gitlab/graphql/batch_key_spec.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'test_prof/recipes/rspec/let_it_be'
RSpec.describe ::Gitlab::Graphql::BatchKey do
- let_it_be(:rect) { Struct.new(:len, :width) }
- let_it_be(:circle) { Struct.new(:radius) }
-
+ let(:rect) { Struct.new(:len, :width) }
+ let(:circle) { Struct.new(:radius) }
let(:lookahead) { nil }
let(:object) { rect.new(2, 3) }
diff --git a/spec/lib/gitlab/graphql/markdown_field_spec.rb b/spec/lib/gitlab/graphql/markdown_field_spec.rb
index a3fb0bbbed8..c2253811e91 100644
--- a/spec/lib/gitlab/graphql/markdown_field_spec.rb
+++ b/spec/lib/gitlab/graphql/markdown_field_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Gitlab::Graphql::MarkdownField do
end
it 'shows the reference to users that are allowed to see it' do
- context = GraphQL::Query::Context.new(query: query, values: { current_user: project.owner }, object: nil)
+ context = GraphQL::Query::Context.new(query: query, values: { current_user: project.first_owner }, object: nil)
type_instance = type_class.authorized_new(note, context)
expect(field.to_graphql.resolve(type_instance, {}, context)).to include(issue_path(issue))
diff --git a/spec/lib/gitlab/graphql/queries_spec.rb b/spec/lib/gitlab/graphql/queries_spec.rb
index 8b7f4ca7933..ad1aaac712e 100644
--- a/spec/lib/gitlab/graphql/queries_spec.rb
+++ b/spec/lib/gitlab/graphql/queries_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'fast_spec_helper'
-require "test_prof/recipes/rspec/let_it_be"
RSpec.describe Gitlab::Graphql::Queries do
shared_examples 'a valid GraphQL query for the blog schema' do
diff --git a/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb
index 6eff816b95a..264fe993197 100644
--- a/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb
+++ b/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require "fast_spec_helper"
-require "support/graphql/fake_tracer"
-require "support/graphql/fake_query_type"
+
+require 'spec_helper'
RSpec.describe Gitlab::Graphql::Tracers::ApplicationContextTracer do
let(:tracer_spy) { spy('tracer_spy') }
diff --git a/spec/lib/gitlab/hook_data/project_builder_spec.rb b/spec/lib/gitlab/hook_data/project_builder_spec.rb
index 672dbab918f..e86ac66b1ad 100644
--- a/spec/lib/gitlab/hook_data/project_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/project_builder_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
let(:attributes) do
[
:event_name, :created_at, :updated_at, :name, :path, :path_with_namespace, :project_id,
- :owner_name, :owner_email, :project_visibility
+ :owners, :owner_name, :owner_email, :project_visibility
]
end
@@ -30,6 +30,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
expect(data[:project_id]).to eq(project.id)
expect(data[:owner_name]).to eq('John')
expect(data[:owner_email]).to eq('john@example.com')
+ expect(data[:owners]).to contain_exactly({ name: 'John', email: 'john@example.com' })
expect(data[:project_visibility]).to eq('internal')
end
end
diff --git a/spec/lib/gitlab/http_connection_adapter_spec.rb b/spec/lib/gitlab/http_connection_adapter_spec.rb
index 7c57d162e9b..e9e517f1fe6 100644
--- a/spec/lib/gitlab/http_connection_adapter_spec.rb
+++ b/spec/lib/gitlab/http_connection_adapter_spec.rb
@@ -15,11 +15,33 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
stub_all_dns('https://example.org', ip_address: '93.184.216.34')
end
+ context 'with use_read_total_timeout option' do
+ let(:options) { { use_read_total_timeout: true } }
+
+ it 'sets up the connection using the Gitlab::NetHttpAdapter' do
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
+ expect(connection.address).to eq('93.184.216.34')
+ expect(connection.hostname_override).to eq('example.org')
+ expect(connection.addr_port).to eq('example.org')
+ expect(connection.port).to eq(443)
+ end
+ end
+
+ context 'with header_read_timeout_buffered_io feature disabled' do
+ before do
+ stub_feature_flags(header_read_timeout_buffered_io: false)
+ end
+
+ it 'uses the regular Net::HTTP class' do
+ expect(connection).to be_a(Net::HTTP)
+ end
+ end
+
context 'when local requests are allowed' do
let(:options) { { allow_local_requests: true } }
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('93.184.216.34')
expect(connection.hostname_override).to eq('example.org')
expect(connection.addr_port).to eq('example.org')
@@ -31,7 +53,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
let(:options) { { allow_local_requests: false } }
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('93.184.216.34')
expect(connection.hostname_override).to eq('example.org')
expect(connection.addr_port).to eq('example.org')
@@ -52,7 +74,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
let(:options) { { allow_local_requests: true } }
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('172.16.0.0')
expect(connection.hostname_override).to be(nil)
expect(connection.addr_port).to eq('172.16.0.0')
@@ -75,7 +97,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
let(:options) { { allow_local_requests: true } }
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('127.0.0.1')
expect(connection.hostname_override).to be(nil)
expect(connection.addr_port).to eq('127.0.0.1')
@@ -88,7 +110,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
let(:uri) { URI('https://example.org:8080') }
it 'sets up the addr_port accordingly' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('93.184.216.34')
expect(connection.hostname_override).to eq('example.org')
expect(connection.addr_port).to eq('example.org:8080')
@@ -103,7 +125,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
end
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('example.org')
expect(connection.hostname_override).to eq(nil)
expect(connection.addr_port).to eq('example.org')
@@ -117,7 +139,7 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
end
it 'sets up the connection' do
- expect(connection).to be_a(Net::HTTP)
+ expect(connection).to be_a(Gitlab::NetHttpAdapter)
expect(connection.address).to eq('example.org')
expect(connection.hostname_override).to eq(nil)
expect(connection.addr_port).to eq('example.org')
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index 7d459f2d88a..7dbd21e6914 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::HTTP do
end
context 'when reading the response is too slow' do
- before do
+ before(:all) do
# Override Net::HTTP to add a delay between sending each response chunk
mocked_http = Class.new(Net::HTTP) do
def request(*)
@@ -51,8 +51,17 @@ RSpec.describe Gitlab::HTTP do
end
@original_net_http = Net.send(:remove_const, :HTTP)
+ @webmock_net_http = WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get('@webMockNetHTTP')
+
Net.send(:const_set, :HTTP, mocked_http)
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_set('@webMockNetHTTP', mocked_http)
+
+ # Reload Gitlab::NetHttpAdapter
+ Gitlab.send(:remove_const, :NetHttpAdapter)
+ load "#{Rails.root}/lib/gitlab/net_http_adapter.rb"
+ end
+ before do
stub_const("#{described_class}::DEFAULT_READ_TOTAL_TIMEOUT", 0.001.seconds)
WebMock.stub_request(:post, /.*/).to_return do |request|
@@ -60,9 +69,14 @@ RSpec.describe Gitlab::HTTP do
end
end
- after do
+ after(:all) do
Net.send(:remove_const, :HTTP)
Net.send(:const_set, :HTTP, @original_net_http)
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_set('@webMockNetHTTP', @webmock_net_http)
+
+ # Reload Gitlab::NetHttpAdapter
+ Gitlab.send(:remove_const, :NetHttpAdapter)
+ load "#{Rails.root}/lib/gitlab/net_http_adapter.rb"
end
let(:options) { {} }
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index f4a112d35aa..ce13f405459 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -529,6 +529,7 @@ project:
- vulnerability_feedback
- vulnerability_identifiers
- vulnerability_scanners
+- dast_profiles
- dast_site_profiles
- dast_scanner_profiles
- dast_sites
@@ -605,6 +606,7 @@ project:
- ci_project_mirror
- sync_events
- secure_files
+- security_trainings
award_emoji:
- awardable
- user
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 31512259bb1..738a76d3360 100644
--- a/spec/lib/gitlab/import_export/command_line_util_spec.rb
+++ b/spec/lib/gitlab/import_export/command_line_util_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
include Gitlab::ImportExport::CommandLineUtil
end.new
- expect { klass.tar_cf(archive: 'test', dir: 'test') }.to raise_error(Gitlab::ImportExport::Error, 'System call failed')
+ expect { klass.tar_cf(archive: 'test', dir: 'test') }.to raise_error(Gitlab::ImportExport::Error, 'command exited with error code 1: Error')
end
end
end
@@ -125,14 +125,31 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
end
context 'when something goes wrong' do
- it 'raises an error' do
+ before do
expect(Gitlab::Popen).to receive(:popen).and_return(['Error', 1])
+ end
+ it 'raises an error' do
klass = Class.new do
include Gitlab::ImportExport::CommandLineUtil
end.new
- expect { klass.untar_xf(archive: 'test', dir: 'test') }.to raise_error(Gitlab::ImportExport::Error, 'System call failed')
+ expect { klass.untar_xf(archive: 'test', dir: 'test') }.to raise_error(Gitlab::ImportExport::Error, 'command exited with error code 1: Error')
+ end
+
+ it 'returns false and includes error status' do
+ klass = Class.new do
+ include Gitlab::ImportExport::CommandLineUtil
+
+ attr_accessor :shared
+
+ def initialize
+ @shared = Gitlab::ImportExport::Shared.new(nil)
+ end
+ end.new
+
+ expect(klass.tar_czf(archive: 'test', dir: 'test')).to eq(false)
+ expect(klass.shared.errors).to eq(['command exited with error code 1: Error'])
end
end
end
diff --git a/spec/lib/gitlab/import_export/config_spec.rb b/spec/lib/gitlab/import_export/config_spec.rb
index 7ad5d3d846c..fcb48678b88 100644
--- a/spec/lib/gitlab/import_export/config_spec.rb
+++ b/spec/lib/gitlab/import_export/config_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'rspec-parameterized'
+require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Config do
let(:yaml_file) { described_class.new }
diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
index adb613c3abc..ce888b71d5e 100644
--- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
@@ -240,7 +240,7 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
merge_request = create(:merge_request, source_project: project, milestone: milestone)
ci_build = create(:ci_build, project: project, when: nil)
- ci_build.pipeline.update(project: project)
+ ci_build.pipeline.update!(project: project)
create(:commit_status, project: project, pipeline: ci_build.pipeline)
create_list(:ci_pipeline, 5, :success, project: project)
diff --git a/spec/lib/gitlab/import_export/fork_spec.rb b/spec/lib/gitlab/import_export/fork_spec.rb
index 65c28a8b8a2..25c82588c13 100644
--- a/spec/lib/gitlab/import_export/fork_spec.rb
+++ b/spec/lib/gitlab/import_export/fork_spec.rb
@@ -38,8 +38,8 @@ RSpec.describe 'forked project import' do
allow(instance).to receive(:storage_path).and_return(export_path)
end
- saver.save
- repo_saver.save
+ saver.save # rubocop:disable Rails/SaveBang
+ repo_saver.save # rubocop:disable Rails/SaveBang
repo_restorer.restore
restorer.restore
diff --git a/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb b/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
index e075c5acfea..31d647f883a 100644
--- a/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::ImportExport::Group::LegacyTreeSaver do
# ^ These are specific for the Group::LegacyTreeSaver
context 'JSON' do
let(:saved_group_json) do
- group_tree_saver.save
+ group_tree_saver.save # rubocop:disable Rails/SaveBang
group_json(group_tree_saver.full_path)
end
@@ -88,7 +88,7 @@ RSpec.describe Gitlab::ImportExport::Group::LegacyTreeSaver do
end
before do
- user2.update(public_email: user2.email)
+ user2.update!(public_email: user2.email)
group.add_developer(user2)
end
diff --git a/spec/lib/gitlab/import_export/group/relation_factory_spec.rb b/spec/lib/gitlab/import_export/group/relation_factory_spec.rb
index 63286fc0719..8e7fe8849d4 100644
--- a/spec/lib/gitlab/import_export/group/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/group/relation_factory_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::ImportExport::Group::RelationFactory do
let(:importer_user) { admin }
let(:excluded_keys) { [] }
let(:created_object) do
- described_class.create(
+ described_class.create( # rubocop:disable Rails/SaveBang
relation_sym: relation_sym,
relation_hash: relation_hash,
relation_index: 1,
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 c52daa8ccfd..de4d193a21c 100644
--- a/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe Gitlab::ImportExport::Group::TreeSaver do
context 'exported files' do
before do
- group_tree_saver.save
+ group_tree_saver.save # rubocop:disable Rails/SaveBang
end
it 'has one group per line' do
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index 20f0f6af6f3..c9d559c992c 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::ImportExport::Importer do
stub_uploads_object_storage(FileUploader)
FileUtils.mkdir_p(shared.export_path)
- ImportExportUpload.create(project: project, import_file: import_file)
+ ImportExportUpload.create!(project: project, import_file: import_file)
allow(FileUtils).to receive(:rm_rf).and_call_original
end
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 d69d775fffb..352af18c822 100644
--- a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
@@ -183,24 +183,8 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
end
describe '.batch_size' do
- context 'when export_reduce_relation_batch_size feature flag is enabled' do
- before do
- stub_feature_flags(export_reduce_relation_batch_size: true)
- end
-
- it 'returns 20' do
- expect(described_class.batch_size(exportable)).to eq(described_class::SMALLER_BATCH_SIZE)
- end
- end
-
- context 'when export_reduce_relation_batch_size feature flag is disabled' do
- before do
- stub_feature_flags(export_reduce_relation_batch_size: false)
- end
-
- it 'returns default batch size' do
- expect(described_class.batch_size(exportable)).to eq(described_class::BATCH_SIZE)
- end
+ it 'returns default batch size' do
+ expect(described_class.batch_size(exportable)).to eq(described_class::BATCH_SIZE)
end
end
end
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 3b7ed7cb32b..0d372def8b0 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
@@ -8,35 +8,17 @@ RSpec.describe Gitlab::ImportExport::LegacyRelationTreeSaver do
let(:tree) { {} }
describe '#serialize' do
- shared_examples 'FastHashSerializer with batch size' do |batch_size|
- let(:serializer) { instance_double(Gitlab::ImportExport::FastHashSerializer) }
+ let(:serializer) { instance_double(Gitlab::ImportExport::FastHashSerializer) }
- it 'uses FastHashSerializer' do
- expect(Gitlab::ImportExport::FastHashSerializer)
- .to receive(:new)
- .with(exportable, tree, batch_size: batch_size)
- .and_return(serializer)
+ it 'uses FastHashSerializer' do
+ expect(Gitlab::ImportExport::FastHashSerializer)
+ .to receive(:new)
+ .with(exportable, tree, batch_size: Gitlab::ImportExport::Json::StreamingSerializer::BATCH_SIZE)
+ .and_return(serializer)
- expect(serializer).to receive(:execute)
+ expect(serializer).to receive(:execute)
- relation_tree_saver.serialize(exportable, tree)
- end
- end
-
- context 'when export_reduce_relation_batch_size feature flag is enabled' do
- before do
- stub_feature_flags(export_reduce_relation_batch_size: true)
- end
-
- 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
- before do
- stub_feature_flags(export_reduce_relation_batch_size: false)
- end
-
- include_examples 'FastHashSerializer with batch size', Gitlab::ImportExport::Json::StreamingSerializer::BATCH_SIZE
+ relation_tree_saver.serialize(exportable, tree)
end
end
end
diff --git a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
index c8887b0ded1..fe064c50b9e 100644
--- a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::ImportExport::LfsRestorer do
)
end
- saver.save
+ saver.save # rubocop:disable Rails/SaveBang
project.lfs_objects.delete_all
end
@@ -81,7 +81,7 @@ RSpec.describe Gitlab::ImportExport::LfsRestorer do
context 'when there is not an existing `LfsObject`' do
before do
- lfs_object.destroy
+ lfs_object.destroy!
end
it 'creates a new lfs object' do
diff --git a/spec/lib/gitlab/import_export/lfs_saver_spec.rb b/spec/lib/gitlab/import_export/lfs_saver_spec.rb
index 55b4f7479b8..84bd782c467 100644
--- a/spec/lib/gitlab/import_export/lfs_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/lfs_saver_spec.rb
@@ -34,13 +34,13 @@ RSpec.describe Gitlab::ImportExport::LfsSaver do
end
it 'does not cause errors' do
- saver.save
+ saver.save # rubocop:disable Rails/SaveBang
expect(shared.errors).to be_empty
end
it 'copies the file in the correct location when there is an lfs object' do
- saver.save
+ saver.save # rubocop:disable Rails/SaveBang
expect(File).to exist("#{shared.export_path}/lfs-objects/#{lfs_object.oid}")
end
@@ -61,7 +61,7 @@ RSpec.describe Gitlab::ImportExport::LfsSaver do
end
it 'saves a json file correctly' do
- saver.save
+ saver.save # rubocop:disable Rails/SaveBang
expect(File.exist?(lfs_json_file)).to eq(true)
expect(lfs_json).to eq(
@@ -96,7 +96,7 @@ RSpec.describe Gitlab::ImportExport::LfsSaver do
expect(fake_uri).to receive(:open).and_return(StringIO.new('LFS file content'))
expect(URI).to receive(:parse).with('http://my-object-storage.local').and_return(fake_uri)
- saver.save
+ saver.save # rubocop:disable Rails/SaveBang
expect(File.read(exported_file_path)).to eq('LFS file content')
end
diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb
index 8b9ca90a280..8d9bff9c610 100644
--- a/spec/lib/gitlab/import_export/members_mapper_spec.rb
+++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb
@@ -243,7 +243,6 @@ RSpec.describe Gitlab::ImportExport::MembersMapper do
before do
group.add_users([user, user2], GroupMember::DEVELOPER)
- user.update(public_email: 'invite@test.com')
end
it 'maps the importer' do
diff --git a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
index ea8b10675af..ffbbf9326ec 100644
--- a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
let(:importer_user) { admin }
let(:excluded_keys) { [] }
let(:created_object) do
- described_class.create(
+ described_class.create( # rubocop:disable Rails/SaveBang
relation_sym: relation_sym,
relation_hash: relation_hash,
relation_index: 1,
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 1d8b137c196..8884722254d 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -880,7 +880,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
before do
group = create(:group, visibility_level: group_visibility)
group.add_users([user], GroupMember::MAINTAINER)
- project.update(group: group)
+ project.update!(group: group)
end
context 'private group visibility' do
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index f68ec21039d..ba781ae78b7 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
project_tree_saver = described_class.new(project: project, current_user: user, shared: shared)
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
end
@@ -305,14 +305,14 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
end
before do
- user2.update(public_email: user2.email)
+ user2.update!(public_email: user2.email)
group.add_developer(user2)
end
context 'when has no permission' do
before do
group.add_developer(user)
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
it 'does not export group members' do
@@ -324,7 +324,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
before do
group.add_maintainer(user)
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
it 'does not export group members' do
@@ -336,7 +336,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
before do
group.add_owner(user)
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
it 'exports group members as group owner' do
@@ -348,7 +348,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
let(:user) { create(:admin) }
before do
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
context 'when admin mode is enabled', :enable_admin_mode do
@@ -376,7 +376,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
let(:relation_name) { :projects }
before do
- project_tree_saver.save
+ project_tree_saver.save # rubocop:disable Rails/SaveBang
end
it { is_expected.to include({ 'description' => params[:description] }) }
@@ -471,7 +471,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
merge_request = create(:merge_request, source_project: project, milestone: milestone)
ci_build = create(:ci_build, project: project, when: nil)
- ci_build.pipeline.update(project: project)
+ ci_build.pipeline.update!(project: project)
create(:commit_status, project: project, pipeline: ci_build.pipeline)
create(:milestone, project: project)
diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
index 718a23f80a1..c0215ff5843 100644
--- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do
before do
allow(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
- bundler.save
+ bundler.save # rubocop:disable Rails/SaveBang
end
after do
diff --git a/spec/lib/gitlab/import_export/saver_spec.rb b/spec/lib/gitlab/import_export/saver_spec.rb
index 877474dd862..f5eed81f73c 100644
--- a/spec/lib/gitlab/import_export/saver_spec.rb
+++ b/spec/lib/gitlab/import_export/saver_spec.rb
@@ -30,19 +30,63 @@ RSpec.describe Gitlab::ImportExport::Saver do
it 'saves the repo using object storage' do
stub_uploads_object_storage(ImportExportUploader)
- subject.save
+ subject.save # rubocop:disable Rails/SaveBang
expect(ImportExportUpload.find_by(project: project).export_file.url)
.to match(%r[\/uploads\/-\/system\/import_export_upload\/export_file.*])
end
+ it 'logs metrics after saving' do
+ stub_uploads_object_storage(ImportExportUploader)
+ expect(Gitlab::Export::Logger).to receive(:info).with(
+ hash_including(
+ message: 'Export archive saved',
+ exportable_class: 'Project',
+ 'correlation_id' => anything,
+ archive_file: anything,
+ compress_duration_s: anything
+ )).and_call_original
+
+ expect(Gitlab::Export::Logger).to receive(:info).with(
+ hash_including(
+ message: 'Export archive uploaded',
+ exportable_class: 'Project',
+ 'correlation_id' => anything,
+ archive_file: anything,
+ compress_duration_s: anything,
+ assign_duration_s: anything,
+ upload_duration_s: anything,
+ upload_bytes: anything
+ )).and_call_original
+
+ subject.save # rubocop:disable Rails/SaveBang
+ end
+
it 'removes archive path and keeps base path untouched' do
allow(shared).to receive(:archive_path).and_return(archive_path)
- subject.save
+ subject.save # rubocop:disable Rails/SaveBang
expect(FileUtils).not_to have_received(:rm_rf).with(base_path)
expect(FileUtils).to have_received(:rm_rf).with(archive_path)
expect(Dir.exist?(archive_path)).to eq(false)
end
+
+ context 'when save throws an exception' do
+ before do
+ expect(subject).to receive(:save_upload).and_raise(SocketError.new)
+ end
+
+ it 'logs a saver error' do
+ allow(Gitlab::Export::Logger).to receive(:info).with(anything).and_call_original
+ expect(Gitlab::Export::Logger).to receive(:info).with(
+ hash_including(
+ message: 'Export archive saver failed',
+ exportable_class: 'Project',
+ 'correlation_id' => anything
+ )).and_call_original
+
+ subject.save # rubocop:disable Rails/SaveBang
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb b/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
index 7d719b6028f..2f39cb560d0 100644
--- a/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::ImportExport::SnippetRepoRestorer do
let!(:snippet_with_repo) { create(:project_snippet, :repository, project: project, author: user) }
let(:bundle_path) { ::Gitlab::ImportExport.snippets_repo_bundle_path(shared.export_path) }
let(:snippet_bundle_path) { File.join(bundle_path, "#{snippet_with_repo.hexdigest}.bundle") }
- let(:result) { exporter.save }
+ let(:result) { exporter.save } # rubocop:disable Rails/SaveBang
let(:repository) { snippet.repository }
before do
diff --git a/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb b/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
index 9f3e8d2fa86..9a9f40b3d0c 100644
--- a/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::ImportExport::SnippetRepoSaver do
aggregate_failures do
expect(snippet.repository).not_to receive(:bundle_to_disk)
- bundler.save
+ bundler.save # rubocop:disable Rails/SaveBang
expect(Dir.empty?(bundle_path)).to be_truthy
end
diff --git a/spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb b/spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
index 7ca365762b5..e529d36fd11 100644
--- a/spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Gitlab::ImportExport::SnippetsRepoRestorer do
let!(:snippet2) { create(:project_snippet, project: project, author: user) }
before do
- exporter.save
+ exporter.save # rubocop:disable Rails/SaveBang
expect(File.exist?(bundle_path(snippet1))).to be true
expect(File.exist?(bundle_path(snippet2))).to be false
@@ -78,7 +78,7 @@ RSpec.describe Gitlab::ImportExport::SnippetsRepoRestorer do
let!(:snippet2) { create(:project_snippet, :repository, project: project, author: user) }
before do
- exporter.save
+ exporter.save # rubocop:disable Rails/SaveBang
expect(File.exist?(bundle_path(snippet1))).to be true
expect(File.exist?(bundle_path(snippet2))).to be true
diff --git a/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb b/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
index aa284c60e73..eaa58c77aff 100644
--- a/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::ImportExport::SnippetsRepoSaver do
snippets_dir = ::Gitlab::ImportExport.snippets_repo_bundle_path(shared.export_path)
expect(Dir.exist?(snippets_dir)).to be_falsey
- bundler.save
+ bundler.save # rubocop:disable Rails/SaveBang
expect(Dir.exist?(snippets_dir)).to be_truthy
end
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::ImportExport::SnippetsRepoSaver do
it 'does not perform any action' do
expect(Gitlab::ImportExport::SnippetRepoSaver).not_to receive(:new)
- bundler.save
+ bundler.save # rubocop:disable Rails/SaveBang
end
end
@@ -40,7 +40,7 @@ RSpec.describe Gitlab::ImportExport::SnippetsRepoSaver do
allow(Gitlab::ImportExport::SnippetRepoSaver).to receive(:new).and_return(service)
expect(service).to receive(:save).and_return(true).twice
- bundler.save
+ bundler.save # rubocop:disable Rails/SaveBang
end
context 'when one snippet cannot be saved' do
diff --git a/spec/lib/gitlab/import_export/uploads_manager_spec.rb b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
index 8282ad9a070..0cfe3a69a09 100644
--- a/spec/lib/gitlab/import_export/uploads_manager_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
@@ -31,13 +31,13 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
let(:upload) { create(:upload, :issuable_upload, :with_file, model: project) }
it 'does not cause errors' do
- manager.save
+ manager.save # rubocop:disable Rails/SaveBang
expect(shared.errors).to be_empty
end
it 'copies the file in the correct location when there is an upload' do
- manager.save
+ manager.save # rubocop:disable Rails/SaveBang
expect(File).to exist(exported_file_path)
end
@@ -56,7 +56,7 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
end
it 'excludes orphaned upload files' do
- manager.save
+ manager.save # rubocop:disable Rails/SaveBang
expect(File).not_to exist(exported_orphan_path)
end
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
end
it 'does not cause errors' do
- manager.save
+ manager.save # rubocop:disable Rails/SaveBang
expect(shared.errors).to be_empty
end
@@ -84,7 +84,7 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
it 'ignores problematic upload and logs exception' do
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(Errno::ENAMETOOLONG), project_id: project.id)
- manager.save
+ manager.save # rubocop:disable Rails/SaveBang
expect(shared.errors).to be_empty
expect(File).not_to exist(exported_file_path)
diff --git a/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb b/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
index 535cce6aa04..c5288b9afbc 100644
--- a/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
+++ b/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription do
describe '#to_s' do
diff --git a/spec/lib/gitlab/json_spec.rb b/spec/lib/gitlab/json_spec.rb
index f9f57752b0a..5ffe736da54 100644
--- a/spec/lib/gitlab/json_spec.rb
+++ b/spec/lib/gitlab/json_spec.rb
@@ -317,36 +317,14 @@ RSpec.describe Gitlab::Json do
let(:env) { {} }
let(:result) { "{\"test\":true}" }
- context "grape_gitlab_json flag is enabled" do
- before do
- stub_feature_flags(grape_gitlab_json: true)
- end
-
- it "generates JSON" do
- expect(subject).to eq(result)
- end
-
- it "uses Gitlab::Json" do
- expect(Gitlab::Json).to receive(:dump).with(obj)
-
- subject
- end
+ it "generates JSON" do
+ expect(subject).to eq(result)
end
- context "grape_gitlab_json flag is disabled" do
- before do
- stub_feature_flags(grape_gitlab_json: false)
- end
+ it "uses Gitlab::Json" do
+ expect(Gitlab::Json).to receive(:dump).with(obj)
- it "generates JSON" do
- expect(subject).to eq(result)
- end
-
- it "uses Grape::Formatter::Json" do
- expect(Grape::Formatter::Json).to receive(:call).with(obj, env)
-
- subject
- end
+ subject
end
context "precompiled JSON" do
@@ -440,15 +418,5 @@ RSpec.describe Gitlab::Json do
expect(subject.size).to eq(10001)
end
end
-
- context 'when json_limited_encoder is disabled' do
- let(:obj) { [{ test: true }] * 1000 }
-
- it 'does not raise an error' do
- stub_feature_flags(json_limited_encoder: false)
-
- expect { subject }.not_to raise_error
- end
- end
end
end
diff --git a/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb b/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
index 2e373613269..3028e0a13aa 100644
--- a/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
@@ -2,6 +2,8 @@
require 'fast_spec_helper'
+require_relative '../../../../lib/gitlab/kubernetes/pod_cmd'
+
RSpec.describe Gitlab::Kubernetes::KubectlCmd do
describe '.delete' do
it 'constructs string properly' do
diff --git a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
index 73b35d3a4e7..cbd1a30c417 100644
--- a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
@@ -63,5 +63,13 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
expect(release.valid?).to eq false
end
end
+
+ context 'when release has NULL tag' do
+ let(:raw_data) { double(base_data.merge(tag_name: '')) }
+
+ it 'returns false' do
+ expect(release.valid?).to eq false
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/metrics/boot_time_tracker_spec.rb b/spec/lib/gitlab/metrics/boot_time_tracker_spec.rb
new file mode 100644
index 00000000000..8a17fa8dd2e
--- /dev/null
+++ b/spec/lib/gitlab/metrics/boot_time_tracker_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Metrics::BootTimeTracker do
+ let(:logger) { double('logger') }
+ let(:gauge) { double('gauge') }
+
+ subject(:tracker) { described_class.instance }
+
+ before do
+ described_class.instance.reset!
+
+ allow(logger).to receive(:info)
+ allow(gauge).to receive(:set)
+ allow(Gitlab::Metrics).to receive(:gauge).and_return(gauge)
+ end
+
+ describe '#track_boot_time!' do
+ described_class::SUPPORTED_RUNTIMES.each do |runtime|
+ context "when called on #{runtime} for the first time" do
+ before do
+ expect(Gitlab::Runtime).to receive(:safe_identify).and_return(runtime)
+ end
+
+ it 'set the startup_time' do
+ tracker.track_boot_time!(logger: logger)
+
+ expect(tracker.startup_time).to be > 0
+ end
+
+ it 'records the current process runtime' do
+ expect(Gitlab::Metrics::System).to receive(:process_runtime_elapsed_seconds).once
+
+ tracker.track_boot_time!(logger: logger)
+ end
+
+ it 'logs the application boot time' do
+ expect(Gitlab::Metrics::System).to receive(:process_runtime_elapsed_seconds).and_return(42)
+ expect(logger).to receive(:info).with(message: 'Application boot finished', runtime: runtime.to_s, duration_s: 42)
+
+ tracker.track_boot_time!(logger: logger)
+ end
+
+ it 'tracks boot time in a prometheus gauge' do
+ expect(Gitlab::Metrics::System).to receive(:process_runtime_elapsed_seconds).and_return(42)
+ expect(gauge).to receive(:set).with({}, 42)
+
+ tracker.track_boot_time!(logger: logger)
+ end
+
+ context 'on subsequent calls' do
+ it 'does nothing' do
+ tracker.track_boot_time!(logger: logger)
+
+ expect(Gitlab::Metrics::System).not_to receive(:process_runtime_elapsed_seconds)
+ expect(logger).not_to receive(:info)
+ expect(gauge).not_to receive(:set)
+
+ tracker.track_boot_time!(logger: logger)
+ end
+ end
+ end
+ end
+
+ context 'when called on other runtimes' do
+ it 'does nothing' do
+ tracker.track_boot_time!(logger: logger)
+
+ expect(Gitlab::Metrics::System).not_to receive(:process_runtime_elapsed_seconds)
+ expect(logger).not_to receive(:info)
+ expect(gauge).not_to receive(:set)
+
+ tracker.track_boot_time!(logger: logger)
+ end
+ end
+ end
+
+ describe '#startup_time' do
+ it 'returns 0 when boot time not tracked' do
+ expect(tracker.startup_time).to eq(0)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb
deleted file mode 100644
index 0531bccf4b4..00000000000
--- a/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Metrics::Exporter::WebExporter do
- let(:exporter) { described_class.new }
- let(:readiness_probe) { exporter.send(:readiness_probe).execute }
-
- before do
- stub_config(
- monitoring: {
- web_exporter: {
- enabled: true,
- port: 0,
- address: '127.0.0.1'
- }
- }
- )
-
- exporter.start
- end
-
- after do
- exporter.stop
- end
-
- context 'when running server', :prometheus do
- it 'readiness probe returns succesful status' do
- expect(readiness_probe.http_status).to eq(200)
- expect(readiness_probe.json).to include(status: 'ok')
- expect(readiness_probe.json).to include('web_exporter' => [{ 'status': 'ok' }])
- end
-
- it 'initializes request metrics' do
- expect(Gitlab::Metrics::RailsSlis).to receive(:initialize_request_slis_if_needed!).and_call_original
-
- http = Net::HTTP.new(exporter.server.config[:BindAddress], exporter.server.config[:Port])
- response = http.request(Net::HTTP::Get.new('/metrics'))
-
- expect(response.body).to include('gitlab_sli:rails_request_apdex')
- end
- end
-
- describe '#mark_as_not_running!' do
- it 'readiness probe returns a failure status', :prometheus do
- exporter.mark_as_not_running!
-
- expect(readiness_probe.http_status).to eq(503)
- expect(readiness_probe.json).to include(status: 'failed')
- expect(readiness_probe.json).to include('web_exporter' => [{ 'status': 'failed' }])
- end
- end
-end
diff --git a/spec/lib/gitlab/metrics/rails_slis_spec.rb b/spec/lib/gitlab/metrics/rails_slis_spec.rb
index a5ccf7fafa4..0c77dc9f582 100644
--- a/spec/lib/gitlab/metrics/rails_slis_spec.rb
+++ b/spec/lib/gitlab/metrics/rails_slis_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::Metrics::RailsSlis do
allow(Gitlab::Graphql::KnownOperations).to receive(:default).and_return(Gitlab::Graphql::KnownOperations.new(%w(foo bar)))
end
- describe '.initialize_request_slis_if_needed!' do
+ describe '.initialize_request_slis!' do
it "initializes the SLI for all possible endpoints if they weren't", :aggregate_failures do
possible_labels = [
{
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::Metrics::RailsSlis do
expect(Gitlab::Metrics::Sli).to receive(:initialize_sli).with(:rails_request_apdex, array_including(*possible_labels)).and_call_original
expect(Gitlab::Metrics::Sli).to receive(:initialize_sli).with(:graphql_query_apdex, array_including(*possible_graphql_labels)).and_call_original
- described_class.initialize_request_slis_if_needed!
+ described_class.initialize_request_slis!
end
it 'does not initialize the SLI if they were initialized already', :aggregate_failures do
@@ -49,13 +49,13 @@ RSpec.describe Gitlab::Metrics::RailsSlis do
expect(Gitlab::Metrics::Sli).to receive(:initialized?).with(:graphql_query_apdex) { true }
expect(Gitlab::Metrics::Sli).not_to receive(:initialize_sli)
- described_class.initialize_request_slis_if_needed!
+ described_class.initialize_request_slis!
end
end
describe '.request_apdex' do
it 'returns the initialized request apdex SLI object' do
- described_class.initialize_request_slis_if_needed!
+ described_class.initialize_request_slis!
expect(described_class.request_apdex).to be_initialized
end
@@ -63,7 +63,7 @@ RSpec.describe Gitlab::Metrics::RailsSlis do
describe '.graphql_query_apdex' do
it 'returns the initialized request apdex SLI object' do
- described_class.initialize_request_slis_if_needed!
+ described_class.initialize_request_slis!
expect(described_class.graphql_query_apdex).to be_initialized
end
diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
index a4877208bcf..dfae5aa6784 100644
--- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
@@ -18,6 +18,20 @@ RSpec.describe Gitlab::Metrics::Samplers::RubySampler do
expect(sampler.metrics[:process_start_time_seconds].get).to eq(Time.now.to_i)
end
end
+
+ context 'when not setting a prefix' do
+ it 'does not prepend metrics with that prefix' do
+ expect(sampler.metrics[:process_start_time_seconds].name).to eq(:ruby_process_start_time_seconds)
+ end
+ end
+
+ context 'when using custom prefix' do
+ let(:sampler) { described_class.new(prefix: 'custom') }
+
+ it 'prepends metrics with that prefix' do
+ expect(sampler.metrics[:process_start_time_seconds].name).to eq(:custom_ruby_process_start_time_seconds)
+ end
+ end
end
describe '#sample' do
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
index 732aa553737..ce3caf8cdfe 100644
--- a/spec/lib/gitlab/metrics/system_spec.rb
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -4,6 +4,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::System do
context 'when /proc files exist' do
+ # Modified column 22 to be 1000 (starttime ticks)
+ let(:proc_stat) do
+ <<~SNIP
+ 2095 (ruby) R 0 2095 2095 34818 2095 4194560 211267 7897 2 0 287 51 10 1 20 0 5 0 1000 566210560 80885 18446744073709551615 94736211292160 94736211292813 140720919612064 0 0 0 0 0 1107394127 0 0 0 17 3 0 0 0 0 0 94736211303768 94736211304544 94736226689024 140720919619473 140720919619513 140720919619513 140720919621604 0
+ SNIP
+ end
+
# Fixtures pulled from:
# Linux carbon 5.3.0-7648-generic #41~1586789791~19.10~9593806-Ubuntu SMP Mon Apr 13 17:50:40 UTC x86_64 x86_64 x86_64 GNU/Linux
let(:proc_status) do
@@ -97,6 +104,29 @@ RSpec.describe Gitlab::Metrics::System do
end
end
+ describe '.process_runtime_elapsed_seconds' do
+ it 'returns the seconds elapsed since the process was started' do
+ # sets process starttime ticks to 1000
+ mock_existing_proc_file('/proc/self/stat', proc_stat)
+ # system clock ticks/sec
+ expect(Etc).to receive(:sysconf).with(Etc::SC_CLK_TCK).and_return(100)
+ # system uptime in seconds
+ expect(::Process).to receive(:clock_gettime).and_return(15)
+
+ # uptime - (starttime_ticks / ticks_per_sec)
+ expect(described_class.process_runtime_elapsed_seconds).to eq(5)
+ end
+
+ context 'when inputs are not available' do
+ it 'returns 0' do
+ mock_missing_proc_file
+ expect(::Process).to receive(:clock_gettime).and_raise(NameError)
+
+ expect(described_class.process_runtime_elapsed_seconds).to eq(0)
+ end
+ end
+ end
+
describe '.summary' do
it 'contains a selection of the available fields' do
stub_const('RUBY_DESCRIPTION', 'ruby-3.0-patch1')
@@ -223,10 +253,10 @@ RSpec.describe Gitlab::Metrics::System do
end
def mock_existing_proc_file(path, content)
- allow(File).to receive(:foreach).with(path) { |_path, &block| content.each_line(&block) }
+ allow(File).to receive(:open).with(path) { |_path, &block| block.call(StringIO.new(content)) }
end
def mock_missing_proc_file
- allow(File).to receive(:foreach).and_raise(Errno::ENOENT)
+ allow(File).to receive(:open).and_raise(Errno::ENOENT)
end
end
diff --git a/spec/lib/gitlab/middleware/memory_report_spec.rb b/spec/lib/gitlab/middleware/memory_report_spec.rb
new file mode 100644
index 00000000000..e063866b056
--- /dev/null
+++ b/spec/lib/gitlab/middleware/memory_report_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'memory_profiler'
+
+RSpec.describe Gitlab::Middleware::MemoryReport do
+ let(:app) { proc { |env| [200, { 'Content-Type' => 'text/plain' }, ['Hello world!']] } }
+ let(:middleware) { described_class.new(app) }
+
+ describe '#call' do
+ shared_examples 'returns original response' do
+ it 'returns original response' do
+ expect(MemoryProfiler).not_to receive(:report)
+
+ status, headers, body = middleware.call(env)
+
+ expect(status).to eq(200)
+ expect(headers).to eq({ 'Content-Type' => 'text/plain' })
+ expect(body.first).to eq('Hello world!')
+ end
+
+ it 'does not call the MemoryProfiler' do
+ expect(MemoryProfiler).not_to receive(:report)
+
+ middleware.call(env)
+ end
+ end
+
+ context 'when the Rails environment is not development' do
+ let(:env) { Rack::MockRequest.env_for('/') }
+
+ it_behaves_like 'returns original response'
+ end
+
+ context 'when the Rails environment is development' do
+ before do
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ context 'when memory report is not requested' do
+ let(:env) { Rack::MockRequest.env_for('/') }
+
+ it_behaves_like 'returns original response'
+ end
+
+ context 'when memory report is requested' do
+ let(:env) { Rack::MockRequest.env_for('/', params: { 'performance_bar' => 'memory' }) }
+
+ before do
+ allow(env).to receive(:[]).and_call_original
+ allow(app).to receive(:call).and_return(empty_memory_report)
+ end
+
+ let(:empty_memory_report) do
+ report = MemoryProfiler::Results.new
+ report.register_results(MemoryProfiler::StatHash.new, MemoryProfiler::StatHash.new, 1)
+ end
+
+ it 'returns a memory report' do
+ expect(MemoryProfiler).to receive(:report).and_yield
+
+ status, headers, body = middleware.call(env)
+
+ expect(status).to eq(200)
+ expect(headers).to eq({ 'Content-Type' => 'text/plain' })
+ expect(body.first).to include('Total allocated: 0 B')
+ end
+
+ context 'when something goes wrong with creating the report' do
+ before do
+ expect(MemoryProfiler).to receive(:report).and_raise(StandardError, 'something went terribly wrong!')
+ end
+
+ it 'logs the error' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_exception)
+
+ middleware.call(env)
+ end
+
+ it 'returns the error' do
+ status, headers, body = middleware.call(env)
+
+ expect(status).to eq(500)
+ expect(headers).to eq({ 'Content-Type' => 'text/plain' })
+ expect(body.first).to include('Could not generate memory report: something went terribly wrong!')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/net_http_adapter_spec.rb b/spec/lib/gitlab/net_http_adapter_spec.rb
new file mode 100644
index 00000000000..21c1a1ebe25
--- /dev/null
+++ b/spec/lib/gitlab/net_http_adapter_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::NetHttpAdapter do
+ describe '#connect' do
+ let(:url) { 'https://example.org' }
+ let(:net_http_adapter) { described_class.new(url) }
+
+ subject(:connect) { net_http_adapter.send(:connect) }
+
+ before do
+ allow(TCPSocket).to receive(:open).and_return(Socket.new(:INET, :STREAM))
+ end
+
+ it 'uses a Gitlab::BufferedIo instance as @socket' do
+ connect
+
+ expect(net_http_adapter.instance_variable_get(:@socket)).to be_a(Gitlab::BufferedIo)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb
index 577d15b8495..42ae5844b95 100644
--- a/spec/lib/gitlab/omniauth_initializer_spec.rb
+++ b/spec/lib/gitlab/omniauth_initializer_spec.rb
@@ -101,5 +101,19 @@ RSpec.describe Gitlab::OmniauthInitializer do
subject.execute([google_config])
end
+
+ it 'configures defaults for gitlab' do
+ conf = {
+ 'name' => 'gitlab',
+ "args" => {}
+ }
+
+ expect(devise_config).to receive(:omniauth).with(
+ :gitlab,
+ authorize_params: { gl_auth_type: 'login' }
+ )
+
+ subject.execute([conf])
+ end
end
end
diff --git a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns_spec.rb b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns_spec.rb
index 2cebf0d9473..087bfb197ec 100644
--- a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns_spec.rb
@@ -16,4 +16,13 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::ArrayScopeCol
it { expect { array_scope_columns }.to raise_error /No array columns were given/ }
end
+
+ context 'when Arel AS node is given as input' do
+ let(:scope) { Issue.select(Issue.arel_table[:id].as('id'), :title) }
+ let(:columns) { scope.select_values }
+
+ it 'works with Arel AS nodes' do
+ expect(array_scope_columns.array_aggregated_column_names).to eq(%w[array_cte_id_array array_cte_title_array])
+ end
+ end
end
diff --git a/spec/lib/gitlab/pipeline_scope_counts_spec.rb b/spec/lib/gitlab/pipeline_scope_counts_spec.rb
new file mode 100644
index 00000000000..a9187ecfb54
--- /dev/null
+++ b/spec/lib/gitlab/pipeline_scope_counts_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::PipelineScopeCounts do
+ let(:current_user) { create(:user) }
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
+ let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') }
+ let_it_be(:sha_pipeline) { create(:ci_pipeline, :running, project: project, sha: 'deadbeef') }
+ let_it_be(:on_demand_dast_scan) { create(:ci_pipeline, :success, project: project, source: 'ondemand_dast_scan') }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'has policy class' do
+ expect(described_class.declarative_policy_class).to be("Ci::ProjectPipelinesPolicy")
+ end
+
+ it 'has expected attributes' do
+ expect(described_class.new(current_user, project, {})).to have_attributes(
+ all: 6,
+ finished: 3,
+ pending: 2,
+ running: 1
+ )
+ end
+
+ describe 'with large amount of pipelines' do
+ it 'sets the PIPELINES_COUNT_LIMIT constant to a value of 1_000' do
+ expect(described_class::PIPELINES_COUNT_LIMIT).to eq(1_000)
+ end
+
+ context 'when there are more records than the limit' do
+ before do
+ stub_const('Gitlab::PipelineScopeCounts::PIPELINES_COUNT_LIMIT', 3)
+ end
+
+ it 'limits the found items' do
+ expect(described_class.new(current_user, project, {}).all).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb
index 891482a5f17..8211806a809 100644
--- a/spec/lib/gitlab/popen_spec.rb
+++ b/spec/lib/gitlab/popen_spec.rb
@@ -40,6 +40,17 @@ RSpec.describe Gitlab::Popen do
it { expect(@output).to include('No such file or directory') }
end
+ context 'non-zero status with a kill' do
+ let(:cmd) { [Gem.ruby, "-e", "thr = Thread.new { sleep 5 }; Process.kill(9, Process.pid); thr.join"] }
+
+ before do
+ @output, @status = @klass.new.popen(cmd)
+ end
+
+ it { expect(@status).to eq(9) }
+ it { expect(@output).to be_empty }
+ end
+
context 'unsafe string command' do
it 'raises an error when it gets called with a string argument' do
expect { @klass.new.popen('ls', path) }.to raise_error(RuntimeError)
diff --git a/spec/lib/gitlab/process_memory_cache/helper_spec.rb b/spec/lib/gitlab/process_memory_cache/helper_spec.rb
index 27d7fd0bdcf..bad4f61282c 100644
--- a/spec/lib/gitlab/process_memory_cache/helper_spec.rb
+++ b/spec/lib/gitlab/process_memory_cache/helper_spec.rb
@@ -33,13 +33,20 @@ RSpec.describe Gitlab::ProcessMemoryCache::Helper, :use_clean_rails_memory_store
end
it 'resets the cache when the shared key is missing', :aggregate_failures do
- expect(Rails.cache).to receive(:read).with(:cached_content_instance_key).twice.and_return(nil)
+ allow(Rails.cache).to receive(:read).with(:cached_content_instance_key).and_return(nil)
is_expected.to receive(:expensive_computation).thrice.and_return(1, 2, 3)
3.times do |index|
expect(subject.cached_content).to eq(index + 1)
end
end
+
+ it 'does not set the shared timestamp if it is already present', :redis do
+ subject.clear_cached_content
+ is_expected.to receive(:expensive_computation).once.and_return(1)
+
+ expect { subject.cached_content }.not_to change { Rails.cache.read(:cached_content_instance_key) }
+ end
end
describe '.invalidate_memory_cache' do
diff --git a/spec/lib/gitlab/project_authorizations_spec.rb b/spec/lib/gitlab/project_authorizations_spec.rb
index 16066934194..7852470196b 100644
--- a/spec/lib/gitlab/project_authorizations_spec.rb
+++ b/spec/lib/gitlab/project_authorizations_spec.rb
@@ -334,7 +334,7 @@ RSpec.describe Gitlab::ProjectAuthorizations do
let(:common_id) { non_existing_record_id }
let!(:group) { create(:group, id: common_id) }
let!(:unrelated_project) { create(:project, id: common_id) }
- let(:user) { unrelated_project.owner }
+ let(:user) { unrelated_project.first_owner }
it 'does not have access to group and its projects' do
mapping = map_access_levels(authorizations)
@@ -345,4 +345,76 @@ RSpec.describe Gitlab::ProjectAuthorizations do
end
end
end
+
+ context 'with pending memberships' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ subject(:mapping) { map_access_levels(authorizations) }
+
+ context 'group membership' do
+ let!(:group_project) { create(:project, namespace: group) }
+
+ before do
+ create(:group_member, :developer, :awaiting, user: user, group: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
+ end
+ end
+
+ context 'inherited group membership' do
+ let!(:sub_group) { create(:group, parent: group) }
+ let!(:sub_group_project) { create(:project, namespace: sub_group) }
+
+ before do
+ create(:group_member, :developer, :awaiting, user: user, group: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[sub_group_project.id]).to be_nil
+ end
+ end
+
+ context 'project membership' do
+ let!(:group_project) { create(:project, namespace: group) }
+
+ before do
+ create(:project_member, :developer, :awaiting, user: user, project: group_project)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
+ end
+ end
+
+ context 'shared group' do
+ let!(:shared_group) { create(:group) }
+ let!(:shared_group_project) { create(:project, namespace: shared_group) }
+
+ before do
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ create(:group_member, :developer, :awaiting, user: user, group: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[shared_group_project.id]).to be_nil
+ end
+ end
+
+ context 'shared project' do
+ let!(:another_group) { create(:group) }
+ let!(:shared_project) { create(:project, namespace: another_group) }
+
+ before do
+ create(:project_group_link, group: group, project: shared_project)
+ create(:group_member, :developer, :awaiting, user: user, group: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[shared_project.id]).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/rack_attack/request_spec.rb b/spec/lib/gitlab/rack_attack/request_spec.rb
index ecdcc23e588..b8a26a64e5b 100644
--- a/spec/lib/gitlab/rack_attack/request_spec.rb
+++ b/spec/lib/gitlab/rack_attack/request_spec.rb
@@ -5,6 +5,20 @@ require 'spec_helper'
RSpec.describe Gitlab::RackAttack::Request do
using RSpec::Parameterized::TableSyntax
+ let(:path) { '/' }
+ let(:env) { {} }
+ let(:session) { {} }
+ let(:request) do
+ ::Rack::Attack::Request.new(
+ env.reverse_merge(
+ 'REQUEST_METHOD' => 'GET',
+ 'PATH_INFO' => Gitlab.config.gitlab.relative_url_root + path,
+ 'rack.input' => StringIO.new,
+ 'rack.session' => session
+ )
+ )
+ end
+
describe 'FILES_PATH_REGEX' do
subject { described_class::FILES_PATH_REGEX }
@@ -16,11 +30,249 @@ RSpec.describe Gitlab::RackAttack::Request do
it { is_expected.not_to match('/api/v4/projects/some/nested/repo/repository/files/README') }
end
+ describe '#api_request?' do
+ subject { request.api_request? }
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/foo/api' | false
+
+ '/api' | true
+ '/api/v4/groups/1' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#api_internal_request?' do
+ subject { request.api_internal_request? }
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/api' | false
+ '/api/v4/groups/1' | false
+ '/api/v4/internal' | false
+ '/foo/api/v4/internal' | false
+
+ '/api/v4/internal/' | true
+ '/api/v4/internal/foo' | true
+ '/api/v1/internal/foo' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#health_check_request?' do
+ subject { request.health_check_request? }
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/foo/-/health' | false
+
+ '/-/health' | true
+ '/-/liveness' | true
+ '/-/readiness' | true
+ '/-/metrics' | true
+ '/-/health/foo' | true
+ '/-/liveness/foo' | true
+ '/-/readiness/foo' | true
+ '/-/metrics/foo' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#container_registry_event?' do
+ subject { request.container_registry_event? }
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/api/v4/container_registry_event' | false
+ '/foo/api/v4/container_registry_event/' | false
+
+ '/api/v4/container_registry_event/' | true
+ '/api/v4/container_registry_event/foo' | true
+ '/api/v1/container_registry_event/foo' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#product_analytics_collector_request?' do
+ subject { request.product_analytics_collector_request? }
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/-/collector' | false
+ '/-/collector/foo' | false
+ '/foo/-/collector/i' | false
+
+ '/-/collector/i' | true
+ '/-/collector/ifoo' | true
+ '/-/collector/i/foo' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#should_be_skipped?' do
+ where(
+ api_internal_request: [true, false],
+ health_check_request: [true, false],
+ container_registry_event: [true, false]
+ )
+
+ with_them do
+ it 'returns true if any condition is true' do
+ allow(request).to receive(:api_internal_request?).and_return(api_internal_request)
+ allow(request).to receive(:health_check_request?).and_return(health_check_request)
+ allow(request).to receive(:container_registry_event?).and_return(container_registry_event)
+
+ expect(request.should_be_skipped?).to be(api_internal_request || health_check_request || container_registry_event)
+ end
+ end
+ end
+
+ describe '#web_request?' do
+ subject { request.web_request? }
+
+ where(:path, :expected) do
+ '/' | true
+ '/groups' | true
+ '/foo/api' | true
+
+ '/api' | false
+ '/api/v4/groups/1' | false
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#protected_path?' do
+ subject { request.protected_path? }
+
+ before do
+ stub_application_setting(protected_paths: [
+ '/protected',
+ '/secure'
+ ])
+ end
+
+ where(:path, :expected) do
+ '/' | false
+ '/groups' | false
+ '/foo/protected' | false
+ '/foo/secure' | false
+
+ '/protected' | true
+ '/secure' | true
+ '/secure/' | true
+ '/secure/foo' | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+ end
+
+ describe '#frontend_request?', :allow_forgery_protection do
+ subject { request.send(:frontend_request?) }
+
+ let(:path) { '/' }
+
+ # Define these as local variables so we can use them in the `where` block.
+ valid_token = SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH)
+ other_token = SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH)
+
+ where(:session, :env, :expected) do
+ {} | {} | false # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ {} | { 'HTTP_X_CSRF_TOKEN' => valid_token } | false
+ { _csrf_token: valid_token } | { 'HTTP_X_CSRF_TOKEN' => other_token } | false
+ { _csrf_token: valid_token } | { 'HTTP_X_CSRF_TOKEN' => valid_token } | true
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+ end
+ end
+
describe '#deprecated_api_request?' do
- let(:env) { { 'REQUEST_METHOD' => 'GET', 'rack.input' => StringIO.new, 'PATH_INFO' => path, 'QUERY_STRING' => query } }
- let(:request) { ::Rack::Attack::Request.new(env) }
+ subject { request.send(:deprecated_api_request?) }
- subject { !!request.__send__(:deprecated_api_request?) }
+ let(:env) { { 'QUERY_STRING' => query } }
where(:path, :query, :expected) do
'/' | '' | false
@@ -42,6 +294,14 @@ RSpec.describe Gitlab::RackAttack::Request do
with_them do
it { is_expected.to eq(expected) }
+
+ context 'when the application is mounted at a relative URL' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it { is_expected.to eq(expected) }
+ end
end
end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 8d67350f0f3..54a0b282e99 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Regex do
shared_examples_for 'project/group name chars regex' do
diff --git a/spec/lib/gitlab/request_profiler/profile_spec.rb b/spec/lib/gitlab/request_profiler/profile_spec.rb
index 2e9c75dde87..30e23a99b22 100644
--- a/spec/lib/gitlab/request_profiler/profile_spec.rb
+++ b/spec/lib/gitlab/request_profiler/profile_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::RequestProfiler::Profile do
let(:profile) { described_class.new(filename) }
diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb
index 4627a8db82e..402b72b9220 100644
--- a/spec/lib/gitlab/runtime_spec.rb
+++ b/spec/lib/gitlab/runtime_spec.rb
@@ -26,8 +26,16 @@ RSpec.describe Gitlab::Runtime do
end
context "when unknown" do
- it "raises an exception when trying to identify" do
- expect { subject.identify }.to raise_error(subject::UnknownProcessError)
+ describe '.identify' do
+ it "raises an exception when trying to identify" do
+ expect { subject.identify }.to raise_error(subject::UnknownProcessError)
+ end
+ end
+
+ describe '.safe_identify' do
+ it "returns nil" do
+ expect(subject.safe_identify).to be_nil
+ end
end
end
@@ -37,8 +45,16 @@ RSpec.describe Gitlab::Runtime do
stub_const('::Rails::Console', double)
end
- it "raises an exception when trying to identify" do
- expect { subject.identify }.to raise_error(subject::AmbiguousProcessError)
+ describe '.identify' do
+ it "raises an exception when trying to identify" do
+ expect { subject.identify }.to raise_error(subject::AmbiguousProcessError)
+ end
+ end
+
+ describe '.safe_identify' do
+ it "returns nil" do
+ expect(subject.safe_identify).to be_nil
+ end
end
end
diff --git a/spec/lib/gitlab/security/scan_configuration_spec.rb b/spec/lib/gitlab/security/scan_configuration_spec.rb
index 0af029968e8..2e8a11dfda3 100644
--- a/spec/lib/gitlab/security/scan_configuration_spec.rb
+++ b/spec/lib/gitlab/security/scan_configuration_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ::Gitlab::Security::ScanConfiguration do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:project) { create(:project, :repository) }
let(:scan) { described_class.new(project: project, type: type, configured: configured) }
@@ -13,9 +15,11 @@ RSpec.describe ::Gitlab::Security::ScanConfiguration do
let(:configured) { true }
context 'with a core scanner' do
- let(:type) { :sast }
+ where(type: %i(sast sast_iac secret_detection))
- it { is_expected.to be_truthy }
+ with_them do
+ it { is_expected.to be_truthy }
+ end
end
context 'with custom scanner' do
@@ -38,27 +42,28 @@ RSpec.describe ::Gitlab::Security::ScanConfiguration do
subject { scan.configuration_path }
let(:configured) { true }
+ let(:type) { :sast }
- context 'with a non configurable scanner' do
- let(:type) { :secret_detection }
+ it { is_expected.to be_nil }
+ end
- it { is_expected.to be_nil }
- end
+ describe '#can_enable_by_merge_request?' do
+ subject { scan.can_enable_by_merge_request? }
- context 'with licensed scanner for FOSS environment' do
- let(:type) { :dast }
+ let(:configured) { true }
- before do
- stub_env('FOSS_ONLY', '1')
- end
+ context 'with a core scanner' do
+ where(type: %i(sast sast_iac secret_detection))
- it { is_expected.to be_nil }
+ with_them do
+ it { is_expected.to be_truthy }
+ end
end
- context 'with custom scanner' do
+ context 'with a custom scanner' do
let(:type) { :my_scanner }
- it { is_expected.to be_nil }
+ it { is_expected.to be_falsey }
end
end
end
diff --git a/spec/lib/gitlab/ssh_public_key_spec.rb b/spec/lib/gitlab/ssh_public_key_spec.rb
index 38486b313cb..cf5d2c3b455 100644
--- a/spec/lib/gitlab/ssh_public_key_spec.rb
+++ b/spec/lib/gitlab/ssh_public_key_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
end
where(:name) do
- [:rsa, :dsa, :ecdsa, :ed25519]
+ [:rsa, :dsa, :ecdsa, :ed25519, :ecdsa_sk, :ed25519_sk]
end
with_them do
@@ -24,7 +24,7 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
describe '.supported_types' do
it 'returns array with the names of supported technologies' do
expect(described_class.supported_types).to eq(
- [:rsa, :dsa, :ecdsa, :ed25519]
+ [:rsa, :dsa, :ecdsa, :ed25519, :ecdsa_sk, :ed25519_sk]
)
end
end
@@ -35,7 +35,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa, [1024, 2048, 3072, 4096]],
[:dsa, [1024, 2048, 3072]],
[:ecdsa, [256, 384, 521]],
- [:ed25519, [256]]
+ [:ed25519, [256]],
+ [:ecdsa_sk, [256]],
+ [:ed25519_sk, [256]]
]
end
@@ -53,6 +55,8 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
ssh-dss
ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
ssh-ed25519
+ sk-ecdsa-sha2-nistp256@openssh.com
+ sk-ssh-ed25519@openssh.com
)
)
end
@@ -64,7 +68,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa, %w(ssh-rsa)],
[:dsa, %w(ssh-dss)],
[:ecdsa, %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)],
- [:ed25519, %w(ssh-ed25519)]
+ [:ed25519, %w(ssh-ed25519)],
+ [:ecdsa_sk, %w(sk-ecdsa-sha2-nistp256@openssh.com)],
+ [:ed25519_sk, %w(sk-ssh-ed25519@openssh.com)]
]
end
@@ -122,13 +128,35 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
rsa_key_8192
dsa_key_2048
ecdsa_key_256
- ed25519_key_256)
+ ed25519_key_256
+ ecdsa_sk_key_256
+ ed25519_sk_key_256)
end
with_them do
let(:key) { attributes_for(factory)[:key] }
it { is_expected.to be_valid }
+
+ context 'when key begins with options' do
+ let(:key) { "restrict,command='dump /home' #{attributes_for(factory)[:key]}" }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when key is in known_hosts format' do
+ context "when key begins with 'example.com'" do
+ let(:key) { "example.com #{attributes_for(factory)[:key]}" }
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when key begins with '@revoked other.example.com'" do
+ let(:key) { "@revoked other.example.com #{attributes_for(factory)[:key]}" }
+
+ it { is_expected.to be_valid }
+ end
+ end
end
end
@@ -137,6 +165,40 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
it { is_expected.not_to be_valid }
end
+
+ context 'when an unsupported SSH key algorithm' do
+ let(:key) { "unsupported-#{attributes_for(:rsa_key_2048)[:key]}" }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ shared_examples 'raises error when the key is represented by a class that is not in the list of supported technologies' do
+ context 'when the key is represented by a class that is not in the list of supported technologies' do
+ it 'raises error' do
+ klass = Class.new
+ key = klass.new
+
+ allow(public_key).to receive(:key).and_return(key)
+
+ expect { subject }.to raise_error("Unsupported key type: #{key.class}")
+ end
+ end
+
+ context 'when the key is represented by a subclass of the class that is in the list of supported technologies' do
+ it 'raises error' do
+ rsa_subclass = Class.new(described_class.technology(:rsa).key_class) do
+ def initialize
+ end
+ end
+
+ key = rsa_subclass.new
+
+ allow(public_key).to receive(:key).and_return(key)
+
+ expect { subject }.to raise_error("Unsupported key type: #{key.class}")
+ end
+ end
end
describe '#type' do
@@ -147,7 +209,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_2048, :rsa],
[:dsa_key_2048, :dsa],
[:ecdsa_key_256, :ecdsa],
- [:ed25519_key_256, :ed25519]
+ [:ed25519_key_256, :ed25519],
+ [:ecdsa_sk_key_256, :ecdsa_sk],
+ [:ed25519_sk_key_256, :ed25519_sk]
]
end
@@ -162,6 +226,8 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
it { is_expected.to be_nil }
end
+
+ include_examples 'raises error when the key is represented by a class that is not in the list of supported technologies'
end
describe '#bits' do
@@ -175,7 +241,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_8192, 8192],
[:dsa_key_2048, 2048],
[:ecdsa_key_256, 256],
- [:ed25519_key_256, 256]
+ [:ed25519_key_256, 256],
+ [:ecdsa_sk_key_256, 256],
+ [:ed25519_sk_key_256, 256]
]
end
@@ -190,6 +258,8 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
it { is_expected.to be_nil }
end
+
+ include_examples 'raises error when the key is represented by a class that is not in the list of supported technologies'
end
describe '#fingerprint' do
@@ -203,7 +273,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_8192, 'fb:53:7f:e9:2f:f7:17:aa:c8:32:52:06:8e:05:e2:82'],
[:dsa_key_2048, 'c8:85:1e:df:44:0f:20:00:3c:66:57:2b:21:10:5a:27'],
[:ecdsa_key_256, '67:a3:a9:7d:b8:e1:15:d4:80:40:21:34:bb:ed:97:38'],
- [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73']
+ [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73'],
+ [:ecdsa_sk_key_256, '56:b9:bc:99:3d:2f:cf:63:6b:70:d8:f9:40:7e:09:4c'],
+ [:ed25519_sk_key_256, 'f9:a0:64:0b:4b:72:72:0e:62:92:d7:04:14:74:1c:c9']
]
end
@@ -220,18 +292,20 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
end
end
- describe '#fingerprint in SHA256 format' do
- subject { public_key.fingerprint("SHA256").gsub("SHA256:", "") if public_key.fingerprint("SHA256") }
+ describe '#fingerprint_sha256' do
+ subject { public_key.fingerprint_sha256 }
where(:factory, :fingerprint_sha256) do
[
- [:rsa_key_2048, 'GdtgO0eHbwLB+mK47zblkoXujkqKRZjgMQrHH6Kks3E'],
- [:rsa_key_4096, 'ByDU7hQ1JB95l6p53rHrffc4eXvEtqGUtQhS+Dhyy7g'],
- [:rsa_key_5120, 'PCCupLbFHScm4AbEufbGDvhBU27IM0MVAor715qKQK8'],
- [:rsa_key_8192, 'CtHFQAS+9Hb8z4vrv4gVQPsHjNN0WIZhWODaB1mQLs4'],
- [:dsa_key_2048, '+a3DQ7cU5GM+gaYOfmc0VWNnykHQSuth3VRcCpWuYNI'],
- [:ecdsa_key_256, 'C+I5k3D+IGeM6k5iBR1ZsphqTKV+7uvL/XZ5hcrTr7g'],
- [:ed25519_key_256, 'DCKAjzxWrdOTjaGKBBjtCW8qY5++GaiAJflrHPmp6W0']
+ [:rsa_key_2048, 'SHA256:GdtgO0eHbwLB+mK47zblkoXujkqKRZjgMQrHH6Kks3E'],
+ [:rsa_key_4096, 'SHA256:ByDU7hQ1JB95l6p53rHrffc4eXvEtqGUtQhS+Dhyy7g'],
+ [:rsa_key_5120, 'SHA256:PCCupLbFHScm4AbEufbGDvhBU27IM0MVAor715qKQK8'],
+ [:rsa_key_8192, 'SHA256:CtHFQAS+9Hb8z4vrv4gVQPsHjNN0WIZhWODaB1mQLs4'],
+ [:dsa_key_2048, 'SHA256:+a3DQ7cU5GM+gaYOfmc0VWNnykHQSuth3VRcCpWuYNI'],
+ [:ecdsa_key_256, 'SHA256:C+I5k3D+IGeM6k5iBR1ZsphqTKV+7uvL/XZ5hcrTr7g'],
+ [:ed25519_key_256, 'SHA256:DCKAjzxWrdOTjaGKBBjtCW8qY5++GaiAJflrHPmp6W0'],
+ [:ecdsa_sk_key_256, 'SHA256:N0sNKBgWKK8usPuPegtgzHQQA9vQ/dRhAEhwFDAnLA4'],
+ [:ed25519_sk_key_256, 'SHA256:U8IKRkIHed6vFMTflwweA3HhIf2DWgZ8EFTm9fgwOUk']
]
end
@@ -249,10 +323,19 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
end
describe '#key_text' do
- let(:key) { 'this is not a key' }
+ where(:key_value) do
+ [
+ 'this is not a key',
+ nil
+ ]
+ end
- it 'carries the unmodified key data' do
- expect(public_key.key_text).to eq(key)
+ with_them do
+ let(:key) { key_value }
+
+ it 'carries the unmodified key data' do
+ expect(public_key.key_text).to eq(key)
+ end
end
end
end
diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb
index 627d3bb42c7..fd3654afee0 100644
--- a/spec/lib/gitlab/subscription_portal_spec.rb
+++ b/spec/lib/gitlab/subscription_portal_spec.rb
@@ -61,7 +61,6 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
:subscriptions_more_minutes_url | 'https://customers.staging.gitlab.com/buy_pipeline_minutes'
:subscriptions_more_storage_url | 'https://customers.staging.gitlab.com/buy_storage'
:subscriptions_manage_url | 'https://customers.staging.gitlab.com/subscriptions'
- :subscriptions_plans_url | 'https://about.gitlab.com/pricing/'
:subscriptions_instance_review_url | 'https://customers.staging.gitlab.com/instance_review'
:subscriptions_gitlab_plans_url | 'https://customers.staging.gitlab.com/gitlab_plans'
:edit_account_url | 'https://customers.staging.gitlab.com/customers/edit'
diff --git a/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb
index 42fc84cf076..b021abc9f25 100644
--- a/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb
+++ b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'support/shared_examples/lib/gitlab/malicious_regexp_shared_examples'
-require 'support/helpers/stub_feature_flags'
+require 'spec_helper'
RSpec.describe Gitlab::UntrustedRegexp::RubySyntax do
describe '.matches_syntax?' do
@@ -77,6 +75,7 @@ RSpec.describe Gitlab::UntrustedRegexp::RubySyntax do
include StubFeatureFlags
before do
+ # When removed we could use `require 'fast_spec_helper'` again.
stub_feature_flags(allow_unsafe_ruby_regexp: true)
allow(Gitlab::UntrustedRegexp).to receive(:new).and_raise(RegexpError)
diff --git a/spec/lib/gitlab/usage/service_ping_report_spec.rb b/spec/lib/gitlab/usage/service_ping_report_spec.rb
new file mode 100644
index 00000000000..9b9b24ad128
--- /dev/null
+++ b/spec/lib/gitlab/usage/service_ping_report_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_caching do
+ let(:usage_data) { { uuid: "1111" } }
+
+ context 'for output: :all_metrics_values' do
+ it 'generates the service ping' do
+ expect(Gitlab::UsageData).to receive(:data)
+
+ described_class.for(output: :all_metrics_values)
+ end
+ end
+
+ context 'for output: :metrics_queries' do
+ it 'generates the service ping' do
+ expect(Gitlab::UsageDataQueries).to receive(:data)
+
+ described_class.for(output: :metrics_queries)
+ end
+ end
+
+ context 'for output: :non_sql_metrics_values' do
+ it 'generates the service ping' do
+ expect(Gitlab::UsageDataNonSqlMetrics).to receive(:data)
+
+ described_class.for(output: :non_sql_metrics_values)
+ end
+ end
+
+ context 'when using cached' do
+ context 'for cached: true' do
+ let(:new_usage_data) { { uuid: "1112" } }
+
+ it 'caches the values' do
+ allow(Gitlab::UsageData).to receive(:data).and_return(usage_data, new_usage_data)
+
+ expect(described_class.for(output: :all_metrics_values)).to eq(usage_data)
+ expect(described_class.for(output: :all_metrics_values, cached: true)).to eq(usage_data)
+
+ expect(Rails.cache.fetch('usage_data')).to eq(usage_data)
+ end
+
+ it 'writes to cache and returns fresh data' do
+ allow(Gitlab::UsageData).to receive(:data).and_return(usage_data, new_usage_data)
+
+ expect(described_class.for(output: :all_metrics_values)).to eq(usage_data)
+ expect(described_class.for(output: :all_metrics_values)).to eq(new_usage_data)
+ expect(described_class.for(output: :all_metrics_values, cached: true)).to eq(new_usage_data)
+
+ expect(Rails.cache.fetch('usage_data')).to eq(new_usage_data)
+ end
+ end
+
+ context 'when no caching' do
+ let(:new_usage_data) { { uuid: "1112" } }
+
+ it 'returns fresh data' do
+ allow(Gitlab::UsageData).to receive(:data).and_return(usage_data, new_usage_data)
+
+ expect(described_class.for(output: :all_metrics_values)).to eq(usage_data)
+ expect(described_class.for(output: :all_metrics_values)).to eq(new_usage_data)
+
+ expect(Rails.cache.fetch('usage_data')).to eq(new_usage_data)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
index f7ff68af8a2..5e74ea3293c 100644
--- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
@@ -49,7 +49,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'secure',
'importer',
'network_policies',
- 'geo'
+ 'geo',
+ 'growth'
)
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..4169546edad
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter, :clean_gitlab_redis_shared_state do # rubocop:disable RSpec/FilePath
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:time) { Time.current }
+ let(:action) { described_class::JETBRAINS_API_REQUEST_ACTION }
+ let(:user_agent) { { user_agent: 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1' } }
+
+ context 'when tracking a jetbrains api request' do
+ it_behaves_like 'a request from an extension'
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..640dadd8c0b
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter, :clean_gitlab_redis_shared_state do # rubocop:disable RSpec/FilePath
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:time) { Time.current }
+ let(:action) { described_class::VS_CODE_API_REQUEST_ACTION }
+ let(:user_agent) { { user_agent: 'vs-code-gitlab-workflow/3.11.1 VSCode/1.52.1 Node.js/12.14.1 (darwin; x64)' } }
+
+ context 'when tracking a vs code api request' do
+ it_behaves_like 'a request from an extension'
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 427e8e67090..bea07dd9c43 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
stub_database_flavor_check('Cloud SQL for PostgreSQL')
end
- describe '.uncached_data' do
- subject { described_class.uncached_data }
+ describe '.data' do
+ subject { described_class.data }
it 'includes basic top and second level keys' do
is_expected.to include(:counts)
@@ -556,8 +556,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:issues_created_from_alerts]).to eq(3)
expect(count_data[:issues_created_manually_from_alerts]).to eq(1)
expect(count_data[:alert_bot_incident_issues]).to eq(4)
- expect(count_data[:incident_labeled_issues]).to eq(3)
-
expect(count_data[:clusters_enabled]).to eq(6)
expect(count_data[:project_clusters_enabled]).to eq(4)
expect(count_data[:group_clusters_enabled]).to eq(1)
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index d756ec5ef83..ba6997adbf6 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -439,6 +439,23 @@ RSpec.describe Gitlab::Utils do
end
end
+ describe '.add_url_parameters' do
+ subject { described_class.add_url_parameters(url, params) }
+
+ where(:url, :params, :expected_url) do
+ nil | nil | ''
+ nil | { b: 3, a: 2 } | '?a=2&b=3'
+ 'https://gitlab.com' | nil | 'https://gitlab.com'
+ 'https://gitlab.com' | { b: 3, a: 2 } | 'https://gitlab.com?a=2&b=3'
+ 'https://gitlab.com?a=1#foo' | { b: 3, 'a': 2 } | 'https://gitlab.com?a=2&b=3#foo'
+ 'https://gitlab.com?a=1#foo' | [[:b, 3], [:a, 2]] | 'https://gitlab.com?a=2&b=3#foo'
+ end
+
+ with_them do
+ it { is_expected.to eq(expected_url) }
+ end
+ end
+
describe '.removes_sensitive_data_from_url' do
it 'returns string object' do
expect(described_class.removes_sensitive_data_from_url('http://gitlab.com')).to be_instance_of(String)
diff --git a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
index 9af21685c9e..66c9bb00ee9 100644
--- a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
+++ b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Global do
describe '#errors' do
it 'reports errors about missing script' do
expect(global.errors)
- .to include "terminal:before_script config should be an array containing strings and arrays of strings"
+ .to include "terminal:before_script config should be a string or a nested array of strings up to 10 levels deep"
end
end
end
diff --git a/spec/lib/gitlab/web_ide/config_spec.rb b/spec/lib/gitlab/web_ide/config_spec.rb
index 7a9011d03c0..7ee9d40410c 100644
--- a/spec/lib/gitlab/web_ide/config_spec.rb
+++ b/spec/lib/gitlab/web_ide/config_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe Gitlab::WebIde::Config do
end
context 'when config logic is incorrect' do
- let(:yml) { 'terminal: { before_script: "ls" }' }
+ let(:yml) { 'terminal: { before_script: 123 }' }
describe '#valid?' do
it 'is not valid' do
diff --git a/spec/lib/gitlab/webpack/file_loader_spec.rb b/spec/lib/gitlab/webpack/file_loader_spec.rb
index 34d00b9f106..6475ef58611 100644
--- a/spec/lib/gitlab/webpack/file_loader_spec.rb
+++ b/spec/lib/gitlab/webpack/file_loader_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'support/helpers/file_read_helpers'
-require 'support/webmock'
+require 'spec_helper'
RSpec.describe Gitlab::Webpack::FileLoader do
include FileReadHelpers
diff --git a/spec/lib/gitlab_edition_spec.rb b/spec/lib/gitlab_edition_spec.rb
index 2f1316819ec..6fc4312252d 100644
--- a/spec/lib/gitlab_edition_spec.rb
+++ b/spec/lib/gitlab_edition_spec.rb
@@ -3,18 +3,22 @@
require 'spec_helper'
RSpec.describe GitlabEdition do
+ def remove_instance_variable(ivar)
+ described_class.remove_instance_variable(ivar) if described_class.instance_variable_defined?(ivar)
+ end
+
before do
# Make sure the ENV is clean
stub_env('FOSS_ONLY', nil)
stub_env('EE_ONLY', nil)
- described_class.instance_variable_set(:@is_ee, nil)
- described_class.instance_variable_set(:@is_jh, nil)
+ remove_instance_variable(:@is_ee)
+ remove_instance_variable(:@is_jh)
end
after do
- described_class.instance_variable_set(:@is_ee, nil)
- described_class.instance_variable_set(:@is_jh, nil)
+ remove_instance_variable(:@is_ee)
+ remove_instance_variable(:@is_jh)
end
describe '.root' do
@@ -51,7 +55,7 @@ RSpec.describe GitlabEdition do
allow(described_class).to receive(:ee?).and_return(false)
end
- it 'returns the exyensions according to the current edition' do
+ it 'returns the extensions according to the current edition' do
expect(described_class.extensions).to be_empty
end
end
@@ -77,7 +81,7 @@ RSpec.describe GitlabEdition do
end
describe '.ee?' do
- context 'for EE' do
+ context 'when EE' do
before do
stub_path('ee/app/models/license.rb', exist?: true)
end
@@ -109,7 +113,7 @@ RSpec.describe GitlabEdition do
end
end
- context 'for CE' do
+ context 'when CE' do
before do
stub_path('ee/app/models/license.rb', exist?: false)
end
@@ -121,12 +125,9 @@ RSpec.describe GitlabEdition do
end
describe '.jh?' do
- context 'for JH' do
+ context 'when JH' do
before do
- stub_path(
- 'ee/app/models/license.rb',
- 'jh',
- exist?: true)
+ stub_path('ee/app/models/license.rb', 'jh', exist?: true)
end
context 'when using default FOSS_ONLY and EE_ONLY' do
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 49ba4debe31..57a4bdc9bb5 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -99,6 +99,13 @@ RSpec.describe Gitlab do
expect(described_class.com?).to eq true
end
+ it 'is true when on other gitlab subdomain with hyphen' do
+ url_with_subdomain = Gitlab::Saas.com_url.gsub('https://', 'https://test-example.')
+ stub_config_setting(url: url_with_subdomain)
+
+ expect(described_class.com?).to eq true
+ end
+
it 'is false when not on GitLab.com' do
stub_config_setting(url: 'http://example.com')
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index 3284c9cd0d1..29e5445cfaa 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
let(:token) { 'token' }
let(:client) { described_class.new(token, nil) }
let(:user_agent_options) { client.instance_eval { user_agent_header } }
+ let(:gcp_project_id) { String('gcp_proj_id') }
+ let(:operation) { true }
describe '.session_key_for_redirect_uri' do
let(:state) { 'random_string' }
@@ -60,7 +62,7 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
before do
allow_any_instance_of(Google::Apis::ContainerV1::ContainerService)
.to receive(:get_zone_cluster).with(any_args, options: user_agent_options)
- .and_return(gke_cluster)
+ .and_return(gke_cluster)
end
it { is_expected.to eq(gke_cluster) }
@@ -122,7 +124,7 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
before do
allow_any_instance_of(Google::Apis::ContainerV1beta1::ContainerService)
.to receive(:create_cluster).with(any_args)
- .and_return(operation)
+ .and_return(operation)
end
it 'sets corresponded parameters' do
@@ -172,7 +174,7 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
before do
allow_any_instance_of(Google::Apis::ContainerV1::ContainerService)
.to receive(:get_zone_operation).with(any_args, options: user_agent_options)
- .and_return(operation)
+ .and_return(operation)
end
it { is_expected.to eq(operation) }
@@ -244,7 +246,7 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
let(:operation) { double('Service Account Key') }
- it 'class Google Api IamService#create_service_account_key' do
+ it 'calls Google Api IamService#create_service_account_key' do
expect_any_instance_of(Google::Apis::IamV1::IamService)
.to receive(:create_service_account_key)
.with(any_args)
@@ -252,4 +254,84 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
is_expected.to eq(operation)
end
end
+
+ describe 'grant_service_account_roles' do
+ subject { client.grant_service_account_roles(spy, spy) }
+
+ it 'calls Google Api CloudResourceManager#set_iam_policy' do
+ mock_gcp_id = 'mock-gcp-id'
+ mock_email = 'mock@email.com'
+ mock_policy = Struct.new(:bindings).new([])
+ mock_body = []
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/iam.serviceAccountUser', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/artifactregistry.admin', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/cloudbuild.builds.builder', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/run.admin', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/storage.admin', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/cloudsql.admin', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::Binding).to receive(:new)
+ .with({ 'role': 'roles/browser', 'members': ["serviceAccount:#{mock_email}"] })
+
+ expect(Google::Apis::CloudresourcemanagerV1::SetIamPolicyRequest).to receive(:new).and_return([])
+
+ expect_next_instance_of(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService) do |instance|
+ expect(instance).to receive(:get_project_iam_policy)
+ .with(mock_gcp_id)
+ .and_return(mock_policy)
+ expect(instance).to receive(:set_project_iam_policy)
+ .with(mock_gcp_id, mock_body)
+ end
+
+ client.grant_service_account_roles(mock_gcp_id, mock_email)
+ end
+ end
+
+ describe '#enable_cloud_run' do
+ subject { client.enable_cloud_run(gcp_project_id) }
+
+ it 'calls Google Api IamService#create_service_account_key' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/run.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
+ describe '#enable_artifacts_registry' do
+ subject { client.enable_artifacts_registry(gcp_project_id) }
+
+ it 'calls Google Api IamService#create_service_account_key' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/artifactregistry.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
+ describe '#enable_cloud_build' do
+ subject { client.enable_cloud_build(gcp_project_id) }
+
+ it 'calls Google Api IamService#create_service_account_key' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/cloudbuild.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
end
diff --git a/spec/lib/learn_gitlab/project_spec.rb b/spec/lib/learn_gitlab/project_spec.rb
index 523703761bf..5d649740c65 100644
--- a/spec/lib/learn_gitlab/project_spec.rb
+++ b/spec/lib/learn_gitlab/project_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe LearnGitlab::Project do
let_it_be(:current_user) { create(:user) }
let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME) }
+ let_it_be(:learn_gitlab_ultimate_trial_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL) }
let_it_be(:learn_gitlab_board) { create(:board, project: learn_gitlab_project, name: LearnGitlab::Project::BOARD_NAME) }
let_it_be(:learn_gitlab_label) { create(:label, project: learn_gitlab_project, name: LearnGitlab::Project::LABEL_NAME) }
@@ -45,6 +46,12 @@ RSpec.describe LearnGitlab::Project do
subject { described_class.new(current_user).project }
it { is_expected.to eq learn_gitlab_project }
+
+ context 'when it is created during trial signup' do
+ let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL) }
+
+ it { is_expected.to eq learn_gitlab_project }
+ end
end
describe '.board' do
diff --git a/spec/lib/peek/views/detailed_view_spec.rb b/spec/lib/peek/views/detailed_view_spec.rb
index 8d6d9a829ef..149685b243a 100644
--- a/spec/lib/peek/views/detailed_view_spec.rb
+++ b/spec/lib/peek/views/detailed_view_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Peek::Views::DetailedView, :request_store do
context 'when a class defines thresholds' do
diff --git a/spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb b/spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb
new file mode 100644
index 00000000000..38066e41c53
--- /dev/null
+++ b/spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::ContainerScanningBuildAction do
+ subject(:result) { described_class.new(auto_devops_enabled, gitlab_ci_content).generate }
+
+ let(:params) { {} }
+
+ context 'with existing .gitlab-ci.yml' do
+ let(:auto_devops_enabled) { false }
+
+ context 'container_scanning has not been included' do
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # 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
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+
+ # container_scanning:
+ # variables:
+ # DOCKER_IMAGE: ...
+ # DOCKER_USER: ...
+ # DOCKER_PASSWORD: ...
+ stages:
+ - test
+ - security
+ variables:
+ RANDOM: make sure this persists
+ include:
+ - template: existing.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
+ CI_YML
+ end
+
+ context 'template includes are an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => [{ "template" => "existing.yml" }] }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'template include is not an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => { "template" => "existing.yml" } }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+ end
+
+ context 'container_scanning has been included' do
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # 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
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+
+ # container_scanning:
+ # variables:
+ # DOCKER_IMAGE: ...
+ # DOCKER_USER: ...
+ # DOCKER_PASSWORD: ...
+ stages:
+ - test
+ variables:
+ RANDOM: make sure this persists
+ include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+ CI_YML
+ end
+
+ context 'container_scanning template include are an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => [{ "template" => "Security/Container-Scanning.gitlab-ci.yml" }] }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'container_scanning template include is not an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => { "template" => "Security/Container-Scanning.gitlab-ci.yml" } }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+ end
+ end
+
+ context 'with no .gitlab-ci.yml' do
+ let(:gitlab_ci_content) { nil }
+
+ context 'autodevops disabled' do
+ let(:auto_devops_enabled) { false }
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # 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
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+
+ # container_scanning:
+ # variables:
+ # DOCKER_IMAGE: ...
+ # DOCKER_USER: ...
+ # DOCKER_PASSWORD: ...
+ include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+ CI_YML
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('create')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'with autodevops enabled' do
+ let(:auto_devops_enabled) { true }
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # 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
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+
+ # container_scanning:
+ # variables:
+ # DOCKER_IMAGE: ...
+ # DOCKER_USER: ...
+ # DOCKER_PASSWORD: ...
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ CI_YML
+ end
+
+ before do
+ allow_next_instance_of(described_class) do |secret_detection_build_actions|
+ allow(secret_detection_build_actions).to receive(:auto_devops_stages).and_return(fast_auto_devops_stages)
+ end
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('create')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ 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') )
+ auto_devops_template['stages']
+ end
+end
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 d93175249f5..6f702e51b73 100644
--- a/spec/lib/security/ci_configuration/sast_build_action_spec.rb
+++ b/spec/lib/security/ci_configuration/sast_build_action_spec.rb
@@ -324,6 +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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -344,6 +345,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -361,6 +363,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -384,6 +387,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -420,6 +424,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -445,6 +450,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -468,6 +474,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -492,6 +499,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -516,6 +524,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
diff --git a/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb b/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb
index ecd1602dd9e..4c459058368 100644
--- a/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb
+++ b/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Security::CiConfiguration::SastIacBuildAction 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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -64,6 +65,7 @@ RSpec.describe Security::CiConfiguration::SastIacBuildAction 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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -114,6 +116,7 @@ RSpec.describe Security::CiConfiguration::SastIacBuildAction 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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
@@ -135,6 +138,7 @@ RSpec.describe Security::CiConfiguration::SastIacBuildAction 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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
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 146c60ffb6e..4d9860ca4a5 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,6 +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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -64,6 +65,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
@@ -114,6 +116,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
@@ -135,6 +138,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
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
diff --git a/spec/lib/serializers/json_spec.rb b/spec/lib/serializers/json_spec.rb
index 0c1801b34f9..96a57cde056 100644
--- a/spec/lib/serializers/json_spec.rb
+++ b/spec/lib/serializers/json_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'oj'
RSpec.describe Serializers::Json do
describe '.dump' do
diff --git a/spec/lib/serializers/symbolized_json_spec.rb b/spec/lib/serializers/symbolized_json_spec.rb
index b30fb074ddd..b9217854d9a 100644
--- a/spec/lib/serializers/symbolized_json_spec.rb
+++ b/spec/lib/serializers/symbolized_json_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'oj'
RSpec.describe Serializers::SymbolizedJson do
describe '.dump' do
diff --git a/spec/lib/sidebars/concerns/work_item_hierarchy_spec.rb b/spec/lib/sidebars/concerns/work_item_hierarchy_spec.rb
new file mode 100644
index 00000000000..2120341bf23
--- /dev/null
+++ b/spec/lib/sidebars/concerns/work_item_hierarchy_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Concerns::WorkItemHierarchy do
+ shared_examples 'hierarchy menu' do
+ let(:item_id) { :hierarchy }
+ specify { is_expected.not_to be_nil }
+ end
+
+ describe 'Project hierarchy menu item' do
+ let_it_be_with_reload(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { Sidebars::Projects::Menus::ProjectInformationMenu.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ it_behaves_like 'hierarchy menu'
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
index 6f2ca719bc9..25a65015847 100644
--- a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
create(:user).tap { |u| project.add_guest(u) }
end
- let(:owner) { project.owner }
+ let(:owner) { project.first_owner }
let(:current_user) { owner }
let(:context) { Sidebars::Projects::Context.new(current_user: current_user, container: project, current_ref: project.repository.root_ref) }
diff --git a/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb b/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb
index dee2716e4c2..2ceb9dcada9 100644
--- a/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::CiCdMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:can_view_pipeline_editor) { true }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master', can_view_pipeline_editor: can_view_pipeline_editor) }
diff --git a/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
index e3ae3add4fd..836c6d26c6c 100644
--- a/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ConfluenceMenu do
let_it_be_with_refind(:project) { create(:project, has_external_wiki: true) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
index 3149c316c63..56eb082e101 100644
--- a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
describe '#render?' do
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 0585eb2254c..2033d40897e 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
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:jira_issues_integration_active) { false }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, jira_issues_integration: jira_issues_integration_active) }
diff --git a/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb b/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb
index a8f4b039b8c..9cf2d19f85c 100644
--- a/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ExternalWikiMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb
index 44013898721..e64b0de9c62 100644
--- a/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::HiddenMenu do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: project.repository.root_ref) }
describe '#render?' do
diff --git a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
index 55281171634..0e415ec6014 100644
--- a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, show_cluster_hint: false) }
describe '#render?' do
diff --git a/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb b/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
index df9b260d211..9838aa8c3e3 100644
--- a/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Sidebars::Projects::Menus::InviteTeamMembersMenu do
subject(:invite_menu) { described_class.new(context) }
context 'when the project is viewed by an owner of the group' do
- let(:owner) { project.owner }
+ let(:owner) { project.first_owner }
describe '#render?' do
it 'renders the Invite team members link' do
diff --git a/spec/lib/sidebars/projects/menus/issues_menu_spec.rb b/spec/lib/sidebars/projects/menus/issues_menu_spec.rb
index e5d486bbe8f..4c0016a77a1 100644
--- a/spec/lib/sidebars/projects/menus/issues_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/issues_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::IssuesMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb
index cef303fb068..45c49500e46 100644
--- a/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::MergeRequestsMenu do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
index 77efe99aaa9..e8c6fb790c3 100644
--- a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::MonitorMenu do
let_it_be_with_refind(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:show_cluster_hint) { true }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, show_cluster_hint: show_cluster_hint) }
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 d6807451a25..afe0b2a8951 100644
--- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
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 7e8d0ab0518..24625413ded 100644
--- a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do
let_it_be_with_reload(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
describe '#container_html_options' do
@@ -59,5 +59,11 @@ RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do
specify { is_expected.to be_nil }
end
end
+
+ describe 'Hierarchy' do
+ let(:item_id) { :hierarchy }
+
+ specify { is_expected.not_to be_nil }
+ end
end
end
diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
index 554a4e3f532..fc181947e60 100644
--- a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do
let_it_be(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master') }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/scope_menu_spec.rb b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb
index 980ab2f7c71..4e87f3b8ead 100644
--- a/spec/lib/sidebars/projects/menus/scope_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ScopeMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
describe '#container_html_options' do
diff --git a/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb
index 6e84beeb274..41158bd58dc 100644
--- a/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::SecurityComplianceMenu do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_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) }
diff --git a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
index 1e5d41dfec4..d6136dddf40 100644
--- a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::SettingsMenu do
let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb b/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb
index 534267a329e..e74647894fa 100644
--- a/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ShimoMenu do
let_it_be_with_reload(:project) { create(:project) }
- let(:context) { Sidebars::Projects::Context.new(current_user: project.owner, container: project) }
+ let(:context) { Sidebars::Projects::Context.new(current_user: project.first_owner, container: project) }
subject(:shimo_menu) { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb
index af219e4a742..04b8c128e3d 100644
--- a/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::SnippetsMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
diff --git a/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb
index 41447ee24a9..362da3e7b50 100644
--- a/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::WikiMenu do
let(:project) { build(:project) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
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
index d7a77a84472..9c4aebaedd8 100644
--- a/spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb
+++ b/spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
MAIL_ROOM_CONFIG_ENABLED_SAMPLE =
":mailboxes:\n"\
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 0fbdc09a206..978118ed1b1 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -714,7 +714,7 @@ RSpec.describe Notify do
describe 'project access requested' do
let(:project) do
create(:project, :public) do |project|
- project.add_maintainer(project.owner)
+ project.add_maintainer(project.first_owner)
end
end
diff --git a/spec/metrics_server/metrics_server_spec.rb b/spec/metrics_server/metrics_server_spec.rb
index fc18df9b5cd..860a3299d85 100644
--- a/spec/metrics_server/metrics_server_spec.rb
+++ b/spec/metrics_server/metrics_server_spec.rb
@@ -15,9 +15,16 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
# we need to reset it after testing.
let!(:old_multiprocess_files_dir) { prometheus_config.multiprocess_files_dir }
+ let(:ruby_sampler_double) { double(Gitlab::Metrics::Samplers::RubySampler) }
+
before do
# We do not want this to have knock-on effects on the test process.
allow(Gitlab::ProcessManagement).to receive(:modify_signals)
+
+ # This being a singleton, we stub it out because only one instance is allowed
+ # to exist per process.
+ allow(Gitlab::Metrics::Samplers::RubySampler).to receive(:initialize_instance).and_return(ruby_sampler_double)
+ allow(ruby_sampler_double).to receive(:start)
end
after do
@@ -27,101 +34,175 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
FileUtils.rm_rf(metrics_dir, secure: true)
end
- describe '.spawn' do
- context 'when in parent process' do
- it 'forks into a new process and detaches it' do
- expect(Process).to receive(:fork).and_return(99)
- expect(Process).to receive(:detach).with(99)
+ %w(puma sidekiq).each do |target|
+ context "when targeting #{target}" do
+ describe '.fork' do
+ context 'when in parent process' do
+ it 'forks into a new process and detaches it' do
+ expect(Process).to receive(:fork).and_return(99)
+ expect(Process).to receive(:detach).with(99)
- described_class.spawn('sidekiq', metrics_dir: metrics_dir)
- end
- end
+ described_class.fork(target, metrics_dir: metrics_dir)
+ end
+ end
+
+ context 'when in child process' do
+ before do
+ # This signals the process that it's "inside" the fork
+ expect(Process).to receive(:fork).and_return(nil)
+ expect(Process).not_to receive(:detach)
+ end
- context 'when in child process' do
- before do
- # This signals the process that it's "inside" the fork
- expect(Process).to receive(:fork).and_return(nil)
- expect(Process).not_to receive(:detach)
+ it 'starts the metrics server with the given arguments' do
+ expect_next_instance_of(MetricsServer) do |server|
+ expect(server).to receive(:start)
+ end
+
+ described_class.fork(target, metrics_dir: metrics_dir)
+ end
+
+ it 'resets signal handlers from parent process' do
+ expect(Gitlab::ProcessManagement).to receive(:modify_signals).with(%i[A B], 'DEFAULT')
+
+ described_class.fork(target, metrics_dir: metrics_dir, reset_signals: %i[A B])
+ end
+ end
end
- it 'starts the metrics server with the given arguments' do
- expect_next_instance_of(MetricsServer) do |server|
- expect(server).to receive(:start)
+ describe '.spawn' do
+ let(:expected_env) do
+ {
+ 'METRICS_SERVER_TARGET' => target,
+ 'WIPE_METRICS_DIR' => '0'
+ }
+ end
+
+ it 'spawns a new server process and returns its PID' do
+ expect(Process).to receive(:spawn).with(
+ expected_env,
+ end_with('bin/metrics-server'),
+ hash_including(pgroup: true)
+ ).and_return(99)
+ expect(Process).to receive(:detach).with(99)
+
+ pid = described_class.spawn(target, metrics_dir: metrics_dir)
+
+ expect(pid).to eq(99)
end
- described_class.spawn('sidekiq', metrics_dir: metrics_dir)
+ context 'when path to gitlab.yml is passed' do
+ it 'sets the GITLAB_CONFIG environment variable' do
+ expect(Process).to receive(:spawn).with(
+ expected_env.merge('GITLAB_CONFIG' => 'path/to/config/gitlab.yml'),
+ end_with('bin/metrics-server'),
+ hash_including(pgroup: true)
+ ).and_return(99)
+
+ described_class.spawn(target, metrics_dir: metrics_dir, gitlab_config: 'path/to/config/gitlab.yml')
+ end
+ end
end
+ end
+ end
- it 'resets signal handlers from parent process' do
- expect(Gitlab::ProcessManagement).to receive(:modify_signals).with(%i[A B], 'DEFAULT')
+ context 'when targeting invalid target' do
+ describe '.fork' do
+ it 'raises an error' do
+ expect { described_class.fork('unsupported', metrics_dir: metrics_dir) }.to(
+ raise_error('Target must be one of [puma,sidekiq]')
+ )
+ end
+ end
- described_class.spawn('sidekiq', metrics_dir: metrics_dir, trapped_signals: %i[A B])
+ describe '.spawn' do
+ it 'raises an error' do
+ expect { described_class.spawn('unsupported', metrics_dir: metrics_dir) }.to(
+ raise_error('Target must be one of [puma,sidekiq]')
+ )
end
end
end
- describe '#start' do
- let(:exporter_class) { Class.new(Gitlab::Metrics::Exporter::BaseExporter) }
- let(:exporter_double) { double('fake_exporter', start: true) }
- let(:settings) { { "fake_exporter" => { "enabled" => true } } }
- let(:ruby_sampler_double) { double(Gitlab::Metrics::Samplers::RubySampler) }
+ shared_examples 'a metrics exporter' do |target, expected_name|
+ describe '#start' do
+ let(:exporter_double) { double('exporter', start: true) }
+ let(:wipe_metrics_dir) { true }
- subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
+ subject(:metrics_server) { described_class.new(target, metrics_dir, wipe_metrics_dir) }
- before do
- stub_const('Gitlab::Metrics::Exporter::FakeExporter', exporter_class)
- expect(exporter_class).to receive(:instance).with(
- settings['fake_exporter'], gc_requests: true, synchronous: true
- ).and_return(exporter_double)
- expect(Settings).to receive(:monitoring).and_return(settings)
+ it 'configures ::Prometheus::Client' do
+ metrics_server.start
- allow(Gitlab::Metrics::Samplers::RubySampler).to receive(:initialize_instance).and_return(ruby_sampler_double)
- allow(ruby_sampler_double).to receive(:start)
- end
+ expect(prometheus_config.multiprocess_files_dir).to eq metrics_dir
+ expect(::Prometheus::Client.configuration.pid_provider.call).to eq expected_name
+ end
- it 'configures ::Prometheus::Client' do
- metrics_server.start
+ it 'ensures that metrics directory exists in correct mode (0700)' do
+ expect(FileUtils).to receive(:mkdir_p).with(metrics_dir, mode: 0700)
- expect(prometheus_config.multiprocess_files_dir).to eq metrics_dir
- expect(::Prometheus::Client.configuration.pid_provider.call).to eq 'fake_exporter'
- end
+ metrics_server.start
+ end
- it 'ensures that metrics directory exists in correct mode (0700)' do
- expect(FileUtils).to receive(:mkdir_p).with(metrics_dir, mode: 0700)
+ context 'when wipe_metrics_dir is true' do
+ it 'removes any old metrics files' do
+ FileUtils.touch("#{metrics_dir}/remove_this.db")
- metrics_server.start
- end
+ expect { metrics_server.start }.to change { Dir.empty?(metrics_dir) }.from(false).to(true)
+ end
+ end
- context 'when wipe_metrics_dir is true' do
- subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
+ context 'when wipe_metrics_dir is false' do
+ let(:wipe_metrics_dir) { false }
- it 'removes any old metrics files' do
- FileUtils.touch("#{metrics_dir}/remove_this.db")
+ it 'does not remove any old metrics files' do
+ FileUtils.touch("#{metrics_dir}/remove_this.db")
- expect { metrics_server.start }.to change { Dir.empty?(metrics_dir) }.from(false).to(true)
+ expect { metrics_server.start }.not_to change { Dir.empty?(metrics_dir) }.from(false)
+ end
end
- end
- context 'when wipe_metrics_dir is false' do
- subject(:metrics_server) { described_class.new('fake', metrics_dir, false)}
+ it 'starts a metrics server' do
+ expect(exporter_double).to receive(:start)
+
+ metrics_server.start
+ end
- it 'does not remove any old metrics files' do
- FileUtils.touch("#{metrics_dir}/remove_this.db")
+ it 'starts a RubySampler instance' do
+ expect(ruby_sampler_double).to receive(:start)
- expect { metrics_server.start }.not_to change { Dir.empty?(metrics_dir) }.from(false)
+ subject.start
end
end
- it 'starts a metrics server' do
- expect(exporter_double).to receive(:start)
+ describe '#name' do
+ let(:exporter_double) { double('exporter', start: true) }
- metrics_server.start
+ subject(:name) { described_class.new(target, metrics_dir, true).name }
+
+ it { is_expected.to eq(expected_name) }
end
+ end
- it 'starts a RubySampler instance' do
- expect(ruby_sampler_double).to receive(:start)
+ context 'for puma' do
+ before do
+ allow(Gitlab::Metrics::Exporter::WebExporter).to receive(:instance).with(
+ gc_requests: true, synchronous: true
+ ).and_return(exporter_double)
+ end
- subject.start
+ it_behaves_like 'a metrics exporter', 'puma', 'web_exporter'
+ end
+
+ context 'for sidekiq' do
+ let(:settings) { { "sidekiq_exporter" => { "enabled" => true } } }
+
+ before do
+ allow(::Settings).to receive(:monitoring).and_return(settings)
+ allow(Gitlab::Metrics::Exporter::SidekiqExporter).to receive(:instance).with(
+ settings['sidekiq_exporter'], gc_requests: true, synchronous: true
+ ).and_return(exporter_double)
end
+
+ it_behaves_like 'a metrics exporter', 'sidekiq', 'sidekiq_exporter'
end
end
diff --git a/spec/migrations/20220106111958_add_insert_or_update_vulnerability_reads_trigger_spec.rb b/spec/migrations/20220106111958_add_insert_or_update_vulnerability_reads_trigger_spec.rb
new file mode 100644
index 00000000000..3e450546315
--- /dev/null
+++ b/spec/migrations/20220106111958_add_insert_or_update_vulnerability_reads_trigger_spec.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddInsertOrUpdateVulnerabilityReadsTrigger do
+ let(:migration) { described_class.new }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:user) { table(:users).create!(id: 13, email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let(:vulnerability) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let(:vulnerability2) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let(:identifier) do
+ table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ let(:finding) do
+ create_finding!(
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+ end
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'UPDATE trigger' do
+ context 'when vulnerability_id is updated' do
+ it 'creates a new vulnerability_reads row' do
+ expect do
+ finding.update!(vulnerability_id: vulnerability.id)
+ end.to change { vulnerability_reads.count }.from(0).to(1)
+ end
+ end
+
+ context 'when vulnerability_id is not updated' do
+ it 'does not create a new vulnerability_reads row' do
+ finding.update!(vulnerability_id: nil)
+
+ expect do
+ finding.update!(location: '')
+ end.not_to change { vulnerability_reads.count }
+ end
+ end
+ end
+
+ describe 'INSERT trigger' do
+ context 'when vulnerability_id is set' do
+ it 'creates a new vulnerability_reads row' do
+ expect do
+ create_finding!(
+ vulnerability_id: vulnerability2.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+ end.to change { vulnerability_reads.count }.from(0).to(1)
+ end
+ end
+
+ context 'when vulnerability_id is not set' do
+ it 'does not create a new vulnerability_reads row' do
+ expect do
+ create_finding!(
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+ end.not_to change { vulnerability_reads.count }
+ end
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the trigger' do
+ expect do
+ finding.update!(vulnerability_id: vulnerability.id)
+ end.not_to change { vulnerability_reads.count }
+ end
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id: nil, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" }, location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location: location,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/migrations/20220106112043_add_update_vulnerability_reads_trigger_spec.rb b/spec/migrations/20220106112043_add_update_vulnerability_reads_trigger_spec.rb
new file mode 100644
index 00000000000..d988b1e42b9
--- /dev/null
+++ b/spec/migrations/20220106112043_add_update_vulnerability_reads_trigger_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddUpdateVulnerabilityReadsTrigger do
+ let(:migration) { described_class.new }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+ let(:issue_links) { table(:vulnerability_issue_links) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:user) { table(:users).create!(id: 13, email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:issue) { table(:issues).create!(description: '1234', state_id: 1, project_id: project.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let(:vulnerability) do
+ create_vulnerability!(
+ project_id: project.id,
+ report_type: 7,
+ author_id: user.id
+ )
+ end
+
+ let(:identifier) do
+ table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'UPDATE trigger' do
+ before do
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ report_type: 7,
+ primary_identifier_id: identifier.id
+ )
+ end
+
+ context 'when vulnerability attributes are updated' do
+ it 'updates vulnerability attributes in vulnerability_reads' do
+ expect do
+ vulnerability.update!(severity: 6)
+ end.to change { vulnerability_reads.first.severity }.from(7).to(6)
+ end
+ end
+
+ context 'when vulnerability attributes are not updated' do
+ it 'does not update vulnerability attributes in vulnerability_reads' do
+ expect do
+ vulnerability.update!(title: "New vulnerability")
+ end.not_to change { vulnerability_reads.first }
+ end
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ report_type: 7,
+ primary_identifier_id: identifier.id
+ )
+ end
+
+ it 'drops the trigger' do
+ expect do
+ vulnerability.update!(severity: 6)
+ end.not_to change { vulnerability_reads.first.severity }
+ end
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id: nil, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" }, location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location: location,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/migrations/20220106112085_add_update_vulnerability_reads_location_trigger_spec.rb b/spec/migrations/20220106112085_add_update_vulnerability_reads_location_trigger_spec.rb
new file mode 100644
index 00000000000..901f1cf6041
--- /dev/null
+++ b/spec/migrations/20220106112085_add_update_vulnerability_reads_location_trigger_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddUpdateVulnerabilityReadsLocationTrigger do
+ let(:migration) { described_class.new }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+ let(:issue_links) { table(:vulnerability_issue_links) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:user) { table(:users).create!(id: 13, email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:issue) { table(:issues).create!(description: '1234', state_id: 1, project_id: project.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let(:vulnerability) do
+ create_vulnerability!(
+ project_id: project.id,
+ report_type: 7,
+ author_id: user.id
+ )
+ end
+
+ let(:identifier) do
+ table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'UPDATE trigger' do
+ context 'when image is updated' do
+ it 'updates location_image in vulnerability_reads' do
+ finding = create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ report_type: 7,
+ location: { "image" => "alpine:3.4" },
+ primary_identifier_id: identifier.id
+ )
+
+ expect do
+ finding.update!(location: { "image" => "alpine:4", "kubernetes_resource" => { "agent_id" => "1234" } })
+ end.to change { vulnerability_reads.first.location_image }.from("alpine:3.4").to("alpine:4")
+ end
+ end
+
+ context 'when image is not updated' do
+ it 'updates location_image in vulnerability_reads' do
+ finding = create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ report_type: 7,
+ location: { "image" => "alpine:3.4", "kubernetes_resource" => { "agent_id" => "1234" } },
+ primary_identifier_id: identifier.id
+ )
+
+ expect do
+ finding.update!(project_fingerprint: "123qweasdzx")
+ end.not_to change { vulnerability_reads.first.location_image }
+ end
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the trigger' do
+ finding = create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+
+ expect do
+ finding.update!(location: '{"image":"alpine:4"}')
+ end.not_to change { vulnerability_reads.first.location_image }
+ end
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id: nil, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" }, location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location: location,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/migrations/20220106163326_add_has_issues_on_vulnerability_reads_trigger_spec.rb b/spec/migrations/20220106163326_add_has_issues_on_vulnerability_reads_trigger_spec.rb
new file mode 100644
index 00000000000..8e50b74eb9c
--- /dev/null
+++ b/spec/migrations/20220106163326_add_has_issues_on_vulnerability_reads_trigger_spec.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddHasIssuesOnVulnerabilityReadsTrigger do
+ let(:migration) { described_class.new }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+ let(:issue_links) { table(:vulnerability_issue_links) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:user) { table(:users).create!(id: 13, email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:issue) { table(:issues).create!(description: '1234', state_id: 1, project_id: project.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let(:vulnerability) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let(:identifier) do
+ table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ before do
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+
+ @vulnerability_read = vulnerability_reads.first
+ end
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'INSERT trigger' do
+ it 'updates has_issues in vulnerability_reads' do
+ expect do
+ issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue.id)
+ end.to change { @vulnerability_read.reload.has_issues }.from(false).to(true)
+ end
+ end
+
+ describe 'DELETE trigger' do
+ let(:issue2) { table(:issues).create!(description: '1234', state_id: 1, project_id: project.id) }
+
+ it 'does not change has_issues when there exists another issue' do
+ issue_link1 = issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue.id)
+ issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue2.id)
+
+ expect do
+ issue_link1.delete
+ end.not_to change { @vulnerability_read.reload.has_issues }
+ end
+
+ it 'unsets has_issues when all issues are deleted' do
+ issue_link1 = issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue.id)
+ issue_link2 = issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue2.id)
+
+ expect do
+ issue_link1.delete
+ issue_link2.delete
+ end.to change { @vulnerability_read.reload.has_issues }.from(true).to(false)
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the trigger' do
+ expect do
+ issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue.id)
+ end.not_to change { @vulnerability_read.has_issues }
+ end
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id: nil, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" }, location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location: location,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb b/spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb
new file mode 100644
index 00000000000..ece971a50c9
--- /dev/null
+++ b/spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe PopulateVulnerabilityReads, :migration do
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let_it_be(:user) { table(:users).create!(email: 'author@example.com', username: 'author', projects_limit: 10) }
+ let_it_be(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let_it_be(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
+ let_it_be(:vulnerabilities) { table(:vulnerabilities) }
+ let_it_be(:vulnerability_reads) { table(:vulnerability_reads) }
+ let_it_be(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let_it_be(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
+ let_it_be(:vulnerability_ids) { [] }
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 1)
+
+ 5.times.each do |x|
+ vulnerability = create_vulnerability!(
+ project_id: project.id,
+ report_type: 7,
+ author_id: user.id
+ )
+ identifier = table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: Digest::SHA1.hexdigest("#{vulnerability.id}"),
+ name: 'Identifier for UUIDv5')
+
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id
+ )
+
+ vulnerability_ids << vulnerability.id
+ end
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migrations' do
+ migrate!
+
+ expect(background_migration_jobs.count).to eq(5)
+ expect(background_migration_jobs.first.arguments).to match_array([vulnerability_ids.first, vulnerability_ids.first, 1])
+ expect(background_migration_jobs.second.arguments).to match_array([vulnerability_ids.second, vulnerability_ids.second, 1])
+ expect(background_migration_jobs.third.arguments).to match_array([vulnerability_ids.third, vulnerability_ids.third, 1])
+ expect(background_migration_jobs.fourth.arguments).to match_array([vulnerability_ids.fourth, vulnerability_ids.fourth, 1])
+ expect(background_migration_jobs.fifth.arguments).to match_array([vulnerability_ids.fifth, vulnerability_ids.fifth, 1])
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(5)
+ expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(2.minutes, vulnerability_ids.first, vulnerability_ids.first, 1)
+ expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(4.minutes, vulnerability_ids.second, vulnerability_ids.second, 1)
+ expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(6.minutes, vulnerability_ids.third, vulnerability_ids.third, 1)
+ expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(8.minutes, vulnerability_ids.fourth, vulnerability_ids.fourth, 1)
+ expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(10.minutes, vulnerability_ids.fifth, vulnerability_ids.fifth, 1)
+ 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
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ id: nil,
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
+ params = {
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ }
+ params[:id] = id unless id.nil?
+ vulnerabilities_findings.create!(params)
+ end
+ # rubocop:enable Metrics/ParameterLists
+end
diff --git a/spec/migrations/20220120094340_drop_position_from_security_findings_spec.rb b/spec/migrations/20220120094340_drop_position_from_security_findings_spec.rb
new file mode 100644
index 00000000000..2ad9a8220c3
--- /dev/null
+++ b/spec/migrations/20220120094340_drop_position_from_security_findings_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('drop_position_from_security_findings')
+
+RSpec.describe DropPositionFromSecurityFindings do
+ let(:events) { table(:security_findings) }
+
+ it 'correctly migrates up and down' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(events.column_names).to include('position')
+ }
+
+ migration.after -> {
+ events.reset_column_information
+ expect(events.column_names).not_to include('position')
+ }
+ end
+ end
+end
diff --git a/spec/migrations/20220124130028_dedup_runner_projects_spec.rb b/spec/migrations/20220124130028_dedup_runner_projects_spec.rb
new file mode 100644
index 00000000000..2698af6f6f5
--- /dev/null
+++ b/spec/migrations/20220124130028_dedup_runner_projects_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20220124130028_dedup_runner_projects.rb')
+
+RSpec.describe DedupRunnerProjects, :migration, schema: 20220120085655 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:runners) { table(:ci_runners) }
+ let(:runner_projects) { table(:ci_runner_projects) }
+
+ let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let!(:project_2) { projects.create!(namespace_id: namespace.id) }
+ let!(:runner) { runners.create!(runner_type: 'project_type') }
+ let!(:runner_2) { runners.create!(runner_type: 'project_type') }
+ let!(:runner_3) { runners.create!(runner_type: 'project_type') }
+
+ let!(:duplicated_runner_project_1) { runner_projects.create!(runner_id: runner.id, project_id: project.id) }
+ let!(:duplicated_runner_project_2) { runner_projects.create!(runner_id: runner.id, project_id: project.id) }
+ let!(:duplicated_runner_project_3) { runner_projects.create!(runner_id: runner_2.id, project_id: project_2.id) }
+ let!(:duplicated_runner_project_4) { runner_projects.create!(runner_id: runner_2.id, project_id: project_2.id) }
+
+ let!(:non_duplicated_runner_project) { runner_projects.create!(runner_id: runner_3.id, project_id: project.id) }
+
+ it 'deduplicates ci_runner_projects table' do
+ expect { migrate! }.to change { runner_projects.count }.from(5).to(3)
+ end
+
+ it 'merges `duplicated_runner_project_1` with `duplicated_runner_project_2`', :aggregate_failures do
+ migrate!
+
+ expect(runner_projects.where(id: duplicated_runner_project_1.id)).not_to(exist)
+
+ merged_runner_projects = runner_projects.find_by(id: duplicated_runner_project_2.id)
+
+ expect(merged_runner_projects).to be_present
+ expect(merged_runner_projects.created_at).to be_like_time(duplicated_runner_project_1.created_at)
+ expect(merged_runner_projects.created_at).to be_like_time(duplicated_runner_project_2.created_at)
+ end
+
+ it 'merges `duplicated_runner_project_3` with `duplicated_runner_project_4`', :aggregate_failures do
+ migrate!
+
+ expect(runner_projects.where(id: duplicated_runner_project_3.id)).not_to(exist)
+
+ merged_runner_projects = runner_projects.find_by(id: duplicated_runner_project_4.id)
+
+ expect(merged_runner_projects).to be_present
+ expect(merged_runner_projects.created_at).to be_like_time(duplicated_runner_project_3.created_at)
+ expect(merged_runner_projects.created_at).to be_like_time(duplicated_runner_project_4.created_at)
+ end
+
+ it 'does not change non duplicated records' do
+ expect { migrate! }.not_to change { non_duplicated_runner_project.reload.attributes }
+ end
+
+ it 'does nothing when there are no runner projects' do
+ runner_projects.delete_all
+
+ migrate!
+
+ expect(runner_projects.count).to eq(0)
+ end
+end
diff --git a/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb b/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb
new file mode 100644
index 00000000000..a48464befdf
--- /dev/null
+++ b/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('remove_dangling_running_builds')
+
+RSpec.describe RemoveDanglingRunningBuilds do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let(:runner) { table(:ci_runners).create!(runner_type: 1) }
+ let(:builds) { table(:ci_builds) }
+ let(:running_builds) { table(:ci_running_builds) }
+
+ let(:running_build) do
+ builds.create!(
+ name: 'test 1',
+ status: 'running',
+ project_id: project.id,
+ type: 'Ci::Build')
+ end
+
+ let(:failed_build) do
+ builds.create!(
+ name: 'test 2',
+ status: 'failed',
+ project_id: project.id,
+ type: 'Ci::Build')
+ end
+
+ let!(:running_metadata) do
+ running_builds.create!(
+ build_id: running_build.id,
+ project_id: project.id,
+ runner_id: runner.id,
+ runner_type:
+ runner.runner_type)
+ end
+
+ let!(:failed_metadata) do
+ running_builds.create!(
+ build_id: failed_build.id,
+ project_id: project.id,
+ runner_id: runner.id,
+ runner_type: runner.runner_type)
+ end
+
+ it 'removes failed builds' do
+ migrate!
+
+ expect(running_metadata.reload).to be_present
+ expect { failed_metadata.reload } .to raise_error(ActiveRecord::RecordNotFound)
+ end
+end
diff --git a/spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb b/spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb
new file mode 100644
index 00000000000..1558facdf96
--- /dev/null
+++ b/spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('fix_approval_rules_code_owners_rule_type_index')
+
+RSpec.describe FixApprovalRulesCodeOwnersRuleTypeIndex, :migration do
+ let(:table_name) { :approval_merge_request_rules }
+ let(:index_name) { 'index_approval_rules_code_owners_rule_type' }
+
+ it 'correctly migrates up and down' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(subject.index_exists_by_name?(table_name, index_name)).to be_truthy
+ }
+
+ migration.after -> {
+ expect(subject.index_exists_by_name?(table_name, index_name)).to be_truthy
+ }
+ end
+ end
+
+ context 'when the index already exists' do
+ before do
+ subject.add_concurrent_index table_name, :merge_request_id, where: 'rule_type = 2', name: index_name
+ end
+
+ it 'keeps the index' do
+ migrate!
+
+ expect(subject.index_exists_by_name?(table_name, index_name)).to be_truthy
+ end
+ end
+end
diff --git a/spec/migrations/20220202105733_delete_service_template_records_spec.rb b/spec/migrations/20220202105733_delete_service_template_records_spec.rb
new file mode 100644
index 00000000000..c9f6b5cbe66
--- /dev/null
+++ b/spec/migrations/20220202105733_delete_service_template_records_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe DeleteServiceTemplateRecords do
+ let(:integrations) { table(:integrations) }
+ let(:chat_names) { table(:chat_names) }
+ let(:web_hooks) { table(:web_hooks) }
+ let(:slack_integrations) { table(:slack_integrations) }
+ let(:zentao_tracker_data) { table(:zentao_tracker_data) }
+ let(:jira_tracker_data) { table(:jira_tracker_data) }
+ let(:issue_tracker_data) { table(:issue_tracker_data) }
+
+ before do
+ template = integrations.create!(template: true)
+ chat_names.create!(service_id: template.id, user_id: 1, team_id: 1, chat_id: 1)
+ web_hooks.create!(service_id: template.id)
+ slack_integrations.create!(service_id: template.id, team_id: 1, team_name: 'team', alias: 'alias', user_id: 1)
+ zentao_tracker_data.create!(integration_id: template.id)
+ jira_tracker_data.create!(service_id: template.id)
+ issue_tracker_data.create!(service_id: template.id)
+
+ integrations.create!(template: false)
+ end
+
+ it 'deletes template records and associated data' do
+ expect { migrate! }
+ .to change { integrations.where(template: true).count }.from(1).to(0)
+ .and change { chat_names.count }.from(1).to(0)
+ .and change { web_hooks.count }.from(1).to(0)
+ .and change { slack_integrations.count }.from(1).to(0)
+ .and change { zentao_tracker_data.count }.from(1).to(0)
+ .and change { jira_tracker_data.count }.from(1).to(0)
+ .and change { issue_tracker_data.count }.from(1).to(0)
+ end
+
+ it 'does not delete non template records' do
+ expect { migrate! }
+ .not_to change { integrations.where(template: false).count }
+ end
+end
diff --git a/spec/migrations/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe_spec.rb b/spec/migrations/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe_spec.rb
new file mode 100644
index 00000000000..bf79ee02ff1
--- /dev/null
+++ b/spec/migrations/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe UpdateIntegrationsTriggerTypeNewOnInsertNullSafe, :migration do
+ let(:integrations) { table(:integrations) }
+
+ before do
+ migrate!
+ end
+
+ it 'leaves defined values alone' do
+ record = integrations.create!(type: 'XService', type_new: 'Integrations::Y')
+
+ expect(integrations.find(record.id)).to have_attributes(type: 'XService', type_new: 'Integrations::Y')
+ end
+
+ it 'keeps type_new synchronized with type' do
+ record = integrations.create!(type: 'AbcService', type_new: nil)
+
+ expect(integrations.find(record.id)).to have_attributes(
+ type: 'AbcService',
+ type_new: 'Integrations::Abc'
+ )
+ end
+
+ it 'keeps type synchronized with type_new' do
+ record = integrations.create!(type: nil, type_new: 'Integrations::Abc')
+
+ expect(integrations.find(record.id)).to have_attributes(
+ type: 'AbcService',
+ type_new: 'Integrations::Abc'
+ )
+ end
+end
diff --git a/spec/migrations/backfill_namespace_id_for_namespace_routes_spec.rb b/spec/migrations/backfill_namespace_id_for_namespace_routes_spec.rb
new file mode 100644
index 00000000000..913ec404795
--- /dev/null
+++ b/spec/migrations/backfill_namespace_id_for_namespace_routes_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillNamespaceIdForNamespaceRoutes do
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of routes' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :routes,
+ column_name: :id,
+ interval: described_class::INTERVAL
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/backfill_project_namespaces_for_group_spec.rb b/spec/migrations/backfill_project_namespaces_for_group_spec.rb
new file mode 100644
index 00000000000..0d34d19d42a
--- /dev/null
+++ b/spec/migrations/backfill_project_namespaces_for_group_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillProjectNamespacesForGroup do
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:parent_group1) { namespaces.create!(name: 'parent_group1', path: 'parent_group1', visibility_level: 20, type: 'Group') }
+ let!(:parent_group1_project) { projects.create!(name: 'parent_group1_project', path: 'parent_group1_project', namespace_id: parent_group1.id, visibility_level: 20) }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ describe '#up' do
+ before do
+ stub_const("BackfillProjectNamespacesForGroup::GROUP_ID", parent_group1.id)
+ end
+
+ it 'schedules background jobs for each batch of namespaces' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :projects,
+ column_name: :id,
+ job_arguments: [described_class::GROUP_ID, 'up'],
+ interval: described_class::DELAY_INTERVAL
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb b/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb
new file mode 100644
index 00000000000..b3fe1776183
--- /dev/null
+++ b/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe PopulateAuditEventStreamingVerificationToken do
+ let(:groups) { table(:namespaces) }
+ let(:destinations) { table(:audit_events_external_audit_event_destinations) }
+ let(:migration) { described_class.new }
+
+ let!(:group) { groups.create!(name: 'test-group', path: 'test-group') }
+ let!(:destination) { destinations.create!(namespace_id: group.id, destination_url: 'https://example.com/destination', verification_token: nil) }
+
+ describe '#up' do
+ it 'adds verification tokens to records created before the migration' do
+ expect do
+ migrate!
+ destination.reload
+ end.to change { destination.verification_token }.from(nil).to(a_string_matching(/\w{24}/))
+ end
+ end
+end
diff --git a/spec/migrations/schedule_fix_incorrect_max_seats_used2_spec.rb b/spec/migrations/schedule_fix_incorrect_max_seats_used2_spec.rb
new file mode 100644
index 00000000000..3720be6cf3e
--- /dev/null
+++ b/spec/migrations/schedule_fix_incorrect_max_seats_used2_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleFixIncorrectMaxSeatsUsed2, :migration do
+ let(:migration_name) { described_class::MIGRATION.to_s.demodulize }
+
+ describe '#up' do
+ it 'schedules a job on Gitlab.com' do
+ allow(Gitlab).to receive(:com?).and_return(true)
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(migration_name).to be_scheduled_delayed_migration(1.hour, 'batch_2_for_start_date_before_02_aug_2021')
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ end
+ end
+ end
+
+ it 'does not schedule any jobs when not Gitlab.com' do
+ allow(Gitlab).to receive(:com?).and_return(false)
+
+ Sidekiq::Testing.fake! do
+ migrate!
+
+ expect(migration_name).not_to be_scheduled_delayed_migration
+ expect(BackgroundMigrationWorker.jobs.size).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_fix_incorrect_max_seats_used_spec.rb b/spec/migrations/schedule_fix_incorrect_max_seats_used_spec.rb
new file mode 100644
index 00000000000..74258f03630
--- /dev/null
+++ b/spec/migrations/schedule_fix_incorrect_max_seats_used_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleFixIncorrectMaxSeatsUsed, :migration do
+ let(:migration) { described_class.new }
+
+ describe '#up' do
+ it 'schedules a job on Gitlab.com' do
+ allow(Gitlab).to receive(:com?).and_return(true)
+
+ expect(migration).to receive(:migrate_in).with(1.hour, 'FixIncorrectMaxSeatsUsed')
+
+ migration.up
+ end
+
+ it 'does not schedule any jobs when not Gitlab.com' do
+ allow(Gitlab::CurrentSettings).to receive(:com?).and_return(false)
+
+ expect(migration).not_to receive(:migrate_in)
+
+ migration.up
+ end
+ end
+end
diff --git a/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb b/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb
index 2545bb4a66c..9b62dd79e08 100644
--- a/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb
+++ b/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb
@@ -51,16 +51,17 @@ RSpec.describe ScheduleRecalculateVulnerabilityFindingSignaturesForFindings, :mi
let_it_be(:finding3) { findings.create!(finding_params) }
let_it_be(:signature3) { vulnerability_finding_signatures.create!(finding_id: finding3.id, algorithm_type: 0, signature_sha: ::Digest::SHA1.digest(SecureRandom.hex(50))) }
- it 'schedules the background jobs', :aggregate_failure do
+ # this migration is now a no-op
+ it 'does not schedule the background jobs', :aggregate_failure do
Sidekiq::Testing.fake! do
freeze_time do
migrate!
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(0)
expect(described_class::MIGRATION)
- .to be_scheduled_migration_with_multiple_args(signature1.id, signature2.id)
+ .not_to be_scheduled_migration_with_multiple_args(signature1.id, signature2.id)
expect(described_class::MIGRATION)
- .to be_scheduled_migration_with_multiple_args(signature3.id, signature3.id)
+ .not_to be_scheduled_migration_with_multiple_args(signature3.id, signature3.id)
end
end
end
diff --git a/spec/migrations/start_backfill_ci_queuing_tables_spec.rb b/spec/migrations/start_backfill_ci_queuing_tables_spec.rb
new file mode 100644
index 00000000000..a1e4179efb6
--- /dev/null
+++ b/spec/migrations/start_backfill_ci_queuing_tables_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe StartBackfillCiQueuingTables do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:builds) { table(:ci_builds) }
+
+ let!(:namespace) do
+ namespaces.create!(name: 'namespace1', path: 'namespace1')
+ end
+
+ let!(:project) do
+ projects.create!(namespace_id: namespace.id, name: 'test1', path: 'test1')
+ end
+
+ let!(:pending_build_1) do
+ builds.create!(status: :pending, name: 'test1', type: 'Ci::Build', project_id: project.id)
+ end
+
+ let!(:running_build) do
+ builds.create!(status: :running, name: 'test2', type: 'Ci::Build', project_id: project.id)
+ end
+
+ let!(:pending_build_2) do
+ builds.create!(status: :pending, name: 'test3', type: 'Ci::Build', project_id: project.id)
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ it 'schedules jobs for builds that are pending' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 2.minutes, pending_build_1.id, pending_build_1.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 4.minutes, pending_build_2.id, pending_build_2.id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/update_default_scan_method_of_dast_site_profile_spec.rb b/spec/migrations/update_default_scan_method_of_dast_site_profile_spec.rb
new file mode 100644
index 00000000000..b73aa7016a1
--- /dev/null
+++ b/spec/migrations/update_default_scan_method_of_dast_site_profile_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe UpdateDefaultScanMethodOfDastSiteProfile do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:dast_sites) { table(:dast_sites) }
+ let(:dast_site_profiles) { table(:dast_site_profiles) }
+
+ before do
+ namespace = namespaces.create!(name: 'test', path: 'test')
+ project = projects.create!(id: 12, namespace_id: namespace.id, name: 'gitlab', path: 'gitlab')
+ dast_site = dast_sites.create!(id: 1, url: 'https://www.gitlab.com', project_id: project.id)
+
+ dast_site_profiles.create!(id: 1, project_id: project.id, dast_site_id: dast_site.id,
+ name: "#{FFaker::Product.product_name.truncate(192)} #{SecureRandom.hex(4)} - 0",
+ scan_method: 0, target_type: 0)
+
+ dast_site_profiles.create!(id: 2, project_id: project.id, dast_site_id: dast_site.id,
+ name: "#{FFaker::Product.product_name.truncate(192)} #{SecureRandom.hex(4)} - 1",
+ scan_method: 0, target_type: 1)
+ end
+
+ it 'updates the scan_method to 1 for profiles with target_type 1' do
+ migrate!
+
+ expect(dast_site_profiles.where(scan_method: 1).count).to eq 1
+ expect(dast_site_profiles.where(scan_method: 0).count).to eq 1
+ end
+end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index bb8d476f257..5bd69ad9fad 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -394,7 +394,7 @@ RSpec.describe Ability do
describe '.project_disabled_features_rules' do
let(:project) { create(:project, :wiki_disabled) }
- subject { described_class.policy_for(project.owner, project) }
+ subject { described_class.policy_for(project.first_owner, project) }
context 'wiki named abilities' do
it 'disables wiki abilities if the project has no wiki' do
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 0ece212d692..a962703d460 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -141,7 +141,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value('default' => 101).for(:repository_storages_weighted).with_message("value for 'default' must be between 0 and 100") }
it { is_expected.not_to allow_value('default' => 100, shouldntexist: 50).for(:repository_storages_weighted).with_message("can't include: shouldntexist") }
- %i[notes_create_limit user_email_lookup_limit].each do |setting|
+ %i[notes_create_limit user_email_lookup_limit users_get_by_id_limit].each do |setting|
it { is_expected.to allow_value(400).for(setting) }
it { is_expected.not_to allow_value('two').for(setting) }
it { is_expected.not_to allow_value(nil).for(setting) }
@@ -158,6 +158,11 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:notes_create_limit_allowlist) }
it { is_expected.to allow_value([]).for(:notes_create_limit_allowlist) }
+ it { is_expected.to allow_value(many_usernames(100)).for(:users_get_by_id_limit_allowlist) }
+ it { is_expected.not_to allow_value(many_usernames(101)).for(:users_get_by_id_limit_allowlist) }
+ it { is_expected.not_to allow_value(nil).for(:users_get_by_id_limit_allowlist) }
+ it { is_expected.to allow_value([]).for(:users_get_by_id_limit_allowlist) }
+
it { is_expected.to allow_value('all_tiers').for(:whats_new_variant) }
it { is_expected.to allow_value('current_tier').for(:whats_new_variant) }
it { is_expected.to allow_value('disabled').for(:whats_new_variant) }
diff --git a/spec/models/audit_event_spec.rb b/spec/models/audit_event_spec.rb
index 4fba5fddc92..9f2724cebee 100644
--- a/spec/models/audit_event_spec.rb
+++ b/spec/models/audit_event_spec.rb
@@ -93,4 +93,37 @@ RSpec.describe AuditEvent do
end
end
end
+
+ describe '#author' do
+ subject { audit_event.author }
+
+ context "when the target type is not Ci::Runner" do
+ let(:audit_event) { build(:project_audit_event, target_id: 678) }
+
+ it 'returns a NullAuthor' do
+ expect(::Gitlab::Audit::NullAuthor).to receive(:for)
+ .and_call_original
+ .once
+
+ is_expected.to be_a_kind_of(::Gitlab::Audit::NullAuthor)
+ end
+ end
+
+ context 'when the target type is Ci::Runner and details contain runner_registration_token' do
+ let(:audit_event) { build(:project_audit_event, target_type: ::Ci::Runner.name, target_id: 678, details: { runner_registration_token: 'abc123' }) }
+
+ it 'returns a CiRunnerTokenAuthor' do
+ expect(::Gitlab::Audit::CiRunnerTokenAuthor).to receive(:new)
+ .with(audit_event)
+ .and_call_original
+ .once
+
+ is_expected.to be_an_instance_of(::Gitlab::Audit::CiRunnerTokenAuthor)
+ end
+
+ it 'name consists of prefix and token' do
+ expect(subject.name).to eq('Registration token: abc123')
+ end
+ end
+ end
end
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index bd4832bd978..6eba9ca63b0 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -215,6 +215,20 @@ RSpec.describe Blob do
end
end
+ describe '#symlink?' do
+ it 'is true for symlinks' do
+ symlink_blob = fake_blob(path: 'file', mode: '120000')
+
+ expect(symlink_blob.symlink?).to eq true
+ end
+
+ it 'is false for non-symlinks' do
+ non_symlink_blob = fake_blob(path: 'file', mode: '100755')
+
+ expect(non_symlink_blob.symlink?).to eq false
+ end
+ end
+
describe '#extension' do
it 'returns the extension' do
blob = fake_blob(path: 'file.md')
diff --git a/spec/models/board_spec.rb b/spec/models/board_spec.rb
index 0b7c21fd0c3..90a06b80f9c 100644
--- a/spec/models/board_spec.rb
+++ b/spec/models/board_spec.rb
@@ -16,6 +16,10 @@ RSpec.describe Board do
it { is_expected.to validate_presence_of(:project) }
end
+ describe 'constants' do
+ it { expect(described_class::RECENT_BOARDS_SIZE).to be_a(Integer) }
+ end
+
describe '#order_by_name_asc' do
let!(:board_B) { create(:board, project: project, name: 'B') }
let!(:board_C) { create(:board, project: project, name: 'C') }
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index b2ffb34da1d..5e30f9160cd 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -133,4 +133,11 @@ RSpec.describe Ci::BuildMetadata do
expect(build.cancel_gracefully?).to be false
end
end
+
+ context 'loose foreign key on ci_builds_metadata.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_build_metadata, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index b8c5af5a911..90298f0e973 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -3618,20 +3618,6 @@ RSpec.describe Ci::Build do
build.scoped_variables
end
-
- context 'when variables builder is used' do
- it 'returns the same variables' do
- build.user = create(:user)
-
- allow(build.pipeline).to receive(:use_variables_builder_definitions?).and_return(false)
- legacy_variables = build.scoped_variables.to_hash
-
- allow(build.pipeline).to receive(:use_variables_builder_definitions?).and_return(true)
- new_variables = build.scoped_variables.to_hash
-
- expect(new_variables).to eq(legacy_variables)
- end
- end
end
describe '#simple_variables_without_dependencies' do
@@ -3642,160 +3628,6 @@ RSpec.describe Ci::Build do
end
end
- shared_examples "secret CI variables" do
- context 'when ref is branch' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:build) { create(:ci_build, ref: 'master', tag: false, pipeline: pipeline, project: project) }
-
- context 'when ref is protected' do
- before do
- create(:protected_branch, :developers_can_merge, name: 'master', project: project)
- end
-
- it { is_expected.to include(variable) }
- end
-
- context 'when ref is not protected' do
- it { is_expected.not_to include(variable) }
- end
- end
-
- context 'when ref is tag' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:build) { create(:ci_build, ref: 'v1.1.0', tag: true, pipeline: pipeline, project: project) }
-
- context 'when ref is protected' do
- before do
- create(:protected_tag, project: project, name: 'v*')
- end
-
- it { is_expected.to include(variable) }
- end
-
- context 'when ref is not protected' do
- it { is_expected.not_to include(variable) }
- end
- end
-
- context 'when ref is merge request' do
- let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.pipelines_for_merge_request.first }
- let(:build) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline, project: project) }
-
- context 'when ref is protected' do
- before do
- create(:protected_branch, :developers_can_merge, name: merge_request.source_branch, project: project)
- end
-
- it 'does not return protected variables as it is not supported for merge request pipelines' do
- is_expected.not_to include(variable)
- end
- end
-
- context 'when ref is not protected' do
- it { is_expected.not_to include(variable) }
- end
- end
- end
-
- describe '#secret_instance_variables' do
- subject { build.secret_instance_variables }
-
- let_it_be(:variable) { create(:ci_instance_variable, protected: true) }
-
- include_examples "secret CI variables"
- end
-
- describe '#secret_group_variables' do
- subject { build.secret_group_variables }
-
- let_it_be(:variable) { create(:ci_group_variable, protected: true, group: group) }
-
- include_examples "secret CI variables"
- end
-
- describe '#secret_project_variables' do
- subject { build.secret_project_variables }
-
- let_it_be(:variable) { create(:ci_variable, protected: true, project: project) }
-
- include_examples "secret CI variables"
- end
-
- describe '#kubernetes_variables' do
- let(:build) { create(:ci_build) }
- let(:service) { double(execute: template) }
- let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) }
- let(:template_valid) { true }
-
- subject { build.kubernetes_variables }
-
- before do
- allow(Ci::GenerateKubeconfigService).to receive(:new).with(build).and_return(service)
- end
-
- it { is_expected.to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
-
- context 'generated config is invalid' do
- let(:template_valid) { false }
-
- it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
- end
- end
-
- describe '#deployment_variables' do
- let(:build) { create(:ci_build, environment: environment) }
- let(:environment) { 'production' }
- let(:kubernetes_namespace) { 'namespace' }
- let(:project_variables) { double }
-
- subject { build.deployment_variables(environment: environment) }
-
- before do
- allow(build).to receive(:expanded_kubernetes_namespace)
- .and_return(kubernetes_namespace)
-
- allow(build.project).to receive(:deployment_variables)
- .with(environment: environment, kubernetes_namespace: kubernetes_namespace)
- .and_return(project_variables)
- end
-
- context 'environment is nil' do
- let(:environment) { nil }
-
- it { is_expected.to be_empty }
- end
- end
-
- describe '#user_variables' do
- subject { build.user_variables.to_hash }
-
- context 'with user' do
- let(:expected_variables) do
- {
- 'GITLAB_USER_EMAIL' => user.email,
- 'GITLAB_USER_ID' => user.id.to_s,
- 'GITLAB_USER_LOGIN' => user.username,
- 'GITLAB_USER_NAME' => user.name
- }
- end
-
- before do
- build.user = user
- end
-
- it { is_expected.to eq(expected_variables) }
- end
-
- context 'without user' do
- before do
- expect(build).to receive(:user).and_return(nil)
- end
-
- it { is_expected.to be_empty }
- end
- end
-
describe '#any_unmet_prerequisites?' do
let(:build) { create(:ci_build, :created) }
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 31c7c7a44bc..e08fe196d65 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -851,7 +851,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state, :clean_git
context 'when project is destroyed' do
let(:subject) do
- Projects::DestroyService.new(project, project.owner).execute
+ Projects::DestroyService.new(project, project.first_owner).execute
end
it_behaves_like 'deletes all build_trace_chunk and data in redis'
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 2e8c41b410a..bd0397e0396 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -703,4 +703,11 @@ RSpec.describe Ci::JobArtifact do
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :ci_job_artifact }
end
+
+ context 'loose foreign key on ci_job_artifacts.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_job_artifact, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/job_token/project_scope_link_spec.rb b/spec/models/ci/job_token/project_scope_link_spec.rb
index 8d7bb44bd16..c000a3e29f7 100644
--- a/spec/models/ci/job_token/project_scope_link_spec.rb
+++ b/spec/models/ci/job_token/project_scope_link_spec.rb
@@ -88,4 +88,18 @@ RSpec.describe Ci::JobToken::ProjectScopeLink do
it { is_expected.to be_nil }
end
end
+
+ context 'loose foreign key on ci_job_token_project_scope_links.source_project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_job_token_project_scope_link, source_project: parent) }
+ end
+ end
+
+ context 'loose foreign key on ci_job_token_project_scope_links.target_project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_job_token_project_scope_link, target_project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/namespace_mirror_spec.rb b/spec/models/ci/namespace_mirror_spec.rb
index a9d916115fc..38471f15849 100644
--- a/spec/models/ci/namespace_mirror_spec.rb
+++ b/spec/models/ci/namespace_mirror_spec.rb
@@ -20,10 +20,10 @@ RSpec.describe Ci::NamespaceMirror do
end
context 'scopes' do
- describe '.contains_namespace' do
+ describe '.by_group_and_descendants' do
let_it_be(:another_group) { create(:group) }
- subject(:result) { described_class.contains_namespace(group2.id) }
+ subject(:result) { described_class.by_group_and_descendants(group2.id) }
it 'returns groups having group2.id in traversal_ids' do
expect(result.pluck(:namespace_id)).to contain_exactly(group2.id, group3.id, group4.id)
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 0f1cb721e95..0f4f148775e 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -227,4 +227,11 @@ RSpec.describe Ci::PipelineSchedule do
it { is_expected.to eq(144) }
end
end
+
+ context 'loose foreign key on ci_pipeline_schedules.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_pipeline_schedule, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 90f56c1e0a4..c29cc04e0e9 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -390,20 +390,63 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#merge_request?' do
- let(:pipeline) { create(:ci_pipeline, merge_request: merge_request) }
- let(:merge_request) { create(:merge_request) }
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be_with_reload(:pipeline) do
+ create(:ci_pipeline, project: project, merge_request_id: merge_request.id)
+ end
+
+ it { expect(pipeline).to be_merge_request }
- it 'returns true' do
- expect(pipeline).to be_merge_request
+ context 'when merge request is already loaded' do
+ it 'does not reload the record and returns true' do
+ expect(pipeline.merge_request).to be_present
+
+ expect { pipeline.merge_request? }.not_to exceed_query_limit(0)
+ expect(pipeline).to be_merge_request
+ end
end
- context 'when merge request is nil' do
- let(:merge_request) { nil }
+ context 'when merge request is not loaded' do
+ it 'executes a database query and returns true' do
+ expect(pipeline).to be_present
- it 'returns false' do
+ expect { pipeline.merge_request? }.not_to exceed_query_limit(1)
+ expect(pipeline).to be_merge_request
+ end
+
+ it 'caches the result' do
+ expect(pipeline).to be_merge_request
+ expect { pipeline.merge_request? }.not_to exceed_query_limit(0)
+ end
+ end
+
+ context 'when merge request was removed' do
+ before do
+ pipeline.update!(merge_request_id: non_existing_record_id)
+ end
+
+ it 'executes a database query and returns false' do
+ expect { pipeline.merge_request? }.not_to exceed_query_limit(1)
expect(pipeline).not_to be_merge_request
end
end
+
+ context 'when merge request id is not present' do
+ before do
+ pipeline.update!(merge_request_id: nil)
+ end
+
+ it { expect(pipeline).not_to be_merge_request }
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_pipeline_merge_request_presence_check: false)
+ pipeline.update!(merge_request_id: non_existing_record_id)
+ end
+
+ it { expect(pipeline).to be_merge_request }
+ end
end
describe '#detached_merge_request_pipeline?' do
@@ -3384,7 +3427,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
create(:ci_pipeline,
project: project,
sha: project.commit('master').sha,
- user: project.owner)
+ user: project.first_owner)
end
before do
@@ -4459,7 +4502,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#reset_source_bridge!' do
let(:pipeline) { create(:ci_pipeline, :created, project: project) }
- subject(:reset_bridge) { pipeline.reset_source_bridge!(project.owner) }
+ subject(:reset_bridge) { pipeline.reset_source_bridge!(project.first_owner) }
context 'when the pipeline is a child pipeline and the bridge is depended' do
let!(:parent_pipeline) { create(:ci_pipeline) }
@@ -4656,9 +4699,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
let(:factory_name) { :ci_pipeline }
end
- it_behaves_like 'cleanup by a loose foreign key' do
- let!(:model) { create(:ci_pipeline, user: create(:user)) }
- let!(:parent) { model.user }
+ context 'loose foreign key on ci_pipelines.user_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:model) { create(:ci_pipeline, user: create(:user)) }
+ let!(:parent) { model.user }
+ end
end
describe 'tags count' do
@@ -4679,4 +4724,55 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it { expect(pipeline.distinct_tags_count).to eq(3) }
end
end
+
+ context 'loose foreign key on ci_pipelines.merge_request_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:merge_request) }
+ let!(:model) { create(:ci_pipeline, merge_request: parent) }
+ end
+ end
+
+ context 'loose foreign key on ci_pipelines.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_pipeline, project: parent) }
+ end
+ end
+
+ describe '#jobs_git_ref' do
+ subject { pipeline.jobs_git_ref }
+
+ context 'when tag is true' do
+ let(:pipeline) { build(:ci_pipeline, tag: true) }
+
+ it 'returns a tag ref' do
+ is_expected.to start_with(Gitlab::Git::TAG_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is false' do
+ let(:pipeline) { build(:ci_pipeline, tag: false) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is nil' do
+ let(:pipeline) { build(:ci_pipeline, tag: nil) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+
+ context 'when it is triggered by a merge request' do
+ let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/ci/ref_spec.rb b/spec/models/ci/ref_spec.rb
index 0a9cd5ef2ec..ffbda4b459f 100644
--- a/spec/models/ci/ref_spec.rb
+++ b/spec/models/ci/ref_spec.rb
@@ -231,4 +231,11 @@ RSpec.describe Ci::Ref do
it_behaves_like 'no-op'
end
end
+
+ context 'loose foreign key on ci_refs.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_ref, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/runner_project_spec.rb b/spec/models/ci/runner_project_spec.rb
index 13369dba2cf..40ad79c7295 100644
--- a/spec/models/ci/runner_project_spec.rb
+++ b/spec/models/ci/runner_project_spec.rb
@@ -6,4 +6,11 @@ RSpec.describe Ci::RunnerProject do
it_behaves_like 'includes Limitable concern' do
subject { build(:ci_runner_project, project: create(:project), runner: create(:ci_runner, :project)) }
end
+
+ context 'loose foreign key on ci_runner_projects.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_runner_project, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 6830a8daa3b..eb29db697a5 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::Runner do
+ include StubGitlabCalls
+
it_behaves_like 'having unique enum values'
it_behaves_like 'it has loose foreign keys' do
@@ -23,6 +25,16 @@ RSpec.describe Ci::Runner do
end
end
+ describe 'projects association' do
+ let(:runner) { create(:ci_runner, :project) }
+
+ it 'does not create a cross-database query' do
+ with_cross_joins_prevented do
+ expect(runner.projects.count).to eq(1)
+ end
+ end
+ end
+
describe 'validation' do
it { is_expected.to validate_presence_of(:access_level) }
it { is_expected.to validate_presence_of(:runner_type) }
@@ -255,22 +267,89 @@ RSpec.describe Ci::Runner do
it_behaves_like '.belonging_to_parent_group_of_project'
end
- describe '.owned_or_instance_wide' do
- it 'returns a globally shared, a project specific and a group specific runner' do
- # group specific
- group = create(:group)
- project = create(:project, group: group)
- group_runner = create(:ci_runner, :group, groups: [group])
+ context 'with instance runners sharing enabled' do
+ # group specific
+ let_it_be(:group) { create(:group, shared_runners_enabled: true) }
+ let_it_be(:project) { create(:project, group: group, shared_runners_enabled: true) }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
- # project specific
- project_runner = create(:ci_runner, :project, projects: [project])
+ # project specific
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) }
- # globally shared
- shared_runner = create(:ci_runner, :instance)
+ # globally shared
+ let_it_be(:shared_runner) { create(:ci_runner, :instance) }
- expect(described_class.owned_or_instance_wide(project.id)).to contain_exactly(
- group_runner, project_runner, shared_runner
- )
+ describe '.owned_or_instance_wide' do
+ subject { described_class.owned_or_instance_wide(project.id) }
+
+ it 'returns a globally shared, a project specific and a group specific runner' do
+ is_expected.to contain_exactly(group_runner, project_runner, shared_runner)
+ end
+ end
+
+ describe '.group_or_instance_wide' do
+ subject { described_class.group_or_instance_wide(group) }
+
+ before do
+ # Ensure the project runner is instantiated
+ project_runner
+ end
+
+ it 'returns a globally shared and a group specific runner' do
+ is_expected.to contain_exactly(group_runner, shared_runner)
+ end
+ end
+ end
+
+ context 'with instance runners sharing disabled' do
+ # group specific
+ let_it_be(:group) { create(:group, shared_runners_enabled: false) }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
+
+ let(:group_runners_enabled) { true }
+ let(:project) { create(:project, group: group, shared_runners_enabled: false) }
+
+ # project specific
+ let(:project_runner) { create(:ci_runner, :project, projects: [project]) }
+
+ # globally shared
+ let_it_be(:shared_runner) { create(:ci_runner, :instance) }
+
+ before do
+ project.update!(group_runners_enabled: group_runners_enabled)
+ end
+
+ describe '.owned_or_instance_wide' do
+ subject { described_class.owned_or_instance_wide(project.id) }
+
+ context 'with group runners disabled' do
+ let(:group_runners_enabled) { false }
+
+ it 'returns only the project specific runner' do
+ is_expected.to contain_exactly(project_runner)
+ end
+ end
+
+ context 'with group runners enabled' do
+ let(:group_runners_enabled) { true }
+
+ it 'returns a project specific and a group specific runner' do
+ is_expected.to contain_exactly(group_runner, project_runner)
+ end
+ end
+ end
+
+ describe '.group_or_instance_wide' do
+ subject { described_class.group_or_instance_wide(group) }
+
+ before do
+ # Ensure the project runner is instantiated
+ project_runner
+ end
+
+ it 'returns a group specific runner' do
+ is_expected.to contain_exactly(group_runner)
+ end
end
end
@@ -291,6 +370,30 @@ RSpec.describe Ci::Runner do
end
end
+ describe '#only_for' do
+ let_it_be_with_reload(:runner) { create(:ci_runner, :project) }
+ let_it_be(:project) { runner.projects.first }
+
+ subject { runner.only_for?(project) }
+
+ context 'with matching project' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'without matching project' do
+ let_it_be(:project) { create(:project) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'with runner having multiple projects' do
+ let_it_be(:other_project) { create(:project) }
+ let_it_be(:runner_project) { create(:ci_runner_project, project: other_project, runner: runner) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
describe '#assign_to' do
let(:project) { create(:project) }
@@ -544,7 +647,7 @@ RSpec.describe Ci::Runner do
end
end
- describe '#can_pick?' do
+ describe '#matches_build?' do
using RSpec::Parameterized::TableSyntax
let_it_be(:pipeline) { create(:ci_pipeline) }
@@ -555,31 +658,15 @@ RSpec.describe Ci::Runner do
let(:tag_list) { [] }
let(:run_untagged) { true }
- subject { runner.can_pick?(build) }
-
- context 'a different runner' do
- let(:other_project) { create(:project) }
- let(:other_runner) { create(:ci_runner, :project, projects: [other_project], tag_list: tag_list, run_untagged: run_untagged) }
-
- before do
- # `can_pick?` is not used outside the runners available for the project
- stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
- end
-
- it 'cannot handle builds' do
- expect(other_runner.can_pick?(build)).to be_falsey
- end
- end
+ subject { runner.matches_build?(build) }
context 'when runner does not have tags' do
- it 'can handle builds without tags' do
- expect(runner.can_pick?(build)).to be_truthy
- end
+ it { is_expected.to be_truthy }
it 'cannot handle build with tags' do
build.tag_list = ['aa']
- expect(runner.can_pick?(build)).to be_falsey
+ is_expected.to be_falsey
end
end
@@ -590,20 +677,18 @@ RSpec.describe Ci::Runner do
it 'can handle build with matching tags' do
build.tag_list = ['bb']
- expect(runner.can_pick?(build)).to be_truthy
+ is_expected.to be_truthy
end
it 'cannot handle build without matching tags' do
build.tag_list = ['aa']
- expect(runner.can_pick?(build)).to be_falsey
+ is_expected.to be_falsey
end
end
context 'when runner can pick untagged jobs' do
- it 'can handle builds without tags' do
- expect(runner.can_pick?(build)).to be_truthy
- end
+ it { is_expected.to be_truthy }
it_behaves_like 'tagged build picker'
end
@@ -611,9 +696,7 @@ RSpec.describe Ci::Runner do
context 'when runner cannot pick untagged jobs' do
let(:run_untagged) { false }
- it 'cannot handle builds without tags' do
- expect(runner.can_pick?(build)).to be_falsey
- end
+ it { is_expected.to be_falsey }
it_behaves_like 'tagged build picker'
end
@@ -622,64 +705,31 @@ RSpec.describe Ci::Runner do
context 'when runner is shared' do
let(:runner) { create(:ci_runner, :instance) }
- it 'can handle builds' do
- expect(runner.can_pick?(build)).to be_truthy
- end
+ it { is_expected.to be_truthy }
context 'when runner is locked' do
let(:runner) { create(:ci_runner, :instance, locked: true) }
- it 'can handle builds' do
- expect(runner.can_pick?(build)).to be_truthy
- end
+ it { is_expected.to be_truthy }
end
it 'does not query for owned or instance runners' do
expect(described_class).not_to receive(:owned_or_instance_wide)
- runner.can_pick?(build)
- end
-
- context 'when feature flag ci_runners_short_circuit_assignable_for is disabled' do
- before do
- stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
- end
-
- it 'does not query for owned or instance runners' do
- expect(described_class).to receive(:owned_or_instance_wide).and_call_original
-
- runner.can_pick?(build)
- end
+ subject
end
end
context 'when runner is not shared' do
- before do
- # `can_pick?` is not used outside the runners available for the project
- stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
- end
-
context 'when runner is assigned to a project' do
- it 'can handle builds' do
- expect(runner.can_pick?(build)).to be_truthy
- end
- end
-
- context 'when runner is assigned to another project' do
- let(:runner_project) { create(:project) }
-
- it 'cannot handle builds' do
- expect(runner.can_pick?(build)).to be_falsey
- end
+ it { is_expected.to be_truthy }
end
context 'when runner is assigned to a group' do
let(:group) { create(:group, projects: [build.project]) }
let(:runner) { create(:ci_runner, :group, tag_list: tag_list, run_untagged: run_untagged, groups: [group]) }
- it 'can handle builds' do
- expect(runner.can_pick?(build)).to be_truthy
- end
+ it { is_expected.to be_truthy }
it 'knows namespace id it is assigned to' do
expect(runner.namespace_ids).to eq [group.id]
@@ -1220,14 +1270,6 @@ RSpec.describe Ci::Runner do
runner.pick_build!(build)
end
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
end
describe 'project runner without projects is destroyable' do
@@ -1259,6 +1301,20 @@ RSpec.describe Ci::Runner do
expect(runners).to eq([runner2, runner1])
end
+
+ it 'supports ordering by the token expiration' do
+ runner1 = create(:ci_runner)
+ runner1.update!(token_expires_at: 1.year.from_now)
+ runner2 = create(:ci_runner)
+ runner3 = create(:ci_runner)
+ runner3.update!(token_expires_at: 1.month.from_now)
+
+ runners = described_class.order_by('token_expires_at_asc')
+ expect(runners).to eq([runner3, runner1, runner2])
+
+ runners = described_class.order_by('token_expires_at_desc')
+ expect(runners).to eq([runner2, runner1, runner3])
+ end
end
describe '.runner_matchers' do
@@ -1386,47 +1442,6 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq(contacted_at_stored) }
end
- describe '.legacy_belonging_to_group' do
- shared_examples 'returns group runners' do
- it 'returns the specific group runner' do
- group = create(:group)
- runner = create(:ci_runner, :group, groups: [group])
- unrelated_group = create(:group)
- create(:ci_runner, :group, groups: [unrelated_group])
-
- expect(described_class.legacy_belonging_to_group(group.id)).to contain_exactly(runner)
- end
-
- context 'runner belonging to parent group' do
- let_it_be(:parent_group) { create(:group) }
- let_it_be(:parent_runner) { create(:ci_runner, :group, groups: [parent_group]) }
- let_it_be(:group) { create(:group, parent: parent_group) }
-
- context 'when include_parent option is passed' do
- it 'returns the group runner from the parent group' do
- expect(described_class.legacy_belonging_to_group(group.id, include_ancestors: true)).to contain_exactly(parent_runner)
- end
- end
-
- context 'when include_parent option is not passed' do
- it 'does not return the group runner from the parent group' do
- expect(described_class.legacy_belonging_to_group(group.id)).to be_empty
- end
- end
- end
- end
-
- it_behaves_like 'returns group runners'
-
- context 'when feature flag :linear_runner_ancestor_scopes is disabled' do
- before do
- stub_feature_flags(linear_runner_ancestor_scopes: false)
- end
-
- it_behaves_like 'returns group runners'
- end
- end
-
describe '.belonging_to_group' do
it 'returns the specific group runner' do
group = create(:group)
@@ -1470,4 +1485,182 @@ RSpec.describe Ci::Runner do
)
end
end
+
+ describe '#token_expires_at', :freeze_time do
+ shared_examples 'expiring token' do |interval:|
+ it 'expires' do
+ expect(runner.token_expires_at).to eq(interval.from_now)
+ end
+ end
+
+ shared_examples 'non-expiring token' do
+ it 'does not expire' do
+ expect(runner.token_expires_at).to be_nil
+ end
+ end
+
+ context 'no expiration' do
+ let(:runner) { create(:ci_runner) }
+
+ it_behaves_like 'non-expiring token'
+ end
+
+ context 'system-wide shared expiration' do
+ before do
+ stub_application_setting(runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner) }
+
+ it_behaves_like 'expiring token', interval: 5.days
+ end
+
+ context 'system-wide group expiration' do
+ before do
+ stub_application_setting(group_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner) }
+
+ it_behaves_like 'non-expiring token'
+ end
+
+ context 'system-wide project expiration' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner) }
+
+ it_behaves_like 'non-expiring token'
+ end
+
+ context 'group expiration' do
+ let(:group_settings) { create(:namespace_settings, runner_token_expiration_interval: 6.days.to_i) }
+ let(:group) { create(:group, namespace_settings: group_settings) }
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 6.days
+ end
+
+ context 'human-readable group expiration' do
+ let(:group_settings) { create(:namespace_settings, runner_token_expiration_interval_human_readable: '7 days') }
+ let(:group) { create(:group, namespace_settings: group_settings) }
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 7.days
+ end
+
+ context 'project expiration' do
+ let(:project) { create(:project, runner_token_expiration_interval: 4.days.to_i).tap(&:save!) }
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 4.days
+ end
+
+ context 'human-readable project expiration' do
+ let(:project) { create(:project, runner_token_expiration_interval_human_readable: '5 days').tap(&:save!) }
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 5.days
+ end
+
+ context 'multiple projects' do
+ let(:project1) { create(:project, runner_token_expiration_interval: 8.days.to_i).tap(&:save!) }
+ let(:project2) { create(:project, runner_token_expiration_interval: 7.days.to_i).tap(&:save!) }
+ let(:project3) { create(:project, runner_token_expiration_interval: 9.days.to_i).tap(&:save!) }
+ let(:runner) { create(:ci_runner, :project, projects: [project1, project2, project3]) }
+
+ it_behaves_like 'expiring token', interval: 7.days
+ end
+
+ context 'with project runner token expiring' do
+ let_it_be(:project) { create(:project, runner_token_expiration_interval: 4.days.to_i).tap(&:save!) }
+
+ context 'project overrides system' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 4.days
+ end
+
+ context 'system overrides project' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 3.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 3.days
+ end
+ end
+
+ context 'with group runner token expiring' do
+ let_it_be(:group_settings) { create(:namespace_settings, runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+
+ context 'group overrides system' do
+ before do
+ stub_application_setting(group_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 4.days
+ end
+
+ context 'system overrides group' do
+ before do
+ stub_application_setting(group_runner_token_expiration_interval: 3.days.to_i)
+ end
+
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 3.days
+ end
+ end
+
+ context "with group's project runner token expiring" do
+ let_it_be(:parent_group_settings) { create(:namespace_settings, subgroup_runner_token_expiration_interval: 2.days.to_i) }
+ let_it_be(:parent_group) { create(:group, namespace_settings: parent_group_settings) }
+
+ context 'parent group overrides subgroup' do
+ let(:group_settings) { create(:namespace_settings, runner_token_expiration_interval: 3.days.to_i) }
+ let(:group) { create(:group, parent: parent_group, namespace_settings: group_settings) }
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 2.days
+ end
+
+ context 'subgroup overrides parent group' do
+ let(:group_settings) { create(:namespace_settings, runner_token_expiration_interval: 1.day.to_i) }
+ let(:group) { create(:group, parent: parent_group, namespace_settings: group_settings) }
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
+
+ it_behaves_like 'expiring token', interval: 1.day
+ end
+ end
+
+ context "with group's project runner token expiring" do
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 2.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+
+ context 'group overrides project' do
+ let(:project) { create(:project, group: group, runner_token_expiration_interval: 3.days.to_i).tap(&:save!) }
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 2.days
+ end
+
+ context 'project overrides group' do
+ let(:project) { create(:project, group: group, runner_token_expiration_interval: 1.day.to_i).tap(&:save!) }
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ it_behaves_like 'expiring token', interval: 1.day
+ end
+ end
+ end
end
diff --git a/spec/models/ci/sources/pipeline_spec.rb b/spec/models/ci/sources/pipeline_spec.rb
index ccf3140650b..73f7cfa739f 100644
--- a/spec/models/ci/sources/pipeline_spec.rb
+++ b/spec/models/ci/sources/pipeline_spec.rb
@@ -17,4 +17,18 @@ RSpec.describe Ci::Sources::Pipeline do
it { is_expected.to validate_presence_of(:source_project) }
it { is_expected.to validate_presence_of(:source_job) }
it { is_expected.to validate_presence_of(:source_pipeline) }
+
+ context 'loose foreign key on ci_sources_pipelines.source_project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_sources_pipeline, source_project: parent) }
+ end
+ end
+
+ context 'loose foreign key on ci_sources_pipelines.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_sources_pipeline, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 2b6f22e68f1..b91348eb408 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -362,4 +362,11 @@ RSpec.describe Ci::Stage, :models do
end
it_behaves_like 'manual playable stage', :ci_stage_entity
+
+ context 'loose foreign key on ci_stages.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_stage_entity, project: parent) }
+ end
+ end
end
diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb
index c254279a32f..4ac8720780c 100644
--- a/spec/models/ci/trigger_spec.rb
+++ b/spec/models/ci/trigger_spec.rb
@@ -59,6 +59,20 @@ RSpec.describe Ci::Trigger do
end
it_behaves_like 'includes Limitable concern' do
- subject { build(:ci_trigger, owner: project.owner, project: project) }
+ subject { build(:ci_trigger, owner: project.first_owner, project: project) }
+ end
+
+ context 'loose foreign key on ci_triggers.owner_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:user) }
+ let!(:model) { create(:ci_trigger, owner: parent) }
+ end
+ end
+
+ context 'loose foreign key on ci_triggers.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_trigger, project: parent) }
+ end
end
end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index 93a24ba9157..29ca088ee04 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -44,4 +44,11 @@ RSpec.describe Ci::Variable do
end
end
end
+
+ context 'loose foreign key on ci_variables.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_variable, project: parent) }
+ end
+ end
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 2176eea75bc..7c67b9a3d63 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -486,7 +486,7 @@ eos
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
+ commit.all_references(project.first_owner).all
expect(commit.title_html).to be_present
expect(Rails.cache.read("banzai/commit:#{commit.id}/safe_message/single_line")).to be_nil
@@ -748,29 +748,23 @@ eos
describe '#work_in_progress?' do
[
- 'squash! ', 'fixup! ', 'wip: ', 'WIP: ', '[WIP] ',
+ 'squash! ', 'fixup! ',
'draft: ', '[Draft] ', '(draft) ', 'Draft: '
- ].each do |wip_prefix|
- it "detects the '#{wip_prefix}' prefix" do
- commit.message = "#{wip_prefix}#{commit.message}"
+ ].each do |draft_prefix|
+ it "detects the '#{draft_prefix}' prefix" do
+ commit.message = "#{draft_prefix}#{commit.message}"
expect(commit).to be_work_in_progress
end
end
- it "detects WIP for a commit just saying 'wip'" do
- commit.message = "wip"
-
- expect(commit).to be_work_in_progress
- end
-
it "does not detect WIP for a commit just saying 'draft'" do
commit.message = "draft"
expect(commit).not_to be_work_in_progress
end
- ["FIXUP!", "Draft - ", "Wipeout"].each do |draft_prefix|
+ ["FIXUP!", "Draft - ", "Wipeout", "WIP: ", "[WIP] ", "wip: "].each do |draft_prefix|
it "doesn't detect '#{draft_prefix}' at the start of the title as a draft" do
commit.message = "#{draft_prefix} #{commit.message}"
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index d5e74d36b58..86ee159b97e 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -987,4 +987,11 @@ RSpec.describe CommitStatus do
commit_status.expire_etag_cache!
end
end
+
+ context 'loose foreign key on ci_builds.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:ci_build, project: parent) }
+ end
+ end
end
diff --git a/spec/models/concerns/after_commit_queue_spec.rb b/spec/models/concerns/after_commit_queue_spec.rb
index 40cddde333e..8f091081dce 100644
--- a/spec/models/concerns/after_commit_queue_spec.rb
+++ b/spec/models/concerns/after_commit_queue_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe AfterCommitQueue do
skip_if_multiple_databases_not_setup
table_sql = <<~SQL
- CREATE TABLE _test_ci_after_commit_queue (
+ CREATE TABLE _test_gitlab_ci_after_commit_queue (
id serial NOT NULL PRIMARY KEY);
SQL
@@ -84,7 +84,7 @@ RSpec.describe AfterCommitQueue do
let(:ci_klass) do
Class.new(Ci::ApplicationRecord) do
- self.table_name = '_test_ci_after_commit_queue'
+ self.table_name = '_test_gitlab_ci_after_commit_queue'
include AfterCommitQueue
diff --git a/spec/models/concerns/ci/has_variable_spec.rb b/spec/models/concerns/ci/has_variable_spec.rb
index e917ec6b802..bf699119a37 100644
--- a/spec/models/concerns/ci/has_variable_spec.rb
+++ b/spec/models/concerns/ci/has_variable_spec.rb
@@ -68,9 +68,48 @@ RSpec.describe Ci::HasVariable do
end
describe '#to_runner_variable' do
+ let_it_be(:ci_variable) { create(:ci_variable) }
+
+ subject { ci_variable }
+
it 'returns a hash for the runner' do
expect(subject.to_runner_variable)
.to include(key: subject.key, value: subject.value, public: false)
end
+
+ context 'with RequestStore enabled', :request_store do
+ let(:expected) do
+ {
+ file: false,
+ key: subject.key,
+ value: subject.value,
+ public: false,
+ masked: false
+ }
+ end
+
+ it 'decrypts once' do
+ expect(OpenSSL::PKCS5).to receive(:pbkdf2_hmac).once.and_call_original
+
+ 2.times { expect(subject.reload.to_runner_variable).to eq(expected) }
+ end
+
+ it 'does not cache similar keys', :aggregate_failures do
+ group_var = create(:ci_group_variable, key: subject.key, value: 'group')
+ project_var = create(:ci_variable, key: subject.key, value: 'project')
+
+ expect(subject.to_runner_variable).to include(key: subject.key, value: subject.value)
+ expect(group_var.to_runner_variable).to include(key: subject.key, value: 'group')
+ expect(project_var.to_runner_variable).to include(key: subject.key, value: 'project')
+ end
+
+ it 'does not cache unpersisted values' do
+ new_variable = Ci::Variable.new(key: SecureRandom.hex, value: "12345")
+ old_value = new_variable.to_runner_variable
+ new_variable.value = '98765'
+
+ expect(new_variable.to_runner_variable).not_to eq(old_value)
+ end
+ end
end
end
diff --git a/spec/models/concerns/cross_database_modification_spec.rb b/spec/models/concerns/cross_database_modification_spec.rb
new file mode 100644
index 00000000000..72544536953
--- /dev/null
+++ b/spec/models/concerns/cross_database_modification_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CrossDatabaseModification do
+ describe '.transaction' do
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(track_gitlab_schema_in_current_transaction: false)
+ end
+
+ it 'does not add to gitlab_transactions_stack' do
+ ApplicationRecord.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+ end
+ end
+
+ context 'feature flag is not yet setup' do
+ before do
+ allow(Feature::FlipperFeature).to receive(:table_exists?).and_raise(ActiveRecord::NoDatabaseError)
+ end
+
+ it 'does not add to gitlab_transactions_stack' do
+ ApplicationRecord.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+ end
+ end
+
+ it 'adds the current gitlab schema to gitlab_transactions_stack', :aggregate_failures do
+ ApplicationRecord.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_main)
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ Ci::ApplicationRecord.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_ci)
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ Project.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_main)
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ Ci::Pipeline.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_ci)
+
+ Project.first
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+
+ ApplicationRecord.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_main)
+
+ Ci::Pipeline.transaction do
+ expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_main, :gitlab_ci)
+
+ Project.first
+ end
+ end
+
+ expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
+ end
+
+ it 'yields' do
+ expect { |block| ApplicationRecord.transaction(&block) }.to yield_control
+ end
+ end
+end
diff --git a/spec/models/concerns/has_environment_scope_spec.rb b/spec/models/concerns/has_environment_scope_spec.rb
index 0cc997709c9..6e8394b6fa5 100644
--- a/spec/models/concerns/has_environment_scope_spec.rb
+++ b/spec/models/concerns/has_environment_scope_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe HasEnvironmentScope do
+ let_it_be(:project) { create(:project) }
+
subject { build(:ci_variable) }
it { is_expected.to allow_value('*').for(:environment_scope) }
@@ -17,8 +19,6 @@ RSpec.describe HasEnvironmentScope do
end
describe '.on_environment' do
- let(:project) { create(:project) }
-
it 'returns scoped objects' do
variable1 = create(:ci_variable, project: project, environment_scope: '*')
variable2 = create(:ci_variable, project: project, environment_scope: 'product/*')
@@ -63,4 +63,32 @@ RSpec.describe HasEnvironmentScope do
end
end
end
+
+ describe '.for_environment' do
+ subject { project.variables.for_environment(environment) }
+
+ let_it_be(:variable1) do
+ create(:ci_variable, project: project, environment_scope: '*')
+ end
+
+ let_it_be(:variable2) do
+ create(:ci_variable, project: project, environment_scope: 'production/*')
+ end
+
+ let_it_be(:variable3) do
+ create(:ci_variable, project: project, environment_scope: 'staging/*')
+ end
+
+ context 'when the environment is present' do
+ let(:environment) { 'production/canary-1' }
+
+ it { is_expected.to eq([variable1, variable2]) }
+ end
+
+ context 'when the environment is nil' do
+ let(:environment) {}
+
+ it { is_expected.to eq([variable1]) }
+ end
+ end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index e9c3d1dc646..832d5b44e5d 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -935,6 +935,14 @@ RSpec.describe Issuable do
subject { issuable.supports_escalation? }
it { is_expected.to eq(supports_escalation) }
+
+ context 'with feature disabled' do
+ before do
+ stub_feature_flags(incident_escalations: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
end
end
diff --git a/spec/models/concerns/resolvable_discussion_spec.rb b/spec/models/concerns/resolvable_discussion_spec.rb
index fc154738f11..7e08f47fb5a 100644
--- a/spec/models/concerns/resolvable_discussion_spec.rb
+++ b/spec/models/concerns/resolvable_discussion_spec.rb
@@ -584,4 +584,14 @@ RSpec.describe Discussion, ResolvableDiscussion do
expect(subject.last_resolved_note).to eq(second_note)
end
end
+
+ describe '#clear_memoized_values' do
+ it 'resets the memoized values' do
+ described_class.memoized_values.each do |memo|
+ subject.instance_variable_set("@#{memo}", 'memoized')
+ expect { subject.clear_memoized_values }.to change { subject.instance_variable_get("@#{memo}") }
+ .from('memoized').to(nil)
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/taskable_spec.rb b/spec/models/concerns/taskable_spec.rb
new file mode 100644
index 00000000000..6b41174a046
--- /dev/null
+++ b/spec/models/concerns/taskable_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Taskable do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '.get_tasks' do
+ let(:description) do
+ <<~MARKDOWN
+ Any text before the list
+ - [ ] First item
+ - [x] Second item
+ * [x] First item
+ * [ ] Second item
+ MARKDOWN
+ end
+
+ let(:expected_result) do
+ [
+ TaskList::Item.new('- [ ]', 'First item'),
+ TaskList::Item.new('- [x]', 'Second item'),
+ TaskList::Item.new('* [x]', 'First item'),
+ TaskList::Item.new('* [ ]', 'Second item')
+ ]
+ end
+
+ subject { described_class.get_tasks(description) }
+
+ it { is_expected.to match(expected_result) }
+ end
+
+ describe '#task_list_items' do
+ where(issuable_type: [:issue, :merge_request])
+
+ with_them do
+ let(:issuable) { build(issuable_type, description: description) }
+
+ subject(:result) { issuable.task_list_items }
+
+ context 'when description is present' do
+ let(:description) { 'markdown' }
+
+ it 'gets tasks from markdown' do
+ expect(described_class).to receive(:get_tasks)
+
+ result
+ end
+ end
+
+ context 'when description is blank' do
+ let(:description) { '' }
+
+ it 'returns empty array' do
+ expect(result).to be_empty
+ end
+
+ it 'does not try to get tasks from markdown' do
+ expect(described_class).not_to receive(:get_tasks)
+
+ result
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 4bdb3e0a32a..2e82a12a61a 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -289,4 +289,142 @@ RSpec.describe Ci::Build, 'TokenAuthenticatable' do
expect(build.read_attribute('token')).to be_nil
end
end
+
+ describe '#token_with_expiration' do
+ describe '#expirable?' do
+ subject { build.token_with_expiration.expirable? }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+end
+
+RSpec.describe Ci::Runner, 'TokenAuthenticatable', :freeze_time do
+ let_it_be(:non_expirable_runner) { create(:ci_runner) }
+ let_it_be(:non_expired_runner) { create(:ci_runner).tap { |r| r.update!(token_expires_at: 5.seconds.from_now) } }
+ let_it_be(:expired_runner) { create(:ci_runner).tap { |r| r.update!(token_expires_at: 5.seconds.ago) } }
+
+ describe '#token_expired?' do
+ subject { runner.token_expired? }
+
+ context 'when enforce_runner_token_expires_at feature flag is disabled' do
+ before do
+ stub_feature_flags(enforce_runner_token_expires_at: false)
+ end
+
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when enforce_runner_token_expires_at feature flag is enabled' do
+ before do
+ stub_feature_flags(enforce_runner_token_expires_at: true)
+ end
+
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
+
+ describe '#token_with_expiration' do
+ describe '#token' do
+ subject { non_expired_runner.token_with_expiration.token }
+
+ it { is_expected.to eq(non_expired_runner.token) }
+ end
+
+ describe '#token_expires_at' do
+ subject { non_expired_runner.token_with_expiration.token_expires_at }
+
+ it { is_expected.to eq(non_expired_runner.token_expires_at) }
+ end
+
+ describe '#expirable?' do
+ subject { non_expired_runner.token_with_expiration.expirable? }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
+ describe '.find_by_token' do
+ subject { Ci::Runner.find_by_token(runner.token) }
+
+ context 'when enforce_runner_token_expires_at feature flag is disabled' do
+ before do
+ stub_feature_flags(enforce_runner_token_expires_at: false)
+ end
+
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
+
+ it { is_expected.to eq(non_expirable_runner) }
+ end
+
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
+
+ it { is_expected.to eq(non_expired_runner) }
+ end
+
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
+
+ it { is_expected.to eq(expired_runner) }
+ end
+ end
+
+ context 'when enforce_runner_token_expires_at feature flag is enabled' do
+ before do
+ stub_feature_flags(enforce_runner_token_expires_at: true)
+ end
+
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
+
+ it { is_expected.to eq(non_expirable_runner) }
+ end
+
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
+
+ it { is_expected.to eq(non_expired_runner) }
+ end
+
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
index b311e302a31..1772fd0ff95 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
@@ -23,6 +23,8 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
let(:options) { { encrypted: :required } }
it 'finds the encrypted resource by cleartext' do
+ allow(model).to receive(:where)
+ .and_return(model)
allow(model).to receive(:find_by)
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
.and_return('encrypted resource')
@@ -36,6 +38,8 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
let(:options) { { encrypted: :optional } }
it 'finds the encrypted resource by cleartext' do
+ allow(model).to receive(:where)
+ .and_return(model)
allow(model).to receive(:find_by)
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
.and_return('encrypted resource')
@@ -49,6 +53,8 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
.to receive(:find_token_authenticatable)
.and_return('plaintext resource')
+ allow(model).to receive(:where)
+ .and_return(model)
allow(model).to receive(:find_by)
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
.and_return(nil)
@@ -62,6 +68,8 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
let(:options) { { encrypted: :migrating } }
it 'finds the cleartext resource by cleartext' do
+ allow(model).to receive(:where)
+ .and_return(model)
allow(model).to receive(:find_by)
.with('some_field' => 'my-value')
.and_return('cleartext resource')
@@ -71,6 +79,8 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
it 'returns nil if resource cannot be found' do
+ allow(model).to receive(:where)
+ .and_return(model)
allow(model).to receive(:find_by)
.with('some_field' => 'my-value')
.and_return(nil)
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index 8f7c13d7ae6..7c0ae51223b 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ContainerRepository do
+RSpec.describe ContainerRepository, :aggregate_failures do
using RSpec::Parameterized::TableSyntax
let(:group) { create(:group, name: 'group') }
@@ -36,7 +36,467 @@ RSpec.describe ContainerRepository do
describe 'validations' do
it { is_expected.to validate_presence_of(:migration_retries_count) }
it { is_expected.to validate_numericality_of(:migration_retries_count).is_greater_than_or_equal_to(0) }
- it { is_expected.to validate_presence_of(:migration_state) }
+
+ it { is_expected.to validate_inclusion_of(:migration_aborted_in_state).in_array(described_class::ABORTABLE_MIGRATION_STATES) }
+ it { is_expected.to allow_value(nil).for(:migration_aborted_in_state) }
+
+ context 'migration_state' do
+ it { is_expected.to validate_presence_of(:migration_state) }
+ it { is_expected.to validate_inclusion_of(:migration_state).in_array(described_class::MIGRATION_STATES) }
+
+ describe 'pre_importing' do
+ it 'validates expected attributes' do
+ expect(build(:container_repository, migration_state: 'pre_importing')).to be_invalid
+ expect(build(:container_repository, :pre_importing)).to be_valid
+ end
+ end
+
+ describe 'pre_import_done' do
+ it 'validates expected attributes' do
+ expect(build(:container_repository, migration_state: 'pre_import_done')).to be_invalid
+ expect(build(:container_repository, :pre_import_done)).to be_valid
+ end
+ end
+
+ describe 'importing' do
+ it 'validates expected attributes' do
+ expect(build(:container_repository, migration_state: 'importing')).to be_invalid
+ expect(build(:container_repository, :importing)).to be_valid
+ end
+ end
+
+ describe 'import_skipped' do
+ it 'validates expected attributes' do
+ expect(build(:container_repository, migration_state: 'import_skipped')).to be_invalid
+ expect(build(:container_repository, :import_skipped)).to be_valid
+ end
+ end
+
+ describe 'import_aborted' do
+ it 'validates expected attributes' do
+ expect(build(:container_repository, migration_state: 'import_aborted')).to be_invalid
+ expect(build(:container_repository, :import_aborted)).to be_valid
+ end
+ end
+ end
+ end
+
+ context ':migration_state state_machine' do
+ shared_examples 'no action when feature flag is disabled' do
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enabled: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ shared_examples 'transitioning to pre_importing', skip_pre_import_success: true do
+ before do
+ repository.update_column(:migration_pre_import_done_at, Time.zone.now)
+ end
+
+ it_behaves_like 'no action when feature flag is disabled'
+
+ context 'successful pre_import request' do
+ it 'sets migration_pre_import_started_at and resets migration_pre_import_done_at' do
+ expect(repository).to receive(:migration_pre_import).and_return(:ok)
+
+ expect { subject }.to change { repository.reload.migration_pre_import_started_at }
+ .and change { repository.migration_pre_import_done_at }.to(nil)
+
+ expect(repository).to be_pre_importing
+ end
+ end
+
+ context 'failed pre_import request' do
+ it 'sets migration_pre_import_started_at and resets migration_pre_import_done_at' do
+ expect(repository).to receive(:migration_pre_import).and_return(:error)
+
+ expect { subject }.to change { repository.reload.migration_pre_import_started_at }
+ .and change { repository.migration_aborted_at }
+ .and change { repository.migration_pre_import_done_at }.to(nil)
+
+ expect(repository.migration_aborted_in_state).to eq('pre_importing')
+ expect(repository).to be_import_aborted
+ end
+ end
+ end
+
+ shared_examples 'transitioning to importing', skip_import_success: true do
+ before do
+ repository.update_columns(migration_import_done_at: Time.zone.now)
+ end
+
+ context 'successful import request' do
+ it 'sets migration_import_started_at and resets migration_import_done_at' do
+ expect(repository).to receive(:migration_import).and_return(:ok)
+
+ expect { subject }.to change { repository.reload.migration_import_started_at }
+ .and change { repository.migration_import_done_at }.to(nil)
+
+ expect(repository).to be_importing
+ end
+ end
+
+ context 'failed import request' do
+ it 'sets migration_import_started_at and resets migration_import_done_at' do
+ expect(repository).to receive(:migration_import).and_return(:error)
+
+ expect { subject }.to change { repository.reload.migration_import_started_at }
+ .and change { repository.migration_aborted_at }
+
+ expect(repository.migration_aborted_in_state).to eq('importing')
+ expect(repository).to be_import_aborted
+ end
+ end
+ end
+
+ shared_examples 'transitioning out of import_aborted' do
+ it 'resets migration_aborted_at and migration_aborted_in_state' do
+ expect { subject }.to change { repository.reload.migration_aborted_in_state }.to(nil)
+ .and change { repository.migration_aborted_at }.to(nil)
+ end
+ end
+
+ shared_examples 'transitioning from allowed states' do |allowed_states|
+ described_class::MIGRATION_STATES.each do |state|
+ result = allowed_states.include?(state)
+
+ context "when transitioning from #{state}" do
+ let(:repository) { create(:container_repository, state.to_sym) }
+
+ it "returns #{result}" do
+ expect(subject).to eq(result)
+ end
+ end
+ end
+ end
+
+ shared_examples 'queueing the next import' do
+ it 'starts the worker' do
+ expect(::ContainerRegistry::Migration::EnqueuerWorker).to receive(:perform_async)
+
+ subject
+ end
+ end
+
+ describe '#start_pre_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository) }
+
+ subject { repository.start_pre_import }
+
+ before do |example|
+ unless example.metadata[:skip_pre_import_success]
+ allow(repository).to receive(:migration_pre_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'transitioning from allowed states', %w[default]
+ it_behaves_like 'transitioning to pre_importing'
+ end
+
+ describe '#retry_pre_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :import_aborted) }
+
+ subject { repository.retry_pre_import }
+
+ before do |example|
+ unless example.metadata[:skip_pre_import_success]
+ allow(repository).to receive(:migration_pre_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'transitioning from allowed states', %w[import_aborted]
+ it_behaves_like 'transitioning to pre_importing'
+ it_behaves_like 'transitioning out of import_aborted'
+ end
+
+ describe '#finish_pre_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :pre_importing) }
+
+ subject { repository.finish_pre_import }
+
+ it_behaves_like 'transitioning from allowed states', %w[pre_importing import_aborted]
+
+ it 'sets migration_pre_import_done_at' do
+ expect { subject }.to change { repository.reload.migration_pre_import_done_at }
+
+ expect(repository).to be_pre_import_done
+ end
+ end
+
+ describe '#start_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :pre_import_done) }
+
+ subject { repository.start_import }
+
+ before do |example|
+ unless example.metadata[:skip_import_success]
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'transitioning from allowed states', %w[pre_import_done]
+ it_behaves_like 'transitioning to importing'
+ end
+
+ describe '#retry_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :import_aborted) }
+
+ subject { repository.retry_import }
+
+ before do |example|
+ unless example.metadata[:skip_import_success]
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'transitioning from allowed states', %w[import_aborted]
+ it_behaves_like 'transitioning to importing'
+ it_behaves_like 'no action when feature flag is disabled'
+ end
+
+ describe '#finish_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :importing) }
+
+ subject { repository.finish_import }
+
+ it_behaves_like 'transitioning from allowed states', %w[importing import_aborted]
+ it_behaves_like 'queueing the next import'
+
+ it 'sets migration_import_done_at and queues the next import' do
+ expect { subject }.to change { repository.reload.migration_import_done_at }
+
+ expect(repository).to be_import_done
+ end
+ end
+
+ describe '#already_migrated' do
+ let_it_be_with_reload(:repository) { create(:container_repository) }
+
+ subject { repository.already_migrated }
+
+ it_behaves_like 'transitioning from allowed states', %w[default]
+
+ it 'sets migration_import_done_at' do
+ subject
+
+ expect(repository).to be_import_done
+ end
+ end
+
+ describe '#abort_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :importing) }
+
+ subject { repository.abort_import }
+
+ it_behaves_like 'transitioning from allowed states', ContainerRepository::ABORTABLE_MIGRATION_STATES
+ it_behaves_like 'queueing the next import'
+
+ it 'sets migration_aborted_at and migration_aborted_at, increments the retry count, and queues the next import' do
+ expect { subject }.to change { repository.migration_aborted_at }
+ .and change { repository.reload.migration_retries_count }.by(1)
+
+ expect(repository.migration_aborted_in_state).to eq('importing')
+ expect(repository).to be_import_aborted
+ end
+ end
+
+ describe '#skip_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository) }
+
+ subject { repository.skip_import(reason: :too_many_retries) }
+
+ it_behaves_like 'transitioning from allowed states', ContainerRepository::ABORTABLE_MIGRATION_STATES
+
+ it 'sets migration_skipped_at and migration_skipped_reason' do
+ expect { subject }.to change { repository.reload.migration_skipped_at }
+
+ expect(repository.migration_skipped_reason).to eq('too_many_retries')
+ expect(repository).to be_import_skipped
+ end
+
+ it 'raises and error if a reason is not given' do
+ expect { repository.skip_import }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe '#finish_pre_import_and_start_import' do
+ let_it_be_with_reload(:repository) { create(:container_repository, :pre_importing) }
+
+ subject { repository.finish_pre_import_and_start_import }
+
+ before do |example|
+ unless example.metadata[:skip_import_success]
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'transitioning from allowed states', %w[pre_importing import_aborted]
+ it_behaves_like 'transitioning to importing'
+ end
+ end
+
+ context 'when triggering registry API requests' do
+ let(:repository_state) { nil }
+ let(:repository) { create(:container_repository, repository_state) }
+
+ shared_examples 'a state machine configured with use_transactions: false' do
+ it 'executes the registry API request outside of a transaction', :delete do
+ expect(repository).to receive(:save).and_call_original do
+ expect(ApplicationRecord.connection.transaction_open?).to be true
+ end
+
+ expect(repository).to receive(:try_import) do
+ expect(ApplicationRecord.connection.transaction_open?).to be false
+ end
+
+ subject
+ end
+ end
+
+ context 'when responding to a start_pre_import event' do
+ subject { repository.start_pre_import }
+
+ it_behaves_like 'a state machine configured with use_transactions: false'
+ end
+
+ context 'when responding to a retry_pre_import event' do
+ let(:repository_state) { :import_aborted }
+
+ subject { repository.retry_pre_import }
+
+ it_behaves_like 'a state machine configured with use_transactions: false'
+ end
+
+ context 'when responding to a start_import event' do
+ let(:repository_state) { :pre_import_done }
+
+ subject { repository.start_import }
+
+ it_behaves_like 'a state machine configured with use_transactions: false'
+ end
+
+ context 'when responding to a retry_import event' do
+ let(:repository_state) { :import_aborted }
+
+ subject { repository.retry_import }
+
+ it_behaves_like 'a state machine configured with use_transactions: false'
+ end
+ end
+
+ describe '#retry_aborted_migration' do
+ subject { repository.retry_aborted_migration }
+
+ shared_examples 'no action' do
+ it 'does nothing' do
+ expect { subject }.not_to change { repository.reload.migration_state }
+
+ expect(subject).to eq(nil)
+ end
+ end
+
+ shared_examples 'retrying the pre_import' do
+ it 'retries the pre_import' do
+ expect(repository).to receive(:migration_pre_import).and_return(:ok)
+
+ expect { subject }.to change { repository.reload.migration_state }.to('pre_importing')
+ end
+ end
+
+ shared_examples 'retrying the import' do
+ it 'retries the import' do
+ expect(repository).to receive(:migration_import).and_return(:ok)
+
+ expect { subject }.to change { repository.reload.migration_state }.to('importing')
+ end
+ end
+
+ context 'when migration_state is not aborted' do
+ it_behaves_like 'no action'
+ end
+
+ context 'when migration_state is aborted' do
+ before do
+ repository.abort_import
+
+ allow(repository.gitlab_api_client)
+ .to receive(:import_status).with(repository.path).and_return(client_response)
+ end
+
+ context 'native response' do
+ let(:client_response) { 'native' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::NativeImportError)
+ end
+ end
+
+ context 'import_in_progress response' do
+ let(:client_response) { 'import_in_progress' }
+
+ it_behaves_like 'no action'
+ end
+
+ context 'import_complete response' do
+ let(:client_response) { 'import_complete' }
+
+ it 'finishes the import' do
+ expect { subject }.to change { repository.reload.migration_state }.to('import_done')
+ end
+ end
+
+ context 'import_failed response' do
+ let(:client_response) { 'import_failed' }
+
+ it_behaves_like 'retrying the import'
+ end
+
+ context 'pre_import_in_progress response' do
+ let(:client_response) { 'pre_import_in_progress' }
+
+ it_behaves_like 'no action'
+ end
+
+ context 'pre_import_complete response' do
+ let(:client_response) { 'pre_import_complete' }
+
+ it 'finishes the pre_import and starts the import' do
+ expect(repository).to receive(:finish_pre_import).and_call_original
+ expect(repository).to receive(:migration_import).and_return(:ok)
+
+ expect { subject }.to change { repository.reload.migration_state }.to('importing')
+ end
+ end
+
+ context 'pre_import_failed response' do
+ let(:client_response) { 'pre_import_failed' }
+
+ it_behaves_like 'retrying the pre_import'
+ end
+
+ context 'error response' do
+ let(:client_response) { 'error' }
+
+ context 'migration_pre_import_done_at is NULL' do
+ it_behaves_like 'retrying the pre_import'
+ end
+
+ context 'migration_pre_import_done_at is not NULL' do
+ before do
+ repository.update_columns(
+ migration_pre_import_started_at: 5.minutes.ago,
+ migration_pre_import_done_at: Time.zone.now
+ )
+ end
+
+ it_behaves_like 'retrying the import'
+ end
+ end
+ end
end
describe '#tag' do
@@ -209,6 +669,54 @@ RSpec.describe ContainerRepository do
end
end
+ context 'registry migration' do
+ shared_examples 'handling the migration step' do |step|
+ let(:client_response) { :foobar }
+
+ before do
+ allow(repository.gitlab_api_client).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ it 'returns the same response as the client' do
+ expect(repository.gitlab_api_client)
+ .to receive(step).with(repository.path).and_return(client_response)
+ expect(subject).to eq(client_response)
+ end
+
+ context 'when the gitlab_api feature is not supported' do
+ before do
+ allow(repository.gitlab_api_client).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it 'returns :error' do
+ expect(repository.gitlab_api_client).not_to receive(step)
+
+ expect(subject).to eq(:error)
+ end
+ end
+
+ context 'too many imports' do
+ it 'raises an error when it receives too_many_imports as a response' do
+ expect(repository.gitlab_api_client)
+ .to receive(step).with(repository.path).and_return(:too_many_imports)
+ expect { subject }.to raise_error(described_class::TooManyImportsError)
+ end
+ end
+ end
+
+ describe '#migration_pre_import' do
+ subject { repository.migration_pre_import }
+
+ it_behaves_like 'handling the migration step', :pre_import_repository
+ end
+
+ describe '#migration_import' do
+ subject { repository.migration_import }
+
+ it_behaves_like 'handling the migration step', :import_repository
+ end
+ end
+
describe '.build_from_path' do
let(:registry_path) do
ContainerRegistry::Path.new(project.full_path + '/some/image')
@@ -304,7 +812,7 @@ RSpec.describe ContainerRepository do
let(:path) { ContainerRegistry::Path.new(project.full_path + '/some/image') }
it 'does not throw validation errors and only creates one repository' do
- expect { repository_creation_race(path) }.to change { ContainerRepository.count }.by(1)
+ expect { repository_creation_race(path) }.to change { described_class.count }.by(1)
end
it 'retrieves a persisted repository for all concurrent calls' do
@@ -322,7 +830,7 @@ RSpec.describe ContainerRepository do
Thread.new do
true while wait_for_it
- ::ContainerRepository.find_or_create_from_path(path)
+ described_class.find_or_create_from_path(path)
end
end
wait_for_it = false
@@ -330,6 +838,52 @@ RSpec.describe ContainerRepository do
end
end
+ describe '.find_by_path' do
+ let_it_be(:container_repository) { create(:container_repository) }
+ let_it_be(:repository_path) { container_repository.project.full_path }
+
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/' + container_repository.name) }
+
+ subject { described_class.find_by_path(path) }
+
+ context 'when repository exists' do
+ it 'finds the repository' do
+ expect(subject).to eq(container_repository)
+ end
+ end
+
+ context 'when repository does not exist' do
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/some/image') }
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+ end
+
+ describe '.find_by_path!' do
+ let_it_be(:container_repository) { create(:container_repository) }
+ let_it_be(:repository_path) { container_repository.project.full_path }
+
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/' + container_repository.name) }
+
+ subject { described_class.find_by_path!(path) }
+
+ context 'when repository exists' do
+ it 'finds the repository' do
+ expect(subject).to eq(container_repository)
+ end
+ end
+
+ context 'when repository does not exist' do
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/some/image') }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
describe '.build_root_repository' do
let(:repository) do
described_class.build_root_repository(project)
@@ -412,6 +966,36 @@ RSpec.describe ContainerRepository do
it { is_expected.to contain_exactly(repository1, repository2, repository4) }
end
+ describe '.with_migration_import_started_at_nil_or_before' do
+ let_it_be(:repository1) { create(:container_repository, migration_import_started_at: 5.minutes.ago) }
+ let_it_be(:repository2) { create(:container_repository, migration_import_started_at: nil) }
+ let_it_be(:repository3) { create(:container_repository, migration_import_started_at: 10.minutes.ago) }
+
+ subject { described_class.with_migration_import_started_at_nil_or_before(7.minutes.ago) }
+
+ it { is_expected.to contain_exactly(repository2, repository3) }
+ end
+
+ describe '.with_migration_pre_import_started_at_nil_or_before' do
+ let_it_be(:repository1) { create(:container_repository, migration_pre_import_started_at: 5.minutes.ago) }
+ let_it_be(:repository2) { create(:container_repository, migration_pre_import_started_at: nil) }
+ let_it_be(:repository3) { create(:container_repository, migration_pre_import_started_at: 10.minutes.ago) }
+
+ subject { described_class.with_migration_pre_import_started_at_nil_or_before(7.minutes.ago) }
+
+ it { is_expected.to contain_exactly(repository2, repository3) }
+ end
+
+ describe '.with_migration_pre_import_done_at_nil_or_before' do
+ let_it_be(:repository1) { create(:container_repository, migration_pre_import_done_at: 5.minutes.ago) }
+ let_it_be(:repository2) { create(:container_repository, migration_pre_import_done_at: nil) }
+ let_it_be(:repository3) { create(:container_repository, migration_pre_import_done_at: 10.minutes.ago) }
+
+ subject { described_class.with_migration_pre_import_done_at_nil_or_before(7.minutes.ago) }
+
+ it { is_expected.to contain_exactly(repository2, repository3) }
+ 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) }
@@ -458,6 +1042,97 @@ RSpec.describe ContainerRepository do
it { is_expected.to eq([repository]) }
end
+ describe '#migration_in_active_state?' do
+ subject { container_repository.migration_in_active_state? }
+
+ described_class::MIGRATION_STATES.each do |state|
+ context "when in #{state} migration_state" do
+ let(:container_repository) { create(:container_repository, state.to_sym)}
+
+ it { is_expected.to eq(state == 'importing' || state == 'pre_importing') }
+ end
+ end
+ end
+
+ describe '#migration_importing?' do
+ subject { container_repository.migration_importing? }
+
+ described_class::MIGRATION_STATES.each do |state|
+ context "when in #{state} migration_state" do
+ let(:container_repository) { create(:container_repository, state.to_sym)}
+
+ it { is_expected.to eq(state == 'importing') }
+ end
+ end
+ end
+
+ describe '#migration_pre_importing?' do
+ subject { container_repository.migration_pre_importing? }
+
+ described_class::MIGRATION_STATES.each do |state|
+ context "when in #{state} migration_state" do
+ let(:container_repository) { create(:container_repository, state.to_sym)}
+
+ it { is_expected.to eq(state == 'pre_importing') }
+ end
+ end
+ end
+
+ describe '#try_import' do
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+
+ let(:response) { nil }
+
+ subject do
+ container_repository.try_import do
+ container_repository.foo
+ end
+ end
+
+ before do
+ allow(container_repository).to receive(:foo).and_return(response)
+ end
+
+ context 'successful request' do
+ let(:response) { :ok }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'TooManyImportsError' do
+ before do
+ stub_application_setting(container_registry_import_start_max_retries: 3)
+ allow(container_repository).to receive(:foo).and_raise(described_class::TooManyImportsError)
+ end
+
+ it 'tries again exponentially and aborts the migration' do
+ expect(container_repository).to receive(:sleep).with(a_value_within(0.01).of(0.1))
+ expect(container_repository).to receive(:sleep).with(a_value_within(0.01).of(0.2))
+ expect(container_repository).to receive(:sleep).with(a_value_within(0.01).of(0.3))
+
+ expect(subject).to eq(false)
+
+ expect(container_repository).to be_import_aborted
+ end
+ end
+
+ context 'other response' do
+ let(:response) { :error }
+
+ it 'aborts the migration' do
+ expect(subject).to eq(false)
+
+ expect(container_repository).to be_import_aborted
+ end
+ end
+
+ context 'with no block given' do
+ it 'raises an error' do
+ expect { container_repository.try_import }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
context 'with repositories' do
let_it_be_with_reload(:repository) { create(:container_repository, :cleanup_unscheduled) }
let_it_be(:other_repository) { create(:container_repository, :cleanup_unscheduled) }
@@ -509,5 +1184,87 @@ RSpec.describe ContainerRepository do
it { is_expected.to eq([repository]) }
end
end
+
+ describe '.recently_done_migration_step' do
+ let_it_be(:import_done_repository) { create(:container_repository, :import_done, migration_pre_import_done_at: 3.days.ago, migration_import_done_at: 2.days.ago) }
+ let_it_be(:import_aborted_repository) { create(:container_repository, :import_aborted, migration_pre_import_done_at: 5.days.ago, migration_aborted_at: 1.day.ago) }
+ let_it_be(:pre_import_done_repository) { create(:container_repository, :pre_import_done, migration_pre_import_done_at: 1.hour.ago) }
+
+ subject { described_class.recently_done_migration_step }
+
+ it 'returns completed imports by done_at date' do
+ expect(subject.to_a).to eq([pre_import_done_repository, import_aborted_repository, import_done_repository])
+ end
+ end
+
+ describe '.ready_for_import' do
+ include_context 'importable repositories'
+
+ subject { described_class.ready_for_import }
+
+ before do
+ stub_application_setting(container_registry_import_target_plan: project.namespace.actual_plan_name)
+ end
+
+ it 'works' do
+ expect(subject).to contain_exactly(valid_container_repository, valid_container_repository2)
+ end
+ end
+
+ describe '#last_import_step_done_at' do
+ let_it_be(:aborted_at) { Time.zone.now - 1.hour }
+ let_it_be(:pre_import_done_at) { Time.zone.now - 2.hours }
+
+ subject { repository.last_import_step_done_at }
+
+ before do
+ repository.update_columns(
+ migration_pre_import_done_at: pre_import_done_at,
+ migration_aborted_at: aborted_at
+ )
+ end
+
+ it { is_expected.to eq(aborted_at) }
+ end
+ end
+
+ describe '#external_import_status' do
+ subject { repository.external_import_status }
+
+ it 'returns the response from the client' do
+ expect(repository.gitlab_api_client).to receive(:import_status).with(repository.path).and_return('test')
+
+ expect(subject).to eq('test')
+ end
+ end
+
+ describe '.with_stale_migration' do
+ let_it_be(:repository) { create(:container_repository) }
+ let_it_be(:stale_pre_importing_old_timestamp) { create(:container_repository, :pre_importing, migration_pre_import_started_at: 10.minutes.ago) }
+ let_it_be(:stale_pre_importing_nil_timestamp) { create(:container_repository, :pre_importing).tap { |r| r.update_column(:migration_pre_import_started_at, nil) } }
+ let_it_be(:stale_pre_importing_recent_timestamp) { create(:container_repository, :pre_importing, migration_pre_import_started_at: 2.minutes.ago) }
+
+ let_it_be(:stale_pre_import_done_old_timestamp) { create(:container_repository, :pre_import_done, migration_pre_import_done_at: 10.minutes.ago) }
+ let_it_be(:stale_pre_import_done_nil_timestamp) { create(:container_repository, :pre_import_done).tap { |r| r.update_column(:migration_pre_import_done_at, nil) } }
+ let_it_be(:stale_pre_import_done_recent_timestamp) { create(:container_repository, :pre_import_done, migration_pre_import_done_at: 2.minutes.ago) }
+
+ let_it_be(:stale_importing_old_timestamp) { create(:container_repository, :importing, migration_import_started_at: 10.minutes.ago) }
+ let_it_be(:stale_importing_nil_timestamp) { create(:container_repository, :importing).tap { |r| r.update_column(:migration_import_started_at, nil) } }
+ let_it_be(:stale_importing_recent_timestamp) { create(:container_repository, :importing, migration_import_started_at: 2.minutes.ago) }
+
+ let(:stale_migrations) do
+ [
+ stale_pre_importing_old_timestamp,
+ stale_pre_importing_nil_timestamp,
+ stale_pre_import_done_old_timestamp,
+ stale_pre_import_done_nil_timestamp,
+ stale_importing_old_timestamp,
+ stale_importing_nil_timestamp
+ ]
+ end
+
+ subject { described_class.with_stale_migration(5.minutes.ago) }
+
+ it { is_expected.to contain_exactly(*stale_migrations) }
end
end
diff --git a/spec/models/customer_relations/contact_spec.rb b/spec/models/customer_relations/contact_spec.rb
index 1225f9d089b..c7b0f1bd3d4 100644
--- a/spec/models/customer_relations/contact_spec.rb
+++ b/spec/models/customer_relations/contact_spec.rb
@@ -26,6 +26,18 @@ RSpec.describe CustomerRelations::Contact, type: :model do
it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :email
end
+ describe '.reference_prefix' do
+ it { expect(described_class.reference_prefix).to eq('[contact:') }
+ end
+
+ describe '.reference_prefix_quoted' do
+ it { expect(described_class.reference_prefix_quoted).to eq('["contact:') }
+ end
+
+ describe '.reference_postfix' do
+ it { expect(described_class.reference_postfix).to eq(']') }
+ end
+
describe '#unique_email_for_group_hierarchy' do
let_it_be(:parent) { create(:group) }
let_it_be(:group) { create(:group, parent: parent) }
@@ -98,4 +110,31 @@ RSpec.describe CustomerRelations::Contact, type: :model do
expect { described_class.find_ids_by_emails(group, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
end
end
+
+ describe '#self.exists_for_group?' do
+ let(:group) { create(:group) }
+ let(:subgroup) { create(:group, parent: group) }
+
+ context 'with no contacts in group or parent' do
+ it 'returns false' do
+ expect(described_class.exists_for_group?(subgroup)).to be_falsey
+ end
+ end
+
+ context 'with contacts in group' do
+ it 'returns true' do
+ create(:contact, group: subgroup)
+
+ expect(described_class.exists_for_group?(subgroup)).to be_truthy
+ end
+ end
+
+ context 'with contacts in parent' do
+ it 'returns true' do
+ create(:contact, group: group)
+
+ expect(described_class.exists_for_group?(subgroup)).to be_truthy
+ end
+ end
+ end
end
diff --git a/spec/models/customer_relations/issue_contact_spec.rb b/spec/models/customer_relations/issue_contact_spec.rb
index c6373fddbfb..39da0b64ea0 100644
--- a/spec/models/customer_relations/issue_contact_spec.rb
+++ b/spec/models/customer_relations/issue_contact_spec.rb
@@ -80,4 +80,12 @@ RSpec.describe CustomerRelations::IssueContact do
expect { described_class.find_contact_ids_by_emails(issue.id, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
end
end
+
+ describe '.delete_for_project' do
+ let_it_be(:issue_contacts) { create_list(:issue_customer_relations_contact, 3, :for_issue, issue: create(:issue, project: project)) }
+
+ it 'destroys all issue_contacts for project' do
+ expect { described_class.delete_for_project(project.id) }.to change { described_class.count }.by(-3)
+ end
+ end
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 29b37ef7371..47c246d12cc 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -369,38 +369,6 @@ RSpec.describe Deployment do
end
end
- describe '#finished_at' do
- subject { deployment.finished_at }
-
- context 'when deployment status is created' do
- let(:deployment) { create(:deployment) }
-
- it { is_expected.to be_nil }
- end
-
- context 'when deployment status is success' do
- let(:deployment) { create(:deployment, :success) }
-
- it { is_expected.to eq(deployment.read_attribute(:finished_at)) }
- end
-
- context 'when deployment status is success' do
- let(:deployment) { create(:deployment, :success, finished_at: nil) }
-
- before do
- deployment.update_column(:finished_at, nil)
- end
-
- it { is_expected.to eq(deployment.read_attribute(:created_at)) }
- end
-
- context 'when deployment status is running' do
- let(:deployment) { create(:deployment, :running) }
-
- it { is_expected.to be_nil }
- end
- end
-
describe '#deployed_at' do
subject { deployment.deployed_at }
@@ -615,7 +583,7 @@ RSpec.describe Deployment do
it 'returns false' do
commit = project.commit('feature')
- expect(deployment.includes_commit?(commit)).to be false
+ expect(deployment.includes_commit?(commit.id)).to be false
end
end
@@ -623,7 +591,7 @@ RSpec.describe Deployment do
it 'returns true' do
commit = project.commit
- expect(deployment.includes_commit?(commit)).to be true
+ expect(deployment.includes_commit?(commit.id)).to be true
end
end
@@ -632,7 +600,7 @@ RSpec.describe Deployment do
deployment.update!(sha: Gitlab::Git::BLANK_SHA)
commit = project.commit
- expect(deployment.includes_commit?(commit)).to be false
+ expect(deployment.includes_commit?(commit.id)).to be false
end
end
end
diff --git a/spec/models/design_management/design_action_spec.rb b/spec/models/design_management/design_action_spec.rb
index 958b1dd9124..4d60ef77025 100644
--- a/spec/models/design_management/design_action_spec.rb
+++ b/spec/models/design_management/design_action_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe DesignManagement::DesignAction do
describe '#gitaly_action' do
let(:path) { 'some/path/somewhere' }
- let(:design) { OpenStruct.new(full_path: path) }
+ let(:design) { double('path', full_path: path) }
subject { described_class.new(design, action, content) }
@@ -75,7 +75,7 @@ RSpec.describe DesignManagement::DesignAction do
describe '#issue_id' do
let(:issue_id) { :foo }
- let(:design) { OpenStruct.new(issue_id: issue_id) }
+ let(:design) { double('id', issue_id: issue_id) }
subject { described_class.new(design, :delete) }
diff --git a/spec/models/design_management/design_at_version_spec.rb b/spec/models/design_management/design_at_version_spec.rb
index a7cf6a9652b..7f1fe7b1e13 100644
--- a/spec/models/design_management/design_at_version_spec.rb
+++ b/spec/models/design_management/design_at_version_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe DesignManagement::DesignAtVersion do
it 'rejects objects with the same id and the wrong class' do
dav = build_stubbed(:design_at_version)
- expect(dav).not_to eq(OpenStruct.new(id: dav.id))
+ expect(dav).not_to eq(double('id', id: dav.id))
end
it 'expects objects to be of the same type, not subtypes' do
diff --git a/spec/models/draft_note_spec.rb b/spec/models/draft_note_spec.rb
index 580a588ae1d..0f85871fd9e 100644
--- a/spec/models/draft_note_spec.rb
+++ b/spec/models/draft_note_spec.rb
@@ -20,6 +20,28 @@ RSpec.describe DraftNote do
it { is_expected.to delegate_method(:file_identifier_hash).to(:diff_file).allow_nil }
end
+ describe '#line_code' do
+ describe 'stored line_code' do
+ let(:draft_note) { build(:draft_note, merge_request: merge_request, line_code: '1234567890') }
+
+ it 'returns stored line_code' do
+ expect(draft_note.line_code).to eq('1234567890')
+ end
+ end
+
+ describe 'none stored line_code' do
+ let(:draft_note) { build(:draft_note, merge_request: merge_request) }
+
+ before do
+ allow(draft_note).to receive(:find_line_code).and_return('none stored line_code')
+ end
+
+ it 'returns found line_code' do
+ expect(draft_note.line_code).to eq('none stored line_code')
+ end
+ end
+ end
+
describe '#diff_file' do
let(:draft_note) { build(:draft_note, merge_request: merge_request) }
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 3dd0e01d7b3..112dc93658f 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -412,7 +412,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
context 'in the same branch' do
it 'returns true' do
- expect(environment.includes_commit?(RepoHelpers.sample_commit)).to be true
+ expect(environment.includes_commit?(RepoHelpers.sample_commit.id)).to be true
end
end
@@ -422,7 +422,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
it 'returns false' do
- expect(environment.includes_commit?(RepoHelpers.sample_commit)).to be false
+ expect(environment.includes_commit?(RepoHelpers.sample_commit.id)).to be false
end
end
end
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 1b9b38a0932..1db1171401c 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -161,7 +161,7 @@ RSpec.describe EnvironmentStatus do
let!(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
let(:environment) { build.deployment.environment }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
context 'when environment is created on a forked project', :sidekiq_inline do
let(:project) { create(:project, :repository) }
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 97854086162..f099015e63e 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -25,20 +25,21 @@ RSpec.describe Event do
expect(instance).to receive(:reset_project_activity)
end
- create_push_event(project, project.owner)
+ create_push_event(project, project.first_owner)
end
end
describe 'after_create :set_last_repository_updated_at' do
context 'with a push event' do
- it 'updates the project last_repository_updated_at' do
- project.update!(last_repository_updated_at: 1.year.ago)
+ it 'updates the project last_repository_updated_at and updated_at' do
+ project.touch(:last_repository_updated_at, time: 1.year.ago) # rubocop: disable Rails/SkipsModelValidations
- create_push_event(project, project.owner)
+ event = create_push_event(project, project.first_owner)
project.reload
- expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.current)
+ expect(project.last_repository_updated_at).to be_like_time(event.created_at)
+ expect(project.updated_at).to be_like_time(event.created_at)
end
end
@@ -46,7 +47,7 @@ RSpec.describe Event do
it 'does not update the project last_repository_updated_at' do
project.update!(last_repository_updated_at: 1.year.ago)
- create(:closed_issue_event, project: project, author: project.owner)
+ create(:closed_issue_event, project: project, author: project.first_owner)
project.reload
@@ -62,14 +63,14 @@ RSpec.describe Event do
project.reload # a reload removes fractions of seconds
expect do
- create_push_event(project, project.owner)
+ create_push_event(project, project.first_owner)
project.reload
end.not_to change { project.last_repository_updated_at }
end
end
describe 'after_create UserInteractedProject.track' do
- let(:event) { build(:push_event, project: project, author: project.owner) }
+ let(:event) { build(:push_event, project: project, author: project.first_owner) }
it 'passes event to UserInteractedProject.track' do
expect(UserInteractedProject).to receive(:track).with(event)
@@ -156,7 +157,7 @@ RSpec.describe Event do
describe "Push event" do
let(:project) { create(:project, :private) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:event) { create_push_event(project, user) }
it do
@@ -172,7 +173,7 @@ RSpec.describe Event do
describe '#target_title' do
let_it_be(:project) { create(:project) }
- let(:author) { project.owner }
+ let(:author) { project.first_owner }
let(:target) { nil }
let(:event) do
@@ -745,7 +746,7 @@ RSpec.describe Event do
target = kind == :project ? nil : build(kind, **extra_data)
- [kind, build(:event, :created, author: project.owner, project: project, target: target)]
+ [kind, build(:event, :created, author: project.first_owner, project: project, target: target)]
end
end
@@ -829,19 +830,20 @@ RSpec.describe Event do
expect(project).not_to receive(:update_column)
.with(:last_activity_at, a_kind_of(Time))
- create_push_event(project, project.owner)
+ create_push_event(project, project.first_owner)
end
end
context 'when a project was updated more than 1 hour ago' do
it 'updates the project' do
- project.update!(last_activity_at: 1.year.ago)
+ project.touch(:last_activity_at, time: 1.year.ago) # rubocop: disable Rails/SkipsModelValidations
- create_push_event(project, project.owner)
+ event = create_push_event(project, project.first_owner)
project.reload
- expect(project.last_activity_at).to be_within(1.minute).of(Time.current)
+ expect(project.last_activity_at).to be_like_time(event.created_at)
+ expect(project.updated_at).to be_like_time(event.created_at)
end
end
end
diff --git a/spec/models/external_pull_request_spec.rb b/spec/models/external_pull_request_spec.rb
index b141600c4fd..82da7cdf34b 100644
--- a/spec/models/external_pull_request_spec.rb
+++ b/spec/models/external_pull_request_spec.rb
@@ -236,4 +236,11 @@ RSpec.describe ExternalPullRequest do
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :external_pull_request }
end
+
+ context 'loose foreign key on external_pull_requests.project_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:project) }
+ let!(:model) { create(:external_pull_request, project: parent) }
+ end
+ end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 05ee2166245..4bc4df02c24 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1249,7 +1249,7 @@ RSpec.describe Group 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 }
+ let(:user) { unrelated_project.first_owner }
it 'returns correct access level' do
expect(shared_group_parent.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb
index 85f433f5f81..0d65fe302e1 100644
--- a/spec/models/hooks/service_hook_spec.rb
+++ b/spec/models/hooks/service_hook_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ServiceHook do
let(:data) { { key: 'value' } }
it '#execute' do
- expect(WebHookService).to receive(:new).with(hook, data, 'service_hook').and_call_original
+ expect(WebHookService).to receive(:new).with(hook, data, 'service_hook', force: false).and_call_original
expect_any_instance_of(WebHookService).to receive(:execute)
hook.execute(data)
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index 89bfb742f5d..a3d36058b74 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -168,17 +168,17 @@ RSpec.describe SystemHook do
let(:data) { { key: 'value' } }
let(:hook_name) { 'system_hook' }
- before do
- expect(WebHookService).to receive(:new).with(hook, data, hook_name).and_call_original
- end
-
it '#execute' do
+ expect(WebHookService).to receive(:new).with(hook, data, hook_name, force: false).and_call_original
+
expect_any_instance_of(WebHookService).to receive(:execute)
hook.execute(data, hook_name)
end
it '#async_execute' do
+ expect(WebHookService).to receive(:new).with(hook, data, hook_name).and_call_original
+
expect_any_instance_of(WebHookService).to receive(:async_execute)
hook.async_execute(data, hook_name)
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index c292e78b32d..482e372543c 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -100,12 +100,18 @@ RSpec.describe WebHook do
hook.execute(data, hook_name)
end
- it 'does not execute non-executable hooks' do
- hook.update!(disabled_until: 1.day.from_now)
+ it 'passes force: false to the web hook service by default' do
+ expect(WebHookService)
+ .to receive(:new).with(hook, data, hook_name, force: false).and_return(double(execute: :done))
- expect(WebHookService).not_to receive(:new)
+ expect(hook.execute(data, hook_name)).to eq :done
+ end
- hook.execute(data, hook_name)
+ it 'passes force: true to the web hook service if required' do
+ expect(WebHookService)
+ .to receive(:new).with(hook, data, hook_name, force: true).and_return(double(execute: :forced))
+
+ expect(hook.execute(data, hook_name, force: true)).to eq :forced
end
it '#async_execute' do
diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb
index a47bc6a5b6d..6b0d8d7ca4a 100644
--- a/spec/models/instance_configuration_spec.rb
+++ b/spec/models/instance_configuration_spec.rb
@@ -206,7 +206,8 @@ RSpec.describe InstanceConfiguration do
group_download_export_limit: 1019,
group_import_limit: 1020,
raw_blob_request_limit: 1021,
- user_email_lookup_limit: 1022
+ user_email_lookup_limit: 1022,
+ users_get_by_id_limit: 1023
)
end
@@ -230,6 +231,7 @@ RSpec.describe InstanceConfiguration do
expect(rate_limits[:group_import]).to eq({ enabled: true, requests_per_period: 1020, period_in_seconds: 60 })
expect(rate_limits[:raw_blob]).to eq({ enabled: true, requests_per_period: 1021, period_in_seconds: 60 })
expect(rate_limits[:user_email_lookup]).to eq({ enabled: true, requests_per_period: 1022, period_in_seconds: 60 })
+ expect(rate_limits[:users_get_by_id]).to eq({ enabled: true, requests_per_period: 1023, period_in_seconds: 600 })
end
end
end
diff --git a/spec/models/instance_metadata_spec.rb b/spec/models/instance_metadata_spec.rb
index e3a9167620b..5fc073c392d 100644
--- a/spec/models/instance_metadata_spec.rb
+++ b/spec/models/instance_metadata_spec.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require_relative '../../app/models/instance_metadata'
+require_relative '../../app/models/instance_metadata/kas'
RSpec.describe InstanceMetadata do
it 'has the correct properties' do
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 7bc670302f1..e822620ab80 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -710,30 +710,21 @@ RSpec.describe Integration do
[
{ name: 'token' },
{ name: 'api_token' },
+ { name: 'token_api' },
+ { name: 'safe_token' },
{ name: 'key' },
{ name: 'api_key' },
{ name: 'password' },
{ name: 'password_field' },
+ { name: 'some_safe_field' },
{ name: 'safe_field' }
- ]
+ ].shuffle
end
end
end
- let(:integration) do
- fake_integration.new(properties: [
- { token: 'token-value' },
- { api_token: 'api_token-value' },
- { key: 'key-value' },
- { api_key: 'api_key-value' },
- { password: 'password-value' },
- { password_field: 'password_field-value' },
- { safe_field: 'safe_field-value' }
- ])
- end
-
it 'filters out sensitive fields' do
- expect(integration.api_field_names).to eq(['safe_field'])
+ expect(fake_integration.new).to have_attributes(api_field_names: match_array(%w[some_safe_field safe_field]))
end
end
diff --git a/spec/models/integrations/datadog_spec.rb b/spec/models/integrations/datadog_spec.rb
index 9856c53a390..cfc44b22a84 100644
--- a/spec/models/integrations/datadog_spec.rb
+++ b/spec/models/integrations/datadog_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Integrations::Datadog do
let(:api_key) { SecureRandom.hex(32) }
let(:dd_env) { 'ci' }
let(:dd_service) { 'awesome-gitlab' }
+ let(:dd_tags) { '' }
let(:expected_hook_url) { default_url + "?dd-api-key=#{api_key}&env=#{dd_env}&service=#{dd_service}" }
@@ -27,7 +28,8 @@ RSpec.describe Integrations::Datadog do
api_url: api_url,
api_key: api_key,
datadog_env: dd_env,
- datadog_service: dd_service
+ datadog_service: dd_service,
+ datadog_tags: dd_tags
)
end
@@ -95,6 +97,20 @@ RSpec.describe Integrations::Datadog do
it { is_expected.not_to allow_value('datadog hq.com').for(:datadog_site) }
it { is_expected.not_to allow_value('example.com').for(:api_url) }
end
+
+ context 'with custom tags' do
+ it { is_expected.to allow_value('').for(:datadog_tags) }
+ it { is_expected.to allow_value('key:value').for(:datadog_tags) }
+ it { is_expected.to allow_value("key:value\nkey2:value2").for(:datadog_tags) }
+ it { is_expected.to allow_value("key:value\nkey2:value with spaces and 123?&$").for(:datadog_tags) }
+ it { is_expected.to allow_value("key:value\n\n\n\nkey2:value2\n").for(:datadog_tags) }
+
+ it { is_expected.not_to allow_value('value').for(:datadog_tags) }
+ it { is_expected.not_to allow_value('key:').for(:datadog_tags) }
+ it { is_expected.not_to allow_value('key: ').for(:datadog_tags) }
+ it { is_expected.not_to allow_value(':value').for(:datadog_tags) }
+ it { is_expected.not_to allow_value("key:value\nINVALID").for(:datadog_tags) }
+ end
end
context 'when integration is not active' do
@@ -134,9 +150,23 @@ RSpec.describe Integrations::Datadog do
context 'without optional params' do
let(:dd_service) { '' }
let(:dd_env) { '' }
+ let(:dd_tags) { '' }
it { is_expected.to eq(default_url + "?dd-api-key=#{api_key}") }
end
+
+ context 'with custom tags' do
+ let(:dd_tags) { "key:value\nkey2:value, 2" }
+ let(:escaped_tags) { CGI.escape("key:value,\"key2:value, 2\"") }
+
+ it { is_expected.to eq(expected_hook_url + "&tags=#{escaped_tags}") }
+
+ context 'and empty lines' do
+ let(:dd_tags) { "key:value\r\n\n\n\nkey2:value, 2\n" }
+
+ it { is_expected.to eq(expected_hook_url + "&tags=#{escaped_tags}") }
+ end
+ end
end
describe '#test' do
diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb
index d67bd8debce..183082bab26 100644
--- a/spec/models/issue_collection_spec.rb
+++ b/spec/models/issue_collection_spec.rb
@@ -50,7 +50,9 @@ RSpec.describe IssueCollection do
end
end
- context 'using a user that is the owner of a project' do
+ # TODO update when we have multiple owners of a project
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350605
+ context 'using a user that is an owner of a project' do
it 'returns the issues of the project' do
expect(collection.updatable_by_user(project.namespace.owner))
.to eq([issue1, issue2])
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index c105f6c3439..5af42cc67ea 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -887,6 +887,8 @@ RSpec.describe Issue do
end
end
+ # TODO update when we have multiple owners of a project
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350605
context 'with an owner' do
before do
project.add_maintainer(user)
@@ -1431,26 +1433,6 @@ RSpec.describe Issue do
end
end
- describe '.with_label_attributes' do
- subject { described_class.with_label_attributes(label_attributes) }
-
- let(:label_attributes) { { title: 'hello world', description: 'hi' } }
-
- it 'gets issues with given label attributes' do
- label = create(:label, **label_attributes)
- labeled_issue = create(:labeled_issue, project: label.project, labels: [label])
-
- expect(subject).to include(labeled_issue)
- end
-
- it 'excludes issues without given label attributes' do
- label = create(:label, title: 'GitLab', description: 'tanuki')
- labeled_issue = create(:labeled_issue, project: label.project, labels: [label])
-
- expect(subject).not_to include(labeled_issue)
- end
- end
-
describe 'banzai_render_context' do
let(:project) { build(:project_empty_repo) }
let(:issue) { build :issue, project: project }
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 19459561edf..6cf73de6cef 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -20,6 +20,8 @@ RSpec.describe Key, :mailer do
it { is_expected.to allow_value(attributes_for(:dsa_key_2048)[:key]).for(:key) }
it { is_expected.to allow_value(attributes_for(:ecdsa_key_256)[:key]).for(:key) }
it { is_expected.to allow_value(attributes_for(:ed25519_key_256)[:key]).for(:key) }
+ it { is_expected.to allow_value(attributes_for(:ecdsa_sk_key_256)[:key]).for(:key) }
+ it { is_expected.to allow_value(attributes_for(:ed25519_sk_key_256)[:key]).for(:key) }
it { is_expected.not_to allow_value('foo-bar').for(:key) }
context 'key format' do
@@ -187,10 +189,12 @@ RSpec.describe Key, :mailer do
forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE
[
- [:rsa_key_2048, 0, true],
- [:dsa_key_2048, 0, true],
- [:ecdsa_key_256, 0, true],
- [:ed25519_key_256, 0, true],
+ [:rsa_key_2048, 0, true],
+ [:dsa_key_2048, 0, true],
+ [:ecdsa_key_256, 0, true],
+ [:ed25519_key_256, 0, true],
+ [:ecdsa_sk_key_256, 0, true],
+ [:ed25519_sk_key_256, 0, true],
[:rsa_key_2048, 1024, true],
[:rsa_key_2048, 2048, true],
@@ -206,10 +210,18 @@ RSpec.describe Key, :mailer do
[:ed25519_key_256, 256, true],
[:ed25519_key_256, 384, false],
- [:rsa_key_2048, forbidden, false],
- [:dsa_key_2048, forbidden, false],
- [:ecdsa_key_256, forbidden, false],
- [:ed25519_key_256, forbidden, false]
+ [:ecdsa_sk_key_256, 256, true],
+ [:ecdsa_sk_key_256, 384, false],
+
+ [:ed25519_sk_key_256, 256, true],
+ [:ed25519_sk_key_256, 384, false],
+
+ [:rsa_key_2048, forbidden, false],
+ [:dsa_key_2048, forbidden, false],
+ [:ecdsa_key_256, forbidden, false],
+ [:ed25519_key_256, forbidden, false],
+ [:ecdsa_sk_key_256, forbidden, false],
+ [:ed25519_sk_key_256, forbidden, false]
]
end
diff --git a/spec/models/label_note_spec.rb b/spec/models/label_note_spec.rb
index ee4822c653d..145ddd44834 100644
--- a/spec/models/label_note_spec.rb
+++ b/spec/models/label_note_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe LabelNote do
+ include Gitlab::Routing.url_helpers
+
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let_it_be(:label) { create(:label, project: project) }
@@ -14,11 +16,27 @@ RSpec.describe LabelNote do
let_it_be(:resource) { create(:issue, project: project) }
it_behaves_like 'label note created from events'
+
+ it 'includes a link to the list of issues filtered by the label' do
+ note = described_class.from_events([
+ create(:resource_label_event, label: label, issue: resource)
+ ])
+
+ expect(note.note_html).to include(project_issues_path(project, label_name: label.title))
+ end
end
context 'when resource is merge request' do
let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'label note created from events'
+
+ it 'includes a link to the list of merge requests filtered by the label' do
+ note = described_class.from_events([
+ create(:resource_label_event, label: label, merge_request: resource)
+ ])
+
+ expect(note.note_html).to include(project_merge_requests_path(project, label_name: label.title))
+ end
end
end
diff --git a/spec/models/loose_foreign_keys/deleted_record_spec.rb b/spec/models/loose_foreign_keys/deleted_record_spec.rb
index 07ffff746a5..23e0ed1f39d 100644
--- a/spec/models/loose_foreign_keys/deleted_record_spec.rb
+++ b/spec/models/loose_foreign_keys/deleted_record_spec.rb
@@ -6,15 +6,15 @@ RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
let_it_be(:table) { 'public.projects' }
describe 'class methods' do
- let_it_be(:deleted_record_1) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 5) }
- let_it_be(:deleted_record_2) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1) }
+ let_it_be(:deleted_record_1) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 5, cleanup_attempts: 2) }
+ let_it_be(:deleted_record_2) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1, cleanup_attempts: 0) }
let_it_be(:deleted_record_3) { described_class.create!(fully_qualified_table_name: 'public.other_table', primary_key_value: 3) }
- let_it_be(:deleted_record_4) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1) } # duplicate
+ let_it_be(:deleted_record_4) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1, cleanup_attempts: 1) } # duplicate
+
+ let(:records) { described_class.load_batch_for_table(table, 10) }
describe '.load_batch_for_table' do
it 'loads records and orders them by creation date' do
- records = described_class.load_batch_for_table(table, 10)
-
expect(records).to eq([deleted_record_1, deleted_record_2, deleted_record_4])
end
@@ -27,13 +27,38 @@ RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
describe '.mark_records_processed' do
it 'updates all records' do
- records = described_class.load_batch_for_table(table, 10)
described_class.mark_records_processed(records)
expect(described_class.status_pending.count).to eq(1)
expect(described_class.status_processed.count).to eq(3)
end
end
+
+ describe '.reschedule' do
+ it 'reschedules all records' do
+ time = Time.zone.parse('2022-01-01').utc
+ update_count = described_class.reschedule(records, time)
+
+ expect(update_count).to eq(records.size)
+
+ records.each(&:reload)
+
+ expect(records).to all(have_attributes(
+ cleanup_attempts: 0,
+ consume_after: time
+ ))
+ end
+ end
+
+ describe '.increment_attempts' do
+ it 'increaments the cleanup_attempts column' do
+ described_class.increment_attempts(records)
+
+ expect(deleted_record_1.reload.cleanup_attempts).to eq(3)
+ expect(deleted_record_2.reload.cleanup_attempts).to eq(1)
+ expect(deleted_record_4.reload.cleanup_attempts).to eq(2)
+ end
+ end
end
describe 'sliding_list partitioning' do
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 1957c58ec81..79491edba94 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -173,6 +173,8 @@ RSpec.describe Member do
let_it_be(:group) { create(:group) }
let_it_be(:blocked_pending_approval_user) { create(:user, :blocked_pending_approval ) }
let_it_be(:blocked_pending_approval_project_member) { create(:project_member, :invited, :developer, project: project, invite_email: blocked_pending_approval_user.email) }
+ let_it_be(:awaiting_group_member) { create(:group_member, :awaiting, group: group) }
+ let_it_be(:awaiting_project_member) { create(:project_member, :awaiting, project: project) }
before_all do
@owner_user = create(:user).tap { |u| group.add_owner(u) }
@@ -471,6 +473,8 @@ RSpec.describe Member do
it { is_expected.to include @blocked_maintainer }
it { is_expected.to include @blocked_developer }
it { is_expected.not_to include @member_with_minimal_access }
+ it { is_expected.not_to include awaiting_group_member }
+ it { is_expected.not_to include awaiting_project_member }
end
describe '.connected_to_user' do
@@ -509,6 +513,8 @@ RSpec.describe Member do
it { is_expected.not_to include @invited_member }
it { is_expected.not_to include @requested_member }
it { is_expected.not_to include @member_with_minimal_access }
+ it { is_expected.not_to include awaiting_group_member }
+ it { is_expected.not_to include awaiting_project_member }
end
describe '.distinct_on_user_with_max_access_level' do
@@ -561,6 +567,21 @@ RSpec.describe Member do
end
end
end
+
+ describe '.active_state' do
+ let_it_be(:active_group_member) { create(:group_member, group: group) }
+ let_it_be(:active_project_member) { create(:project_member, project: project) }
+
+ it 'includes members with an active state' do
+ expect(group.members.active_state).to include active_group_member
+ expect(project.members.active_state).to include active_project_member
+ end
+
+ it 'does not include members with an awaiting state' do
+ expect(group.members.active_state).not_to include awaiting_group_member
+ expect(project.members.active_state).not_to include awaiting_project_member
+ end
+ end
end
describe 'Delegate methods' do
@@ -894,4 +915,15 @@ RSpec.describe Member do
end
end
end
+
+ describe '#set_member_namespace_id' do
+ let(:group) { create(:group) }
+ let(:member) { create(:group_member, group: group) }
+
+ describe 'on create' do
+ it 'sets the member_namespace_id' do
+ expect(member.member_namespace_id).to eq group.id
+ end
+ end
+ end
end
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 031caefbd43..3923f4161cc 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -257,4 +257,15 @@ RSpec.describe ProjectMember do
it_behaves_like 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
end
end
+
+ describe '#set_member_namespace_id' do
+ let(:project) { create(:project) }
+ let(:member) { create(:project_member, project: project) }
+
+ context 'on create' do
+ it 'sets the member_namespace_id' do
+ expect(member.member_namespace_id).to eq project.project_namespace_id
+ end
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 4005a2ec6da..f2f2023a992 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -144,6 +144,20 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '.attention' do
+ let_it_be(:merge_request5) { create(:merge_request, :unique_branches, assignees: [user2])}
+ let_it_be(:merge_request6) { create(:merge_request, :unique_branches, assignees: [user2])}
+
+ before do
+ assignee = merge_request6.find_assignee(user2)
+ assignee.update!(state: :reviewed)
+ end
+
+ it 'returns MRs that have any attention requests' do
+ expect(described_class.attention(user2)).to eq([merge_request2, merge_request5])
+ end
+ end
+
describe '.drafts' do
it 'returns MRs where draft == true' do
expect(described_class.drafts).to eq([merge_request4])
@@ -585,6 +599,21 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(merge_requests).to eq([older_mr, newer_mr])
end
end
+
+ context 'title' do
+ let_it_be(:first_mr) { create(:merge_request, :closed, title: 'One') }
+ let_it_be(:second_mr) { create(:merge_request, :closed, title: 'Two') }
+
+ it 'sorts asc' do
+ merge_requests = described_class.sort_by_attribute(:title_asc)
+ expect(merge_requests).to eq([first_mr, second_mr])
+ end
+
+ it 'sorts desc' do
+ merge_requests = described_class.sort_by_attribute(:title_desc)
+ expect(merge_requests).to eq([second_mr, first_mr])
+ end
+ end
end
describe 'time to merge calculations' do
@@ -1354,17 +1383,17 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { build_stubbed(:merge_request) }
[
- 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:',
'draft:', 'Draft: ', '[Draft]', '[DRAFT] '
- ].each do |wip_prefix|
- it "detects the '#{wip_prefix}' prefix" do
- subject.title = "#{wip_prefix}#{subject.title}"
+ ].each do |draft_prefix|
+ it "detects the '#{draft_prefix}' prefix" do
+ subject.title = "#{draft_prefix}#{subject.title}"
expect(subject.work_in_progress?).to eq true
end
end
[
+ 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:',
"WIP ", "(WIP)",
"draft", "Draft", "Draft -", "draft - ", "Draft ", "draft "
].each do |draft_prefix|
@@ -1375,10 +1404,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- it "detects merge request title just saying 'wip'" do
+ it "doesn't detect merge request title just saying 'wip'" do
subject.title = "wip"
- expect(subject.work_in_progress?).to eq true
+ expect(subject.work_in_progress?).to eq false
end
it "does not detect merge request title just saying 'draft'" do
@@ -1444,29 +1473,30 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe "#wipless_title" do
subject { build_stubbed(:merge_request) }
- [
- 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:',
- 'draft:', 'Draft: ', '[Draft]', '[DRAFT] '
- ].each do |wip_prefix|
- it "removes the '#{wip_prefix}' prefix" do
+ ['draft:', 'Draft: ', '[Draft]', '[DRAFT] '].each do |draft_prefix|
+ it "removes a '#{draft_prefix}' prefix" do
wipless_title = subject.title
- subject.title = "#{wip_prefix}#{subject.title}"
+ subject.title = "#{draft_prefix}#{subject.title}"
expect(subject.wipless_title).to eq wipless_title
end
it "is satisfies the #work_in_progress? method" do
- subject.title = "#{wip_prefix}#{subject.title}"
+ subject.title = "#{draft_prefix}#{subject.title}"
subject.title = subject.wipless_title
expect(subject.work_in_progress?).to eq false
end
end
- it 'removes only WIP prefix from the MR title' do
- subject.title = 'WIP: Implement feature called WIP'
+ [
+ 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:'
+ ].each do |wip_prefix|
+ it "doesn't remove a '#{wip_prefix}' prefix" do
+ subject.title = "#{wip_prefix}#{subject.title}"
- expect(subject.wipless_title).to eq 'Implement feature called WIP'
+ expect(subject.wipless_title).to eq subject.title
+ end
end
it 'removes only draft prefix from the MR title' do
@@ -1522,6 +1552,42 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#permits_force_push?' do
+ let_it_be(:merge_request) { build_stubbed(:merge_request) }
+
+ subject { merge_request.permits_force_push? }
+
+ context 'when source branch is not protected' do
+ before do
+ allow(ProtectedBranch).to receive(:protected?).and_return(false)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when source branch is protected' do
+ before do
+ allow(ProtectedBranch).to receive(:protected?).and_return(true)
+ end
+
+ context 'when force push is not allowed' do
+ before do
+ allow(ProtectedBranch).to receive(:allow_force_push?) { false }
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when force push is allowed' do
+ before do
+ allow(ProtectedBranch).to receive(:allow_force_push?) { true }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+
describe '#can_remove_source_branch?' do
let_it_be(:user) { create(:user) }
let_it_be(:merge_request, reload: true) { create(:merge_request, :simple) }
@@ -3509,7 +3575,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
let!(:job) { create(:ci_build, :with_deployment, :start_review_app, pipeline: pipeline, project: project) }
it 'returns environments' do
- is_expected.to eq(pipeline.environments)
+ is_expected.to eq(pipeline.environments_in_self_and_descendants.to_a)
expect(subject.count).to be(1)
end
@@ -3562,21 +3628,38 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
describe '#update_diff_discussion_positions' do
- let(:discussion) { create(:diff_note_on_merge_request, project: subject.project, noteable: subject).to_discussion }
- let(:commit) { subject.project.commit(sample_commit.id) }
- let(:old_diff_refs) { subject.diff_refs }
+ subject { create(:merge_request, source_project: project) }
- 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!(
- base_commit_sha: commit.parent_id,
- start_commit_sha: commit.parent_id,
- head_commit_sha: commit.sha
- )
+ let(:project) { create(:project, :repository) }
+ let(:create_commit) { project.commit("913c66a37b4a45b9769037c55c2d238bd0942d2e") }
+ let(:modify_commit) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
+ let(:edit_commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") }
+ let(:discussion) { create(:diff_note_on_merge_request, noteable: subject, project: project, position: old_position).to_discussion }
+ let(:path) { "files/ruby/popen.rb" }
+ let(:new_line) { 9 }
+
+ let(:old_diff_refs) do
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: create_commit.parent_id,
+ head_sha: modify_commit.sha
+ )
+ end
- subject.reload_merge_request_diff
- end
+ let(:new_diff_refs) do
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: create_commit.parent_id,
+ head_sha: edit_commit.sha
+ )
+ end
+
+ let(:old_position) do
+ Gitlab::Diff::Position.new(
+ old_path: path,
+ new_path: path,
+ old_line: nil,
+ new_line: new_line,
+ diff_refs: old_diff_refs
+ )
end
it "updates diff discussion positions" do
@@ -3584,36 +3667,67 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject.project,
subject.author,
old_diff_refs: old_diff_refs,
- new_diff_refs: commit.diff_refs,
+ new_diff_refs: new_diff_refs,
paths: discussion.position.paths
).and_call_original
expect_any_instance_of(Discussions::UpdateDiffPositionService).to receive(:execute).with(discussion).and_call_original
- expect_any_instance_of(DiffNote).to receive(:save).once
subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
- new_diff_refs: commit.diff_refs,
+ new_diff_refs: new_diff_refs,
current_user: subject.author)
end
- context 'when resolve_outdated_diff_discussions is set' do
- let(:project) { create(:project, :repository) }
+ it 'does not call the resolve method' do
+ expect(MergeRequests::ResolvedDiscussionNotificationService).not_to receive(:new)
- subject { create(:merge_request, source_project: project) }
+ subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ current_user: subject.author)
+ end
+ context 'when resolve_outdated_diff_discussions is set' do
before do
discussion
subject.project.update!(resolve_outdated_diff_discussions: true)
end
- it 'calls MergeRequests::ResolvedDiscussionNotificationService' do
- expect_any_instance_of(MergeRequests::ResolvedDiscussionNotificationService)
- .to receive(:execute).with(subject)
+ context 'when the active discussion is resolved in the update' do
+ it 'calls MergeRequests::ResolvedDiscussionNotificationService' do
+ expect_any_instance_of(MergeRequests::ResolvedDiscussionNotificationService)
+ .to receive(:execute).with(subject)
- subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
- new_diff_refs: commit.diff_refs,
- current_user: subject.author)
+ subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ current_user: subject.author)
+ end
+ end
+
+ context 'when the active discussion does not have resolved in the update' do
+ let(:new_line) { 16 }
+
+ it 'does not call the resolve method' do
+ expect(MergeRequests::ResolvedDiscussionNotificationService).not_to receive(:new)
+
+ subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ current_user: subject.author)
+ end
+ end
+
+ context 'when the active discussion was already resolved' do
+ before do
+ discussion.resolve!(subject.author)
+ end
+
+ it 'does not call the resolve method' do
+ expect(MergeRequests::ResolvedDiscussionNotificationService).not_to receive(:new)
+
+ subject.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ current_user: subject.author)
+ end
end
end
end
@@ -4965,4 +5079,11 @@ RSpec.describe MergeRequest, factory_default: :keep do
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :merge_request }
end
+
+ context 'loose foreign key on merge_requests.head_pipeline_id' do
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:parent) { create(:ci_pipeline) }
+ let!(:model) { create(:merge_request, head_pipeline: parent) }
+ end
+ end
end
diff --git a/spec/models/namespace/root_storage_statistics_spec.rb b/spec/models/namespace/root_storage_statistics_spec.rb
index 51c191069ec..11852828eab 100644
--- a/spec/models/namespace/root_storage_statistics_spec.rb
+++ b/spec/models/namespace/root_storage_statistics_spec.rb
@@ -28,24 +28,24 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
let(:project1) { create(:project, namespace: namespace) }
let(:project2) { create(:project, namespace: namespace) }
- let!(:stat1) { create(:project_statistics, project: project1, with_data: true, size_multiplier: 100) }
- let!(:stat2) { create(:project_statistics, project: project2, with_data: true, size_multiplier: 200) }
+ let!(:project_stat1) { create(:project_statistics, project: project1, with_data: true, size_multiplier: 100) }
+ let!(:project_stat2) { create(:project_statistics, project: project2, with_data: true, size_multiplier: 200) }
- shared_examples 'data refresh' do
+ shared_examples 'project data refresh' do
it 'aggregates project statistics' do
root_storage_statistics.recalculate!
root_storage_statistics.reload
- total_repository_size = stat1.repository_size + stat2.repository_size
- total_wiki_size = stat1.wiki_size + stat2.wiki_size
- total_lfs_objects_size = stat1.lfs_objects_size + stat2.lfs_objects_size
- total_build_artifacts_size = stat1.build_artifacts_size + stat2.build_artifacts_size
- total_packages_size = stat1.packages_size + stat2.packages_size
- total_storage_size = stat1.storage_size + stat2.storage_size
- total_snippets_size = stat1.snippets_size + stat2.snippets_size
- total_pipeline_artifacts_size = stat1.pipeline_artifacts_size + stat2.pipeline_artifacts_size
- total_uploads_size = stat1.uploads_size + stat2.uploads_size
+ total_repository_size = project_stat1.repository_size + project_stat2.repository_size
+ total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size
+ total_lfs_objects_size = project_stat1.lfs_objects_size + project_stat2.lfs_objects_size
+ total_build_artifacts_size = project_stat1.build_artifacts_size + project_stat2.build_artifacts_size
+ total_packages_size = project_stat1.packages_size + project_stat2.packages_size
+ total_storage_size = project_stat1.storage_size + project_stat2.storage_size
+ total_snippets_size = project_stat1.snippets_size + project_stat2.snippets_size
+ total_pipeline_artifacts_size = project_stat1.pipeline_artifacts_size + project_stat2.pipeline_artifacts_size
+ total_uploads_size = project_stat1.uploads_size + project_stat2.uploads_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
@@ -83,7 +83,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
end
end
- it_behaves_like 'data refresh'
+ it_behaves_like 'project data refresh'
it_behaves_like 'does not include personal snippets'
context 'with subgroups' do
@@ -93,19 +93,81 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
let(:project1) { create(:project, namespace: subgroup1) }
let(:project2) { create(:project, namespace: subgroup2) }
- it_behaves_like 'data refresh'
+ it_behaves_like 'project data refresh'
it_behaves_like 'does not include personal snippets'
end
+ context 'with a group namespace' do
+ let_it_be(:root_group) { create(:group) }
+ let_it_be(:group1) { create(:group, parent: root_group) }
+ let_it_be(:subgroup1) { create(:group, parent: group1) }
+ let_it_be(:group2) { create(:group, parent: root_group) }
+ let_it_be(:root_namespace_stat) { create(:namespace_statistics, namespace: root_group, storage_size: 100, dependency_proxy_size: 100) }
+ let_it_be(:group1_namespace_stat) { create(:namespace_statistics, namespace: group1, storage_size: 200, dependency_proxy_size: 200) }
+ let_it_be(:group2_namespace_stat) { create(:namespace_statistics, namespace: group2, storage_size: 300, dependency_proxy_size: 300) }
+ let_it_be(:subgroup1_namespace_stat) { create(:namespace_statistics, namespace: subgroup1, storage_size: 300, dependency_proxy_size: 100) }
+
+ let(:namespace) { root_group }
+
+ it 'aggregates namespace statistics' do
+ # This group is not a descendant of the root_group so it shouldn't be included in the final stats.
+ other_group = create(:group)
+ create(:namespace_statistics, namespace: other_group, storage_size: 500, dependency_proxy_size: 500)
+
+ root_storage_statistics.recalculate!
+
+ total_repository_size = project_stat1.repository_size + project_stat2.repository_size
+ total_lfs_objects_size = project_stat1.lfs_objects_size + project_stat2.lfs_objects_size
+ total_build_artifacts_size = project_stat1.build_artifacts_size + project_stat2.build_artifacts_size
+ total_packages_size = project_stat1.packages_size + project_stat2.packages_size
+ total_snippets_size = project_stat1.snippets_size + project_stat2.snippets_size
+ total_pipeline_artifacts_size = project_stat1.pipeline_artifacts_size + project_stat2.pipeline_artifacts_size
+ total_uploads_size = project_stat1.uploads_size + project_stat2.uploads_size
+ total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size
+ total_dependency_proxy_size = root_namespace_stat.dependency_proxy_size + group1_namespace_stat.dependency_proxy_size + group2_namespace_stat.dependency_proxy_size + subgroup1_namespace_stat.dependency_proxy_size
+ total_storage_size = project_stat1.storage_size + project_stat2.storage_size + root_namespace_stat.storage_size + group1_namespace_stat.storage_size + group2_namespace_stat.storage_size + subgroup1_namespace_stat.storage_size
+
+ expect(root_storage_statistics.repository_size).to eq(total_repository_size)
+ expect(root_storage_statistics.lfs_objects_size).to eq(total_lfs_objects_size)
+ expect(root_storage_statistics.build_artifacts_size).to eq(total_build_artifacts_size)
+ expect(root_storage_statistics.packages_size).to eq(total_packages_size)
+ expect(root_storage_statistics.snippets_size).to eq(total_snippets_size)
+ expect(root_storage_statistics.pipeline_artifacts_size).to eq(total_pipeline_artifacts_size)
+ expect(root_storage_statistics.uploads_size).to eq(total_uploads_size)
+ expect(root_storage_statistics.dependency_proxy_size).to eq(total_dependency_proxy_size)
+ expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
+ expect(root_storage_statistics.storage_size).to eq(total_storage_size)
+ end
+
+ it 'works when there are no namespace statistics' do
+ NamespaceStatistics.delete_all
+
+ root_storage_statistics.recalculate!
+
+ total_storage_size = project_stat1.storage_size + project_stat2.storage_size
+
+ expect(root_storage_statistics.storage_size).to eq(total_storage_size)
+ end
+ end
+
context 'with a personal namespace' do
let_it_be(:user) { create(:user) }
let(:namespace) { user.namespace }
- it_behaves_like 'data refresh'
+ it_behaves_like 'project data refresh'
+
+ it 'does not aggregate namespace statistics' do
+ create(:namespace_statistics, namespace: user.namespace, storage_size: 200, dependency_proxy_size: 200)
+
+ root_storage_statistics.recalculate!
+
+ expect(root_storage_statistics.storage_size).to eq(project_stat1.storage_size + project_stat2.storage_size)
+ expect(root_storage_statistics.dependency_proxy_size).to eq(0)
+ end
context 'when user has personal snippets' do
- let(:total_project_snippets_size) { stat1.snippets_size + stat2.snippets_size }
+ let(:total_project_snippets_size) { project_stat1.snippets_size + project_stat2.snippets_size }
it 'aggregates personal and project snippets size' do
# This is just a a snippet authored by other user
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 5da0f7a134c..1728d4fc3f3 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe Namespace do
it { is_expected.to have_one :root_storage_statistics }
it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_one :namespace_settings }
+ it { is_expected.to have_one(:namespace_statistics) }
it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress }
@@ -361,10 +362,70 @@ RSpec.describe Namespace do
context 'linear' do
it_behaves_like 'namespace traversal scopes'
end
+
+ shared_examples 'makes recursive queries' do
+ specify do
+ expect { subject }.to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+
+ shared_examples 'does not make recursive queries' do
+ specify do
+ expect { subject }.not_to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+
+ describe '.self_and_descendants' do
+ let_it_be(:namespace) { create(:namespace) }
+
+ subject { described_class.where(id: namespace).self_and_descendants.load }
+
+ it_behaves_like 'does not make recursive queries'
+
+ context 'when feature flag :use_traversal_ids is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it_behaves_like 'makes recursive queries'
+ end
+
+ context 'when feature flag :use_traversal_ids_for_descendants_scopes is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids_for_descendants_scopes: false)
+ end
+
+ it_behaves_like 'makes recursive queries'
+ end
+ end
+
+ describe '.self_and_descendant_ids' do
+ let_it_be(:namespace) { create(:namespace) }
+
+ subject { described_class.where(id: namespace).self_and_descendant_ids.load }
+
+ it_behaves_like 'does not make recursive queries'
+
+ context 'when feature flag :use_traversal_ids is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it_behaves_like 'makes recursive queries'
+ end
+
+ context 'when feature flag :use_traversal_ids_for_descendants_scopes is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids_for_descendants_scopes: false)
+ end
+
+ it_behaves_like 'makes recursive queries'
+ end
+ end
end
context 'traversal_ids on create' do
- context 'default traversal_ids' do
+ shared_examples 'default traversal_ids' do
let(:namespace) { build(:namespace) }
before do
@@ -374,6 +435,18 @@ RSpec.describe Namespace do
it { expect(namespace.traversal_ids).to eq [namespace.id] }
end
+
+ context 'with before_commit callback' do
+ it_behaves_like 'default traversal_ids'
+ end
+
+ context 'with after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
+ end
+
+ it_behaves_like 'default traversal_ids'
+ end
end
describe "after_commit :expire_child_caches" do
@@ -2158,4 +2231,13 @@ RSpec.describe Namespace do
end
end
end
+
+ describe 'storage_enforcement_date' do
+ let_it_be(:namespace) { create(:group) }
+
+ # Date TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ it 'returns false' do
+ expect(namespace.storage_enforcement_date).to be(nil)
+ end
+ end
end
diff --git a/spec/models/namespace_statistics_spec.rb b/spec/models/namespace_statistics_spec.rb
new file mode 100644
index 00000000000..ac747b70a9f
--- /dev/null
+++ b/spec/models/namespace_statistics_spec.rb
@@ -0,0 +1,207 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NamespaceStatistics do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ it { is_expected.to belong_to(:namespace) }
+
+ it { is_expected.to validate_presence_of(:namespace) }
+
+ describe '#refresh!' do
+ let(:namespace) { group }
+ let(:statistics) { create(:namespace_statistics, namespace: namespace) }
+ let(:columns) { [] }
+
+ subject(:refresh!) { statistics.refresh!(only: columns) }
+
+ context 'when database is read_only' do
+ it 'does not save the object' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+
+ expect(statistics).not_to receive(:save!)
+
+ refresh!
+ end
+ end
+
+ context 'when namespace belong to a user' do
+ let(:namespace) { user.namespace }
+
+ it 'does not save the object' do
+ expect(statistics).not_to receive(:save!)
+
+ refresh!
+ end
+ end
+
+ shared_examples 'creates the namespace statistics' do
+ specify do
+ expect(statistics).to receive(:save!)
+
+ refresh!
+ end
+ end
+
+ context 'when invalid option is passed' do
+ let(:columns) { [:foo] }
+
+ it 'does not update any column' do
+ create(:dependency_proxy_manifest, group: namespace, size: 50)
+
+ expect(statistics).not_to receive(:update_dependency_proxy_size)
+ expect { refresh! }.not_to change { statistics.reload.storage_size }
+ end
+
+ it_behaves_like 'creates the namespace statistics'
+ end
+
+ context 'when no option is passed' do
+ it 'updates the dependency proxy size' do
+ expect(statistics).to receive(:update_dependency_proxy_size)
+
+ refresh!
+ end
+
+ it_behaves_like 'creates the namespace statistics'
+ end
+
+ context 'when dependency_proxy_size option is passed' do
+ let(:columns) { [:dependency_proxy_size] }
+
+ it 'updates the dependency proxy size' do
+ expect(statistics).to receive(:update_dependency_proxy_size)
+
+ refresh!
+ end
+
+ it_behaves_like 'creates the namespace statistics'
+ end
+ end
+
+ describe '#update_storage_size' do
+ let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) }
+
+ it 'sets storage_size to the dependency_proxy_size' do
+ statistics.dependency_proxy_size = 3
+
+ statistics.update_storage_size
+
+ expect(statistics.storage_size).to eq 3
+ end
+ end
+
+ describe '#update_dependency_proxy_size' do
+ let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) }
+ let_it_be(:dependency_proxy_manifest) { create(:dependency_proxy_manifest, group: group, size: 50) }
+ let_it_be(:dependency_proxy_blob) { create(:dependency_proxy_blob, group: group, size: 50) }
+
+ subject(:update_dependency_proxy_size) { statistics.update_dependency_proxy_size }
+
+ it 'updates the dependency proxy size' do
+ update_dependency_proxy_size
+
+ expect(statistics.dependency_proxy_size).to eq 100
+ end
+
+ context 'when namespace does not belong to a group' do
+ let(:statistics) { create(:namespace_statistics, namespace: user.namespace) }
+
+ it 'does not update the dependency proxy size' do
+ update_dependency_proxy_size
+
+ expect(statistics.dependency_proxy_size).to be_zero
+ end
+ end
+ end
+
+ context 'before saving statistics' do
+ let(:statistics) { create(:namespace_statistics, namespace: group, dependency_proxy_size: 10) }
+
+ it 'updates storage size' do
+ expect(statistics).to receive(:update_storage_size).and_call_original
+
+ statistics.save!
+
+ expect(statistics.storage_size).to eq 10
+ end
+ end
+
+ context 'after saving statistics', :aggregate_failures do
+ let(:statistics) { create(:namespace_statistics, namespace: namespace) }
+ let(:namespace) { group }
+
+ context 'when storage_size is not updated' do
+ it 'does not enqueue the job to update root storage statistics' do
+ expect(statistics).not_to receive(:update_root_storage_statistics)
+ expect(Namespaces::ScheduleAggregationWorker).not_to receive(:perform_async)
+
+ statistics.save!
+ end
+ end
+
+ context 'when storage_size is updated' do
+ before do
+ # we have to update this value instead of `storage_size` because the before_save
+ # hook we have. If we don't do it, storage_size will be set to the dependency_proxy_size value
+ # which is 0.
+ statistics.dependency_proxy_size = 10
+ end
+
+ it 'enqueues the job to update root storage statistics' do
+ expect(statistics).to receive(:update_root_storage_statistics).and_call_original
+ expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group.id)
+
+ statistics.save!
+ end
+
+ context 'when namespace does not belong to a group' do
+ let(:namespace) { user.namespace }
+
+ it 'does not enqueue the job to update root storage statistics' do
+ expect(statistics).to receive(:update_root_storage_statistics).and_call_original
+ expect(Namespaces::ScheduleAggregationWorker).not_to receive(:perform_async)
+
+ statistics.save!
+ end
+ end
+ end
+
+ context 'when other columns are updated' do
+ it 'does not enqueue the job to update root storage statistics' do
+ columns_to_update = NamespaceStatistics.columns_hash.reject { |k, _| %w(id namespace_id).include?(k) || k.include?('_size') }.keys
+ columns_to_update.each { |c| statistics[c] = 10 }
+
+ expect(statistics).not_to receive(:update_root_storage_statistics)
+ expect(Namespaces::ScheduleAggregationWorker).not_to receive(:perform_async)
+
+ statistics.save!
+ end
+ end
+ end
+
+ context 'after destroy statistics', :aggregate_failures do
+ let(:statistics) { create(:namespace_statistics, namespace: namespace) }
+ let(:namespace) { group }
+
+ it 'enqueues the job to update root storage statistics' do
+ expect(statistics).to receive(:update_root_storage_statistics).and_call_original
+ expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group.id)
+
+ statistics.destroy!
+ end
+
+ context 'when namespace belongs to a group' do
+ let(:namespace) { user.namespace }
+
+ it 'does not enqueue the job to update root storage statistics' do
+ expect(statistics).to receive(:update_root_storage_statistics).and_call_original
+ expect(Namespaces::ScheduleAggregationWorker).not_to receive(:perform_async)
+
+ statistics.destroy!
+ end
+ end
+ end
+end
diff --git a/spec/models/namespaces/user_namespace_spec.rb b/spec/models/namespaces/user_namespace_spec.rb
index 7c00a597756..fb9e7571666 100644
--- a/spec/models/namespaces/user_namespace_spec.rb
+++ b/spec/models/namespaces/user_namespace_spec.rb
@@ -9,4 +9,13 @@ RSpec.describe Namespaces::UserNamespace, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:owner) }
end
+
+ describe '#owners' do
+ let(:owner) { build(:user) }
+ let(:namespace) { build(:namespace, owner: owner) }
+
+ specify do
+ expect(namespace.owners).to match_array([owner])
+ end
+ end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 9d9cca0678a..34ce0031bd2 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -445,7 +445,7 @@ RSpec.describe Note do
end
end
- describe "#system_note_with_references_visible_for?" do
+ describe "#system_note_visible_for?" do
let(:project) { create(:project, :public) }
let(:user) { create(:user) }
let(:guest) { create(:project_member, :guest, project: project, user: create(:user)).user }
@@ -469,22 +469,25 @@ RSpec.describe Note do
end
it 'returns visible but not readable for non-member user' do
- expect(note.system_note_with_references_visible_for?(non_member)).to be_truthy
+ expect(note.system_note_visible_for?(non_member)).to be_truthy
expect(note.readable_by?(non_member)).to be_falsy
end
it 'returns visible but not readable for a nil user' do
- expect(note.system_note_with_references_visible_for?(nil)).to be_truthy
+ expect(note.system_note_visible_for?(nil)).to be_truthy
expect(note.readable_by?(nil)).to be_falsy
end
end
end
describe "#system_note_viewable_by?(user)" do
- let_it_be(:note) { create(:note) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:note) { create(:note, project: project) }
let_it_be(:user) { create(:user) }
- let!(:metadata) { create(:system_note_metadata, note: note, action: "branch") }
+ let(:action) { "commit" }
+ let!(:metadata) { create(:system_note_metadata, note: note, action: action) }
context "when system_note_metadata is not present" do
it "returns true" do
@@ -494,32 +497,50 @@ RSpec.describe Note do
end
end
- context "system_note_metadata isn't of type 'branch'" do
- before do
- metadata.action = "not_a_branch"
- end
-
+ context "system_note_metadata isn't of type 'branch' or 'contact'" do
it "returns true" do
expect(note.send(:system_note_viewable_by?, user)).to be_truthy
end
end
- context "user doesn't have :download_code ability" do
- it "returns false" do
- expect(note.send(:system_note_viewable_by?, user)).to be_falsey
+ context "system_note_metadata is of type 'branch'" do
+ let(:action) { "branch" }
+
+ context "user doesn't have :download_code ability" do
+ it "returns false" do
+ expect(note.send(:system_note_viewable_by?, user)).to be_falsey
+ end
+ end
+
+ context "user has the :download_code ability" do
+ it "returns true" do
+ expect(Ability).to receive(:allowed?).with(user, :download_code, note.project).and_return(true)
+
+ expect(note.send(:system_note_viewable_by?, user)).to be_truthy
+ end
end
end
- context "user has the :download_code ability" do
- it "returns true" do
- expect(Ability).to receive(:allowed?).with(user, :download_code, note.project).and_return(true)
+ context "system_note_metadata is of type 'contact'" do
+ let(:action) { "contact" }
- expect(note.send(:system_note_viewable_by?, user)).to be_truthy
+ context "user doesn't have :read_crm_contact ability" do
+ it "returns false" do
+ expect(note.send(:system_note_viewable_by?, user)).to be_falsey
+ end
+ end
+
+ context "user has the :read_crm_contact ability" do
+ it "returns true" do
+ expect(Ability).to receive(:allowed?).with(user, :read_crm_contact, note.project.group).and_return(true)
+
+ expect(note.send(:system_note_viewable_by?, user)).to be_truthy
+ end
end
end
end
- describe "system_note_with_references_visible_for?" do
+ describe "system_note_visible_for?" do
let_it_be(:private_user) { create(:user) }
let_it_be(:private_project) { create(:project, namespace: private_user.namespace) { |p| p.add_maintainer(private_user) } }
let_it_be(:private_issue) { create(:issue, project: private_project) }
@@ -529,11 +550,11 @@ RSpec.describe Note do
shared_examples "checks references" do
it "returns false" do
- expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
+ expect(note.system_note_visible_for?(ext_issue.author)).to be_falsy
end
it "returns true" do
- expect(note.system_note_with_references_visible_for?(private_user)).to be_truthy
+ expect(note.system_note_visible_for?(private_user)).to be_truthy
end
it "returns true if user visible reference count set" do
@@ -541,7 +562,7 @@ RSpec.describe Note do
note.total_reference_count = 1
expect(note).not_to receive(:reference_mentionables)
- expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_truthy
+ expect(note.system_note_visible_for?(ext_issue.author)).to be_truthy
end
it "returns false if user visible reference count set but does not match total reference count" do
@@ -549,14 +570,14 @@ RSpec.describe Note do
note.total_reference_count = 2
expect(note).not_to receive(:reference_mentionables)
- expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
+ expect(note.system_note_visible_for?(ext_issue.author)).to be_falsy
end
it "returns false if ref count is 0" do
note.user_visible_reference_count = 0
expect(note).not_to receive(:reference_mentionables)
- expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
+ expect(note.system_note_visible_for?(ext_issue.author)).to be_falsy
end
end
@@ -617,16 +638,16 @@ RSpec.describe Note do
let(:note) do
create :note,
noteable: ext_issue, project: ext_proj,
- note: "mentioned in #{ext_proj.owner.to_reference}",
+ note: "mentioned in #{ext_proj.first_owner.to_reference}",
system: true
end
it "returns true for other users" do
- expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_truthy
+ expect(note.system_note_visible_for?(ext_issue.author)).to be_truthy
end
it "returns true for anonymous users" do
- expect(note.system_note_with_references_visible_for?(nil)).to be_truthy
+ expect(note.system_note_visible_for?(nil)).to be_truthy
end
end
end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index a86caa074f1..fd453d8e5a9 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -148,16 +148,6 @@ RSpec.describe Packages::PackageFile, type: :model do
it 'does not return them' do
expect(described_class.for_helm_with_channel(project, channel)).to contain_exactly(helm_file2)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- expect(described_class.for_helm_with_channel(project, channel)).to contain_exactly(helm_file2, package_file_pending_destruction)
- end
- end
end
end
@@ -232,16 +222,6 @@ RSpec.describe Packages::PackageFile, type: :model do
it 'does not return them' do
expect(subject).to contain_exactly(helm_package_file2)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- expect(subject).to contain_exactly(package_file_pending_destruction)
- end
- end
end
end
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 0735bf25690..2ebc9864d9b 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -36,9 +36,12 @@ RSpec.describe PagesDomain do
'123.456.789' => true,
'0x12345.com' => true,
'0123123' => true,
- '_foo.com' => false,
+ 'a-reserved.com' => true,
+ 'a.b-reserved.com' => true,
'reserved.com' => false,
+ '_foo.com' => false,
'a.reserved.com' => false,
+ 'a.b.reserved.com' => false,
nil => false
}.each do |value, validity|
context "domain #{value.inspect} validity" do
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 8cd831d2f85..88206fbf48c 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -22,6 +22,16 @@ RSpec.describe PersonalAccessToken do
end
describe 'scopes' do
+ describe '.project_access_tokens' do
+ let_it_be(:user) { create(:user, :project_bot) }
+ let_it_be(:project_member) { create(:project_member, user: user) }
+ let_it_be(:project_access_token) { create(:personal_access_token, user: user) }
+
+ subject { described_class.project_access_token }
+
+ it { is_expected.to contain_exactly(project_access_token) }
+ end
+
describe '.for_user' do
it 'returns personal access tokens of specified user only' do
user_1 = create(:user)
diff --git a/spec/models/preloaders/users_max_access_level_in_projects_preloader_spec.rb b/spec/models/preloaders/users_max_access_level_in_projects_preloader_spec.rb
new file mode 100644
index 00000000000..7ecb6bb9861
--- /dev/null
+++ b/spec/models/preloaders/users_max_access_level_in_projects_preloader_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+RSpec.describe Preloaders::UsersMaxAccessLevelInProjectsPreloader do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+
+ let_it_be(:project_1) { create(:project) }
+ let_it_be(:project_2) { create(:project) }
+ let_it_be(:project_3) { create(:project) }
+
+ let(:projects) { [project_1, project_2, project_3] }
+ let(:users) { [user1, user2] }
+
+ before do
+ project_1.add_developer(user1)
+ project_1.add_developer(user2)
+
+ project_2.add_developer(user1)
+ project_2.add_developer(user2)
+
+ project_3.add_developer(user1)
+ project_3.add_developer(user2)
+ end
+
+ context 'preload maximum access level to avoid querying project_authorizations', :request_store do
+ it 'avoids N+1 queries', :request_store do
+ Preloaders::UsersMaxAccessLevelInProjectsPreloader.new(projects: projects, users: users).execute
+
+ expect(count_queries).to eq(0)
+ end
+
+ it 'runs N queries without preloading' do
+ query_count_without_preload = count_queries
+
+ Preloaders::UsersMaxAccessLevelInProjectsPreloader.new(projects: projects, users: users).execute
+ count_queries_with_preload = count_queries
+
+ expect(count_queries_with_preload).to be < query_count_without_preload
+ end
+ end
+
+ def count_queries
+ ActiveRecord::QueryRecorder.new do
+ projects.each do |project|
+ user1.can?(:read_project, project)
+ user2.can?(:read_project, project)
+ end
+ end.count
+ end
+end
diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb
index 843beb4ce23..4ad2446f8d0 100644
--- a/spec/models/project_import_state_spec.rb
+++ b/spec/models/project_import_state_spec.rb
@@ -79,6 +79,29 @@ RSpec.describe ProjectImportState, type: :model do
expect(import_state.last_error).to eq(error_message)
end
+
+ it 'removes project import data' do
+ import_data = ProjectImportData.new(data: { 'test' => 'some data' })
+ project = create(:project, import_data: import_data)
+ import_state = create(:import_state, :started, project: project)
+
+ expect do
+ import_state.mark_as_failed(error_message)
+ end.to change { project.reload.import_data }.from(import_data).to(nil)
+ end
+
+ context 'when remove_import_data_on_failure feature flag is disabled' do
+ it 'removes project import data' do
+ stub_feature_flags(remove_import_data_on_failure: false)
+
+ project = create(:project, import_data: ProjectImportData.new(data: { 'test' => 'some data' }))
+ import_state = create(:import_state, :started, project: project)
+
+ expect do
+ import_state.mark_as_failed(error_message)
+ end.not_to change { project.reload.import_data }
+ end
+ end
end
describe '#human_status_name' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 30114d36a06..c487c87db1c 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -236,27 +236,42 @@ RSpec.describe Project, factory_default: :keep do
end
context 'with project namespaces' do
- it 'automatically creates a project namespace' do
- project = build(:project, path: 'hopefully-valid-path1')
- project.save!
+ shared_examples 'creates project namespace' do
+ it 'automatically creates a project namespace' do
+ project = build(:project, path: 'hopefully-valid-path1')
+ project.save!
- expect(project).to be_persisted
- expect(project.project_namespace).to be_persisted
- expect(project.project_namespace).to be_in_sync_with_project(project)
- end
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_persisted
+ expect(project.project_namespace).to be_in_sync_with_project(project)
+ expect(project.reload.project_namespace.traversal_ids).to eq([project.namespace.traversal_ids, project.project_namespace.id].flatten.compact)
+ end
- context 'with FF disabled' do
- before do
- stub_feature_flags(create_project_namespace_on_project_create: false)
+ context 'with FF disabled' do
+ before do
+ stub_feature_flags(create_project_namespace_on_project_create: false)
+ end
+
+ it 'does not create a project namespace' do
+ project = build(:project, path: 'hopefully-valid-path2')
+ project.save!
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_nil
+ end
end
+ end
- it 'does not create a project namespace' do
- project = build(:project, path: 'hopefully-valid-path2')
- project.save!
+ context 'sync-ing traversal_ids in before_commit callback' do
+ it_behaves_like 'creates project namespace'
+ end
- expect(project).to be_persisted
- expect(project.project_namespace).to be_nil
+ context 'sync-ing traversal_ids in after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
end
+
+ it_behaves_like 'creates project namespace'
end
end
end
@@ -870,7 +885,88 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#merge_commit_template_or_default' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns default merge commit template' do
+ expect(project.merge_commit_template_or_default).to eq(Project::DEFAULT_MERGE_COMMIT_TEMPLATE)
+ end
+
+ context 'when merge commit template is set and not nil' do
+ before do
+ project.merge_commit_template = '%{description}'
+ end
+
+ it 'returns current value' do
+ expect(project.merge_commit_template_or_default).to eq('%{description}')
+ end
+ end
+ end
+
+ describe '#merge_commit_template_or_default=' do
+ let_it_be(:project) { create(:project) }
+
+ it 'sets template to nil when set to default value' do
+ project.merge_commit_template_or_default = Project::DEFAULT_MERGE_COMMIT_TEMPLATE
+ expect(project.merge_commit_template).to be_nil
+ end
+
+ it 'sets template to nil when set to default value but with CRLF line endings' do
+ project.merge_commit_template_or_default = "Merge branch '%{source_branch}' into '%{target_branch}'\r\n\r\n%{title}\r\n\r\n%{issues}\r\n\r\nSee merge request %{reference}"
+ expect(project.merge_commit_template).to be_nil
+ end
+
+ it 'allows changing template' do
+ project.merge_commit_template_or_default = '%{description}'
+ expect(project.merge_commit_template).to eq('%{description}')
+ end
+
+ it 'allows setting template to nil' do
+ project.merge_commit_template_or_default = nil
+ expect(project.merge_commit_template).to be_nil
+ end
+ end
+
+ describe '#squash_commit_template_or_default' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns default squash commit template' do
+ expect(project.squash_commit_template_or_default).to eq(Project::DEFAULT_SQUASH_COMMIT_TEMPLATE)
+ end
+
+ context 'when squash commit template is set and not nil' do
+ before do
+ project.squash_commit_template = '%{description}'
+ end
+
+ it 'returns current value' do
+ expect(project.squash_commit_template_or_default).to eq('%{description}')
+ end
+ end
+ end
+
+ describe '#squash_commit_template_or_default=' do
+ let_it_be(:project) { create(:project) }
+
+ it 'sets template to nil when set to default value' do
+ project.squash_commit_template_or_default = Project::DEFAULT_SQUASH_COMMIT_TEMPLATE
+ expect(project.squash_commit_template).to be_nil
+ end
+
+ it 'allows changing template' do
+ project.squash_commit_template_or_default = '%{description}'
+ expect(project.squash_commit_template).to eq('%{description}')
+ end
+
+ it 'allows setting template to nil' do
+ project.squash_commit_template_or_default = nil
+ expect(project.squash_commit_template).to be_nil
+ end
+ end
+
describe 'reference methods' do
+ # TODO update when we have multiple owners of a project
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350605
let_it_be(:owner) { create(:user, name: 'Gitlab') }
let_it_be(:namespace) { create(:namespace, name: 'Sample namespace', path: 'sample-namespace', owner: owner) }
let_it_be(:project) { create(:project, name: 'Sample project', path: 'sample-project', namespace: namespace) }
@@ -2874,7 +2970,7 @@ RSpec.describe Project, factory_default: :keep do
end
before do
- project.repository.rm_branch(project.owner, branch.name)
+ project.repository.rm_branch(project.first_owner, branch.name)
end
subject { project.latest_pipeline(branch.name) }
@@ -3869,45 +3965,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#ci_instance_variables_for' do
- let(:project) { build_stubbed(:project) }
-
- let!(:instance_variable) do
- create(:ci_instance_variable, value: 'secret')
- end
-
- let!(:protected_instance_variable) do
- create(:ci_instance_variable, :protected, value: 'protected')
- end
-
- subject { project.ci_instance_variables_for(ref: 'ref') }
-
- before do
- stub_application_setting(
- default_branch_protection: Gitlab::Access::PROTECTION_NONE)
- end
-
- context 'when the ref is not protected' do
- before do
- allow(project).to receive(:protected_for?).with('ref').and_return(false)
- end
-
- it 'contains only the CI variables' do
- is_expected.to contain_exactly(instance_variable)
- end
- end
-
- context 'when the ref is protected' do
- before do
- allow(project).to receive(:protected_for?).with('ref').and_return(true)
- end
-
- it 'contains all the variables' do
- is_expected.to contain_exactly(instance_variable, protected_instance_variable)
- end
- end
- end
-
describe '#any_lfs_file_locks?', :request_store do
let_it_be(:project) { create(:project) }
@@ -6238,6 +6295,21 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '.for_group_and_its_ancestor_groups' do
+ it 'returns projects for group and its ancestors' do
+ group_1 = create(:group)
+ project_1 = create(:project, namespace: group_1)
+ group_2 = create(:group, parent: group_1)
+ project_2 = create(:project, namespace: group_2)
+ group_3 = create(:group, parent: group_2)
+ project_3 = create(:project, namespace: group_2)
+ group_4 = create(:group, parent: group_3)
+ create(:project, namespace: group_4)
+
+ expect(described_class.for_group_and_its_ancestor_groups(group_3)).to match_array([project_1, project_2, project_3])
+ end
+ end
+
describe '.deployments' do
subject { project.deployments }
@@ -7116,6 +7188,29 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to be true }
end
+ describe '#related_group_ids' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:sub_group) { create(:group, parent: group) }
+
+ context 'when associated with a namespace' do
+ let(:project) { create(:project, namespace: create(:namespace)) }
+ let!(:linked_group) { create(:project_group_link, project: project).group }
+
+ it 'only includes linked groups' do
+ expect(project.related_group_ids).to contain_exactly(linked_group.id)
+ end
+ end
+
+ context 'when associated with a group' do
+ let(:project) { create(:project, group: sub_group) }
+ let!(:linked_group) { create(:project_group_link, project: project).group }
+
+ it 'includes self, ancestors and linked groups' do
+ expect(project.related_group_ids).to contain_exactly(group.id, sub_group.id, linked_group.id)
+ end
+ end
+ end
+
describe '#package_already_taken?' do
let_it_be(:namespace) { create(:namespace, path: 'test') }
let_it_be(:project) { create(:project, :public, namespace: namespace) }
@@ -7410,6 +7505,67 @@ RSpec.describe Project, factory_default: :keep do
expect(project.reload.topics.map(&:name)).to eq(%w[topic1 topic2 topic3])
end
end
+
+ context 'public topics counter' do
+ let_it_be(:topic_1) { create(:topic, name: 't1') }
+ let_it_be(:topic_2) { create(:topic, name: 't2') }
+ let_it_be(:topic_3) { create(:topic, name: 't3') }
+
+ let(:private) { Gitlab::VisibilityLevel::PRIVATE }
+ let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
+ let(:public) { Gitlab::VisibilityLevel::PUBLIC }
+
+ subject do
+ project_updates = {
+ visibility_level: new_visibility,
+ topic_list: new_topic_list
+ }.compact
+
+ project.update!(project_updates)
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ where(:initial_visibility, :new_visibility, :new_topic_list, :expected_count_changes) do
+ ref(:private) | nil | 't2, t3' | [0, 0, 0]
+ ref(:internal) | nil | 't2, t3' | [-1, 0, 1]
+ ref(:public) | nil | 't2, t3' | [-1, 0, 1]
+ ref(:private) | ref(:public) | nil | [1, 1, 0]
+ ref(:private) | ref(:internal) | nil | [1, 1, 0]
+ ref(:private) | ref(:private) | nil | [0, 0, 0]
+ ref(:internal) | ref(:public) | nil | [0, 0, 0]
+ ref(:internal) | ref(:internal) | nil | [0, 0, 0]
+ ref(:internal) | ref(:private) | nil | [-1, -1, 0]
+ ref(:public) | ref(:public) | nil | [0, 0, 0]
+ ref(:public) | ref(:internal) | nil | [0, 0, 0]
+ ref(:public) | ref(:private) | nil | [-1, -1, 0]
+ ref(:private) | ref(:public) | 't2, t3' | [0, 1, 1]
+ ref(:private) | ref(:internal) | 't2, t3' | [0, 1, 1]
+ ref(:private) | ref(:private) | 't2, t3' | [0, 0, 0]
+ ref(:internal) | ref(:public) | 't2, t3' | [-1, 0, 1]
+ ref(:internal) | ref(:internal) | 't2, t3' | [-1, 0, 1]
+ ref(:internal) | ref(:private) | 't2, t3' | [-1, -1, 0]
+ ref(:public) | ref(:public) | 't2, t3' | [-1, 0, 1]
+ ref(:public) | ref(:internal) | 't2, t3' | [-1, 0, 1]
+ ref(:public) | ref(:private) | 't2, t3' | [-1, -1, 0]
+ end
+ # rubocop:enable Lint/BinaryOperatorWithIdenticalOperands
+
+ with_them do
+ it 'increments or decrements counters of topics' do
+ project.reload.update!(
+ visibility_level: initial_visibility,
+ topic_list: [topic_1.name, topic_2.name]
+ )
+
+ expect { subject }
+ .to change { topic_1.reload.non_private_projects_count }.by(expected_count_changes[0])
+ .and change { topic_2.reload.non_private_projects_count }.by(expected_count_changes[1])
+ .and change { topic_3.reload.non_private_projects_count }.by(expected_count_changes[2])
+ end
+ end
+ end
end
shared_examples 'all_runners' do
@@ -7801,7 +7957,8 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#context_commits_enabled?' do
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
subject(:result) { project.context_commits_enabled? }
@@ -7821,19 +7978,19 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to be_falsey }
end
- context 'when context_commits feature flag is enabled on this project' do
+ context 'when context_commits feature flag is enabled on project group' do
before do
- stub_feature_flags(context_commits: project)
+ stub_feature_flags(context_commits: group)
end
it { is_expected.to be_truthy }
end
- context 'when context_commits feature flag is enabled on another project' do
- let(:another_project) { create(:project) }
+ context 'when context_commits feature flag is enabled on another group' do
+ let(:another_group) { create(:group) }
before do
- stub_feature_flags(context_commits: another_project)
+ stub_feature_flags(context_commits: another_group)
end
it { is_expected.to be_falsey }
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index c0bad96effc..bfdebbc33df 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -77,15 +77,43 @@ RSpec.describe ProjectTeam do
end
end
+ describe 'owner methods' do
+ context 'personal project' do
+ let(:project) { create(:project) }
+ let(:owner) { project.first_owner }
+
+ specify { expect(project.team.owners).to contain_exactly(owner) }
+ specify { expect(project.team.owner?(owner)).to be_truthy }
+ end
+
+ context 'group project' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+ let(:user1) { create(:user) }
+ let(:user2) { create(:user) }
+
+ before do
+ group.add_owner(user1)
+ group.add_owner(user2)
+ end
+
+ specify { expect(project.team.owners).to contain_exactly(user1, user2) }
+ specify { expect(project.team.owner?(user1)).to be_truthy }
+ specify { expect(project.team.owner?(user2)).to be_truthy }
+ end
+ end
+
describe '#fetch_members' do
context 'personal project' do
let(:project) { create(:project) }
it 'returns project members' do
+ # TODO this can be updated when we have multiple project owners
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/350605
user = create(:user)
project.add_guest(user)
- expect(project.team.members).to contain_exactly(user, project.owner)
+ expect(project.team.members).to contain_exactly(user, project.first_owner)
end
it 'returns project members of a specified level' do
@@ -103,7 +131,7 @@ RSpec.describe ProjectTeam do
group_access: Gitlab::Access::GUEST)
expect(project.team.members)
- .to contain_exactly(group_member.user, project.owner)
+ .to contain_exactly(group_member.user, project.first_owner)
end
it 'returns invited members of a group of a specified level' do
diff --git a/spec/models/state_note_spec.rb b/spec/models/state_note_spec.rb
index bd07af7ceca..e91150695b0 100644
--- a/spec/models/state_note_spec.rb
+++ b/spec/models/state_note_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe StateNote do
it 'contains the expected values' do
expect(subject.author).to eq(author)
expect(subject.created_at).to eq(event.created_at)
- expect(subject.note).to eq('resolved the corresponding error and closed the issue.')
+ expect(subject.note).to eq('resolved the corresponding error and closed the issue')
end
end
@@ -65,7 +65,7 @@ RSpec.describe StateNote do
it 'contains the expected values' do
expect(subject.author).to eq(author)
expect(subject.created_at).to eq(event.created_at)
- expect(subject.note).to eq('automatically closed this issue because the alert resolved.')
+ expect(subject.note).to eq('automatically closed this incident because the alert resolved')
end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index c2535fd3698..e4f25c79e53 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2612,6 +2612,12 @@ RSpec.describe User do
it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
expect(described_class.search(user3.name.upcase)).to eq([user3])
end
+
+ context 'when use_minimum_char_limit is false' do
+ it 'returns users with a partially matching name' do
+ expect(described_class.search('u', use_minimum_char_limit: false)).to eq([user3, user, user2])
+ end
+ end
end
describe 'email matching' do
@@ -2671,204 +2677,20 @@ RSpec.describe User do
it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
expect(described_class.search(user3.username.upcase)).to eq([user3])
end
- end
-
- it 'returns no matches for an empty string' do
- expect(described_class.search('')).to be_empty
- end
-
- it 'returns no matches for nil' do
- expect(described_class.search(nil)).to be_empty
- end
- end
-
- describe '.search_without_secondary_emails' do
- let_it_be(:user) { create(:user, name: 'John Doe', username: 'john.doe', email: 'someone.1@example.com' ) }
- let_it_be(:another_user) { create(:user, name: 'Albert Smith', username: 'albert.smith', email: 'another.2@example.com' ) }
- let_it_be(:email) { create(:email, user: another_user, email: 'alias@example.com') }
-
- it 'returns users with a matching name' do
- expect(described_class.search_without_secondary_emails(user.name)).to eq([user])
- end
-
- it 'returns users with a partially matching name' do
- expect(described_class.search_without_secondary_emails(user.name[0..2])).to eq([user])
- end
-
- it 'returns users with a matching name regardless of the casing' do
- expect(described_class.search_without_secondary_emails(user.name.upcase)).to eq([user])
- end
-
- it 'returns users with a matching email' do
- expect(described_class.search_without_secondary_emails(user.email)).to eq([user])
- end
-
- it 'does not return users with a partially matching email' do
- expect(described_class.search_without_secondary_emails(user.email[1...-1])).to be_empty
- end
-
- it 'returns users with a matching email regardless of the casing' do
- expect(described_class.search_without_secondary_emails(user.email.upcase)).to eq([user])
- end
-
- it 'returns users with a matching username' do
- expect(described_class.search_without_secondary_emails(user.username)).to eq([user])
- end
-
- it 'returns users with a partially matching username' do
- expect(described_class.search_without_secondary_emails(user.username[0..2])).to eq([user])
- end
-
- it 'returns users with a matching username regardless of the casing' do
- expect(described_class.search_without_secondary_emails(user.username.upcase)).to eq([user])
- end
-
- it 'does not return users with a matching whole secondary email' do
- expect(described_class.search_without_secondary_emails(email.email)).not_to include(email.user)
- end
- it 'does not return users with a matching part of secondary email' do
- expect(described_class.search_without_secondary_emails(email.email[1...-1])).to be_empty
- end
-
- it 'returns no matches for an empty string' do
- expect(described_class.search_without_secondary_emails('')).to be_empty
- end
-
- it 'returns no matches for nil' do
- expect(described_class.search_without_secondary_emails(nil)).to be_empty
- end
- end
-
- describe '.search_with_public_emails' do
- let_it_be(:user) { create(:user, name: 'John Doe', username: 'john.doe', email: 'someone.1@example.com' ) }
- let_it_be(:another_user) { create(:user, name: 'Albert Smith', username: 'albert.smith', email: 'another.2@example.com' ) }
- let_it_be(:public_email) do
- create(:email, :confirmed, user: another_user, email: 'alias@example.com').tap do |email|
- another_user.update!(public_email: email.email)
+ context 'when use_minimum_char_limit is false' do
+ it 'returns users with a partially matching username' do
+ expect(described_class.search('se', use_minimum_char_limit: false)).to eq([user3, user, user2])
+ end
end
end
- let_it_be(:secondary_email) do
- create(:email, :confirmed, user: another_user, email: 'secondary@example.com')
- end
-
- it 'returns users with a matching name' do
- expect(described_class.search_with_public_emails(user.name)).to match_array([user])
- end
-
- it 'returns users with a partially matching name' do
- expect(described_class.search_with_public_emails(user.name[0..2])).to match_array([user])
- end
-
- it 'returns users with a matching name regardless of the casing' do
- expect(described_class.search_with_public_emails(user.name.upcase)).to match_array([user])
- end
-
- it 'returns users with a matching public email' do
- expect(described_class.search_with_public_emails(another_user.public_email)).to match_array([another_user])
- end
-
- it 'does not return users with a partially matching email' do
- expect(described_class.search_with_public_emails(another_user.public_email[1...-1])).to be_empty
- end
-
- it 'returns users with a matching email regardless of the casing' do
- expect(described_class.search_with_public_emails(another_user.public_email.upcase)).to match_array([another_user])
- end
-
- it 'returns users with a matching username' do
- expect(described_class.search_with_public_emails(user.username)).to match_array([user])
- end
-
- it 'returns users with a partially matching username' do
- expect(described_class.search_with_public_emails(user.username[0..2])).to match_array([user])
- end
-
- it 'returns users with a matching username regardless of the casing' do
- expect(described_class.search_with_public_emails(user.username.upcase)).to match_array([user])
- end
-
- it 'does not return users with a matching whole private email' do
- expect(described_class.search_with_public_emails(user.email)).not_to include(user)
- end
-
- it 'does not return users with a matching whole private email' do
- expect(described_class.search_with_public_emails(secondary_email.email)).to be_empty
- end
-
- it 'does not return users with a matching part of secondary email' do
- expect(described_class.search_with_public_emails(secondary_email.email[1...-1])).to be_empty
- end
-
- it 'does not return users with a matching part of private email' do
- expect(described_class.search_with_public_emails(user.email[1...-1])).to be_empty
- end
-
- it 'returns no matches for an empty string' do
- expect(described_class.search_with_public_emails('')).to be_empty
- end
-
- it 'returns no matches for nil' do
- expect(described_class.search_with_public_emails(nil)).to be_empty
- end
- end
-
- describe '.search_with_secondary_emails' do
- let_it_be(:user) { create(:user, name: 'John Doe', username: 'john.doe', email: 'someone.1@example.com' ) }
- let_it_be(:another_user) { create(:user, name: 'Albert Smith', username: 'albert.smith', email: 'another.2@example.com' ) }
- let_it_be(:email) { create(:email, user: another_user, email: 'alias@example.com') }
-
- it 'returns users with a matching name' do
- expect(described_class.search_with_secondary_emails(user.name)).to eq([user])
- end
-
- it 'returns users with a partially matching name' do
- expect(described_class.search_with_secondary_emails(user.name[0..2])).to eq([user])
- end
-
- it 'returns users with a matching name regardless of the casing' do
- expect(described_class.search_with_secondary_emails(user.name.upcase)).to eq([user])
- end
-
- it 'returns users with a matching email' do
- expect(described_class.search_with_secondary_emails(user.email)).to eq([user])
- end
-
- it 'does not return users with a partially matching email' do
- expect(described_class.search_with_secondary_emails(user.email[1...-1])).to be_empty
- end
-
- it 'returns users with a matching email regardless of the casing' do
- expect(described_class.search_with_secondary_emails(user.email.upcase)).to eq([user])
- end
-
- it 'returns users with a matching username' do
- expect(described_class.search_with_secondary_emails(user.username)).to eq([user])
- end
-
- it 'returns users with a partially matching username' do
- expect(described_class.search_with_secondary_emails(user.username[0..2])).to eq([user])
- end
-
- it 'returns users with a matching username regardless of the casing' do
- expect(described_class.search_with_secondary_emails(user.username.upcase)).to eq([user])
- end
-
- it 'returns users with a matching whole secondary email' do
- expect(described_class.search_with_secondary_emails(email.email)).to eq([email.user])
- end
-
- it 'does not return users with a matching part of secondary email' do
- expect(described_class.search_with_secondary_emails(email.email[1...-1])).to be_empty
- end
-
it 'returns no matches for an empty string' do
- expect(described_class.search_with_secondary_emails('')).to be_empty
+ expect(described_class.search('')).to be_empty
end
it 'returns no matches for nil' do
- expect(described_class.search_with_secondary_emails(nil)).to be_empty
+ expect(described_class.search(nil)).to be_empty
end
end
@@ -3683,13 +3505,16 @@ RSpec.describe User do
let!(:project1) { create(:project) }
let!(:project2) { fork_project(project3) }
let!(:project3) { create(:project) }
+ let!(:project_aimed_for_deletion) { create(:project, marked_for_deletion_at: 2.days.ago, pending_delete: false) }
let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) }
let!(:push_event) { create(:push_event, project: project1, author: subject) }
let!(:merge_event) { create(:event, :created, project: project3, target: merge_request, author: subject) }
+ let!(:merge_event_2) { create(:event, :created, project: project_aimed_for_deletion, target: merge_request, author: subject) }
before do
project1.add_maintainer(subject)
project2.add_maintainer(subject)
+ project_aimed_for_deletion.add_maintainer(subject)
end
it 'includes IDs for projects the user has pushed to' do
@@ -3703,6 +3528,10 @@ RSpec.describe User do
it "doesn't include IDs for unrelated projects" do
expect(subject.contributed_projects).not_to include(project2)
end
+
+ it "doesn't include projects aimed for deletion" do
+ expect(subject.contributed_projects).not_to include(project_aimed_for_deletion)
+ end
end
describe '#fork_of' do
@@ -4365,6 +4194,8 @@ RSpec.describe User do
context 'when FF ci_owned_runners_cross_joins_fix is disabled' do
before do
+ skip_if_multiple_databases_are_setup
+
stub_feature_flags(ci_owned_runners_cross_joins_fix: false)
end
diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb
new file mode 100644
index 00000000000..2fa1abda44a
--- /dev/null
+++ b/spec/models/work_item_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItem do
+ describe '#noteable_target_type_name' do
+ it 'returns `issue` as the target name' do
+ work_item = build(:work_item)
+
+ expect(work_item.noteable_target_type_name).to eq('issue')
+ end
+ end
+end
diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb
index 9a65823c950..b68bb966820 100644
--- a/spec/policies/ci/pipeline_policy_spec.rb
+++ b/spec/policies/ci/pipeline_policy_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe Ci::PipelinePolicy, :models do
let(:project) { create(:project, :public) }
context 'when user has owner access' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it 'is enabled' do
expect(policy).to be_allowed :destroy_pipeline
@@ -107,7 +107,7 @@ RSpec.describe Ci::PipelinePolicy, :models do
let(:project) { create(:project, :public) }
context 'when user has owner access' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it 'is enabled' do
expect(policy).to be_allowed :read_pipeline_variable
@@ -129,7 +129,7 @@ RSpec.describe Ci::PipelinePolicy, :models do
end
context 'when user is developer and it is not the creator of the pipeline' do
- let(:pipeline) { create(:ci_empty_pipeline, project: project, user: project.owner) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, user: project.first_owner) }
before do
project.add_developer(user)
diff --git a/spec/policies/clusters/agent_token_policy_spec.rb b/spec/policies/clusters/agent_token_policy_spec.rb
index 9ae99e66f59..f5ac8bd67e6 100644
--- a/spec/policies/clusters/agent_token_policy_spec.rb
+++ b/spec/policies/clusters/agent_token_policy_spec.rb
@@ -10,13 +10,22 @@ RSpec.describe Clusters::AgentTokenPolicy do
let(:project) { token.agent.project }
describe 'rules' do
+ context 'when reporter' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it { expect(policy).to be_disallowed :admin_cluster }
+ it { expect(policy).to be_disallowed :read_cluster }
+ end
+
context 'when developer' do
before do
project.add_developer(user)
end
it { expect(policy).to be_disallowed :admin_cluster }
- it { expect(policy).to be_disallowed :read_cluster }
+ it { expect(policy).to be_allowed :read_cluster }
end
context 'when maintainer' do
diff --git a/spec/policies/clusters/agents/activity_event_policy_spec.rb b/spec/policies/clusters/agents/activity_event_policy_spec.rb
index 1262fcfd9f2..365168de79f 100644
--- a/spec/policies/clusters/agents/activity_event_policy_spec.rb
+++ b/spec/policies/clusters/agents/activity_event_policy_spec.rb
@@ -10,13 +10,22 @@ RSpec.describe Clusters::Agents::ActivityEventPolicy do
let(:project) { event.agent.project }
describe 'rules' do
+ context 'reporter' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it { expect(policy).to be_disallowed :admin_cluster }
+ it { expect(policy).to be_disallowed :read_cluster }
+ end
+
context 'developer' do
before do
project.add_developer(user)
end
it { expect(policy).to be_disallowed :admin_cluster }
- it { expect(policy).to be_disallowed :read_cluster }
+ it { expect(policy).to be_allowed :read_cluster }
end
context 'maintainer' do
diff --git a/spec/policies/namespaces/project_namespace_policy_spec.rb b/spec/policies/namespaces/project_namespace_policy_spec.rb
index f6fe4ae552a..f1022747fab 100644
--- a/spec/policies/namespaces/project_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/project_namespace_policy_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Namespaces::ProjectNamespacePolicy do
end
context 'parent owner' do
- let_it_be(:current_user) { parent.owner }
+ let_it_be(:current_user) { parent.first_owner }
it { is_expected.to be_disallowed(*permissions) }
end
diff --git a/spec/policies/project_member_policy_spec.rb b/spec/policies/project_member_policy_spec.rb
index aebbe685bb3..12b3e60fdb2 100644
--- a/spec/policies/project_member_policy_spec.rb
+++ b/spec/policies/project_member_policy_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe ProjectMemberPolicy do
end
context 'when user is project owner' do
- let(:member_user) { project.owner }
+ let(:member_user) { project.first_owner }
let(:member) { project.members.find_by!(user: member_user) }
it { is_expected.to be_allowed(:read_project) }
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 38e4e18c894..793b1fffd5f 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -117,7 +117,7 @@ RSpec.describe ProjectPolicy do
end
describe 'for unconfirmed user' do
- let(:current_user) { project.owner.tap { |u| u.update!(confirmed_at: nil) } }
+ let(:current_user) { project.first_owner.tap { |u| u.update!(confirmed_at: nil) } }
it 'disallows to modify pipelines' do
expect_disallowed(:create_pipeline)
@@ -144,7 +144,7 @@ RSpec.describe ProjectPolicy do
end
describe 'for project owner' do
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
it 'allows :destroy_pipeline' do
expect(current_user.can?(:destroy_pipeline, pipeline)).to be_truthy
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index 3bf592ed2b9..225386d9596 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe BlobPresenter do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let(:repository) { project.repository }
let(:blob) { repository.blob_at('HEAD', 'files/ruby/regex.rb') }
@@ -87,6 +87,33 @@ RSpec.describe BlobPresenter do
it { expect(presenter.permalink_path).to eq("/#{project.full_path}/-/blob/#{project.repository.commit.sha}/files/ruby/regex.rb") }
end
+ context 'environment has been deployed' do
+ let(:external_url) { "https://some.environment" }
+ let(:environment) { create(:environment, project: project, external_url: external_url) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, project: project, sha: blob.commit_id) }
+
+ before do
+ allow(project).to receive(:public_path_for_source_path).with(blob.path, blob.commit_id).and_return(blob.path)
+ end
+
+ describe '#environment_formatted_external_url' do
+ it { expect(presenter.environment_formatted_external_url).to eq("some.environment") }
+ end
+
+ describe '#environment_external_url_for_route_map' do
+ it { expect(presenter.environment_external_url_for_route_map).to eq("#{external_url}/#{blob.path}") }
+ end
+
+ describe 'chooses the latest deployed environment for #environment_formatted_external_url and #environment_external_url_for_route_map' do
+ let(:another_external_url) { "https://another.environment" }
+ let(:another_environment) { create(:environment, project: project, external_url: another_external_url) }
+ let!(:another_deployment) { create(:deployment, :success, environment: another_environment, project: project, sha: blob.commit_id) }
+
+ it { expect(presenter.environment_formatted_external_url).to eq("another.environment") }
+ it { expect(presenter.environment_external_url_for_route_map).to eq("#{another_external_url}/#{blob.path}") }
+ end
+ end
+
describe '#code_owners' do
it { expect(presenter.code_owners).to match_array([]) }
end
@@ -143,13 +170,13 @@ RSpec.describe BlobPresenter do
let(:git_blob) { blob.__getobj__ }
it 'returns highlighted content' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: nil)
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
presenter.highlight
end
it 'returns plain content when :plain is true' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: true, language: nil)
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: true, language: 'ruby')
presenter.highlight(plain: true)
end
@@ -162,7 +189,7 @@ RSpec.describe BlobPresenter do
end
it 'returns limited highlighted content' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', "line one\n", plain: nil, language: nil)
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', "line one\n", plain: nil, language: 'ruby')
presenter.highlight(to: 1)
end
@@ -220,6 +247,36 @@ RSpec.describe BlobPresenter do
end
end
+ describe '#blob_language' do
+ subject { presenter.blob_language }
+
+ it { is_expected.to eq('ruby') }
+
+ context 'gitlab-language contains a match' do
+ before do
+ allow(blob).to receive(:language_from_gitattributes).and_return('cpp')
+ end
+
+ it { is_expected.to eq('cpp') }
+ end
+
+ context 'when blob is ipynb' do
+ let(:blob) { repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb') }
+
+ before do
+ allow(Gitlab::Diff::CustomDiff).to receive(:transformed_for_diff?).and_return(true)
+ end
+
+ it { is_expected.to eq('md') }
+ end
+
+ context 'when blob is binary' do
+ let(:blob) { repository.blob_at('HEAD', 'Gemfile.zip') }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '#raw_plain_data' do
let(:blob) { repository.blob_at('HEAD', file) }
diff --git a/spec/presenters/blobs/unfold_presenter_spec.rb b/spec/presenters/blobs/unfold_presenter_spec.rb
index 4e9f83e8001..14c36461e90 100644
--- a/spec/presenters/blobs/unfold_presenter_spec.rb
+++ b/spec/presenters/blobs/unfold_presenter_spec.rb
@@ -206,6 +206,14 @@ RSpec.describe Blobs::UnfoldPresenter do
end
end
+ context 'when since exceeds number of lines' do
+ let(:params) { { since: 2 } }
+
+ it 'returns an empty list' do
+ expect(subject.lines.size).to eq(0)
+ end
+ end
+
context 'when full is true' do
let(:params) { { full: true } }
diff --git a/spec/presenters/clusterable_presenter_spec.rb b/spec/presenters/clusterable_presenter_spec.rb
index d19abd4e4d8..7c2e19728d5 100644
--- a/spec/presenters/clusterable_presenter_spec.rb
+++ b/spec/presenters/clusterable_presenter_spec.rb
@@ -79,6 +79,30 @@ RSpec.describe ClusterablePresenter do
end
end
+ describe '#can_admin_cluster?' do
+ let(:user) { create(:user) }
+
+ subject { described_class.new(clusterable).can_admin_cluster? }
+
+ before do
+ clusterable.add_maintainer(user)
+
+ allow(clusterable).to receive(:current_user).and_return(user)
+ end
+
+ context 'when clusterable is a group' do
+ let(:clusterable) { create(:group) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+
+ context 'when clusterable is a project' do
+ let(:clusterable) { create(:project, :repository) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+ end
+
describe '#environments_cluster_path' do
subject { described_class.new(clusterable).environments_cluster_path(cluster) }
diff --git a/spec/presenters/packages/conan/package_presenter_spec.rb b/spec/presenters/packages/conan/package_presenter_spec.rb
index 27ecf32b6f2..d35137cd820 100644
--- a/spec/presenters/packages/conan/package_presenter_spec.rb
+++ b/spec/presenters/packages/conan/package_presenter_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
let_it_be(:user) { create(:user) }
let_it_be(:package) { create(:conan_package) }
let_it_be(:project) { package.project }
+ let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: package) }
let_it_be(:conan_package_reference) { '123456789'}
let(:params) { { package_scope: :instance } }
@@ -208,22 +209,4 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
end
end
end
-
- # TODO when cleaning up packages_installable_package_files, consider removing this context and
- # add a dummy package file pending destruction on L8
- context 'with package files pending destruction' do
- let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: package) }
-
- subject { presenter.send(:package_files).to_a }
-
- it { is_expected.not_to include(package_file_pending_destruction) }
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it { is_expected.to include(package_file_pending_destruction) }
- end
- end
end
diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb
index 4e2645b27ff..71ec3ee2d67 100644
--- a/spec/presenters/packages/detail/package_presenter_spec.rb
+++ b/spec/presenters/packages/detail/package_presenter_spec.rb
@@ -161,14 +161,6 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
subject { presenter.detail_view[:package_files].map { |e| e[:id] } }
it { is_expected.not_to include(package_file_pending_destruction.id) }
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it { is_expected.to include(package_file_pending_destruction.id) }
- end
end
end
end
diff --git a/spec/presenters/packages/npm/package_presenter_spec.rb b/spec/presenters/packages/npm/package_presenter_spec.rb
index 2308f928c92..8b99e6d8605 100644
--- a/spec/presenters/packages/npm/package_presenter_spec.rb
+++ b/spec/presenters/packages/npm/package_presenter_spec.rb
@@ -104,17 +104,6 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
it 'does not return them' do
expect(shasums).not_to include(package_file_pending_destruction.file_sha1)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- package2.package_files.id_not_in(package_file_pending_destruction.id).delete_all
- end
-
- it 'returns them' do
- expect(shasums).to include(package_file_pending_destruction.file_sha1)
- end
- end
end
end
diff --git a/spec/presenters/packages/nuget/package_metadata_presenter_spec.rb b/spec/presenters/packages/nuget/package_metadata_presenter_spec.rb
index 6e99b6bafec..6c56763e719 100644
--- a/spec/presenters/packages/nuget/package_metadata_presenter_spec.rb
+++ b/spec/presenters/packages/nuget/package_metadata_presenter_spec.rb
@@ -29,14 +29,6 @@ RSpec.describe Packages::Nuget::PackageMetadataPresenter do
let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: package, file_name: 'pending_destruction.nupkg') }
it { is_expected.not_to include('pending_destruction.nupkg') }
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it { is_expected.to include('pending_destruction.nupkg') }
- end
end
end
diff --git a/spec/presenters/packages/pypi/package_presenter_spec.rb b/spec/presenters/packages/pypi/package_presenter_spec.rb
index 8a23c0ec3cb..b19abdbc17a 100644
--- a/spec/presenters/packages/pypi/package_presenter_spec.rb
+++ b/spec/presenters/packages/pypi/package_presenter_spec.rb
@@ -59,14 +59,6 @@ RSpec.describe ::Packages::Pypi::PackagePresenter do
let(:project_or_group) { project }
it { is_expected.not_to include(package_file_pending_destruction.file_name)}
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it { is_expected.to include(package_file_pending_destruction.file_name)}
- end
end
end
end
diff --git a/spec/presenters/projects/security/configuration_presenter_spec.rb b/spec/presenters/projects/security/configuration_presenter_spec.rb
index f9150179ae5..5f874ab5a3f 100644
--- a/spec/presenters/projects/security/configuration_presenter_spec.rb
+++ b/spec/presenters/projects/security/configuration_presenter_spec.rb
@@ -86,8 +86,9 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
expect(feature['type']).to eq('sast')
expect(feature['configured']).to eq(true)
- expect(feature['configuration_path']).to eq(project_security_configuration_sast_path(project))
+ expect(feature['configuration_path']).to be_nil
expect(feature['available']).to eq(true)
+ expect(feature['can_enable_by_merge_request']).to eq(true)
end
context 'when checking features configured status' do
diff --git a/spec/controllers/abuse_reports_controller_spec.rb b/spec/requests/abuse_reports_controller_spec.rb
index 11371108375..94c80ccb89a 100644
--- a/spec/controllers/abuse_reports_controller_spec.rb
+++ b/spec/requests/abuse_reports_controller_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe AbuseReportsController do
user_id = user.id
user.destroy!
- get :new, params: { user_id: user_id }
+ get new_abuse_report_path(user_id: user_id)
expect(response).to redirect_to root_path
expect(flash[:alert]).to eq(_('Cannot create the abuse report. The user has been deleted.'))
@@ -32,7 +32,7 @@ RSpec.describe AbuseReportsController do
it 'redirects the reporter to the user\'s profile' do
user.block
- get :new, params: { user_id: user.id }
+ get new_abuse_report_path(user_id: user.id)
expect(response).to redirect_to user
expect(flash[:alert]).to eq(_('Cannot create the abuse report. This user has been blocked.'))
@@ -44,7 +44,7 @@ RSpec.describe AbuseReportsController do
context 'with valid attributes' do
it 'saves the abuse report' do
expect do
- post :create, params: { abuse_report: attrs }
+ post abuse_reports_path(abuse_report: attrs)
end.to change { AbuseReport.count }.by(1)
end
@@ -53,22 +53,22 @@ RSpec.describe AbuseReportsController do
expect(instance).to receive(:notify)
end
- post :create, params: { abuse_report: attrs }
+ post abuse_reports_path(abuse_report: attrs)
end
it 'redirects back to root' do
- post :create, params: { abuse_report: attrs }
+ post abuse_reports_path(abuse_report: attrs)
expect(response).to redirect_to root_path
end
end
context 'with invalid attributes' do
- it 'renders new' do
+ it 'redirects back to root' do
attrs.delete(:user_id)
- post :create, params: { abuse_report: attrs }
+ post abuse_reports_path(abuse_report: attrs)
- expect(response).to render_template(:new)
+ expect(response).to redirect_to root_path
end
end
end
diff --git a/spec/requests/admin/background_migrations_controller_spec.rb b/spec/requests/admin/background_migrations_controller_spec.rb
index c7d5d5cae08..67c9c4df827 100644
--- a/spec/requests/admin/background_migrations_controller_spec.rb
+++ b/spec/requests/admin/background_migrations_controller_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Admin::BackgroundMigrationsController, :enable_admin_mode do
let(:migration) { create(:batched_background_migration, status: 'failed') }
before do
- create(:batched_background_migration_job, batched_migration: migration, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3)
+ create(:batched_background_migration_job, :failed, batched_migration: migration, batch_size: 10, min_value: 6, max_value: 15, attempts: 3)
allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10])
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 6a02f81fcae..df9be2616c5 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe API::API do
describe 'logging', :aggregate_failures do
let_it_be(:project) { create(:project, :public) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
context 'when the endpoint is handled by the application' do
context 'when the endpoint supports all possible fields' do
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index ad517a05533..780e45cf443 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -188,6 +188,24 @@ RSpec.describe API::Branches do
end
end
+ context 'when sort parameter is passed' do
+ it 'sorts branches' do
+ get api(route, user), params: { sort: 'name_asc', per_page: 10 }
+
+ sorted_branch_names = json_response.map { |branch| branch['name'] }
+
+ project_branch_names = project.repository.branch_names.sort.take(10)
+
+ expect(sorted_branch_names).to eq(project_branch_names)
+ end
+
+ context 'when sort value is not supported' do
+ it_behaves_like '400 response' do
+ let(:request) { get api(route, user), params: { sort: 'unknown' }}
+ end
+ end
+ end
+
context 'when unauthenticated', 'and project is public' do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 13838cffd76..1b87a5e24f5 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -988,7 +988,7 @@ RSpec.describe API::Ci::Pipelines do
describe 'DELETE /projects/:id/pipelines/:pipeline_id' do
context 'authorized user' do
- let(:owner) { project.owner }
+ let(:owner) { project.first_owner }
it 'destroys the pipeline' do
delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner)
diff --git a/spec/requests/api/ci/runner/runners_post_spec.rb b/spec/requests/api/ci/runner/runners_post_spec.rb
index 530b601add9..5eb5d3977a3 100644
--- a/spec/requests/api/ci/runner/runners_post_spec.rb
+++ b/spec/requests/api/ci/runner/runners_post_spec.rb
@@ -30,11 +30,11 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
post api('/runners'), params: {
token: 'valid token',
description: 'server.hostname',
- maintainer_note: 'Some maintainer notes',
+ maintenance_note: 'Some maintainer notes',
run_untagged: false,
tag_list: 'tag1, tag2',
locked: true,
- active: true,
+ paused: false,
access_level: 'ref_protected',
maximum_timeout: 9000
}
@@ -46,7 +46,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
allow_next_instance_of(::Ci::RegisterRunnerService) do |service|
expected_params = {
description: 'server.hostname',
- maintainer_note: 'Some maintainer notes',
+ maintenance_note: 'Some maintainer notes',
run_untagged: false,
tag_list: %w(tag1 tag2),
locked: true,
@@ -55,19 +55,33 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
maximum_timeout: 9000
}.stringify_keys
- allow(service).to receive(:execute)
+ expect(service).to receive(:execute)
.once
.with('valid token', a_hash_including(expected_params))
.and_return(new_runner)
end
end
- it 'creates runner' do
- request
+ context 'when token_expires_at is nil' do
+ it 'creates runner' do
+ request
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['id']).to eq(new_runner.id)
- expect(json_response['token']).to eq(new_runner.token)
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to eq({ 'id' => new_runner.id, 'token' => new_runner.token, 'token_expires_at' => nil })
+ end
+ end
+
+ context 'when token_expires_at is a valid date' do
+ before do
+ new_runner.token_expires_at = DateTime.new(2022, 1, 11, 14, 39, 24)
+ end
+
+ it 'creates runner' do
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to eq({ 'id' => new_runner.id, 'token' => new_runner.token, 'token_expires_at' => '2022-01-11T14:39:24.000Z' })
+ end
end
it_behaves_like 'storing arguments in the application context for the API' do
@@ -81,6 +95,59 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when deprecated maintainer_note field is provided' do
+ RSpec::Matchers.define_negated_matcher :excluding, :include
+
+ def request
+ post api('/runners'), params: {
+ token: 'valid token',
+ maintainer_note: 'Some maintainer notes'
+ }
+ end
+
+ let(:new_runner) { create(:ci_runner) }
+
+ it 'converts to maintenance_note param' do
+ allow_next_instance_of(::Ci::RegisterRunnerService) do |service|
+ expect(service).to receive(:execute)
+ .once
+ .with('valid token', a_hash_including('maintenance_note' => 'Some maintainer notes')
+ .and(excluding('maintainter_note' => anything)))
+ .and_return(new_runner)
+ end
+
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
+ context 'when deprecated active parameter is provided' do
+ def request
+ post api('/runners'), params: {
+ token: 'valid token',
+ active: false
+ }
+ end
+
+ let_it_be(:new_runner) { create(:ci_runner) }
+
+ it 'uses active value in registration' do
+ expect_next_instance_of(::Ci::RegisterRunnerService) do |service|
+ expected_params = { active: false }.stringify_keys
+
+ expect(service).to receive(:execute)
+ .once
+ .with('valid token', a_hash_including(expected_params))
+ .and_return(new_runner)
+ end
+
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
context 'calling actual register service' do
include StubGitlabCalls
diff --git a/spec/requests/api/ci/runner/runners_verify_post_spec.rb b/spec/requests/api/ci/runner/runners_verify_post_spec.rb
index 4680076acae..038e126deaa 100644
--- a/spec/requests/api/ci/runner/runners_verify_post_spec.rb
+++ b/spec/requests/api/ci/runner/runners_verify_post_spec.rb
@@ -49,6 +49,30 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
let(:expected_params) { { client_id: "runner/#{runner.id}" } }
end
end
+
+ context 'when non-expired token is provided' do
+ subject { post api('/runners/verify'), params: { token: runner.token } }
+
+ it 'verifies Runner credentials' do
+ runner["token_expires_at"] = 10.days.from_now
+ runner.save!
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when expired token is provided' do
+ subject { post api('/runners/verify'), params: { token: runner.token } }
+
+ it 'does not verify Runner credentials' do
+ runner["token_expires_at"] = 10.days.ago
+ runner.save!
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
end
end
diff --git a/spec/requests/api/ci/runners_reset_registration_token_spec.rb b/spec/requests/api/ci/runners_reset_registration_token_spec.rb
index df64c0bd22b..e1dc347f8dd 100644
--- a/spec/requests/api/ci/runners_reset_registration_token_spec.rb
+++ b/spec/requests/api/ci/runners_reset_registration_token_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe API::Ci::Runners do
end
include_context 'when authorized', 'project' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
def get_token
project.reload.runners_token
diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb
index 305c0bd9df0..336ce70d8d2 100644
--- a/spec/requests/api/ci/runners_spec.rb
+++ b/spec/requests/api/ci/runners_spec.rb
@@ -86,14 +86,24 @@ RSpec.describe API::Ci::Runners do
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'filters runners by status' do
- create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+ context 'with an inactive runner' do
+ let_it_be(:runner) { create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project]) }
- get api('/runners?status=paused', user)
+ it 'filters runners by paused state' do
+ get api('/runners?paused=true', user)
- expect(json_response).to match_array [
- a_hash_including('description' => 'Inactive project runner')
- ]
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'filters runners by status' do
+ get api('/runners?status=paused', user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
end
it 'does not filter by invalid status' do
@@ -109,7 +119,7 @@ RSpec.describe API::Ci::Runners do
get api('/runners?tag_list=tag1,tag2', user)
expect(json_response).to match_array [
- a_hash_including('description' => 'Runner tagged with tag1 and tag2')
+ a_hash_including('description' => 'Runner tagged with tag1 and tag2', 'active' => true, 'paused' => false)
]
end
end
@@ -137,7 +147,7 @@ RSpec.describe API::Ci::Runners do
get api('/runners/all', admin)
expect(json_response).to match_array [
- a_hash_including('description' => 'Project runner', 'is_shared' => false, 'runner_type' => 'project_type'),
+ a_hash_including('description' => 'Project runner', 'is_shared' => false, 'active' => true, 'paused' => 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'),
@@ -199,14 +209,24 @@ RSpec.describe API::Ci::Runners do
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'filters runners by status' do
- create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+ context 'with an inactive runner' do
+ let_it_be(:runner) { create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project]) }
- get api('/runners/all?status=paused', admin)
+ it 'filters runners by status' do
+ get api('/runners/all?paused=true', admin)
- expect(json_response).to match_array [
- a_hash_including('description' => 'Inactive project runner')
- ]
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'filters runners by status' do
+ get api('/runners/all?status=paused', admin)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
end
it 'does not filter by invalid status' do
@@ -255,6 +275,8 @@ RSpec.describe API::Ci::Runners do
expect(json_response['description']).to eq(shared_runner.description)
expect(json_response['maximum_timeout']).to be_nil
expect(json_response['status']).to eq("not_connected")
+ expect(json_response['active']).to eq(true)
+ expect(json_response['paused']).to eq(false)
end
end
@@ -359,6 +381,14 @@ RSpec.describe API::Ci::Runners do
expect(shared_runner.reload.active).to eq(!active)
end
+ it 'runner paused state' do
+ active = shared_runner.active
+ update_runner(shared_runner.id, admin, paused: active)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(shared_runner.reload.active).to eq(!active)
+ end
+
it 'runner tag list' do
update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql'])
@@ -500,6 +530,10 @@ RSpec.describe API::Ci::Runners do
context 'admin user' do
context 'when runner is shared' do
it 'deletes runner' do
+ expect_next_instance_of(Ci::UnregisterRunnerService, shared_runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
expect do
delete api("/runners/#{shared_runner.id}", admin)
@@ -514,6 +548,10 @@ RSpec.describe API::Ci::Runners do
context 'when runner is not shared' do
it 'deletes used project runner' do
+ expect_next_instance_of(Ci::UnregisterRunnerService, project_runner) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
expect do
delete api("/runners/#{project_runner.id}", admin)
@@ -523,6 +561,10 @@ RSpec.describe API::Ci::Runners do
end
it 'returns 404 if runner does not exist' do
+ allow_next_instance_of(Ci::UnregisterRunnerService) do |service|
+ expect(service).not_to receive(:execute)
+ end
+
delete api('/runners/0', admin)
expect(response).to have_gitlab_http_status(:not_found)
@@ -604,6 +646,10 @@ RSpec.describe API::Ci::Runners do
context 'unauthorized user' do
it 'does not delete project runner' do
+ allow_next_instance_of(Ci::UnregisterRunnerService) do |service|
+ expect(service).not_to receive(:execute)
+ end
+
delete api("/runners/#{project_runner.id}")
expect(response).to have_gitlab_http_status(:unauthorized)
@@ -618,7 +664,7 @@ RSpec.describe API::Ci::Runners do
post api("/runners/#{shared_runner.id}/reset_authentication_token", admin)
expect(response).to have_gitlab_http_status(:success)
- expect(json_response).to eq({ 'token' => shared_runner.reload.token })
+ expect(json_response).to eq({ 'token' => shared_runner.reload.token, 'token_expires_at' => nil })
end.to change { shared_runner.reload.token }
end
@@ -642,7 +688,7 @@ RSpec.describe API::Ci::Runners do
post api("/runners/#{project_runner.id}/reset_authentication_token", user)
expect(response).to have_gitlab_http_status(:success)
- expect(json_response).to eq({ 'token' => project_runner.reload.token })
+ expect(json_response).to eq({ 'token' => project_runner.reload.token, 'token_expires_at' => nil })
end.to change { project_runner.reload.token }
end
@@ -683,7 +729,22 @@ RSpec.describe API::Ci::Runners do
post api("/runners/#{group_runner_a.id}/reset_authentication_token", user)
expect(response).to have_gitlab_http_status(:success)
- expect(json_response).to eq({ 'token' => group_runner_a.reload.token })
+ expect(json_response).to eq({ 'token' => group_runner_a.reload.token, 'token_expires_at' => nil })
+ end.to change { group_runner_a.reload.token }
+ end
+
+ it 'resets group runner authentication token with owner access with expiration time', :freeze_time do
+ expect(group_runner_a.reload.token_expires_at).to be_nil
+
+ group.update!(runner_token_expiration_interval: 5.days)
+
+ expect do
+ post api("/runners/#{group_runner_a.id}/reset_authentication_token", user)
+ group_runner_a.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to eq({ 'token' => group_runner_a.token, 'token_expires_at' => group_runner_a.token_expires_at.iso8601(3) })
+ expect(group_runner_a.token_expires_at).to eq(5.days.from_now)
end.to change { group_runner_a.reload.token }
end
end
@@ -908,9 +969,9 @@ RSpec.describe API::Ci::Runners do
get api("/projects/#{project.id}/runners", user)
expect(json_response).to match_array [
- a_hash_including('description' => 'Project runner'),
- a_hash_including('description' => 'Two projects runner'),
- a_hash_including('description' => 'Shared runner')
+ a_hash_including('description' => 'Project runner', 'active' => true, 'paused' => false),
+ a_hash_including('description' => 'Two projects runner', 'active' => true, 'paused' => false),
+ a_hash_including('description' => 'Shared runner', 'active' => true, 'paused' => false)
]
end
@@ -946,14 +1007,24 @@ RSpec.describe API::Ci::Runners do
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'filters runners by status' do
- create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+ context 'with an inactive runner' do
+ let_it_be(:runner) { create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project]) }
- get api("/projects/#{project.id}/runners?status=paused", user)
+ it 'filters runners by status' do
+ get api("/projects/#{project.id}/runners?paused=true", user)
- expect(json_response).to match_array [
- a_hash_including('description' => 'Inactive project runner')
- ]
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'filters runners by status' do
+ get api("/projects/#{project.id}/runners?status=paused", user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
end
it 'does not filter by invalid status' do
@@ -980,13 +1051,14 @@ RSpec.describe API::Ci::Runners do
end
end
- shared_context 'GET /groups/:id/runners' do
+ describe 'GET /groups/:id/runners' do
context 'authorized user with maintainer privileges' do
it 'returns all runners' do
get api("/groups/#{group.id}/runners", user)
expect(json_response).to match_array([
- a_hash_including('description' => 'Group runner A')
+ a_hash_including('description' => 'Group runner A', 'active' => true, 'paused' => false),
+ a_hash_including('description' => 'Shared runner', 'active' => true, 'paused' => false)
])
end
@@ -999,6 +1071,15 @@ RSpec.describe API::Ci::Runners do
])
end
+ it 'returns instance runners when instance_type is specified' do
+ get api("/groups/#{group.id}/runners?type=instance_type", user)
+
+ expect(json_response).to match_array([
+ a_hash_including('description' => 'Shared runner')
+ ])
+ end
+
+ # TODO: Remove in %15.0 (https://gitlab.com/gitlab-org/gitlab/-/issues/351466)
it 'returns empty result when type does not match' do
get api("/groups/#{group.id}/runners?type=project_type", user)
@@ -1012,21 +1093,31 @@ RSpec.describe API::Ci::Runners do
end
end
- context 'filter runners by status' do
- it 'returns runners by valid status' do
- create(:ci_runner, :group, :inactive, description: 'Inactive group runner', groups: [group])
+ context 'with an inactive runner' do
+ let_it_be(:runner) { create(:ci_runner, :group, :inactive, description: 'Inactive group runner', groups: [group]) }
- get api("/groups/#{group.id}/runners?status=paused", user)
+ it 'returns runners by paused state' do
+ get api("/groups/#{group.id}/runners?paused=true", user)
expect(json_response).to match_array([
a_hash_including('description' => 'Inactive group runner')
])
end
- it 'does not filter by invalid status' do
- get api("/groups/#{group.id}/runners?status=bogus", user)
+ context 'filter runners by status' do
+ it 'returns runners by valid status' do
+ get api("/groups/#{group.id}/runners?status=paused", user)
- expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response).to match_array([
+ a_hash_including('description' => 'Inactive group runner')
+ ])
+ end
+
+ it 'does not filter by invalid status' do
+ get api("/groups/#{group.id}/runners?status=bogus", user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
end
end
@@ -1048,16 +1139,6 @@ RSpec.describe API::Ci::Runners do
end
end
- it_behaves_like 'GET /groups/:id/runners'
-
- context 'when the FF ci_find_runners_by_ci_mirrors is disabled' do
- before do
- stub_feature_flags(ci_find_runners_by_ci_mirrors: false)
- end
-
- it_behaves_like 'GET /groups/:id/runners'
- end
-
describe 'POST /projects/:id/runners' do
context 'authorized user' do
let_it_be(:project_runner2) { create(:ci_runner, :project, projects: [project2]) }
diff --git a/spec/requests/api/ci/secure_files_spec.rb b/spec/requests/api/ci/secure_files_spec.rb
new file mode 100644
index 00000000000..5cf6999f60a
--- /dev/null
+++ b/spec/requests/api/ci/secure_files_spec.rb
@@ -0,0 +1,314 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Ci::SecureFiles do
+ before do
+ stub_ci_secure_file_object_storage
+ stub_feature_flags(ci_secure_files: true)
+ end
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:project) { create(:project, creator_id: user.id) }
+ let_it_be(:maintainer) { create(:project_member, :maintainer, user: user, project: project) }
+ let_it_be(:developer) { create(:project_member, :developer, user: user2, project: project) }
+ let_it_be(:secure_file) { create(:ci_secure_file, project: project) }
+
+ describe 'GET /projects/:id/secure_files' do
+ context 'feature flag' do
+ it 'returns a 503 when the feature flag is disabled' do
+ stub_feature_flags(ci_secure_files: false)
+
+ get api("/projects/#{project.id}/secure_files", user)
+
+ expect(response).to have_gitlab_http_status(:service_unavailable)
+ end
+
+ it 'returns a 200 when the feature flag is enabled' do
+ get api("/projects/#{project.id}/secure_files", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_a(Array)
+ end
+ end
+
+ context 'authorized user with proper permissions' do
+ it 'returns project secure files' do
+ get api("/projects/#{project.id}/secure_files", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_a(Array)
+ end
+ end
+
+ context 'authorized user with invalid permissions' do
+ it 'does not return project secure files' do
+ get api("/projects/#{project.id}/secure_files", user2)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not return project secure files' do
+ get api("/projects/#{project.id}/secure_files")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/secure_files/:secure_file_id' do
+ context 'authorized user with proper permissions' do
+ it 'returns project secure file details' do
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq(secure_file.name)
+ expect(json_response['permissions']).to eq(secure_file.permissions)
+ end
+
+ it 'responds with 404 Not Found if requesting non-existing secure file' do
+ get api("/projects/#{project.id}/secure_files/99999", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'authorized user with invalid permissions' do
+ it 'does not return project secure file details' do
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}", user2)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not return project secure file details' do
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/secure_files/:secure_file_id/download' do
+ context 'authorized user with proper permissions' do
+ it 'returns a secure file' do
+ sample_file = fixture_file('ci_secure_files/upload-keystore.jks')
+ secure_file.file = CarrierWaveStringFile.new(sample_file)
+ secure_file.save!
+
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}/download", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(Base64.encode64(response.body)).to eq(Base64.encode64(sample_file))
+ end
+
+ it 'responds with 404 Not Found if requesting non-existing secure file' do
+ get api("/projects/#{project.id}/secure_files/99999/download", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'authorized user with invalid permissions' do
+ it 'does not return project secure file details' do
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}/download", user2)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not return project secure file details' do
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}/download")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/secure_files' do
+ context 'authorized user with proper permissions' do
+ it 'creates a secure file' do
+ params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks',
+ permissions: 'execute'
+ }
+
+ expect do
+ post api("/projects/#{project.id}/secure_files", user), params: params
+ end.to change {project.secure_files.count}.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq('upload-keystore.jks')
+ expect(json_response['permissions']).to eq('execute')
+ expect(json_response['checksum']).to eq(secure_file.checksum)
+ expect(json_response['checksum_algorithm']).to eq('sha256')
+
+ secure_file = Ci::SecureFile.find(json_response['id'])
+ expect(secure_file.checksum).to eq(
+ Digest::SHA256.hexdigest(fixture_file('ci_secure_files/upload-keystore.jks'))
+ )
+ expect(json_response['id']).to eq(secure_file.id)
+ end
+
+ it 'creates a secure file with read_only permissions by default' do
+ params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks'
+ }
+
+ expect do
+ post api("/projects/#{project.id}/secure_files", user), params: params
+ end.to change {project.secure_files.count}.by(1)
+
+ expect(json_response['permissions']).to eq('read_only')
+ end
+
+ it 'uploads and downloads a secure file' do
+ post_params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks',
+ permissions: 'read_write'
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ secure_file_id = json_response['id']
+
+ get api("/projects/#{project.id}/secure_files/#{secure_file_id}/download", user)
+
+ expect(Base64.encode64(response.body)).to eq(Base64.encode64(fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks').read))
+ end
+
+ it 'returns an error when the file checksum fails to validate' do
+ secure_file.update!(checksum: 'foo')
+
+ get api("/projects/#{project.id}/secure_files/#{secure_file.id}/download", user)
+
+ expect(response.code).to eq("500")
+ end
+
+ it 'returns an error when no file is uploaded' do
+ post_params = {
+ name: 'upload-keystore.jks'
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('file is missing')
+ end
+
+ it 'returns an error when the file name is missing' do
+ post_params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks')
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('name is missing')
+ end
+
+ it 'returns an error when an unexpected permission is supplied' do
+ post_params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks',
+ permissions: 'foo'
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('permissions does not have a valid value')
+ end
+
+ it 'returns an error when an unexpected validation failure happens' do
+ allow_next_instance_of(Ci::SecureFile) do |instance|
+ allow(instance).to receive(:valid?).and_return(false)
+ allow(instance).to receive_message_chain(:errors, :any?).and_return(true)
+ allow(instance).to receive_message_chain(:errors, :messages).and_return(['Error 1', 'Error 2'])
+ end
+
+ post_params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks'
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns a 413 error when the file size is too large' do
+ allow_next_instance_of(Ci::SecureFile) do |instance|
+ allow(instance).to receive_message_chain(:file, :size).and_return(6.megabytes.to_i)
+ end
+
+ post_params = {
+ file: fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks'),
+ name: 'upload-keystore.jks'
+ }
+
+ post api("/projects/#{project.id}/secure_files", user), params: post_params
+
+ expect(response).to have_gitlab_http_status(:payload_too_large)
+ end
+ end
+
+ context 'authorized user with invalid permissions' do
+ it 'does not create a secure file' do
+ post api("/projects/#{project.id}/secure_files", user2)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not create a secure file' do
+ post api("/projects/#{project.id}/secure_files")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/secure_files/:secure_file_id' do
+ context 'authorized user with proper permissions' do
+ it 'deletes the secure file' do
+ expect do
+ delete api("/projects/#{project.id}/secure_files/#{secure_file.id}", user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end.to change {project.secure_files.count}.by(-1)
+ end
+
+ it 'responds with 404 Not Found if requesting non-existing secure_file' do
+ delete api("/projects/#{project.id}/secure_files/99999", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'authorized user with invalid permissions' do
+ it 'does not delete the secure_file' do
+ delete api("/projects/#{project.id}/secure_files/#{secure_file.id}", user2)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not delete the secure_file' do
+ delete api("/projects/#{project.id}/secure_files/#{secure_file.id}")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 2bc642f8b14..156a4cf5ff3 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -5,6 +5,7 @@ require 'mime/types'
RSpec.describe API::Commits do
include ProjectForksHelper
+ include SessionHelpers
let(:user) { create(:user) }
let(:guest) { create(:user).tap { |u| project.add_guest(u) } }
@@ -227,6 +228,12 @@ RSpec.describe API::Commits do
expect(response.headers['X-Page']).to eq('3')
end
end
+
+ context 'when per_page is 0' do
+ let(:per_page) { 0 }
+
+ it_behaves_like '400 response'
+ end
end
context 'with order parameter' do
@@ -378,14 +385,7 @@ RSpec.describe API::Commits do
context 'when using warden' do
it 'increments usage counters', :clean_gitlab_redis_sessions do
- session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
- session_hash = { 'warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]] }
-
- Gitlab::Redis::Sessions.with do |redis|
- redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
- end
-
- cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+ stub_session('warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]])
expect(::Gitlab::UsageDataCounters::WebIdeCounter).to receive(:increment_commits_count)
expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_web_ide_edit_action)
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index 35dba93b766..a265f67115a 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -167,76 +167,85 @@ RSpec.describe API::Features, stub_feature_flags: false do
end
end
+ shared_examples 'does not enable the flag' do |actor_type, actor_path|
+ it 'returns the current state of the flag without changes' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor_path }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ "name" => feature_name,
+ "state" => "off",
+ "gates" => [
+ { "key" => "boolean", "value" => false }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+ end
+
+ shared_examples 'enables the flag for the actor' do |actor_type|
+ it 'sets the feature gate' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor.full_path }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["#{actor.class}:#{actor.id}"] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+ end
+
context 'when enabling for a project by path' do
context 'when the project exists' do
- let!(:project) { create(:project) }
-
- it 'sets the feature gate' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', project: project.full_path }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'actors', 'value' => ["Project:#{project.id}"] }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ it_behaves_like 'enables the flag for the actor', :project do
+ let(:actor) { create(:project) }
end
end
context 'when the project does not exist' do
- it 'sets no new values' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', project: 'mep/to/the/mep/mep' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- "name" => feature_name,
- "state" => "off",
- "gates" => [
- { "key" => "boolean", "value" => false }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
+ it_behaves_like 'does not enable the flag', :project, 'mep/to/the/mep/mep'
end
end
context 'when enabling for a group by path' do
context 'when the group exists' do
- it 'sets the feature gate' do
- group = create(:group)
-
- post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'actors', 'value' => ["Group:#{group.id}"] }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ it_behaves_like 'enables the flag for the actor', :group do
+ let(:actor) { create(:group) }
end
end
context 'when the group does not exist' do
- it 'sets no new values and keeps the feature disabled' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- "name" => feature_name,
- "state" => "off",
- "gates" => [
- { "key" => "boolean", "value" => false }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ it_behaves_like 'does not enable the flag', :group, 'not/a/group'
+ end
+ end
+
+ context 'when enabling for a namespace by path' do
+ context 'when the user namespace exists' do
+ it_behaves_like 'enables the flag for the actor', :namespace do
+ let(:actor) { create(:namespace) }
+ end
+ end
+
+ context 'when the group namespace exists' do
+ it_behaves_like 'enables the flag for the actor', :namespace do
+ let(:actor) { create(:group) }
+ end
+ end
+
+ context 'when the user namespace does not exist' do
+ it_behaves_like 'does not enable the flag', :namespace, 'not/a/group'
+ end
+
+ context 'when a project namespace exists' do
+ let(:project_namespace) { create(:project_namespace) }
+
+ it_behaves_like 'does not enable the flag', :namespace do
+ let(:actor_path) { project_namespace.full_path }
end
end
end
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 578a71a7272..c19defa37e8 100644
--- a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
+++ b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'Getting Ci Cd Setting' do
include GraphqlHelpers
let_it_be_with_reload(:project) { create(:project, :repository) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let(:fields) do
<<~QUERY
diff --git a/spec/requests/api/graphql/ci/config_spec.rb b/spec/requests/api/graphql/ci/config_spec.rb
index 755585f8e0e..62b15a8396c 100644
--- a/spec/requests/api/graphql/ci/config_spec.rb
+++ b/spec/requests/api/graphql/ci/config_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe 'Query.ciConfig' do
context 'when using deprecated keywords' do
let_it_be(:content) do
YAML.dump(
- rspec: { script: 'ls' },
+ rspec: { script: 'ls', type: 'test' },
types: ['test']
)
end
@@ -233,7 +233,10 @@ RSpec.describe 'Query.ciConfig' do
it 'returns a warning' do
post_graphql_query
- expect(graphql_data['ciConfig']['warnings']).to include('root `types` is deprecated in 9.0 and will be removed in 15.0.')
+ expect(graphql_data['ciConfig']['warnings']).to include(
+ 'root `types` is deprecated in 9.0 and will be removed in 15.0.',
+ 'jobs:rspec `type` is deprecated in 9.0 and will be removed in 15.0.'
+ )
end
end
diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb
index 8c919b48849..fa16b9e1ddd 100644
--- a/spec/requests/api/graphql/ci/runner_spec.rb
+++ b/spec/requests/api/graphql/ci/runner_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe 'Query.runner(id)' do
access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true, executor_type: :shell)
end
+ let_it_be(:active_project_runner) { create(:ci_runner, :project) }
+
def get_runner(id)
case id
when :active_instance_runner
@@ -33,6 +35,8 @@ RSpec.describe 'Query.runner(id)' do
inactive_instance_runner
when :active_group_runner
active_group_runner
+ when :active_project_runner
+ active_project_runner
end
end
@@ -55,7 +59,7 @@ RSpec.describe 'Query.runner(id)' do
runner = get_runner(runner_id)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
+ 'id' => runner.to_global_id.to_s,
'description' => runner.description,
'createdAt' => runner.created_at&.iso8601,
'contactedAt' => runner.contacted_at&.iso8601,
@@ -64,6 +68,7 @@ RSpec.describe 'Query.runner(id)' do
'revision' => runner.revision,
'locked' => false,
'active' => runner.active,
+ 'paused' => !runner.active,
'status' => runner.status('14.5').to_s.upcase,
'maximumTimeout' => runner.maximum_timeout,
'accessLevel' => runner.access_level.to_s.upcase,
@@ -72,6 +77,7 @@ RSpec.describe 'Query.runner(id)' do
'runnerType' => runner.instance_type? ? 'INSTANCE_TYPE' : 'PROJECT_TYPE',
'executorName' => runner.executor_type&.dasherize,
'jobCount' => 0,
+ 'jobs' => a_hash_including("count" => 0, "nodes" => [], "pageInfo" => anything),
'projectCount' => nil,
'adminUrl' => "http://localhost/admin/runners/#{runner.id}",
'userPermissions' => {
@@ -103,7 +109,7 @@ RSpec.describe 'Query.runner(id)' do
runner = get_runner(runner_id)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
+ 'id' => runner.to_global_id.to_s,
'adminUrl' => nil
)
expect(runner_data['tagList']).to match_array runner.tag_list
@@ -179,7 +185,7 @@ RSpec.describe 'Query.runner(id)' do
runner_data = graphql_data_at(:runner)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{project_runner.id}",
+ 'id' => project_runner.to_global_id.to_s,
'locked' => is_locked
)
end
@@ -216,13 +222,36 @@ RSpec.describe 'Query.runner(id)' do
a_hash_including(
'webUrl' => "http://localhost/groups/#{group.full_path}/-/runners/#{active_group_runner.id}",
'node' => {
- 'id' => "gid://gitlab/Ci::Runner/#{active_group_runner.id}"
+ 'id' => active_group_runner.to_global_id.to_s
}
)
]
end
end
+ describe 'for group runner request' do
+ let(:query) do
+ %(
+ query {
+ runner(id: "#{active_group_runner.to_global_id}") {
+ groups {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+ )
+ end
+
+ it 'retrieves groups field with expected value' do
+ post_graphql(query, current_user: user)
+
+ runner_data = graphql_data_at(:runner, :groups)
+ expect(runner_data).to eq 'nodes' => [{ 'id' => group.to_global_id.to_s }]
+ end
+ end
+
describe 'for runner with status' do
let_it_be(:stale_runner) { create(:ci_runner, description: 'Stale runner 1', created_at: 3.months.ago) }
let_it_be(:never_contacted_instance_runner) { create(:ci_runner, description: 'Missing runner 1', created_at: 1.month.ago, contacted_at: nil) }
@@ -279,21 +308,51 @@ RSpec.describe 'Query.runner(id)' do
let!(:job) { create(:ci_build, runner: project_runner1) }
- context 'requesting project and job counts' do
+ context 'requesting projects and counts for projects and jobs' do
+ let(:jobs_fragment) do
+ %(
+ jobs {
+ count
+ nodes {
+ id
+ status
+ }
+ }
+ )
+ end
+
let(:query) do
%(
query {
projectRunner1: runner(id: "#{project_runner1.to_global_id}") {
projectCount
jobCount
+ #{jobs_fragment}
+ projects {
+ nodes {
+ id
+ }
+ }
}
projectRunner2: runner(id: "#{project_runner2.to_global_id}") {
projectCount
jobCount
+ #{jobs_fragment}
+ projects {
+ nodes {
+ id
+ }
+ }
}
activeInstanceRunner: runner(id: "#{active_instance_runner.to_global_id}") {
projectCount
jobCount
+ #{jobs_fragment}
+ projects {
+ nodes {
+ id
+ }
+ }
}
}
)
@@ -312,13 +371,29 @@ RSpec.describe 'Query.runner(id)' do
expect(runner1_data).to match a_hash_including(
'jobCount' => 1,
- 'projectCount' => 2)
+ 'jobs' => a_hash_including(
+ "count" => 1,
+ "nodes" => [{ "id" => job.to_global_id.to_s, "status" => job.status.upcase }]
+ ),
+ 'projectCount' => 2,
+ 'projects' => {
+ 'nodes' => [
+ { 'id' => project1.to_global_id.to_s },
+ { 'id' => project2.to_global_id.to_s }
+ ]
+ })
expect(runner2_data).to match a_hash_including(
'jobCount' => 0,
- 'projectCount' => 0)
+ 'jobs' => nil, # returning jobs not allowed for more than 1 runner (see RunnerJobsResolver)
+ 'projectCount' => 0,
+ 'projects' => {
+ 'nodes' => []
+ })
expect(runner3_data).to match a_hash_including(
'jobCount' => 0,
- 'projectCount' => nil)
+ 'jobs' => nil, # returning jobs not allowed for more than 1 runner (see RunnerJobsResolver)
+ 'projectCount' => nil,
+ 'projects' => nil)
end
end
end
@@ -326,7 +401,17 @@ RSpec.describe 'Query.runner(id)' do
describe 'by regular user' do
let(:user) { create(:user) }
- it_behaves_like 'retrieval by unauthorized user', :active_instance_runner
+ context 'on instance runner' do
+ it_behaves_like 'retrieval by unauthorized user', :active_instance_runner
+ end
+
+ context 'on group runner' do
+ it_behaves_like 'retrieval by unauthorized user', :active_group_runner
+ end
+
+ context 'on project runner' do
+ it_behaves_like 'retrieval by unauthorized user', :active_project_runner
+ end
end
describe 'by non-admin user' do
diff --git a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
index 802ab847b3d..35a70a180a2 100644
--- a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
+++ b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'container repository details' do
)
end
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:variables) { {} }
let(:tags) { %w[latest tag1 tag2 tag3 tag4 tag5] }
let(:container_repository_global_id) { container_repository.to_global_id.to_s }
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index 8bbeae97f57..e80f5e0e0ff 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -166,7 +166,7 @@ RSpec.describe 'GitlabSchema configurations' do
end
context 'authentication' do
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
it 'authenticates all queries' do
subject
@@ -216,7 +216,7 @@ RSpec.describe 'GitlabSchema configurations' do
context "global id's" do
it 'uses GlobalID to expose ids' do
post_graphql(graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id)),
- current_user: project.owner)
+ current_user: project.first_owner)
parsed_id = GlobalID.parse(graphql_data['project']['id'])
diff --git a/spec/requests/api/graphql/group/recent_issue_boards_query_spec.rb b/spec/requests/api/graphql/group/recent_issue_boards_query_spec.rb
new file mode 100644
index 00000000000..4914beec870
--- /dev/null
+++ b/spec/requests/api/graphql/group/recent_issue_boards_query_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting group recent issue boards' do
+ include GraphqlHelpers
+
+ it_behaves_like 'querying a GraphQL type recent boards' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent) { create(:group, :public) }
+ let_it_be(:board) { create(:board, resource_parent: parent, name: 'test group board') }
+ let(:board_type) { 'group' }
+ end
+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 05f6804a208..30e7f196542 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
@@ -45,7 +45,7 @@ RSpec.describe 'CiCdSettingsUpdate' do
end
context 'when authorized' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
it 'updates ci cd settings' do
post_graphql_mutation(mutation, current_user: user)
diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
index b53a7ddde32..5269c60b50a 100644
--- a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'CiJobTokenScopeAddProject' do
end
context 'when authorized' do
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
before do
target_project.add_developer(current_user)
diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
index f1f42b00ada..b62291d1ebd 100644
--- a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe 'CiJobTokenScopeRemoveProject' do
end
context 'when authorized' do
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
before do
target_project.add_guest(current_user)
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
index 08959d354e2..37656ab4eea 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'PipelineDestroy' do
include GraphqlHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project, user: user) }
let(:mutation) do
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
index 322706be119..12368e7e9c5 100644
--- 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
@@ -71,7 +71,7 @@ RSpec.describe 'RunnersRegistrationTokenReset' do
end
include_context 'when authorized', 'project' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
def get_token
project.reload.runners_token
diff --git a/spec/requests/api/graphql/mutations/issues/create_spec.rb b/spec/requests/api/graphql/mutations/issues/create_spec.rb
index 6baed352b37..3d81b456c9c 100644
--- a/spec/requests/api/graphql/mutations/issues/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/create_spec.rb
@@ -52,5 +52,22 @@ RSpec.describe 'Create an issue' do
it_behaves_like 'has spam protection' do
let(:mutation_class) { ::Mutations::Issues::Create }
end
+
+ context 'when position params are provided' do
+ let(:existing_issue) { create(:issue, project: project, relative_position: 50) }
+
+ before do
+ input.merge!(
+ move_after_id: existing_issue.to_global_id.to_s
+ )
+ end
+
+ it 'sets the correct position' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['issue']['relativePosition']).to be < existing_issue.relative_position
+ end
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
index 929609d4160..0c034f38dc8 100644
--- a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
+++ b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'ConfigureSastIac' do
let(:mutation_response) { graphql_mutation_response(:configureSastIac) }
context 'when authorized' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
it 'creates a branch with sast iac configured' do
post_graphql_mutation(mutation, current_user: user)
diff --git a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb
index 23a154b71a0..8fa6e44b208 100644
--- a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb
+++ b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'ConfigureSecretDetection' do
let(:mutation_response) { graphql_mutation_response(:configureSecretDetection) }
context 'when authorized' do
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
it 'creates a branch with secret detection configured' do
post_graphql_mutation(mutation, current_user: user)
diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
new file mode 100644
index 00000000000..e1c7fd9d60d
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::UserPreferences::Update do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+
+ let(:sort_value) { 'TITLE_ASC' }
+
+ let(:input) do
+ {
+ 'issuesSort' => sort_value
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:userPreferencesUpdate, input) }
+ let(:mutation_response) { graphql_mutation_response(:userPreferencesUpdate) }
+
+ context 'when user has no existing preference' do
+ it 'creates the user preference record' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['userPreferences']['issuesSort']).to eq(sort_value)
+
+ expect(current_user.user_preference.persisted?).to eq(true)
+ expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s)
+ end
+ end
+
+ context 'when user has existing preference' do
+ before do
+ current_user.create_user_preference!(issues_sort: Types::IssueSortEnum.values['TITLE_DESC'].value)
+ end
+
+ it 'updates the existing value' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ current_user.user_preference.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['userPreferences']['issuesSort']).to eq(sort_value)
+
+ expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
index e7a0c7753fb..6abdaa2c850 100644
--- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
@@ -47,6 +47,18 @@ RSpec.describe 'Create a work item' do
)
end
+ context 'when input is invalid' do
+ let(:input) { { 'title' => '', 'workItemTypeId' => WorkItems::Type.default_by_type(:task).to_global_id.to_s } }
+
+ it 'does not create and returns validation errors' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to not_change(WorkItem, :count)
+
+ expect(graphql_mutation_response(:work_item_create)['errors']).to contain_exactly("Title can't be blank")
+ end
+ end
+
it_behaves_like 'has spam protection' do
let(:mutation_class) { ::Mutations::WorkItems::Create }
end
@@ -56,8 +68,13 @@ RSpec.describe 'Create a work item' do
stub_feature_flags(work_items: false)
end
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ["Field 'workItemCreate' doesn't exist on type 'Mutation'", "Variable $workItemCreateInput is declared by anonymous mutation but not used"]
+ it 'does not create the work item and returns an error' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to not_change(WorkItem, :count)
+
+ expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
end
end
end
diff --git a/spec/requests/api/graphql/mutations/work_items/delete_spec.rb b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb
new file mode 100644
index 00000000000..14c8b757a57
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Delete a work item' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+
+ let(:current_user) { developer }
+ let(:mutation) { graphql_mutation(:workItemDelete, { 'id' => work_item.to_global_id.to_s }) }
+ let(:mutation_response) { graphql_mutation_response(:work_item_delete) }
+
+ context 'when the user is not allowed to delete a work item' do
+ let(:work_item) { create(:work_item, project: project) }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to delete a work item' do
+ let_it_be(:authored_work_item, refind: true) { create(:work_item, project: project, author: developer, assignees: [developer]) }
+
+ let(:work_item) { authored_work_item }
+
+ it 'deletes the work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change(WorkItem, :count).by(-1)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['project']).to include('id' => work_item.project.to_global_id.to_s)
+ end
+
+ context 'when the work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not delete the work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to not_change(WorkItem, :count)
+
+ expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
new file mode 100644
index 00000000000..71b03103115
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Update a work item' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+ let_it_be(:work_item, refind: true) { create(:work_item, project: project) }
+
+ let(:work_item_event) { 'CLOSE' }
+ let(:input) { { 'stateEvent' => work_item_event, 'title' => 'updated title' } }
+
+ let(:mutation) { graphql_mutation(:workItemUpdate, input.merge('id' => work_item.to_global_id.to_s)) }
+
+ let(:mutation_response) { graphql_mutation_response(:work_item_update) }
+
+ context 'the user is not allowed to update a work item' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to update a work item' do
+ let(:current_user) { developer }
+
+ context 'when the work item is open' do
+ it 'closes and updates the work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :state).from('opened').to('closed').and(
+ change(work_item, :title).from(work_item.title).to('updated title')
+ )
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']).to include(
+ 'state' => 'CLOSED',
+ 'title' => 'updated title'
+ )
+ end
+ end
+
+ context 'when the work item is closed' do
+ let(:work_item_event) { 'REOPEN' }
+
+ before do
+ work_item.close!
+ end
+
+ it 'reopens the work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :state).from('closed').to('opened')
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']).to include(
+ 'state' => 'OPEN'
+ )
+ end
+ end
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::WorkItems::Update }
+ end
+
+ context 'when the work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not update the work item and returns and error' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to not_change(work_item, :title)
+
+ expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 2ff3bc7cc47..365efc514d4 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -102,18 +102,6 @@ RSpec.describe 'package details' do
expect(package_file_ids).to contain_exactly(package_file.to_global_id.to_s)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- subject
-
- expect(package_file_ids).to contain_exactly(package_file_pending_destruction.to_global_id.to_s, package_file.to_global_id.to_s)
- end
- end
end
context 'with a batched query' do
@@ -145,8 +133,9 @@ RSpec.describe 'package details' do
let(:pipeline_gids) { pipelines.sort_by(&:id).map(&:to_gid).map(&:to_s).reverse }
before do
- composer_package.pipelines = pipelines
- composer_package.save!
+ pipelines.each do |pipeline|
+ create(:package_build_info, package: composer_package, pipeline: pipeline)
+ end
end
def run_query(args)
diff --git a/spec/requests/api/graphql/project/container_expiration_policy_spec.rb b/spec/requests/api/graphql/project/container_expiration_policy_spec.rb
index dc16847a669..e3ea9e46353 100644
--- a/spec/requests/api/graphql/project/container_expiration_policy_spec.rb
+++ b/spec/requests/api/graphql/project/container_expiration_policy_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'getting a repository in a project' do
include GraphqlHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let_it_be(:container_expiration_policy) { project.container_expiration_policy }
let(:fields) do
diff --git a/spec/requests/api/graphql/project/container_repositories_spec.rb b/spec/requests/api/graphql/project/container_repositories_spec.rb
index 692143b2215..bbab6012f3f 100644
--- a/spec/requests/api/graphql/project/container_repositories_spec.rb
+++ b/spec/requests/api/graphql/project/container_repositories_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'getting container repositories in a project' do
)
end
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:variables) { {} }
let(:container_repositories_response) { graphql_data.dig('project', 'containerRepositories', 'edges') }
let(:container_repositories_count_response) { graphql_data.dig('project', 'containerRepositoriesCount') }
diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
index 40a3281d3b7..2b85704f479 100644
--- a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
+++ b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'getting a detailed sentry error' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:project_setting) { create(:project_error_tracking_setting, project: project) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let_it_be(:sentry_detailed_error) { build(:error_tracking_sentry_detailed_error) }
let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s }
diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
index a540386a9de..3ca0e35882a 100644
--- a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
+++ b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'sentry errors requests' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:project_setting) { create(:project_error_tracking_setting, project: project) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let(:query) do
graphql_query_for(
diff --git a/spec/requests/api/graphql/project/grafana_integration_spec.rb b/spec/requests/api/graphql/project/grafana_integration_spec.rb
index 9b24698f40c..e7534945e7a 100644
--- a/spec/requests/api/graphql/project/grafana_integration_spec.rb
+++ b/spec/requests/api/graphql/project/grafana_integration_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'Getting Grafana Integration' do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
let(:fields) do
diff --git a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
index 9d98498ca8a..46fd65db1c5 100644
--- a/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
+++ b/spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Getting versions related to an issue' do
create(:design_version, issue: issue)
end
- let_it_be(:owner) { issue.project.owner }
+ let_it_be(:owner) { issue.project.first_owner }
def version_query(params = version_params)
query_graphql_field(:versions, params, version_query_fields)
diff --git a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
index def41efddde..f0205319983 100644
--- a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Getting designs related to an issue' do
include DesignManagementTestHelpers
let_it_be(:design) { create(:design, :with_smaller_image_versions, versions_count: 1) }
- let_it_be(:current_user) { design.project.owner }
+ let_it_be(:current_user) { design.project.first_owner }
let(:design_query) do
<<~NODE
diff --git a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
index 7148750b6cb..de2ace95757 100644
--- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Getting designs related to an issue' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design) { create(:design, :with_file, versions_count: 1, issue: issue) }
- let_it_be(:current_user) { project.owner }
+ let_it_be(:current_user) { project.first_owner }
let_it_be(:note) { create(:diff_note_on_design, noteable: design, project: project) }
before do
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index b0bedd99fce..303748bc70e 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -29,6 +29,10 @@ RSpec.describe 'getting merge request listings nested in a project' do
create(:merge_request, :unique_branches, source_project: project)
end
+ let(:all_merge_requests) do
+ [merge_request_a, merge_request_b, merge_request_c, merge_request_d, merge_request_e]
+ end
+
let(:results) { graphql_data.dig('project', 'mergeRequests', 'nodes') }
let(:search_params) { nil }
@@ -180,6 +184,39 @@ RSpec.describe 'getting merge request listings nested in a project' do
it_behaves_like 'when searching with parameters'
end
+ context 'when searching by update time' do
+ let(:start_time) { 10.days.ago }
+ let(:cutoff) { start_time + 36.hours }
+
+ before do
+ all_merge_requests.each_with_index do |mr, i|
+ mr.updated_at = start_time + i.days
+ mr.save!(touch: false)
+ end
+ end
+
+ context 'when searching by updated_after' do
+ let(:search_params) { { updated_after: cutoff } }
+ let(:mrs) { all_merge_requests[2..] }
+
+ it_behaves_like 'when searching with parameters'
+ end
+
+ context 'when searching by updated_before' do
+ let(:search_params) { { updated_before: cutoff } }
+ let(:mrs) { all_merge_requests[0..1] }
+
+ it_behaves_like 'when searching with parameters'
+ end
+
+ context 'when searching by updated_before and updated_after' do
+ let(:search_params) { { updated_after: cutoff, updated_before: cutoff + 2.days } }
+ let(:mrs) { all_merge_requests[2..3] }
+
+ it_behaves_like 'when searching with parameters'
+ end
+ end
+
context 'when searching by combination' do
let(:search_params) { { state: :closed, labels: [label.title] } }
let(:mrs) { [merge_request_c] }
diff --git a/spec/requests/api/graphql/project/project_members_spec.rb b/spec/requests/api/graphql/project/project_members_spec.rb
index 466464f600c..315d44884ff 100644
--- a/spec/requests/api/graphql/project/project_members_spec.rb
+++ b/spec/requests/api/graphql/project/project_members_spec.rb
@@ -110,6 +110,102 @@ RSpec.describe 'getting project members information' do
end
end
+ context 'merge request interactions' do
+ let(:project_path) { var('ID!').with(parent_project.full_path) }
+ let(:mr_a) do
+ var('MergeRequestID!')
+ .with(global_id_of(create(:merge_request, source_project: parent_project, source_branch: 'branch-1')))
+ end
+
+ let(:mr_b) do
+ var('MergeRequestID!')
+ .with(global_id_of(create(:merge_request, source_project: parent_project, source_branch: 'branch-2')))
+ end
+
+ let(:interaction_query) do
+ <<~HEREDOC
+ edges {
+ node {
+ user {
+ id
+ }
+ mrA: #{query_graphql_field(:merge_request_interaction, { id: mr_a }, 'canMerge')}
+ }
+ }
+ HEREDOC
+ end
+
+ let(:interaction_b_query) do
+ <<~HEREDOC
+ edges {
+ node {
+ user {
+ id
+ }
+ mrA: #{query_graphql_field(:merge_request_interaction, { id: mr_a }, 'canMerge')}
+ mrB: #{query_graphql_field(:merge_request_interaction, { id: mr_b }, 'canMerge')}
+ }
+ }
+ HEREDOC
+ end
+
+ it 'avoids N+1 queries, when requesting multiple MRs' do
+ control_query = with_signature(
+ [project_path, mr_a],
+ graphql_query_for(:project, { full_path: project_path },
+ query_graphql_field(:project_members, nil, interaction_query))
+ )
+ query_two = with_signature(
+ [project_path, mr_a, mr_b],
+ graphql_query_for(:project, { full_path: project_path },
+ query_graphql_field(:project_members, nil, interaction_b_query))
+ )
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(control_query, current_user: user, variables: [project_path, mr_a])
+ end
+
+ # two project members, neither of whom can merge
+ expect(can_merge(:mrA)).to eq [false, false]
+
+ expect do
+ post_graphql(query_two, current_user: user, variables: [project_path, mr_a, mr_b])
+
+ expect(can_merge(:mrA)).to eq [false, false]
+ expect(can_merge(:mrB)).to eq [false, false]
+ end.not_to exceed_query_limit(control_count)
+ end
+
+ it 'avoids N+1 queries, when more users are involved' do
+ new_user = create(:user)
+
+ query = with_signature(
+ [project_path, mr_a],
+ graphql_query_for(:project, { full_path: project_path },
+ query_graphql_field(:project_members, nil, interaction_query))
+ )
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: user, variables: [project_path, mr_a])
+ end
+
+ # two project members, neither of whom can merge
+ expect(can_merge(:mrA)).to eq [false, false]
+
+ parent_project.add_guest(new_user)
+
+ expect do
+ post_graphql(query, current_user: user, variables: [project_path, mr_a])
+
+ expect(can_merge(:mrA)).to eq [false, false, false]
+ end.not_to exceed_query_limit(control_count)
+ end
+
+ def can_merge(name)
+ graphql_data_at(:project, :project_members, :edges, :node, name, :can_merge)
+ end
+ end
+
context 'when unauthenticated' do
it 'returns members' do
fetch_members(current_user: nil, project: parent_project)
diff --git a/spec/requests/api/graphql/project/recent_issue_boards_query_spec.rb b/spec/requests/api/graphql/project/recent_issue_boards_query_spec.rb
new file mode 100644
index 00000000000..b3daf86c4af
--- /dev/null
+++ b/spec/requests/api/graphql/project/recent_issue_boards_query_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting project recent issue boards' do
+ include GraphqlHelpers
+
+ it_behaves_like 'querying a GraphQL type recent boards' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent) { create(:project, :public, namespace: user.namespace) }
+ let_it_be(:board) { create(:board, resource_parent: parent, name: 'test project board') }
+ let(:board_type) { 'project' }
+ end
+end
diff --git a/spec/requests/api/graphql/project/repository/blobs_spec.rb b/spec/requests/api/graphql/project/repository/blobs_spec.rb
index 12f6fbd793e..ba87f1100f2 100644
--- a/spec/requests/api/graphql/project/repository/blobs_spec.rb
+++ b/spec/requests/api/graphql/project/repository/blobs_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'getting blobs in a project repository' do
include GraphqlHelpers
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:paths) { ["CONTRIBUTING.md", "README.md"] }
let(:ref) { project.default_branch }
let(:fields) do
diff --git a/spec/requests/api/graphql/project/repository_spec.rb b/spec/requests/api/graphql/project/repository_spec.rb
index 8810f2fa3d5..b00f64c3db6 100644
--- a/spec/requests/api/graphql/project/repository_spec.rb
+++ b/spec/requests/api/graphql/project/repository_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'getting a repository in a project' do
include GraphqlHelpers
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:fields) do
<<~QUERY
#{all_graphql_fields_for('repository'.classify)}
diff --git a/spec/requests/api/graphql/project/tree/tree_spec.rb b/spec/requests/api/graphql/project/tree/tree_spec.rb
index f4cd316da96..25e878a5b1a 100644
--- a/spec/requests/api/graphql/project/tree/tree_spec.rb
+++ b/spec/requests/api/graphql/project/tree/tree_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'getting a tree in a project' do
include GraphqlHelpers
let(:project) { create(:project, :repository) }
- let(:current_user) { project.owner }
+ let(:current_user) { project.first_owner }
let(:path) { "" }
let(:ref) { "master" }
let(:fields) do
diff --git a/spec/requests/api/group_clusters_spec.rb b/spec/requests/api/group_clusters_spec.rb
index f65f9384efa..c48b5007f91 100644
--- a/spec/requests/api/group_clusters_spec.rb
+++ b/spec/requests/api/group_clusters_spec.rb
@@ -6,11 +6,11 @@ RSpec.describe API::GroupClusters do
include KubernetesHelpers
let(:current_user) { create(:user) }
- let(:developer_user) { create(:user) }
+ let(:unauthorized_user) { create(:user) }
let(:group) { create(:group, :private) }
before do
- group.add_developer(developer_user)
+ group.add_reporter(unauthorized_user)
group.add_maintainer(current_user)
end
@@ -24,7 +24,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
it 'responds with 403' do
- get api("/groups/#{group.id}/clusters", developer_user)
+ get api("/groups/#{group.id}/clusters", unauthorized_user)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -68,7 +68,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
it 'responds with 403' do
- get api("/groups/#{group.id}/clusters/#{cluster_id}", developer_user)
+ get api("/groups/#{group.id}/clusters/#{cluster_id}", unauthorized_user)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -183,7 +183,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
it 'responds with 403' do
- post api("/groups/#{group.id}/clusters/user", developer_user), params: cluster_params
+ post api("/groups/#{group.id}/clusters/user", unauthorized_user), params: cluster_params
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -290,7 +290,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
before do
- post api("/groups/#{group.id}/clusters/user", developer_user), params: cluster_params
+ post api("/groups/#{group.id}/clusters/user", unauthorized_user), params: cluster_params
end
it 'responds with 403' do
@@ -364,7 +364,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
it 'responds with 403' do
- put api("/groups/#{group.id}/clusters/#{cluster.id}", developer_user), params: update_params
+ put api("/groups/#{group.id}/clusters/#{cluster.id}", unauthorized_user), params: update_params
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -505,7 +505,7 @@ RSpec.describe API::GroupClusters do
context 'non-authorized user' do
it 'responds with 403' do
- delete api("/groups/#{group.id}/clusters/#{cluster.id}", developer_user), params: cluster_params
+ delete api("/groups/#{group.id}/clusters/#{cluster.id}", unauthorized_user), params: cluster_params
expect(response).to have_gitlab_http_status(:forbidden)
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 88c004345fc..7de3567dcdd 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -1163,17 +1163,33 @@ RSpec.describe API::Groups do
expect(json_response.length).to eq(3)
end
- it "returns projects including those in subgroups" do
- subgroup = create(:group, parent: group1)
- create(:project, group: subgroup)
- create(:project, group: subgroup)
+ context 'when include_subgroups is true' do
+ it "returns projects including those in subgroups" do
+ subgroup = create(:group, parent: group1)
+ create(:project, group: subgroup)
+ create(:project, group: subgroup)
- get api("/groups/#{group1.id}/projects", user1), params: { include_subgroups: true }
+ get api("/groups/#{group1.id}/projects", user1), params: { include_subgroups: true }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an(Array)
- expect(json_response.length).to eq(5)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(5)
+ end
+ end
+
+ context 'when include_ancestor_groups is true' do
+ it 'returns ancestors groups projects' do
+ subgroup = create(:group, parent: group1)
+ subgroup_project = create(:project, group: subgroup)
+
+ get api("/groups/#{subgroup.id}/projects", user1), params: { include_ancestor_groups: true }
+
+ records = Gitlab::Json.parse(response.body)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(records.map { |r| r['id'] }).to match_array([project1.id, project3.id, subgroup_project.id, archived_project.id])
+ end
end
it "does not return a non existing group" do
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 9aa8aaafc68..2b7963eadab 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -612,6 +612,30 @@ RSpec.describe API::Internal::Base do
expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-mep-mep' => 'false')
end
end
+
+ context "with a sidechannels enabled for a project" do
+ before do
+ stub_feature_flags(gitlab_shell_upload_pack_sidechannel: project)
+ end
+
+ it "has the use_sidechannel field set to true for that project" do
+ pull(key, project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response["gl_repository"]).to eq("project-#{project.id}")
+ expect(json_response["gitaly"]["use_sidechannel"]).to eq(true)
+ end
+
+ it "has the use_sidechannel field set to false for other projects" do
+ other_project = create(:project, :public, :repository)
+
+ pull(key, other_project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response["gl_repository"]).to eq("project-#{other_project.id}")
+ expect(json_response["gitaly"]["use_sidechannel"]).to eq(false)
+ end
+ end
end
context "git push" do
@@ -724,6 +748,30 @@ RSpec.describe API::Internal::Base do
end
end
+ context 'with a pending membership' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ before_all do
+ create(:project_member, :awaiting, :developer, source: project, user: user)
+ end
+
+ it 'returns not found for git pull' do
+ pull(key, project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response["status"]).to be_falsey
+ expect(user.reload.last_activity_on).to be_nil
+ end
+
+ it 'returns not found for git push' do
+ push(key, project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response["status"]).to be_falsey
+ expect(user.reload.last_activity_on).to be_nil
+ end
+ end
+
context "custom action" do
let(:access_checker) { double(Gitlab::GitAccess) }
let(:payload) do
diff --git a/spec/requests/api/internal/container_registry/migration_spec.rb b/spec/requests/api/internal/container_registry/migration_spec.rb
new file mode 100644
index 00000000000..27e99a21c65
--- /dev/null
+++ b/spec/requests/api/internal/container_registry/migration_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Internal::ContainerRegistry::Migration do
+ let_it_be_with_reload(:repository) { create(:container_repository) }
+
+ let(:secret_token) { 'secret_token' }
+ let(:sent_token) { secret_token }
+ let(:repository_path) { repository.path }
+ let(:status) { 'pre_import_complete' }
+ let(:params) { { path: repository.path, status: status } }
+
+ before do
+ allow(Gitlab.config.registry).to receive(:notification_secret) { secret_token }
+ end
+
+ describe 'PUT /internal/registry/repositories/:path/migration/status' do
+ subject do
+ put api("/internal/registry/repositories/#{repository_path}/migration/status"),
+ params: params,
+ headers: { 'Authorization' => sent_token }
+ end
+
+ shared_examples 'returning an error' do |with_message: nil, returning_status: :bad_request|
+ it "returns bad request response" do
+ expect { subject }
+ .not_to change { repository.reload.migration_state }
+
+ expect(response).to have_gitlab_http_status(returning_status)
+ expect(response.body).to include(with_message) if with_message
+ end
+ end
+
+ context 'with a valid sent token' do
+ shared_examples 'updating the repository migration status' do |from:, to:|
+ it "updates the migration status from #{from} to #{to}" do
+ expect { subject }
+ .to change { repository.reload.migration_state }.from(from).to(to)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with status pre_import_complete' do
+ let(:status) { 'pre_import_complete' }
+
+ it_behaves_like 'returning an error', with_message: 'Wrong migration state (default)'
+
+ context 'with repository in pre_importing migration state' do
+ let(:repository) { create(:container_repository, :pre_importing) }
+
+ before do
+ allow_next_found_instance_of(ContainerRepository) do |found_repository|
+ allow(found_repository).to receive(:migration_import).and_return(:ok)
+ end
+ end
+
+ it_behaves_like 'updating the repository migration status', from: 'pre_importing', to: 'importing'
+
+ context 'with a failing transition' do
+ before do
+ allow_next_found_instance_of(ContainerRepository) do |found_repository|
+ allow(found_repository).to receive(:finish_pre_import_and_start_import).and_return(false)
+ end
+ end
+
+ it_behaves_like 'returning an error', with_message: "Couldn't transition from pre_importing to importing"
+ end
+ end
+
+ context 'with repository in importing migration state' do
+ let(:repository) { create(:container_repository, :importing) }
+
+ it_behaves_like 'returning an error', with_message: "Couldn't transition from pre_importing to importing"
+ end
+ end
+
+ context 'with status import_complete' do
+ let(:status) { 'import_complete' }
+
+ it_behaves_like 'returning an error', with_message: 'Wrong migration state (default)'
+
+ context 'with repository in importing migration state' do
+ let(:repository) { create(:container_repository, :importing) }
+ let(:transition_result) { true }
+
+ it_behaves_like 'updating the repository migration status', from: 'importing', to: 'import_done'
+
+ context 'with a failing transition' do
+ before do
+ allow_next_found_instance_of(ContainerRepository) do |found_repository|
+ allow(found_repository).to receive(:finish_import).and_return(false)
+ end
+ end
+
+ it_behaves_like 'returning an error', with_message: "Couldn't transition from importing to import_done"
+ end
+ end
+
+ context 'with repository in pre_importing migration state' do
+ let(:repository) { create(:container_repository, :pre_importing) }
+
+ it_behaves_like 'returning an error', with_message: "Couldn't transition from importing to import_done"
+ end
+ end
+
+ %w[pre_import_failed import_failed].each do |status|
+ context 'with status pre_import_failed' do
+ let(:status) { 'pre_import_failed' }
+
+ it_behaves_like 'returning an error', with_message: 'Wrong migration state (default)'
+
+ context 'with repository in importing migration state' do
+ let(:repository) { create(:container_repository, :importing) }
+
+ it_behaves_like 'updating the repository migration status', from: 'importing', to: 'import_aborted'
+ end
+
+ context 'with repository in pre_importing migration state' do
+ let(:repository) { create(:container_repository, :pre_importing) }
+
+ it_behaves_like 'updating the repository migration status', from: 'pre_importing', to: 'import_aborted'
+ end
+ end
+ end
+
+ context 'with a non existing path' do
+ let(:repository_path) { 'this/does/not/exist' }
+
+ it_behaves_like 'returning an error', returning_status: :not_found
+ end
+
+ context 'with invalid status' do
+ let(:params) { super().merge(status: nil).compact }
+
+ it_behaves_like 'returning an error', returning_status: :bad_request
+ end
+
+ context 'with invalid path' do
+ let(:repository_path) { nil }
+
+ it_behaves_like 'returning an error', returning_status: :not_found
+ end
+ end
+
+ context 'with an invalid sent token' do
+ let(:sent_token) { 'not_valid' }
+
+ it_behaves_like 'returning an error', returning_status: :unauthorized
+ end
+ end
+end
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index 9204ee4d7f0..c5e57b5b18b 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -488,6 +488,8 @@ RSpec.describe API::Issues do
let_it_be(:issue3) { create(:issue, project: project, author: user, due_date: frozen_time + 10.days) }
let_it_be(:issue4) { create(:issue, project: project, author: user, due_date: frozen_time + 34.days) }
let_it_be(:issue5) { create(:issue, project: project, author: user, due_date: frozen_time - 8.days) }
+ let_it_be(:issue6) { create(:issue, project: project, author: user, due_date: frozen_time) }
+ let_it_be(:issue7) { create(:issue, project: project, author: user, due_date: frozen_time + 1.day) }
before do
travel_to(frozen_time)
@@ -500,7 +502,13 @@ RSpec.describe API::Issues do
it 'returns them all when argument is empty' do
get api('/issues?due_date=', user)
- expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id)
+ end
+
+ it 'returns issues with due date' do
+ get api('/issues?due_date=any', user)
+
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
end
it 'returns issues without due date' do
@@ -512,19 +520,31 @@ RSpec.describe API::Issues do
it 'returns issues due for this week' do
get api('/issues?due_date=week', user)
- expect_paginated_array_response(issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue2.id)
end
it 'returns issues due for this month' do
get api('/issues?due_date=month', user)
- expect_paginated_array_response(issue3.id, issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue3.id, issue2.id)
end
it 'returns issues that are due previous two weeks and next month' do
get api('/issues?due_date=next_month_and_previous_two_weeks', user)
- expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
+ end
+
+ it 'returns issues that are due today' do
+ get api('/issues?due_date=today', user)
+
+ expect_paginated_array_response(issue6.id)
+ end
+
+ it 'returns issues that are due tomorrow' do
+ get api('/issues?due_date=tomorrow', user)
+
+ expect_paginated_array_response(issue7.id)
end
it 'returns issues that are overdue' do
@@ -1164,14 +1184,15 @@ RSpec.describe API::Issues do
end
describe 'PUT /projects/:id/issues/:issue_iid/reorder' do
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:issue1) { create(:issue, project: project, relative_position: 10) }
let_it_be(:issue2) { create(:issue, project: project, relative_position: 20) }
let_it_be(:issue3) { create(:issue, project: project, relative_position: 30) }
context 'when user has access' do
- before do
- project.add_developer(user)
+ before_all do
+ group.add_developer(user)
end
context 'with valid params' do
@@ -1197,6 +1218,19 @@ RSpec.describe API::Issues do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'with issue in different project' do
+ let(:other_project) { create(:project, group: group) }
+ let(:other_issue) { create(:issue, project: other_project, relative_position: 80) }
+
+ it 'reorders issues and returns a successful 200 response' do
+ put api("/projects/#{other_project.id}/issues/#{other_issue.iid}/reorder", user), params: { move_after_id: issue2.id, move_before_id: issue3.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(other_issue.reload.relative_position)
+ .to be_between(issue2.reload.relative_position, issue3.reload.relative_position)
+ end
+ end
end
context 'with unauthorized user' do
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index 7c1e731a99a..73bc4a5d1f3 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe API::Lint do
context 'when authenticated' do
let_it_be(:api_user) { create(:user) }
- context 'with valid .gitlab-ci.yaml content' do
+ context 'with valid .gitlab-ci.yml content' do
let(:yaml_content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
end
@@ -140,7 +140,7 @@ RSpec.describe API::Lint do
end
end
- context 'with valid .gitlab-ci.yaml with warnings' do
+ context 'with valid .gitlab-ci.yml with warnings' do
let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
it 'passes validation but returns warnings' do
@@ -153,8 +153,8 @@ RSpec.describe API::Lint do
end
end
- context 'with valid .gitlab-ci.yaml using deprecated keywords' do
- let(:yaml_content) { { job: { script: 'ls' }, types: ['test'] }.to_yaml }
+ context 'with valid .gitlab-ci.yml using deprecated keywords' do
+ let(:yaml_content) { { job: { script: 'ls', type: 'test' }, types: ['test'] }.to_yaml }
it 'passes validation but returns warnings' do
post api('/ci/lint', api_user), params: { content: yaml_content }
@@ -166,7 +166,7 @@ RSpec.describe API::Lint do
end
end
- context 'with an invalid .gitlab_ci.yml' do
+ context 'with an invalid .gitlab-ci.yml' do
context 'with invalid syntax' do
let(:yaml_content) { 'invalid content' }
@@ -384,6 +384,15 @@ RSpec.describe API::Lint do
project.add_developer(api_user)
end
+ context 'with no commit' do
+ it 'returns error about providing content' do
+ ci_lint
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['errors']).to match_array(['Please provide content of .gitlab-ci.yml'])
+ end
+ end
+
context 'with valid .gitlab-ci.yml content' do
let(:yaml_content) do
{ include: { local: 'another-gitlab-ci.yml' }, test: { stage: 'test', script: 'echo 1' } }.to_yaml
diff --git a/spec/requests/api/markdown_spec.rb b/spec/requests/api/markdown_spec.rb
index faf671d350f..0488bce4663 100644
--- a/spec/requests/api/markdown_spec.rb
+++ b/spec/requests/api/markdown_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe API::Markdown do
end
context "when authorized" do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it_behaves_like "rendered markdown text without GFM"
end
@@ -97,7 +97,7 @@ RSpec.describe API::Markdown do
context "with project" do
let(:params) { { text: text, gfm: true, project: project.full_path } }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it "renders markdown text" do
expect(response).to have_gitlab_http_status(:created)
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 02061bb8ab6..6186a43f992 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -416,6 +416,8 @@ RSpec.describe API::Members do
end
it "returns 409 if member already exists" do
+ source.add_guest(stranger)
+
post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
params: { user_id: maintainer.id, access_level: Member::MAINTAINER }
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index a751f785913..9e6fea9e5b4 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -436,6 +436,26 @@ RSpec.describe API::MergeRequests do
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort)
end
+
+ context 'returns an array of merge_requests ordered by title' do
+ it 'asc when requested' do
+ path = endpoint_path + '?order_by=title&sort=asc'
+
+ get api(path, user)
+
+ response_titles = json_response.map { |merge_request| merge_request['title'] }
+ expect(response_titles).to eq(response_titles.sort)
+ end
+
+ it 'desc when requested' do
+ path = endpoint_path + '?order_by=title&sort=desc'
+
+ get api(path, user)
+
+ response_titles = json_response.map { |merge_request| merge_request['title'] }
+ expect(response_titles).to eq(response_titles.sort.reverse)
+ end
+ end
end
context 'NOT params' do
@@ -985,14 +1005,6 @@ RSpec.describe API::MergeRequests do
it_behaves_like 'merge requests list'
- context 'when :api_caching_merge_requests is disabled' do
- before do
- stub_feature_flags(api_caching_merge_requests: false)
- end
-
- it_behaves_like 'merge requests list'
- end
-
it "returns 404 for non public projects" do
project = create(:project, :private)
@@ -2876,7 +2888,7 @@ RSpec.describe API::MergeRequests do
it 'is false for an unauthorized user' do
expect do
- put api("/projects/#{target_project.id}/merge_requests/#{merge_request.iid}", target_project.owner), params: { state_event: 'close', remove_source_branch: true }
+ put api("/projects/#{target_project.id}/merge_requests/#{merge_request.iid}", target_project.first_owner), params: { state_event: 'close', remove_source_branch: true }
end.not_to change { merge_request.reload.merge_params }
expect(response).to have_gitlab_http_status(:ok)
@@ -3324,6 +3336,18 @@ RSpec.describe API::MergeRequests do
end
end
+ context 'when merge request branch does not allow force push' do
+ before do
+ create(:protected_branch, project: project, name: merge_request.source_branch, allow_force_push: false)
+ end
+
+ it 'returns 403' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
it 'returns 403 if the user cannot push to the branch' do
guest = create(:user)
project.add_guest(guest)
diff --git a/spec/requests/api/package_files_spec.rb b/spec/requests/api/package_files_spec.rb
index a7e6a97fd0e..01c7ef1476f 100644
--- a/spec/requests/api/package_files_spec.rb
+++ b/spec/requests/api/package_files_spec.rb
@@ -87,18 +87,6 @@ RSpec.describe API::PackageFiles do
expect(package_file_ids).not_to include(package_file_pending_destruction.id)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- get api(url, user)
-
- expect(package_file_ids).to include(package_file_pending_destruction.id)
- end
- end
end
end
end
@@ -186,18 +174,6 @@ RSpec.describe API::PackageFiles do
expect(response).to have_gitlab_http_status(:not_found)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'can be accessed', :aggregate_failures do
- expect { api_request }.not_to change { package.package_files.pending_destruction.count }
-
- expect(response).to have_gitlab_http_status(:no_content)
- end
- end
end
end
end
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index 01d2fb18f00..8a6e87944ec 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -121,7 +121,6 @@ project_feature:
- created_at
- metrics_dashboard_access_level
- project_id
- - requirements_access_level
- security_and_compliance_access_level
- updated_at
computed_attributes:
@@ -139,6 +138,7 @@ project_setting:
- has_confluence
- has_shimo
- has_vulnerabilities
+ - legacy_open_source_license_available
- prevent_merge_without_jira_issue
- warn_about_potentially_unwanted_characters
- previous_default_branch
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index 253b61e5865..b83b41a881a 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -5,13 +5,15 @@ require 'spec_helper'
RSpec.describe API::ProjectClusters do
include KubernetesHelpers
- let_it_be(:current_user) { create(:user) }
+ let_it_be(:maintainer_user) { create(:user) }
let_it_be(:developer_user) { create(:user) }
+ let_it_be(:reporter_user) { create(:user) }
let_it_be(:project) { create(:project) }
before do
- project.add_maintainer(current_user)
+ project.add_maintainer(maintainer_user)
project.add_developer(developer_user)
+ project.add_reporter(reporter_user)
end
describe 'GET /projects/:id/clusters' do
@@ -24,7 +26,7 @@ RSpec.describe API::ProjectClusters do
context 'non-authorized user' do
it 'responds with 403' do
- get api("/projects/#{project.id}/clusters", developer_user)
+ get api("/projects/#{project.id}/clusters", reporter_user)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -32,7 +34,7 @@ RSpec.describe API::ProjectClusters do
context 'authorized user' do
before do
- get api("/projects/#{project.id}/clusters", current_user)
+ get api("/projects/#{project.id}/clusters", developer_user)
end
it 'includes pagination headers' do
@@ -61,13 +63,13 @@ RSpec.describe API::ProjectClusters do
let(:cluster) do
create(:cluster, :project, :provided_by_gcp, :with_domain,
platform_kubernetes: platform_kubernetes,
- user: current_user,
+ user: maintainer_user,
projects: [project])
end
context 'non-authorized user' do
it 'responds with 403' do
- get api("/projects/#{project.id}/clusters/#{cluster_id}", developer_user)
+ get api("/projects/#{project.id}/clusters/#{cluster_id}", reporter_user)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -75,7 +77,7 @@ RSpec.describe API::ProjectClusters do
context 'authorized user' do
before do
- get api("/projects/#{project.id}/clusters/#{cluster_id}", current_user)
+ get api("/projects/#{project.id}/clusters/#{cluster_id}", developer_user)
end
it 'returns specific cluster' do
@@ -111,8 +113,8 @@ RSpec.describe API::ProjectClusters do
it 'returns user information' do
user = json_response['user']
- expect(user['id']).to eq(current_user.id)
- expect(user['username']).to eq(current_user.username)
+ expect(user['id']).to eq(maintainer_user.id)
+ expect(user['username']).to eq(maintainer_user.username)
end
it 'returns GCP provider information' do
@@ -156,7 +158,7 @@ RSpec.describe API::ProjectClusters do
let(:management_project_id) { management_project.id }
before do
- management_project.add_maintainer(current_user)
+ management_project.add_maintainer(maintainer_user)
end
let(:platform_kubernetes_attributes) do
@@ -190,7 +192,7 @@ RSpec.describe API::ProjectClusters do
context 'authorized user' do
before do
- post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
+ post api("/projects/#{project.id}/clusters/user", maintainer_user), params: cluster_params
end
context 'with valid params' do
@@ -317,7 +319,7 @@ RSpec.describe API::ProjectClusters do
create(:cluster, :provided_by_gcp, :project,
projects: [project])
- post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
+ post api("/projects/#{project.id}/clusters/user", maintainer_user), params: cluster_params
end
it 'responds with 201' do
@@ -369,9 +371,9 @@ RSpec.describe API::ProjectClusters do
context 'authorized user' do
before do
- management_project.add_maintainer(current_user)
+ management_project.add_maintainer(maintainer_user)
- put api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: update_params
+ put api("/projects/#{project.id}/clusters/#{cluster.id}", maintainer_user), params: update_params
cluster.reload
end
@@ -501,7 +503,7 @@ RSpec.describe API::ProjectClusters do
context 'authorized user' do
before do
- delete api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: cluster_params
+ delete api("/projects/#{project.id}/clusters/#{cluster.id}", maintainer_user), params: cluster_params
end
it 'deletes the cluster' do
diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb
index b9c458373a8..2bc31153f2c 100644
--- a/spec/requests/api/project_export_spec.rb
+++ b/spec/requests/api/project_export_spec.rb
@@ -450,7 +450,7 @@ RSpec.describe API::ProjectExport, :clean_gitlab_redis_cache do
expect_next_instance_of(Projects::ImportExport::ExportService) do |service|
expect(service).to receive(:execute)
end
- post api(path, project.owner), params: params
+ post api(path, project.first_owner), params: params
expect(response).to have_gitlab_http_status(:accepted)
end
diff --git a/spec/requests/api/project_snapshots_spec.rb b/spec/requests/api/project_snapshots_spec.rb
index 33c86d56ed4..bf78ff56206 100644
--- a/spec/requests/api/project_snapshots_spec.rb
+++ b/spec/requests/api/project_snapshots_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe API::ProjectSnapshots do
end
it 'returns authentication error as project owner' do
- get api("/projects/#{project.id}/snapshot", project.owner)
+ get api("/projects/#{project.id}/snapshot", project.first_owner)
expect(response).to have_gitlab_http_status(:forbidden)
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index bf41a808219..02df82d14a8 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -30,7 +30,7 @@ RSpec.shared_examples 'languages and percentages JSON response' do
context 'when the languages were detected before' do
before do
- Projects::DetectRepositoryLanguagesService.new(project, project.owner).execute
+ Projects::DetectRepositoryLanguagesService.new(project, project.first_owner).execute
end
it 'returns the detection from the database' do
@@ -2166,6 +2166,7 @@ RSpec.describe API::Projects do
approvals_before_merge
compliance_frameworks
mirror
+ requirements_access_level
requirements_enabled
security_and_compliance_enabled
issues_template
@@ -2710,7 +2711,7 @@ RSpec.describe API::Projects do
it 'returns the project users' do
get api("/projects/#{project.id}/users", current_user)
- user = project.namespace.owner
+ user = project.namespace.first_owner
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 21a8622e08d..f42fc7aabc2 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -561,17 +561,6 @@ RSpec.describe API::Repositories do
let(:request) { get api(route, guest) }
end
end
-
- context 'api_caching_rate_limit_repository_compare is disabled' do
- before do
- stub_feature_flags(api_caching_rate_limit_repository_compare: false)
- end
-
- it_behaves_like 'repository compare' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
end
describe 'GET /projects/:id/repository/contributors' do
diff --git a/spec/requests/api/rubygem_packages_spec.rb b/spec/requests/api/rubygem_packages_spec.rb
index 0e63a7269e7..f0408d94137 100644
--- a/spec/requests/api/rubygem_packages_spec.rb
+++ b/spec/requests/api/rubygem_packages_spec.rb
@@ -187,19 +187,6 @@ RSpec.describe API::RubygemPackages do
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).not_to eq(package_file_pending_destruction.file.file.read)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(package_file_pending_destruction.file.file.read)
- end
- end
end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 7e940d52a41..f7048a1ca6b 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -32,6 +32,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['dsa_key_restriction']).to eq(0)
expect(json_response['ecdsa_key_restriction']).to eq(0)
expect(json_response['ed25519_key_restriction']).to eq(0)
+ expect(json_response['ecdsa_sk_key_restriction']).to eq(0)
+ expect(json_response['ed25519_sk_key_restriction']).to eq(0)
expect(json_response['performance_bar_allowed_group_id']).to be_nil
expect(json_response['allow_local_requests_from_hooks_and_services']).to be(false)
expect(json_response['allow_local_requests_from_web_hooks_and_services']).to be(false)
@@ -49,6 +51,9 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['whats_new_variant']).to eq('all_tiers')
expect(json_response['user_deactivation_emails_enabled']).to be(true)
expect(json_response['suggest_pipeline_enabled']).to be(true)
+ expect(json_response['runner_token_expiration_interval']).to be_nil
+ expect(json_response['group_runner_token_expiration_interval']).to be_nil
+ expect(json_response['project_runner_token_expiration_interval']).to be_nil
end
end
@@ -111,6 +116,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
dsa_key_restriction: 2048,
ecdsa_key_restriction: 384,
ed25519_key_restriction: 256,
+ ecdsa_sk_key_restriction: 256,
+ ed25519_sk_key_restriction: 256,
enforce_terms: true,
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
@@ -137,7 +144,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
personal_access_token_prefix: "GL-",
user_deactivation_emails_enabled: false,
admin_mode: true,
- suggest_pipeline_enabled: false
+ suggest_pipeline_enabled: false,
+ users_get_by_id_limit: 456
}
expect(response).to have_gitlab_http_status(:ok)
@@ -163,6 +171,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['dsa_key_restriction']).to eq(2048)
expect(json_response['ecdsa_key_restriction']).to eq(384)
expect(json_response['ed25519_key_restriction']).to eq(256)
+ expect(json_response['ecdsa_sk_key_restriction']).to eq(256)
+ expect(json_response['ed25519_sk_key_restriction']).to eq(256)
expect(json_response['enforce_terms']).to be(true)
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
@@ -190,6 +200,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['admin_mode']).to be(true)
expect(json_response['user_deactivation_emails_enabled']).to be(false)
expect(json_response['suggest_pipeline_enabled']).to be(false)
+ expect(json_response['users_get_by_id_limit']).to eq(456)
end
end
@@ -644,5 +655,37 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
end
end
end
+
+ context 'runner token expiration_intervals' do
+ it 'updates the settings' do
+ put api("/application/settings", admin), params: {
+ runner_token_expiration_interval: 3600,
+ group_runner_token_expiration_interval: 3600 * 2,
+ project_runner_token_expiration_interval: 3600 * 3
+ }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(
+ 'runner_token_expiration_interval' => 3600,
+ 'group_runner_token_expiration_interval' => 3600 * 2,
+ 'project_runner_token_expiration_interval' => 3600 * 3
+ )
+ end
+
+ it 'updates the settings with empty values' do
+ put api("/application/settings", admin), params: {
+ runner_token_expiration_interval: nil,
+ group_runner_token_expiration_interval: nil,
+ project_runner_token_expiration_interval: nil
+ }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(
+ 'runner_token_expiration_interval' => nil,
+ 'group_runner_token_expiration_interval' => nil,
+ 'project_runner_token_expiration_interval' => nil
+ )
+ end
+ end
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index bb56192a2ff..3558babf2f1 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -16,250 +16,232 @@ RSpec.describe API::Tags do
project.add_developer(user)
end
- describe 'GET /projects/:id/repository/tags' do
+ describe 'GET /projects/:id/repository/tags', :use_clean_rails_memory_store_caching do
before do
stub_feature_flags(tag_list_keyset_pagination: false)
end
- shared_examples "get repository tags" do
- let(:route) { "/projects/#{project_id}/repository/tags" }
+ let(:route) { "/projects/#{project_id}/repository/tags" }
- context 'sorting' do
- let(:current_user) { user }
+ context 'sorting' do
+ let(:current_user) { user }
- it 'sorts by descending order by default' do
- get api(route, current_user)
+ it 'sorts by descending order by default' do
+ get api(route, current_user)
- desc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
- desc_order_tags.reverse!.map! { |tag| tag.dereferenced_target.id }
+ desc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
+ desc_order_tags.reverse!.map! { |tag| tag.dereferenced_target.id }
- expect(json_response.map { |tag| tag['commit']['id'] }).to eq(desc_order_tags)
- end
+ expect(json_response.map { |tag| tag['commit']['id'] }).to eq(desc_order_tags)
+ end
- it 'sorts by ascending order if specified' do
- get api("#{route}?sort=asc", current_user)
+ it 'sorts by ascending order if specified' do
+ get api("#{route}?sort=asc", current_user)
- asc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
- asc_order_tags.map! { |tag| tag.dereferenced_target.id }
+ asc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
+ asc_order_tags.map! { |tag| tag.dereferenced_target.id }
- expect(json_response.map { |tag| tag['commit']['id'] }).to eq(asc_order_tags)
- end
+ expect(json_response.map { |tag| tag['commit']['id'] }).to eq(asc_order_tags)
+ end
- it 'sorts by name in descending order when requested' do
- get api("#{route}?order_by=name", current_user)
+ it 'sorts by name in descending order when requested' do
+ get api("#{route}?order_by=name", current_user)
- ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort.reverse
+ ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort.reverse
- expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
- end
+ expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
+ end
- it 'sorts by name in ascending order when requested' do
- get api("#{route}?order_by=name&sort=asc", current_user)
+ it 'sorts by name in ascending order when requested' do
+ get api("#{route}?order_by=name&sort=asc", current_user)
- ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort
+ ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort
- expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
- end
+ expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
end
+ end
- context 'searching' do
- it 'only returns searched tags' do
- get api("#{route}", user), params: { search: 'v1.1.0' }
+ context 'searching' do
+ it 'only returns searched tags' do
+ get api("#{route}", user), params: { search: 'v1.1.0' }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response[0]['name']).to eq('v1.1.0')
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ expect(json_response[0]['name']).to eq('v1.1.0')
end
+ end
- shared_examples_for 'repository tags' do
- it 'returns the repository tags' do
- get api(route, current_user)
+ shared_examples_for 'repository tags' do
+ it 'returns the repository tags' do
+ get api(route, current_user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response).to include_pagination_headers
- expect(json_response.map { |r| r['name'] }).to include(tag_name)
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response).to include_pagination_headers
+ expect(json_response.map { |r| r['name'] }).to include(tag_name)
+ end
- context 'when repository is disabled' do
- include_context 'disabled repository'
+ context 'when repository is disabled' do
+ include_context 'disabled repository'
- it_behaves_like '403 response' do
- let(:request) { get api(route, current_user) }
- end
+ it_behaves_like '403 response' do
+ let(:request) { get api(route, current_user) }
end
end
+ end
- context 'when unauthenticated', 'and project is public' do
- let(:project) { create(:project, :public, :repository) }
+ context 'when unauthenticated', 'and project is public' do
+ let(:project) { create(:project, :public, :repository) }
- it_behaves_like 'repository tags'
- end
+ it_behaves_like 'repository tags'
+ end
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get api(route) }
- let(:message) { '404 Project Not Found' }
- end
+ context 'when unauthenticated', 'and project is private' do
+ it_behaves_like '404 response' do
+ let(:request) { get api(route) }
+ let(:message) { '404 Project Not Found' }
end
+ end
- context 'when authenticated', 'as a maintainer' do
- let(:current_user) { user }
+ context 'when authenticated', 'as a maintainer' do
+ let(:current_user) { user }
- it_behaves_like 'repository tags'
+ it_behaves_like 'repository tags'
- context 'requesting with the escaped project full path' do
- let(:project_id) { CGI.escape(project.full_path) }
+ context 'requesting with the escaped project full path' do
+ let(:project_id) { CGI.escape(project.full_path) }
- it_behaves_like 'repository tags'
- end
+ it_behaves_like 'repository tags'
end
+ end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get api(route, guest) }
- end
+ context 'when authenticated', 'as a guest' do
+ it_behaves_like '403 response' do
+ let(:request) { get api(route, guest) }
end
+ end
- context 'with releases' do
- let(:description) { 'Awesome release!' }
+ context 'with releases' do
+ let(:description) { 'Awesome release!' }
- let!(:release) do
- create(:release,
- :legacy,
- project: project,
- tag: tag_name,
- description: description)
- end
+ let!(:release) do
+ create(:release,
+ :legacy,
+ project: project,
+ tag: tag_name,
+ description: description)
+ end
- it 'returns an array of project tags with release info' do
- get api(route, user)
+ it 'returns an array of project tags with release info' do
+ get api(route, user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response).to include_pagination_headers
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response).to include_pagination_headers
- expected_tag = json_response.find { |r| r['name'] == tag_name }
- expect(expected_tag['message']).to eq(tag_message)
- expect(expected_tag['release']['description']).to eq(description)
- end
+ expected_tag = json_response.find { |r| r['name'] == tag_name }
+ expect(expected_tag['message']).to eq(tag_message)
+ expect(expected_tag['release']['description']).to eq(description)
end
+ end
- context 'with keyset pagination on', :aggregate_errors do
- before do
- stub_feature_flags(tag_list_keyset_pagination: true)
- end
+ context 'with keyset pagination on', :aggregate_errors do
+ before do
+ stub_feature_flags(tag_list_keyset_pagination: true)
+ end
- context 'with keyset pagination option' do
- let(:base_params) { { pagination: 'keyset' } }
+ context 'with keyset pagination option' do
+ let(:base_params) { { pagination: 'keyset' } }
- context 'with gitaly pagination params' do
- context 'with high limit' do
- let(:params) { base_params.merge(per_page: 100) }
+ context 'with gitaly pagination params' do
+ context 'with high limit' do
+ let(:params) { base_params.merge(per_page: 100) }
- it 'returns all repository tags' do
- get api(route, user), params: params
+ it 'returns all repository tags' do
+ get api(route, user), params: params
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response.headers).not_to include('Link')
- tag_names = json_response.map { |x| x['name'] }
- expect(tag_names).to match_array(project.repository.tag_names)
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).not_to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(project.repository.tag_names)
end
+ end
- context 'with low limit' do
- let(:params) { base_params.merge(per_page: 2) }
+ context 'with low limit' do
+ let(:params) { base_params.merge(per_page: 2) }
- it 'returns limited repository tags' do
- get api(route, user), params: params
+ it 'returns limited repository tags' do
+ get api(route, user), params: params
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response.headers).to include('Link')
- tag_names = json_response.map { |x| x['name'] }
- expect(tag_names).to match_array(%w(v1.1.0 v1.1.1))
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(%w(v1.1.0 v1.1.1))
end
+ end
- context 'with missing page token' do
- let(:params) { base_params.merge(page_token: 'unknown') }
+ context 'with missing page token' do
+ let(:params) { base_params.merge(page_token: 'unknown') }
- it_behaves_like '422 response' do
- let(:request) { get api(route, user), params: params }
- let(:message) { 'Invalid page token: refs/tags/unknown' }
- end
+ it_behaves_like '422 response' do
+ let(:request) { get api(route, user), params: params }
+ let(:message) { 'Invalid page token: refs/tags/unknown' }
end
end
end
end
end
- context ":api_caching_tags flag enabled", :use_clean_rails_memory_store_caching do
+ describe "cache expiry" do
+ let(:route) { "/projects/#{project_id}/repository/tags" }
+ let(:current_user) { user }
+
before do
- stub_feature_flags(api_caching_tags: true)
+ # Set the cache
+ get api(route, current_user)
end
- it_behaves_like "get repository tags"
-
- describe "cache expiry" do
- let(:route) { "/projects/#{project_id}/repository/tags" }
- let(:current_user) { user }
+ it "is cached" do
+ expect(API::Entities::Tag).not_to receive(:represent)
- before do
- # Set the cache
- get api(route, current_user)
- end
+ get api(route, current_user)
+ end
- it "is cached" do
- expect(API::Entities::Tag).not_to receive(:represent)
+ shared_examples "cache expired" do
+ it "isn't cached" do
+ expect(API::Entities::Tag).to receive(:represent).exactly(3).times
get api(route, current_user)
end
+ end
- shared_examples "cache expired" do
- it "isn't cached" do
- expect(API::Entities::Tag).to receive(:represent).exactly(3).times
-
- get api(route, current_user)
- end
- end
-
- context "when protected tag is changed" do
- before do
- create(:protected_tag, name: tag_name, project: project)
- end
-
- it_behaves_like "cache expired"
+ context "when protected tag is changed" do
+ before do
+ create(:protected_tag, name: tag_name, project: project)
end
- context "when release is changed" do
- before do
- create(:release, :legacy, project: project, tag: tag_name)
- end
+ it_behaves_like "cache expired"
+ end
- it_behaves_like "cache expired"
+ context "when release is changed" do
+ before do
+ create(:release, :legacy, project: project, tag: tag_name)
end
- context "when project is changed" do
- before do
- project.touch
- end
+ it_behaves_like "cache expired"
+ end
- it_behaves_like "cache expired"
+ context "when project is changed" do
+ before do
+ project.touch
end
- end
- end
- context ":api_caching_tags flag disabled" do
- before do
- stub_feature_flags(api_caching_tags: false)
+ it_behaves_like "cache expired"
end
-
- it_behaves_like "get repository tags"
end
context 'when gitaly is unavailable' do
diff --git a/spec/requests/api/terraform/modules/v1/packages_spec.rb b/spec/requests/api/terraform/modules/v1/packages_spec.rb
index 8160113bbde..7d86244cb1b 100644
--- a/spec/requests/api/terraform/modules/v1/packages_spec.rb
+++ b/spec/requests/api/terraform/modules/v1/packages_spec.rb
@@ -232,20 +232,6 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
expect(response.body).not_to eq(package_file_pending_destruction.file.file.read)
expect(response.body).to eq(package_file.file.file.read)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(package_file_pending_destruction.file.file.read)
- expect(response.body).not_to eq(package_file.file.file.read)
- end
- end
end
end
diff --git a/spec/requests/api/usage_data_spec.rb b/spec/requests/api/usage_data_spec.rb
index bacaf960e6a..aefccc4fbf7 100644
--- a/spec/requests/api/usage_data_spec.rb
+++ b/spec/requests/api/usage_data_spec.rb
@@ -57,13 +57,26 @@ RSpec.describe API::UsageData do
end
end
- %w[merge_requests commits].each do |postfix|
- context 'with correct params' do
- let(:known_event_postfix) { postfix }
+ context 'with correct params' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:prefix, :event) do
+ 'static_site_editor' | 'merge_requests'
+ 'static_site_editor' | 'commits'
+ end
+
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ stub_feature_flags(usage_data_api: true)
+ allow(Gitlab::RequestForgeryProtection).to receive(:verified?).and_return(true)
+ stub_feature_flags("usage_data_#{prefix}_#{event}" => true)
+ end
+
+ with_them do
+ it 'returns status :ok' do
+ expect(Gitlab::UsageDataCounters::BaseCounter).to receive(:count).with(event)
- it 'returns status ok' do
- expect(Gitlab::UsageDataCounters::BaseCounter).to receive(:count).with(known_event_postfix)
- post api(endpoint, user), params: { event: known_event }
+ post api(endpoint, user), params: { event: "#{prefix}_#{event}" }
expect(response).to have_gitlab_http_status(:ok)
end
@@ -73,6 +86,7 @@ RSpec.describe API::UsageData do
context 'with unknown event' do
before do
skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
end
it 'returns status ok' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 98875d7e8d2..985e07bf174 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -499,7 +499,8 @@ RSpec.describe API::Users do
let_it_be(:user2, reload: true) { create(:user, username: 'another_user') }
before do
- allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:users_get_by_id, scope: user).and_return(false)
+ allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?)
+ .with(:users_get_by_id, scope: user, users_allowlist: []).and_return(false)
end
it "returns a user by id" do
@@ -600,7 +601,7 @@ RSpec.describe API::Users do
context 'when the rate limit is not exceeded' do
it 'returns a success status' do
expect(Gitlab::ApplicationRateLimiter)
- .to receive(:throttled?).with(:users_get_by_id, scope: user)
+ .to receive(:throttled?).with(:users_get_by_id, scope: user, users_allowlist: [])
.and_return(false)
get api("/users/#{user.id}", user)
@@ -613,7 +614,7 @@ RSpec.describe API::Users do
context 'when feature flag is enabled' do
it 'returns "too many requests" status' do
expect(Gitlab::ApplicationRateLimiter)
- .to receive(:throttled?).with(:users_get_by_id, scope: user)
+ .to receive(:throttled?).with(:users_get_by_id, scope: user, users_allowlist: [])
.and_return(true)
get api("/users/#{user.id}", user)
@@ -629,6 +630,24 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'allows users whose username is in the allowlist' do
+ allowlist = [user.username]
+ current_settings = Gitlab::CurrentSettings.current_application_settings
+
+ # Necessary to ensure the same object is returned on each call
+ allow(Gitlab::CurrentSettings).to receive(:current_application_settings).and_return current_settings
+
+ allow(current_settings).to receive(:users_get_by_id_limit_allowlist).and_return(allowlist)
+
+ expect(Gitlab::ApplicationRateLimiter)
+ .to receive(:throttled?).with(:users_get_by_id, scope: user, users_allowlist: allowlist)
+ .and_call_original
+
+ get api("/users/#{user.id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when feature flag is disabled' do
diff --git a/spec/requests/boards/lists_controller_spec.rb b/spec/requests/boards/lists_controller_spec.rb
index 4d9f1dace4d..47f4925d5b0 100644
--- a/spec/requests/boards/lists_controller_spec.rb
+++ b/spec/requests/boards/lists_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Boards::ListsController do
describe '#index' do
let(:board) { create(:board) }
- let(:user) { board.project.owner }
+ let(:user) { board.project.first_owner }
it 'does not have N+1 queries' do
login_as(user)
diff --git a/spec/requests/concerns/planning_hierarchy_spec.rb b/spec/requests/concerns/planning_hierarchy_spec.rb
new file mode 100644
index 00000000000..ece9270b3a1
--- /dev/null
+++ b/spec/requests/concerns/planning_hierarchy_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PlanningHierarchy, type: :request do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ describe 'GET #planning_hierarchy' do
+ it 'renders planning hierarchy' do
+ get project_planning_hierarchy_path(project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to match(/id="js-work-items-hierarchy"/)
+ end
+ end
+end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 623cf24b9cb..340ed7bde53 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -836,6 +836,24 @@ RSpec.describe 'Git HTTP requests' do
end
end
end
+
+ context "when the user is admin" do
+ let(:admin) { create(:admin) }
+ let(:env) { { user: admin.username, password: admin.password } }
+
+ # Currently, the admin mode is bypassed for git operations.
+ # Once the admin mode is considered for git operations, this test will fail.
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/296509
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it_behaves_like 'pulls are allowed'
+ it_behaves_like 'pushes are allowed'
+ end
+
+ context 'when admin mode is disabled' do
+ it_behaves_like 'pulls are allowed'
+ it_behaves_like 'pushes are allowed'
+ end
+ end
end
end
@@ -929,10 +947,10 @@ RSpec.describe 'Git HTTP requests' do
context 'when admin mode is disabled' do
it_behaves_like 'can download code only'
- it 'downloads from other project get status 404' do
+ it 'downloads from other project get status 403' do
clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
@@ -1534,10 +1552,10 @@ RSpec.describe 'Git HTTP requests' do
context 'when admin mode is disabled' do
it_behaves_like 'can download code only'
- it 'downloads from other project get status 404' do
+ it 'downloads from other project get status 403' do
clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
diff --git a/spec/requests/import/gitlab_projects_controller_spec.rb b/spec/requests/import/gitlab_projects_controller_spec.rb
index 58843a7fec4..eed035608d0 100644
--- a/spec/requests/import/gitlab_projects_controller_spec.rb
+++ b/spec/requests/import/gitlab_projects_controller_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Import::GitlabProjectsController do
include_context 'workhorse headers'
let_it_be(:namespace) { create(:namespace) }
- let_it_be(:user) { namespace.owner }
+ let_it_be(:user) { namespace.first_owner }
before do
login_as(user)
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index f89395fccaf..4b2f11da77e 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -546,14 +546,6 @@ RSpec.describe 'Git LFS API and storage' do
expect(lfs_object.reload.projects.pluck(:id)).to match_array([other_project.id, project.id])
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(lfs_auto_link_fork_source: false)
- end
-
- it_behaves_like 'batch upload with existing LFS object'
- end
end
context 'when user does not have access to parent' do
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 8ee752da44e..70a310ba0d5 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -275,7 +275,7 @@ RSpec.describe 'OpenID Connect requests' do
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])
+ expect(json_response['scopes_supported']).to match_array %w[api read_user read_api read_repository write_repository sudo openid profile email]
end
context 'with a cross-origin request' do
@@ -285,7 +285,7 @@ RSpec.describe 'OpenID Connect requests' do
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])
+ expect(json_response['scopes_supported']).to match_array %w[api read_user read_api read_repository write_repository sudo openid profile email]
end
it_behaves_like 'cross-origin GET request'
diff --git a/spec/requests/projects/cluster_agents_controller_spec.rb b/spec/requests/projects/cluster_agents_controller_spec.rb
index e4c4f537699..914d5b17ba8 100644
--- a/spec/requests/projects/cluster_agents_controller_spec.rb
+++ b/spec/requests/projects/cluster_agents_controller_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Projects::ClusterAgentsController do
let_it_be(:user) { create(:user) }
before do
- project.add_developer(user)
+ project.add_reporter(user)
sign_in(user)
subject
end
diff --git a/spec/requests/projects/clusters/integrations_controller_spec.rb b/spec/requests/projects/clusters/integrations_controller_spec.rb
index 323c61b9af3..c05e3da675c 100644
--- a/spec/requests/projects/clusters/integrations_controller_spec.rb
+++ b/spec/requests/projects/clusters/integrations_controller_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Projects::Clusters::IntegrationsController do
describe 'POST create_or_update' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it_behaves_like '#create_or_update action' do
let(:path) { create_or_update_project_cluster_integration_path(project, cluster) }
diff --git a/spec/requests/projects/google_cloud/deployments_controller_spec.rb b/spec/requests/projects/google_cloud/deployments_controller_spec.rb
index a5eccc43147..fd356bc61c7 100644
--- a/spec/requests/projects/google_cloud/deployments_controller_spec.rb
+++ b/spec/requests/projects/google_cloud/deployments_controller_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::GoogleCloud::DeploymentsController do
- let_it_be(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:repository) { project.repository }
let_it_be(:user_guest) { create(:user) }
let_it_be(:user_developer) { create(:user) }
@@ -36,8 +37,6 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
it 'returns not found on GET request' do
urls_list.each do |url|
unauthorized_members.each do |unauthorized_member|
- sign_in(unauthorized_member)
-
get url
expect(response).to have_gitlab_http_status(:not_found)
@@ -65,18 +64,63 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
let_it_be(:url) { "#{project_google_cloud_deployments_cloud_run_path(project)}" }
before do
+ sign_in(user_maintainer)
+
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
allow(client).to receive(:validate_token).and_return(true)
end
end
- it 'renders placeholder' do
- authorized_members.each do |authorized_member|
- sign_in(authorized_member)
+ it 'redirects to google_cloud home on enable service error' do
+ # since GPC_PROJECT_ID is not set, enable cloud run service should return an error
+
+ get url
+
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ end
+
+ it 'tracks error and redirects to gcp_error' do
+ mock_google_error = Google::Apis::ClientError.new('some_error')
+
+ allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service|
+ allow(service).to receive(:execute).and_raise(mock_google_error)
+ end
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(mock_google_error, { project_id: project.id })
+
+ get url
+
+ expect(response).to render_template(:gcp_error)
+ end
+
+ context 'GCP_PROJECT_IDs are defined' do
+ it 'redirects to google_cloud home on generate pipeline error' do
+ allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |enable_cloud_run_service|
+ allow(enable_cloud_run_service).to receive(:execute).and_return({ status: :success })
+ end
+
+ allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |generate_pipeline_service|
+ allow(generate_pipeline_service).to receive(:execute).and_return({ status: :error })
+ end
get url
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ end
+
+ it 'redirects to create merge request form' do
+ allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service|
+ allow(service).to receive(:execute).and_return({ status: :success })
+ end
+
+ allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |service|
+ allow(service).to receive(:execute).and_return({ status: :success })
+ end
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response.location).to include(project_new_merge_request_path(project))
end
end
end
diff --git a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
index 6b4d1c490e2..0f243a6a7a9 100644
--- a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
+++ b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
@@ -2,10 +2,6 @@
require 'spec_helper'
-# Mock Types
-MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
-MockServiceAccount = Struct.new(:project_id, :unique_id)
-
RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
let_it_be(:project) { create(:project, :public) }
@@ -86,10 +82,12 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
context 'and user has successfully completed the google oauth2 flow' do
before do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
allow(client).to receive(:validate_token).and_return(true)
allow(client).to receive(:list_projects).and_return([{}, {}, {}])
- allow(client).to receive(:create_service_account).and_return(MockServiceAccount.new(123, 456))
+ allow(client).to receive(:create_service_account).and_return(mock_service_account)
allow(client).to receive(:create_service_account_key).and_return({})
+ allow(client).to receive(:grant_service_account_roles)
end
end
@@ -147,7 +145,8 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
context 'but gitlab instance is not configured for google oauth2' do
before do
- unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '')
+ unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret)
+ .new('', '')
allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
.with('google_oauth2')
.and_return(unconfigured_google_oauth2)
diff --git a/spec/requests/projects/merge_requests/creations_spec.rb b/spec/requests/projects/merge_requests/creations_spec.rb
index 0a3e663444f..842ad01656e 100644
--- a/spec/requests/projects/merge_requests/creations_spec.rb
+++ b/spec/requests/projects/merge_requests/creations_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'merge requests creations' do
include ProjectForksHelper
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
login_as(user)
diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb
index 6cf7bfb1795..c761af86c16 100644
--- a/spec/requests/projects/merge_requests_discussions_spec.rb
+++ b/spec/requests/projects/merge_requests_discussions_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'merge requests discussions' do
# Further tests can be found at merge_requests_controller_spec.rb
describe 'GET /:namespace/:project/-/merge_requests/:iid/discussions' do
let(:project) { create(:project, :repository, :public) }
- let(:owner) { project.owner }
+ let(:owner) { project.first_owner }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
diff --git a/spec/requests/projects/merge_requests_spec.rb b/spec/requests/projects/merge_requests_spec.rb
index 59fde803560..91153554e55 100644
--- a/spec/requests/projects/merge_requests_spec.rb
+++ b/spec/requests/projects/merge_requests_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'merge requests actions' do
reviewers: [user2])
end
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:user2) { create(:user) }
before do
diff --git a/spec/requests/projects/metrics_dashboard_spec.rb b/spec/requests/projects/metrics_dashboard_spec.rb
index c248463faa3..61bfe1c6edf 100644
--- a/spec/requests/projects/metrics_dashboard_spec.rb
+++ b/spec/requests/projects/metrics_dashboard_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects::MetricsDashboardController' do
let_it_be(:project) { create(:project) }
let_it_be(:environment) { create(:environment, project: project) }
let_it_be(:environment2) { create(:environment, project: project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
before do
project.add_developer(user)
diff --git a/spec/requests/projects/noteable_notes_spec.rb b/spec/requests/projects/noteable_notes_spec.rb
index 2bf1ffb2edc..44ee50ca002 100644
--- a/spec/requests/projects/noteable_notes_spec.rb
+++ b/spec/requests/projects/noteable_notes_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Project noteable notes' do
let(:etag_store) { Gitlab::EtagCaching::Store.new }
let(:notes_path) { project_noteable_notes_path(project, target_type: merge_request.class.name.underscore, target_id: merge_request.id) }
let(:project) { merge_request.project }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:response_etag) { response.headers['ETag'] }
let(:stored_etag) { "W/\"#{etag_store.get(notes_path)}\"" }
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 793438808a5..f2126e3cf9c 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_caching do
include RackAttackSpecHelpers
+ include SessionHelpers
let(:settings) { Gitlab::CurrentSettings.current_application_settings }
@@ -63,6 +64,22 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
end
end
+ describe 'API requests from the frontend', :api, :clean_gitlab_redis_sessions do
+ context 'when unauthenticated' do
+ it_behaves_like 'rate-limited frontend API requests' do
+ let(:throttle_setting_prefix) { 'throttle_unauthenticated' }
+ end
+ end
+
+ context 'when authenticated' do
+ it_behaves_like 'rate-limited frontend API requests' do
+ let_it_be(:personal_access_token) { create(:personal_access_token) }
+
+ let(:throttle_setting_prefix) { 'throttle_authenticated' }
+ end
+ end
+ end
+
describe 'API requests authenticated with personal access token', :api do
let_it_be(:user) { create(:user) }
let_it_be(:token) { create(:personal_access_token, user: user) }
@@ -184,6 +201,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
context 'unauthenticated requests' do
let(:protected_path_that_does_not_require_authentication) do
+ # This is one of the default values for `application_settings.protected_paths`
'/users/sign_in'
end
@@ -227,6 +245,20 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
expect_rejection { post protected_path_that_does_not_require_authentication, params: post_params }
end
+ it 'allows non-POST requests to protected paths over the rate limit' do
+ (1 + requests_per_period).times do
+ get protected_path_that_does_not_require_authentication
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it 'allows POST requests to unprotected paths over the rate limit' do
+ (1 + requests_per_period).times do
+ post '/api/graphql'
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
it_behaves_like 'tracking when dry-run mode is set' do
let(:throttle_name) { 'throttle_unauthenticated_protected_paths' }
end
diff --git a/spec/requests/recursive_webhook_detection_spec.rb b/spec/requests/recursive_webhook_detection_spec.rb
index a3014bf1d73..fe27c90b6c8 100644
--- a/spec/requests/recursive_webhook_detection_spec.rb
+++ b/spec/requests/recursive_webhook_detection_spec.rb
@@ -11,6 +11,11 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
let_it_be(:project_hook) { create(:project_hook, project: project, merge_requests_events: true) }
let_it_be(:system_hook) { create(:system_hook, merge_requests_events: true) }
+ let(:stubbed_project_hook_hostname) { stubbed_hostname(project_hook.url, hostname: stubbed_project_hook_ip_address) }
+ let(:stubbed_system_hook_hostname) { stubbed_hostname(system_hook.url, hostname: stubbed_system_hook_ip_address) }
+ let(:stubbed_project_hook_ip_address) { '8.8.8.8' }
+ let(:stubbed_system_hook_ip_address) { '8.8.8.9' }
+
# Trigger a change to the merge request to fire the webhooks.
def trigger_web_hooks
params = { merge_request: { description: FFaker::Lorem.sentence } }
@@ -18,8 +23,8 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
end
def stub_requests
- stub_full_request(project_hook.url, method: :post, ip_address: '8.8.8.8')
- stub_full_request(system_hook.url, method: :post, ip_address: '8.8.8.9')
+ stub_full_request(project_hook.url, method: :post, ip_address: stubbed_project_hook_ip_address)
+ stub_full_request(system_hook.url, method: :post, ip_address: stubbed_system_hook_ip_address)
end
before do
@@ -37,10 +42,10 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
trigger_web_hooks
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url))
+ expect(WebMock).to have_requested(:post, stubbed_project_hook_hostname)
.with { |req| req.headers['X-Gitlab-Event-Uuid'] == uuid }
.once
- expect(WebMock).to have_requested(:post, stubbed_hostname(system_hook.url))
+ expect(WebMock).to have_requested(:post, stubbed_system_hook_hostname)
.with { |req| req.headers['X-Gitlab-Event-Uuid'] == uuid }
.once
end
@@ -54,24 +59,24 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
Gitlab::WebHooks::RecursionDetection.set_request_uuid(nil)
end
- it 'executes all webhooks and logs an error for the recursive hook', :aggregate_failures do
+ it 'blocks and logs an error for the recursive webhook, but execute the non-recursive webhook', :aggregate_failures do
stub_requests
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
recursion_detection: {
uuid: uuid,
ids: [project_hook.id]
}
)
- ).twice # Twice: once in `#async_execute`, and again in `#execute`.
+ ).once
trigger_web_hooks
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url)).once
- expect(WebMock).to have_requested(:post, stubbed_hostname(system_hook.url)).once
+ expect(WebMock).not_to have_requested(:post, stubbed_project_hook_hostname)
+ expect(WebMock).to have_requested(:post, stubbed_system_hook_hostname).once
end
end
@@ -87,35 +92,35 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
Gitlab::WebHooks::RecursionDetection.set_request_uuid(nil)
end
- it 'executes and logs errors for all hooks', :aggregate_failures do
+ it 'blocks and logs errors for all hooks', :aggregate_failures do
stub_requests
previous_hook_ids = previous_hooks.map(&:id)
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
recursion_detection: {
uuid: uuid,
ids: include(*previous_hook_ids)
}
)
- ).twice
+ ).once
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: system_hook.id,
recursion_detection: {
uuid: uuid,
ids: include(*previous_hook_ids)
}
)
- ).twice
+ ).once
trigger_web_hooks
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url)).once
- expect(WebMock).to have_requested(:post, stubbed_hostname(system_hook.url)).once
+ expect(WebMock).not_to have_requested(:post, stubbed_project_hook_hostname)
+ expect(WebMock).not_to have_requested(:post, stubbed_system_hook_hostname)
end
end
end
@@ -156,10 +161,10 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
expect(uuid_headers).to all(be_present)
expect(uuid_headers.uniq.length).to eq(2)
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url))
+ expect(WebMock).to have_requested(:post, stubbed_project_hook_hostname)
.with { |req| uuid_headers.include?(req.headers['X-Gitlab-Event-Uuid']) }
.once
- expect(WebMock).to have_requested(:post, stubbed_hostname(system_hook.url))
+ expect(WebMock).to have_requested(:post, stubbed_system_hook_hostname)
.with { |req| uuid_headers.include?(req.headers['X-Gitlab-Event-Uuid']) }
.once
end
@@ -175,8 +180,8 @@ RSpec.describe 'Recursive webhook detection', :sidekiq_inline, :clean_gitlab_red
expect(uuid_headers).to all(be_present)
expect(uuid_headers.length).to eq(4)
expect(uuid_headers.uniq.length).to eq(4)
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url)).twice
- expect(WebMock).to have_requested(:post, stubbed_hostname(system_hook.url)).twice
+ expect(WebMock).to have_requested(:post, stubbed_project_hook_hostname).twice
+ expect(WebMock).to have_requested(:post, stubbed_system_hook_hostname).twice
end
end
end
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index dacc11eece7..d033ce15b00 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -506,6 +506,7 @@ RSpec.describe UsersController do
describe 'GET #contributed' do
let(:project) { create(:project, :public) }
+ let(:aimed_for_deletion_project) { create(:project, :public, :archived, marked_for_deletion_at: 3.days.ago) }
subject do
get user_contributed_projects_url author.username, format: format
@@ -516,7 +517,10 @@ RSpec.describe UsersController do
project.add_developer(public_user)
project.add_developer(private_user)
+ aimed_for_deletion_project.add_developer(public_user)
+ aimed_for_deletion_project.add_developer(private_user)
create(:push_event, project: project, author: author)
+ create(:push_event, project: aimed_for_deletion_project, author: author)
subject
end
@@ -526,6 +530,11 @@ RSpec.describe UsersController do
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).not_to be_empty
end
+
+ it 'does not list projects aimed for deletion' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:contributed_projects)).to eq([project])
+ end
end
%i(html json).each do |format|
@@ -557,6 +566,7 @@ RSpec.describe UsersController do
describe 'GET #starred' do
let(:project) { create(:project, :public) }
+ let(:aimed_for_deletion_project) { create(:project, :public, :archived, marked_for_deletion_at: 3.days.ago) }
subject do
get user_starred_projects_url author.username, format: format
@@ -574,6 +584,11 @@ RSpec.describe UsersController do
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).not_to be_empty
end
+
+ it 'does not list projects aimed for deletion' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:starred_projects)).to eq([project])
+ end
end
%i(html json).each do |format|
@@ -634,13 +649,13 @@ RSpec.describe UsersController do
end
describe 'GET #exists' do
- before do
- sign_in(user)
+ context 'when user exists' do
+ before do
+ sign_in(user)
- allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false)
- end
+ allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false)
+ end
- context 'when user exists' do
it 'returns JSON indicating the user exists' do
get user_exists_url user.username
@@ -661,6 +676,15 @@ RSpec.describe UsersController do
end
context 'when the user does not exist' do
+ it 'will not show a signup page if registration is disabled' do
+ stub_application_setting(signup_enabled: false)
+ get user_exists_url 'foo'
+
+ expected_json = { error: "You must be authenticated to access this path." }.to_json
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response.body).to eq(expected_json)
+ end
+
it 'returns JSON indicating the user does not exist' do
get user_exists_url 'foo'
diff --git a/spec/rubocop/cop/file_decompression_spec.rb b/spec/rubocop/cop/file_decompression_spec.rb
new file mode 100644
index 00000000000..7be1a784001
--- /dev/null
+++ b/spec/rubocop/cop/file_decompression_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../rubocop/cop/file_decompression'
+
+RSpec.describe RuboCop::Cop::FileDecompression do
+ subject(:cop) { described_class.new }
+
+ it 'does not flag when using a system command not related to file decompression' do
+ expect_no_offenses('system("ls")')
+ end
+
+ described_class::FORBIDDEN_COMMANDS.map { [_1, '^' * _1.length] }.each do |cmd, len|
+ it "flags the when using '#{cmd}' system command" do
+ expect_offense(<<~SOURCE)
+ system('#{cmd}')
+ ^^^^^^^^#{len}^^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+
+ expect_offense(<<~SOURCE)
+ exec('#{cmd}')
+ ^^^^^^#{len}^^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+
+ expect_offense(<<~SOURCE)
+ Kernel.spawn('#{cmd}')
+ ^^^^^^^^^^^^^^#{len}^^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+
+ expect_offense(<<~SOURCE)
+ IO.popen('#{cmd}')
+ ^^^^^^^^^^#{len}^^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+ end
+
+ it "flags the when using '#{cmd}' subshell command" do
+ expect_offense(<<~SOURCE)
+ `#{cmd}`
+ ^#{len}^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+
+ expect_offense(<<~SOURCE)
+ %x(#{cmd})
+ ^^^#{len}^ While extracting files check for symlink to avoid arbitrary file reading[...]
+ SOURCE
+ end
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/event_store_subscriber_spec.rb b/spec/rubocop/cop/gitlab/event_store_subscriber_spec.rb
new file mode 100644
index 00000000000..e17fb71f9bc
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/event_store_subscriber_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/gitlab/event_store_subscriber'
+
+RSpec.describe RuboCop::Cop::Gitlab::EventStoreSubscriber do
+ subject(:cop) { described_class.new }
+
+ context 'when an event store subscriber overrides #perform' do
+ it 'registers an offense' do
+ expect_offense(<<~WORKER)
+ class SomeWorker
+ include Gitlab::EventStore::Subscriber
+
+ def perform(*args)
+ ^^^^^^^^^^^^^^^^^^ Do not override `perform` in a `Gitlab::EventStore::Subscriber`.
+ end
+
+ def handle_event(event); end
+ end
+ WORKER
+ end
+ end
+
+ context 'when an event store subscriber does not override #perform' do
+ it 'does not register an offense' do
+ expect_no_offenses(<<~WORKER)
+ class SomeWorker
+ include Gitlab::EventStore::Subscriber
+
+ def handle_event(event); end
+ end
+ WORKER
+ end
+ end
+
+ context 'when an event store subscriber does not implement #handle_event' do
+ it 'registers an offense' do
+ expect_offense(<<~WORKER)
+ class SomeWorker
+ include Gitlab::EventStore::Subscriber
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A `Gitlab::EventStore::Subscriber` must implement `#handle_event(event)`.
+ end
+ WORKER
+ end
+ end
+
+ context 'when a Sidekiq worker overrides #perform' do
+ it 'does not register an offense' do
+ expect_no_offenses(<<~WORKER)
+ class SomeWorker
+ include ApplicationWorker
+
+ def perform(*args); end
+ end
+ WORKER
+ end
+ end
+
+ context 'when a Sidekiq worker implements #handle_event' do
+ it 'does not register an offense' do
+ expect_no_offenses(<<~WORKER)
+ class SomeWorker
+ include ApplicationWorker
+
+ def handle_event(event); end
+ end
+ WORKER
+ end
+ end
+
+ context 'a non worker class' do
+ it 'does not register an offense' do
+ expect_no_offenses(<<~MODEL)
+ class Model < ApplicationRecord
+ include ActiveSupport::Concern
+ end
+ MODEL
+ end
+ end
+end
diff --git a/spec/rubocop/cop/migration/schedule_async_spec.rb b/spec/rubocop/cop/migration/schedule_async_spec.rb
index 5f848dd9b66..09d2c77369c 100644
--- a/spec/rubocop/cop/migration/schedule_async_spec.rb
+++ b/spec/rubocop/cop/migration/schedule_async_spec.rb
@@ -53,6 +53,17 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
end
end
+ context 'CiDatabaseWorker.perform_async' do
+ it 'adds an offense when calling `CiDatabaseWorker.peform_async`' do
+ expect_offense(<<~RUBY)
+ def up
+ CiDatabaseWorker.perform_async(ClazzName, "Bar", "Baz")
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
+ end
+ RUBY
+ end
+ end
+
context 'BackgroundMigrationWorker.perform_in' do
it 'adds an offense' do
expect_offense(<<~RUBY)
@@ -65,6 +76,18 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
end
end
+ context 'CiDatabaseWorker.perform_in' do
+ it 'adds an offense' do
+ expect_offense(<<~RUBY)
+ def up
+ CiDatabaseWorker
+ ^^^^^^^^^^^^^^^^ Don't call [...]
+ .perform_in(delay, ClazzName, "Bar", "Baz")
+ end
+ RUBY
+ end
+ end
+
context 'BackgroundMigrationWorker.bulk_perform_async' do
it 'adds an offense' do
expect_offense(<<~RUBY)
@@ -77,12 +100,36 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
end
end
+ context 'CiDatabaseWorker.bulk_perform_async' do
+ it 'adds an offense' do
+ expect_offense(<<~RUBY)
+ def up
+ BackgroundMigration::CiDatabaseWorker
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
+ .bulk_perform_async(jobs)
+ end
+ RUBY
+ end
+ end
+
context 'BackgroundMigrationWorker.bulk_perform_in' do
it 'adds an offense' do
expect_offense(<<~RUBY)
def up
- BackgroundMigrationWorker
- ^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
+ ::BackgroundMigrationWorker
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
+ .bulk_perform_in(5.minutes, jobs)
+ end
+ RUBY
+ end
+ end
+
+ context 'CiDatabaseWorker.bulk_perform_in' do
+ it 'adds an offense' do
+ expect_offense(<<~RUBY)
+ def up
+ ::BackgroundMigration::CiDatabaseWorker
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
.bulk_perform_in(5.minutes, jobs)
end
RUBY
diff --git a/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb b/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
index 01afaf3acb6..74912b53d37 100644
--- a/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
+++ b/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
@@ -39,9 +39,15 @@ RSpec.describe RuboCop::Cop::Scalability::BulkPerformWithContext do
CODE
end
- it "does not add an offense for scheduling BackgroundMigrations" do
+ it "does not add an offense for scheduling on the BackgroundMigrationWorker" do
expect_no_offenses(<<~CODE)
BackgroundMigrationWorker.bulk_perform_in(args)
CODE
end
+
+ it "does not add an offense for scheduling on the CiDatabaseWorker" do
+ expect_no_offenses(<<~CODE)
+ BackgroundMigration::CiDatabaseWorker.bulk_perform_in(args)
+ CODE
+ end
end
diff --git a/spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication_spec.rb b/spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication_spec.rb
deleted file mode 100644
index 6e7212b1002..00000000000
--- a/spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication_spec.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative '../../../../rubocop/cop/sidekiq_load_balancing/worker_data_consistency_with_deduplication'
-
-RSpec.describe RuboCop::Cop::SidekiqLoadBalancing::WorkerDataConsistencyWithDeduplication do
- using RSpec::Parameterized::TableSyntax
-
- subject(:cop) { described_class.new }
-
- before do
- allow(cop)
- .to receive(:in_worker?)
- .and_return(true)
- end
-
- where(:data_consistency) { %i[delayed sticky] }
-
- with_them do
- let(:strategy) { described_class::DEFAULT_STRATEGY }
- let(:corrected) do
- <<~CORRECTED
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- deduplicate #{strategy}, including_scheduled: true
- idempotent!
- end
- CORRECTED
- end
-
- context 'when deduplication strategy is not explicitly set' do
- it 'registers an offense and corrects using default strategy' do
- expect_offense(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- idempotent!
- ^^^^^^^^^^^ Workers that declare either `:sticky` or `:delayed` data consistency [...]
- end
- CODE
-
- expect_correction(corrected)
- end
-
- context 'when identation is different' do
- let(:corrected) do
- <<~CORRECTED
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- deduplicate #{strategy}, including_scheduled: true
- idempotent!
- end
- CORRECTED
- end
-
- it 'registers an offense and corrects with correct identation' do
- expect_offense(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- idempotent!
- ^^^^^^^^^^^ Workers that declare either `:sticky` or `:delayed` data consistency [...]
- end
- CODE
-
- expect_correction(corrected)
- end
- end
- end
-
- context 'when deduplication strategy does not include including_scheduling option' do
- let(:strategy) { ':until_executed' }
-
- it 'registers an offense and corrects' do
- expect_offense(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- deduplicate :until_executed
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Workers that declare either `:sticky` or `:delayed` data consistency [...]
- idempotent!
- end
- CODE
-
- expect_correction(corrected)
- end
- end
-
- context 'when deduplication strategy has including_scheduling option disabled' do
- let(:strategy) { ':until_executed' }
-
- it 'registers an offense and corrects' do
- expect_offense(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :#{data_consistency}
-
- deduplicate :until_executed, including_scheduled: false
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Workers that declare either `:sticky` or `:delayed` data consistency [...]
- idempotent!
- end
- CODE
-
- expect_correction(corrected)
- end
- end
-
- context "when deduplication strategy is :none" do
- it 'does not register an offense' do
- expect_no_offenses(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :always
-
- deduplicate :none
- idempotent!
- end
- CODE
- end
- end
-
- context "when deduplication strategy has including_scheduling option enabled" do
- it 'does not register an offense' do
- expect_no_offenses(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :always
-
- deduplicate :until_executing, including_scheduled: true
- idempotent!
- end
- CODE
- end
- end
- end
-
- context "data_consistency: :always" do
- it 'does not register an offense' do
- expect_no_offenses(<<~CODE)
- class SomeWorker
- include ApplicationWorker
-
- data_consistency :always
-
- idempotent!
- end
- CODE
- end
- end
-end
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index a24841fe286..da2734feb51 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe BuildDetailsEntity do
describe '#as_json' do
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, :failed, pipeline: pipeline) }
let(:request) { double('request', project: project) }
diff --git a/spec/serializers/ci/lint/result_serializer_spec.rb b/spec/serializers/ci/lint/result_serializer_spec.rb
index a834ea05e14..3fdaba1808a 100644
--- a/spec/serializers/ci/lint/result_serializer_spec.rb
+++ b/spec/serializers/ci/lint/result_serializer_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Ci::Lint::ResultSerializer, :aggregate_failures do
let(:result) do
Gitlab::Ci::Lint
- .new(project: project, current_user: project.owner)
+ .new(project: project, current_user: project.first_owner)
.validate(yaml_content, dry_run: false)
end
@@ -64,7 +64,7 @@ RSpec.describe Ci::Lint::ResultSerializer, :aggregate_failures do
context 'when dry run is enabled' do
let(:result) do
Gitlab::Ci::Lint
- .new(project: project, current_user: project.owner)
+ .new(project: project, current_user: project.first_owner)
.validate(yaml_content, dry_run: true)
end
diff --git a/spec/serializers/codequality_degradation_entity_spec.rb b/spec/serializers/codequality_degradation_entity_spec.rb
index 315f00baa72..f56420bfdbd 100644
--- a/spec/serializers/codequality_degradation_entity_spec.rb
+++ b/spec/serializers/codequality_degradation_entity_spec.rb
@@ -30,6 +30,21 @@ RSpec.describe CodequalityDegradationEntity do
expect(subject[:line]).to eq(10)
end
end
+
+ context 'when severity is capitalized' do
+ let(:codequality_degradation) { build(:codequality_degradation_3) }
+
+ before do
+ codequality_degradation[:severity] = 'MINOR'
+ end
+
+ it 'lowercases severity', :aggregate_failures do
+ expect(subject[:description]).to eq("Avoid parameter lists longer than 5 parameters. [12/5]")
+ expect(subject[:severity]).to eq("minor")
+ expect(subject[:file_path]).to eq("file_b.rb")
+ expect(subject[:line]).to eq(10)
+ end
+ end
end
end
end
diff --git a/spec/serializers/deployment_cluster_entity_spec.rb b/spec/serializers/deployment_cluster_entity_spec.rb
index 95f2f8ce6fc..419ae746b74 100644
--- a/spec/serializers/deployment_cluster_entity_spec.rb
+++ b/spec/serializers/deployment_cluster_entity_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe DeploymentClusterEntity do
subject { described_class.new(deployment, request: request).as_json }
let(:maintainer) { create(:user) }
- let(:developer) { create(:user) }
+ let(:reporter) { create(:user) }
let(:current_user) { maintainer }
let(:request) { double(:request, current_user: current_user) }
let(:project) { create(:project) }
@@ -17,7 +17,7 @@ RSpec.describe DeploymentClusterEntity do
before do
project.add_maintainer(maintainer)
- project.add_developer(developer)
+ project.add_reporter(reporter)
end
it 'matches deployment_cluster entity schema' do
@@ -31,7 +31,7 @@ RSpec.describe DeploymentClusterEntity do
end
context 'when the user does not have permission to view the cluster' do
- let(:current_user) { developer }
+ let(:current_user) { reporter }
it 'does not include the path nor the namespace' do
expect(subject[:path]).to be_nil
diff --git a/spec/serializers/diff_file_base_entity_spec.rb b/spec/serializers/diff_file_base_entity_spec.rb
index 99dbaff4b7e..11ceb7991d7 100644
--- a/spec/serializers/diff_file_base_entity_spec.rb
+++ b/spec/serializers/diff_file_base_entity_spec.rb
@@ -142,7 +142,7 @@ RSpec.describe DiffFileBaseEntity do
end
context 'when source_project and target_project are different' do
- let(:target_project) { fork_project(source_project, source_project.owner, repository: true) }
+ let(:target_project) { fork_project(source_project, source_project.first_owner, repository: true) }
it 'returns the merge_request ide route with the target_project as param' do
expect(entity[:ide_edit_path]).to eq("#{expected_merge_request_path}?target_project=#{ERB::Util.url_encode(target_project.full_path)}")
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
index 80b6f00d8c9..658062c9461 100644
--- a/spec/serializers/environment_serializer_spec.rb
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -204,21 +204,6 @@ RSpec.describe EnvironmentSerializer do
json
end
-
- # Including for test coverage pipeline failure, remove along with feature flag.
- context 'when custom preload feature is disabled' do
- before do
- Feature.disable(:custom_preloader_for_deployments)
- end
-
- it 'avoids N+1 database queries' do
- control_count = ActiveRecord::QueryRecorder.new { json }.count
-
- create_environment_with_associations(project)
-
- expect { json }.not_to exceed_query_limit(control_count)
- end
- end
end
def create_environment_with_associations(project)
diff --git a/spec/serializers/group_child_entity_spec.rb b/spec/serializers/group_child_entity_spec.rb
index 59340181075..469189c0768 100644
--- a/spec/serializers/group_child_entity_spec.rb
+++ b/spec/serializers/group_child_entity_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe GroupChildEntity do
include ExternalAuthorizationServiceHelpers
include Gitlab::Routing.url_helpers
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+
let(:request) { double('request') }
let(:entity) { described_class.new(object, request: request) }
@@ -103,6 +104,22 @@ RSpec.describe GroupChildEntity do
expect(json[:can_leave]).to be_truthy
end
+ it 'allows an owner to delete the group' do
+ expect(json[:can_remove]).to be_truthy
+ end
+
+ it 'allows admin to delete the group', :enable_admin_mode do
+ allow(request).to receive(:current_user).and_return(create(:admin))
+
+ expect(json[:can_remove]).to be_truthy
+ end
+
+ it 'disallows a maintainer to delete the group' do
+ object.add_maintainer(user)
+
+ expect(json[:can_remove]).to be_falsy
+ end
+
it 'has the correct edit path' do
expect(json[:edit_path]).to eq(edit_group_path(object))
end
diff --git a/spec/serializers/issue_sidebar_basic_entity_spec.rb b/spec/serializers/issue_sidebar_basic_entity_spec.rb
new file mode 100644
index 00000000000..da07290f349
--- /dev/null
+++ b/spec/serializers/issue_sidebar_basic_entity_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueSidebarBasicEntity do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user, developer_projects: [project]) }
+ let_it_be(:issue) { create(:issue, project: project, assignees: [user]) }
+
+ let(:serializer) { IssueSerializer.new(current_user: user, project: project) }
+
+ subject(:entity) { serializer.represent(issue, serializer: 'sidebar') }
+
+ it 'contains keys related to issuables' do
+ expect(entity).to include(
+ :id, :iid, :type, :author_id, :project_id, :discussion_locked, :reference, :milestone,
+ :labels, :current_user, :issuable_json_path, :namespace_path, :project_path,
+ :project_full_path, :project_issuables_path, :create_todo_path, :project_milestones_path,
+ :project_labels_path, :toggle_subscription_path, :move_issue_path, :projects_autocomplete_path,
+ :project_emails_disabled, :create_note_email, :supports_time_tracking, :supports_milestone,
+ :supports_severity, :supports_escalation
+ )
+ end
+
+ it 'contains attributes related to the issue' do
+ expect(entity).to include(:due_date, :confidential, :severity)
+ end
+
+ describe 'current_user' do
+ it 'contains attributes related to the current user' do
+ expect(entity[:current_user]).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url, :todo,
+ :can_edit, :can_move, :can_admin_label
+ )
+ end
+
+ describe 'can_update_escalation_status' do
+ context 'for a standard issue' do
+ it 'is not present' do
+ expect(entity[:current_user]).not_to have_key(:can_update_escalation_status)
+ end
+ end
+
+ context 'for an incident issue' do
+ before do
+ issue.update!(issue_type: Issue.issue_types[:incident])
+ end
+
+ it 'is present and true' do
+ expect(entity[:current_user][:can_update_escalation_status]).to be(true)
+ end
+
+ context 'without permissions' do
+ let(:serializer) { IssueSerializer.new(current_user: create(:user), project: project) }
+
+ it 'is present and false' do
+ expect(entity[:current_user]).to have_key(:can_update_escalation_status)
+ expect(entity[:current_user][:can_update_escalation_status]).to be(false)
+ end
+ end
+
+ context 'with :incident_escalations feature flag disabled' do
+ before do
+ stub_feature_flags(incident_escalations: false)
+ end
+
+ it 'is not present' do
+ expect(entity[:current_user]).not_to include(:can_update_escalation_status)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
index ecc93219b53..e9c1fe23855 100644
--- a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
@@ -21,12 +21,6 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
is_expected.to include(:target_branch_sha)
end
- it 'has public_merge_status as merge_status' do
- expect(resource).to receive(:public_merge_status).and_return('checking')
-
- expect(subject[:merge_status]).to eq 'checking'
- end
-
it 'has blob path data' do
allow(resource).to receive_messages(
base_pipeline: pipeline,
@@ -38,6 +32,20 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
expect(subject[:blob_path]).to include(:head_path)
end
+ describe 'merge_status' do
+ it 'calls for MergeRequest#check_mergeability' do
+ expect(resource).to receive(:check_mergeability).with(async: true)
+
+ subject[:merge_status]
+ end
+
+ it 'has public_merge_status as merge_status' do
+ expect(resource).to receive(:public_merge_status).and_return('checking')
+
+ expect(subject[:merge_status]).to eq 'checking'
+ end
+ end
+
describe 'diverged_commits_count' do
context 'when MR open and its diverging' do
it 'returns diverged commits count' do
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 3aebe16438c..581efd331ef 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -180,16 +180,6 @@ RSpec.describe MergeRequestPollWidgetEntity do
it 'calculates mergeability and returns true' do
expect(subject[:mergeable]).to eq(true)
end
-
- context 'when check_mergeability_async_in_widget is disabled' do
- before do
- stub_feature_flags(check_mergeability_async_in_widget: false)
- end
-
- it 'calculates mergeability and returns true' do
- expect(subject[:mergeable]).to eq(true)
- end
- end
end
end
end
diff --git a/spec/serializers/runner_entity_spec.rb b/spec/serializers/runner_entity_spec.rb
index 39cac65c5ac..f34cb794834 100644
--- a/spec/serializers/runner_entity_spec.rb
+++ b/spec/serializers/runner_entity_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe RunnerEntity do
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:entity) { described_class.new(runner, request: request, current_user: user) }
let(:request) { double('request') }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
before do
allow(request).to receive(:current_user).and_return(user)
diff --git a/spec/serializers/test_case_entity_spec.rb b/spec/serializers/test_case_entity_spec.rb
index cdeefd2fec5..03fb88bc6c3 100644
--- a/spec/serializers/test_case_entity_spec.rb
+++ b/spec/serializers/test_case_entity_spec.rb
@@ -41,6 +41,18 @@ RSpec.describe TestCaseEntity do
end
end
+ context 'when no test name is entered' do
+ let(:test_case) { build(:report_test_case, name: "") }
+
+ it 'contains correct test case details' do
+ expect(subject[:status]).to eq('success')
+ expect(subject[:name]).to eq('(No name)')
+ expect(subject[:classname]).to eq('trace')
+ expect(subject[:file]).to eq('spec/trace_spec.rb')
+ expect(subject[:execution_time]).to eq(1.23)
+ end
+ end
+
context 'when attachment is present' do
let(:test_case) { build(:report_test_case, :failed_with_attachment, job: job) }
diff --git a/spec/serializers/trigger_variable_entity_spec.rb b/spec/serializers/trigger_variable_entity_spec.rb
index e90bfc24f9f..deabbb9d54b 100644
--- a/spec/serializers/trigger_variable_entity_spec.rb
+++ b/spec/serializers/trigger_variable_entity_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe TriggerVariableEntity do
end
context 'when user is owner' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it 'exposes the variable value' do
expect(subject).to include(:value)
diff --git a/spec/services/alert_management/alerts/update_service_spec.rb b/spec/services/alert_management/alerts/update_service_spec.rb
index 35697ac79a0..882543fd701 100644
--- a/spec/services/alert_management/alerts/update_service_spec.rb
+++ b/spec/services/alert_management/alerts/update_service_spec.rb
@@ -28,8 +28,11 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
specify { expect { response }.not_to change(Note, :count) }
end
- shared_examples 'adds a system note' do
- specify { expect { response }.to change { alert.reload.notes.count }.by(1) }
+ shared_examples 'adds a system note' do |note_matcher = nil|
+ specify do
+ expect { response }.to change { alert.reload.notes.count }.by(1)
+ expect(alert.notes.last.note).to match(note_matcher) if note_matcher
+ end
end
shared_examples 'error response' do |message|
@@ -288,6 +291,12 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
end
end
end
+
+ context 'when a status change reason is included' do
+ let(:params) { { status: new_status, status_change_reason: ' by changing the incident status' } }
+
+ it_behaves_like 'adds a system note', /changed the status to \*\*Acknowledged\*\* by changing the incident status/
+ end
end
end
end
diff --git a/spec/services/alert_management/create_alert_issue_service_spec.rb b/spec/services/alert_management/create_alert_issue_service_spec.rb
index 55f8e47717c..083e5b8c6f1 100644
--- a/spec/services/alert_management/create_alert_issue_service_spec.rb
+++ b/spec/services/alert_management/create_alert_issue_service_spec.rb
@@ -43,10 +43,10 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
expect(execute).to be_success
end
- it 'updates alert.issue_id' do
+ it 'sets alert.issue_id in the same ActiveRecord query execution' do
execute
- expect(alert.reload.issue_id).to eq(created_issue.id)
+ expect(alert.issue_id).to eq(created_issue.id)
end
it 'creates a system note' do
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index 5c9d2c5e680..e20d59fb0ef 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -475,6 +475,24 @@ RSpec.describe ApplicationSettings::UpdateService do
end
end
+ context 'when users_get_by_id_limit and users_get_by_id_limit_allowlist_raw are passed' do
+ let(:params) do
+ {
+ users_get_by_id_limit: 456,
+ users_get_by_id_limit_allowlist_raw: 'someone, someone_else'
+ }
+ end
+
+ it 'updates users_get_by_id_limit and users_get_by_id_limit_allowlist value' do
+ subject.execute
+
+ application_settings.reload
+
+ expect(application_settings.users_get_by_id_limit).to eq(456)
+ expect(application_settings.users_get_by_id_limit_allowlist).to eq(%w[someone someone_else])
+ end
+ end
+
context 'when require_admin_approval_after_user_signup changes' do
context 'when it goes from enabled to disabled' do
let(:params) { { require_admin_approval_after_user_signup: false } }
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index 83f77780b80..00841de9ff4 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -145,28 +145,4 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'an unmodified token'
end
end
-
- context 'CDN redirection' do
- include_context 'container registry auth service context'
-
- let_it_be(:current_user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be(:current_params) { { scopes: ["repository:#{project.full_path}:pull"] } }
-
- before do
- project.add_developer(current_user)
- end
-
- it_behaves_like 'a valid token'
- it { expect(payload['access']).to include(include('cdn_redirect' => true)) }
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(container_registry_cdn_redirect: false)
- end
-
- it_behaves_like 'a valid token'
- it { expect(payload['access']).not_to include(have_key('cdn_redirect')) }
- end
- end
end
diff --git a/spec/services/branches/create_service_spec.rb b/spec/services/branches/create_service_spec.rb
index 1962aca35e1..0d2f5838574 100644
--- a/spec/services/branches/create_service_spec.rb
+++ b/spec/services/branches/create_service_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Branches::CreateService do
allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
- expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
pre_receive_error,
pre_receive_message: raw_message,
branch_name: 'new-feature',
diff --git a/spec/services/ci/copy_cross_database_associations_service_spec.rb b/spec/services/ci/copy_cross_database_associations_service_spec.rb
new file mode 100644
index 00000000000..5938ac258d0
--- /dev/null
+++ b/spec/services/ci/copy_cross_database_associations_service_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CopyCrossDatabaseAssociationsService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:old_build) { create(:ci_build, pipeline: pipeline) }
+ let_it_be(:new_build) { create(:ci_build, pipeline: pipeline) }
+
+ subject(:execute) { described_class.new.execute(old_build, new_build) }
+
+ describe '#execute' do
+ it 'returns a success response' do
+ expect(execute).to be_success
+ end
+ end
+end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index d61abf6a6ee..43eb57df66c 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -441,44 +441,99 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
end
end
- context 'when relationship between pipelines is cyclical' do
- before do
- pipeline_a = create(:ci_pipeline, project: upstream_project)
- pipeline_b = create(:ci_pipeline, project: downstream_project)
- pipeline_c = create(:ci_pipeline, project: upstream_project)
+ describe 'cyclical dependency detection' do
+ shared_examples 'detects cyclical pipelines' do
+ it 'does not create a new pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'changes status of the bridge build' do
+ service.execute(bridge)
- create_source_pipeline(pipeline_a, pipeline_b)
- create_source_pipeline(pipeline_b, pipeline_c)
- create_source_pipeline(pipeline_c, upstream_pipeline)
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'pipeline_loop_detected'
+ end
end
- it 'does not create a new pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
+ shared_examples 'passes cyclical pipeline precondition' do
+ it 'creates a new pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }
+ end
+
+ it 'expect bridge build not to be failed' do
+ service.execute(bridge)
+
+ expect(bridge.reload).not_to be_failed
+ end
end
- it 'changes status of the bridge build' do
- service.execute(bridge)
+ context 'when pipeline ancestry contains 2 cycles of dependencies' do
+ before do
+ # A(push on master) -> B(pipeline on master) -> A(push on master) ->
+ # B(pipeline on master) -> A(push on master)
+ pipeline_1 = create(:ci_pipeline, project: upstream_project, source: :push)
+ pipeline_2 = create(:ci_pipeline, project: downstream_project, source: :pipeline)
+ pipeline_3 = create(:ci_pipeline, project: upstream_project, source: :push)
+ pipeline_4 = create(:ci_pipeline, project: downstream_project, source: :pipeline)
+
+ create_source_pipeline(pipeline_1, pipeline_2)
+ create_source_pipeline(pipeline_2, pipeline_3)
+ create_source_pipeline(pipeline_3, pipeline_4)
+ create_source_pipeline(pipeline_4, upstream_pipeline)
+ end
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq 'pipeline_loop_detected'
+ it_behaves_like 'detects cyclical pipelines'
+
+ context 'when ci_drop_cyclical_triggered_pipelines is not enabled' do
+ before do
+ stub_feature_flags(ci_drop_cyclical_triggered_pipelines: false)
+ end
+
+ it_behaves_like 'passes cyclical pipeline precondition'
+ end
end
- context 'when ci_drop_cyclical_triggered_pipelines is not enabled' do
+ context 'when source in the ancestry differ' do
before do
- stub_feature_flags(ci_drop_cyclical_triggered_pipelines: false)
+ # A(push on master) -> B(pipeline on master) -> A(pipeline on master)
+ pipeline_1 = create(:ci_pipeline, project: upstream_project, source: :push)
+ pipeline_2 = create(:ci_pipeline, project: downstream_project, source: :pipeline)
+ upstream_pipeline.update!(source: :pipeline)
+
+ create_source_pipeline(pipeline_1, pipeline_2)
+ create_source_pipeline(pipeline_2, upstream_pipeline)
end
- it 'creates a new pipeline' do
- expect { service.execute(bridge) }
- .to change { Ci::Pipeline.count }
+ it_behaves_like 'passes cyclical pipeline precondition'
+ end
+
+ context 'when ref in the ancestry differ' do
+ before do
+ # A(push on master) -> B(pipeline on master) -> A(push on feature-1)
+ pipeline_1 = create(:ci_pipeline, ref: 'master', project: upstream_project, source: :push)
+ pipeline_2 = create(:ci_pipeline, ref: 'master', project: downstream_project, source: :pipeline)
+ upstream_pipeline.update!(ref: 'feature-1')
+
+ create_source_pipeline(pipeline_1, pipeline_2)
+ create_source_pipeline(pipeline_2, upstream_pipeline)
end
- it 'expect bridge build not to be failed' do
- service.execute(bridge)
+ it_behaves_like 'passes cyclical pipeline precondition'
+ end
- expect(bridge.reload).not_to be_failed
+ context 'when only 1 cycle is detected' do
+ before do
+ # A(push on master) -> B(pipeline on master) -> A(push on master)
+ pipeline_1 = create(:ci_pipeline, ref: 'master', project: upstream_project, source: :push)
+ pipeline_2 = create(:ci_pipeline, ref: 'master', project: downstream_project, source: :pipeline)
+
+ create_source_pipeline(pipeline_1, pipeline_2)
+ create_source_pipeline(pipeline_2, upstream_pipeline)
end
+
+ it_behaves_like 'passes cyclical pipeline precondition'
end
end
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
index 26bc6f747e1..7365ad162d2 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
@@ -1043,22 +1043,6 @@ RSpec.describe Ci::PipelineProcessing::AtomicProcessingService do
expect(all_builds_names).to eq(%w[A1 A2 B])
expect(all_builds_statuses).to eq(%w[pending created created])
end
-
- context 'when the FF ci_order_subsequent_jobs_by_stage is disabled' do
- before do
- stub_feature_flags(ci_order_subsequent_jobs_by_stage: false)
- end
-
- it 'processes subsequent jobs in an incorrect order when playing first job' do
- expect(all_builds_names).to eq(%w[A1 A2 B])
- expect(all_builds_statuses).to eq(%w[manual skipped skipped])
-
- play_manual_action('A1')
-
- expect(all_builds_names).to eq(%w[A1 A2 B])
- expect(all_builds_statuses).to eq(%w[pending created skipped])
- end
- end
end
private
diff --git a/spec/services/ci/pipeline_schedule_service_spec.rb b/spec/services/ci/pipeline_schedule_service_spec.rb
index 65bbd13c5e7..b8e4fb19f5d 100644
--- a/spec/services/ci/pipeline_schedule_service_spec.rb
+++ b/spec/services/ci/pipeline_schedule_service_spec.rb
@@ -32,5 +32,22 @@ RSpec.describe Ci::PipelineScheduleService do
expect { subject }.not_to raise_error
end
end
+
+ context 'when the project is missing' do
+ before do
+ project.delete
+ end
+
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
+ end
+
+ it 'does not run RunPipelineScheduleWorker' do
+ expect(RunPipelineScheduleWorker)
+ .not_to receive(:perform_async).with(schedule.id, schedule.owner.id)
+
+ subject
+ end
+ end
end
end
diff --git a/spec/services/ci/process_sync_events_service_spec.rb b/spec/services/ci/process_sync_events_service_spec.rb
index 8b7717fe4bf..6b9717fe57d 100644
--- a/spec/services/ci/process_sync_events_service_spec.rb
+++ b/spec/services/ci/process_sync_events_service_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe Ci::ProcessSyncEventsService do
project2.update!(group: parent_group_2)
end
+ it { is_expected.to eq(service_results(2, 2, 2)) }
+
it 'consumes events' do
expect { execute }.to change(Projects::SyncEvent, :count).from(2).to(0)
@@ -36,20 +38,32 @@ RSpec.describe Ci::ProcessSyncEventsService do
)
end
- it 'enqueues Projects::ProcessSyncEventsWorker if any left' do
- stub_const("#{described_class}::BATCH_SIZE", 1)
+ context 'when any event left after processing' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
- expect(Projects::ProcessSyncEventsWorker).to receive(:perform_async)
+ it { is_expected.to eq(service_results(2, 1, 1)) }
- execute
+ it 'enqueues Projects::ProcessSyncEventsWorker' do
+ expect(Projects::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ execute
+ end
end
- it 'does not enqueue Projects::ProcessSyncEventsWorker if no left' do
- stub_const("#{described_class}::BATCH_SIZE", 2)
+ context 'when no event left after processing' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+ end
- expect(Projects::ProcessSyncEventsWorker).not_to receive(:perform_async)
+ it { is_expected.to eq(service_results(2, 2, 2)) }
- execute
+ it 'does not enqueue Projects::ProcessSyncEventsWorker' do
+ expect(Projects::ProcessSyncEventsWorker).not_to receive(:perform_async)
+
+ execute
+ end
end
context 'when there is no event' do
@@ -57,37 +71,45 @@ RSpec.describe Ci::ProcessSyncEventsService do
Projects::SyncEvent.delete_all
end
+ it { is_expected.to eq(service_results(0, 0, nil)) }
+
it 'does nothing' do
expect { execute }.not_to change(Projects::SyncEvent, :count)
end
end
- context 'when the FF ci_namespace_project_mirrors is disabled' do
+ context 'when there is non-executed events' do
before do
- stub_feature_flags(ci_namespace_project_mirrors: false)
- end
+ new_project = create(:project)
+ sync_event_class.delete_all
- it 'does nothing' do
- expect { execute }.not_to change(Projects::SyncEvent, :count)
- end
- end
+ project1.update!(group: parent_group_2)
+ new_project.update!(group: parent_group_1)
+ project2.update!(group: parent_group_1)
- it 'does not delete non-executed events' do
- new_project = create(:project)
- sync_event_class.delete_all
+ @new_project_sync_event = new_project.sync_events.last
- project1.update!(group: parent_group_2)
- new_project.update!(group: parent_group_1)
- project2.update!(group: parent_group_1)
+ allow(sync_event_class).to receive(:preload_synced_relation).and_return(
+ sync_event_class.where.not(id: @new_project_sync_event)
+ )
+ end
- new_project_sync_event = new_project.sync_events.last
+ it { is_expected.to eq(service_results(3, 2, 2)) }
- allow(sync_event_class).to receive(:preload_synced_relation).and_return(
- sync_event_class.where.not(id: new_project_sync_event)
- )
+ it 'does not delete non-executed events' do
+ expect { execute }.to change(Projects::SyncEvent, :count).from(3).to(1)
+ expect(@new_project_sync_event.reload).to be_persisted
+ end
+ end
+
+ private
- expect { execute }.to change(Projects::SyncEvent, :count).from(3).to(1)
- expect(new_project_sync_event.reload).to be_persisted
+ def service_results(total, consumable, processed)
+ {
+ estimated_total_events: total,
+ consumable_events: consumable,
+ processed_events: processed
+ }.compact
end
end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 251159864f5..2127a4fa0fc 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -750,6 +750,8 @@ module Ci
context 'with ci_queuing_use_denormalized_data_strategy disabled' do
before do
+ skip_if_multiple_databases_are_setup
+
stub_feature_flags(ci_queuing_use_denormalized_data_strategy: false)
end
@@ -773,6 +775,8 @@ module Ci
context 'when not using pending builds table' do
before do
+ skip_if_multiple_databases_are_setup
+
stub_feature_flags(ci_pending_builds_queue_source: false)
end
diff --git a/spec/services/ci/register_runner_service_spec.rb b/spec/services/ci/register_runner_service_spec.rb
index e813a1d8b31..491582bbd13 100644
--- a/spec/services/ci/register_runner_service_spec.rb
+++ b/spec/services/ci/register_runner_service_spec.rb
@@ -2,8 +2,10 @@
require 'spec_helper'
-RSpec.describe ::Ci::RegisterRunnerService do
+RSpec.describe ::Ci::RegisterRunnerService, '#execute' do
let(:registration_token) { 'abcdefg123456' }
+ let(:token) { }
+ let(:args) { {} }
before do
stub_feature_flags(runner_registration_control: false)
@@ -11,213 +13,219 @@ RSpec.describe ::Ci::RegisterRunnerService do
stub_application_setting(valid_runner_registrars: ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
end
- describe '#execute' do
- let(:token) { }
- let(:args) { {} }
+ subject { described_class.new.execute(token, args) }
- subject { described_class.new.execute(token, args) }
+ context 'when no token is provided' do
+ let(:token) { '' }
- context 'when no token is provided' do
- let(:token) { '' }
-
- it 'returns nil' do
- is_expected.to be_nil
- end
+ it 'returns nil' do
+ is_expected.to be_nil
end
+ end
- context 'when invalid token is provided' do
- let(:token) { 'invalid' }
+ context 'when invalid token is provided' do
+ let(:token) { 'invalid' }
- it 'returns nil' do
- is_expected.to be_nil
- end
+ it 'returns nil' do
+ is_expected.to be_nil
end
+ end
- context 'when valid token is provided' do
- context 'with a registration token' do
- let(:token) { registration_token }
+ context 'when valid token is provided' do
+ context 'with a registration token' do
+ let(:token) { registration_token }
+
+ it 'creates runner with default values' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.persisted?).to be_truthy
+ expect(subject.run_untagged).to be true
+ expect(subject.active).to be true
+ expect(subject.token).not_to eq(registration_token)
+ expect(subject).to be_instance_type
+ end
- it 'creates runner with default values' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_truthy
- expect(subject.run_untagged).to be true
- expect(subject.active).to be true
- expect(subject.token).not_to eq(registration_token)
- expect(subject).to be_instance_type
- end
-
- context 'with non-default arguments' do
- let(:args) do
- {
- description: 'some description',
- active: false,
- locked: true,
- run_untagged: false,
- tag_list: %w(tag1 tag2),
- access_level: 'ref_protected',
- maximum_timeout: 600,
- name: 'some name',
- version: 'some version',
- revision: 'some revision',
- platform: 'some platform',
- architecture: 'some architecture',
- ip_address: '10.0.0.1',
- config: {
- gpus: 'some gpu config'
- }
+ context 'with non-default arguments' do
+ let(:args) do
+ {
+ description: 'some description',
+ active: false,
+ locked: true,
+ run_untagged: false,
+ tag_list: %w(tag1 tag2),
+ access_level: 'ref_protected',
+ maximum_timeout: 600,
+ name: 'some name',
+ version: 'some version',
+ revision: 'some revision',
+ platform: 'some platform',
+ architecture: 'some architecture',
+ ip_address: '10.0.0.1',
+ config: {
+ gpus: 'some gpu config'
}
- end
+ }
+ end
- it 'creates runner with specified values', :aggregate_failures do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.active).to eq args[:active]
- expect(subject.locked).to eq args[:locked]
- expect(subject.run_untagged).to eq args[:run_untagged]
- expect(subject.tags).to contain_exactly(
- an_object_having_attributes(name: 'tag1'),
- an_object_having_attributes(name: 'tag2')
- )
- expect(subject.access_level).to eq args[:access_level]
- expect(subject.maximum_timeout).to eq args[:maximum_timeout]
- expect(subject.name).to eq args[:name]
- expect(subject.version).to eq args[:version]
- expect(subject.revision).to eq args[:revision]
- expect(subject.platform).to eq args[:platform]
- expect(subject.architecture).to eq args[:architecture]
- expect(subject.ip_address).to eq args[:ip_address]
- end
+ it 'creates runner with specified values', :aggregate_failures do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.active).to eq args[:active]
+ expect(subject.locked).to eq args[:locked]
+ expect(subject.run_untagged).to eq args[:run_untagged]
+ expect(subject.tags).to contain_exactly(
+ an_object_having_attributes(name: 'tag1'),
+ an_object_having_attributes(name: 'tag2')
+ )
+ expect(subject.access_level).to eq args[:access_level]
+ expect(subject.maximum_timeout).to eq args[:maximum_timeout]
+ expect(subject.name).to eq args[:name]
+ expect(subject.version).to eq args[:version]
+ expect(subject.revision).to eq args[:revision]
+ expect(subject.platform).to eq args[:platform]
+ expect(subject.architecture).to eq args[:architecture]
+ expect(subject.ip_address).to eq args[:ip_address]
end
end
- context 'when project token is used' do
- let(:project) { create(:project) }
- let(:token) { project.runners_token }
+ context 'with runner token expiration interval', :freeze_time do
+ before do
+ stub_application_setting(runner_token_expiration_interval: 5.days)
+ end
- it 'creates project runner' do
+ it 'creates runner with token expiration' do
is_expected.to be_an_instance_of(::Ci::Runner)
- expect(project.runners.size).to eq(1)
- is_expected.to eq(project.runners.first)
- expect(subject.token).not_to eq(registration_token)
- expect(subject.token).not_to eq(project.runners_token)
- expect(subject).to be_project_type
+ expect(subject.token_expires_at).to eq(5.days.from_now)
end
+ end
+ end
- context 'when it exceeds the application limits' do
- before do
- 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
+ context 'when project token is used' do
+ let(:project) { create(:project) }
+ let(:token) { project.runners_token }
+
+ it 'creates project runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(project.runners.size).to eq(1)
+ is_expected.to eq(project.runners.first)
+ expect(subject.token).not_to eq(registration_token)
+ expect(subject.token).not_to eq(project.runners_token)
+ expect(subject).to be_project_type
+ end
- it 'does not create runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_falsey
- expect(subject.errors.messages).to eq('runner_projects.base': ['Maximum number of ci registered project runners (1) exceeded'])
- expect(project.runners.reload.size).to eq(1)
- end
+ context 'when it exceeds the application limits' do
+ before do
+ 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
- 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 'does not create runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.persisted?).to be_falsey
+ expect(subject.errors.messages).to eq('runner_projects.base': ['Maximum number of ci registered project runners (1) exceeded'])
+ expect(project.runners.reload.size).to eq(1)
+ end
+ end
- it 'creates runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(project.runners.reload.size).to eq(2)
- expect(project.runners.recent.size).to eq(1)
- 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
- context 'when valid runner registrars do not include project' do
+ it 'creates runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.errors).to be_empty
+ expect(project.runners.reload.size).to eq(2)
+ expect(project.runners.recent.size).to eq(1)
+ end
+ end
+
+ context 'when valid runner registrars do not include project' do
+ before do
+ stub_application_setting(valid_runner_registrars: ['group'])
+ end
+
+ context 'when feature flag is enabled' do
before do
- stub_application_setting(valid_runner_registrars: ['group'])
+ stub_feature_flags(runner_registration_control: true)
end
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
-
- it 'returns 403 error' do
- is_expected.to be_nil
- end
+ it 'returns 403 error' do
+ is_expected.to be_nil
end
+ end
- context 'when feature flag is disabled' do
- it 'registers the runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(subject.active).to be true
- end
+ context 'when feature flag is disabled' do
+ it 'registers the runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.errors).to be_empty
+ expect(subject.active).to be true
end
end
end
+ end
+
+ context 'when group token is used' do
+ let(:group) { create(:group) }
+ let(:token) { group.runners_token }
+
+ it 'creates a group runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.errors).to be_empty
+ expect(group.runners.reload.size).to eq(1)
+ expect(subject.token).not_to eq(registration_token)
+ expect(subject.token).not_to eq(group.runners_token)
+ expect(subject).to be_group_type
+ end
- context 'when group token is used' do
- let(:group) { create(:group) }
- let(:token) { group.runners_token }
+ context 'when it exceeds the application limits' do
+ before do
+ 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
- it 'creates a group runner' do
+ it 'does not create runner' do
is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
+ expect(subject.persisted?).to be_falsey
+ expect(subject.errors.messages).to eq('runner_namespaces.base': ['Maximum number of ci registered group runners (1) exceeded'])
expect(group.runners.reload.size).to eq(1)
- expect(subject.token).not_to eq(registration_token)
- expect(subject.token).not_to eq(group.runners_token)
- expect(subject).to be_group_type
end
+ end
- context 'when it exceeds the application limits' do
- before do
- 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
-
- it 'does not create runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_falsey
- expect(subject.errors.messages).to eq('runner_namespaces.base': ['Maximum number of ci registered group runners (1) exceeded'])
- expect(group.runners.reload.size).to eq(1)
- 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
- 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
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.errors).to be_empty
+ expect(group.runners.reload.size).to eq(3)
+ expect(group.runners.recent.size).to eq(1)
+ end
+ end
- it 'creates runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(group.runners.reload.size).to eq(3)
- expect(group.runners.recent.size).to eq(1)
- end
+ context 'when valid runner registrars do not include group' do
+ before do
+ stub_application_setting(valid_runner_registrars: ['project'])
end
- context 'when valid runner registrars do not include group' do
+ context 'when feature flag is enabled' do
before do
- stub_application_setting(valid_runner_registrars: ['project'])
+ stub_feature_flags(runner_registration_control: true)
end
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
-
- it 'returns nil' do
- is_expected.to be_nil
- end
+ it 'returns nil' do
+ is_expected.to be_nil
end
+ end
- context 'when feature flag is disabled' do
- it 'registers the runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(subject.active).to be true
- end
+ context 'when feature flag is disabled' do
+ it 'registers the runner' do
+ is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(subject.errors).to be_empty
+ expect(subject.active).to be true
end
end
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 4e8e41ca6e6..2421fd56c47 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -60,7 +60,8 @@ RSpec.describe Ci::RetryBuildService do
artifacts_file artifacts_metadata artifacts_size commands
resource resource_group_id processed security_scans author
pipeline_id report_results pending_state pages_deployments
- queuing_entry runtime_metadata trace_metadata].freeze
+ queuing_entry runtime_metadata trace_metadata
+ dast_site_profile dast_scanner_profile].freeze
shared_examples 'build duplication' do
let_it_be(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
@@ -370,23 +371,6 @@ RSpec.describe Ci::RetryBuildService do
it_behaves_like 'when build with deployment is retried'
it_behaves_like 'when build with dynamic environment is retried'
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- let(:new_build) do
- travel_to(1.second.from_now) do
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345668') do
- service.clone!(build)
- end
- end
- end
-
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it_behaves_like 'when build with deployment is retried'
- it_behaves_like 'when build with dynamic environment is retried'
- end
-
context 'when build has needs' do
before do
create(:ci_build_need, build: build, name: 'build1')
diff --git a/spec/services/ci/unregister_runner_service_spec.rb b/spec/services/ci/unregister_runner_service_spec.rb
new file mode 100644
index 00000000000..f427e04f228
--- /dev/null
+++ b/spec/services/ci/unregister_runner_service_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::UnregisterRunnerService, '#execute' do
+ subject { described_class.new(runner).execute }
+
+ let(:runner) { create(:ci_runner) }
+
+ it 'destroys runner' do
+ expect(runner).to receive(:destroy).once.and_call_original
+ expect { subject }.to change { Ci::Runner.count }.by(-1)
+ expect(runner[:errors]).to be_nil
+ end
+end
diff --git a/spec/services/ci/update_build_queue_service_spec.rb b/spec/services/ci/update_build_queue_service_spec.rb
index 2e2ef120f1b..ef43866d8d4 100644
--- a/spec/services/ci/update_build_queue_service_spec.rb
+++ b/spec/services/ci/update_build_queue_service_spec.rb
@@ -308,36 +308,12 @@ RSpec.describe Ci::UpdateBuildQueueService 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
-
- 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
+ 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])
+ create_list(:ci_runner, 10, :project, :online, projects: [project], tag_list: %w[b c d])
- expect { subject.tick(build) }.to exceed_all_query_limit(control_count)
- end
+ expect { subject.tick(build) }.not_to exceed_all_query_limit(control_count)
end
end
end
diff --git a/spec/services/ci/update_runner_service_spec.rb b/spec/services/ci/update_runner_service_spec.rb
index 1c875b2f54a..eee80bfef47 100644
--- a/spec/services/ci/update_runner_service_spec.rb
+++ b/spec/services/ci/update_runner_service_spec.rb
@@ -23,6 +23,20 @@ RSpec.describe Ci::UpdateRunnerService do
end
end
+ context 'with paused param' do
+ let(:params) { { paused: true } }
+
+ it 'updates the runner and ticking the queue' do
+ expect(runner.active).to be_truthy
+ expect(update).to be_truthy
+
+ runner.reload
+
+ expect(runner).to have_received(:tick_runner_queue)
+ expect(runner.active).to be_falsey
+ end
+ end
+
context 'with cost factor params' do
let(:params) { { public_projects_minutes_cost_factor: 1.1, private_projects_minutes_cost_factor: 2.2 }}
diff --git a/spec/services/concerns/rate_limited_service_spec.rb b/spec/services/concerns/rate_limited_service_spec.rb
index f73871b7e44..97f5ca53c0d 100644
--- a/spec/services/concerns/rate_limited_service_spec.rb
+++ b/spec/services/concerns/rate_limited_service_spec.rb
@@ -6,11 +6,10 @@ RSpec.describe RateLimitedService do
let(:key) { :issues_create }
let(:scope) { [:project, :current_user] }
let(:opts) { { scope: scope, users_allowlist: -> { [User.support_bot.username] } } }
- let(:rate_limiter_klass) { ::Gitlab::ApplicationRateLimiter }
- let(:rate_limiter_instance) { rate_limiter_klass.new(key, **opts) }
+ let(:rate_limiter) { ::Gitlab::ApplicationRateLimiter }
describe 'RateLimitedError' do
- subject { described_class::RateLimitedError.new(key: key, rate_limiter: rate_limiter_instance) }
+ subject { described_class::RateLimitedError.new(key: key, rate_limiter: rate_limiter) }
describe '#headers' do
it 'returns a Hash of HTTP headers' do
@@ -26,7 +25,7 @@ RSpec.describe RateLimitedService do
request = instance_double(Grape::Request)
user = instance_double(User)
- expect(rate_limiter_klass).to receive(:log_request).with(request, "#{key}_request_limit".to_sym, user)
+ expect(rate_limiter).to receive(:log_request).with(request, "#{key}_request_limit".to_sym, user)
subject.log_request(request, user)
end
@@ -34,7 +33,7 @@ RSpec.describe RateLimitedService do
end
describe 'RateLimiterScopedAndKeyed' do
- subject { described_class::RateLimiterScopedAndKeyed.new(key: key, opts: opts, rate_limiter_klass: rate_limiter_klass) }
+ subject { described_class::RateLimiterScopedAndKeyed.new(key: key, opts: opts, rate_limiter: rate_limiter) }
describe '#rate_limit!' do
let(:project_with_feature_enabled) { create(:project) }
@@ -49,13 +48,12 @@ RSpec.describe RateLimitedService do
let(:rate_limited_service_issues_create_feature_enabled) { nil }
before do
- allow(rate_limiter_klass).to receive(:new).with(key, **evaluated_opts).and_return(rate_limiter_instance)
stub_feature_flags(rate_limited_service_issues_create: rate_limited_service_issues_create_feature_enabled)
end
shared_examples 'a service that does not attempt to throttle' do
it 'does not attempt to throttle' do
- expect(rate_limiter_instance).not_to receive(:throttled?)
+ expect(rate_limiter).not_to receive(:throttled?)
expect(subject.rate_limit!(service)).to be_nil
end
@@ -63,7 +61,7 @@ RSpec.describe RateLimitedService do
shared_examples 'a service that does attempt to throttle' do
before do
- allow(rate_limiter_instance).to receive(:throttled?).and_return(throttled)
+ allow(rate_limiter).to receive(:throttled?).and_return(throttled)
end
context 'when rate limiting is not in effect' do
@@ -134,7 +132,7 @@ RSpec.describe RateLimitedService do
end
before do
- allow(RateLimitedService::RateLimiterScopedAndKeyed).to receive(:new).with(key: key, opts: opts, rate_limiter_klass: rate_limiter_klass).and_return(rate_limiter_scoped_and_keyed)
+ allow(RateLimitedService::RateLimiterScopedAndKeyed).to receive(:new).with(key: key, opts: opts, rate_limiter: rate_limiter).and_return(rate_limiter_scoped_and_keyed)
end
context 'bypasses rate limiting' do
@@ -173,12 +171,12 @@ RSpec.describe RateLimitedService do
end
before do
- allow(RateLimitedService::RateLimiterScopedAndKeyed).to receive(:new).with(key: key, opts: opts, rate_limiter_klass: rate_limiter_klass).and_return(rate_limiter_scoped_and_keyed)
+ allow(RateLimitedService::RateLimiterScopedAndKeyed).to receive(:new).with(key: key, opts: opts, rate_limiter: rate_limiter).and_return(rate_limiter_scoped_and_keyed)
end
context 'and applies rate limiting' do
it 'raises an RateLimitedService::RateLimitedError exception' do
- expect(rate_limiter_scoped_and_keyed).to receive(:rate_limit!).with(subject).and_raise(RateLimitedService::RateLimitedError.new(key: key, rate_limiter: rate_limiter_instance))
+ expect(rate_limiter_scoped_and_keyed).to receive(:rate_limit!).with(subject).and_raise(RateLimitedService::RateLimitedError.new(key: key, rate_limiter: rate_limiter))
expect { subject.execute }.to raise_error(RateLimitedService::RateLimitedError)
end
diff --git a/spec/services/draft_notes/create_service_spec.rb b/spec/services/draft_notes/create_service_spec.rb
index 9e084dbed1c..528c8717525 100644
--- a/spec/services/draft_notes/create_service_spec.rb
+++ b/spec/services/draft_notes/create_service_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe DraftNotes::CreateService do
expect(merge_request).to receive_message_chain(:diffs, :clear_cache)
- create_draft(note: 'This is a test')
+ create_draft(note: 'This is a test', line_code: '123')
end
end
@@ -104,7 +104,7 @@ RSpec.describe DraftNotes::CreateService do
expect(merge_request).not_to receive(:diffs)
- create_draft(note: 'This is a test')
+ create_draft(note: 'This is a test', line_code: '123')
end
end
end
diff --git a/spec/services/environments/stop_service_spec.rb b/spec/services/environments/stop_service_spec.rb
index acc9869002f..362071c1c26 100644
--- a/spec/services/environments/stop_service_spec.rb
+++ b/spec/services/environments/stop_service_spec.rb
@@ -185,7 +185,7 @@ RSpec.describe Environments::StopService do
end
it 'has active environment at first' do
- expect(pipeline.environments.first).to be_available
+ expect(pipeline.environments_in_self_and_descendants.first).to be_available
end
context 'when user is a developer' do
@@ -196,7 +196,7 @@ RSpec.describe Environments::StopService do
it 'stops the active environment' do
subject
- expect(pipeline.environments.first).to be_stopped
+ expect(pipeline.environments_in_self_and_descendants.first).to be_stopped
end
end
@@ -208,7 +208,7 @@ RSpec.describe Environments::StopService do
it 'does not stop the active environment' do
subject
- expect(pipeline.environments.first).to be_available
+ expect(pipeline.environments_in_self_and_descendants.first).to be_available
end
end
@@ -232,7 +232,7 @@ RSpec.describe Environments::StopService do
it 'does not stop the active environment' do
subject
- expect(pipeline.environments.first).to be_available
+ expect(pipeline.environments_in_self_and_descendants.first).to be_available
end
end
end
diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb
index abe0112b27e..f5e94c4af0f 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe FeatureFlags::UpdateService do
it 'executes hooks' do
hook = create(:project_hook, :all_events_enabled, project: project)
- expect(WebHookWorker).to receive(:perform_async).with(hook.id, an_instance_of(Hash), 'feature_flag_hooks')
+ expect(WebHookWorker).to receive(:perform_async).with(hook.id, an_instance_of(Hash), 'feature_flag_hooks', an_instance_of(Hash))
subject
end
diff --git a/spec/services/google_cloud/create_service_accounts_service_spec.rb b/spec/services/google_cloud/create_service_accounts_service_spec.rb
index 190e1a8098c..53d21df713a 100644
--- a/spec/services/google_cloud/create_service_accounts_service_spec.rb
+++ b/spec/services/google_cloud/create_service_accounts_service_spec.rb
@@ -2,22 +2,26 @@
require 'spec_helper'
-# Mock Types
-MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
-MockServiceAccount = Struct.new(:project_id, :unique_id)
-
RSpec.describe GoogleCloud::CreateServiceAccountsService do
describe '#execute' do
before do
+ mock_google_oauth2_creds = Struct.new(:app_id, :app_secret)
+ .new('mock-app-id', 'mock-app-secret')
allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
.with('google_oauth2')
- .and_return(MockGoogleOAuth2Credentials.new('mock-app-id', 'mock-app-secret'))
+ .and_return(mock_google_oauth2_creds)
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ mock_service_account = Struct.new(:project_id, :unique_id, :email)
+ .new('mock-project-id', 'mock-unique-id', 'mock-email')
allow(client).to receive(:create_service_account)
- .and_return(MockServiceAccount.new('mock-project-id', 'mock-unique-id'))
+ .and_return(mock_service_account)
+
allow(client).to receive(:create_service_account_key)
.and_return('mock-key')
+
+ allow(client)
+ .to receive(:grant_service_account_roles)
end
end
diff --git a/spec/services/google_cloud/enable_cloud_run_service_spec.rb b/spec/services/google_cloud/enable_cloud_run_service_spec.rb
new file mode 100644
index 00000000000..6d2b1f5cfd5
--- /dev/null
+++ b/spec/services/google_cloud/enable_cloud_run_service_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::EnableCloudRunService do
+ describe 'when a project does not have any gcp projects' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns error' do
+ result = described_class.new(project).execute
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.')
+ end
+ end
+
+ describe 'when a project has 3 gcp projects' do
+ let_it_be(:project) { create(:project) }
+
+ before do
+ project.variables.build(environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj-prod')
+ project.variables.build(environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj-staging')
+ project.save!
+ end
+
+ it 'enables cloud run, artifacts registry and cloud build', :aggregate_failures do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
+ expect(instance).to receive(:enable_cloud_run).with('prj-prod')
+ expect(instance).to receive(:enable_artifacts_registry).with('prj-prod')
+ expect(instance).to receive(:enable_cloud_build).with('prj-prod')
+ expect(instance).to receive(:enable_cloud_run).with('prj-staging')
+ expect(instance).to receive(:enable_artifacts_registry).with('prj-staging')
+ expect(instance).to receive(:enable_cloud_build).with('prj-staging')
+ end
+
+ result = described_class.new(project).execute
+
+ expect(result[:status]).to eq(:success)
+ end
+ end
+end
diff --git a/spec/services/google_cloud/generate_pipeline_service_spec.rb b/spec/services/google_cloud/generate_pipeline_service_spec.rb
new file mode 100644
index 00000000000..75494f229b5
--- /dev/null
+++ b/spec/services/google_cloud/generate_pipeline_service_spec.rb
@@ -0,0 +1,230 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::GeneratePipelineService do
+ describe 'for cloud-run' do
+ describe 'when there is no existing pipeline' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:service_params) { { action: described_class::ACTION_DEPLOY_TO_CLOUD_RUN } }
+ let_it_be(:service) { described_class.new(project, maintainer, service_params) }
+
+ before do
+ project.add_maintainer(maintainer)
+ end
+
+ it 'creates a new branch with commit for cloud-run deployment' do
+ response = service.execute
+
+ branch_name = response[:branch_name]
+ commit = response[:commit]
+ local_branches = project.repository.local_branches
+ created_branch = local_branches.find { |branch| branch.name == branch_name }
+
+ expect(response[:status]).to eq(:success)
+ expect(branch_name).to start_with('deploy-to-cloud-run-')
+ expect(created_branch).to be_present
+ expect(created_branch.target).to eq(commit[:result])
+ end
+
+ it 'generated pipeline includes cloud-run deployment' do
+ response = service.execute
+
+ ref = response[:commit][:result]
+ gitlab_ci_yml = project.repository.gitlab_ci_yml_for(ref)
+
+ expect(response[:status]).to eq(:success)
+ expect(gitlab_ci_yml).to include('https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-run.gitlab-ci.yml')
+ end
+
+ context 'simulate errors' do
+ it 'fails to create branch' do
+ allow_next_instance_of(Branches::CreateService) do |create_service|
+ allow(create_service).to receive(:execute)
+ .and_return({ status: :error })
+ end
+
+ response = service.execute
+ expect(response[:status]).to eq(:error)
+ end
+
+ it 'fails to commit changes' do
+ allow_next_instance_of(Files::CreateService) do |create_service|
+ allow(create_service).to receive(:execute)
+ .and_return({ status: :error })
+ end
+
+ response = service.execute
+ expect(response[:status]).to eq(:error)
+ end
+ end
+ end
+
+ describe 'when there is an existing pipeline without `deploy` stage' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } }
+ let_it_be(:service) { described_class.new(project, maintainer, service_params) }
+
+ before do
+ project.add_maintainer(maintainer)
+
+ file_name = '.gitlab-ci.yml'
+ file_content = <<EOF
+stages:
+ - build
+ - test
+
+build-java:
+ stage: build
+ script: mvn clean install
+
+test-java:
+ stage: test
+ script: mvn clean test
+EOF
+ project.repository.create_file(maintainer,
+ file_name,
+ file_content,
+ message: 'Pipeline with three stages and two jobs',
+ branch_name: project.default_branch)
+ end
+
+ it 'introduces a `deploy` stage and includes the deploy-to-cloud-run job' do
+ response = service.execute
+
+ branch_name = response[:branch_name]
+ gitlab_ci_yml = project.repository.gitlab_ci_yml_for(branch_name)
+ pipeline = Gitlab::Config::Loader::Yaml.new(gitlab_ci_yml).load!
+
+ expect(response[:status]).to eq(:success)
+ expect(pipeline[:stages]).to eq(%w[build test deploy])
+ expect(pipeline[:include]).to be_present
+ expect(gitlab_ci_yml).to include('https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-run.gitlab-ci.yml')
+ end
+ end
+
+ describe 'when there is an existing pipeline with `deploy` stage' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } }
+ let_it_be(:service) { described_class.new(project, maintainer, service_params) }
+
+ before do
+ project.add_maintainer(maintainer)
+
+ file_name = '.gitlab-ci.yml'
+ file_content = <<EOF
+stages:
+ - build
+ - test
+ - deploy
+
+build-java:
+ stage: build
+ script: mvn clean install
+
+test-java:
+ stage: test
+ script: mvn clean test
+EOF
+ project.repository.create_file(maintainer,
+ file_name,
+ file_content,
+ message: 'Pipeline with three stages and two jobs',
+ branch_name: project.default_branch)
+ end
+
+ it 'includes the deploy-to-cloud-run job' do
+ response = service.execute
+
+ branch_name = response[:branch_name]
+ gitlab_ci_yml = project.repository.gitlab_ci_yml_for(branch_name)
+ pipeline = Gitlab::Config::Loader::Yaml.new(gitlab_ci_yml).load!
+
+ expect(response[:status]).to eq(:success)
+ expect(pipeline[:stages]).to eq(%w[build test deploy])
+ expect(pipeline[:include]).to be_present
+ expect(gitlab_ci_yml).to include('https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-run.gitlab-ci.yml')
+ end
+ end
+
+ describe 'when there is an existing pipeline with `includes`' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } }
+ let_it_be(:service) { described_class.new(project, maintainer, service_params) }
+
+ before do
+ project.add_maintainer(maintainer)
+
+ file_name = '.gitlab-ci.yml'
+ file_content = <<EOF
+stages:
+ - build
+ - test
+ - deploy
+
+include:
+ local: 'some-pipeline.yml'
+EOF
+ project.repository.create_file(maintainer,
+ file_name,
+ file_content,
+ message: 'Pipeline with three stages and two jobs',
+ branch_name: project.default_branch)
+ end
+
+ it 'includes the deploy-to-cloud-run job' do
+ response = service.execute
+
+ branch_name = response[:branch_name]
+ gitlab_ci_yml = project.repository.gitlab_ci_yml_for(branch_name)
+ pipeline = Gitlab::Config::Loader::Yaml.new(gitlab_ci_yml).load!
+
+ expect(response[:status]).to eq(:success)
+ expect(pipeline[:stages]).to eq(%w[build test deploy])
+ expect(pipeline[:include]).to be_present
+ expect(gitlab_ci_yml).to include('https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-run.gitlab-ci.yml')
+ end
+ end
+ end
+
+ describe 'for cloud-storage' do
+ describe 'when there is no existing pipeline' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_STORAGE } }
+ let_it_be(:service) { described_class.new(project, maintainer, service_params) }
+
+ before do
+ project.add_maintainer(maintainer)
+ end
+
+ it 'creates a new branch with commit for cloud-storage deployment' do
+ response = service.execute
+
+ branch_name = response[:branch_name]
+ commit = response[:commit]
+ local_branches = project.repository.local_branches
+ search_for_created_branch = local_branches.find { |branch| branch.name == branch_name }
+
+ expect(response[:status]).to eq(:success)
+ expect(branch_name).to start_with('deploy-to-cloud-storage-')
+ expect(search_for_created_branch).to be_present
+ expect(search_for_created_branch.target).to eq(commit[:result])
+ end
+
+ it 'generated pipeline includes cloud-storage deployment' do
+ response = service.execute
+
+ ref = response[:commit][:result]
+ gitlab_ci_yml = project.repository.gitlab_ci_yml_for(ref)
+
+ expect(response[:status]).to eq(:success)
+ expect(gitlab_ci_yml).to include('https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-storage.gitlab-ci.yml')
+ end
+ end
+ end
+end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 81cab973b30..7ec523a1f2b 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -8,6 +8,10 @@ RSpec.describe Groups::CreateService, '#execute' do
subject { service.execute }
+ shared_examples 'has sync-ed traversal_ids' do
+ specify { expect(subject.reload.traversal_ids).to eq([subject.parent&.traversal_ids, subject.id].flatten.compact) }
+ end
+
describe 'visibility level restrictions' do
let!(:service) { described_class.new(user, group_params) }
@@ -77,6 +81,18 @@ RSpec.describe Groups::CreateService, '#execute' do
it 'adds an onboarding progress record' do
expect { subject }.to change(OnboardingProgress, :count).from(0).to(1)
end
+
+ context 'with before_commit callback' do
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
+
+ context 'with after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
+ end
+
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
end
context 'when user can not create a group' do
@@ -102,6 +118,18 @@ RSpec.describe Groups::CreateService, '#execute' do
it 'does not add an onboarding progress record' do
expect { subject }.not_to change(OnboardingProgress, :count).from(0)
end
+
+ context 'with before_commit callback' do
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
+
+ context 'with after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
+ end
+
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
end
context 'as guest' do
@@ -289,4 +317,33 @@ RSpec.describe Groups::CreateService, '#execute' do
end
end
end
+
+ describe 'logged_out_marketing_header experiment', :experiment do
+ let(:service) { described_class.new(user, group_params) }
+
+ subject { service.execute }
+
+ before do
+ stub_experiments(logged_out_marketing_header: :candidate)
+ end
+
+ it 'tracks signed_up event' do
+ expect(experiment(:logged_out_marketing_header)).to track(
+ :namespace_created,
+ namespace: an_instance_of(Group)
+ ).on_next_instance.with_context(actor: user)
+
+ subject
+ end
+
+ context 'when group has not been persisted' do
+ let(:service) { described_class.new(user, group_params.merge(name: '<script>alert("Attack!")</script>')) }
+
+ it 'does not track signed_up event' do
+ expect(experiment(:logged_out_marketing_header)).not_to track(:namespace_created)
+
+ subject
+ end
+ end
+ end
end
diff --git a/spec/services/groups/update_statistics_service_spec.rb b/spec/services/groups/update_statistics_service_spec.rb
new file mode 100644
index 00000000000..5bef51c2727
--- /dev/null
+++ b/spec/services/groups/update_statistics_service_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::UpdateStatisticsService do
+ let_it_be(:group, reload: true) { create(:group) }
+
+ let(:statistics) { %w(wiki_size) }
+
+ subject(:service) { described_class.new(group, statistics: statistics)}
+
+ describe '#execute', :aggregate_failures do
+ context 'when group is nil' do
+ let(:group) { nil }
+
+ it 'does nothing' do
+ expect(NamespaceStatistics).not_to receive(:new)
+
+ result = service.execute
+
+ expect(result).to be_error
+ end
+ end
+
+ context 'with an existing group' do
+ context 'when namespace statistics exists for the group' do
+ it 'uses the existing statistics and refreshes them' do
+ namespace_statistics = create(:namespace_statistics, namespace: group)
+
+ expect(namespace_statistics).to receive(:refresh!).with(only: statistics.map(&:to_sym)).and_call_original
+
+ result = service.execute
+
+ expect(result).to be_success
+ end
+ end
+
+ context 'when namespace statistics does not exist for the group' do
+ it 'creates the statistics and refreshes them' do
+ expect_next_instance_of(NamespaceStatistics) do |instance|
+ expect(instance).to receive(:refresh!).with(only: statistics.map(&:to_sym)).and_call_original
+ end
+
+ result = nil
+
+ expect do
+ result = service.execute
+ end.to change { NamespaceStatistics.count }.by(1)
+
+ expect(result).to be_success
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/incident_management/create_incident_label_service_spec.rb b/spec/services/incident_management/create_incident_label_service_spec.rb
deleted file mode 100644
index 441cddf1d2e..00000000000
--- a/spec/services/incident_management/create_incident_label_service_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IncidentManagement::CreateIncidentLabelService do
- it_behaves_like 'incident management label service'
-end
diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb
index 47ce9d01f66..ac44bc4608c 100644
--- a/spec/services/incident_management/incidents/create_service_spec.rb
+++ b/spec/services/incident_management/incidents/create_service_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
context 'when incident has title and description' do
let(:title) { 'Incident title' }
let(:new_issue) { Issue.last! }
- let(:label_title) { attributes_for(:label, :incident)[:title] }
it 'responds with success' do
expect(create_incident).to be_success
@@ -38,8 +37,6 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
end
let(:issue) { new_issue }
-
- include_examples 'does not have incident label'
end
context 'with default severity' do
@@ -69,20 +66,6 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
end
end
end
-
- context 'when incident label does not exists' do
- it 'does not create incident label' do
- expect { create_incident }.to not_change { project.labels.where(title: label_title).count }
- end
- end
-
- context 'when incident label already exists' do
- let!(:label) { create(:label, project: project, title: label_title) }
-
- it 'does not create new labels' do
- expect { create_incident }.not_to change(Label, :count)
- end
- end
end
context 'when incident has no title' do
@@ -100,6 +83,25 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
it 'result payload contains an Issue object' do
expect(create_incident.payload[:issue]).to be_kind_of(Issue)
end
+
+ context 'with alert' do
+ let(:alert) { create(:alert_management_alert, project: project) }
+
+ subject(:create_incident) { described_class.new(project, user, title: title, description: description, alert: alert).execute }
+
+ it 'associates the alert with the incident' do
+ expect(create_incident[:issue].alert_management_alert).to eq(alert)
+ end
+
+ context 'the alert prevents the issue from saving' do
+ let(:alert) { create(:alert_management_alert, :with_validation_errors, project: project) }
+
+ it 'responds with errors' do
+ expect(create_incident).to be_error
+ expect(create_incident.message).to eq('Hosts hosts array is over 255 chars')
+ end
+ end
+ end
end
end
end
diff --git a/spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb b/spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb
index e9db6ba8d28..731406613dd 100644
--- a/spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb
+++ b/spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb
@@ -30,7 +30,15 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::AfterUpdateServic
end
end
+ shared_examples 'adds a status change system note' do
+ specify do
+ expect { result }.to change { issue.reload.notes.count }.by(1)
+ end
+ end
+
context 'with status attributes' do
+ it_behaves_like 'adds a status change system note'
+
it 'updates the alert with the new alert status' do
expect(::AlertManagement::Alerts::UpdateService).to receive(:new).once.and_call_original
expect(described_class).to receive(:new).once.and_call_original
@@ -45,12 +53,15 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::AfterUpdateServic
end
it_behaves_like 'does not attempt to update the alert'
+ it_behaves_like 'adds a status change system note'
end
context 'when new status matches the current status' do
let(:status_event) { :trigger }
it_behaves_like 'does not attempt to update the alert'
+
+ specify { expect { result }.not_to change { issue.reload.notes.count } }
end
end
end
diff --git a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
index bfed5319028..b30b3a69ae6 100644
--- a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
+++ b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
end
shared_examples 'invalid params error response' do
- include_examples 'error response', 'Invalid value was provided for a parameter.'
+ include_examples 'error response', 'Invalid value was provided for parameters: status'
end
it_behaves_like 'successful response', { status_event: :acknowledge }
@@ -105,4 +105,10 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
it_behaves_like 'successful response', { status_event: :acknowledge }
end
end
+
+ context 'with status_change_reason param' do
+ let(:params) { { status_change_reason: ' by changing the incident status' } }
+
+ it_behaves_like 'successful response', { status_change_reason: ' by changing the incident status' }
+ end
end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index 158f9dec83e..1f6118e9fcc 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Issues::CloseService do
expect { service.execute(issue) }.to change { issue.notes.count }.by(1)
new_note = issue.notes.last
- expect(new_note.note).to eq('changed the status to **Resolved** by closing the incident')
+ expect(new_note.note).to eq('changed the incident status to **Resolved** by closing the incident')
expect(new_note.author).to eq(user)
end
@@ -334,8 +334,12 @@ RSpec.describe Issues::CloseService do
let!(:alert) { create(:alert_management_alert, issue: issue, project: project) }
it 'resolves an alert and sends a system note' do
- expect_next_instance_of(SystemNotes::AlertManagementService) do |notes_service|
- expect(notes_service).to receive(:closed_alert_issue).with(issue)
+ expect_any_instance_of(SystemNoteService) do |notes_service|
+ expect(notes_service).to receive(:change_alert_status).with(
+ alert,
+ current_user,
+ " by closing issue #{issue.to_reference(project)}"
+ )
end
close_issue
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index b2dcfb5c6d3..f4bb1f0877b 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Issues::CreateService do
expect(described_class.rate_limiter_scoped_and_keyed.key).to eq(:issues_create)
expect(described_class.rate_limiter_scoped_and_keyed.opts[:scope]).to eq(%i[project current_user external_author])
- expect(described_class.rate_limiter_scoped_and_keyed.rate_limiter_klass).to eq(Gitlab::ApplicationRateLimiter)
+ expect(described_class.rate_limiter_scoped_and_keyed.rate_limiter).to eq(Gitlab::ApplicationRateLimiter)
end
end
@@ -92,6 +92,21 @@ RSpec.describe Issues::CreateService do
end
end
+ context 'when setting a position' do
+ let(:issue_before) { create(:issue, project: project, relative_position: 10) }
+ let(:issue_after) { create(:issue, project: project, relative_position: 50) }
+
+ before do
+ opts.merge!(move_between_ids: [issue_before.id, issue_after.id])
+ end
+
+ it 'sets the correct relative position' do
+ expect(issue).to be_persisted
+ expect(issue.relative_position).to be_present
+ expect(issue.relative_position).to be_between(issue_before.relative_position, issue_after.relative_position)
+ end
+ end
+
it_behaves_like 'not an incident issue'
context 'when issue is incident type' do
@@ -100,7 +115,6 @@ RSpec.describe Issues::CreateService do
end
let(:current_user) { user }
- let(:incident_label_attributes) { attributes_for(:label, :incident) }
subject { issue }
@@ -114,12 +128,6 @@ RSpec.describe Issues::CreateService do
end
it_behaves_like 'incident issue'
- it_behaves_like 'does not have incident label'
-
- it 'does not create an incident label' do
- expect { subject }
- .to not_change { Label.where(incident_label_attributes).count }
- end
it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index ef501f47f0d..35a380e01d0 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -168,6 +168,48 @@ RSpec.describe Issues::MoveService do
end
end
+ context 'issue with contacts' do
+ let_it_be(:contacts) { create_list(:contact, 2, group: group) }
+
+ before do
+ old_issue.customer_relations_contacts = contacts
+ end
+
+ it 'preserves contacts' do
+ new_issue = move_service.execute(old_issue, new_project)
+
+ expect(new_issue.customer_relations_contacts).to eq(contacts)
+ end
+
+ context 'when moving to another root group' do
+ let(:another_project) { create(:project, namespace: create(:group)) }
+
+ before do
+ another_project.add_reporter(user)
+ end
+
+ it 'does not preserve contacts' do
+ new_issue = move_service.execute(old_issue, another_project)
+
+ expect(new_issue.customer_relations_contacts).to be_empty
+ end
+ end
+
+ context 'when customer_relations feature is disabled' do
+ let(:another_project) { create(:project, namespace: create(:group)) }
+
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it 'does not preserve contacts' do
+ new_issue = move_service.execute(old_issue, new_project)
+
+ expect(new_issue.customer_relations_contacts).to be_empty
+ end
+ end
+ end
+
context 'moving to same project' do
let(:new_project) { old_project }
diff --git a/spec/services/issues/reorder_service_spec.rb b/spec/services/issues/reorder_service_spec.rb
index 15668a3aa23..392930c1b9f 100644
--- a/spec/services/issues/reorder_service_spec.rb
+++ b/spec/services/issues/reorder_service_spec.rb
@@ -67,20 +67,10 @@ RSpec.describe Issues::ReorderService do
it_behaves_like 'issues reorder service'
context 'when ordering in a group issue list' do
- let(:params) { { move_after_id: issue2.id, move_before_id: issue3.id, group_full_path: group.full_path } }
+ let(:params) { { move_after_id: issue2.id, move_before_id: issue3.id } }
subject { service(params) }
- it 'sends the board_group_id parameter' do
- match_params = { move_between_ids: [issue2.id, issue3.id], board_group_id: group.id }
-
- expect(Issues::UpdateService)
- .to receive(:new).with(project: project, current_user: user, params: match_params)
- .and_return(double(execute: build(:issue)))
-
- subject.execute(issue1)
- end
-
it 'sorts issues' do
project2 = create(:project, namespace: group)
issue4 = create(:issue, project: project2)
diff --git a/spec/services/issues/set_crm_contacts_service_spec.rb b/spec/services/issues/set_crm_contacts_service_spec.rb
index 2418f317551..64011a7a003 100644
--- a/spec/services/issues/set_crm_contacts_service_spec.rb
+++ b/spec/services/issues/set_crm_contacts_service_spec.rb
@@ -7,20 +7,41 @@ RSpec.describe Issues::SetCrmContactsService do
let_it_be(:group) { create(:group, :crm_enabled) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:contacts) { create_list(:contact, 4, group: group) }
+ let_it_be(:issue, reload: true) { create(:issue, project: project) }
+ let_it_be(:issue_contact_1) do
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[0]).contact
+ end
- let(:issue) { create(:issue, project: project) }
- let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
-
- before do
- create(:issue_customer_relations_contact, issue: issue, contact: contacts[0])
- create(:issue_customer_relations_contact, issue: issue, contact: contacts[1])
+ let_it_be(:issue_contact_2) do
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[1]).contact
end
+ let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
+
subject(:set_crm_contacts) do
described_class.new(project: project, current_user: user, params: params).execute(issue)
end
describe '#execute' do
+ shared_examples 'setting contacts' do
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array(expected_contacts)
+ end
+ end
+
+ shared_examples 'adds system note' do |added_count, removed_count|
+ it 'calls SystemNoteService.change_issuable_contacts with correct counts' do
+ expect(SystemNoteService)
+ .to receive(:change_issuable_contacts)
+ .with(issue, project, user, added_count, removed_count)
+
+ set_crm_contacts
+ end
+ end
+
context 'when the user has no permission' do
let(:params) { { replace_ids: [contacts[1].id, contacts[2].id] } }
@@ -67,56 +88,63 @@ RSpec.describe Issues::SetCrmContactsService do
context 'replace' do
let(:params) { { replace_ids: [contacts[1].id, contacts[2].id] } }
+ let(:expected_contacts) { [contacts[1], contacts[2]] }
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
-
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[1], contacts[2]])
- end
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 1, 1
end
context 'add' do
- let(:params) { { add_ids: [contacts[3].id] } }
-
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
+ let(:added_contact) { contacts[3] }
+ let(:params) { { add_ids: [added_contact.id] } }
+ let(:expected_contacts) { [issue_contact_1, issue_contact_2, added_contact] }
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[1], contacts[3]])
- end
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 1, 0
end
context 'add by email' do
- let(:params) { { add_emails: [contacts[3].email] } }
+ let(:added_contact) { contacts[3] }
+ let(:expected_contacts) { [issue_contact_1, issue_contact_2, added_contact] }
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
+ context 'with pure emails in params' do
+ let(:params) { { add_emails: [contacts[3].email] } }
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[1], contacts[3]])
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 1, 0
+ end
+
+ context 'with autocomplete prefix emails in params' do
+ let(:params) { { add_emails: ["[\"contact:\"#{contacts[3].email}\"]"] } }
+
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 1, 0
end
end
context 'remove' do
let(:params) { { remove_ids: [contacts[0].id] } }
+ let(:expected_contacts) { [contacts[1]] }
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
-
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[1]])
- end
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 0, 1
end
context 'remove by email' do
- let(:params) { { remove_emails: [contacts[0].email] } }
+ let(:expected_contacts) { [contacts[1]] }
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
+ context 'with pure email in params' do
+ let(:params) { { remove_emails: [contacts[0].email] } }
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[1]])
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 0, 1
+ end
+
+ context 'with autocomplete prefix and suffix email in params' do
+ let(:params) { { remove_emails: ["[contact:#{contacts[0].email}]"] } }
+
+ it_behaves_like 'setting contacts'
+ it_behaves_like 'adds system note', 0, 1
end
end
@@ -145,15 +173,19 @@ RSpec.describe Issues::SetCrmContactsService do
context 'when combining params' do
let(:error_invalid_params) { 'You cannot combine replace_ids with add_ids or remove_ids' }
+ let(:expected_contacts) { [contacts[0], contacts[3]] }
context 'add and remove' do
- let(:params) { { remove_ids: [contacts[1].id], add_ids: [contacts[3].id] } }
+ context 'with contact ids' do
+ let(:params) { { remove_ids: [contacts[1].id], add_ids: [contacts[3].id] } }
- it 'updates the issue with correct contacts' do
- response = set_crm_contacts
+ it_behaves_like 'setting contacts'
+ end
+
+ context 'with contact emails' do
+ let(:params) { { remove_emails: [contacts[1].email], add_emails: ["[\"contact:#{contacts[3].email}]"] } }
- expect(response).to be_success
- expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[3]])
+ it_behaves_like 'setting contacts'
end
end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 11ed47b84d9..95394ba6597 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -385,7 +385,6 @@ RSpec.describe Issues::UpdateService, :mailer do
[issue_1, issue_2, issue_3].map(&:save)
opts[:move_between_ids] = [issue_1.id, issue_2.id]
- opts[:board_group_id] = group.id
described_class.new(project: issue_3.project, current_user: user, params: opts).execute(issue_3)
expect(issue_2.relative_position).to be_between(issue_1.relative_position, issue_2.relative_position)
@@ -1147,11 +1146,11 @@ RSpec.describe Issues::UpdateService, :mailer do
let(:opts) { { escalation_status: { status: 'acknowledged' } } }
let(:escalation_update_class) { ::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService }
- shared_examples 'updates the escalation status record' do |expected_status|
+ shared_examples 'updates the escalation status record' do |expected_status, expected_reason = nil|
let(:service_double) { instance_double(escalation_update_class) }
it 'has correct value' do
- expect(escalation_update_class).to receive(:new).with(issue, user).and_return(service_double)
+ expect(escalation_update_class).to receive(:new).with(issue, user, status_change_reason: expected_reason).and_return(service_double)
expect(service_double).to receive(:execute)
update_issue(opts)
@@ -1197,6 +1196,12 @@ RSpec.describe Issues::UpdateService, :mailer do
end
end
+ context 'with a status change reason provided' do
+ let(:opts) { { escalation_status: { status: 'acknowledged', status_change_reason: ' by changing the alert status' } } }
+
+ it_behaves_like 'updates the escalation status record', :acknowledged, ' by changing the alert status'
+ end
+
context 'with unsupported status value' do
let(:opts) { { escalation_status: { status: 'unsupported-status' } } }
@@ -1303,19 +1308,12 @@ RSpec.describe Issues::UpdateService, :mailer do
end
context 'when moving an issue ' do
- it 'raises an error for invalid move ids within a project' do
+ it 'raises an error for invalid move ids' do
opts = { move_between_ids: [9000, non_existing_record_id] }
expect { described_class.new(project: issue.project, current_user: user, params: opts).execute(issue) }
.to raise_error(ActiveRecord::RecordNotFound)
end
-
- it 'raises an error for invalid move ids within a group' do
- opts = { move_between_ids: [9000, non_existing_record_id], board_group_id: create(:group).id }
-
- expect { described_class.new(project: issue.project, current_user: user, params: opts).execute(issue) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
end
include_examples 'issuable update service' do
diff --git a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
index d3d57ea2444..538d9638879 100644
--- a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
+++ b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
@@ -115,4 +115,82 @@ RSpec.describe LooseForeignKeys::BatchCleanerService do
expect(loose_fk_child_table_2.where(parent_id_with_different_column: other_parent_record.id).count).to eq(2)
end
end
+
+ describe 'fair queueing' do
+ context 'when the execution is over the limit' do
+ let(:modification_tracker) { instance_double(LooseForeignKeys::ModificationTracker) }
+ let(:over_limit_return_values) { [true] }
+ let(:deleted_record) { LooseForeignKeys::DeletedRecord.load_batch_for_table('public._test_loose_fk_parent_table', 1).first }
+ let(:deleted_records_rescheduled_counter) { Gitlab::Metrics.registry.get(:loose_foreign_key_rescheduled_deleted_records) }
+ let(:deleted_records_incremented_counter) { Gitlab::Metrics.registry.get(:loose_foreign_key_incremented_deleted_records) }
+
+ let(:cleaner) do
+ described_class.new(parent_table: '_test_loose_fk_parent_table',
+ loose_foreign_key_definitions: loose_foreign_key_definitions,
+ deleted_parent_records: LooseForeignKeys::DeletedRecord.load_batch_for_table('public._test_loose_fk_parent_table', 100),
+ modification_tracker: modification_tracker
+ )
+ end
+
+ before do
+ parent_record_1.delete
+ allow(modification_tracker).to receive(:over_limit?).and_return(*over_limit_return_values)
+ allow(modification_tracker).to receive(:add_deletions)
+ end
+
+ context 'when the deleted record is under the maximum allowed cleanup attempts' do
+ it 'updates the cleanup_attempts column', :aggregate_failures do
+ deleted_record.update!(cleanup_attempts: 1)
+
+ cleaner.execute
+
+ expect(deleted_record.reload.cleanup_attempts).to eq(2)
+ expect(deleted_records_incremented_counter.get(table: loose_fk_parent_table.table_name, db_config_name: 'main')).to eq(1)
+ end
+
+ context 'when the deleted record is above the maximum allowed cleanup attempts' do
+ it 'reschedules the record', :aggregate_failures do
+ deleted_record.update!(cleanup_attempts: LooseForeignKeys::BatchCleanerService::CLEANUP_ATTEMPTS_BEFORE_RESCHEDULE + 1)
+
+ freeze_time do
+ cleaner.execute
+
+ expect(deleted_record.reload).to have_attributes(
+ cleanup_attempts: 0,
+ consume_after: 5.minutes.from_now
+ )
+ expect(deleted_records_rescheduled_counter.get(table: loose_fk_parent_table.table_name, db_config_name: 'main')).to eq(1)
+ end
+ end
+ end
+
+ describe 'when over limit happens on the second cleanup call without skip locked' do
+ # over_limit? is called twice, we test here the 2nd call
+ # - When invoking cleanup with SKIP LOCKED
+ # - When invoking cleanup (no SKIP LOCKED)
+ let(:over_limit_return_values) { [false, true] }
+
+ it 'updates the cleanup_attempts column' do
+ expect(cleaner).to receive(:run_cleaner_service).twice
+
+ deleted_record.update!(cleanup_attempts: 1)
+
+ cleaner.execute
+
+ expect(deleted_record.reload.cleanup_attempts).to eq(2)
+ end
+ end
+ end
+
+ context 'when the lfk_fair_queueing FF is off' do
+ before do
+ stub_feature_flags(lfk_fair_queueing: false)
+ end
+
+ it 'does nothing' do
+ expect { cleaner.execute }.not_to change { deleted_record.reload.cleanup_attempts }
+ end
+ end
+ end
+ end
end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 13f56fe7458..4d9e69719b4 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -39,6 +39,15 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
expect(source.users).to include member
expect(OnboardingProgress.completed?(source, :user_added)).to be(true)
end
+
+ it 'triggers a members added event' do
+ expect(Gitlab::EventStore)
+ .to receive(:publish)
+ .with(an_instance_of(Members::MembersAddedEvent))
+ .and_call_original
+
+ expect(execute_service[:status]).to eq(:success)
+ end
end
end
@@ -108,6 +117,24 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
user: user
)
end
+
+ context 'with an already existing member' do
+ before do
+ source.add_developer(member)
+ end
+
+ 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
end
context 'when it is a net_new_user' do
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index 781be57d709..2155b4ffad1 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -89,10 +89,10 @@ RSpec.describe MergeRequests::AfterCreateService do
merge_request.mark_as_preparing!
end
- it 'marks the merge request as unchecked' do
- execute_service
+ it 'checks for mergeability' do
+ expect(merge_request).to receive(:check_mergeability).with(async: true)
- expect(merge_request.reload).to be_unchecked
+ execute_service
end
context 'when preparing for mergeability fails' do
@@ -108,17 +108,6 @@ RSpec.describe MergeRequests::AfterCreateService do
expect { execute_service }.to raise_error(StandardError)
expect(merge_request.reload).to be_preparing
end
-
- context 'when early_prepare_for_mergeability feature flag is disabled' do
- before do
- stub_feature_flags(early_prepare_for_mergeability: false)
- end
-
- it 'does not mark the merge request as unchecked' do
- expect { execute_service }.to raise_error(StandardError)
- expect(merge_request.reload).to be_preparing
- end
- end
end
context 'when preparing merge request fails' do
@@ -130,20 +119,9 @@ RSpec.describe MergeRequests::AfterCreateService do
.and_raise(StandardError)
end
- it 'still marks the merge request as unchecked' do
+ it 'still checks for mergeability' do
+ expect(merge_request).to receive(:check_mergeability).with(async: true)
expect { execute_service }.to raise_error(StandardError)
- expect(merge_request.reload).to be_unchecked
- end
-
- context 'when early_prepare_for_mergeability feature flag is disabled' do
- before do
- stub_feature_flags(early_prepare_for_mergeability: false)
- end
-
- it 'does not mark the merge request as unchecked' do
- expect { execute_service }.to raise_error(StandardError)
- expect(merge_request.reload).to be_preparing
- end
end
end
end
diff --git a/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb b/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
index fe4ce0dab5e..ae8846974ce 100644
--- a/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
+++ b/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe MergeRequests::BulkRemoveAttentionRequestedService do
let(:reviewer) { merge_request.find_reviewer(user) }
let(:assignee) { merge_request.find_assignee(assignee_user) }
let(:project) { merge_request.project }
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request) }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, users: [user, assignee_user]) }
let(:result) { service.execute }
before do
@@ -20,7 +20,7 @@ RSpec.describe MergeRequests::BulkRemoveAttentionRequestedService do
describe '#execute' do
context 'invalid permissions' do
- let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request) }
+ let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request, users: [user]) }
it 'returns an error' do
expect(result[:status]).to eq :error
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index da547716e1e..a196c944eda 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -61,19 +61,19 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(merge_request.reload).to be_preparing
end
- describe 'when marked with /wip' do
+ describe 'when marked with /draft' do
context 'in title and in description' do
let(:opts) do
{
- title: 'WIP: Awesome merge_request',
- description: "well this is not done yet\n/wip",
+ title: 'Draft: Awesome merge_request',
+ description: "well this is not done yet\n/draft",
source_branch: 'feature',
target_branch: 'master',
assignees: [user2]
}
end
- it 'sets MR to WIP' do
+ it 'sets MR to draft' do
expect(merge_request.work_in_progress?).to be(true)
end
end
@@ -89,7 +89,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
}
end
- it 'sets MR to WIP' do
+ it 'sets MR to draft' do
expect(merge_request.work_in_progress?).to be(true)
end
end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 127c94763d9..ecb856bd1a4 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -388,7 +388,7 @@ RSpec.describe MergeRequests::MergeService do
end
it 'logs and saves error if there is an error when squashing' do
- error_message = 'Failed to squash. Should be done manually'
+ error_message = 'Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch.'
allow_any_instance_of(MergeRequests::SquashService).to receive(:squash!).and_return(nil)
merge_request.update!(squash: true)
diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb
index 65599b7e046..c24b83e21a6 100644
--- a/spec/services/merge_requests/mergeability_check_service_spec.rb
+++ b/spec/services/merge_requests/mergeability_check_service_spec.rb
@@ -73,12 +73,10 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) }
describe '#async_execute' do
- shared_examples_for 'no job is enqueued' do
- it 'does not enqueue MergeRequestMergeabilityCheckWorker' do
- expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async)
+ it 'updates merge status to checking' do
+ described_class.new(merge_request).async_execute
- described_class.new(merge_request).async_execute
- end
+ expect(merge_request).to be_checking
end
it 'enqueues MergeRequestMergeabilityCheckWorker' do
@@ -92,15 +90,11 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
allow(Gitlab::Database).to receive(:read_only?) { true }
end
- it_behaves_like 'no job is enqueued'
- end
+ it 'does not enqueue MergeRequestMergeabilityCheckWorker' do
+ expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async)
- context 'when merge_status is already checking' do
- before do
- merge_request.mark_as_checking
+ described_class.new(merge_request).async_execute
end
-
- it_behaves_like 'no job is enqueued'
end
end
diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb
index e671bbf2cd6..a47e626666b 100644
--- a/spec/services/merge_requests/rebase_service_spec.rb
+++ b/spec/services/merge_requests/rebase_service_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe MergeRequests::RebaseService do
context 'with a pre-receive failure' do
let(:pre_receive_error) { "Commit message does not follow the pattern 'ACME'" }
- let(:merge_error) { "Something went wrong during the rebase pre-receive hook: #{pre_receive_error}." }
+ let(:merge_error) { "The rebase pre-receive hook failed: #{pre_receive_error}." }
before do
allow(repository).to receive(:gitaly_operation_client).and_raise(Gitlab::Git::PreReceiveError, "GitLab: #{pre_receive_error}")
diff --git a/spec/services/merge_requests/squash_service_spec.rb b/spec/services/merge_requests/squash_service_spec.rb
index e5bea0e7b14..387be8471b5 100644
--- a/spec/services/merge_requests/squash_service_spec.rb
+++ b/spec/services/merge_requests/squash_service_spec.rb
@@ -168,7 +168,7 @@ RSpec.describe MergeRequests::SquashService do
it 'raises a squash error' do
expect(service.execute).to match(
status: :error,
- message: a_string_including('does not allow squashing commits when merge requests are accepted'))
+ message: a_string_including('allow you to squash commits when merging'))
end
end
@@ -205,7 +205,7 @@ RSpec.describe MergeRequests::SquashService do
end
it 'returns an error' do
- expect(service.execute).to match(status: :error, message: a_string_including('squash'))
+ expect(service.execute).to match(status: :error, message: a_string_including('Squash'))
end
end
end
@@ -232,7 +232,7 @@ RSpec.describe MergeRequests::SquashService do
end
it 'returns an error' do
- expect(service.execute).to match(status: :error, message: a_string_including('squash'))
+ expect(service.execute).to match(status: :error, message: a_string_including('Squash'))
end
it 'cleans up the temporary directory' do
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 2925dad7f6b..48d9f019274 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -102,16 +102,16 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2)
end
- it 'tracks Draft/WIP marking' do
+ it 'tracks Draft marking' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_marked_as_draft_action).once.with(user: user)
- opts[:title] = "WIP: #{opts[:title]}"
+ opts[:title] = "Draft: #{opts[:title]}"
MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2)
end
- it 'tracks Draft/WIP un-marking' do
+ it 'tracks Draft un-marking' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_unmarked_as_draft_action).once.with(user: user)
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 1fb50b07b3b..babbd44a9f1 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -325,11 +325,11 @@ RSpec.describe Notes::CreateService do
expect(issuable.work_in_progress?).to eq(can_use_quick_action)
}
),
- # Remove WIP status
+ # Remove draft status
QuickAction.new(
action_text: "/draft",
before_action: -> {
- issuable.reload.update!(title: "WIP: title")
+ issuable.reload.update!(title: "Draft: title")
},
expectation: ->(noteable, can_use_quick_action) {
expect(noteable.work_in_progress?).not_to eq(can_use_quick_action)
diff --git a/spec/services/packages/maven/metadata/sync_service_spec.rb b/spec/services/packages/maven/metadata/sync_service_spec.rb
index a736ed281f0..9a704d749b3 100644
--- a/spec/services/packages/maven/metadata/sync_service_spec.rb
+++ b/spec/services/packages/maven/metadata/sync_service_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:versionless_package_for_versions) { create(:maven_package, name: 'test', version: nil, project: project) }
let_it_be_with_reload(:metadata_file_for_versions) { create(:package_file, :xml, package: versionless_package_for_versions) }
+ let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: versionless_package_for_versions, file_name: Packages::Maven::Metadata.filename) }
let(:service) { described_class.new(container: project, current_user: user, params: { package_name: versionless_package_for_versions.name }) }
@@ -265,22 +266,4 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
end
end
end
-
- # TODO When cleaning up packages_installable_package_files, consider adding a
- # dummy package file pending for destruction on L10/11 and remove this context
- context 'with package files pending destruction' do
- let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: versionless_package_for_versions, file_name: Packages::Maven::Metadata.filename) }
-
- subject { service.send(:metadata_package_file_for, versionless_package_for_versions) }
-
- it { is_expected.not_to eq(package_file_pending_destruction) }
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it { is_expected.to eq(package_file_pending_destruction) }
- end
- 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 8eddd27f8a2..fc21cfd502e 100644
--- a/spec/services/packages/nuget/metadata_extraction_service_spec.rb
+++ b/spec/services/packages/nuget/metadata_extraction_service_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe Packages::Nuget::MetadataExtractionService do
end
context 'with invalid package file id' do
- let(:package_file) { OpenStruct.new(id: 555) }
+ let(:package_file) { double('file', id: 555) }
it { expect { subject }.to raise_error(::Packages::Nuget::MetadataExtractionService::ExtractionError, 'invalid package file') }
end
@@ -109,7 +109,7 @@ RSpec.describe Packages::Nuget::MetadataExtractionService do
context 'with a too big nuspec file' do
before do
- allow_any_instance_of(Zip::File).to receive(:glob).and_return([OpenStruct.new(size: 6.megabytes)])
+ allow_any_instance_of(Zip::File).to receive(:glob).and_return([double('file', size: 6.megabytes)])
end
it { expect { subject }.to raise_error(::Packages::Nuget::MetadataExtractionService::ExtractionError, 'nuspec file too big') }
diff --git a/spec/services/pages/zip_directory_service_spec.rb b/spec/services/pages/zip_directory_service_spec.rb
index 9cce90c6c0d..00fe75dbbfd 100644
--- a/spec/services/pages/zip_directory_service_spec.rb
+++ b/spec/services/pages/zip_directory_service_spec.rb
@@ -27,6 +27,10 @@ RSpec.describe Pages::ZipDirectoryService do
let(:archive) { result[:archive_path] }
let(:entries_count) { result[:entries_count] }
+ it 'returns true if ZIP64 is enabled' do
+ expect(::Zip.write_zip64_support).to be true
+ end
+
shared_examples 'handles invalid public directory' do
it 'returns success' do
expect(status).to eq(:success)
@@ -35,7 +39,7 @@ RSpec.describe Pages::ZipDirectoryService do
end
end
- context "when work direcotry doesn't exist" do
+ context "when work directory doesn't exist" do
let(:service_directory) { "/tmp/not/existing/dir" }
include_examples 'handles invalid public directory'
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index ef7741c2d0f..ed043bacf31 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -148,6 +148,32 @@ RSpec.describe Projects::AutocompleteService do
end
end
+ describe '#contacts' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:contact_1) { create(:contact, group: group) }
+ let_it_be(:contact_2) { create(:contact, group: group) }
+
+ subject { described_class.new(project, user).contacts.as_json }
+
+ before do
+ stub_feature_flags(customer_relations: true)
+ group.add_developer(user)
+ end
+
+ it 'returns contact data correctly' do
+ expected_contacts = [
+ { 'id' => contact_1.id, 'email' => contact_1.email,
+ 'first_name' => contact_1.first_name, 'last_name' => contact_1.last_name },
+ { 'id' => contact_2.id, 'email' => contact_2.email,
+ 'first_name' => contact_2.first_name, 'last_name' => contact_2.last_name }
+ ]
+
+ expect(subject).to match_array(expected_contacts)
+ end
+ end
+
describe '#labels_as_hash' do
def expect_labels_to_equal(labels, expected_labels)
expect(labels.size).to eq(expected_labels.size)
diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb
index 94037d6de1e..246ca301cfa 100644
--- a/spec/services/projects/container_repository/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
]
end
- RSpec.shared_examples 'logging a success response' do
+ shared_examples 'logging a success response' do
it 'logs an info message' do
expect(service).to receive(:log_info).with(
service_class: 'Projects::ContainerRepository::DeleteTagsService',
@@ -28,7 +28,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}|
+ shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}|
it 'logs an error message' do
log_data = {
service_class: 'Projects::ContainerRepository::DeleteTagsService',
@@ -45,7 +45,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'calling the correct delete tags service' do |expected_service_class|
+ shared_examples 'calling the correct delete tags service' do |expected_service_class|
let(:service_response) { { status: :success, deleted: tags } }
let(:excluded_service_class) { available_service_classes.excluding(expected_service_class).first }
@@ -69,7 +69,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'handling invalid params' do
+ shared_examples 'handling invalid params' do
context 'with invalid params' do
before do
expect(::Projects::ContainerRepository::Gitlab::DeleteTagsService).not_to receive(:new)
@@ -91,7 +91,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'supporting fast delete' do
+ shared_examples 'supporting fast delete' do
context 'when the registry supports fast delete' do
before do
allow(repository.client).to receive(:supports_tag_delete?).and_return(true)
@@ -155,6 +155,14 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
it_behaves_like 'handling invalid params'
end
+
+ context 'when the repository is importing' do
+ before do
+ repository.update_columns(migration_state: 'importing', migration_import_started_at: Time.zone.now)
+ end
+
+ it { is_expected.to include(status: :error, message: 'repository importing') }
+ end
end
context 'without user' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index d5fbf96ce74..10f694827e1 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -7,9 +7,10 @@ RSpec.describe Projects::CreateService, '#execute' do
include GitHelpers
let(:user) { create :user }
+ let(:project_name) { 'GitLab' }
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: user.namespace.id
}
end
@@ -144,6 +145,12 @@ RSpec.describe Projects::CreateService, '#execute' do
subject { create_project(user, opts) }
end
+
+ it 'logs creation' do
+ expect(Gitlab::AppLogger).to receive(:info).with(/#{user.name} created a new project/)
+
+ create_project(user, opts)
+ end
end
context "admin creates project with other user's namespace_id" do
@@ -183,9 +190,13 @@ RSpec.describe Projects::CreateService, '#execute' do
user.refresh_authorized_projects # Ensure cache is warm
end
- it do
- project = create_project(user, opts.merge!(namespace_id: group.id))
+ subject(:project) { create_project(user, opts.merge!(namespace_id: group.id)) }
+ shared_examples 'has sync-ed traversal_ids' do
+ specify { expect(project.reload.project_namespace.traversal_ids).to eq([project.namespace.traversal_ids, project.project_namespace.id].flatten.compact) }
+ end
+
+ it 'creates the project' do
expect(project).to be_valid
expect(project.owner).to eq(group)
expect(project.namespace).to eq(group)
@@ -193,6 +204,18 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(user.authorized_projects).to include(project)
expect(project.project_namespace).to be_in_sync_with_project(project)
end
+
+ context 'with before_commit callback' do
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
+
+ context 'with after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
+ end
+
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
end
context 'group sharing', :sidekiq_inline do
@@ -202,7 +225,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: shared_group.id
}
end
@@ -237,7 +260,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:share_max_access_level) { Gitlab::Access::MAINTAINER }
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: subgroup_for_projects.id
}
end
@@ -583,58 +606,55 @@ RSpec.describe Projects::CreateService, '#execute' do
opts[:initialize_with_readme] = '1'
end
- shared_examples 'creates README.md' do
+ shared_examples 'a repo with a README.md' do
it { expect(project.repository.commit_count).to be(1) }
it { expect(project.repository.readme.name).to eql('README.md') }
- it { expect(project.repository.readme.data).to include('# GitLab') }
+ it { expect(project.repository.readme.data).to include(expected_content) }
end
- it_behaves_like 'creates README.md'
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) do
+ <<~MARKDOWN
+ cd existing_repo
+ git remote add origin #{project.http_url_to_repo}
+ git branch -M master
+ git push -uf origin master
+ MARKDOWN
+ end
+ end
- context 'and a default_branch_name is specified' do
+ context 'and a readme_template is specified' do
before do
- allow(Gitlab::CurrentSettings)
- .to receive(:default_branch_name)
- .and_return('example_branch')
+ opts[:readme_template] = "# GitLab\nThis is customized readme."
end
- it_behaves_like 'creates README.md'
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) { "# GitLab\nThis is customized readme." }
+ end
+ end
+
+ context 'and a default_branch_name is specified' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('example_branch')
+ end
- it 'creates README.md within the specified branch rather than master' do
+ it 'creates the correct branch' do
branches = project.repository.branches
expect(branches.size).to eq(1)
expect(branches.collect(&:name)).to contain_exactly('example_branch')
end
- describe 'advanced readme content', experiment: :new_project_readme_content do
- before do
- stub_experiments(new_project_readme_content: :advanced)
- end
-
- it_behaves_like 'creates README.md'
-
- it 'includes advanced content in the README.md' do
- content = project.repository.readme.data
- expect(content).to include <<~MARKDOWN
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) do
+ <<~MARKDOWN
+ cd existing_repo
git remote add origin #{project.http_url_to_repo}
git branch -M example_branch
git push -uf origin example_branch
MARKDOWN
end
end
-
- context 'and readme_template is specified' do
- before do
- opts[:readme_template] = "# GitLab\nThis is customized template."
- end
-
- it_behaves_like 'creates README.md'
-
- it 'creates README.md with specified template' do
- expect(project.repository.readme.data).to include('This is customized template.')
- end
- end
end
end
@@ -676,7 +696,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: group.id
}
end
@@ -697,7 +717,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: subgroup.id
}
end
@@ -808,7 +828,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: group.id
}
end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 9475f562d71..d60ec8c2958 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -15,20 +15,39 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
before do
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: :any, tags: [])
+ allow(Gitlab::EventStore).to receive(:publish)
end
shared_examples 'deleting the project' do
- before do
- # Run sidekiq immediately to check that renamed repository will be removed
+ it 'deletes the project', :sidekiq_inline do
destroy_project(project, user, {})
- end
- it 'deletes the project', :sidekiq_inline do
expect(Project.unscoped.all).not_to include(project)
expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_falsey
expect(project.gitlab_shell.repository_exists?(project.repository_storage, remove_path + '.git')).to be_falsey
end
+
+ it 'publishes a ProjectDeleted event with project id and namespace id' do
+ expected_data = { project_id: project.id, namespace_id: project.namespace_id }
+ expect(Gitlab::EventStore)
+ .to receive(:publish)
+ .with(event_type(Projects::ProjectDeletedEvent).containing(expected_data))
+
+ destroy_project(project, user, {})
+ end
+
+ context 'when feature flag publish_project_deleted_event is disabled' do
+ before do
+ stub_feature_flags(publish_project_deleted_event: false)
+ end
+
+ it 'does not publish an event' do
+ expect(Gitlab::EventStore).not_to receive(:publish).with(event_type(Projects::ProjectDeletedEvent))
+
+ destroy_project(project, user, {})
+ end
+ end
end
shared_examples 'deleting the project with pipeline and build' do
@@ -97,6 +116,24 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end
end
+ context "deleting a project with merge requests" do
+ let!(:merge_request) { create(:merge_request, source_project: project) }
+
+ before do
+ allow(project).to receive(:destroy!).and_return(true)
+ end
+
+ it "deletes merge request and related records" do
+ merge_request_diffs = merge_request.merge_request_diffs
+ expect(merge_request_diffs.size).to eq(1)
+
+ mrdc_count = MergeRequestDiffCommit.where(merge_request_diff_id: merge_request_diffs.first.id).count
+
+ expect { destroy_project(project, user, {}) }
+ .to change { MergeRequestDiffCommit.count }.by(-mrdc_count)
+ end
+ end
+
it_behaves_like 'deleting the project'
it 'invalidates personal_project_count cache' do
diff --git a/spec/services/projects/import_export/export_service_spec.rb b/spec/services/projects/import_export/export_service_spec.rb
index 6002aaf427a..54abbc04084 100644
--- a/spec/services/projects/import_export/export_service_spec.rb
+++ b/spec/services/projects/import_export/export_service_spec.rb
@@ -93,11 +93,23 @@ RSpec.describe Projects::ImportExport::ExportService do
end
it 'saves the project in the file system' do
- expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared)
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
service.execute
end
+ context 'when the upload fails' do
+ before do
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(false)
+ end
+
+ it 'notifies the user of an error' do
+ expect(service).to receive(:notify_error).and_call_original
+
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
+ end
+ end
+
it 'calls the after export strategy' do
expect(after_export_strategy).to receive(:execute)
@@ -107,6 +119,7 @@ RSpec.describe Projects::ImportExport::ExportService do
context 'when after export strategy fails' do
before do
allow(after_export_strategy).to receive(:execute).and_return(false)
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
end
after do
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index 1d63f72ec38..ccfd119b55b 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -298,7 +298,7 @@ RSpec.describe Projects::ImportService do
end
def stub_github_omniauth_provider
- provider = OpenStruct.new(
+ provider = ActiveSupport::InheritableOptions.new(
'name' => 'github',
'app_id' => 'asd123',
'app_secret' => 'asd123',
diff --git a/spec/services/projects/overwrite_project_service_spec.rb b/spec/services/projects/overwrite_project_service_spec.rb
index cc6a863a11d..7038910508f 100644
--- a/spec/services/projects/overwrite_project_service_spec.rb
+++ b/spec/services/projects/overwrite_project_service_spec.rb
@@ -81,16 +81,58 @@ RSpec.describe Projects::OverwriteProjectService do
end
end
- it 'removes the original project' do
- subject.execute(project_from)
+ it 'schedules original project for deletion' do
+ expect_next_instance_of(Projects::DestroyService) do |service|
+ expect(service).to receive(:async_execute)
+ end
- expect { Project.find(project_from.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ subject.execute(project_from)
end
it 'renames the project' do
+ original_path = project_from.full_path
+
subject.execute(project_from)
- expect(project_to.full_path).to eq project_from.full_path
+ expect(project_to.full_path).to eq(original_path)
+ end
+
+ it 'renames source project to temp name' do
+ allow(SecureRandom).to receive(:hex).and_return('test')
+
+ subject.execute(project_from)
+
+ expect(project_from.full_path).to include('-old-test')
+ end
+
+ context 'when project rename fails' do
+ before do
+ expect(subject).to receive(:move_relationships_between).with(project_from, project_to)
+ expect(subject).to receive(:move_relationships_between).with(project_to, project_from)
+ end
+
+ context 'source rename' do
+ it 'moves relations back to source project and raises an exception' do
+ allow(subject).to receive(:rename_project).and_return(status: :error)
+
+ expect { subject.execute(project_from) }.to raise_error(StandardError, 'Source project rename failed during project overwrite')
+ end
+ end
+
+ context 'new project rename' do
+ it 'moves relations back, renames source project back to original name and raises' do
+ name = project_from.name
+ path = project_from.path
+
+ allow(subject).to receive(:rename_project).and_call_original
+ allow(subject).to receive(:rename_project).with(project_to, name, path).and_return(status: :error)
+
+ expect { subject.execute(project_from) }.to raise_error(StandardError, 'New project rename failed during project overwrite')
+
+ expect(project_from.name).to eq(name)
+ expect(project_from.path).to eq(path)
+ end
+ end
end
end
@@ -121,7 +163,7 @@ RSpec.describe Projects::OverwriteProjectService do
end
end
- context 'forks' do
+ context 'forks', :sidekiq_inline do
context 'when moving a root forked project' do
it 'moves the descendant forks' do
expect(project_from.forks.count).to eq 2
@@ -147,6 +189,7 @@ RSpec.describe Projects::OverwriteProjectService do
expect(project_to.fork_network.fork_network_members.map(&:project)).not_to include project_from
end
end
+
context 'when moving a intermediate forked project' do
let(:project_to) { create(:project, namespace: lvl1_forked_project_1.namespace) }
@@ -180,22 +223,26 @@ RSpec.describe Projects::OverwriteProjectService do
end
context 'if an exception is raised' do
+ before do
+ allow(subject).to receive(:rename_project).and_raise(StandardError)
+ end
+
it 'rollbacks changes' do
updated_at = project_from.updated_at
- allow(subject).to receive(:rename_project).and_raise(StandardError)
-
expect { subject.execute(project_from) }.to raise_error(StandardError)
expect(Project.find(project_from.id)).not_to be_nil
expect(project_from.reload.updated_at.change(usec: 0)).to eq updated_at.change(usec: 0)
end
- it 'tries to restore the original project repositories' do
- allow(subject).to receive(:rename_project).and_raise(StandardError)
-
- expect(subject).to receive(:attempt_restore_repositories).with(project_from)
+ it 'removes fork network member' do
+ expect(ForkNetworkMember).to receive(:create!)
+ expect(ForkNetworkMember).to receive(:find_by)
+ expect(subject).to receive(:remove_source_project_from_fork_network).and_call_original
expect { subject.execute(project_from) }.to raise_error(StandardError)
+
+ expect(project_from.fork_network_member).to be_nil
end
end
end
diff --git a/spec/services/projects/readme_renderer_service_spec.rb b/spec/services/projects/readme_renderer_service_spec.rb
new file mode 100644
index 00000000000..14cdcf67640
--- /dev/null
+++ b/spec/services/projects/readme_renderer_service_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ReadmeRendererService, '#execute' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:service) { described_class.new(project, nil, opts) }
+
+ let_it_be(:project) { create(:project, title: 'My Project', description: '_custom_description_') }
+
+ let(:opts) { {} }
+
+ it 'renders the an ERB readme template' do
+ expect(service.execute).to start_with(<<~MARKDOWN)
+ # My Project
+
+ _custom_description_
+
+ ## Getting started
+
+ To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+
+ Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
+
+ ## Add your files
+
+ - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
+ - [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+
+ ```
+ cd existing_repo
+ git remote add origin #{project.http_url_to_repo}
+ git branch -M master
+ git push -uf origin master
+ ```
+ MARKDOWN
+ end
+
+ context 'with a custom template' do
+ before do
+ allow(File).to receive(:read).and_call_original
+ end
+
+ it 'renders that template file' do
+ opts[:template_name] = :custom_readme
+
+ expect(service).to receive(:sanitized_filename).with(:custom_readme).and_return('custom_readme.md.tt')
+ expect(File).to receive(:read).with('custom_readme.md.tt').and_return('_custom_readme_file_content_')
+ expect(service.execute).to eq('_custom_readme_file_content_')
+ end
+
+ context 'with path traversal in mind' do
+ where(:template_name, :exception, :expected_path) do
+ '../path/traversal/bad' | [Gitlab::Utils::PathTraversalAttackError, 'Invalid path'] | nil
+ '/bad/template' | [StandardError, 'path /bad/template.md.tt is not allowed'] | nil
+ 'good/template' | nil | 'good/template.md.tt'
+ end
+
+ with_them do
+ it 'raises the expected exception on bad paths' do
+ opts[:template_name] = template_name
+
+ if exception
+ expect { subject.execute }.to raise_error(*exception)
+ else
+ expect(File).to receive(:read).with(described_class::TEMPLATE_PATH.join(expected_path).to_s).and_return('')
+
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index ddd16100b40..fb94e94fd18 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -5,13 +5,14 @@ require 'spec_helper'
RSpec.describe Projects::TransferService do
include GitHelpers
- let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') }
let(:project) { create(:project, :repository, :legacy_storage, namespace: user.namespace) }
+ let(:target) { group }
- subject(:execute_transfer) { described_class.new(project, user).execute(group).tap { project.reload } }
+ subject(:execute_transfer) { described_class.new(project, user).execute(target).tap { project.reload } }
context 'with npm packages' do
before do
@@ -690,6 +691,32 @@ RSpec.describe Projects::TransferService do
end
end
+ context 'handling issue contacts' do
+ let_it_be(:root_group) { create(:group) }
+
+ let(:project) { create(:project, group: root_group) }
+
+ before do
+ root_group.add_owner(user)
+ target.add_owner(user)
+ create_list(:issue_customer_relations_contact, 2, :for_issue, issue: create(:issue, project: project))
+ end
+
+ context 'with the same root_ancestor' do
+ let(:target) { create(:group, parent: root_group) }
+
+ it 'retains issue contacts' do
+ expect { execute_transfer }.not_to change { CustomerRelations::IssueContact.count }
+ end
+ end
+
+ context 'with a different root_ancestor' do
+ it 'deletes issue contacts' do
+ expect { execute_transfer }.to change { CustomerRelations::IssueContact.count }.by(-2)
+ end
+ end
+ end
+
def rugged_config
rugged_repo(project.repository).config
end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index e56e54db6f4..ca3ae437540 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -11,13 +11,14 @@ RSpec.describe QuickActions::InterpretService do
let_it_be(:developer2) { create(:user) }
let_it_be(:developer3) { create(:user) }
let_it_be_with_reload(:issue) { create(:issue, project: project) }
- let(:milestone) { create(:milestone, project: project, title: '9.10') }
- let(:commit) { create(:commit, project: project) }
let_it_be(:inprogress) { create(:label, project: project, title: 'In Progress') }
let_it_be(:helmchart) { create(:label, project: project, title: 'Helm Chart Registry') }
let_it_be(:bug) { create(:label, project: project, title: 'Bug') }
- let(:service) { described_class.new(project, developer) }
+ let(:milestone) { create(:milestone, project: project, title: '9.10') }
+ let(:commit) { create(:commit, project: project) }
+
+ subject(:service) { described_class.new(project, developer) }
before_all do
public_project.add_developer(developer)
@@ -485,6 +486,8 @@ RSpec.describe QuickActions::InterpretService do
end
shared_examples 'failed command' do |error_msg|
+ let(:match_msg) { error_msg ? eq(error_msg) : be_empty }
+
it 'populates {} if content contains an unsupported command' do
_, updates, _ = service.execute(content, issuable)
@@ -494,11 +497,7 @@ RSpec.describe QuickActions::InterpretService do
it "returns #{error_msg || 'an empty'} message" do
_, _, message = service.execute(content, issuable)
- if error_msg
- expect(message).to eq(error_msg)
- else
- expect(message).to be_empty
- end
+ expect(message).to match_msg
end
end
@@ -703,6 +702,27 @@ RSpec.describe QuickActions::InterpretService do
end
end
+ shared_examples 'attention command' do
+ it 'updates reviewers attention status' do
+ _, _, message = service.execute(content, issuable)
+
+ expect(message).to eq("Requested attention from #{developer.to_reference}.")
+
+ reviewer.reload
+
+ expect(reviewer).to be_attention_requested
+ end
+ end
+
+ shared_examples 'remove attention command' do
+ it 'updates reviewers attention status' do
+ _, _, message = service.execute(content, issuable)
+
+ expect(message).to eq("Removed attention from #{developer.to_reference}.")
+ expect(reviewer).not_to be_attention_requested
+ end
+ end
+
it_behaves_like 'reopen command' do
let(:content) { '/reopen' }
let(:issuable) { issue }
@@ -887,9 +907,10 @@ RSpec.describe QuickActions::InterpretService do
end
end
- it_behaves_like 'failed command', "Failed to assign a user because no user was found." do
+ it_behaves_like 'failed command', 'a parse error' do
let(:content) { '/assign @abcd1234' }
let(:issuable) { issue }
+ let(:match_msg) { eq "Could not apply assign command. Failed to find users for '@abcd1234'." }
end
it_behaves_like 'failed command', "Failed to assign a user because no user was found." do
@@ -950,10 +971,38 @@ RSpec.describe QuickActions::InterpretService do
it_behaves_like 'assign_reviewer command'
end
+ context 'with a private user' do
+ let(:ref) { create(:user, :unconfirmed).to_reference }
+ let(:content) { "/assign_reviewer #{ref}" }
+
+ it_behaves_like 'failed command', 'a parse error' do
+ let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '#{ref}'." }
+ end
+ end
+
+ context 'with a private user, bare username' do
+ let(:ref) { create(:user, :unconfirmed).username }
+ let(:content) { "/assign_reviewer #{ref}" }
+
+ it_behaves_like 'failed command', 'a parse error' do
+ let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '#{ref}'." }
+ end
+ end
+
+ context 'with @all' do
+ let(:content) { "/assign_reviewer @all" }
+
+ it_behaves_like 'failed command', 'a parse error' do
+ let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '@all'." }
+ end
+ end
+
context 'with an incorrect user' do
let(:content) { '/assign_reviewer @abcd1234' }
- it_behaves_like 'failed command', "Failed to assign a reviewer because no user was found."
+ it_behaves_like 'failed command', 'a parse error' do
+ let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '@abcd1234'." }
+ end
end
context 'with the "reviewer" alias' do
@@ -971,13 +1020,15 @@ RSpec.describe QuickActions::InterpretService do
context 'with no user' do
let(:content) { '/assign_reviewer' }
- it_behaves_like 'failed command', "Failed to assign a reviewer because no user was found."
+ it_behaves_like 'failed command', "Failed to assign a reviewer because no user was specified."
end
- context 'includes only the user reference with extra text' do
- let(:content) { "/assign_reviewer @#{developer.username} do it!" }
+ context 'with extra text' do
+ let(:content) { "/assign_reviewer #{developer.to_reference} do it!" }
- it_behaves_like 'assign_reviewer command'
+ it_behaves_like 'failed command', 'a parse error' do
+ let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for 'do' and 'it!'." }
+ end
end
end
@@ -2279,6 +2330,82 @@ RSpec.describe QuickActions::InterpretService do
expect(message).to eq('One or more contacts were successfully removed.')
end
end
+
+ describe 'attention command' do
+ let(:issuable) { create(:merge_request, reviewers: [developer], source_project: project) }
+ let(:reviewer) { issuable.merge_request_reviewers.find_by(user_id: developer.id) }
+ let(:content) { "/attention @#{developer.username}" }
+
+ context 'with one user' do
+ before do
+ reviewer.update!(state: :reviewed)
+ end
+
+ it_behaves_like 'attention command'
+ end
+
+ context 'with no user' do
+ let(:content) { "/attention" }
+
+ it_behaves_like 'failed command', 'Failed to request attention because no user was found.'
+ end
+
+ context 'with incorrect permissions' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it_behaves_like 'failed command', 'Could not apply attention command.'
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(mr_attention_requests: false)
+ end
+
+ it_behaves_like 'failed command', 'Could not apply attention command.'
+ end
+
+ context 'with an issue instead of a merge request' do
+ let(:issuable) { issue }
+
+ it_behaves_like 'failed command', 'Could not apply attention command.'
+ end
+ end
+
+ describe 'remove attention command' do
+ let(:issuable) { create(:merge_request, reviewers: [developer], source_project: project) }
+ let(:reviewer) { issuable.merge_request_reviewers.find_by(user_id: developer.id) }
+ let(:content) { "/remove_attention @#{developer.username}" }
+
+ context 'with one user' do
+ it_behaves_like 'remove attention command'
+ end
+
+ context 'with no user' do
+ let(:content) { "/remove_attention" }
+
+ it_behaves_like 'failed command', 'Failed to remove attention because no user was found.'
+ end
+
+ context 'with incorrect permissions' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it_behaves_like 'failed command', 'Could not apply remove_attention command.'
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(mr_attention_requests: false)
+ end
+
+ it_behaves_like 'failed command', 'Could not apply remove_attention command.'
+ end
+
+ context 'with an issue instead of a merge request' do
+ let(:issuable) { issue }
+
+ it_behaves_like 'failed command', 'Could not apply remove_attention command.'
+ end
+ end
end
describe '#explain' do
@@ -2317,12 +2444,42 @@ RSpec.describe QuickActions::InterpretService do
end
describe 'assign command' do
- let(:content) { "/assign @#{developer.username} do it!" }
+ shared_examples 'assigns developer' do
+ it 'tells us we will assign the developer' do
+ _, explanations = service.explain(content, merge_request)
- it 'includes only the user reference' do
- _, explanations = service.explain(content, merge_request)
+ expect(explanations).to eq(["Assigns @#{developer.username}."])
+ end
+ end
+
+ context 'when using a reference' do
+ let(:content) { "/assign @#{developer.username}" }
- expect(explanations).to eq(["Assigns @#{developer.username}."])
+ include_examples 'assigns developer'
+ end
+
+ context 'when using a bare username' do
+ let(:content) { "/assign #{developer.username}" }
+
+ include_examples 'assigns developer'
+ end
+
+ context 'when using me' do
+ let(:content) { "/assign me" }
+
+ include_examples 'assigns developer'
+ end
+
+ context 'when there are unparseable arguments' do
+ let(:arg) { "#{developer.username} to this issue" }
+ let(:content) { "/assign #{arg}" }
+
+ it 'tells us why we cannot do that' do
+ _, explanations = service.explain(content, merge_request)
+
+ expect(explanations)
+ .to contain_exactly "Problem with assign command: Failed to find users for 'to', 'this', and 'issue'."
+ end
end
end
@@ -2598,6 +2755,45 @@ RSpec.describe QuickActions::InterpretService do
expect(service.commands_executed_count).to eq(3)
end
end
+
+ describe 'crm commands' do
+ let(:add_contacts) { '/add_contacts' }
+ let(:remove_contacts) { '/remove_contacts' }
+
+ before_all do
+ group.add_developer(developer)
+ end
+
+ context 'when group has no contacts' do
+ it '/add_contacts is not available' do
+ _, explanations = service.explain(add_contacts, issue)
+
+ expect(explanations).to be_empty
+ end
+
+ it '/remove_contacts is not available' do
+ _, explanations = service.explain(remove_contacts, issue)
+
+ expect(explanations).to be_empty
+ end
+ end
+
+ context 'when group has contacts' do
+ let!(:contact) { create(:contact, group: group) }
+
+ it '/add_contacts is available' do
+ _, explanations = service.explain(add_contacts, issue)
+
+ expect(explanations).to contain_exactly("Add customer relation contact(s).")
+ end
+
+ it '/remove_contacts is available' do
+ _, explanations = service.explain(remove_contacts, issue)
+
+ expect(explanations).to contain_exactly("Remove customer relation contact(s).")
+ end
+ end
+ end
end
describe '#available_commands' do
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index 7287825a0be..d53fc968e2a 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe Releases::CreateService do
end
end
- context 'when multiple miletone titles are passed in but one of them does not exist' do
+ context 'when multiple milestone titles are passed in but one of them does not exist' do
let(:title) { 'v1.0' }
let(:inexistent_title) { 'v111.0' }
let!(:milestone) { create(:milestone, :active, project: project, title: title) }
diff --git a/spec/services/security/ci_configuration/container_scanning_create_service_spec.rb b/spec/services/security/ci_configuration/container_scanning_create_service_spec.rb
new file mode 100644
index 00000000000..df76750efc8
--- /dev/null
+++ b/spec/services/security/ci_configuration/container_scanning_create_service_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::ContainerScanningCreateService, :snowplow do
+ subject(:result) { described_class.new(project, user).execute }
+
+ let(:branch_name) { 'set-container-scanning-config-1' }
+
+ let(:snowplow_event) do
+ {
+ category: 'Security::CiConfiguration::ContainerScanningCreateService',
+ action: 'create',
+ label: ''
+ }
+ end
+
+ include_examples 'services security ci configuration create service', true
+end
diff --git a/spec/services/service_ping/submit_service_ping_service_spec.rb b/spec/services/service_ping/submit_service_ping_service_spec.rb
index 2971c9a9309..73be8f000a9 100644
--- a/spec/services/service_ping/submit_service_ping_service_spec.rb
+++ b/spec/services/service_ping/submit_service_ping_service_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe ServicePing::SubmitService do
shared_examples 'does not run' do
it do
expect(Gitlab::HTTP).not_to receive(:post)
- expect(Gitlab::UsageData).not_to receive(:data)
+ expect(Gitlab::Usage::ServicePingReport).not_to receive(:for)
subject.execute
end
@@ -63,7 +63,7 @@ RSpec.describe ServicePing::SubmitService do
shared_examples 'does not send a blank usage ping payload' do
it do
- expect(Gitlab::HTTP).not_to receive(:post)
+ expect(Gitlab::HTTP).not_to receive(:post).with(subject.url, any_args)
expect { subject.execute }.to raise_error(described_class::SubmissionError) do |error|
expect(error.message).to include('Usage data is blank')
@@ -118,7 +118,7 @@ RSpec.describe ServicePing::SubmitService do
it 'generates service ping' do
stub_response(body: with_dev_ops_score_params)
- expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_call_original
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_call_original
subject.execute
end
@@ -129,6 +129,7 @@ RSpec.describe ServicePing::SubmitService do
stub_usage_data_connections
stub_database_flavor_check
stub_application_setting(usage_ping_enabled: true)
+ stub_response(body: nil, url: subject.error_url, status: 201)
end
context 'and user requires usage stats consent' do
@@ -150,7 +151,7 @@ RSpec.describe ServicePing::SubmitService do
it 'forces a refresh of usage data statistics before submitting' do
stub_response(body: with_dev_ops_score_params)
- expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_call_original
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_call_original
subject.execute
end
@@ -166,7 +167,7 @@ RSpec.describe ServicePing::SubmitService do
recorded_at = Time.current
usage_data = { uuid: 'uuid', recorded_at: recorded_at }
- expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_return(usage_data)
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(usage_data)
subject.execute
@@ -189,7 +190,7 @@ RSpec.describe ServicePing::SubmitService do
recorded_at = Time.current
usage_data = { uuid: 'uuid', recorded_at: recorded_at }
- expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_return(usage_data)
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(usage_data)
subject.execute
@@ -234,7 +235,7 @@ RSpec.describe ServicePing::SubmitService do
recorded_at = Time.current
usage_data = { uuid: 'uuid', recorded_at: recorded_at }
- expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_return(usage_data)
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(usage_data)
subject.execute
@@ -259,7 +260,7 @@ RSpec.describe ServicePing::SubmitService do
context 'and usage data is empty string' do
before do
- allow(Gitlab::UsageData).to receive(:data).and_return({})
+ allow(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return({})
end
it_behaves_like 'does not send a blank usage ping payload'
@@ -268,7 +269,7 @@ RSpec.describe ServicePing::SubmitService do
context 'and usage data is nil' do
before do
allow(ServicePing::BuildPayloadService).to receive(:execute).and_return(nil)
- allow(Gitlab::UsageData).to receive(:data).and_return(nil)
+ allow(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(nil)
end
it_behaves_like 'does not send a blank usage ping payload'
@@ -277,13 +278,23 @@ RSpec.describe ServicePing::SubmitService do
context 'if payload service fails' do
before do
stub_response(body: with_dev_ops_score_params)
- allow(ServicePing::BuildPayloadService).to receive(:execute).and_raise(described_class::SubmissionError, 'SubmissionError')
+ allow(ServicePing::BuildPayloadService).to receive_message_chain(:new, :execute)
+ .and_raise(described_class::SubmissionError, 'SubmissionError')
end
- it 'calls UsageData .data method' do
+ it 'calls Gitlab::Usage::ServicePingReport .for method' do
usage_data = build_usage_data
- expect(Gitlab::UsageData).to receive(:data).and_return(usage_data)
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(usage_data)
+
+ subject.execute
+ end
+
+ it 'submits error' do
+ expect(Gitlab::HTTP).to receive(:post).with(subject.url, any_args)
+ .and_call_original
+ expect(Gitlab::HTTP).to receive(:post).with(subject.error_url, any_args)
+ .and_call_original
subject.execute
end
@@ -315,10 +326,10 @@ RSpec.describe ServicePing::SubmitService do
end
end
- it 'calls UsageData .data method' do
+ it 'calls Gitlab::Usage::ServicePingReport .for method' do
usage_data = build_usage_data
- expect(Gitlab::UsageData).to receive(:data).and_return(usage_data)
+ expect(Gitlab::Usage::ServicePingReport).to receive(:for).with(output: :all_metrics_values).and_return(usage_data)
# SubmissionError is raised as a result of 404 in response from HTTP Request
expect { subject.execute }.to raise_error(described_class::SubmissionError)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 3ec2c71b20c..a719487a219 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -77,6 +77,19 @@ RSpec.describe SystemNoteService do
end
end
+ describe '.change_issuable_contacts' do
+ let(:added_count) { 5 }
+ let(:removed_count) { 3 }
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:change_issuable_contacts).with(added_count, removed_count)
+ end
+
+ described_class.change_issuable_contacts(noteable, project, author, added_count, removed_count)
+ end
+ end
+
describe '.close_after_error_tracking_resolve' do
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
@@ -572,12 +585,26 @@ RSpec.describe SystemNoteService do
describe '.change_alert_status' do
let(:alert) { build(:alert_management_alert) }
- it 'calls AlertManagementService' do
- expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
- expect(service).to receive(:change_alert_status).with(alert)
+ context 'with status change reason' do
+ let(:reason) { 'reason for status change' }
+
+ it 'calls AlertManagementService' do
+ expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
+ expect(service).to receive(:change_alert_status).with(reason)
+ end
+
+ described_class.change_alert_status(alert, author, reason)
end
+ end
+
+ context 'without status change reason' do
+ it 'calls AlertManagementService' do
+ expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
+ expect(service).to receive(:change_alert_status).with(nil)
+ end
- described_class.change_alert_status(alert, author)
+ described_class.change_alert_status(alert, author)
+ end
end
end
@@ -618,15 +645,29 @@ RSpec.describe SystemNoteService do
end
end
- describe '.resolve_incident_status' do
- let(:incident) { build(:incident, :closed) }
+ describe '.change_incident_status' do
+ let(:incident) { instance_double('Issue', project: project) }
- it 'calls IncidentService' do
- expect_next_instance_of(SystemNotes::IncidentService) do |service|
- expect(service).to receive(:resolve_incident_status)
+ context 'with status change reason' do
+ let(:reason) { 'reason for status change' }
+
+ it 'calls IncidentService' do
+ expect_next_instance_of(SystemNotes::IncidentService) do |service|
+ expect(service).to receive(:change_incident_status).with(reason)
+ end
+
+ described_class.change_incident_status(incident, author, reason)
end
+ end
- described_class.resolve_incident_status(incident, author)
+ context 'without status change reason' do
+ it 'calls IncidentService' do
+ expect_next_instance_of(SystemNotes::IncidentService) do |service|
+ expect(service).to receive(:change_incident_status).with(nil)
+ end
+
+ described_class.change_incident_status(incident, author)
+ end
end
end
diff --git a/spec/services/system_notes/alert_management_service_spec.rb b/spec/services/system_notes/alert_management_service_spec.rb
index 6e6bfeaa205..039975c1bf6 100644
--- a/spec/services/system_notes/alert_management_service_spec.rb
+++ b/spec/services/system_notes/alert_management_service_spec.rb
@@ -21,14 +21,26 @@ RSpec.describe ::SystemNotes::AlertManagementService do
end
describe '#change_alert_status' do
- subject { described_class.new(noteable: noteable, project: project, author: author).change_alert_status(noteable) }
+ subject { described_class.new(noteable: noteable, project: project, author: author).change_alert_status(reason) }
- it_behaves_like 'a system note' do
- let(:action) { 'status' }
+ context 'with no specified reason' do
+ let(:reason) { nil }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'status' }
+ end
+
+ it 'has the appropriate message' do
+ expect(subject.note).to eq("changed the status to **Acknowledged**")
+ end
end
- it 'has the appropriate message' do
- expect(subject.note).to eq("changed the status to **Acknowledged**")
+ context 'with reason provided' do
+ let(:reason) { ' by changing incident status' }
+
+ it 'has the appropriate message' do
+ expect(subject.note).to eq("changed the status to **Acknowledged** by changing incident status")
+ end
end
end
@@ -42,21 +54,7 @@ RSpec.describe ::SystemNotes::AlertManagementService do
end
it 'has the appropriate message' do
- expect(subject.note).to eq("created issue #{issue.to_reference(project)} for this alert")
- end
- end
-
- describe '#closed_alert_issue' do
- let_it_be(:issue) { noteable.issue }
-
- subject { described_class.new(noteable: noteable, project: project, author: author).closed_alert_issue(issue) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'status' }
- end
-
- it 'has the appropriate message' do
- expect(subject.note).to eq("changed the status to **Resolved** by closing issue #{issue.to_reference(project)}")
+ expect(subject.note).to eq("created incident #{issue.to_reference(project)} for this alert")
end
end
diff --git a/spec/services/system_notes/incident_service_spec.rb b/spec/services/system_notes/incident_service_spec.rb
index 669e357b7a4..5de352ad8fa 100644
--- a/spec/services/system_notes/incident_service_spec.rb
+++ b/spec/services/system_notes/incident_service_spec.rb
@@ -57,13 +57,27 @@ RSpec.describe ::SystemNotes::IncidentService do
end
end
- describe '#resolve_incident_status' do
- subject(:resolve_incident_status) { described_class.new(noteable: noteable, project: project, author: author).resolve_incident_status }
+ describe '#change_incident_status' do
+ let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: noteable) }
- it 'creates a new note about resolved incident', :aggregate_failures do
- expect { resolve_incident_status }.to change { noteable.notes.count }.by(1)
+ let(:service) { described_class.new(noteable: noteable, project: project, author: author) }
- expect(noteable.notes.last.note).to eq('changed the status to **Resolved** by closing the incident')
+ context 'with a provided reason' do
+ subject(:change_incident_status) { service.change_incident_status(' by changing the alert status') }
+
+ it 'creates a new note for an incident status change', :aggregate_failures do
+ expect { change_incident_status }.to change { noteable.notes.count }.by(1)
+ expect(noteable.notes.last.note).to eq("changed the incident status to **Triggered** by changing the alert status")
+ end
+ end
+
+ context 'without provided reason' do
+ subject(:change_incident_status) { service.change_incident_status(nil) }
+
+ it 'creates a new note for an incident status change', :aggregate_failures do
+ expect { change_incident_status }.to change { noteable.notes.count }.by(1)
+ expect(noteable.notes.last.note).to eq("changed the incident status to **Triggered**")
+ end
end
end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index 7e53e66303b..e1c97026418 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -188,6 +188,54 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
+ describe '#change_issuable_contacts' do
+ subject { service.change_issuable_contacts(1, 1) }
+
+ let_it_be(:noteable) { create(:issue, project: project) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'contact' }
+ end
+
+ def build_note(added_count, removed_count)
+ service.change_issuable_contacts(added_count, removed_count).note
+ end
+
+ it 'builds a correct phrase when one contact is added' do
+ expect(build_note(1, 0)).to eq "added 1 contact"
+ end
+
+ it 'builds a correct phrase when one contact is removed' do
+ expect(build_note(0, 1)).to eq "removed 1 contact"
+ end
+
+ it 'builds a correct phrase when one contact is added and one contact is removed' do
+ expect(build_note(1, 1)).to(
+ eq("added 1 contact and removed 1 contact")
+ )
+ end
+
+ it 'builds a correct phrase when three contacts are added and one removed' do
+ expect(build_note(3, 1)).to(
+ eq("added 3 contacts and removed 1 contact")
+ )
+ end
+
+ it 'builds a correct phrase when three contacts are removed and one added' do
+ expect(build_note(1, 3)).to(
+ eq("added 1 contact and removed 3 contacts")
+ )
+ end
+
+ it 'builds a correct phrase when the locale is different' do
+ Gitlab::I18n.with_locale('pt-BR') do
+ expect(build_note(1, 3)).to(
+ eq("added 1 contact and removed 3 contacts")
+ )
+ end
+ end
+ end
+
describe '#change_status' do
subject { service.change_status(status, source) }
diff --git a/spec/services/test_hooks/project_service_spec.rb b/spec/services/test_hooks/project_service_spec.rb
index cd6284b4a87..d97a6f15270 100644
--- a/spec/services/test_hooks/project_service_spec.rb
+++ b/spec/services/test_hooks/project_service_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe TestHooks::ProjectService do
it 'executes hook' do
allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -49,7 +49,7 @@ RSpec.describe TestHooks::ProjectService do
it 'executes hook' do
allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -69,7 +69,7 @@ RSpec.describe TestHooks::ProjectService do
allow(Gitlab::DataBuilder::Note).to receive(:build).and_return(sample_data)
allow_next(NotesFinder).to receive(:execute).and_return(Note.all)
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -86,7 +86,7 @@ RSpec.describe TestHooks::ProjectService do
allow(issue).to receive(:to_hook_data).and_return(sample_data)
allow_next(IssuesFinder).to receive(:execute).and_return([issue])
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -119,7 +119,7 @@ RSpec.describe TestHooks::ProjectService do
allow(merge_request).to receive(:to_hook_data).and_return(sample_data)
allow_next(MergeRequestsFinder).to receive(:execute).and_return([merge_request])
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -138,7 +138,7 @@ RSpec.describe TestHooks::ProjectService do
allow(Gitlab::DataBuilder::Build).to receive(:build).and_return(sample_data)
allow_next(Ci::JobsFinder).to receive(:execute).and_return([ci_job])
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -157,7 +157,7 @@ RSpec.describe TestHooks::ProjectService do
allow(Gitlab::DataBuilder::Pipeline).to receive(:build).and_return(sample_data)
allow_next(Ci::PipelinesFinder).to receive(:execute).and_return([pipeline])
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -184,7 +184,7 @@ RSpec.describe TestHooks::ProjectService do
create(:wiki_page, wiki: project.wiki)
allow(Gitlab::DataBuilder::WikiPage).to receive(:build).and_return(sample_data)
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -203,7 +203,7 @@ RSpec.describe TestHooks::ProjectService do
allow(release).to receive(:to_hook_data).and_return(sample_data)
allow_next(ReleasesFinder).to receive(:execute).and_return([release])
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
diff --git a/spec/services/test_hooks/system_service_spec.rb b/spec/services/test_hooks/system_service_spec.rb
index 48c8c24212a..66a1218d123 100644
--- a/spec/services/test_hooks/system_service_spec.rb
+++ b/spec/services/test_hooks/system_service_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe TestHooks::SystemService do
it 'executes hook' do
expect(Gitlab::DataBuilder::Push).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -45,7 +45,7 @@ RSpec.describe TestHooks::SystemService do
allow(project.repository).to receive(:tags).and_return(['tag'])
expect(Gitlab::DataBuilder::Push).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -57,7 +57,7 @@ RSpec.describe TestHooks::SystemService do
it 'executes hook' do
expect(Gitlab::DataBuilder::Repository).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Repository::SAMPLE_DATA, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Repository::SAMPLE_DATA, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -76,7 +76,7 @@ RSpec.describe TestHooks::SystemService do
it 'executes hook' do
expect(MergeRequest).to receive(:of_projects).and_return([merge_request])
expect(merge_request).to receive(:to_hook_data).and_return(sample_data)
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
+ expect(hook).to receive(:execute).with(sample_data, trigger_key, force: true).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
diff --git a/spec/services/update_container_registry_info_service_spec.rb b/spec/services/update_container_registry_info_service_spec.rb
index 740e53b0472..64071e79508 100644
--- a/spec/services/update_container_registry_info_service_spec.rb
+++ b/spec/services/update_container_registry_info_service_spec.rb
@@ -48,6 +48,7 @@ RSpec.describe UpdateContainerRegistryInfoService do
before do
stub_registry_info({})
+ stub_supports_gitlab_api(false)
end
it 'uses a token with no access permissions' do
@@ -63,6 +64,7 @@ RSpec.describe UpdateContainerRegistryInfoService do
context 'when unabled to detect the container registry type' do
it 'sets the application settings to their defaults' do
stub_registry_info({})
+ stub_supports_gitlab_api(false)
subject
@@ -76,20 +78,23 @@ RSpec.describe UpdateContainerRegistryInfoService do
context 'when able to detect the container registry type' do
context 'when using the GitLab container registry' do
it 'updates application settings accordingly' do
- stub_registry_info(vendor: 'gitlab', version: '2.9.1-gitlab', features: %w[a,b,c])
+ stub_registry_info(vendor: 'gitlab', version: '2.9.1-gitlab', features: %w[a b c])
+ stub_supports_gitlab_api(true)
subject
application_settings.reload
expect(application_settings.container_registry_vendor).to eq('gitlab')
expect(application_settings.container_registry_version).to eq('2.9.1-gitlab')
- expect(application_settings.container_registry_features).to eq(%w[a,b,c])
+ expect(application_settings.container_registry_features)
+ .to match_array(%W[a b c #{ContainerRegistry::GitlabApiClient::REGISTRY_GITLAB_V1_API_FEATURE}])
end
end
context 'when using a third-party container registry' do
it 'updates application settings accordingly' do
stub_registry_info(vendor: 'other', version: nil, features: nil)
+ stub_supports_gitlab_api(false)
subject
@@ -112,4 +117,10 @@ RSpec.describe UpdateContainerRegistryInfoService do
allow(client).to receive(:registry_info).and_return(output)
end
end
+
+ def stub_supports_gitlab_api(output)
+ allow_next_instance_of(ContainerRegistry::GitlabApiClient) do |client|
+ allow(client).to receive(:supports_gitlab_api?).and_return(output)
+ end
+ end
end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 7d933ea9c5c..64371f97908 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -52,6 +52,25 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
end
end
+ describe '#disabled?' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(hook, data, :push_hooks, force: forced) }
+
+ let(:hook) { double(executable?: executable, allow_local_requests?: false) }
+
+ where(:forced, :executable, :disabled) do
+ false | true | false
+ false | false | true
+ true | true | false
+ true | false | false
+ end
+
+ with_them do
+ it { is_expected.to have_attributes(disabled?: disabled) }
+ end
+ end
+
describe '#execute' do
let!(:uuid) { SecureRandom.uuid }
let(:headers) do
@@ -129,7 +148,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
end
it 'does not execute disabled hooks' do
- project_hook.update!(recent_failures: 4)
+ allow(service_instance).to receive(:disabled?).and_return(true)
expect(service_instance.execute).to eq({ status: :error, message: 'Hook disabled' })
end
@@ -149,13 +168,13 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
.once
end
- it 'executes and logs if a recursive web hook is detected', :aggregate_failures do
+ it 'blocks and logs if a recursive web hook is detected', :aggregate_failures do
stub_full_request(project_hook.url, method: :post)
Gitlab::WebHooks::RecursionDetection.register!(project_hook)
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
hook_type: 'ProjectHook',
hook_name: 'push_hooks',
@@ -166,12 +185,10 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
service_instance.execute
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url))
- .with(headers: headers)
- .once
+ expect(WebMock).not_to have_requested(:post, stubbed_hostname(project_hook.url))
end
- it 'executes and logs if the recursion count limit would be exceeded', :aggregate_failures do
+ it 'blocks and logs if the recursion count limit would be exceeded', :aggregate_failures do
stub_full_request(project_hook.url, method: :post)
stub_const("#{Gitlab::WebHooks::RecursionDetection.name}::COUNT_LIMIT", 3)
previous_hooks = create_list(:project_hook, 3)
@@ -179,7 +196,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
hook_type: 'ProjectHook',
hook_name: 'push_hooks',
@@ -190,9 +207,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
service_instance.execute
- expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url))
- .with(headers: headers)
- .once
+ expect(WebMock).not_to have_requested(:post, stubbed_hostname(project_hook.url))
end
it 'handles exceptions' do
@@ -255,6 +270,20 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
stub_full_request(project_hook.url, method: :post).to_return(status: 200, body: 'Success')
end
+ context 'when forced' do
+ let(:service_instance) { described_class.new(project_hook, data, :push_hooks, force: true) }
+
+ it 'logs execution inline' do
+ expect(::WebHooks::LogExecutionWorker).not_to receive(:perform_async)
+ expect(::WebHooks::LogExecutionService)
+ .to receive(:new)
+ .with(hook: project_hook, log_data: Hash, response_category: :ok)
+ .and_return(double(execute: nil))
+
+ run_service
+ end
+ end
+
it 'log successful execution' do
run_service
@@ -408,7 +437,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
describe '#async_execute' do
def expect_to_perform_worker(hook)
- expect(WebHookWorker).to receive(:perform_async).with(hook.id, data, 'push_hooks')
+ expect(WebHookWorker).to receive(:perform_async).with(hook.id, data, 'push_hooks', an_instance_of(Hash))
end
def expect_to_rate_limit(hook, threshold:, throttled: false)
@@ -496,15 +525,15 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
Gitlab::WebHooks::RecursionDetection.set_request_uuid(SecureRandom.uuid)
end
- it 'queues a worker and logs an error if the call chain limit would be exceeded' do
+ it 'does not queue a worker and logs an error if the call chain limit would be exceeded' do
stub_const("#{Gitlab::WebHooks::RecursionDetection.name}::COUNT_LIMIT", 3)
previous_hooks = create_list(:project_hook, 3)
previous_hooks.each { Gitlab::WebHooks::RecursionDetection.register!(_1) }
- expect(WebHookWorker).to receive(:perform_async)
+ expect(WebHookWorker).not_to receive(:perform_async)
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
hook_type: 'ProjectHook',
hook_name: 'push_hooks',
@@ -519,13 +548,13 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
service_instance.async_execute
end
- it 'queues a worker and logs an error if a recursive call chain is detected' do
+ it 'does not queue a worker and logs an error if a recursive call chain is detected' do
Gitlab::WebHooks::RecursionDetection.register!(project_hook)
- expect(WebHookWorker).to receive(:perform_async)
+ expect(WebHookWorker).not_to receive(:perform_async)
expect(Gitlab::AuthLogger).to receive(:error).with(
include(
- message: 'Webhook recursion detected and will be blocked in future',
+ message: 'Recursive webhook blocked from executing',
hook_id: project_hook.id,
hook_type: 'ProjectHook',
hook_name: 'push_hooks',
diff --git a/spec/services/work_items/create_service_spec.rb b/spec/services/work_items/create_service_spec.rb
index 2c054ae59a0..f495e967b26 100644
--- a/spec/services/work_items/create_service_spec.rb
+++ b/spec/services/work_items/create_service_spec.rb
@@ -5,34 +5,46 @@ require 'spec_helper'
RSpec.describe WorkItems::CreateService do
include AfterNextHelpers
- let_it_be(:group) { create(:group) }
- let_it_be_with_reload(:project) { create(:project, group: group) }
- let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:user_with_no_access) { create(:user) }
let(:spam_params) { double }
+ let(:current_user) { guest }
+ let(:opts) do
+ {
+ title: 'Awesome work_item',
+ description: 'please fix'
+ }
+ end
+
+ before_all do
+ project.add_guest(guest)
+ end
describe '#execute' do
- let(:work_item) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute }
+ subject(:service_result) { described_class.new(project: project, current_user: current_user, params: opts, spam_params: spam_params).execute }
before do
stub_spam_services
end
- context 'when params are valid' do
- before_all do
- project.add_guest(user)
- end
+ context 'when user is not allowed to create a work item in the project' do
+ let(:current_user) { user_with_no_access }
+
+ it { is_expected.to be_error }
- let(:opts) do
- {
- title: 'Awesome work_item',
- description: 'please fix'
- }
+ it 'returns an access error' do
+ expect(service_result.errors).to contain_exactly('Operation not allowed')
end
+ end
+ context 'when params are valid' do
it 'created instance is a WorkItem' do
expect(Issuable::CommonSystemNotesService).to receive_message_chain(:new, :execute)
+ work_item = service_result[:work_item]
+
expect(work_item).to be_persisted
expect(work_item).to be_a(::WorkItem)
expect(work_item.title).to eq('Awesome work_item')
@@ -41,17 +53,17 @@ RSpec.describe WorkItems::CreateService do
end
end
- context 'checking spam' do
- let(:params) do
- {
- title: 'Spam work_item'
- }
- end
+ context 'when params are invalid' do
+ let(:opts) { { title: '' } }
- subject do
- described_class.new(project: project, current_user: user, params: params, spam_params: spam_params)
+ it { is_expected.to be_error }
+
+ it 'returns validation errors' do
+ expect(service_result.errors).to contain_exactly("Title can't be blank")
end
+ end
+ context 'checking spam' do
it 'executes SpamActionService' do
expect_next_instance_of(
Spam::SpamActionService,
@@ -65,7 +77,7 @@ RSpec.describe WorkItems::CreateService do
expect(instance).to receive(:execute)
end
- subject.execute
+ service_result
end
end
end
diff --git a/spec/services/work_items/delete_service_spec.rb b/spec/services/work_items/delete_service_spec.rb
new file mode 100644
index 00000000000..6cca5018852
--- /dev/null
+++ b/spec/services/work_items/delete_service_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::DeleteService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:work_item, refind: true) { create(:work_item, project: project, author: guest) }
+
+ let(:user) { guest }
+
+ before_all do
+ project.add_guest(guest)
+ # note necessary to test note removal as part of work item deletion
+ create(:note, project: project, noteable: work_item)
+ end
+
+ describe '#execute' do
+ subject(:result) { described_class.new(project: project, current_user: user).execute(work_item) }
+
+ context 'when user can delete the work item' do
+ it { is_expected.to be_success }
+
+ # currently we don't expect destroy to fail. Mocking here for coverage and keeping
+ # the service's return type consistent
+ context 'when there are errors preventing to delete the work item' do
+ before do
+ allow(work_item).to receive(:destroy).and_return(false)
+ work_item.errors.add(:title)
+ end
+
+ it { is_expected.to be_error }
+
+ it 'returns error messages' do
+ expect(result.errors).to contain_exactly('Title is invalid')
+ end
+ end
+ end
+
+ context 'when user cannot delete the work item' do
+ let(:user) { create(:user) }
+
+ it { is_expected.to be_error }
+
+ it 'returns error messages' do
+ expect(result.errors).to contain_exactly('User not authorized to delete work item')
+ end
+ end
+ end
+end
diff --git a/spec/services/work_items/update_service_spec.rb b/spec/services/work_items/update_service_spec.rb
new file mode 100644
index 00000000000..f71f1060e40
--- /dev/null
+++ b/spec/services/work_items/update_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::UpdateService do
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:project) { create(:project).tap { |proj| proj.add_developer(developer) } }
+ let_it_be_with_reload(:work_item) { create(:work_item, project: project, assignees: [developer]) }
+
+ let(:spam_params) { double }
+ let(:opts) { {} }
+ let(:current_user) { developer }
+
+ describe '#execute' do
+ subject(:update_work_item) { described_class.new(project: project, current_user: current_user, params: opts, spam_params: spam_params).execute(work_item) }
+
+ before do
+ stub_spam_services
+ end
+
+ context 'when title is changed' do
+ let(:opts) { { title: 'changed' } }
+
+ it 'triggers issuable_title_updated graphql subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_title_updated).with(work_item).and_call_original
+
+ update_work_item
+ end
+ end
+
+ context 'when title is not changed' do
+ let(:opts) { { description: 'changed' } }
+
+ it 'does not trigger issuable_title_updated graphql subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_title_updated)
+
+ update_work_item
+ end
+ end
+
+ context 'when updating state_event' do
+ context 'when state_event is close' do
+ let(:opts) { { state_event: 'close' } }
+
+ it 'closes the work item' do
+ expect do
+ update_work_item
+ work_item.reload
+ end.to change(work_item, :state).from('opened').to('closed')
+ end
+ end
+
+ context 'when state_event is reopen' do
+ let(:opts) { { state_event: 'reopen' } }
+
+ before do
+ work_item.close!
+ end
+
+ it 'reopens the work item' do
+ expect do
+ update_work_item
+ work_item.reload
+ end.to change(work_item, :state).from('closed').to('opened')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 6d5036365e1..37e9ef1d994 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -112,11 +112,20 @@ RSpec.configure do |config|
# falling back to all tests when there is no `:focus` example.
config.filter_run focus: true
config.run_all_when_everything_filtered = true
+ end
- # Re-run failures locally with `--only-failures`
- config.example_status_persistence_file_path = './spec/examples.txt'
+ # Attempt to troubleshoot https://gitlab.com/gitlab-org/gitlab/-/issues/351531
+ config.after do |example|
+ if example.exception.is_a?(Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification::CrossDatabaseModificationAcrossUnsupportedTablesError)
+ ::CrossDatabaseModification::TransactionStackTrackRecord.log_gitlab_transactions_stack(action: :after_failure, example: example.description)
+ else
+ ::CrossDatabaseModification::TransactionStackTrackRecord.log_gitlab_transactions_stack(action: :after_example, example: example.description)
+ end
end
+ # Re-run failures locally with `--only-failures`
+ config.example_status_persistence_file_path = ENV.fetch('RSPEC_LAST_RUN_RESULTS_FILE', './spec/examples.txt')
+
config.define_derived_metadata(file_path: %r{(ee)?/spec/.+_spec\.rb\z}) do |metadata|
location = metadata[:location]
@@ -184,7 +193,6 @@ RSpec.configure do |config|
config.include RedisHelpers
config.include Rails.application.routes.url_helpers, type: :routing
config.include PolicyHelpers, type: :policy
- config.include MemoryUsageHelper
config.include ExpectRequestWithStatus, type: :request
config.include IdempotentWorkerHelper, type: :worker
config.include RailsHelpers
@@ -208,7 +216,9 @@ RSpec.configure do |config|
config.exceptions_to_hard_fail = [DeprecationToolkitEnv::DeprecationBehaviors::SelectiveRaise::RaiseDisallowedDeprecation]
end
- if ENV['FLAKY_RSPEC_GENERATE_REPORT']
+ require_relative '../tooling/rspec_flaky/config'
+
+ if RspecFlaky::Config.generate_report?
require_relative '../tooling/rspec_flaky/listener'
config.reporter.register_listener(
@@ -242,10 +252,6 @@ RSpec.configure do |config|
::Ci::ApplicationRecord.set_open_transactions_baseline
end
- config.append_before do
- Thread.current[:current_example_group] = ::RSpec.current_example.metadata[:example_group]
- end
-
config.append_after do
ApplicationRecord.reset_open_transactions_baseline
::Ci::ApplicationRecord.reset_open_transactions_baseline
@@ -288,8 +294,6 @@ RSpec.configure do |config|
# See https://gitlab.com/gitlab-org/gitlab/-/issues/33867
stub_feature_flags(file_identifier_hash: false)
- stub_feature_flags(diffs_virtual_scrolling: false)
-
# The following `vue_issues_list` stub can be removed
# once the Vue issues page has feature parity with the current Haml page
stub_feature_flags(vue_issues_list: false)
@@ -462,14 +466,6 @@ RSpec.configure do |config|
$stdout = STDOUT
end
- config.around(:each, stubbing_settings_source: true) do |example|
- original_instance = ::Settings.instance_variable_get(:@instance)
-
- example.run
-
- ::Settings.instance_variable_set(:@instance, original_instance)
- end
-
config.disable_monkey_patching!
end
diff --git a/spec/support/cross_database_modification.rb b/spec/support/cross_database_modification.rb
new file mode 100644
index 00000000000..e0d91001c03
--- /dev/null
+++ b/spec/support/cross_database_modification.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.after do |example|
+ [::ApplicationRecord, ::Ci::ApplicationRecord].each do |base_class|
+ base_class.gitlab_transactions_stack.clear if base_class.respond_to?(:gitlab_transactions_stack)
+ end
+ end
+end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index fb70f82ef87..e3a05f17593 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -73,6 +73,8 @@ module DbCleaner
end
end
+ Gitlab::Database::Partitioning.sync_partitions_ignore_db_error
+
puts "Databases re-creation done in #{Gitlab::Metrics::System.monotonic_time - start}"
end
diff --git a/spec/support/flaky_tests.rb b/spec/support/flaky_tests.rb
index 5ce55c47aab..4df0d23bfc3 100644
--- a/spec/support/flaky_tests.rb
+++ b/spec/support/flaky_tests.rb
@@ -4,14 +4,14 @@ return unless ENV['CI']
return if ENV['SKIP_FLAKY_TESTS_AUTOMATICALLY'] == "false"
return if ENV['CI_MERGE_REQUEST_LABELS'].to_s.include?('pipeline:run-flaky-tests')
+require_relative '../../tooling/rspec_flaky/config'
require_relative '../../tooling/rspec_flaky/report'
RSpec.configure do |config|
$flaky_test_example_ids = begin # rubocop:disable Style/GlobalVars
- raise "$SUITE_FLAKY_RSPEC_REPORT_PATH is empty." if ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'].to_s.empty?
- raise "#{ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']} doesn't exist" unless File.exist?(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'])
+ raise "#{RspecFlaky::Config.suite_flaky_examples_report_path} doesn't exist" unless File.exist?(RspecFlaky::Config.suite_flaky_examples_report_path)
- RspecFlaky::Report.load(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']).map { |_, flaky_test_data| flaky_test_data.to_h[:example_id] }
+ RspecFlaky::Report.load(RspecFlaky::Config.suite_flaky_examples_report_path).map { |_, flaky_test_data| flaky_test_data.to_h[:example_id] }
rescue => e # rubocop:disable Style/RescueStandardError
puts e
[]
@@ -29,8 +29,9 @@ RSpec.configure do |config|
end
config.after(:suite) do
- next unless ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH']
+ next unless RspecFlaky::Config.skipped_flaky_tests_report_path
+ next if $skipped_flaky_tests_report.empty? # rubocop:disable Style/GlobalVars
- File.write(ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH'], "#{$skipped_flaky_tests_report.join("\n")}\n") # rubocop:disable Style/GlobalVars
+ File.write(RspecFlaky::Config.skipped_flaky_tests_report_path, "#{ENV['CI_JOB_URL']}\n#{$skipped_flaky_tests_report.join("\n")}\n\n") # rubocop:disable Style/GlobalVars
end
end
diff --git a/spec/support/gitlab_experiment.rb b/spec/support/gitlab_experiment.rb
index 3d099dc689c..823aab0436e 100644
--- a/spec/support/gitlab_experiment.rb
+++ b/spec/support/gitlab_experiment.rb
@@ -10,6 +10,16 @@ RSpec.configure do |config|
# Disable all caching for experiments in tests.
config.before do
allow(Gitlab::Experiment::Configuration).to receive(:cache).and_return(nil)
+
+ # Disable all deprecation warnings in the test environment, which can be
+ # resolved one by one and tracked in:
+ #
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/350944
+ allow(Gitlab::Experiment::Configuration).to receive(:deprecator).and_wrap_original do |method, version|
+ method.call(version).tap do |deprecator|
+ deprecator.silenced = true
+ end
+ end
end
config.before(:each, :experiment) do
diff --git a/spec/support/graphql/arguments.rb b/spec/support/graphql/arguments.rb
index d8c334c2ca4..20e940030f8 100644
--- a/spec/support/graphql/arguments.rb
+++ b/spec/support/graphql/arguments.rb
@@ -41,6 +41,7 @@ module Graphql
when Hash then "{#{new(value)}}"
when Integer, Float, Symbol then value.to_s
when String then "\"#{value.gsub(/"/, '\\"')}\""
+ when Time, Date then "\"#{value.iso8601}\""
when nil then 'null'
when true then 'true'
when false then 'false'
diff --git a/spec/support/helpers/fake_blob_helpers.rb b/spec/support/helpers/fake_blob_helpers.rb
index 6c8866deac4..47fb9a345a3 100644
--- a/spec/support/helpers/fake_blob_helpers.rb
+++ b/spec/support/helpers/fake_blob_helpers.rb
@@ -4,13 +4,14 @@ module FakeBlobHelpers
class FakeBlob
include BlobLike
- attr_reader :path, :size, :data, :lfs_oid, :lfs_size
+ attr_reader :path, :size, :data, :lfs_oid, :lfs_size, :mode
- def initialize(path: 'file.txt', size: 1.kilobyte, data: 'foo', binary: false, lfs: nil)
+ def initialize(path: 'file.txt', size: 1.kilobyte, data: 'foo', binary: false, lfs: nil, mode: nil)
@path = path
@size = size
@data = data
@binary = binary
+ @mode = mode
@lfs_pointer = lfs.present?
if @lfs_pointer
diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb
index 11040562b49..2a4f78ca57f 100644
--- a/spec/support/helpers/features/invite_members_modal_helper.rb
+++ b/spec/support/helpers/features/invite_members_modal_helper.rb
@@ -8,7 +8,7 @@ module Spec
def invite_member(name, role: 'Guest', expires_at: nil)
click_on 'Invite members'
- page.within '[data-testid="invite-members-modal"]' do
+ page.within '[data-testid="invite-modal"]' do
find('[data-testid="members-token-select-input"]').set(name)
wait_for_requests
diff --git a/spec/support/helpers/features/iteration_helpers.rb b/spec/support/helpers/features/iteration_helpers.rb
new file mode 100644
index 00000000000..8e1d252f55f
--- /dev/null
+++ b/spec/support/helpers/features/iteration_helpers.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module IterationHelpers
+ def iteration_period(iteration)
+ "#{iteration.start_date.to_s(:medium)} - #{iteration.due_date.to_s(:medium)}"
+ end
+end
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 905c439f4d9..a4ee618457d 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -120,7 +120,7 @@ module GitalySetup
end
def build_gitaly
- run_command(%w[make all git], env: env.merge('GIT_VERSION' => nil))
+ run_command(%w[make all WITH_BUNDLED_GIT=YesPlease], env: env.merge('GIT_VERSION' => nil))
end
def start_gitaly(toml = nil)
@@ -327,8 +327,8 @@ module GitalySetup
message += "\nCheck log/gitaly-test.log for errors.\n"
- unless ci?
- message += "\nIf binaries are missing, try running `make -C tmp/tests/gitaly build git.`\n"
+ unless ENV['CI']
+ message += "\nIf binaries are missing, try running `make -C tmp/tests/gitaly all WITH_BUNDLED_GIT=YesPlease`.\n"
message += "\nOtherwise, try running `rm -rf #{tmp_tests_gitaly_dir}`."
end
@@ -336,7 +336,7 @@ module GitalySetup
end
def git_binary
- File.join(tmp_tests_gitaly_dir, "_build", "deps", "git", "install", "bin", "git")
+ File.join(tmp_tests_gitaly_dir, "_build", "bin", "gitaly-git")
end
def gitaly_binary
diff --git a/spec/support/helpers/import_spec_helper.rb b/spec/support/helpers/import_spec_helper.rb
index d8fb2ba08af..26b78acbc44 100644
--- a/spec/support/helpers/import_spec_helper.rb
+++ b/spec/support/helpers/import_spec_helper.rb
@@ -25,7 +25,7 @@ module ImportSpecHelper
end
def stub_omniauth_provider(name)
- provider = OpenStruct.new(
+ provider = ActiveSupport::InheritableOptions.new(
name: name,
app_id: 'asd123',
app_secret: 'asd123'
diff --git a/spec/support/helpers/key_generator_helper.rb b/spec/support/helpers/key_generator_helper.rb
deleted file mode 100644
index 58bde80a31f..00000000000
--- a/spec/support/helpers/key_generator_helper.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module Support
- module Helpers
- class KeyGeneratorHelper
- # The components in a openssh .pub / known_host RSA public key.
- RSA_COMPONENTS = ['ssh-rsa', :e, :n].freeze
-
- attr_reader :size
-
- def initialize(size = 2048)
- @size = size
- end
-
- def generate
- key = OpenSSL::PKey::RSA.generate(size)
- components = RSA_COMPONENTS.map do |component|
- key.respond_to?(component) ? encode_mpi(key.public_send(component)) : component
- end
-
- # Ruby tries to be helpful and adds new lines every 60 bytes :(
- 'ssh-rsa ' + [pack_pubkey_components(components)].pack('m').delete("\n")
- end
-
- private
-
- # Encodes an openssh-mpi-encoded integer.
- def encode_mpi(n) # rubocop:disable Naming/UncommunicativeMethodParamName
- chars = []
- n = n.to_i
- chars << (n & 0xff) && n >>= 8 while n != 0
- chars << 0 if chars.empty? || chars.last >= 0x80
- chars.reverse.pack('C*')
- end
-
- # Packs string components into an openssh-encoded pubkey.
- def pack_pubkey_components(strings)
- (strings.flat_map { |s| [s.length].pack('N') }).zip(strings).join
- end
- end
- end
- end
-end
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 4e0e8dd96ee..c0734bae375 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -178,7 +178,7 @@ module LoginHelpers
end
def mock_saml_config
- OpenStruct.new(name: 'saml', label: 'saml', args: {
+ ActiveSupport::InheritableOptions.new(name: 'saml', label: 'saml', args: {
assertion_consumer_service_url: 'https://localhost:3443/users/auth/saml/callback',
idp_cert_fingerprint: '26:43:2C:47:AF:F0:6B:D0:07:9C:AD:A3:74:FE:5D:94:5F:4E:9E:52',
idp_sso_target_url: 'https://idp.example.com/sso/saml',
diff --git a/spec/support/helpers/memory_usage_helper.rb b/spec/support/helpers/memory_usage_helper.rb
deleted file mode 100644
index 02d1935921f..00000000000
--- a/spec/support/helpers/memory_usage_helper.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module MemoryUsageHelper
- extend ActiveSupport::Concern
-
- def gather_memory_data(csv_path)
- write_csv_entry(csv_path,
- {
- example_group_path: TestEnv.topmost_example_group[:location],
- example_group_description: TestEnv.topmost_example_group[:description],
- time: Time.current,
- job_name: ENV['CI_JOB_NAME']
- }.merge(get_memory_usage))
- end
-
- def write_csv_entry(path, entry)
- CSV.open(path, "a", headers: entry.keys, write_headers: !File.exist?(path)) do |file|
- file << entry.values
- end
- end
-
- def get_memory_usage
- output, status = Gitlab::Popen.popen(%w(free -m))
- abort "`free -m` return code is #{status}: #{output}" unless status == 0
-
- result = output.split("\n")[1].split(" ")[1..]
- attrs = %i(m_total m_used m_free m_shared m_buffers_cache m_available).freeze
-
- attrs.zip(result).to_h
- end
-
- included do |config|
- config.after(:all) do
- gather_memory_data(ENV['MEMORY_TEST_PATH']) if ENV['MEMORY_TEST_PATH']
- end
- end
-end
diff --git a/spec/support/helpers/merge_request_diff_helpers.rb b/spec/support/helpers/merge_request_diff_helpers.rb
index 30afde7efed..7515c789add 100644
--- a/spec/support/helpers/merge_request_diff_helpers.rb
+++ b/spec/support/helpers/merge_request_diff_helpers.rb
@@ -1,8 +1,11 @@
# frozen_string_literal: true
module MergeRequestDiffHelpers
+ PageEndReached = Class.new(StandardError)
+
def click_diff_line(line_holder, diff_side = nil)
line = get_line_components(line_holder, diff_side)
+ scroll_to_elements_bottom(line_holder)
line_holder.hover
line[:num].find('.js-add-diff-note-button').click
end
@@ -27,4 +30,55 @@ module MergeRequestDiffHelpers
line_holder.find('.diff-line-num', match: :first)
{ content: line_holder.all('.line_content')[side_index], num: line_holder.all('.diff-line-num')[side_index] }
end
+
+ def has_reached_page_end
+ evaluate_script("(window.innerHeight + window.scrollY) >= document.body.offsetHeight")
+ end
+
+ def scroll_to_elements_bottom(element)
+ evaluate_script("(function(el) {
+ window.scrollBy(0, el.getBoundingClientRect().bottom - window.innerHeight);
+ })(arguments[0]);", element.native)
+ end
+
+ # we're not using Capybara's .obscured here because it also checks if the element is clickable
+ def within_viewport?(element)
+ evaluate_script("(function(el) {
+ var rect = el.getBoundingClientRect();
+ return (
+ rect.bottom >= 0 &&
+ rect.right >= 0 &&
+ rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
+ rect.left <= (window.innerWidth || document.documentElement.clientWidth)
+ );
+ })(arguments[0]);", element.native)
+ end
+
+ def find_within_viewport(selector, **options)
+ begin
+ element = find(selector, **options, wait: 2)
+ rescue Capybara::ElementNotFound
+ return
+ end
+ return element if within_viewport?(element)
+
+ nil
+ end
+
+ def find_by_scrolling(selector, **options)
+ element = find_within_viewport(selector, **options)
+ return element if element
+
+ page.execute_script "window.scrollTo(0,0)"
+ until element
+
+ if has_reached_page_end
+ raise PageEndReached, "Failed to find any elements matching a selector '#{selector}' by scrolling. Page end reached."
+ end
+
+ page.execute_script "window.scrollBy(0,window.innerHeight/1.5)"
+ element = find_within_viewport(selector, **options)
+ end
+ element
+ end
end
diff --git a/spec/support/helpers/note_interaction_helpers.rb b/spec/support/helpers/note_interaction_helpers.rb
index a4322618cd3..fa2705a64fa 100644
--- a/spec/support/helpers/note_interaction_helpers.rb
+++ b/spec/support/helpers/note_interaction_helpers.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
module NoteInteractionHelpers
+ include MergeRequestDiffHelpers
+
def open_more_actions_dropdown(note)
- note_element = find("#note_#{note.id}")
+ note_element = find_by_scrolling("#note_#{note.id}")
note_element.find('.more-actions-toggle').click
note_element.find('.more-actions .dropdown-menu li', match: :first)
diff --git a/spec/support/helpers/rack_attack_spec_helpers.rb b/spec/support/helpers/rack_attack_spec_helpers.rb
index d50a6382a40..c82a87dc58e 100644
--- a/spec/support/helpers/rack_attack_spec_helpers.rb
+++ b/spec/support/helpers/rack_attack_spec_helpers.rb
@@ -26,14 +26,14 @@ module RackAttackSpecHelpers
{ 'AUTHORIZATION' => "Basic #{encoded_login}" }
end
- def expect_rejection(&block)
+ def expect_rejection(name = nil, &block)
yield
expect(response).to have_gitlab_http_status(:too_many_requests)
expect(response.headers.to_h).to include(
'RateLimit-Limit' => a_string_matching(/^\d+$/),
- 'RateLimit-Name' => a_string_matching(/^throttle_.*$/),
+ 'RateLimit-Name' => name || a_string_matching(/^throttle_.*$/),
'RateLimit-Observed' => a_string_matching(/^\d+$/),
'RateLimit-Remaining' => a_string_matching(/^\d+$/),
'Retry-After' => a_string_matching(/^\d+$/)
diff --git a/spec/support/helpers/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index bbba58d60d6..f275be39dc4 100644
--- a/spec/support/helpers/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
@@ -129,7 +129,7 @@ eos
commit_message: 'Add new content')
Files::CreateService.new(
project,
- project.owner,
+ project.first_owner,
commit_message: commit_message,
start_branch: start_branch,
branch_name: branch_name,
diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb
index 236585296e5..394a401afca 100644
--- a/spec/support/helpers/session_helpers.rb
+++ b/spec/support/helpers/session_helpers.rb
@@ -1,6 +1,22 @@
# frozen_string_literal: true
module SessionHelpers
+ # Stub a session in Redis, for use in request specs where we can't mock the session directly.
+ # This also needs the :clean_gitlab_redis_sessions tag on the spec.
+ def stub_session(session_hash)
+ unless RSpec.current_example.metadata[:clean_gitlab_redis_sessions]
+ raise 'Add :clean_gitlab_redis_sessions to your spec!'
+ end
+
+ session_id = Rack::Session::SessionId.new(SecureRandom.hex)
+
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
+ end
+
+ cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+ end
+
def expect_single_session_with_authenticated_ttl
expect_single_session_with_expiration(Settings.gitlab['session_expire_delay'] * 60)
end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index c3459f7bc81..749554f7786 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -51,6 +51,8 @@ module StubGitlabCalls
allow(Gitlab.config.registry).to receive_messages(registry_settings)
allow(Auth::ContainerRegistryAuthenticationService)
.to receive(:full_access_token).and_return('token')
+ allow(Auth::ContainerRegistryAuthenticationService)
+ .to receive(:import_access_token).and_return('token')
end
def stub_container_registry_tags(repository: :any, tags: [], with_manifest: false)
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 5c3ca92c4d0..18c25f4b770 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -371,17 +371,6 @@ module TestEnv
FileUtils.rm_rf(path)
end
- def current_example_group
- Thread.current[:current_example_group]
- end
-
- # looking for a top-level `describe`
- def topmost_example_group
- example_group = current_example_group
- example_group = example_group[:parent_example_group] until example_group[:parent_example_group].nil?
- example_group
- end
-
def seed_db
Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.import
end
diff --git a/spec/support/import_export/import_export.yml b/spec/support/import_export/import_export.yml
index 116bc8d0b9c..fa10e1335c5 100644
--- a/spec/support/import_export/import_export.yml
+++ b/spec/support/import_export/import_export.yml
@@ -28,4 +28,4 @@ excluded_attributes:
- :iid
project:
- :id
- - :created_at \ No newline at end of file
+ - :created_at
diff --git a/spec/support/matchers/event_store.rb b/spec/support/matchers/event_store.rb
new file mode 100644
index 00000000000..96a71ae3c22
--- /dev/null
+++ b/spec/support/matchers/event_store.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :event_type do |event_class|
+ match do |actual|
+ actual.instance_of?(event_class) &&
+ actual.data == @expected_data
+ end
+
+ chain :containing do |expected_data|
+ @expected_data = expected_data
+ end
+end
diff --git a/spec/support/matchers/schema_matcher.rb b/spec/support/matchers/schema_matcher.rb
index 5e08e96f4e1..d2f32b60464 100644
--- a/spec/support/matchers/schema_matcher.rb
+++ b/spec/support/matchers/schema_matcher.rb
@@ -36,12 +36,38 @@ end
RSpec::Matchers.define :match_response_schema do |schema, dir: nil, **options|
match do |response|
- schema_path = Pathname.new(SchemaPath.expand(schema, dir))
- validator = SchemaPath.validator(schema_path)
+ @schema_path = Pathname.new(SchemaPath.expand(schema, dir))
+ validator = SchemaPath.validator(@schema_path)
- data = Gitlab::Json.parse(response.body)
+ @data = Gitlab::Json.parse(response.body)
- validator.valid?(data)
+ @schema_errors = validator.validate(@data)
+ @schema_errors.none?
+ end
+
+ failure_message do |actual|
+ message = []
+
+ message << <<~MESSAGE
+ expected JSON response to match schema #{@schema_path.inspect}.
+
+ JSON input: #{Gitlab::Json.pretty_generate(@data).indent(2)}
+
+ Schema errors:
+ MESSAGE
+
+ @schema_errors.each do |error|
+ property_name, actual_value = error.values_at('data_pointer', 'data')
+ property_name = 'root' if property_name.empty?
+
+ message << <<~MESSAGE
+ Property: #{property_name}
+ Actual value: #{Gitlab::Json.pretty_generate(actual_value).indent(2)}
+ Error: #{JSONSchemer::Errors.pretty(error)}
+ MESSAGE
+ end
+
+ message.join("\n")
end
end
diff --git a/spec/support/shared_contexts/container_repositories_shared_context.rb b/spec/support/shared_contexts/container_repositories_shared_context.rb
new file mode 100644
index 00000000000..7f61631dce0
--- /dev/null
+++ b/spec/support/shared_contexts/container_repositories_shared_context.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'importable repositories' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:valid_container_repository) { create(:container_repository, project: project, created_at: 2.days.ago) }
+ let_it_be(:valid_container_repository2) { create(:container_repository, project: project, created_at: 1.year.ago) }
+ let_it_be(:importing_container_repository) { create(:container_repository, :importing, project: project, created_at: 2.days.ago) }
+ let_it_be(:new_container_repository) { create(:container_repository, project: project) }
+
+ let_it_be(:denied_group) { create(:group) }
+ let_it_be(:denied_project) { create(:project, group: denied_group) }
+ let_it_be(:denied_container_repository) { create(:container_repository, project: denied_project, created_at: 2.days.ago) }
+
+ before do
+ stub_application_setting(container_registry_import_created_before: 1.day.ago)
+ stub_feature_flags(
+ container_registry_phase_2_deny_list: false,
+ container_registry_migration_limit_gitlab_org: false
+ )
+
+ Feature::FlipperGate.create!(
+ feature_key: 'container_registry_phase_2_deny_list',
+ key: 'actors',
+ value: "Group:#{denied_group.id}"
+ )
+ 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
index 3d2b0433b21..3ea6658c0c1 100644
--- a/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
+++ b/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
@@ -18,6 +18,8 @@ Integration.available_integration_names.each do |integration|
hash.merge!(k => 'https://example.atlassian.net/wiki')
elsif integration == 'datadog' && k == :datadog_site
hash.merge!(k => 'datadoghq.com')
+ elsif integration == 'datadog' && k == :datadog_tags
+ hash.merge!(k => 'key:value')
elsif integration == 'packagist' && k == :server
hash.merge!(k => 'https://packagist.example.com')
elsif k =~ /^(.*_url|url|webhook)/
diff --git a/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb b/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb
index 54bb9fd108e..fadd46a7e12 100644
--- a/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb
+++ b/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_context 'project service Jira context' do
+RSpec.shared_context 'project integration Jira context' do
let(:url) { 'https://jira.example.com' }
let(:test_url) { 'https://jira.example.com/rest/api/2/serverInfo' }
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
index 6414a4d1eb3..bac7bd00f46 100644
--- a/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
+++ b/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_context 'project service activation' do
+RSpec.shared_context 'project integration activation' do
include_context 'integration activation'
let_it_be(:project) { create(:project) }
diff --git a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
index 6b15eadc1c1..3479dac0077 100644
--- a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
RSpec.shared_context 'GroupProjectsFinder context' do
- let_it_be(:group) { create(:group) }
+ let_it_be(:root_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: root_group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:current_user) { create(:user) }
let(:params) { {} }
@@ -16,6 +17,9 @@ RSpec.shared_context 'GroupProjectsFinder context' do
let_it_be(:shared_project_3) { create(:project, :internal, path: '5', name: 'c') }
let_it_be(:subgroup_project) { create(:project, :public, path: '6', group: subgroup, name: 'b') }
let_it_be(:subgroup_private_project) { create(:project, :private, path: '7', group: subgroup, name: 'a') }
+ let_it_be(:root_group_public_project) { create(:project, :public, path: '8', group: root_group, name: 'root-public-project') }
+ let_it_be(:root_group_private_project) { create(:project, :private, path: '9', group: root_group, name: 'root-private-project') }
+ let_it_be(:root_group_private_project_2) { create(:project, :private, path: '10', group: root_group, name: 'root-private-project-2') }
before do
shared_project_1.project_group_links.create!(group_access: Gitlab::Access::MAINTAINER, group: group)
diff --git a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
index 9ac3d4a04f9..13e7ecf2669 100644
--- a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
+++ b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
@@ -11,7 +11,7 @@ RSpec.shared_context 'package details setup' do
let(:package_files) { all_graphql_fields_for('PackageFile') }
let(:dependency_links) { all_graphql_fields_for('PackageDependencyLink') }
let(:pipelines) { all_graphql_fields_for('Pipeline', max_depth: 1) }
- let(:user) { project.owner }
+ let(:user) { project.first_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'] } }
diff --git a/spec/support/shared_contexts/lib/container_registry/client_shared_context.rb b/spec/support/shared_contexts/lib/container_registry/client_shared_context.rb
new file mode 100644
index 00000000000..a87a3247b95
--- /dev/null
+++ b/spec/support/shared_contexts/lib/container_registry/client_shared_context.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'container registry client' do
+ let(:token) { '12345' }
+ let(:options) { { token: token } }
+ let(:registry_api_url) { 'http://container-registry' }
+ let(:client) { described_class.new(registry_api_url, options) }
+ let(:push_blob_headers) do
+ {
+ 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
+ 'Authorization' => "bearer #{token}",
+ 'Content-Type' => 'application/octet-stream',
+ 'User-Agent' => "GitLab/#{Gitlab::VERSION}"
+ }
+ end
+
+ let(:headers_with_accept_types) do
+ {
+ 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
+ 'Authorization' => "bearer #{token}",
+ 'User-Agent' => "GitLab/#{Gitlab::VERSION}"
+ }
+ end
+
+ let(:expected_faraday_headers) { { user_agent: "GitLab/#{Gitlab::VERSION}" } }
+ let(:expected_faraday_request_options) { Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS }
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 27967850389..576a8aa44fa 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -22,6 +22,7 @@ RSpec.shared_context 'project navbar structure' do
nav_sub_items: [
_('Activity'),
_('Labels'),
+ _('Planning hierarchy'),
_('Members')
]
},
diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
index 0dfd76de79c..76db2bd82f1 100644
--- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -47,6 +47,7 @@ RSpec.shared_context 'GroupPolicy context' do
create_custom_emoji
create_package
create_package_settings
+ read_cluster
]
end
@@ -54,7 +55,7 @@ RSpec.shared_context 'GroupPolicy context' do
%i[
destroy_package
create_projects
- read_cluster create_cluster update_cluster admin_cluster add_cluster
+ create_cluster update_cluster admin_cluster add_cluster
]
end
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 c39252cef13..3641edc845a 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -17,7 +17,7 @@ RSpec.shared_context 'ProjectPolicy context' do
%i[
award_emoji create_issue create_merge_request_in create_note
create_project read_issue_board read_issue read_issue_iid read_issue_link
- read_label read_issue_board_list read_milestone read_note read_project
+ read_label read_planning_hierarchy read_issue_board_list read_milestone read_note read_project
read_project_for_iids read_project_member read_release read_snippet
read_wiki upload_file
]
diff --git a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
index 21be989d697..e26b8cd8b37 100644
--- a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
+++ b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
@@ -3,7 +3,7 @@
RSpec.shared_context 'container repository delete tags service shared context' do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :private) }
- let_it_be(:repository) { create(:container_repository, :root, project: project) }
+ let_it_be_with_reload(:repository) { create(:container_repository, :root, project: project) }
let(:params) { { tags: tags } }
diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
index 62b35923bcd..5ed8dc7ce98 100644
--- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
@@ -205,10 +205,30 @@ RSpec.shared_examples 'handle uploads' do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
- it "responds with status 200" do
- show_upload
+ context "enforce_auth_checks_on_uploads feature flag" do
+ context "with flag enabled" do
+ before do
+ stub_feature_flags(enforce_auth_checks_on_uploads: true)
+ end
- expect(response).to have_gitlab_http_status(:ok)
+ it "responds with status 302" do
+ show_upload
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ end
+ end
+
+ context "with flag disabled" do
+ before do
+ stub_feature_flags(enforce_auth_checks_on_uploads: false)
+ end
+
+ it "responds with status 200" do
+ show_upload
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
end
end
@@ -276,10 +296,30 @@ RSpec.shared_examples 'handle uploads' do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
- it "responds with status 200" do
- show_upload
+ context "enforce_auth_checks_on_uploads feature flag" do
+ context "with flag enabled" do
+ before do
+ stub_feature_flags(enforce_auth_checks_on_uploads: true)
+ end
+
+ it "responds with status 404" do
+ show_upload
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context "with flag disabled" do
+ before do
+ stub_feature_flags(enforce_auth_checks_on_uploads: false)
+ end
+
+ it "responds with status 200" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb b/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
index e0a032b1a43..8a07e52019c 100644
--- a/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'comment on merge request file' do
it 'adds a comment' do
- click_diff_line(find("[id='#{sample_commit.line_code}']"))
+ click_diff_line(find_by_scrolling("[id='#{sample_commit.line_code}']"))
page.within('.js-discussion-note-form') do
fill_in(:note_note, with: 'Line is wrong')
diff --git a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
index 1c816ee4b0a..456175e7113 100644
--- a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
@@ -62,7 +62,7 @@ RSpec.shared_examples 'a creatable merge request' do
end
it 'updates the branches when selecting a new target project', :js do
- target_project_member = target_project.owner
+ target_project_member = target_project.first_owner
::Branches::CreateService.new(target_project, target_project_member)
.execute('a-brand-new-branch-to-test', 'master')
diff --git a/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb b/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
index a9dac7a391f..281a70e46c4 100644
--- a/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
+++ b/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
@@ -54,7 +54,10 @@ RSpec.shared_examples 'labels sidebar widget' do
end
fill_in 'Search', with: 'Devel'
- sleep 1
+ expect(page).to have_css('.labels-fetch-loading')
+ wait_for_all_requests
+
+ expect(page).to have_css('[data-testid="dropdown-content"] .gl-new-dropdown-item')
expect(page.all(:css, '[data-testid="dropdown-content"] .gl-new-dropdown-item').length).to eq(1)
find_field('Search').native.send_keys(:enter)
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 52451839281..c63faace6b2 100644
--- a/spec/support/shared_examples/features/variable_list_shared_examples.rb
+++ b/spec/support/shared_examples/features/variable_list_shared_examples.rb
@@ -166,7 +166,7 @@ RSpec.shared_examples 'variable list' do
wait_for_requests
expect(find('.flash-container')).to be_present
- expect(find('.flash-text').text).to have_content('Variables key (key) has already been taken')
+ expect(find('[data-testid="alert-danger"]').text).to have_content('Variables key (key) has already been taken')
end
it 'prevents a variable to be added if no values are provided when a variable is set to masked' do
diff --git a/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
index 1a981f42086..2285d9a17e2 100644
--- a/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
@@ -85,7 +85,9 @@ RSpec.shared_examples 'User previews wiki changes' do
end
it 'renders content with CommonMark' do
- fill_in :wiki_content, with: "1. one\n - sublist\n"
+ # using two `\n` ensures we're sublist to it's own line due
+ # to list auto-continue
+ fill_in :wiki_content, with: "1. one\n\n - sublist\n"
click_on "Preview"
# the above generates two separate lists (not embedded) in CommonMark
diff --git a/spec/support/shared_examples/graphql/boards_shared_examples.rb b/spec/support/shared_examples/graphql/boards_shared_examples.rb
new file mode 100644
index 00000000000..e8a4c17fb92
--- /dev/null
+++ b/spec/support/shared_examples/graphql/boards_shared_examples.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'querying a GraphQL type recent boards' do
+ describe 'Get list of recently visited boards' do
+ let(:boards_data) { graphql_data[board_type]['recentIssueBoards']['nodes'] }
+
+ context 'when the request is correct' do
+ before do
+ visit_board
+ parent.add_reporter(user)
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns recent boards for user successfully' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_errors).to be_nil
+ expect(boards_data.size).to eq(1)
+ expect(boards_data[0]['name']).to eq(board.name)
+ end
+ end
+
+ context 'when requests has errors' do
+ context 'when there are no recently visited boards' do
+ it 'returns empty result' do
+ post_graphql(query, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors).to be_nil
+ expect(boards_data).to be_empty
+ end
+ end
+ end
+ end
+
+ def query(query_params: {}, full_path: parent.full_path)
+ board_nodes = <<~NODE
+ nodes {
+ name
+ }
+ NODE
+
+ graphql_query_for(
+ board_type.to_sym,
+ { full_path: full_path },
+ query_graphql_field(:recent_issue_boards, query_params, board_nodes)
+ )
+ end
+
+ def visit_board
+ if board_type == 'group'
+ create(:board_group_recent_visit, group: parent, board: board, user: user)
+ else
+ create(:board_project_recent_visit, project: parent, board: board, user: user)
+ end
+ end
+end
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 011a2157f24..b17e59f0797 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
@@ -16,17 +16,4 @@ RSpec.shared_examples 'a mutation which can mutate a spammable' do
subject
end
end
-
- describe "#spam_action_response_fields" do
- it 'resolves with spam action fields' do
- subject
-
- # NOTE: We do not need to assert on the specific values of spam action fields here, we only need
- # to verify that #spam_action_response_fields was invoked and that the fields are present in the
- # response. The specific behavior of #spam_action_response_fields is covered in the
- # HasSpamActionResponseFields unit tests.
- expect(mutation_response.keys)
- .to include('spam', 'spamLogId', 'needsCaptchaResponse', 'captchaSiteKey')
- end
- end
end
diff --git a/spec/support/shared_examples/graphql/mutations/security/ci_configuration_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/security/ci_configuration_shared_examples.rb
index 2bb3d807aa7..14b2663a72c 100644
--- a/spec/support/shared_examples/graphql/mutations/security/ci_configuration_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/security/ci_configuration_shared_examples.rb
@@ -18,7 +18,7 @@ RSpec.shared_examples_for 'graphql mutations security ci configuration' do
ServiceResponse.success(payload: { branch: branch, success_path: success_path })
end
- let(:error) { "An error occured!" }
+ let(:error) { "An error occurred!" }
let(:service_error_response) do
ServiceResponse.error(message: error)
diff --git a/spec/support/shared_examples/integrations/integration_settings_form.rb b/spec/support/shared_examples/integrations/integration_settings_form.rb
new file mode 100644
index 00000000000..d0bb40e43ee
--- /dev/null
+++ b/spec/support/shared_examples/integrations/integration_settings_form.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'integration settings form' do
+ include IntegrationsHelper
+ # Note: these specs don't validate channel fields
+ # which are present on a few integrations
+ it 'displays all the integrations' do
+ aggregate_failures do
+ integrations.each do |integration|
+ navigate_to_integration(integration)
+
+ page.within('form.integration-settings-form') do
+ expect(page).to have_field('Active', type: 'checkbox', wait: 0),
+ "#{integration.title} active field not present"
+
+ fields = parse_json(fields_for_integration(integration))
+ fields.each do |field|
+ field_name = field[:name]
+ expect(page).to have_field(field[:title], wait: 0),
+ "#{integration.title} field #{field_name} not present"
+ end
+
+ events = parse_json(trigger_events_for_integration(integration))
+ events.each do |trigger|
+ # normalizing the title because capybara location is case sensitive
+ title = normalize_title trigger[:title], integration
+
+ expect(page).to have_field(title, type: 'checkbox', wait: 0),
+ "#{integration.title} field #{title} checkbox not present"
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def normalize_title(title, integration)
+ return 'Merge request' if integration.is_a?(Integrations::Jira) && title == 'merge_request'
+
+ title.titlecase
+ end
+
+ def parse_json(json)
+ Gitlab::Json.parse(json, symbolize_names: true)
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb
index 5baa6478225..fdca326dbea 100644
--- a/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
RSpec.shared_examples 'tracks assignment and records the subject' do |experiment, subject_type|
+ before do
+ stub_experiments(experiment => true)
+ end
+
it 'tracks the assignment', :experiment do
expect(experiment(experiment))
.to track(:assignment)
@@ -11,9 +15,7 @@ RSpec.shared_examples 'tracks assignment and records the subject' do |experiment
end
it 'records the subject' do
- stub_experiments(experiment => :candidate)
-
- expect(Experiment).to receive(:add_subject).with(experiment.to_s, variant: :experimental, subject: subject)
+ expect(Experiment).to receive(:add_subject).with(experiment.to_s, variant: anything, subject: subject)
action
end
diff --git a/spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/code_review_extension_request_examples.rb
index 7593d51fe76..6221366ab51 100644
--- a/spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/code_review_extension_request_examples.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.shared_examples 'a tracked vs code unique action' do |event|
+RSpec.shared_examples 'a request from an extension' do |event|
before do
stub_application_setting(usage_ping_enabled: true)
end
@@ -11,10 +11,12 @@ RSpec.shared_examples 'a tracked vs code unique action' do |event|
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to)
end
- it 'tracks when the user agent is from vs code' do
- aggregate_failures do
- user_agent = { user_agent: 'vs-code-gitlab-workflow/3.11.1 VSCode/1.52.1 Node.js/12.14.1 (darwin; x64)' }
+ def track_action(params)
+ described_class.track_api_request_when_trackable(**params)
+ end
+ it 'tracks when the user agent is matching' do
+ aggregate_failures do
expect(track_action(user: user1, **user_agent)).to be_truthy
expect(track_action(user: user1, **user_agent)).to be_truthy
expect(track_action(user: user2, **user_agent)).to be_truthy
@@ -23,7 +25,7 @@ RSpec.shared_examples 'a tracked vs code unique action' do |event|
end
end
- it 'does not track when the user agent is not from vs code' do
+ it 'does not track when the user agent is not matching' do
aggregate_failures do
user_agent = { user_agent: 'normal_user_agent' }
@@ -40,24 +42,6 @@ RSpec.shared_examples 'a tracked vs code unique action' do |event|
end
it 'does not track if user is not present' do
- user_agent = { user_agent: 'vs-code-gitlab-workflow/3.11.1 VSCode/1.52.1 Node.js/12.14.1 (darwin; x64)' }
-
expect(track_action(user: nil, **user_agent)).to be_nil
end
end
-
-RSpec.describe Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter, :clean_gitlab_redis_shared_state do
- let(:user1) { build(:user, id: 1) }
- let(:user2) { build(:user, id: 2) }
- let(:time) { Time.current }
-
- context 'when tracking a vs code api request' do
- it_behaves_like 'a tracked vs code unique action' do
- let(:action) { described_class::VS_CODE_API_REQUEST_ACTION }
-
- def track_action(params)
- described_class.track_api_request_when_trackable(**params)
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb b/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb
index d3fd28727b5..b4c438771ce 100644
--- a/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb
+++ b/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.shared_examples 'ZenTao menu with CE version' do
let(:project) { create(:project, has_external_issue_tracker: true) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
let(:zentao_integration) { create(:zentao_integration, project: project) }
diff --git a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
index 42eec74e64f..5f59d43ad19 100644
--- a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
+++ b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
@@ -7,6 +7,12 @@ RSpec.shared_examples 'it has loose foreign keys' do
let(:fully_qualified_table_name) { "#{connection.current_schema}.#{table_name}" }
let(:deleted_records) { LooseForeignKeys::DeletedRecord.where(fully_qualified_table_name: fully_qualified_table_name) }
+ around do |example|
+ LooseForeignKeys::DeletedRecord.using_connection(connection) do
+ example.run
+ end
+ end
+
it 'has at least one loose foreign key definition' do
definitions = Gitlab::Database::LooseForeignKeys.definitions_by_table[table_name]
expect(definitions.size).to be > 0
@@ -69,7 +75,9 @@ RSpec.shared_examples 'cleanup by a loose foreign key' do
expect(find_model).to be_present
- LooseForeignKeys::ProcessDeletedRecordsService.new(connection: model.connection).execute
+ LooseForeignKeys::DeletedRecord.using_connection(parent.connection) do
+ LooseForeignKeys::ProcessDeletedRecordsService.new(connection: parent.connection).execute
+ end
if foreign_key_definition.on_delete.eql?(:async_delete)
expect(find_model).not_to be_present
diff --git a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
index d823e7ac221..8ff30021d6e 100644
--- a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
+++ b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
@@ -178,4 +178,22 @@ RSpec.shared_examples 'StageEventModel' do
end
end
end
+
+ describe '#total_time' do
+ it 'calcualtes total time from the start_event_timestamp and end_event_timestamp columns' do
+ model = described_class.new(start_event_timestamp: Time.new(2022, 1, 1, 12, 5, 0), end_event_timestamp: Time.new(2022, 1, 1, 12, 6, 30))
+
+ expect(model.total_time).to eq(90)
+ end
+
+ context 'when total time is calculated in SQL as an extra column' do
+ it 'returns the SQL calculated time' do
+ create(stage_event_factory) # rubocop:disable Rails/SaveBang
+
+ model = described_class.select('*, 5 AS total_time').first
+
+ expect(model.total_time).to eq(5)
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index 5b4b8c8fcc1..f7e09cfca62 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -301,8 +301,9 @@ RSpec.shared_examples_for "member creation" do
end
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ let(:task_project) { source.is_a?(Group) ? create(:project, group: source) : source }
+
it 'creates a member_task with the correct attributes', :aggregate_failures do
- task_project = source.is_a?(Group) ? create(:project, group: source) : source
described_class.new(source, user, :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id).execute
member = source.members.last
@@ -310,6 +311,43 @@ RSpec.shared_examples_for "member creation" do
expect(member.tasks_to_be_done).to match_array([:ci, :code])
expect(member.member_task.project).to eq(task_project)
end
+
+ context 'with an already existing member' do
+ before do
+ source.add_user(user, :developer)
+ end
+
+ it 'does not update tasks to be done if tasks already exist', :aggregate_failures do
+ member = source.members.find_by(user_id: user.id)
+ create(:member_task, member: member, project: task_project, tasks_to_be_done: %w(code ci))
+
+ expect do
+ described_class.new(source,
+ user,
+ :developer,
+ tasks_to_be_done: %w(issues),
+ tasks_project_id: task_project.id).execute
+ end.not_to change(MemberTask, :count)
+
+ member.reset
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project).to eq(task_project)
+ end
+
+ it 'adds tasks to be done if they do not exist', :aggregate_failures do
+ expect do
+ described_class.new(source,
+ user,
+ :developer,
+ tasks_to_be_done: %w(issues),
+ tasks_project_id: task_project.id).execute
+ end.to change(MemberTask, :count).by(1)
+
+ member = source.members.find_by(user_id: user.id)
+ expect(member.tasks_to_be_done).to match_array([:issues])
+ expect(member.member_task.project).to eq(task_project)
+ end
+ end
end
end
end
@@ -393,14 +431,52 @@ RSpec.shared_examples_for "bulk member creation" do
end
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ let(:task_project) { source.is_a?(Group) ? create(:project, group: source) : source }
+
it 'creates a member_task with the correct attributes', :aggregate_failures do
- task_project = source.is_a?(Group) ? create(:project, group: source) : source
members = described_class.add_users(source, [user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id)
member = members.last
expect(member.tasks_to_be_done).to match_array([:ci, :code])
expect(member.member_task.project).to eq(task_project)
end
+
+ context 'with an already existing member' do
+ before do
+ source.add_user(user1, :developer)
+ end
+
+ it 'does not update tasks to be done if tasks already exist', :aggregate_failures do
+ member = source.members.find_by(user_id: user1.id)
+ create(:member_task, member: member, project: task_project, tasks_to_be_done: %w(code ci))
+
+ expect do
+ described_class.add_users(source,
+ [user1.id],
+ :developer,
+ tasks_to_be_done: %w(issues),
+ tasks_project_id: task_project.id)
+ end.not_to change(MemberTask, :count)
+
+ member.reset
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project).to eq(task_project)
+ end
+
+ it 'adds tasks to be done if they do not exist', :aggregate_failures do
+ expect do
+ described_class.add_users(source,
+ [user1.id],
+ :developer,
+ tasks_to_be_done: %w(issues),
+ tasks_project_id: task_project.id)
+ end.to change(MemberTask, :count).by(1)
+
+ member = source.members.find_by(user_id: user1.id)
+ expect(member.tasks_to_be_done).to match_array([:issues])
+ expect(member.member_task.project).to eq(task_project)
+ end
+ end
end
end
end
diff --git a/spec/support/shared_examples/models/note_access_check_shared_examples.rb b/spec/support/shared_examples/models/note_access_check_shared_examples.rb
index 44edafe9091..0c9992b832f 100644
--- a/spec/support/shared_examples/models/note_access_check_shared_examples.rb
+++ b/spec/support/shared_examples/models/note_access_check_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'users with note access' do
it 'returns true' do
users.each do |user|
- expect(note.system_note_with_references_visible_for?(user)).to be_truthy
+ expect(note.system_note_visible_for?(user)).to be_truthy
expect(note.readable_by?(user)).to be_truthy
end
end
@@ -12,7 +12,7 @@ end
RSpec.shared_examples 'users without note access' do
it 'returns false' do
users.each do |user|
- expect(note.system_note_with_references_visible_for?(user)).to be_falsy
+ expect(note.system_note_visible_for?(user)).to be_falsy
expect(note.readable_by?(user)).to be_falsy
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 3f8c3b8960b..6b0ae589efb 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
@@ -235,18 +235,6 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
it 'does not return them' do
expect(subject.to_a).not_to include(package_file_pending_destruction)
end
-
- context 'with packages_installable_package_files disabled' do
- before do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- subject
-
- expect(subject.to_a).to include(package_file_pending_destruction)
- end
- end
end
end
end
diff --git a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
index 06326ffac97..ad0bbc0aeff 100644
--- a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
+++ b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
@@ -115,14 +115,14 @@ RSpec.shared_examples 'UpdateProjectStatistics' do |with_counter_attribute|
expect(ProjectStatistics)
.not_to receive(:increment_statistic)
- expect(Projects::DestroyService.new(project, project.owner).execute).to eq(true)
+ expect(Projects::DestroyService.new(project, project.first_owner).execute).to eq(true)
end
it 'does not schedule a namespace statistics worker' do
expect(Namespaces::ScheduleAggregationWorker)
.not_to receive(:perform_async)
- expect(Projects::DestroyService.new(project, project.owner).execute).to eq(true)
+ expect(Projects::DestroyService.new(project, project.first_owner).execute).to eq(true)
end
end
end
diff --git a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
index b43b7946e69..bcb5464ed5b 100644
--- a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
@@ -299,4 +299,51 @@ RSpec.shared_examples 'namespace traversal scopes' do
include_examples '.self_and_descendant_ids'
end
end
+
+ shared_examples '.self_and_hierarchy' do
+ let(:base_scope) { Group.where(id: base_groups) }
+
+ subject { base_scope.self_and_hierarchy }
+
+ context 'with ancestors only' do
+ let(:base_groups) { [group_1, group_2] }
+
+ it { is_expected.to match_array(groups) }
+ end
+
+ context 'with descendants only' do
+ let(:base_groups) { [deep_nested_group_1, deep_nested_group_2] }
+
+ it { is_expected.to match_array(groups) }
+ end
+
+ context 'nodes with both ancestors and descendants' do
+ let(:base_groups) { [nested_group_1, nested_group_2] }
+
+ it { is_expected.to match_array(groups) }
+ end
+
+ context 'with duplicate base groups' do
+ let(:base_groups) { [nested_group_1, nested_group_1] }
+
+ it { is_expected.to contain_exactly(group_1, nested_group_1, deep_nested_group_1) }
+ end
+ end
+
+ describe '.self_and_hierarchy' do
+ it_behaves_like '.self_and_hierarchy'
+
+ context "use_traversal_ids_for_self_and_hierarchy_scopes feature flag is false" do
+ before do
+ stub_feature_flags(use_traversal_ids_for_self_and_hierarchy_scopes: false)
+ end
+
+ it_behaves_like '.self_and_hierarchy'
+
+ it 'make recursive queries' do
+ base_groups = Group.where(id: nested_group_1)
+ expect { base_groups.self_and_hierarchy.load }.to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/path_extraction_shared_examples.rb b/spec/support/shared_examples/path_extraction_shared_examples.rb
index 39c7c1f2a94..d76348aa26a 100644
--- a/spec/support/shared_examples/path_extraction_shared_examples.rb
+++ b/spec/support/shared_examples/path_extraction_shared_examples.rb
@@ -40,12 +40,13 @@ RSpec.shared_examples 'assigns ref vars' do
end
context 'path contains space' do
- let(:params) { { path: 'with space', ref: '38008cb17ce1466d8fec2dfa6f6ab8dcfe5cf49e' } }
+ let(:ref) { '38008cb17ce1466d8fec2dfa6f6ab8dcfe5cf49e' }
+ let(:path) { 'with space' }
it 'is not converted to %20 in @path' do
assign_ref_vars
- expect(@path).to eq(params[:path])
+ expect(@path).to eq(path)
end
end
diff --git a/spec/support/shared_examples/policies/clusterable_shared_examples.rb b/spec/support/shared_examples/policies/clusterable_shared_examples.rb
index b96aa71acbe..faf283f9059 100644
--- a/spec/support/shared_examples/policies/clusterable_shared_examples.rb
+++ b/spec/support/shared_examples/policies/clusterable_shared_examples.rb
@@ -6,12 +6,24 @@ RSpec.shared_examples 'clusterable policies' do
subject { described_class.new(current_user, clusterable) }
+ context 'with a reporter' do
+ before do
+ clusterable.add_reporter(current_user)
+ end
+
+ it { expect_disallowed(:read_cluster) }
+ it { expect_disallowed(:add_cluster) }
+ it { expect_disallowed(:create_cluster) }
+ it { expect_disallowed(:update_cluster) }
+ it { expect_disallowed(:admin_cluster) }
+ end
+
context 'with a developer' do
before do
clusterable.add_developer(current_user)
end
- it { expect_disallowed(:read_cluster) }
+ it { expect_allowed(:read_cluster) }
it { expect_disallowed(:add_cluster) }
it { expect_disallowed(:create_cluster) }
it { expect_disallowed(:update_cluster) }
diff --git a/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
index 052fd0622d0..f414500f202 100644
--- a/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
@@ -66,7 +66,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
it 'shows the help state when icon is clicked' do
page.within '.time-tracking-component-wrap' do
- find('.help-button').click
+ find('[data-testid="helpButton"]').click
expect(page).to have_content 'Track time with quick actions'
expect(page).to have_content 'Learn more'
end
@@ -92,8 +92,8 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
it 'hides the help state when close icon is clicked' do
page.within '.time-tracking-component-wrap' do
- find('.help-button').click
- find('.close-help-button').click
+ find('[data-testid="helpButton"]').click
+ find('[data-testid="closeHelpButton"]').click
expect(page).not_to have_content 'Track time with quick actions'
expect(page).not_to have_content 'Learn more'
@@ -102,7 +102,7 @@ RSpec.shared_examples 'issuable time tracker' do |issuable_type|
it 'displays the correct help url' do
page.within '.time-tracking-component-wrap' do
- find('.help-button').click
+ find('[data-testid="helpButton"]').click
expect(find_link('Learn more')[:href]).to have_content('/help/user/project/time_tracking.md')
end
diff --git a/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb
index 28decb4011d..2258bdd2c79 100644
--- a/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb
@@ -73,6 +73,16 @@ RSpec.shared_examples 'rebase quick action' do
expect(page).to have_content 'This merge request cannot be rebased while there are conflicts.'
end
end
+
+ context 'when the merge request branch is protected from force push' do
+ let!(:protected_branch) { create(:protected_branch, project: project, name: merge_request.source_branch, allow_force_push: false) }
+
+ it 'does not rebase the MR' do
+ add_note("/rebase")
+
+ expect(page).to have_content 'This merge request branch is protected from force push.'
+ end
+ end
end
context 'when the current user cannot rebase the MR' do
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
index 8bffd1f71e9..a42a1fda62e 100644
--- a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
@@ -10,6 +10,8 @@ RSpec.shared_examples 'when the snippet is not found' do
end
RSpec.shared_examples 'snippet edit usage data counters' do
+ include SessionHelpers
+
context 'when user is sessionless' do
it 'does not track usage data actions' do
expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).not_to receive(:track_snippet_editor_edit_action)
@@ -20,14 +22,7 @@ RSpec.shared_examples 'snippet edit usage data counters' do
context 'when user is not sessionless', :clean_gitlab_redis_sessions do
before do
- session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
- session_hash = { 'warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]] }
-
- Gitlab::Redis::Sessions.with do |redis|
- redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
- end
-
- cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+ stub_session('warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]])
end
it 'tracks usage data actions', :clean_gitlab_redis_sessions do
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
index 882c79cb03f..127b1a6d4c4 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
@@ -3,11 +3,11 @@
RSpec.shared_examples 'group and project packages query' do
include GraphqlHelpers
- let_it_be(:versionaless_package) { create(:maven_package, project: project1, version: nil) }
- let_it_be(:maven_package) { create(:maven_package, project: project1, name: 'tab', version: '4.0.0', created_at: 5.days.ago) }
- let_it_be(:package) { create(:npm_package, project: project1, name: 'uab', version: '5.0.0', created_at: 4.days.ago) }
- let_it_be(:composer_package) { create(:composer_package, project: project2, name: 'vab', version: '6.0.0', created_at: 3.days.ago) }
- let_it_be(:debian_package) { create(:debian_package, project: project2, name: 'zab', version: '7.0.0', created_at: 2.days.ago) }
+ let_it_be(:versionless_package) { create(:maven_package, project: project1, version: nil) }
+ let_it_be(:maven_package) { create(:maven_package, project: project1, name: 'bab', version: '6.0.0', created_at: 1.day.ago) }
+ let_it_be(:npm_package) { create(:npm_package, project: project1, name: 'cab', version: '7.0.0', created_at: 4.days.ago) }
+ let_it_be(:composer_package) { create(:composer_package, project: project2, name: 'dab', version: '4.0.0', created_at: 3.days.ago) }
+ let_it_be(:debian_package) { create(:debian_package, project: project2, name: 'aab', version: '5.0.0', created_at: 2.days.ago) }
let_it_be(:composer_metadatum) do
create(:composer_metadatum, package: composer_package,
target_sha: 'afdeh',
@@ -21,11 +21,11 @@ RSpec.shared_examples 'group and project packages query' do
let(:fields) do
<<~QUERY
- count
- nodes {
- #{all_graphql_fields_for('packages'.classify, excluded: ['project'])}
- metadata { #{query_graphql_fragment('ComposerMetadata')} }
- }
+ count
+ nodes {
+ #{all_graphql_fields_for('packages'.classify, excluded: ['project'])}
+ metadata { #{query_graphql_fragment('ComposerMetadata')} }
+ }
QUERY
end
@@ -47,7 +47,7 @@ RSpec.shared_examples 'group and project packages query' do
it 'returns packages successfully' do
expect(package_names).to contain_exactly(
- package.name,
+ npm_package.name,
maven_package.name,
debian_package.name,
composer_package.name
@@ -88,7 +88,23 @@ RSpec.shared_examples 'group and project packages query' do
end
describe 'sorting and pagination' do
- let_it_be(:ascending_packages) { [maven_package, package, composer_package, debian_package].map { |package| global_id_of(package)} }
+ let_it_be(:packages_order_map) do
+ {
+ TYPE_ASC: [maven_package, npm_package, composer_package, debian_package],
+ TYPE_DESC: [debian_package, composer_package, npm_package, maven_package],
+
+ NAME_ASC: [debian_package, maven_package, npm_package, composer_package],
+ NAME_DESC: [composer_package, npm_package, maven_package, debian_package],
+
+ VERSION_ASC: [composer_package, debian_package, maven_package, npm_package],
+ VERSION_DESC: [npm_package, maven_package, debian_package, composer_package],
+
+ CREATED_ASC: [npm_package, composer_package, debian_package, maven_package],
+ CREATED_DESC: [maven_package, debian_package, composer_package, npm_package]
+ }
+ end
+
+ let(:expected_packages) { sorted_packages.map { |package| global_id_of(package) } }
let(:data_path) { [resource_type, :packages] }
@@ -96,22 +112,14 @@ RSpec.shared_examples 'group and project packages query' do
resource.add_reporter(current_user)
end
- [:CREATED_ASC, :NAME_ASC, :VERSION_ASC, :TYPE_ASC].each do |order|
+ [:CREATED_ASC, :NAME_ASC, :VERSION_ASC, :TYPE_ASC, :CREATED_DESC, :NAME_DESC, :VERSION_DESC, :TYPE_DESC].each do |order|
context "#{order}" do
- it_behaves_like 'sorted paginated query' do
- let(:sort_param) { order }
- let(:first_param) { 4 }
- let(:all_records) { ascending_packages }
- end
- end
- end
+ let(:sorted_packages) { packages_order_map.fetch(order) }
- [:CREATED_DESC, :NAME_DESC, :VERSION_DESC, :TYPE_DESC].each do |order|
- context "#{order}" do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { order }
let(:first_param) { 4 }
- let(:all_records) { ascending_packages.reverse }
+ let(:all_records) { expected_packages }
end
end
end
@@ -180,7 +188,7 @@ RSpec.shared_examples 'group and project packages query' do
context 'include_versionless' do
let(:params) { { include_versionless: true } }
- it { is_expected.to include({ "name" => versionaless_package.name }) }
+ it { is_expected.to include({ "name" => versionless_package.name }) }
end
end
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
index 9385706d991..ab93f54111b 100644
--- 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
@@ -49,17 +49,5 @@ RSpec.shared_examples 'a package with files' do
expect(response_package_file_ids).not_to include(package_file_pending_destruction.to_global_id.to_s)
end
-
- context 'with packages_installable_package_files disabled' do
- before(:context) do
- stub_feature_flags(packages_installable_package_files: false)
- end
-
- it 'returns them' do
- expect(package.reload.package_files).to include(package_file_pending_destruction)
-
- expect(response_package_file_ids).to include(package_file_pending_destruction.to_global_id.to_s)
- end
- end
end
end
diff --git a/spec/support/shared_examples/requests/api/notes_shared_examples.rb b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
index 0434d0beb7e..2a157f6e855 100644
--- a/spec/support/shared_examples/requests/api/notes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
@@ -190,7 +190,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
if parent_type == 'projects'
context 'by a project owner' do
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
it 'sets the creation time on the new note' do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index b294467d482..c6c6c44dce8 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -580,3 +580,88 @@ RSpec.shared_examples 'rate-limited unauthenticated requests' do
end
end
end
+
+# Requires let variables:
+# * throttle_setting_prefix: "throttle_authenticated", "throttle_unauthenticated"
+RSpec.shared_examples 'rate-limited frontend API requests' do
+ let(:requests_per_period) { 1 }
+ let(:csrf_token) { SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) }
+ let(:csrf_session) { { _csrf_token: csrf_token } }
+ let(:personal_access_token) { nil }
+
+ let(:api_path) { '/projects' }
+
+ # These don't actually exist, so a 404 is the expected response.
+ let(:files_api_path) { '/projects/1/repository/files/ref/path' }
+ let(:packages_api_path) { '/projects/1/packages/foo' }
+ let(:deprecated_api_path) { '/groups/1?with_projects=true' }
+
+ def get_api(path: api_path, csrf: false)
+ headers = csrf ? { 'X-CSRF-Token' => csrf_token } : nil
+ get api(path, personal_access_token: personal_access_token), headers: headers
+ end
+
+ def expect_not_found(&block)
+ yield
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ before do
+ stub_application_setting(
+ "#{throttle_setting_prefix}_enabled" => true,
+ "#{throttle_setting_prefix}_requests_per_period" => requests_per_period,
+ "#{throttle_setting_prefix}_api_enabled" => true,
+ "#{throttle_setting_prefix}_api_requests_per_period" => requests_per_period,
+ "#{throttle_setting_prefix}_web_enabled" => true,
+ "#{throttle_setting_prefix}_web_requests_per_period" => requests_per_period,
+ "#{throttle_setting_prefix}_files_api_enabled" => true,
+ "#{throttle_setting_prefix}_packages_api_enabled" => true,
+ "#{throttle_setting_prefix}_deprecated_api_enabled" => true
+ )
+
+ stub_session(csrf_session)
+ end
+
+ context 'with a CSRF token' do
+ it 'uses the rate limit for web requests' do
+ requests_per_period.times { get_api csrf: true }
+
+ expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true }
+ expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: files_api_path }
+ expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: packages_api_path }
+ expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: deprecated_api_path }
+
+ # API rate limit is not triggered yet
+ expect_ok { get_api }
+ expect_not_found { get_api path: files_api_path }
+ expect_not_found { get_api path: packages_api_path }
+ expect_not_found { get_api path: deprecated_api_path }
+ end
+
+ context 'without a CSRF session' do
+ let(:csrf_session) { nil }
+
+ it 'always uses the rate limit for API requests' do
+ requests_per_period.times { get_api csrf: true }
+
+ expect_rejection("#{throttle_setting_prefix}_api") { get_api csrf: true }
+ expect_rejection("#{throttle_setting_prefix}_api") { get_api }
+ end
+ end
+ end
+
+ context 'without a CSRF token' do
+ it 'uses the rate limit for API requests' do
+ requests_per_period.times { get_api }
+
+ expect_rejection("#{throttle_setting_prefix}_api") { get_api }
+
+ # Web and custom API rate limits are not triggered yet
+ expect_ok { get_api csrf: true }
+ expect_not_found { get_api path: files_api_path }
+ expect_not_found { get_api path: packages_api_path }
+ expect_not_found { get_api path: deprecated_api_path }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb b/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
index d9b837258ce..a46c2f0ac5c 100644
--- a/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
@@ -140,19 +140,6 @@ RSpec.shared_examples 'issues move service' do |group|
expect(issue2.reload.updated_at.change(usec: 0)).to eq updated_at2.change(usec: 0)
end
- if group
- context 'when on a group board' do
- it 'sends the board_group_id parameter' do
- params.merge!(move_after_id: issue1.id, move_before_id: issue2.id)
-
- match_params = { move_between_ids: [issue1.id, issue2.id], board_group_id: parent.id }
- expect(Issues::UpdateService).to receive(:new).with(project: issue.project, current_user: user, params: match_params).and_return(double(execute: build(:issue)))
-
- described_class.new(parent, user, params).execute(issue)
- end
- end
- end
-
def reorder_issues(params, issues: [])
issues.each do |issue|
issue.move_to_end && issue.save!
diff --git a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
index 87bf134eeb8..c808b9a5318 100644
--- a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
@@ -71,7 +71,6 @@ end
RSpec.shared_examples 'an accessible' do
before do
stub_feature_flags(container_registry_migration_phase1: false)
- stub_feature_flags(container_registry_cdn_redirect: false)
end
let(:access) do
@@ -164,10 +163,9 @@ RSpec.shared_examples 'a container registry auth service' do
before do
stub_feature_flags(container_registry_migration_phase1: false)
- stub_feature_flags(container_registry_cdn_redirect: false)
end
- describe '#full_access_token' do
+ describe '.full_access_token' do
let_it_be(:project) { create(:project) }
let(:token) { described_class.full_access_token(project.full_path) }
@@ -181,7 +179,26 @@ RSpec.shared_examples 'a container registry auth service' do
it_behaves_like 'not a container repository factory'
end
- describe '#pull_access_token' do
+ describe '.import_access_token' do
+ let(:access) do
+ [{ 'type' => 'registry',
+ 'name' => 'import',
+ 'actions' => ['*'] }]
+ end
+
+ let(:token) { described_class.import_access_token }
+
+ subject { { token: token } }
+
+ it_behaves_like 'a valid token'
+ it_behaves_like 'not a container repository factory'
+
+ it 'has the correct scope' do
+ expect(payload).to include('access' => access)
+ end
+ end
+
+ describe '.pull_access_token' do
let_it_be(:project) { create(:project) }
let(:token) { described_class.pull_access_token(project.full_path) }
@@ -1126,4 +1143,72 @@ RSpec.shared_examples 'a container registry auth service' do
end
end
end
+
+ context 'when importing' do
+ let_it_be(:container_repository) { create(:container_repository, :root, :importing) }
+ let_it_be(:current_project) { container_repository.project }
+ let_it_be(:current_user) { create(:user) }
+
+ before do
+ current_project.add_developer(current_user)
+ end
+
+ shared_examples 'containing the import error' do
+ it 'includes a helpful error message' do
+ expect(subject[:errors].first).to include(message: /Your repository is currently being migrated/)
+ end
+ end
+
+ context 'push request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:push"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context 'delete request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:delete"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context '* request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:*"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context 'pull request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:pull"] }
+ end
+
+ let(:project) { current_project }
+
+ it_behaves_like 'a pullable'
+ end
+
+ context 'mixed request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:pull,push"] }
+ end
+
+ let(:project) { current_project }
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/services/incident_shared_examples.rb b/spec/support/shared_examples/services/incident_shared_examples.rb
index 36b0acf5a51..cc26cf87322 100644
--- a/spec/support/shared_examples/services/incident_shared_examples.rb
+++ b/spec/support/shared_examples/services/incident_shared_examples.rb
@@ -28,28 +28,15 @@ end
#
# include_examples 'not an incident issue'
RSpec.shared_examples 'not an incident issue' do
- let(:label_properties) { attributes_for(:label, :incident) }
-
it 'has not incident as issue type' do
expect(issue.issue_type).not_to eq('incident')
expect(issue.work_item_type.base_type).not_to eq('incident')
end
-
- it_behaves_like 'does not have incident label'
-end
-
-RSpec.shared_examples 'does not have incident label' do
- let(:label_properties) { attributes_for(:label, :incident) }
-
- it 'has not an incident label' do
- expect(issue.labels).not_to include(have_attributes(label_properties))
- end
end
# This shared example is to test the execution of incident management label services
# For example:
# - IncidentManagement::CreateIncidentSlaExceededLabelService
-# - IncidentManagement::CreateIncidentLabelService
# It doesn't require any defined variables
diff --git a/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb b/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb
new file mode 100644
index 00000000000..661a96266f1
--- /dev/null
+++ b/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'renders registration features prompt' do |disabled_field|
+ it 'renders a placeholder input with registration features message', :aggregate_failures do
+ render
+
+ if disabled_field
+ expect(rendered).to have_field(disabled_field, disabled: true)
+ end
+
+ expect(rendered).to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: s_('RegistrationFeatures|use this feature') })
+ expect(rendered).to have_link(s_('RegistrationFeatures|Registration Features Program'))
+ end
+end
+
+RSpec.shared_examples 'does not render registration features prompt' do |disabled_field|
+ it 'does not render a placeholder input with registration features message', :aggregate_failures do
+ render
+
+ if disabled_field
+ expect(rendered).not_to have_field(disabled_field, disabled: true)
+ end
+
+ expect(rendered).not_to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: s_('RegistrationFeatures|use this feature') })
+ expect(rendered).not_to have_link(s_('RegistrationFeatures|Registration Features Program'))
+ end
+end
diff --git a/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb b/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb
index 0d3e158d358..7fdf049a823 100644
--- a/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb
+++ b/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'it runs background migration jobs' do |tracking_database, metric_name|
+RSpec.shared_examples 'it runs background migration jobs' do |tracking_database|
describe 'defining the job attributes' do
it 'defines the data_consistency as always' do
expect(described_class.get_data_consistency).to eq(:always)
@@ -33,16 +33,6 @@ RSpec.shared_examples 'it runs background migration jobs' do |tracking_database,
end
end
- describe '.unhealthy_metric_name' do
- it 'does not raise an error' do
- expect { described_class.unhealthy_metric_name }.not_to raise_error
- end
-
- it 'overrides the method to return the unhealthy metric name' do
- expect(described_class.unhealthy_metric_name).to eq(metric_name)
- end
- end
-
describe '.minimum_interval' do
it 'returns 2 minutes' do
expect(described_class.minimum_interval).to eq(2.minutes.to_i)
@@ -189,11 +179,11 @@ RSpec.shared_examples 'it runs background migration jobs' do |tracking_database,
end
it 'increments the unhealthy counter' do
- counter = Gitlab::Metrics.counter(metric_name, 'msg')
+ counter = Gitlab::Metrics.counter(:background_migration_database_health_reschedules, 'msg')
expect(described_class).to receive(:perform_in)
- expect { worker.perform('Foo', [10, 20]) }.to change { counter.get }.by(1)
+ expect { worker.perform('Foo', [10, 20]) }.to change { counter.get(db_config_name: tracking_database) }.by(1)
end
context 'when lease_attempts is 0' do
diff --git a/spec/support/shared_examples/workers/project_export_shared_examples.rb b/spec/support/shared_examples/workers/project_export_shared_examples.rb
index a9bcc3f4f7c..175ef9bd012 100644
--- a/spec/support/shared_examples/workers/project_export_shared_examples.rb
+++ b/spec/support/shared_examples/workers/project_export_shared_examples.rb
@@ -53,6 +53,10 @@ RSpec.shared_examples 'export worker' do
it 'does not raise an exception when strategy is invalid' do
expect(::Projects::ImportExport::ExportService).not_to receive(:new)
+ expect_next_instance_of(ProjectExportJob) do |job|
+ expect(job).to receive(:finish)
+ end
+
expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.not_to raise_error
end
@@ -63,6 +67,18 @@ RSpec.shared_examples 'export worker' do
it 'does not raise error when user cannot be found' do
expect { subject.perform(non_existing_record_id, project.id, {}) }.not_to raise_error
end
+
+ it 'fails the export job status' do
+ expect_next_instance_of(::Projects::ImportExport::ExportService) do |service|
+ expect(service).to receive(:execute).and_raise(Gitlab::ImportExport::Error)
+ end
+
+ expect_next_instance_of(ProjectExportJob) do |job|
+ expect(job).to receive(:fail_op)
+ end
+
+ expect { subject.perform(user.id, project.id, {}) }.to raise_error(Gitlab::ImportExport::Error)
+ end
end
end
diff --git a/spec/support/stub_settings_source.rb b/spec/support/stub_settings_source.rb
new file mode 100644
index 00000000000..c0e4e468b90
--- /dev/null
+++ b/spec/support/stub_settings_source.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.around(:each, stub_settings_source: true) do |example|
+ original_instance = ::Settings.instance_variable_get(:@instance)
+
+ example.run
+
+ ::Settings.instance_variable_set(:@instance, original_instance)
+ end
+end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index c5e73aa3b45..e9aa8cbb991 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -4,7 +4,8 @@ require 'rake_helper'
RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { true }
- let(:backup_types) { %w{db repo uploads builds artifacts pages lfs terraform_state registry packages} }
+ let(:backup_tasks) { %w{db repo uploads builds artifacts pages lfs terraform_state registry packages} }
+ let(:backup_types) { %w{db repositories uploads builds artifacts pages lfs terraform_state registry packages} }
def tars_glob
Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
@@ -48,7 +49,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
def reenable_backup_sub_tasks
- backup_types.each do |subtask|
+ backup_tasks.each do |subtask|
Rake::Task["gitlab:backup:#{subtask}:create"].reenable
end
end
@@ -72,8 +73,11 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
allow(YAML).to receive(:load_file)
.and_return({ gitlab_version: gitlab_version })
expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
- backup_types.each do |subtask|
- expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive(:invoke)
+ expect_next_instance_of(::Backup::Manager) do |instance|
+ backup_types.each do |subtask|
+ expect(instance).to receive(:run_restore_task).with(subtask).ordered
+ end
+ expect(instance).not_to receive(:run_restore_task)
end
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
end
@@ -128,16 +132,14 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.and_return({ gitlab_version: Gitlab::VERSION })
expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:terraform_state:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:packages:restore']).to receive(:invoke)
+
+ expect_next_instance_of(::Backup::Manager) do |instance|
+ backup_types.each do |subtask|
+ expect(instance).to receive(:run_restore_task).with(subtask).ordered
+ end
+ expect(instance).not_to receive(:run_restore_task)
+ end
+
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
end
@@ -198,7 +200,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'specific backup tasks' do
it 'prints a progress message to stdout' do
- backup_types.each do |task|
+ backup_tasks.each do |task|
expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end
end
@@ -206,7 +208,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
it 'logs the progress to log file' do
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping database ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "[SKIPPED]")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ...")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
@@ -217,7 +219,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "done").exactly(9).times
- backup_types.each do |task|
+ backup_tasks.each do |task|
run_rake_task("gitlab:backup:#{task}:create")
end
end
@@ -344,9 +346,9 @@ 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_snippet_a = create(:project_snippet, :repository, project: project_a, author: project_a.owner)
+ project_snippet_a = create(:project_snippet, :repository, project: project_a, author: project_a.first_owner)
project_b = create(:project, :repository, repository_storage: second_storage_name)
- project_snippet_b = create(:project_snippet, :repository, project: project_b, author: project_b.owner)
+ project_snippet_b = create(:project_snippet, :repository, project: project_b, author: project_b.first_owner)
project_snippet_b.snippet_repository.update!(shard: project_b.project_repository.shard)
create(:wiki_page, container: project_a)
create(:design, :with_file, issue: create(:issue, project: project_a))
@@ -414,11 +416,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'has defaults' do
- expect_next_instance_of(::Backup::Repositories) do |instance|
- expect(instance).to receive(:dump)
- .with(max_concurrency: 1, max_storage_concurrency: 1)
- .and_call_original
- end
+ expect(::Backup::Repositories).to receive(:new)
+ .with(anything, strategy: anything, max_concurrency: 1, max_storage_concurrency: 1)
+ .and_call_original
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
end
@@ -432,11 +432,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
stub_env('GITLAB_BACKUP_MAX_CONCURRENCY', 5)
stub_env('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 2)
- expect_next_instance_of(::Backup::Repositories) do |instance|
- expect(instance).to receive(:dump)
- .with(max_concurrency: 5, max_storage_concurrency: 2)
- .and_call_original
- end
+ expect(::Backup::Repositories).to receive(:new)
+ .with(anything, strategy: anything, max_concurrency: 5, max_storage_concurrency: 2)
+ .and_call_original
expect(::Backup::GitalyBackup).to receive(:new).with(anything, max_parallelism: 5, storage_parallelism: 2).and_call_original
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
@@ -489,16 +487,12 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.to receive(:invoke).and_return(true)
expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke
- expect(Rake::Task['gitlab:backup:db:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:repo:restore']).not_to receive :invoke
- expect(Rake::Task['gitlab:backup:uploads:restore']).not_to receive :invoke
- expect(Rake::Task['gitlab:backup:builds:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:pages:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:terraform_state:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
- expect(Rake::Task['gitlab:backup:packages:restore']).to receive :invoke
+ expect_next_instance_of(::Backup::Manager) do |instance|
+ (backup_types - %w{repositories uploads}).each do |subtask|
+ expect(instance).to receive(:run_restore_task).with(subtask).ordered
+ end
+ expect(instance).not_to receive(:run_restore_task)
+ end
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
end
@@ -538,8 +532,11 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.to receive(:invoke).and_return(true)
expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke
- backup_types.each do |subtask|
- expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive :invoke
+ expect_next_instance_of(::Backup::Manager) do |instance|
+ backup_types.each do |subtask|
+ expect(instance).to receive(:run_restore_task).with(subtask).ordered
+ end
+ expect(instance).not_to receive(:run_restore_task)
end
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout_from_any_process
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 92c896b1ab0..c3fd8135ae0 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -20,6 +20,99 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
allow(Rake::Task['db:seed_fu']).to receive(:invoke).and_return(true)
end
+ describe 'mark_migration_complete' do
+ context 'with a single database' do
+ let(:main_model) { ActiveRecord::Base }
+
+ before do
+ skip_if_multiple_databases_are_setup
+ end
+
+ it 'marks the migration complete on the given database' do
+ expect(main_model.connection).to receive(:quote).and_call_original
+ expect(main_model.connection).to receive(:execute)
+ .with("INSERT INTO schema_migrations (version) VALUES ('123')")
+
+ run_rake_task('gitlab:db:mark_migration_complete', '[123]')
+ end
+ end
+
+ context 'with multiple databases' do
+ let(:main_model) { double(:model, connection: double(:connection)) }
+ let(:ci_model) { double(:model, connection: double(:connection)) }
+ let(:base_models) { { 'main' => main_model, 'ci' => ci_model } }
+
+ before do
+ skip_if_multiple_databases_not_setup
+
+ allow(Gitlab::Database).to receive(:database_base_models).and_return(base_models)
+ end
+
+ it 'marks the migration complete on each database' do
+ expect(main_model.connection).to receive(:quote).with('123').and_return("'123'")
+ expect(main_model.connection).to receive(:execute)
+ .with("INSERT INTO schema_migrations (version) VALUES ('123')")
+
+ expect(ci_model.connection).to receive(:quote).with('123').and_return("'123'")
+ expect(ci_model.connection).to receive(:execute)
+ .with("INSERT INTO schema_migrations (version) VALUES ('123')")
+
+ run_rake_task('gitlab:db:mark_migration_complete', '[123]')
+ end
+
+ context 'when the single database task is used' do
+ it 'marks the migration complete for the given database' do
+ expect(main_model.connection).to receive(:quote).with('123').and_return("'123'")
+ expect(main_model.connection).to receive(:execute)
+ .with("INSERT INTO schema_migrations (version) VALUES ('123')")
+
+ expect(ci_model.connection).not_to receive(:quote)
+ expect(ci_model.connection).not_to receive(:execute)
+
+ run_rake_task('gitlab:db:mark_migration_complete:main', '[123]')
+ end
+ end
+ end
+
+ context 'when the migration is already marked complete' do
+ let(:main_model) { double(:model, connection: double(:connection)) }
+ let(:base_models) { { 'main' => main_model } }
+
+ before do
+ allow(Gitlab::Database).to receive(:database_base_models).and_return(base_models)
+ end
+
+ it 'prints a warning message' do
+ allow(main_model.connection).to receive(:quote).with('123').and_return("'123'")
+
+ expect(main_model.connection).to receive(:execute)
+ .with("INSERT INTO schema_migrations (version) VALUES ('123')")
+ .and_raise(ActiveRecord::RecordNotUnique)
+
+ expect { run_rake_task('gitlab:db:mark_migration_complete', '[123]') }
+ .to output(/Migration version '123' is already marked complete on database main/).to_stdout
+ end
+ end
+
+ context 'when an invalid version is given' do
+ let(:main_model) { double(:model, connection: double(:connection)) }
+ let(:base_models) { { 'main' => main_model } }
+
+ before do
+ allow(Gitlab::Database).to receive(:database_base_models).and_return(base_models)
+ end
+
+ it 'prints an error and exits' do
+ expect(main_model).not_to receive(:quote)
+ expect(main_model.connection).not_to receive(:execute)
+
+ expect { run_rake_task('gitlab:db:mark_migration_complete', '[abc]') }
+ .to output(/Must give a version argument that is a non-zero integer/).to_stdout
+ .and raise_error(SystemExit) { |error| expect(error.status).to eq(1) }
+ end
+ end
+ end
+
describe 'configure' do
it 'invokes db:migrate when schema has already been loaded' do
allow(ActiveRecord::Base.connection).to receive(:tables).and_return(%w[table1 table2])
@@ -353,6 +446,44 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
end
+ describe 'gitlab:db:reset_as_non_superuser' do
+ let(:connection_pool) { instance_double(ActiveRecord::ConnectionAdapters::ConnectionPool ) }
+ let(:connection) { instance_double(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) }
+ let(:configurations) { double(ActiveRecord::DatabaseConfigurations) }
+ let(:configuration) { instance_double(ActiveRecord::DatabaseConfigurations::HashConfig) }
+ let(:config_hash) { { username: 'foo' } }
+
+ it 'migrate as nonsuperuser check with default username' do
+ allow(Rake::Task['db:drop']).to receive(:invoke)
+ allow(Rake::Task['db:create']).to receive(:invoke)
+ allow(ActiveRecord::Base).to receive(:configurations).and_return(configurations)
+ allow(configurations).to receive(:configs_for).and_return([configuration])
+ allow(configuration).to receive(:configuration_hash).and_return(config_hash)
+ allow(ActiveRecord::Base).to receive(:establish_connection).and_return(connection_pool)
+
+ expect(config_hash).to receive(:merge).with({ username: 'gitlab' })
+ expect(Gitlab::Database).to receive(:check_for_non_superuser)
+ expect(Rake::Task['db:migrate']).to receive(:invoke)
+
+ run_rake_task('gitlab:db:reset_as_non_superuser')
+ end
+
+ it 'migrate as nonsuperuser check with specified username' do
+ allow(Rake::Task['db:drop']).to receive(:invoke)
+ allow(Rake::Task['db:create']).to receive(:invoke)
+ allow(ActiveRecord::Base).to receive(:configurations).and_return(configurations)
+ allow(configurations).to receive(:configs_for).and_return([configuration])
+ allow(configuration).to receive(:configuration_hash).and_return(config_hash)
+ allow(ActiveRecord::Base).to receive(:establish_connection).and_return(connection_pool)
+
+ expect(config_hash).to receive(:merge).with({ username: 'foo' })
+ expect(Gitlab::Database).to receive(:check_for_non_superuser)
+ expect(Rake::Task['db:migrate']).to receive(:invoke)
+
+ run_rake_task('gitlab:db:reset_as_non_superuser', '[foo]')
+ end
+ end
+
def run_rake_task(task_name, arguments = '')
Rake::Task[task_name].reenable
Rake.application.invoke_task("#{task_name}#{arguments}")
diff --git a/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb b/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb
new file mode 100644
index 00000000000..edd56f1667f
--- /dev/null
+++ b/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:dependency_proxy namespace rake task', :silence_stdout do
+ before :all do
+ Rake.application.rake_require 'tasks/gitlab/dependency_proxy/migrate'
+ end
+
+ describe 'migrate' do
+ let(:local) { ObjectStorage::Store::LOCAL }
+ let(:remote) { ObjectStorage::Store::REMOTE }
+ let!(:blob) { create(:dependency_proxy_blob) }
+ let!(:manifest) { create(:dependency_proxy_manifest) }
+
+ def dependency_proxy_migrate
+ run_rake_task('gitlab:dependency_proxy:migrate')
+ end
+
+ context 'object storage disabled' do
+ before do
+ stub_dependency_proxy_object_storage(enabled: false)
+ end
+
+ it "doesn't migrate files" do
+ expect { dependency_proxy_migrate }.to raise_error('Object store is disabled for dependency proxy feature')
+ end
+ end
+
+ context 'object storage enabled' do
+ before do
+ stub_dependency_proxy_object_storage
+ end
+
+ it 'migrates local file to object storage' do
+ expect { dependency_proxy_migrate }.to change { blob.reload.file_store }.from(local).to(remote)
+ .and change { manifest.reload.file_store }.from(local).to(remote)
+ end
+ end
+
+ context 'an error is raised while migrating' do
+ let(:blob_error) { 'Failed to transfer dependency proxy blob file' }
+ let(:manifest_error) { 'Failed to transfer dependency proxy manifest file' }
+ let!(:blob_non_existent) { create(:dependency_proxy_blob) }
+ let!(:manifest_non_existent) { create(:dependency_proxy_manifest) }
+
+ before do
+ stub_dependency_proxy_object_storage
+ blob_non_existent.file.file.delete
+ manifest_non_existent.file.file.delete
+ end
+
+ it 'fails to migrate a local file that does not exist' do
+ expect { dependency_proxy_migrate }.to output(include(blob_error, manifest_error)).to_stdout
+ end
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/info_rake_spec.rb b/spec/tasks/gitlab/info_rake_spec.rb
deleted file mode 100644
index 19ed43723e2..00000000000
--- a/spec/tasks/gitlab/info_rake_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'rake_helper'
-
-RSpec.describe 'gitlab:env:info', :silence_stdout do
- before do
- Rake.application.rake_require 'tasks/gitlab/info'
-
- stub_warn_user_is_not_gitlab
- allow(Gitlab::Popen).to receive(:popen)
- end
-
- describe 'git version' do
- before do
- allow(Gitlab::Popen).to receive(:popen).with([Gitlab.config.git.bin_path, '--version'])
- .and_return(git_version)
- end
-
- context 'when git installed' do
- let(:git_version) { 'git version 2.10.0' }
-
- it 'prints git version' do
- run_rake_task('gitlab:env:info')
-
- expect($stdout.string).to match(/Git Version:(.*)2.10.0/)
- end
- end
-
- context 'when git not installed' do
- let(:git_version) { '' }
-
- it 'prints unknown' do
- run_rake_task('gitlab:env:info')
-
- expect($stdout.string).to match(/Git Version:(.*)unknown/)
- end
- end
- end
-end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index 52aa90beb2b..1b416286f8e 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -209,6 +209,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'lib/api/entities/project_integration.rb' | [:integrations_be, :backend]
'lib/gitlab/hook_data/note_builder.rb' | [:integrations_be, :backend]
'lib/gitlab/data_builder/note.rb' | [:integrations_be, :backend]
+ 'lib/gitlab/web_hooks/recursion_detection.rb' | [:integrations_be, :backend]
'ee/lib/ee/gitlab/integrations/sti_type.rb' | [:integrations_be, :backend]
'ee/lib/ee/api/helpers/integrations_helpers.rb' | [:integrations_be, :backend]
'ee/app/serializers/integrations/jira_serializers/issue_entity.rb' | [:integrations_be, :backend]
diff --git a/spec/tooling/docs/deprecation_handling_spec.rb b/spec/tooling/docs/deprecation_handling_spec.rb
index e389fe882b2..e43f5c7147b 100644
--- a/spec/tooling/docs/deprecation_handling_spec.rb
+++ b/spec/tooling/docs/deprecation_handling_spec.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
-require_relative '../../fast_spec_helper'
+require 'spec_helper'
+
require_relative '../../../tooling/docs/deprecation_handling'
-require_relative '../../support/helpers/next_instance_of'
RSpec.describe Docs::DeprecationHandling do
- include ::NextInstanceOf
-
let(:type) { 'deprecation' }
subject { described_class.new(type).render }
diff --git a/spec/tooling/lib/tooling/test_map_generator_spec.rb b/spec/tooling/lib/tooling/test_map_generator_spec.rb
index eb49b1db20e..b52d78b01a3 100644
--- a/spec/tooling/lib/tooling/test_map_generator_spec.rb
+++ b/spec/tooling/lib/tooling/test_map_generator_spec.rb
@@ -39,11 +39,23 @@ RSpec.describe Tooling::TestMapGenerator do
YAML
end
+ let(:yaml3) do
+ <<~YAML
+ ---
+ :type: Crystalball::ExecutionMap
+ :commit: 74056e8d9cf3773f43faa1cf5416f8779c8284c9
+ :timestamp: 1602671965
+ :version:
+ ---
+ YAML
+ end
+
let(:pathname) { instance_double(Pathname) }
before do
stub_file_read('yaml1.yml', content: yaml1)
stub_file_read('yaml2.yml', content: yaml2)
+ stub_file_read('yaml3.yml', content: yaml3)
end
context 'with single yaml' do
@@ -74,6 +86,10 @@ RSpec.describe Tooling::TestMapGenerator do
expect(subject.mapping[file]).to match_array(tests)
end
end
+
+ it 'displays a warning when report has no examples' do
+ expect { subject.parse('yaml3.yml') }.to output(%|No examples in yaml3.yml! Metadata: {:type=>"Crystalball::ExecutionMap", :commit=>"74056e8d9cf3773f43faa1cf5416f8779c8284c9", :timestamp=>1602671965, :version=>nil}\n|).to_stdout
+ end
end
context 'with multiple yamls' do
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
index 8a944a473d7..33d3a5b49b3 100644
--- a/spec/tooling/quality/test_level_spec.rb
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
- .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,metrics_server,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,sidekiq_cluster,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
+ .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,events,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,metrics_server,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,sidekiq_cluster,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
end
end
@@ -110,7 +110,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
- .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|metrics_server|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|sidekiq_cluster|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
+ .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|events|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|metrics_server|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|sidekiq_cluster|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
end
end
diff --git a/spec/tooling/rspec_flaky/config_spec.rb b/spec/tooling/rspec_flaky/config_spec.rb
index 12b5ed74cb2..c95e5475d66 100644
--- a/spec/tooling/rspec_flaky/config_spec.rb
+++ b/spec/tooling/rspec_flaky/config_spec.rb
@@ -11,9 +11,10 @@ RSpec.describe RspecFlaky::Config, :aggregate_failures do
before do
# Stub these env variables otherwise specs don't behave the same on the CI
stub_env('FLAKY_RSPEC_GENERATE_REPORT', nil)
- stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', nil)
+ stub_env('FLAKY_RSPEC_SUITE_REPORT_PATH', nil)
stub_env('FLAKY_RSPEC_REPORT_PATH', nil)
stub_env('NEW_FLAKY_RSPEC_REPORT_PATH', nil)
+ stub_env('SKIPPED_FLAKY_TESTS_REPORT_PATH', nil)
# Ensure the behavior is the same locally and on CI (where Rails is defined since we run this test as part of the whole suite), i.e. Rails isn't defined
allow(described_class).to receive(:rails_path).and_wrap_original do |method, path|
path
@@ -51,15 +52,15 @@ RSpec.describe RspecFlaky::Config, :aggregate_failures do
end
describe '.suite_flaky_examples_report_path' do
- context "when ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'] is not set" do
+ context "when ENV['FLAKY_RSPEC_SUITE_REPORT_PATH'] is not set" do
it 'returns the default path' do
- expect(described_class.suite_flaky_examples_report_path).to eq('rspec_flaky/suite-report.json')
+ expect(described_class.suite_flaky_examples_report_path).to eq('rspec/flaky/suite-report.json')
end
end
- context "when ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'] is set" do
+ context "when ENV['FLAKY_RSPEC_SUITE_REPORT_PATH'] is set" do
before do
- stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', 'foo/suite-report.json')
+ stub_env('FLAKY_RSPEC_SUITE_REPORT_PATH', 'foo/suite-report.json')
end
it 'returns the value of the env variable' do
@@ -71,7 +72,7 @@ RSpec.describe RspecFlaky::Config, :aggregate_failures do
describe '.flaky_examples_report_path' do
context "when ENV['FLAKY_RSPEC_REPORT_PATH'] is not set" do
it 'returns the default path' do
- expect(described_class.flaky_examples_report_path).to eq('rspec_flaky/report.json')
+ expect(described_class.flaky_examples_report_path).to eq('rspec/flaky/report.json')
end
end
@@ -89,7 +90,7 @@ RSpec.describe RspecFlaky::Config, :aggregate_failures do
describe '.new_flaky_examples_report_path' do
context "when ENV['NEW_FLAKY_RSPEC_REPORT_PATH'] is not set" do
it 'returns the default path' do
- expect(described_class.new_flaky_examples_report_path).to eq('rspec_flaky/new-report.json')
+ expect(described_class.new_flaky_examples_report_path).to eq('rspec/flaky/new-report.json')
end
end
@@ -103,4 +104,22 @@ RSpec.describe RspecFlaky::Config, :aggregate_failures do
end
end
end
+
+ describe '.skipped_flaky_tests_report_path' do
+ context "when ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH'] is not set" do
+ it 'returns the default path' do
+ expect(described_class.skipped_flaky_tests_report_path).to eq('rspec/flaky/skipped_flaky_tests_report.txt')
+ end
+ end
+
+ context "when ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH'] is set" do
+ before do
+ stub_env('SKIPPED_FLAKY_TESTS_REPORT_PATH', 'foo/skipped_flaky_tests_report.txt')
+ end
+
+ it 'returns the value of the env variable' do
+ expect(described_class.skipped_flaky_tests_report_path).to eq('foo/skipped_flaky_tests_report.txt')
+ end
+ end
+ end
end
diff --git a/spec/tooling/rspec_flaky/listener_spec.rb b/spec/tooling/rspec_flaky/listener_spec.rb
index 51a815dafbf..62bbe53cac1 100644
--- a/spec/tooling/rspec_flaky/listener_spec.rb
+++ b/spec/tooling/rspec_flaky/listener_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe RspecFlaky::Listener, :aggregate_failures do
before do
# Stub these env variables otherwise specs don't behave the same on the CI
stub_env('CI_JOB_URL', nil)
- stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', nil)
+ stub_env('FLAKY_RSPEC_SUITE_REPORT_PATH', nil)
end
describe '#initialize' do
@@ -73,11 +73,11 @@ RSpec.describe RspecFlaky::Listener, :aggregate_failures do
it_behaves_like 'a valid Listener instance'
end
- context 'when SUITE_FLAKY_RSPEC_REPORT_PATH is set' do
+ context 'when FLAKY_RSPEC_SUITE_REPORT_PATH is set' do
let(:report_file_path) { 'foo/report.json' }
before do
- stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', report_file_path)
+ stub_env('FLAKY_RSPEC_SUITE_REPORT_PATH', report_file_path)
end
context 'and report file exists' do
diff --git a/spec/uploaders/import_export_uploader_spec.rb b/spec/uploaders/import_export_uploader_spec.rb
index cb7a89193e6..64e92f5d60e 100644
--- a/spec/uploaders/import_export_uploader_spec.rb
+++ b/spec/uploaders/import_export_uploader_spec.rb
@@ -10,6 +10,20 @@ RSpec.describe ImportExportUploader do
subject { described_class.new(model, :import_file) }
context 'local store' do
+ describe '#move_to_cache' do
+ it 'returns false' do
+ expect(subject.move_to_cache).to be false
+ end
+
+ context 'with project export' do
+ subject { described_class.new(model, :export_file) }
+
+ it 'returns true' do
+ expect(subject.move_to_cache).to be true
+ end
+ end
+ end
+
describe '#move_to_store' do
it 'returns true' do
expect(subject.move_to_store).to be true
@@ -33,6 +47,20 @@ RSpec.describe ImportExportUploader do
let(:fixture) { File.join('spec', 'fixtures', 'group_export.tar.gz') }
end
+ describe '#move_to_cache' do
+ it 'returns false' do
+ expect(subject.move_to_cache).to be false
+ end
+
+ context 'with project export' do
+ subject { described_class.new(model, :export_file) }
+
+ it 'returns true' do
+ expect(subject.move_to_cache).to be false
+ end
+ end
+ end
+
describe '#move_to_store' do
it 'returns false' do
expect(subject.move_to_store).to be false
diff --git a/spec/validators/x509_certificate_credentials_validator_spec.rb b/spec/validators/x509_certificate_credentials_validator_spec.rb
index 9076aee7681..5da1813e379 100644
--- a/spec/validators/x509_certificate_credentials_validator_spec.rb
+++ b/spec/validators/x509_certificate_credentials_validator_spec.rb
@@ -55,6 +55,14 @@ RSpec.describe X509CertificateCredentialsValidator do
expect(record.errors[:private_key]).to include('could not read private key, is the passphrase correct?')
end
+ it 'adds an error when private key does not match certificate' do
+ record.private_key = SSHData::PrivateKey::RSA.generate(4096).openssl.to_pem
+
+ validator.validate(record)
+
+ expect(record.errors[:private_key]).to include('private key does not match certificate.')
+ end
+
it 'has no error when the private key is correct' do
record.private_key = pkey_data
@@ -85,7 +93,7 @@ RSpec.describe X509CertificateCredentialsValidator do
validator.validate(record)
- expect(record.errors[:private_key]).not_to be_empty
+ expect(record.errors[:private_key]).to include('could not read private key, is the passphrase correct?')
end
end
end
diff --git a/spec/views/admin/application_settings/general.html.haml_spec.rb b/spec/views/admin/application_settings/general.html.haml_spec.rb
index 434ca8bf0e7..7d28175d134 100644
--- a/spec/views/admin/application_settings/general.html.haml_spec.rb
+++ b/spec/views/admin/application_settings/general.html.haml_spec.rb
@@ -33,4 +33,31 @@ RSpec.describe 'admin/application_settings/general.html.haml' do
end
end
end
+
+ describe 'prompt user about registration features' do
+ before do
+ assign(:application_setting, app_settings)
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ context 'when service ping is enabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ it_behaves_like 'does not render registration features prompt', :application_setting_disabled_repository_size_limit
+ end
+
+ context 'with no license and service ping disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+
+ if Gitlab.ee?
+ allow(License).to receive(:current).and_return(nil)
+ end
+ end
+
+ it_behaves_like 'renders registration features prompt', :application_setting_disabled_repository_size_limit
+ end
+ end
end
diff --git a/spec/views/admin/dashboard/index.html.haml_spec.rb b/spec/views/admin/dashboard/index.html.haml_spec.rb
index 9db2bd3741a..9f1ff960444 100644
--- a/spec/views/admin/dashboard/index.html.haml_spec.rb
+++ b/spec/views/admin/dashboard/index.html.haml_spec.rb
@@ -63,4 +63,33 @@ RSpec.describe 'admin/dashboard/index.html.haml' do
expect(rendered).to have_selector('.js-gitlab-version-check')
end
end
+
+ describe 'GitLab KAS' do
+ before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(enabled)
+ allow(Gitlab::Kas).to receive(:version).and_return('kas-1.2.3')
+ end
+
+ context 'KAS enabled' do
+ let(:enabled) { true }
+
+ it 'includes KAS version' do
+ render
+
+ expect(rendered).to have_content('GitLab KAS')
+ expect(rendered).to have_content('kas-1.2.3')
+ end
+ end
+
+ context 'KAS disabled' do
+ let(:enabled) { false }
+
+ it 'does not include KAS version' do
+ render
+
+ expect(rendered).not_to have_content('GitLab KAS')
+ expect(rendered).not_to have_content('kas-1.2.3')
+ end
+ 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 6efb2730964..37dbfd39f2d 100644
--- a/spec/views/devise/shared/_signup_box.html.haml_spec.rb
+++ b/spec/views/devise/shared/_signup_box.html.haml_spec.rb
@@ -63,6 +63,22 @@ RSpec.describe 'devise/shared/_signup_box' do
end
end
+ context 'using the borderless option' do
+ let(:border_css_classes) { '.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base' }
+
+ it 'renders with a border by default' do
+ render
+
+ expect(rendered).to have_selector(border_css_classes)
+ end
+
+ it 'renders without a border when borderless is truthy' do
+ render('devise/shared/signup_box', borderless: true)
+
+ expect(rendered).not_to have_selector(border_css_classes)
+ end
+ end
+
def stub_devise
allow(view).to receive(:devise_mapping).and_return(Devise.mappings[:user])
allow(view).to receive(:resource).and_return(spy)
diff --git a/spec/views/groups/settings/_transfer.html.haml_spec.rb b/spec/views/groups/settings/_transfer.html.haml_spec.rb
deleted file mode 100644
index 911eb5b7ab3..00000000000
--- a/spec/views/groups/settings/_transfer.html.haml_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'groups/settings/_transfer.html.haml' do
- describe 'render' do
- it 'enables the Select parent group dropdown and does not show an alert for a group' do
- group = build(:group)
-
- render 'groups/settings/transfer', group: group
-
- expect(rendered).to have_button 'Select parent group'
- expect(rendered).not_to have_button 'Select parent group', disabled: true
- expect(rendered).not_to have_text "This group can't be transfered because it is linked to a subscription."
- end
- end
-end
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 f7da288b9f3..22e925e22ae 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'layouts/nav/sidebar/_project' do
let_it_be_with_reload(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
let(:current_ref) { 'master' }
before do
@@ -286,10 +286,20 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
describe 'Pipeline Editor' do
- it 'has a link to the pipeline editor' do
- render
+ context 'with a current_ref' do
+ it 'has a link to the pipeline editor' do
+ render
+
+ expect(rendered).to have_link('Editor', href: project_ci_pipeline_editor_path(project, params: { branch_name: current_ref }))
+ end
+ end
+
+ context 'with the default_branch' do
+ it 'has a link to the pipeline editor' do
+ render
- expect(rendered).to have_link('Editor', href: project_ci_pipeline_editor_path(project))
+ expect(rendered).to have_link('Editor', href: project_ci_pipeline_editor_path(project, params: { branch_name: project.default_branch }))
+ end
end
context 'when user cannot access pipeline editor' do
diff --git a/spec/views/profiles/keys/_key.html.haml_spec.rb b/spec/views/profiles/keys/_key.html.haml_spec.rb
index bb101198ac3..ed8026d2453 100644
--- a/spec/views/profiles/keys/_key.html.haml_spec.rb
+++ b/spec/views/profiles/keys/_key.html.haml_spec.rb
@@ -90,8 +90,8 @@ RSpec.describe 'profiles/keys/_key.html.haml' do
using RSpec::Parameterized::TableSyntax
where(:valid, :expiry, :result) do
- false | 2.days.from_now | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
- false | 2.days.ago | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
+ false | 2.days.from_now | 'Key type is forbidden. Must be DSA, ECDSA, ED25519, ECDSA_SK, or ED25519_SK'
+ false | 2.days.ago | 'Key type is forbidden. Must be DSA, ECDSA, ED25519, ECDSA_SK, or ED25519_SK'
true | 2.days.ago | 'Key usable beyond expiration date.'
true | 2.days.from_now | ''
end
diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb
index 11f542767f4..a85ddf7a005 100644
--- a/spec/views/projects/edit.html.haml_spec.rb
+++ b/spec/views/projects/edit.html.haml_spec.rb
@@ -45,10 +45,10 @@ RSpec.describe 'projects/edit' do
end
context 'merge commit template' do
- it 'displays a placeholder if none is set' do
+ it 'displays default template if none is set' do
render
- expect(rendered).to have_field('project[merge_commit_template]', placeholder: <<~MSG.rstrip)
+ expect(rendered).to have_field('project[merge_commit_template_or_default]', with: <<~MSG.rstrip)
Merge branch '%{source_branch}' into '%{target_branch}'
%{title}
@@ -64,15 +64,15 @@ RSpec.describe 'projects/edit' do
render
- expect(rendered).to have_field('project[merge_commit_template]', with: '%{title}')
+ expect(rendered).to have_field('project[merge_commit_template_or_default]', with: '%{title}')
end
end
context 'squash template' do
- it 'displays a placeholder if none is set' do
+ it 'displays default template if none is set' do
render
- expect(rendered).to have_field('project[squash_commit_template]', placeholder: '%{title}')
+ expect(rendered).to have_field('project[squash_commit_template_or_default]', with: '%{title}')
end
it 'displays the user entered value' do
@@ -80,7 +80,7 @@ RSpec.describe 'projects/edit' do
render
- expect(rendered).to have_field('project[squash_commit_template]', with: '%{first_multiline_commit}')
+ expect(rendered).to have_field('project[squash_commit_template_or_default]', with: '%{first_multiline_commit}')
end
end
@@ -139,4 +139,26 @@ RSpec.describe 'projects/edit' do
end
end
end
+
+ describe 'prompt user about registration features' do
+ context 'when service ping is enabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ it_behaves_like 'does not render registration features prompt', :project_disabled_repository_size_limit
+ end
+
+ context 'with no license and service ping disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+
+ if Gitlab.ee?
+ allow(License).to receive(:current).and_return(nil)
+ end
+ end
+
+ it_behaves_like 'renders registration features prompt', :project_disabled_repository_size_limit
+ end
+ end
end
diff --git a/spec/views/projects/services/_form.haml_spec.rb b/spec/views/projects/services/_form.haml_spec.rb
deleted file mode 100644
index f212fd78b1a..00000000000
--- a/spec/views/projects/services/_form.haml_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'projects/services/_form' do
- let(:project) { create(:redmine_project) }
- let(:user) { create(:admin) }
-
- before do
- assign(:project, project)
-
- 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,
- integration: project.redmine_integration,
- request: double(referer: '/services')
- )
- end
-
- context 'integrations form' do
- it 'does not render form element' do
- render
-
- expect(rendered).not_to have_selector('[data-testid="integration-form"]')
- end
-
- context 'when vue_integration_form feature flag is disabled' do
- before do
- stub_feature_flags(vue_integration_form: false)
- end
-
- it 'renders form element' do
- render
-
- expect(rendered).to have_selector('[data-testid="integration-form"]')
- end
-
- context 'commit_events and merge_request_events' do
- it 'display merge_request_events and commit_events descriptions' do
- allow(Integrations::Redmine).to receive(:supported_events).and_return(%w(commit merge_request))
-
- render
-
- expect(rendered).to have_css("input[name='redirect_to'][value='/services']", count: 1, visible: false)
- end
- end
- end
- end
-end
diff --git a/spec/views/shared/_gl_toggle.haml_spec.rb b/spec/views/shared/_gl_toggle.haml_spec.rb
new file mode 100644
index 00000000000..3ac1ef30c84
--- /dev/null
+++ b/spec/views/shared/_gl_toggle.haml_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'shared/_gl_toggle.html.haml' do
+ context 'defaults' do
+ before do
+ render partial: 'shared/gl_toggle', locals: {
+ classes: '.js-gl-toggle'
+ }
+ end
+
+ it 'does not set a name' do
+ expect(rendered).not_to have_selector('[data-name]')
+ end
+
+ it 'sets default is-checked attributes' do
+ expect(rendered).to have_selector('[data-is-checked="false"]')
+ end
+
+ it 'sets default disabled attributes' do
+ expect(rendered).to have_selector('[data-disabled="false"]')
+ end
+
+ it 'sets default is-loading attributes' do
+ expect(rendered).to have_selector('[data-is-loading="false"]')
+ end
+
+ it 'does not set a label' do
+ expect(rendered).not_to have_selector('[data-label]')
+ end
+
+ it 'does not set a label position' do
+ expect(rendered).not_to have_selector('[data-label-position]')
+ end
+ end
+
+ context 'with custom options' do
+ before do
+ render partial: 'shared/gl_toggle', locals: {
+ classes: 'js-custom-gl-toggle',
+ name: 'toggle-name',
+ is_checked: true,
+ disabled: true,
+ is_loading: true,
+ label: 'Custom label',
+ label_position: 'top',
+ data: {
+ foo: 'bar'
+ }
+ }
+ end
+
+ it 'sets the custom class' do
+ expect(rendered).to have_selector('.js-custom-gl-toggle')
+ end
+
+ it 'sets the custom name' do
+ expect(rendered).to have_selector('[data-name="toggle-name"]')
+ end
+
+ it 'sets the custom is-checked attributes' do
+ expect(rendered).to have_selector('[data-is-checked="true"]')
+ end
+
+ it 'sets the custom disabled attributes' do
+ expect(rendered).to have_selector('[data-disabled="true"]')
+ end
+
+ it 'sets the custom is-loading attributes' do
+ expect(rendered).to have_selector('[data-is-loading="true"]')
+ end
+
+ it 'sets the custom label' do
+ expect(rendered).to have_selector('[data-label="Custom label"]')
+ end
+
+ it 'sets the cutom label position' do
+ expect(rendered).to have_selector('[data-label-position="top"]')
+ end
+
+ it 'sets cutom data attributes' do
+ expect(rendered).to have_selector('[data-foo="bar"]')
+ end
+ end
+end
diff --git a/spec/views/shared/_global_alert.html.haml_spec.rb b/spec/views/shared/_global_alert.html.haml_spec.rb
index 7eec068645a..84198cbb75e 100644
--- a/spec/views/shared/_global_alert.html.haml_spec.rb
+++ b/spec/views/shared/_global_alert.html.haml_spec.rb
@@ -49,12 +49,6 @@ RSpec.describe 'shared/_global_alert.html.haml' do
allow(view).to receive(:fluid_layout).and_return(false)
end
- it 'does not add layout limited class' do
- render
-
- expect(rendered).not_to have_selector('.gl-alert-layout-limited')
- end
-
it 'adds container classes' do
render
@@ -74,10 +68,6 @@ RSpec.describe 'shared/_global_alert.html.haml' do
render
end
- it 'adds layout limited class' do
- expect(rendered).to have_selector('.gl-alert-layout-limited')
- end
-
it 'does not add container classes' do
expect(rendered).not_to have_selector('.container-fluid.container-limited')
end
diff --git a/spec/views/shared/issuable/_sidebar.html.haml_spec.rb b/spec/views/shared/issuable/_sidebar.html.haml_spec.rb
new file mode 100644
index 00000000000..2097b8890cc
--- /dev/null
+++ b/spec/views/shared/issuable/_sidebar.html.haml_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'shared/issuable/_sidebar.html.haml' do
+ let_it_be(:user) { create(:user) }
+
+ subject(:rendered) do
+ render 'shared/issuable/sidebar', issuable_sidebar: IssueSerializer.new(current_user: user)
+ .represent(issuable, serializer: 'sidebar'), assignees: []
+ end
+
+ context 'project in a group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:incident) { create(:incident, project: project) }
+
+ before do
+ assign(:project, project)
+ end
+
+ context 'issuable that does not support escalations' do
+ let(:issuable) { incident }
+
+ it 'shows escalation policy dropdown' do
+ expect(rendered).to have_css('[data-testid="escalation_status_container"]')
+ end
+ end
+
+ context 'issuable that supports escalations' do
+ let(:issuable) { issue }
+
+ it 'does not show escalation policy dropdown' do
+ expect(rendered).not_to have_css('[data-testid="escalation_status_container"]')
+ end
+ end
+ end
+end
diff --git a/spec/workers/auto_devops/disable_worker_spec.rb b/spec/workers/auto_devops/disable_worker_spec.rb
index 239f4b09f5c..e1de97e0ce5 100644
--- a/spec/workers/auto_devops/disable_worker_spec.rb
+++ b/spec/workers/auto_devops/disable_worker_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe AutoDevops::DisableWorker, '#perform' do
let(:namespace) { create(:namespace, owner: owner) }
let(:project) { create(:project, :repository, :auto_devops, namespace: namespace) }
- it 'sends an email to pipeline user and project owner' do
+ it 'sends an email to pipeline user and project owner(s)' do
expect(NotificationService).to receive_message_chain(:new, :autodevops_disabled).with(pipeline, [user.email, owner.email])
subject.perform(pipeline.id)
diff --git a/spec/workers/background_migration/ci_database_worker_spec.rb b/spec/workers/background_migration/ci_database_worker_spec.rb
new file mode 100644
index 00000000000..82c562c4042
--- /dev/null
+++ b/spec/workers/background_migration/ci_database_worker_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BackgroundMigration::CiDatabaseWorker, :clean_gitlab_redis_shared_state, if: Gitlab::Database.has_config?(:ci) do
+ it_behaves_like 'it runs background migration jobs', 'ci'
+end
diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb
index 4297e55ca6c..1558c3c9250 100644
--- a/spec/workers/background_migration_worker_spec.rb
+++ b/spec/workers/background_migration_worker_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe BackgroundMigrationWorker, :clean_gitlab_redis_shared_state do
- it_behaves_like 'it runs background migration jobs', 'main', :background_migration_database_health_reschedules
+ it_behaves_like 'it runs background migration jobs', 'main'
end
diff --git a/spec/workers/ci/delete_objects_worker_spec.rb b/spec/workers/ci/delete_objects_worker_spec.rb
index 52d90d7667a..3d985dffdc5 100644
--- a/spec/workers/ci/delete_objects_worker_spec.rb
+++ b/spec/workers/ci/delete_objects_worker_spec.rb
@@ -6,15 +6,16 @@ RSpec.describe Ci::DeleteObjectsWorker do
let(:worker) { described_class.new }
it { expect(described_class.idempotent?).to be_truthy }
+ it { is_expected.to respond_to(:max_running_jobs) }
+ it { is_expected.to respond_to(:remaining_work_count) }
+ it { is_expected.to respond_to(:perform_work) }
describe '#perform' do
it 'executes a service' do
- allow(worker).to receive(:max_running_jobs).and_return(25)
-
expect_next_instance_of(Ci::DeleteObjectsService) do |instance|
expect(instance).to receive(:execute)
expect(instance).to receive(:remaining_batches_count)
- .with(max_batch_count: 25)
+ .with(max_batch_count: 20)
.once
.and_call_original
end
@@ -22,30 +23,4 @@ RSpec.describe Ci::DeleteObjectsWorker do
worker.perform
end
end
-
- describe '#max_running_jobs' do
- using RSpec::Parameterized::TableSyntax
-
- before do
- stub_feature_flags(
- ci_delete_objects_medium_concurrency: medium,
- ci_delete_objects_high_concurrency: high
- )
- end
-
- subject(:max_running_jobs) { worker.max_running_jobs }
-
- where(:medium, :high, :expected) do
- false | false | 2
- true | false | 20
- true | true | 20
- false | true | 50
- end
-
- with_them do
- it 'sets up concurrency depending on the feature flag' do
- expect(max_running_jobs).to eq(expected)
- end
- end
- end
end
diff --git a/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb b/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb
index 116a0e4d035..a637ac088ff 100644
--- a/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb
+++ b/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::ExternalPullRequests::CreatePipelineWorker do
let_it_be(:project) { create(:project, :auto_devops, :repository) }
- let_it_be(:user) { project.owner }
+ let_it_be(:user) { project.first_owner }
let_it_be(:external_pull_request) do
branch = project.repository.branches.last
create(:external_pull_request, project: project, source_branch: branch.name, source_sha: branch.target)
diff --git a/spec/workers/cleanup_container_repository_worker_spec.rb b/spec/workers/cleanup_container_repository_worker_spec.rb
index 6ae4308bd46..6723ea2049d 100644
--- a/spec/workers/cleanup_container_repository_worker_spec.rb
+++ b/spec/workers/cleanup_container_repository_worker_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe CleanupContainerRepositoryWorker, :clean_gitlab_redis_shared_state do
let(:repository) { create(:container_repository) }
let(:project) { repository.project }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
subject { described_class.new }
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index 85731de2a45..95d9b982fc4 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -247,45 +247,6 @@ RSpec.describe ApplicationWorker do
end
end
- describe '.perform_async' do
- using RSpec::Parameterized::TableSyntax
-
- where(:primary_only?, :skip_scheduling_ff, :data_consistency, :schedules_job?) do
- true | false | :sticky | false
- true | false | :delayed | false
- true | false | :always | false
- true | true | :sticky | false
- true | true | :delayed | false
- true | true | :always | false
- false | false | :sticky | true
- false | false | :delayed | true
- false | false | :always | false
- false | true | :sticky | false
- false | true | :delayed | false
- false | true | :always | false
- end
-
- before do
- stub_const(worker.name, worker)
- worker.data_consistency(data_consistency)
-
- allow(Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(primary_only?)
- stub_feature_flags(skip_scheduling_workers_for_replicas: skip_scheduling_ff)
- end
-
- with_them do
- it 'schedules or enqueues the job correctly' do
- if schedules_job?
- expect(worker).to receive(:perform_in).with(described_class::DEFAULT_DELAY_INTERVAL.seconds, 123)
- else
- expect(worker).not_to receive(:perform_in)
- end
-
- worker.perform_async(123)
- end
- end
- end
-
context 'different kinds of push_bulk' do
shared_context 'set safe limit beyond the number of jobs to be enqueued' do
before do
diff --git a/spec/workers/container_expiration_policy_worker_spec.rb b/spec/workers/container_expiration_policy_worker_spec.rb
index ebf80041151..2cfb613865d 100644
--- a/spec/workers/container_expiration_policy_worker_spec.rb
+++ b/spec/workers/container_expiration_policy_worker_spec.rb
@@ -60,12 +60,11 @@ RSpec.describe ContainerExpirationPolicyWorker do
context 'with container expiration policies' do
let_it_be(:container_expiration_policy, reload: true) { create(:container_expiration_policy, :runnable) }
let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) }
- let_it_be(:user) { container_expiration_policy.project.owner }
context 'a valid policy' do
it 'runs the policy' do
expect(ContainerExpirationPolicyService)
- .to receive(:new).with(container_expiration_policy.project, user).and_call_original
+ .to receive(:new).with(container_expiration_policy.project, nil).and_call_original
expect(CleanupContainerRepositoryWorker).to receive(:perform_async).once.and_call_original
expect { subject }.not_to raise_error
@@ -102,7 +101,7 @@ RSpec.describe ContainerExpirationPolicyWorker do
end
it 'disables the policy and tracks an error' do
- expect(ContainerExpirationPolicyService).not_to receive(:new).with(container_expiration_policy, user)
+ expect(ContainerExpirationPolicyService).not_to receive(:new).with(container_expiration_policy, nil)
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)
diff --git a/spec/workers/container_registry/migration/enqueuer_worker_spec.rb b/spec/workers/container_registry/migration/enqueuer_worker_spec.rb
new file mode 100644
index 00000000000..12c14c35365
--- /dev/null
+++ b/spec/workers/container_registry/migration/enqueuer_worker_spec.rb
@@ -0,0 +1,178 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures do
+ let_it_be_with_reload(:container_repository) { create(:container_repository, created_at: 2.days.ago) }
+
+ let(:worker) { described_class.new }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_application_setting(container_registry_import_created_before: 1.day.ago)
+ stub_container_registry_tags(repository: container_repository.path, tags: %w(tag1 tag2 tag3), with_manifest: true)
+ end
+
+ describe '#perform' do
+ subject { worker.perform }
+
+ shared_examples 'no action' do
+ it 'does not queue or change any repositories' do
+ subject
+
+ expect(container_repository.reload).to be_default
+ end
+ end
+
+ shared_examples 're-enqueuing based on capacity' do
+ context 'below capacity' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(9999)
+ end
+
+ it 're-enqueues the worker' do
+ expect(ContainerRegistry::Migration::EnqueuerWorker).to receive(:perform_async)
+
+ subject
+ end
+ end
+
+ context 'above capacity' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(-1)
+ end
+
+ it 'does not re-enqueue the worker' do
+ expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_async)
+
+ subject
+ end
+ end
+ end
+
+ context 'with qualified repository' do
+ it 'starts the pre-import for the next qualified repository' do
+ method = worker.method(:next_repository)
+ allow(worker).to receive(:next_repository) do
+ next_qualified_repository = method.call
+ allow(next_qualified_repository).to receive(:migration_pre_import).and_return(:ok)
+ next_qualified_repository
+ end
+
+ expect(worker).to receive(:log_extra_metadata_on_done)
+ .with(:container_repository_id, container_repository.id)
+ expect(worker).to receive(:log_extra_metadata_on_done)
+ .with(:import_type, 'next')
+
+ subject
+
+ expect(container_repository.reload).to be_pre_importing
+ end
+
+ it_behaves_like 're-enqueuing based on capacity'
+ end
+
+ context 'migrations are disabled' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enabled?).and_return(false)
+ end
+
+ it_behaves_like 'no action'
+ end
+
+ context 'above capacity' do
+ before do
+ create(:container_repository, :importing)
+ create(:container_repository, :importing)
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(1)
+ end
+
+ it_behaves_like 'no action'
+
+ it 'does not re-enqueue the worker' do
+ expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_async)
+
+ subject
+ end
+ end
+
+ context 'too soon before previous completed import step' do
+ before do
+ create(:container_repository, :import_done, migration_import_done_at: 1.minute.ago)
+ allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(1.hour)
+ end
+
+ it_behaves_like 'no action'
+ end
+
+ context 'when an aborted import is available' do
+ let_it_be(:aborted_repository) { create(:container_repository, :import_aborted) }
+
+ it 'retries the import for the aborted repository' do
+ method = worker.method(:next_aborted_repository)
+ allow(worker).to receive(:next_aborted_repository) do
+ next_aborted_repository = method.call
+ allow(next_aborted_repository).to receive(:migration_import).and_return(:ok)
+ allow(next_aborted_repository.gitlab_api_client).to receive(:import_status).and_return('import_failed')
+ next_aborted_repository
+ end
+
+ expect(worker).to receive(:log_extra_metadata_on_done)
+ .with(:container_repository_id, aborted_repository.id)
+ expect(worker).to receive(:log_extra_metadata_on_done)
+ .with(:import_type, 'retry')
+
+ subject
+
+ expect(aborted_repository.reload).to be_importing
+ expect(container_repository.reload).to be_default
+ end
+
+ it_behaves_like 're-enqueuing based on capacity'
+ end
+
+ context 'when no repository qualifies' do
+ include_examples 'an idempotent worker' do
+ before do
+ allow(ContainerRepository).to receive(:ready_for_import).and_return(ContainerRepository.none)
+ end
+
+ it_behaves_like 'no action'
+ end
+ end
+
+ context 'over max tag count' do
+ before do
+ stub_application_setting(container_registry_import_max_tags_count: 2)
+ end
+
+ it 'skips the repository' do
+ subject
+
+ expect(container_repository.reload).to be_import_skipped
+ expect(container_repository.migration_skipped_reason).to eq('too_many_tags')
+ expect(container_repository.migration_skipped_at).not_to be_nil
+ end
+
+ it_behaves_like 're-enqueuing based on capacity'
+ end
+
+ context 'when an error occurs' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:max_tags_count).and_raise(StandardError)
+ end
+
+ it 'aborts the import' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ instance_of(StandardError),
+ next_repository_id: container_repository.id,
+ next_aborted_repository_id: nil
+ )
+
+ subject
+
+ expect(container_repository.reload).to be_import_aborted
+ end
+ end
+ end
+end
diff --git a/spec/workers/container_registry/migration/guard_worker_spec.rb b/spec/workers/container_registry/migration/guard_worker_spec.rb
new file mode 100644
index 00000000000..7d1df320d4e
--- /dev/null
+++ b/spec/workers/container_registry/migration/guard_worker_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::Migration::GuardWorker, :aggregate_failures do
+ include_context 'container registry client'
+
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ let(:pre_importing_migrations) { ::ContainerRepository.with_migration_states(:pre_importing) }
+ let(:pre_import_done_migrations) { ::ContainerRepository.with_migration_states(:pre_import_done) }
+ let(:importing_migrations) { ::ContainerRepository.with_migration_states(:importing) }
+ let(:import_aborted_migrations) { ::ContainerRepository.with_migration_states(:import_aborted) }
+ let(:import_done_migrations) { ::ContainerRepository.with_migration_states(:import_done) }
+
+ subject { worker.perform }
+
+ before do
+ stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
+ allow(::ContainerRegistry::Migration).to receive(:max_step_duration).and_return(5.minutes)
+ end
+
+ context 'on gitlab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ end
+
+ shared_examples 'not aborting any migration' do
+ it 'will not abort the migration' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:stale_migrations_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:aborted_stale_migrations_count, 0)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:long_running_stale_migration_container_repository_ids, [stale_migration.id])
+
+ expect { subject }
+ .to not_change(pre_importing_migrations, :count)
+ .and not_change(pre_import_done_migrations, :count)
+ .and not_change(importing_migrations, :count)
+ .and not_change(import_done_migrations, :count)
+ .and not_change(import_aborted_migrations, :count)
+ .and not_change { stale_migration.reload.migration_state }
+ .and not_change { ongoing_migration.migration_state }
+ end
+ end
+
+ context 'with no stale migrations' do
+ it_behaves_like 'an idempotent worker'
+
+ it 'will not update any migration state' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:stale_migrations_count, 0)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:aborted_stale_migrations_count, 0)
+
+ expect { subject }
+ .to not_change(pre_importing_migrations, :count)
+ .and not_change(pre_import_done_migrations, :count)
+ .and not_change(importing_migrations, :count)
+ .and not_change(import_aborted_migrations, :count)
+ end
+ end
+
+ context 'with pre_importing stale migrations' do
+ let(:ongoing_migration) { create(:container_repository, :pre_importing) }
+ let(:stale_migration) { create(:container_repository, :pre_importing, migration_pre_import_started_at: 35.minutes.ago) }
+ let(:import_status) { 'test' }
+
+ before do
+ allow_next_instance_of(ContainerRegistry::GitlabApiClient) do |client|
+ allow(client).to receive(:import_status).and_return(import_status)
+ end
+ end
+
+ it 'will abort the migration' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:stale_migrations_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:aborted_stale_migrations_count, 1)
+
+ expect { subject }
+ .to change(pre_importing_migrations, :count).by(-1)
+ .and not_change(pre_import_done_migrations, :count)
+ .and not_change(importing_migrations, :count)
+ .and not_change(import_done_migrations, :count)
+ .and change(import_aborted_migrations, :count).by(1)
+ .and change { stale_migration.reload.migration_state }.from('pre_importing').to('import_aborted')
+ .and not_change { ongoing_migration.migration_state }
+ end
+
+ context 'the client returns pre_import_in_progress' do
+ let(:import_status) { 'pre_import_in_progress' }
+
+ it_behaves_like 'not aborting any migration'
+ end
+ end
+
+ context 'with pre_import_done stale migrations' do
+ let(:ongoing_migration) { create(:container_repository, :pre_import_done) }
+ let(:stale_migration) { create(:container_repository, :pre_import_done, migration_pre_import_done_at: 35.minutes.ago) }
+
+ before do
+ allow(::ContainerRegistry::Migration).to receive(:max_step_duration).and_return(5.minutes)
+ end
+
+ it 'will abort the migration' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:stale_migrations_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:aborted_stale_migrations_count, 1)
+
+ expect { subject }
+ .to not_change(pre_importing_migrations, :count)
+ .and change(pre_import_done_migrations, :count).by(-1)
+ .and not_change(importing_migrations, :count)
+ .and not_change(import_done_migrations, :count)
+ .and change(import_aborted_migrations, :count).by(1)
+ .and change { stale_migration.reload.migration_state }.from('pre_import_done').to('import_aborted')
+ .and not_change { ongoing_migration.migration_state }
+ end
+ end
+
+ context 'with importing stale migrations' do
+ let(:ongoing_migration) { create(:container_repository, :importing) }
+ let(:stale_migration) { create(:container_repository, :importing, migration_import_started_at: 35.minutes.ago) }
+ let(:import_status) { 'test' }
+
+ before do
+ allow_next_instance_of(ContainerRegistry::GitlabApiClient) do |client|
+ allow(client).to receive(:import_status).and_return(import_status)
+ end
+ end
+
+ it 'will abort the migration' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:stale_migrations_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:aborted_stale_migrations_count, 1)
+
+ expect { subject }
+ .to not_change(pre_importing_migrations, :count)
+ .and not_change(pre_import_done_migrations, :count)
+ .and change(importing_migrations, :count).by(-1)
+ .and not_change(import_done_migrations, :count)
+ .and change(import_aborted_migrations, :count).by(1)
+ .and change { stale_migration.reload.migration_state }.from('importing').to('import_aborted')
+ .and not_change { ongoing_migration.migration_state }
+ end
+
+ context 'the client returns import_in_progress' do
+ let(:import_status) { 'import_in_progress' }
+
+ it_behaves_like 'not aborting any migration'
+ end
+ end
+ end
+
+ context 'not on gitlab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ end
+
+ it 'is a no op' do
+ expect(::ContainerRepository).not_to receive(:with_stale_migration)
+ expect(worker).not_to receive(:log_extra_metadata_on_done)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/container_registry/migration/observer_worker_spec.rb b/spec/workers/container_registry/migration/observer_worker_spec.rb
new file mode 100644
index 00000000000..fec6640d7ec
--- /dev/null
+++ b/spec/workers/container_registry/migration/observer_worker_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::Migration::ObserverWorker, :aggregate_failures do
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ subject { worker.perform }
+
+ context 'when the migration feature flag is disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enabled: false)
+ end
+
+ it 'does nothing' do
+ expect(worker).not_to receive(:log_extra_metadata_on_done)
+
+ subject
+ end
+ end
+
+ context 'when the migration is enabled' do
+ before do
+ create_list(:container_repository, 3)
+ create(:container_repository, :pre_importing)
+ create(:container_repository, :pre_import_done)
+ create_list(:container_repository, 2, :importing)
+ create(:container_repository, :import_aborted)
+ # batch_count is not allowed within a transaction but
+ # all rspec tests run inside of a transaction.
+ # This mocks the false positive.
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) # rubocop:disable Database/MultipleDatabases
+ end
+
+ it 'logs all the counts' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:default_count, 3)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:pre_importing_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:pre_import_done_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:importing_count, 2)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:import_done_count, 0)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:import_aborted_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:import_skipped_count, 0)
+
+ subject
+ end
+
+ context 'with load balancing enabled', :db_load_balancing do
+ it 'uses the replica' do
+ expect(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_replicas_for_read_queries).and_call_original
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/delete_container_repository_worker_spec.rb b/spec/workers/delete_container_repository_worker_spec.rb
index b8363a2f81a..ec040eab2d4 100644
--- a/spec/workers/delete_container_repository_worker_spec.rb
+++ b/spec/workers/delete_container_repository_worker_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe DeleteContainerRepositoryWorker do
let(:registry) { create(:container_repository) }
let(:project) { registry.project }
- let(:user) { project.owner }
+ let(:user) { project.first_owner }
subject { described_class.new }
diff --git a/spec/workers/delete_merged_branches_worker_spec.rb b/spec/workers/delete_merged_branches_worker_spec.rb
index 861ca111b92..056fcb1200d 100644
--- a/spec/workers/delete_merged_branches_worker_spec.rb
+++ b/spec/workers/delete_merged_branches_worker_spec.rb
@@ -13,11 +13,11 @@ RSpec.describe DeleteMergedBranchesWorker do
expect(instance).to receive(:execute).and_return(true)
end
- worker.perform(project.id, project.owner.id)
+ worker.perform(project.id, project.first_owner.id)
end
it "returns false when project was not found" do
- expect(worker.perform('unknown', project.owner.id)).to be_falsy
+ expect(worker.perform('unknown', project.first_owner.id)).to be_falsy
end
end
end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 4f9c207f976..1cd5d23d8fc 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -135,6 +135,7 @@ RSpec.describe 'Every Sidekiq worker' do
'AutoDevops::DisableWorker' => 3,
'AutoMergeProcessWorker' => 3,
'BackgroundMigrationWorker' => 3,
+ 'BackgroundMigration::CiDatabaseWorker' => 3,
'BuildFinishedWorker' => 3,
'BuildHooksWorker' => 3,
'BuildQueueWorker' => 3,
@@ -348,6 +349,7 @@ RSpec.describe 'Every Sidekiq worker' do
'Namespaces::OnboardingPipelineCreatedWorker' => 3,
'Namespaces::OnboardingProgressWorker' => 3,
'Namespaces::OnboardingUserAddedWorker' => 3,
+ 'Namespaces::RefreshRootStatisticsWorker' => 3,
'Namespaces::RootStatisticsWorker' => 3,
'Namespaces::ScheduleAggregationWorker' => 3,
'NetworkPolicyMetricsWorker' => 3,
@@ -371,7 +373,6 @@ RSpec.describe 'Every Sidekiq worker' do
'PagesDomainSslRenewalWorker' => 3,
'PagesDomainVerificationWorker' => 3,
'PagesTransferWorker' => 3,
- 'PagesUpdateConfigurationWorker' => 1,
'PagesWorker' => 3,
'PersonalAccessTokens::Groups::PolicyWorker' => 3,
'PersonalAccessTokens::Instance::PolicyWorker' => 3,
@@ -459,7 +460,8 @@ RSpec.describe 'Every Sidekiq worker' do
'WebHooks::DestroyWorker' => 3,
'WebHooks::LogExecutionWorker' => 3,
'Wikis::GitGarbageCollectWorker' => false,
- 'X509CertificateRevokeWorker' => 3
+ 'X509CertificateRevokeWorker' => 3,
+ 'ComplianceManagement::MergeRequests::ComplianceViolationsWorker' => 3
}
end
diff --git a/spec/workers/groups/update_statistics_worker_spec.rb b/spec/workers/groups/update_statistics_worker_spec.rb
new file mode 100644
index 00000000000..7fc166ed300
--- /dev/null
+++ b/spec/workers/groups/update_statistics_worker_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::UpdateStatisticsWorker do
+ let_it_be(:group) { create(:group) }
+
+ let(:statistics) { %w(wiki_size) }
+
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ it 'updates the group statistics' do
+ expect(Groups::UpdateStatisticsService).to receive(:new)
+ .with(group, statistics: statistics)
+ .and_call_original
+
+ worker.perform(group.id, statistics)
+ end
+
+ context 'when group id does not exist' do
+ it 'ends gracefully' do
+ expect(Groups::UpdateStatisticsService).not_to receive(:new)
+
+ expect { worker.perform(non_existing_record_id, statistics) }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
index 497f95cf34d..6f4389a7541 100644
--- a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
+++ b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
@@ -141,16 +141,6 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
end
end
- context 'when the loose_foreign_key_cleanup feature flag is off' do
- before do
- stub_feature_flags(loose_foreign_key_cleanup: false)
- end
-
- it 'does nothing' do
- expect { described_class.new.perform }.not_to change { LooseForeignKeys::DeletedRecord.status_processed.count }
- end
- end
-
describe 'multi-database support' do
where(:current_minute, :configured_base_models, :expected_connection) do
2 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | ApplicationRecord.connection
diff --git a/spec/workers/namespaces/process_sync_events_worker_spec.rb b/spec/workers/namespaces/process_sync_events_worker_spec.rb
index 59be1fffdb4..c15a74a2934 100644
--- a/spec/workers/namespaces/process_sync_events_worker_spec.rb
+++ b/spec/workers/namespaces/process_sync_events_worker_spec.rb
@@ -7,10 +7,12 @@ RSpec.describe Namespaces::ProcessSyncEventsWorker do
let!(:group2) { create(:group) }
let!(:group3) { create(:group) }
+ subject(:worker) { described_class.new }
+
include_examples 'an idempotent worker'
describe '#perform' do
- subject(:perform) { described_class.new.perform }
+ subject(:perform) { worker.perform }
before do
group2.update!(parent: group1)
@@ -28,5 +30,13 @@ RSpec.describe Namespaces::ProcessSyncEventsWorker do
an_object_having_attributes(namespace_id: group3.id, traversal_ids: [group1.id, group2.id, group3.id])
)
end
+
+ it 'logs the service result', :aggregate_failures do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:estimated_total_events, 5)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:consumable_events, 5)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:processed_events, 5)
+
+ perform
+ end
end
end
diff --git a/spec/workers/namespaces/update_root_statistics_worker_spec.rb b/spec/workers/namespaces/update_root_statistics_worker_spec.rb
new file mode 100644
index 00000000000..a525904b757
--- /dev/null
+++ b/spec/workers/namespaces/update_root_statistics_worker_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::UpdateRootStatisticsWorker do
+ let(:namespace_id) { 123 }
+
+ let(:event) do
+ Projects::ProjectDeletedEvent.new(data: { project_id: 1, namespace_id: namespace_id })
+ end
+
+ subject { consume_event(event) }
+
+ def consume_event(event)
+ described_class.new.perform(event.class.name, event.data)
+ end
+
+ it 'enqueues ScheduleAggregationWorker' do
+ expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(namespace_id)
+
+ subject
+ end
+end
diff --git a/spec/workers/pages_update_configuration_worker_spec.rb b/spec/workers/pages_update_configuration_worker_spec.rb
deleted file mode 100644
index af71f6b3cca..00000000000
--- a/spec/workers/pages_update_configuration_worker_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-require "spec_helper"
-
-RSpec.describe PagesUpdateConfigurationWorker do
- let_it_be(:project) { create(:project) }
-
- describe "#perform" do
- it "does not break" do
- expect { subject.perform(-1) }.not_to raise_error
- end
- end
-end
diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb
index f59d8ad4615..4a7db0eca56 100644
--- a/spec/workers/pipeline_schedule_worker_spec.rb
+++ b/spec/workers/pipeline_schedule_worker_spec.rb
@@ -103,4 +103,14 @@ RSpec.describe PipelineScheduleWorker do
expect { subject }.not_to raise_error
end
end
+
+ context 'when the project is missing' do
+ before do
+ project.delete
+ end
+
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
+ end
+ end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 42e39c51a88..9b33e559c71 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe PostReceive do
let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
let(:gl_repository) { "project-#{project.id}" }
- let(:key) { create(:key, user: project.owner) }
+ let(:key) { create(:key, user: project.first_owner) }
let!(:key_id) { key.shell_id }
let(:project) do
@@ -47,7 +47,7 @@ RSpec.describe PostReceive do
context 'with PersonalSnippet' do
let(:gl_repository) { "snippet-#{snippet.id}" }
- let(:snippet) { create(:personal_snippet, author: project.owner) }
+ let(:snippet) { create(:personal_snippet, author: project.first_owner) }
it 'does not log an error' do
expect(Gitlab::GitLogger).not_to receive(:error)
@@ -60,7 +60,7 @@ RSpec.describe PostReceive do
context 'with ProjectSnippet' do
let(:gl_repository) { "snippet-#{snippet.id}" }
- let(:snippet) { create(:snippet, type: 'ProjectSnippet', project: nil, author: project.owner) }
+ let(:snippet) { create(:snippet, type: 'ProjectSnippet', project: nil, author: project.first_owner) }
it 'returns false and logs an error' do
expect(Gitlab::GitLogger).to receive(:error).with("POST-RECEIVE: #{error_message}")
@@ -74,7 +74,7 @@ RSpec.describe PostReceive do
let(:empty_project) { create(:project, :empty_repo) }
before do
- allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(empty_project.owner)
+ allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(empty_project.first_owner)
# Need to mock here so we can expect calls on project
allow(Gitlab::GlRepository).to receive(:parse).and_return([empty_project, empty_project, Gitlab::GlRepository::PROJECT])
end
@@ -128,7 +128,7 @@ RSpec.describe PostReceive do
let(:push_service) { double(execute: true) }
before do
- allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
+ allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(project.first_owner)
allow(Gitlab::GlRepository).to receive(:parse).and_return([project, project, Gitlab::GlRepository::PROJECT])
end
@@ -381,7 +381,7 @@ RSpec.describe PostReceive do
allow(Project).to receive(:find_by).and_return(project)
expect_next(MergeRequests::PushedBranchesService).to receive(:execute).and_return(%w(tést))
- expect(UpdateMergeRequestsWorker).to receive(:perform_async).with(project.id, project.owner.id, any_args)
+ expect(UpdateMergeRequestsWorker).to receive(:perform_async).with(project.id, project.first_owner.id, any_args)
perform
end
@@ -461,13 +461,13 @@ RSpec.describe PostReceive do
end
context 'with PersonalSnippet' do
- let!(:snippet) { create(:personal_snippet, :repository, author: project.owner) }
+ let!(:snippet) { create(:personal_snippet, :repository, author: project.first_owner) }
it_behaves_like 'snippet changes actions'
end
context 'with ProjectSnippet' do
- let!(:snippet) { create(:project_snippet, :repository, project: project, author: project.owner) }
+ let!(:snippet) { create(:project_snippet, :repository, project: project, author: project.first_owner) }
it_behaves_like 'snippet changes actions'
end
diff --git a/spec/workers/project_destroy_worker_spec.rb b/spec/workers/project_destroy_worker_spec.rb
index 00a4ddac29f..0b0543a5089 100644
--- a/spec/workers/project_destroy_worker_spec.rb
+++ b/spec/workers/project_destroy_worker_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe ProjectDestroyWorker do
describe '#perform' do
it 'deletes the project' do
- subject.perform(project.id, project.owner.id, {})
+ subject.perform(project.id, project.first_owner.id, {})
expect(Project.all).not_to include(project)
expect(Dir.exist?(path)).to be_falsey
@@ -22,7 +22,7 @@ RSpec.describe ProjectDestroyWorker do
it 'does not raise error when project could not be found' do
expect do
- subject.perform(-1, project.owner.id, {})
+ subject.perform(-1, project.first_owner.id, {})
end.not_to raise_error
end
diff --git a/spec/workers/projects/git_garbage_collect_worker_spec.rb b/spec/workers/projects/git_garbage_collect_worker_spec.rb
index 7b54d7df4b2..ae567107443 100644
--- a/spec/workers/projects/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/projects/git_garbage_collect_worker_spec.rb
@@ -32,6 +32,21 @@ RSpec.describe Projects::GitGarbageCollectWorker do
subject.perform(*params)
end
+
+ context 'when deduplication service runs into a GRPC internal error' do
+ before do
+ allow_next_instance_of(::Projects::GitDeduplicationService) do |instance|
+ expect(instance).to receive(:execute).and_raise(GRPC::Internal)
+ end
+ end
+
+ it_behaves_like 'can collect git garbage' do
+ let(:resource) { project }
+ let(:statistics_service_klass) { Projects::UpdateStatisticsService }
+ let(:statistics_keys) { [:repository_size, :lfs_objects_size] }
+ let(:expected_default_lease) { "projects:#{resource.id}" }
+ end
+ end
end
context 'LFS object garbage collection' do
diff --git a/spec/workers/projects/process_sync_events_worker_spec.rb b/spec/workers/projects/process_sync_events_worker_spec.rb
index 600fbbc6b20..963e0ad1028 100644
--- a/spec/workers/projects/process_sync_events_worker_spec.rb
+++ b/spec/workers/projects/process_sync_events_worker_spec.rb
@@ -6,10 +6,12 @@ RSpec.describe Projects::ProcessSyncEventsWorker do
let!(:group) { create(:group) }
let!(:project) { create(:project) }
+ subject(:worker) { described_class.new }
+
include_examples 'an idempotent worker'
describe '#perform' do
- subject(:perform) { described_class.new.perform }
+ subject(:perform) { worker.perform }
before do
project.update!(namespace: group)
@@ -24,5 +26,13 @@ RSpec.describe Projects::ProcessSyncEventsWorker do
an_object_having_attributes(namespace_id: group.id)
)
end
+
+ it 'logs the service result', :aggregate_failures do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:estimated_total_events, 2)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:consumable_events, 2)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:processed_events, 2)
+
+ perform
+ end
end
end
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index bb11d1dbb58..846b4455bf9 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -10,12 +10,25 @@ RSpec.describe RunPipelineScheduleWorker do
let(:worker) { described_class.new }
- context 'when a project not found' do
+ context 'when a schedule not found' do
it 'does not call the Service' do
expect(Ci::CreatePipelineService).not_to receive(:new)
expect(worker).not_to receive(:run_pipeline_schedule)
- worker.perform(100000, user.id)
+ worker.perform(non_existing_record_id, user.id)
+ end
+ end
+
+ context 'when a schedule project is missing' do
+ before do
+ project.delete
+ end
+
+ it 'does not call the Service' do
+ expect(Ci::CreatePipelineService).not_to receive(:new)
+ expect(worker).not_to receive(:run_pipeline_schedule)
+
+ worker.perform(pipeline_schedule.id, user.id)
end
end
@@ -24,7 +37,7 @@ RSpec.describe RunPipelineScheduleWorker do
expect(Ci::CreatePipelineService).not_to receive(:new)
expect(worker).not_to receive(:run_pipeline_schedule)
- worker.perform(pipeline_schedule.id, 10000)
+ worker.perform(pipeline_schedule.id, non_existing_record_id)
end
end
diff --git a/spec/workers/web_hook_worker_spec.rb b/spec/workers/web_hook_worker_spec.rb
index bbb8844a447..dbdf7a2b978 100644
--- a/spec/workers/web_hook_worker_spec.rb
+++ b/spec/workers/web_hook_worker_spec.rb
@@ -19,7 +19,16 @@ RSpec.describe WebHookWorker do
expect { subject.perform(non_existing_record_id, data, hook_name) }.not_to raise_error
end
- it 'retrieves recursion detection data, reinstates it, and cleans it from payload', :request_store, :aggregate_failures do
+ it 'retrieves recursion detection data and reinstates it', :request_store, :aggregate_failures do
+ uuid = SecureRandom.uuid
+ params = { recursion_detection_request_uuid: uuid }
+
+ expect_next(WebHookService, project_hook, data.with_indifferent_access, hook_name, anything).to receive(:execute)
+ expect { subject.perform(project_hook.id, data, hook_name, params) }
+ .to change { Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid }.to(uuid)
+ end
+
+ it 'retrieves recursion detection data, reinstates it, and cleans it from payload when passed through as data', :request_store, :aggregate_failures do
uuid = SecureRandom.uuid
full_data = data.merge({ _gitlab_recursion_detection_request_uuid: uuid })
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index f49b8bf7f2a..eaf33608b83 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -45,6 +45,8 @@ module Tooling
%r{\Adoc/.*(\.(md|png|gif|jpg|yml))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
%r{\Adata/whats_new/} => :docs,
+ %r{\Adata/deprecations/} => :none,
+ %r{\Adata/removals/} => :none,
%r{\A((ee|jh)/)?app/finders/(.+/)?integrations/} => [:integrations_be, :database, :backend],
[%r{\A((ee|jh)/)?db/(geo/)?(migrate|post_migrate)/}, %r{(:integrations|:\w+_tracker_data)\b}] => [:integrations_be, :database, :migration],
@@ -56,7 +58,7 @@ module Tooling
((ee|jh)/)?app/controllers/(.+/)?oauth/jira/.+ |
((ee|jh)/)?app/services/(.+/)?jira.+ |
((ee|jh)/)?app/workers/(.+/)?(propagate_integration.+|irker_worker\.rb) |
- ((ee|jh)/)?lib/(.+/)?(atlassian|data_builder|hook_data)/.+ |
+ ((ee|jh)/)?lib/(.+/)?(atlassian|data_builder|hook_data|web_hooks)/.+ |
((ee|jh)/)?lib/(.+/)?.*integration.+ |
((ee|jh)/)?lib/(.+/)?api/v3/github\.rb |
((ee|jh)/)?lib/(.+/)?api/github/entities\.rb
diff --git a/tooling/lib/tooling/test_map_generator.rb b/tooling/lib/tooling/test_map_generator.rb
index 20e4ed8e405..f96f33ff074 100644
--- a/tooling/lib/tooling/test_map_generator.rb
+++ b/tooling/lib/tooling/test_map_generator.rb
@@ -12,7 +12,12 @@ module Tooling
def parse(yaml_files)
Array(yaml_files).each do |yaml_file|
data = File.read(yaml_file)
- _metadata, example_groups = data.split("---\n").reject(&:empty?).map { |yml| YAML.safe_load(yml, [Symbol]) }
+ metadata, example_groups = data.split("---\n").reject(&:empty?).map { |yml| YAML.safe_load(yml, [Symbol]) }
+
+ if example_groups.nil?
+ puts "No examples in #{yaml_file}! Metadata: #{metadata}"
+ next
+ end
example_groups.each do |example_id, files|
files.each do |file|
diff --git a/tooling/quality/test_level.rb b/tooling/quality/test_level.rb
index 50cbc69beb2..624564ecd05 100644
--- a/tooling/quality/test_level.rb
+++ b/tooling/quality/test_level.rb
@@ -24,6 +24,7 @@ module Quality
elastic
elastic_integration
experiments
+ events
factories
finders
frontend
diff --git a/tooling/rspec_flaky/config.rb b/tooling/rspec_flaky/config.rb
index ea18a601c11..36e35671587 100644
--- a/tooling/rspec_flaky/config.rb
+++ b/tooling/rspec_flaky/config.rb
@@ -7,15 +7,19 @@ module RspecFlaky
end
def self.suite_flaky_examples_report_path
- ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'] || rails_path("rspec_flaky/suite-report.json")
+ ENV['FLAKY_RSPEC_SUITE_REPORT_PATH'] || rails_path("rspec/flaky/suite-report.json")
end
def self.flaky_examples_report_path
- ENV['FLAKY_RSPEC_REPORT_PATH'] || rails_path("rspec_flaky/report.json")
+ ENV['FLAKY_RSPEC_REPORT_PATH'] || rails_path("rspec/flaky/report.json")
end
def self.new_flaky_examples_report_path
- ENV['NEW_FLAKY_RSPEC_REPORT_PATH'] || rails_path("rspec_flaky/new-report.json")
+ ENV['NEW_FLAKY_RSPEC_REPORT_PATH'] || rails_path("rspec/flaky/new-report.json")
+ end
+
+ def self.skipped_flaky_tests_report_path
+ ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH'] || rails_path("rspec/flaky/skipped_flaky_tests_report.txt")
end
def self.rails_path(path)
diff --git a/vendor/project_templates/cluster_management.tar.gz b/vendor/project_templates/cluster_management.tar.gz
index 7b12044e414..843a8a355f1 100644
--- a/vendor/project_templates/cluster_management.tar.gz
+++ b/vendor/project_templates/cluster_management.tar.gz
Binary files differ
diff --git a/workhorse/.tool-versions b/workhorse/.tool-versions
index bf23029f784..29cc9a03144 100644
--- a/workhorse/.tool-versions
+++ b/workhorse/.tool-versions
@@ -1 +1 @@
-golang 1.16.12
+golang 1.17.6
diff --git a/workhorse/Makefile b/workhorse/Makefile
index 031fe581d28..44b3e2b8248 100644
--- a/workhorse/Makefile
+++ b/workhorse/Makefile
@@ -12,7 +12,7 @@ ifdef SOURCE_DATE_EPOCH
else
BUILD_TIME := $(shell date -u "$(DATE_FMT)")
endif
-GOBUILD := go build -ldflags "-X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)"
+GO_BUILD_GENERIC_LDFLAGS := -X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)
GITALY := tmp/tests/gitaly/_build/bin/gitaly
GITALY_PID_FILE := gitaly.pid
EXE_ALL := gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse
@@ -30,31 +30,35 @@ define message
@echo "### $(1)"
endef
+# To compute a unique and deterministic value for GNU build-id, we build the Go binary a second time.
+# From the first build, we extract its unique and deterministic Go build-id, and use that to derive
+# a comparably unique and deterministic GNU build-id to inject into the final binary.
+# If we cannot extract a Go build-id, we punt and fallback to using a random 32-byte hex string.
+# This fallback is unique but non-deterministic. Uniqueness is critical, because the GNU build-id
+# can be used as a cache key in a build cache. Without the fallback, we risk cache key collisions.
+## Skip generation of the GNU build ID if set to speed up builds.
+WITHOUT_BUILD_ID ?=
.NOTPARALLEL:
.PHONY: all
all: clean-build $(EXE_ALL)
-.PHONY: gitlab-resize-image
-gitlab-resize-image:
+.PHONY: gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata
+gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata:
$(call message,Building $@)
- $(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
-
-.PHONY: gitlab-zip-cat
-gitlab-zip-cat:
- $(call message,Building $@)
- $(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
-
-.PHONY: gitlab-zip-metadata
-gitlab-zip-metadata:
- $(call message,Building $@)
- $(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
+ go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
+ifndef WITHOUT_BUILD_ID
+ go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
+endif
.PHONY: gitlab-workhorse
gitlab-workhorse:
$(call message,Building $@)
- $(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
+ go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
+ifndef WITHOUT_BUILD_ID
+ go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
+endif
.PHONY: install
install: $(EXE_ALL)
diff --git a/workhorse/_support/make-gnu-build-id.sh b/workhorse/_support/make-gnu-build-id.sh
new file mode 100755
index 00000000000..815966dab7e
--- /dev/null
+++ b/workhorse/_support/make-gnu-build-id.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+main()
+{
+ GO_BINARY=$1
+
+ if [ $# -ne 1 ] || [ ! -f $GO_BINARY ] ; then
+ fail "Usage: $0 [path_to_go_binary]"
+ fi
+
+ GO_BUILD_ID=$( go tool buildid "$GO_BINARY" || openssl rand -hex 32 )
+ if [ -z "$GO_BUILD_ID" ] ; then
+ fail "ERROR: Could not extract Go build-id or generate a random hex string."
+ fi
+
+ GNU_BUILD_ID=$( echo $GO_BUILD_ID | sha1sum | cut -d' ' -f1 )
+ if [ -z "$GNU_BUILD_ID" ] ; then
+ fail "ERROR: Could not generate a GNU build-id"
+ fi
+
+ echo "$GNU_BUILD_ID"
+}
+
+fail()
+{
+ echo "$@" 1>&2
+ exit 1
+}
+
+main "$@"
diff --git a/workhorse/internal/artifacts/artifacts_store_test.go b/workhorse/internal/artifacts/artifacts_store_test.go
index a01a723298f..f9fb28cf7ce 100644
--- a/workhorse/internal/artifacts/artifacts_store_test.go
+++ b/workhorse/internal/artifacts/artifacts_store_test.go
@@ -284,12 +284,9 @@ func TestUploadHandlerMultipartUploadSizeLimit(t *testing.T) {
contentBuffer, contentType := createTestMultipartForm(t, make([]byte, uploadSize))
response := testUploadArtifacts(t, contentType, ts.URL+Path, &contentBuffer)
require.Equal(t, http.StatusRequestEntityTooLarge, response.Code)
-
- // Poll because AbortMultipartUpload is async
- for i := 0; os.IsMultipartUpload(test.ObjectPath) && i < 100; i++ {
- time.Sleep(10 * time.Millisecond)
- }
- require.False(t, os.IsMultipartUpload(test.ObjectPath), "MultipartUpload should not be in progress anymore")
+ require.Eventually(t, func() bool {
+ return !os.IsMultipartUpload(test.ObjectPath)
+ }, time.Second, time.Millisecond, "MultipartUpload should not be in progress anymore")
require.Empty(t, os.GetObjectMD5(test.ObjectPath), "upload should have failed, so the object should not exists")
}
diff --git a/workhorse/internal/artifacts/artifacts_upload.go b/workhorse/internal/artifacts/artifacts_upload.go
index ef289fbb93b..f1fd69082f8 100644
--- a/workhorse/internal/artifacts/artifacts_upload.go
+++ b/workhorse/internal/artifacts/artifacts_upload.go
@@ -162,6 +162,6 @@ func UploadArtifacts(myAPI *api.API, h http.Handler, p upload.Preparer) http.Han
format := r.URL.Query().Get(ArtifactFormatKey)
mg := &artifactsUploadProcessor{opts: opts, format: format, SavedFileTracker: upload.SavedFileTracker{Request: r}}
- upload.HandleFileUploads(w, r, h, a, mg, opts)
+ upload.InterceptMultipartFiles(w, r, h, a, mg, opts)
}, "/authorize")
}
diff --git a/workhorse/internal/dependencyproxy/dependencyproxy_test.go b/workhorse/internal/dependencyproxy/dependencyproxy_test.go
index d9169b2b4ce..6056433f3b1 100644
--- a/workhorse/internal/dependencyproxy/dependencyproxy_test.go
+++ b/workhorse/internal/dependencyproxy/dependencyproxy_test.go
@@ -91,12 +91,12 @@ func TestInject(t *testing.T) {
}))
defer originResourceServer.Close()
- // BodyUploader expects http.Handler as its second param, we can create a stub function and verify that
+ // RequestBody expects http.Handler as its second param, we can create a stub function and verify that
// it's only called for successful requests
handlerIsCalled := false
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handlerIsCalled = true })
- bodyUploader := upload.BodyUploader(&fakePreAuthHandler{}, handlerFunc, &upload.DefaultPreparer{})
+ bodyUploader := upload.RequestBody(&fakePreAuthHandler{}, handlerFunc, &upload.DefaultPreparer{})
injector := NewInjector()
injector.SetUploadHandler(bodyUploader)
diff --git a/workhorse/internal/filestore/file_handler_test.go b/workhorse/internal/filestore/file_handler_test.go
index f57026a59df..2fd034bb761 100644
--- a/workhorse/internal/filestore/file_handler_test.go
+++ b/workhorse/internal/filestore/file_handler_test.go
@@ -28,29 +28,15 @@ func testDeadline() time.Time {
func requireFileGetsRemovedAsync(t *testing.T, filePath string) {
var err error
-
- // Poll because the file removal is async
- for i := 0; i < 100; i++ {
+ require.Eventually(t, func() bool {
_, err = os.Stat(filePath)
- if err != nil {
- break
- }
- time.Sleep(100 * time.Millisecond)
- }
-
+ return err != nil
+ }, 10*time.Second, 10*time.Millisecond)
require.True(t, os.IsNotExist(err), "File hasn't been deleted during cleanup")
}
func requireObjectStoreDeletedAsync(t *testing.T, expectedDeletes int, osStub *test.ObjectstoreStub) {
- // Poll because the object removal is async
- for i := 0; i < 100; i++ {
- if osStub.DeletesCnt() == expectedDeletes {
- break
- }
- time.Sleep(10 * time.Millisecond)
- }
-
- require.Equal(t, expectedDeletes, osStub.DeletesCnt(), "Object not deleted")
+ require.Eventually(t, func() bool { return osStub.DeletesCnt() == expectedDeletes }, time.Second, time.Millisecond, "Object not deleted")
}
func TestSaveFileWrongSize(t *testing.T) {
diff --git a/workhorse/internal/lfs/lfs.go b/workhorse/internal/lfs/lfs.go
index 363e2113422..e26f59046ea 100644
--- a/workhorse/internal/lfs/lfs.go
+++ b/workhorse/internal/lfs/lfs.go
@@ -6,7 +6,6 @@ package lfs
import (
"fmt"
- "net/http"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
@@ -49,7 +48,3 @@ func (l *uploadPreparer) Prepare(a *api.Response) (*filestore.SaveFileOpts, uplo
return opts, &object{oid: a.LfsOid, size: a.LfsSize}, nil
}
-
-func PutStore(a *api.API, h http.Handler, p upload.Preparer) http.Handler {
- return upload.BodyUploader(a, h, p)
-}
diff --git a/workhorse/internal/objectstore/object_test.go b/workhorse/internal/objectstore/object_test.go
index c15248edf78..b9c1fb2087b 100644
--- a/workhorse/internal/objectstore/object_test.go
+++ b/workhorse/internal/objectstore/object_test.go
@@ -56,13 +56,7 @@ func testObjectUploadNoErrors(t *testing.T, startObjectStore osFactory, useDelet
if useDeleteURL {
expectedDeleteCnt = 1
}
- // Poll because the object removal is async
- for i := 0; i < 100; i++ {
- if osStub.DeletesCnt() == expectedDeleteCnt {
- break
- }
- time.Sleep(10 * time.Millisecond)
- }
+ require.Eventually(t, func() bool { return osStub.DeletesCnt() == expectedDeleteCnt }, time.Second, time.Millisecond)
if useDeleteURL {
require.Equal(t, 1, osStub.DeletesCnt(), "Object hasn't been deleted")
diff --git a/workhorse/internal/redis/keywatcher_test.go b/workhorse/internal/redis/keywatcher_test.go
index 99892bc64b8..7ff5f8204c0 100644
--- a/workhorse/internal/redis/keywatcher_test.go
+++ b/workhorse/internal/redis/keywatcher_test.go
@@ -180,11 +180,7 @@ func TestShutdown(t *testing.T) {
}()
go func() {
- for countWatchers(runnerKey) == 0 {
- time.Sleep(time.Millisecond)
- }
-
- require.Equal(t, 1, countWatchers(runnerKey))
+ require.Eventually(t, func() bool { return countWatchers(runnerKey) == 1 }, 10*time.Second, time.Millisecond)
Shutdown()
wg.Done()
@@ -192,11 +188,7 @@ func TestShutdown(t *testing.T) {
wg.Wait()
- for countWatchers(runnerKey) == 1 {
- time.Sleep(time.Millisecond)
- }
-
- require.Equal(t, 0, countWatchers(runnerKey))
+ require.Eventually(t, func() bool { return countWatchers(runnerKey) == 0 }, 10*time.Second, time.Millisecond)
// Adding a key after the shutdown should result in an immediate response
var val WatchKeyStatus
diff --git a/workhorse/internal/upload/accelerate.go b/workhorse/internal/upload/accelerate.go
index 81f44d33a82..28d3b3dee2e 100644
--- a/workhorse/internal/upload/accelerate.go
+++ b/workhorse/internal/upload/accelerate.go
@@ -17,16 +17,21 @@ type MultipartClaims struct {
jwt.StandardClaims
}
-func Accelerate(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
+// Multipart is a request middleware. If the request has a MIME multipart
+// request body, the middleware will iterate through the multipart parts.
+// When it finds a file part (filename != ""), the middleware will save
+// the file contents to a temporary location and replace the file part
+// with a reference to the temporary location.
+func Multipart(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
return rails.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {
s := &SavedFileTracker{Request: r}
opts, _, err := p.Prepare(a)
if err != nil {
- helper.Fail500(w, r, fmt.Errorf("Accelerate: error preparing file storage options"))
+ helper.Fail500(w, r, fmt.Errorf("Multipart: error preparing file storage options"))
return
}
- HandleFileUploads(w, r, h, a, s, opts)
+ InterceptMultipartFiles(w, r, h, a, s, opts)
}, "/authorize")
}
diff --git a/workhorse/internal/upload/body_uploader.go b/workhorse/internal/upload/body_uploader.go
index 4849d9bae75..6c53bd9241b 100644
--- a/workhorse/internal/upload/body_uploader.go
+++ b/workhorse/internal/upload/body_uploader.go
@@ -16,16 +16,23 @@ type PreAuthorizer interface {
PreAuthorizeHandler(next api.HandleFunc, suffix string) http.Handler
}
-// Verifier allows to check an upload before sending it to rails
+// Verifier is an optional pluggable behavior for upload paths. If
+// Verify() returns an error, Workhorse will return an error response to
+// the client instead of propagating the request to Rails. The motivating
+// use case is Git LFS, where Workhorse checks the size and SHA256
+// checksum of the uploaded file.
type Verifier interface {
- // Verify can abort the upload returning an error
+ // Verify can abort the upload by returning an error
Verify(handler *filestore.FileHandler) error
}
-// Preparer allows to customize BodyUploader configuration
+// Preparer is a pluggable behavior that interprets a Rails API response
+// and either tells Workhorse how to handle the upload, via the
+// SaveFileOpts and Verifier, or it rejects the request by returning a
+// non-nil error. Its intended use is to make sure the upload gets stored
+// in the right location: either a local directory, or one of several
+// supported object storage backends.
type Preparer interface {
- // Prepare converts api.Response into a *SaveFileOpts, it can optionally return an Verifier that will be
- // invoked after the real upload, before the finalization with rails
Prepare(a *api.Response) (*filestore.SaveFileOpts, Verifier, error)
}
@@ -36,26 +43,26 @@ func (s *DefaultPreparer) Prepare(a *api.Response) (*filestore.SaveFileOpts, Ver
return opts, nil, err
}
-// BodyUploader is an http.Handler that perform a pre authorization call to rails before hijacking the request body and
-// uploading it.
-// Providing an Preparer allows to customize the upload process
-func BodyUploader(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
+// RequestBody is a request middleware. It will store the request body to
+// a location by determined an api.Response value. It then forwards the
+// request to gitlab-rails without the original request body.
+func RequestBody(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
return rails.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {
opts, verifier, err := p.Prepare(a)
if err != nil {
- helper.Fail500(w, r, fmt.Errorf("BodyUploader: preparation failed: %v", err))
+ helper.Fail500(w, r, fmt.Errorf("RequestBody: preparation failed: %v", err))
return
}
fh, err := filestore.SaveFileFromReader(r.Context(), r.Body, r.ContentLength, opts)
if err != nil {
- helper.Fail500(w, r, fmt.Errorf("BodyUploader: upload failed: %v", err))
+ helper.Fail500(w, r, fmt.Errorf("RequestBody: upload failed: %v", err))
return
}
if verifier != nil {
if err := verifier.Verify(fh); err != nil {
- helper.Fail500(w, r, fmt.Errorf("BodyUploader: verification failed: %v", err))
+ helper.Fail500(w, r, fmt.Errorf("RequestBody: verification failed: %v", err))
return
}
}
@@ -63,7 +70,7 @@ func BodyUploader(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler
data := url.Values{}
fields, err := fh.GitLabFinalizeFields("file")
if err != nil {
- helper.Fail500(w, r, fmt.Errorf("BodyUploader: finalize fields failed: %v", err))
+ helper.Fail500(w, r, fmt.Errorf("RequestBody: finalize fields failed: %v", err))
return
}
@@ -80,7 +87,7 @@ func BodyUploader(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler
sft := SavedFileTracker{Request: r}
sft.Track("file", fh.LocalPath)
if err := sft.Finalize(r.Context()); err != nil {
- helper.Fail500(w, r, fmt.Errorf("BodyUploader: finalize failed: %v", err))
+ helper.Fail500(w, r, fmt.Errorf("RequestBody: finalize failed: %v", err))
return
}
diff --git a/workhorse/internal/upload/body_uploader_test.go b/workhorse/internal/upload/body_uploader_test.go
index aeb366616ca..b3d561ac131 100644
--- a/workhorse/internal/upload/body_uploader_test.go
+++ b/workhorse/internal/upload/body_uploader_test.go
@@ -24,7 +24,7 @@ const (
fileLen = len(fileContent)
)
-func TestBodyUploader(t *testing.T) {
+func TestRequestBody(t *testing.T) {
testhelper.ConfigureSecret()
body := strings.NewReader(fileContent)
@@ -38,7 +38,7 @@ func TestBodyUploader(t *testing.T) {
require.Equal(t, fileContent, string(uploadEcho))
}
-func TestBodyUploaderCustomPreparer(t *testing.T) {
+func TestRequestBodyCustomPreparer(t *testing.T) {
body := strings.NewReader(fileContent)
resp := testUpload(&rails{}, &alwaysLocalPreparer{}, echoProxy(t, fileLen), body)
@@ -49,7 +49,7 @@ func TestBodyUploaderCustomPreparer(t *testing.T) {
require.Equal(t, fileContent, string(uploadEcho))
}
-func TestBodyUploaderCustomVerifier(t *testing.T) {
+func TestRequestBodyCustomVerifier(t *testing.T) {
body := strings.NewReader(fileContent)
verifier := &mockVerifier{}
@@ -62,11 +62,11 @@ func TestBodyUploaderCustomVerifier(t *testing.T) {
require.True(t, verifier.invoked, "Verifier.Verify not invoked")
}
-func TestBodyUploaderAuthorizationFailure(t *testing.T) {
+func TestRequestBodyAuthorizationFailure(t *testing.T) {
testNoProxyInvocation(t, http.StatusUnauthorized, &rails{unauthorized: true}, &alwaysLocalPreparer{})
}
-func TestBodyUploaderErrors(t *testing.T) {
+func TestRequestBodyErrors(t *testing.T) {
tests := []struct {
name string
preparer *alwaysLocalPreparer
@@ -95,7 +95,7 @@ func testUpload(auth PreAuthorizer, preparer Preparer, proxy http.Handler, body
req := httptest.NewRequest("POST", "http://example.com/upload", body)
w := httptest.NewRecorder()
- BodyUploader(auth, proxy, preparer).ServeHTTP(w, req)
+ RequestBody(auth, proxy, preparer).ServeHTTP(w, req)
return w.Result()
}
diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go
index b9324ac8b7b..bbabe840ef5 100644
--- a/workhorse/internal/upload/rewrite.go
+++ b/workhorse/internal/upload/rewrite.go
@@ -6,8 +6,10 @@ import (
"fmt"
"io"
"io/ioutil"
+ "mime"
"mime/multipart"
"net/http"
+ "net/textproto"
"os"
"path/filepath"
"strings"
@@ -95,7 +97,8 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
return err
}
- name := p.FormName()
+ name, filename := parseAndNormalizeContentDisposition(p.Header)
+
if name == "" {
continue
}
@@ -104,7 +107,7 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
return ErrInjectedClientParam
}
- if p.FileName() != "" {
+ if filename != "" {
err = rew.handleFilePart(r.Context(), name, p, opts)
} else {
err = rew.copyPart(r.Context(), name, p)
@@ -118,6 +121,13 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
return nil
}
+func parseAndNormalizeContentDisposition(header textproto.MIMEHeader) (string, string) {
+ const key = "Content-Disposition"
+ mediaType, params, _ := mime.ParseMediaType(header.Get(key))
+ header.Set(key, mime.FormatMediaType(mediaType, params))
+ return params["name"], params["filename"]
+}
+
func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipart.Part, opts *filestore.SaveFileOpts) error {
if rew.filter.Count() >= maxFilesAllowed {
return ErrTooManyFilesUploaded
diff --git a/workhorse/internal/upload/rewrite_test.go b/workhorse/internal/upload/rewrite_test.go
index e3f33a02489..145f62ee910 100644
--- a/workhorse/internal/upload/rewrite_test.go
+++ b/workhorse/internal/upload/rewrite_test.go
@@ -1,6 +1,7 @@
package upload
import (
+ "net/textproto"
"os"
"runtime"
"testing"
@@ -54,3 +55,83 @@ func TestImageTypeRecongition(t *testing.T) {
})
}
}
+
+func TestParseAndNormalizeContentDisposition(t *testing.T) {
+ tests := []struct {
+ desc string
+ header string
+ name string
+ filename string
+ sanitizedHeader string
+ }{
+ {
+ desc: "without content disposition",
+ header: "",
+ name: "",
+ filename: "",
+ sanitizedHeader: "",
+ }, {
+ desc: "content disposition without filename",
+ header: `form-data; name="filename"`,
+ name: "filename",
+ filename: "",
+ sanitizedHeader: `form-data; name=filename`,
+ }, {
+ desc: "with filename",
+ header: `form-data; name="file"; filename=foobar`,
+ name: "file",
+ filename: "foobar",
+ sanitizedHeader: `form-data; filename=foobar; name=file`,
+ }, {
+ desc: "with filename*",
+ header: `form-data; name="file"; filename*=UTF-8''bar`,
+ name: "file",
+ filename: "bar",
+ sanitizedHeader: `form-data; filename=bar; name=file`,
+ }, {
+ desc: "filename and filename*",
+ header: `form-data; name="file"; filename=foobar; filename*=UTF-8''bar`,
+ name: "file",
+ filename: "bar",
+ sanitizedHeader: `form-data; filename=bar; name=file`,
+ }, {
+ desc: "with empty filename",
+ header: `form-data; name="file"; filename=""`,
+ name: "file",
+ filename: "",
+ sanitizedHeader: `form-data; filename=""; name=file`,
+ }, {
+ desc: "with complex filename*",
+ header: `form-data; name="file"; filename*=UTF-8''viel%20Spa%C3%9F`,
+ name: "file",
+ filename: "viel Spaß",
+ sanitizedHeader: `form-data; filename*=utf-8''viel%20Spa%C3%9F; name=file`,
+ }, {
+ desc: "with unsupported charset",
+ header: `form-data; name="file"; filename*=UTF-16''bar`,
+ name: "file",
+ filename: "",
+ sanitizedHeader: `form-data; name=file`,
+ }, {
+ desc: "with filename and filename* with unsupported charset",
+ header: `form-data; name="file"; filename=foobar; filename*=UTF-16''bar`,
+ name: "file",
+ filename: "foobar",
+ sanitizedHeader: `form-data; filename=foobar; name=file`,
+ },
+ }
+
+ for _, testCase := range tests {
+ t.Run(testCase.desc, func(t *testing.T) {
+ h := make(textproto.MIMEHeader)
+ h.Set("Content-Disposition", testCase.header)
+ h.Set("Content-Type", "application/octet-stream")
+
+ name, filename := parseAndNormalizeContentDisposition(h)
+
+ require.Equal(t, testCase.name, name)
+ require.Equal(t, testCase.filename, filename)
+ require.Equal(t, testCase.sanitizedHeader, h.Get("Content-Disposition"))
+ })
+ }
+}
diff --git a/workhorse/internal/upload/skip_rails_authorizer.go b/workhorse/internal/upload/skip_rails_authorizer.go
index c8055a673eb..e74048fb6e3 100644
--- a/workhorse/internal/upload/skip_rails_authorizer.go
+++ b/workhorse/internal/upload/skip_rails_authorizer.go
@@ -6,15 +6,15 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
)
-// SkipRailsAuthorizer implements a fake PreAuthorizer that do not calls rails API and
-// authorize each call as a local only upload to TempPath
+// SkipRailsAuthorizer implements a fake PreAuthorizer that does not call
+// the gitlab-rails API. It must be fast because it gets called on each
+// request proxied to Rails.
type SkipRailsAuthorizer struct {
- // TempPath is the temporary path for a local only upload
+ // TempPath is a directory where workhorse can store files that can later
+ // be accessed by gitlab-rails.
TempPath string
}
-// PreAuthorizeHandler implements PreAuthorizer. It always grant the upload.
-// The fake API response contains only TempPath
func (l *SkipRailsAuthorizer) PreAuthorizeHandler(next api.HandleFunc, _ string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next(w, r, &api.Response{TempPath: l.TempPath})
diff --git a/workhorse/internal/upload/uploads.go b/workhorse/internal/upload/uploads.go
index b408d260379..1806e7563ce 100644
--- a/workhorse/internal/upload/uploads.go
+++ b/workhorse/internal/upload/uploads.go
@@ -15,7 +15,8 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts"
)
-// These methods are allowed to have thread-unsafe implementations.
+// MultipartFormProcessor abstracts away implementation differences
+// between generic MIME multipart file uploads and CI artifact uploads.
type MultipartFormProcessor interface {
ProcessFile(ctx context.Context, formName string, file *filestore.FileHandler, writer *multipart.Writer) error
ProcessField(ctx context.Context, formName string, writer *multipart.Writer) error
@@ -24,7 +25,10 @@ type MultipartFormProcessor interface {
Count() int
}
-func HandleFileUploads(w http.ResponseWriter, r *http.Request, h http.Handler, preauth *api.Response, filter MultipartFormProcessor, opts *filestore.SaveFileOpts) {
+// InterceptMultipartFiles is the core of the implementation of
+// Multipart. Because it is also used for CI artifact uploads it is a
+// public function.
+func InterceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Handler, preauth *api.Response, filter MultipartFormProcessor, opts *filestore.SaveFileOpts) {
var body bytes.Buffer
writer := multipart.NewWriter(&body)
defer writer.Close()
diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go
index 7c22b3b4e28..f262bf94b08 100644
--- a/workhorse/internal/upload/uploads_test.go
+++ b/workhorse/internal/upload/uploads_test.go
@@ -1,13 +1,16 @@
package upload
import (
+ "bufio"
"bytes"
"context"
"fmt"
+ "io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
+ "net/textproto"
"os"
"regexp"
"strconv"
@@ -75,7 +78,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, handler, apiResponse, nil, opts)
+ InterceptMultipartFiles(response, httpRequest, handler, apiResponse, nil, opts)
require.Equal(t, 202, response.Code)
require.Equal(t, "RESPONSE", response.Body.String(), "response body")
@@ -146,7 +149,7 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 202, response.Code)
cancel() // this will trigger an async cleanup
@@ -215,7 +218,7 @@ func TestUploadHandlerDetectingInjectedMultiPartData(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, test.response, response.Code)
cancel() // this will trigger an async cleanup
@@ -245,7 +248,7 @@ func TestUploadProcessingField(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 500, response.Code)
}
@@ -276,7 +279,7 @@ func TestUploadingMultipleFiles(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 400, response.Code)
require.Equal(t, "upload request contains more than 10 files\n", response.Body.String())
@@ -332,7 +335,7 @@ func TestUploadProcessingFile(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 200, response.Code)
})
@@ -378,12 +381,95 @@ func TestInvalidFileNames(t *testing.T) {
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
+ InterceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
require.Equal(t, testCase.code, response.Code)
require.Equal(t, testCase.expectedPrefix, opts.TempFilePrefix)
}
}
+func TestContentDispositionRewrite(t *testing.T) {
+ testhelper.ConfigureSecret()
+
+ tempPath, err := ioutil.TempDir("", "uploads")
+ require.NoError(t, err)
+ defer os.RemoveAll(tempPath)
+
+ tests := []struct {
+ desc string
+ header string
+ code int
+ sanitizedHeader string
+ }{
+ {
+ desc: "with name",
+ header: `form-data; name="foo"`,
+ code: 200,
+ sanitizedHeader: `form-data; name=foo`,
+ },
+ {
+ desc: "with name and name*",
+ header: `form-data; name="foo"; name*=UTF-8''bar`,
+ code: 200,
+ sanitizedHeader: `form-data; name=bar`,
+ },
+ {
+ desc: "with name and invalid name*",
+ header: `form-data; name="foo"; name*=UTF-16''bar`,
+ code: 200,
+ sanitizedHeader: `form-data; name=foo`,
+ },
+ }
+
+ for _, testCase := range tests {
+ t.Run(testCase.desc, func(t *testing.T) {
+ h := make(textproto.MIMEHeader)
+ h.Set("Content-Disposition", testCase.header)
+ h.Set("Content-Type", "application/octet-stream")
+
+ buffer := &bytes.Buffer{}
+ writer := multipart.NewWriter(buffer)
+ file, err := writer.CreatePart(h)
+ require.NoError(t, err)
+ fmt.Fprint(file, "test")
+ writer.Close()
+
+ httpRequest := httptest.NewRequest("POST", "/example", buffer)
+ httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
+
+ var upstreamRequestBuffer bytes.Buffer
+ customHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ r.Write(&upstreamRequestBuffer)
+ })
+
+ response := httptest.NewRecorder()
+ apiResponse := &api.Response{TempPath: tempPath}
+ preparer := &DefaultPreparer{}
+ opts, _, err := preparer.Prepare(apiResponse)
+ require.NoError(t, err)
+
+ InterceptMultipartFiles(response, httpRequest, customHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
+
+ upstreamRequest, err := http.ReadRequest(bufio.NewReader(&upstreamRequestBuffer))
+ require.NoError(t, err)
+
+ reader, err := upstreamRequest.MultipartReader()
+ require.NoError(t, err)
+
+ for i := 0; ; i++ {
+ p, err := reader.NextPart()
+ if err == io.EOF {
+ require.Equal(t, i, 1)
+ break
+ }
+ require.NoError(t, err)
+ require.Equal(t, testCase.sanitizedHeader, p.Header.Get("Content-Disposition"))
+ }
+
+ require.Equal(t, testCase.code, response.Code)
+ })
+ }
+}
+
func TestUploadHandlerRemovingExif(t *testing.T) {
content, err := ioutil.ReadFile("exif/testdata/sample_exif.jpg")
require.NoError(t, err)
@@ -484,7 +570,7 @@ func runUploadTest(t *testing.T, image []byte, filename string, httpCode int, ts
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
- HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ InterceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, httpCode, response.Code)
}
@@ -495,15 +581,9 @@ func newProxy(url string) *proxy.Proxy {
func waitUntilDeleted(t *testing.T, path string) {
var err error
-
- // Poll because the file removal is async
- for i := 0; i < 100; i++ {
+ require.Eventually(t, func() bool {
_, err = os.Stat(path)
- if err != nil {
- break
- }
- time.Sleep(100 * time.Millisecond)
- }
-
+ return err != nil
+ }, 10*time.Second, 10*time.Millisecond)
require.True(t, os.IsNotExist(err), "expected the file to be deleted")
}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 06160702f84..b8089865ffe 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -228,17 +228,17 @@ func configureRoutes(u *upstream) {
preparers := createUploadPreparers(u.Config)
uploadPath := path.Join(u.DocumentRoot, "uploads/tmp")
- uploadAccelerateProxy := upload.Accelerate(&upload.SkipRailsAuthorizer{TempPath: uploadPath}, proxy, preparers.uploads)
- ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", uploadAccelerateProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout)
+ tempfileMultipartProxy := upload.Multipart(&upload.SkipRailsAuthorizer{TempPath: uploadPath}, proxy, preparers.uploads)
+ ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout)
ciAPILongPolling := builds.RegisterHandler(ciAPIProxyQueue, redis.WatchKey, u.APICILongPollingDuration)
- dependencyProxyInjector.SetUploadHandler(upload.BodyUploader(api, signingProxy, preparers.packages))
+ dependencyProxyInjector.SetUploadHandler(upload.RequestBody(api, signingProxy, preparers.packages))
// Serve static files or forward the requests
defaultUpstream := static.ServeExisting(
u.URLPrefix,
staticpages.CacheDisabled,
- static.DeployPage(static.ErrorPagesUnless(u.DevelopmentMode, staticpages.ErrorFormatHTML, uploadAccelerateProxy)),
+ static.DeployPage(static.ErrorPagesUnless(u.DevelopmentMode, staticpages.ErrorFormatHTML, tempfileMultipartProxy)),
)
probeUpstream := static.ErrorPagesUnless(u.DevelopmentMode, staticpages.ErrorFormatJSON, proxy)
healthUpstream := static.ErrorPagesUnless(u.DevelopmentMode, staticpages.ErrorFormatText, proxy)
@@ -248,7 +248,7 @@ func configureRoutes(u *upstream) {
u.route("GET", gitProjectPattern+`info/refs\z`, git.GetInfoRefsHandler(api)),
u.route("POST", gitProjectPattern+`git-upload-pack\z`, contentEncodingHandler(git.UploadPack(api)), withMatcher(isContentType("application/x-git-upload-pack-request"))),
u.route("POST", gitProjectPattern+`git-receive-pack\z`, contentEncodingHandler(git.ReceivePack(api)), withMatcher(isContentType("application/x-git-receive-pack-request"))),
- u.route("PUT", gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`, lfs.PutStore(api, signingProxy, preparers.lfs), withMatcher(isContentType("application/octet-stream"))),
+ u.route("PUT", gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`, upload.RequestBody(api, signingProxy, preparers.lfs), withMatcher(isContentType("application/octet-stream"))),
// CI Artifacts
u.route("POST", apiPattern+`v4/jobs/[0-9]+/artifacts\z`, contentEncodingHandler(artifacts.UploadArtifacts(api, signingProxy, preparers.artifacts))),
@@ -276,56 +276,56 @@ func configureRoutes(u *upstream) {
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56731.
// Maven Artifact Repository
- u.route("PUT", apiProjectPattern+`packages/maven/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/maven/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// Conan Artifact Repository
- u.route("PUT", apiPattern+`v4/packages/conan/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
- u.route("PUT", apiProjectPattern+`packages/conan/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiPattern+`v4/packages/conan/`, upload.RequestBody(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/conan/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// Generic Packages Repository
- u.route("PUT", apiProjectPattern+`packages/generic/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/generic/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// NuGet Artifact Repository
- u.route("PUT", apiProjectPattern+`packages/nuget/`, upload.Accelerate(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/nuget/`, upload.Multipart(api, signingProxy, preparers.packages)),
// PyPI Artifact Repository
- u.route("POST", apiProjectPattern+`packages/pypi`, upload.Accelerate(api, signingProxy, preparers.packages)),
+ u.route("POST", apiProjectPattern+`packages/pypi`, upload.Multipart(api, signingProxy, preparers.packages)),
// Debian Artifact Repository
- u.route("PUT", apiProjectPattern+`packages/debian/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/debian/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// Gem Artifact Repository
- u.route("POST", apiProjectPattern+`packages/rubygems/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("POST", apiProjectPattern+`packages/rubygems/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// Terraform Module Package Repository
- u.route("PUT", apiProjectPattern+`packages/terraform/modules/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/terraform/modules/`, upload.RequestBody(api, signingProxy, preparers.packages)),
// Helm Artifact Repository
- u.route("POST", apiProjectPattern+`packages/helm/api/[^/]+/charts\z`, upload.Accelerate(api, signingProxy, preparers.packages)),
+ u.route("POST", apiProjectPattern+`packages/helm/api/[^/]+/charts\z`, upload.Multipart(api, signingProxy, preparers.packages)),
// We are porting API to disk acceleration
// we need to declare each routes until we have fixed all the routes on the rails codebase.
// Overall status can be seen at https://gitlab.com/groups/gitlab-org/-/epics/1802#current-status
- u.route("POST", apiProjectPattern+`wikis/attachments\z`, uploadAccelerateProxy),
- u.route("POST", apiPattern+`graphql\z`, uploadAccelerateProxy),
- u.route("POST", apiTopicPattern, uploadAccelerateProxy),
- u.route("PUT", apiTopicPattern, uploadAccelerateProxy),
- u.route("POST", apiPattern+`v4/groups/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
- u.route("POST", apiPattern+`v4/projects/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", apiProjectPattern+`wikis/attachments\z`, tempfileMultipartProxy),
+ u.route("POST", apiPattern+`graphql\z`, tempfileMultipartProxy),
+ u.route("POST", apiTopicPattern, tempfileMultipartProxy),
+ u.route("PUT", apiTopicPattern, tempfileMultipartProxy),
+ u.route("POST", apiPattern+`v4/groups/import`, upload.Multipart(api, signingProxy, preparers.uploads)),
+ u.route("POST", apiPattern+`v4/projects/import`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Project Import via UI upload acceleration
- u.route("POST", importPattern+`gitlab_project`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", importPattern+`gitlab_project`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Group Import via UI upload acceleration
- u.route("POST", importPattern+`gitlab_group`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", importPattern+`gitlab_group`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Metric image upload
- u.route("POST", apiProjectPattern+`issues/[0-9]+/metric_images\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", apiProjectPattern+`issues/[0-9]+/metric_images\z`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Requirements Import via UI upload acceleration
- u.route("POST", projectPattern+`requirements_management/requirements/import_csv`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", projectPattern+`requirements_management/requirements/import_csv`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Uploads via API
- u.route("POST", apiProjectPattern+`uploads\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", apiProjectPattern+`uploads\z`, upload.Multipart(api, signingProxy, preparers.uploads)),
// Explicitly proxy API requests
u.route("", apiPattern, proxy),
@@ -343,9 +343,9 @@ func configureRoutes(u *upstream) {
),
// Uploads
- u.route("POST", projectPattern+`uploads\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
- u.route("POST", snippetUploadPattern, upload.Accelerate(api, signingProxy, preparers.uploads)),
- u.route("POST", userUploadPattern, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", projectPattern+`uploads\z`, upload.Multipart(api, signingProxy, preparers.uploads)),
+ u.route("POST", snippetUploadPattern, upload.Multipart(api, signingProxy, preparers.uploads)),
+ u.route("POST", userUploadPattern, upload.Multipart(api, signingProxy, preparers.uploads)),
// health checks don't intercept errors and go straight to rails
// TODO: We should probably not return a HTML deploy page?
@@ -390,6 +390,7 @@ func configureRoutes(u *upstream) {
u.route("", "^/api/v4/geo_nodes", defaultUpstream),
u.route("", "^/api/v4/geo_replication", defaultUpstream),
u.route("", "^/api/v4/geo/proxy_git_ssh", defaultUpstream),
+ u.route("", "^/api/v4/geo/graphql", defaultUpstream),
// Internal API routes
u.route("", "^/api/v4/internal", defaultUpstream),
diff --git a/yarn.lock b/yarn.lock
index 51cc427e10f..dc2080f9bfb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,25 @@
# yarn lockfile v1
+"@apollo/client@^3.2.5", "@apollo/client@^3.3.11":
+ version "3.3.11"
+ resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.3.11.tgz#125051405e83dc899d471d43b79fd6045d92a802"
+ integrity sha512-54+D5FB6RJlQ+g37f432gaexnyvDsG5X6L9VO5kqN54HJlbF8hCf/8CXtAQEHCWodAwZhy6kOLp2RM96829q3A==
+ dependencies:
+ "@graphql-typed-document-node/core" "^3.0.0"
+ "@types/zen-observable" "^0.8.0"
+ "@wry/context" "^0.5.2"
+ "@wry/equality" "^0.3.0"
+ fast-json-stable-stringify "^2.0.0"
+ graphql-tag "^2.12.0"
+ hoist-non-react-statics "^3.3.2"
+ optimism "^0.14.0"
+ prop-types "^15.7.2"
+ symbol-observable "^2.0.0"
+ ts-invariant "^0.6.0"
+ tslib "^1.10.0"
+ zen-observable "^0.8.14"
+
"@babel/code-frame@7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
@@ -9,32 +28,39 @@
dependencies:
"@babel/highlight" "^7.10.4"
-"@babel/code-frame@7.16.0", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.14.5":
+"@babel/code-frame@7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==
dependencies:
"@babel/highlight" "^7.16.0"
-"@babel/compat-data@^7.10.1", "@babel/compat-data@^7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
- integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
-
-"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.10.1", "@babel/core@^7.7.5":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8"
- integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==
- dependencies:
- "@babel/code-frame" "^7.14.5"
- "@babel/generator" "^7.15.0"
- "@babel/helper-compilation-targets" "^7.15.0"
- "@babel/helper-module-transforms" "^7.15.0"
- "@babel/helpers" "^7.14.8"
- "@babel/parser" "^7.15.0"
- "@babel/template" "^7.14.5"
- "@babel/traverse" "^7.15.0"
- "@babel/types" "^7.15.0"
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
+ integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
+ dependencies:
+ "@babel/highlight" "^7.16.7"
+
+"@babel/compat-data@^7.10.1", "@babel/compat-data@^7.16.4":
+ version "7.16.8"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60"
+ integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==
+
+"@babel/core@^7.1.0", "@babel/core@^7.10.1", "@babel/core@^7.7.5":
+ version "7.16.12"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784"
+ integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.16.8"
+ "@babel/helper-compilation-targets" "^7.16.7"
+ "@babel/helper-module-transforms" "^7.16.7"
+ "@babel/helpers" "^7.16.7"
+ "@babel/parser" "^7.16.12"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.10"
+ "@babel/types" "^7.16.8"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
@@ -42,12 +68,12 @@
semver "^6.3.0"
source-map "^0.5.0"
-"@babel/generator@^7.15.0", "@babel/generator@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0"
- integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==
+"@babel/generator@^7.15.4", "@babel/generator@^7.16.8":
+ version "7.16.8"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe"
+ integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.8"
jsesc "^2.5.1"
source-map "^0.5.0"
@@ -66,14 +92,14 @@
"@babel/helper-explode-assignable-expression" "^7.10.1"
"@babel/types" "^7.10.1"
-"@babel/helper-compilation-targets@^7.10.2", "@babel/helper-compilation-targets@^7.15.0":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9"
- integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==
+"@babel/helper-compilation-targets@^7.10.2", "@babel/helper-compilation-targets@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b"
+ integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==
dependencies:
- "@babel/compat-data" "^7.15.0"
- "@babel/helper-validator-option" "^7.14.5"
- browserslist "^4.16.6"
+ "@babel/compat-data" "^7.16.4"
+ "@babel/helper-validator-option" "^7.16.7"
+ browserslist "^4.17.5"
semver "^6.3.0"
"@babel/helper-create-class-features-plugin@^7.10.1", "@babel/helper-create-class-features-plugin@^7.14.5":
@@ -106,6 +132,13 @@
"@babel/types" "^7.10.1"
lodash "^4.17.13"
+"@babel/helper-environment-visitor@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7"
+ integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-explode-assignable-expression@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.1.tgz#e9d76305ee1162ca467357ae25df94f179af2b7e"
@@ -114,28 +147,28 @@
"@babel/traverse" "^7.10.1"
"@babel/types" "^7.10.1"
-"@babel/helper-function-name@^7.10.1", "@babel/helper-function-name@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc"
- integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==
+"@babel/helper-function-name@^7.10.1", "@babel/helper-function-name@^7.15.4", "@babel/helper-function-name@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f"
+ integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
dependencies:
- "@babel/helper-get-function-arity" "^7.15.4"
- "@babel/template" "^7.15.4"
- "@babel/types" "^7.15.4"
+ "@babel/helper-get-function-arity" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/types" "^7.16.7"
-"@babel/helper-get-function-arity@^7.10.1", "@babel/helper-get-function-arity@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b"
- integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==
+"@babel/helper-get-function-arity@^7.10.1", "@babel/helper-get-function-arity@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
+ integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.7"
-"@babel/helper-hoist-variables@^7.10.1", "@babel/helper-hoist-variables@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df"
- integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==
+"@babel/helper-hoist-variables@^7.10.1", "@babel/helper-hoist-variables@^7.15.4", "@babel/helper-hoist-variables@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246"
+ integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.7"
"@babel/helper-member-expression-to-functions@^7.15.4":
version "7.15.4"
@@ -144,26 +177,26 @@
dependencies:
"@babel/types" "^7.15.4"
-"@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.10.1", "@babel/helper-module-imports@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f"
- integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==
+"@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.10.1", "@babel/helper-module-imports@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437"
+ integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.7"
-"@babel/helper-module-transforms@^7.10.1", "@babel/helper-module-transforms@^7.15.0":
- version "7.15.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226"
- integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw==
+"@babel/helper-module-transforms@^7.10.1", "@babel/helper-module-transforms@^7.15.0", "@babel/helper-module-transforms@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41"
+ integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==
dependencies:
- "@babel/helper-module-imports" "^7.15.4"
- "@babel/helper-replace-supers" "^7.15.4"
- "@babel/helper-simple-access" "^7.15.4"
- "@babel/helper-split-export-declaration" "^7.15.4"
- "@babel/helper-validator-identifier" "^7.15.7"
- "@babel/template" "^7.15.4"
- "@babel/traverse" "^7.15.4"
- "@babel/types" "^7.15.6"
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-simple-access" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/helper-validator-identifier" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
"@babel/helper-optimise-call-expression@^7.10.1", "@babel/helper-optimise-call-expression@^7.15.4":
version "7.15.4"
@@ -205,12 +238,12 @@
"@babel/traverse" "^7.15.4"
"@babel/types" "^7.15.4"
-"@babel/helper-simple-access@^7.14.8", "@babel/helper-simple-access@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b"
- integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==
+"@babel/helper-simple-access@^7.14.8", "@babel/helper-simple-access@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7"
+ integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.7"
"@babel/helper-skip-transparent-expression-wrappers@^7.14.5":
version "7.15.4"
@@ -219,22 +252,22 @@
dependencies:
"@babel/types" "^7.15.4"
-"@babel/helper-split-export-declaration@^7.10.1", "@babel/helper-split-export-declaration@^7.15.4":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257"
- integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==
+"@babel/helper-split-export-declaration@^7.10.1", "@babel/helper-split-export-declaration@^7.15.4", "@babel/helper-split-export-declaration@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b"
+ integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
dependencies:
- "@babel/types" "^7.15.4"
+ "@babel/types" "^7.16.7"
-"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7":
- version "7.15.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
- integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
+"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
+ integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
-"@babel/helper-validator-option@^7.14.5":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
- integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
+"@babel/helper-validator-option@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
+ integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==
"@babel/helper-wrap-function@^7.10.1":
version "7.10.1"
@@ -246,29 +279,34 @@
"@babel/traverse" "^7.10.1"
"@babel/types" "^7.10.1"
-"@babel/helpers@^7.14.8":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43"
- integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==
+"@babel/helpers@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc"
+ integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==
dependencies:
- "@babel/template" "^7.15.4"
- "@babel/traverse" "^7.15.4"
- "@babel/types" "^7.15.4"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
-"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0":
- version "7.16.0"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a"
- integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==
+"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0", "@babel/highlight@^7.16.7":
+ version "7.16.10"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
+ integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
dependencies:
- "@babel/helper-validator-identifier" "^7.15.7"
+ "@babel/helper-validator-identifier" "^7.16.7"
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@7.15.8", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.15.0", "@babel/parser@^7.15.4":
+"@babel/parser@7.15.8":
version "7.15.8"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016"
integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7":
+ version "7.16.12"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6"
+ integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==
+
"@babel/plugin-proposal-async-generator-functions@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.1.tgz#6911af5ba2e615c4ff3c497fe2f47b35bf6d7e55"
@@ -791,7 +829,7 @@
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.13.10", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.8.4":
version "7.14.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
@@ -803,16 +841,16 @@
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.10.2.tgz#49dbbadcbc4b199df064d7d8b3e21c915b84abdb"
integrity sha512-PNQuj9oQH6BL/3l9iiL8hJLQwX14woA2/FHcPtNIZAc7IgFZYJdtMBMXiy4xcefADHTSvoBnmc2AybrHRW1IKQ==
-"@babel/template@^7.10.1", "@babel/template@^7.14.5", "@babel/template@^7.15.4", "@babel/template@^7.3.3":
- version "7.15.4"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
- integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==
+"@babel/template@^7.10.1", "@babel/template@^7.16.7", "@babel/template@^7.3.3":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
+ integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
dependencies:
- "@babel/code-frame" "^7.14.5"
- "@babel/parser" "^7.15.4"
- "@babel/types" "^7.15.4"
+ "@babel/code-frame" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/types" "^7.16.7"
-"@babel/traverse@7.15.4", "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.0", "@babel/traverse@^7.15.4":
+"@babel/traverse@7.15.4":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d"
integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==
@@ -827,7 +865,23 @@
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@7.15.6", "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.15.0", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.4", "@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7":
+ version "7.16.10"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f"
+ integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.16.8"
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-function-name" "^7.16.7"
+ "@babel/helper-hoist-variables" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/parser" "^7.16.10"
+ "@babel/types" "^7.16.8"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@7.15.6":
version "7.15.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
@@ -835,6 +889,14 @@
"@babel/helper-validator-identifier" "^7.14.9"
to-fast-properties "^2.0.0"
+"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.15.4", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+ version "7.16.8"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1"
+ integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ to-fast-properties "^2.0.0"
+
"@bcoe/v8-coverage@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@@ -853,6 +915,11 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
+"@discoveryjs/json-ext@^0.5.0":
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
+ integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==
+
"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d"
@@ -905,34 +972,29 @@
resolved "https://registry.yarnpkg.com/@gitlab/favicon-overlay/-/favicon-overlay-2.0.0.tgz#2f32d0b6a4d5b8ac44e2927083d9ab478a78c984"
integrity sha512-GNcORxXJ98LVGzOT9dDYKfbheqH6lNgPDD72lyXRnQIH7CjgGyos8i17aSBPq1f4s3zF3PyedFiAR4YEZbva2Q==
-"@gitlab/stylelint-config@2.6.0":
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-2.6.0.tgz#8c7d6c9d8e0a9a30eda98a2076dee222b88c840b"
- integrity sha512-9rBMsvQg2IX7FRNtp+ajRk4Map2kBlkepvc/0CTfd84oLX8zadRqG+J62/Ox285vLnihsVM13SGOD7BWvrvQzw==
+"@gitlab/stylelint-config@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-4.0.0.tgz#d24646592908d92dce35aaa8e7bea66fd53e4160"
+ integrity sha512-5avbb8XQLdnL/vdrxf9jvdPl/HPaXnI7Y/fArOHe1uMpgcBoBWUKmon15+lHJ4MgURsGuYSiM2FIgArDSylR4g==
dependencies:
- stylelint "13.9.0"
- stylelint-declaration-strict-value "1.7.7"
- stylelint-scss "3.18.0"
-
-"@gitlab/svgs@2.2.0":
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.2.0.tgz#95cf58d6ae634d535145159f08f5cff6241d4013"
- integrity sha512-mCwR3KfNPsxRoojtTjMIZwdd4FFlBh5DlR9AeodP+7+k8rILdWGYxTZbJMPNXoPbZx16R94nG8c5bR7toD4QBw==
+ postcss-scss "4.0.3"
+ stylelint-declaration-strict-value "1.8.0"
+ stylelint-scss "4.1.0"
-"@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/svgs@2.5.0":
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.5.0.tgz#e0569916fa858462b1801cc90ef8dd9706a12e96"
+ integrity sha512-cH/EBs//wdkH6kG+kDpvRCIl63/A8JgjAhBJ+ZWucPgtNCDD6x6RDMGdQrxSqhYwcCKDoLStfcxmblBkuiSRXQ==
-"@gitlab/ui@32.68.0":
- version "32.68.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.68.0.tgz#f7c4ebd2f9b3635db16589b289fdda149ca1cbcc"
- integrity sha512-rTd0+bNBjPvL1ZMfGEHNoBSZwumu6DMQLBwtPhUaj288nAB4K2xibdhFmsm1yqhnW04VNLyBs9FqKdXRQqFttA==
+"@gitlab/ui@36.6.0":
+ version "36.6.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-36.6.0.tgz#902ec76623de3b46d450fbe2074d00a39a58d61c"
+ integrity sha512-hHuknkt4KTQVPEA8t+Cg29hocqMUv4bYfVH7Hinj3qFaIK32zMKUGQ2P/w5BG8R+cP9PTjw+WxNYc4WpRPpcUw==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"
copy-to-clipboard "^3.0.8"
- dompurify "^2.3.4"
+ dompurify "^2.3.5"
echarts "^5.2.1"
highlight.js "^10.6.0"
iframe-resizer "^4.3.2"
@@ -1106,6 +1168,11 @@
tslib "~2.3.0"
value-or-promise "1.0.11"
+"@graphql-typed-document-node/core@^3.0.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950"
+ integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==
+
"@humanwhocodes/config-array@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
@@ -1369,15 +1436,15 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590"
integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==
-"@rails/actioncable@6.1.4-1":
- version "6.1.4-1"
- resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.4-1.tgz#69982e7f352d732f71fda0cc01b7ba8269c9945b"
- integrity sha512-b6sLoMop3gX22Wm2P5LPpKcZGwsf1ZoAGS+g1HrTrdlsZ/ENOKIBiSNnHOJajHwcYlF0TefBs7e7jIYZHVYihQ==
+"@rails/actioncable@6.1.4-6":
+ version "6.1.4-6"
+ resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.4-6.tgz#22dd0f60e634f237f2a19d031f4e7afa26a924b4"
+ integrity sha512-cGwo5AWlEg6Q5JeUl2r8cmgaSlJtgR9BOOGF7Yb1PyKOinuWod6PW6UeQLgXf+n2MNiWz+yqldb1m3+Aun/2lg==
-"@rails/ujs@6.1.4-1":
- version "6.1.4-1"
- resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4-1.tgz#37507fe288a1c7c3a593602aa4dea42e5cb5797f"
- integrity sha512-Fewm2wHk1n6Kf4E86dzzHDJOFg4EWcSHH3FsMEGs59bTdmf7099mjkOssOQtBqju4R39iaAOQNui7r8P+Q5Dgg==
+"@rails/ujs@6.1.4-6":
+ version "6.1.4-6"
+ resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4-6.tgz#244520a1580b5791cebc81471978bc6b3c8966c0"
+ integrity sha512-j2ejw0ShVHiDWtq1Yv1PGX/GFCDiXX+5YiUY2Z17eeMJhQkxXeg3maQZkkT5OT/YBOI+jiWqtp03GM1Hdp/arA==
"@sentry/browser@5.30.0":
version "5.30.0"
@@ -1455,21 +1522,6 @@
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.60.tgz#2043877fabb7eb986fcb61b67ee480afbb29f4f0"
integrity sha512-T+MvM8SUF7daA279hyQgwmva3J5LvPqwgQ/mWwxdVshehOQIPLUd310I0c6x6nZ0F/x4UjDWgRWzAqy6NLwV1w==
-"@stylelint/postcss-css-in-js@^0.37.2":
- version "0.37.2"
- resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz#7e5a84ad181f4234a2480803422a47b8749af3d2"
- integrity sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==
- dependencies:
- "@babel/core" ">=7.9.0"
-
-"@stylelint/postcss-markdown@^0.36.2":
- version "0.36.2"
- resolved "https://registry.yarnpkg.com/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz#0a540c4692f8dcdfc13c8e352c17e7bfee2bb391"
- integrity sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ==
- dependencies:
- remark "^13.0.0"
- unist-util-find-all-after "^3.0.2"
-
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
@@ -1490,25 +1542,25 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@tiptap/core@^2.0.0-beta.160":
- version "2.0.0-beta.160"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.160.tgz#98f0625dc12a3498c6bbe2ae4aed4667b62a2a11"
- integrity sha512-oKtx4vn4ew+mCH3kiBeD4UdPa5IVLLBCuSgGNnqdoIuRv397uh5SwOz7TiL5A+vTa6yke0xLSKxZ+QNR2qfVXg==
+"@tiptap/core@^2.0.0-beta.171":
+ version "2.0.0-beta.171"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.171.tgz#e681964c443383b81d2638c51fc3bbfda034a4fb"
+ integrity sha512-4CdJfcchmBOFooWPBMJ7AxJISeTstMFriQv0RyReMt0Dpef/c9UoU+NkKLwwv5VRUX0M8dL5SzEhkB8wIODqlA==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
"@types/prosemirror-keymap" "^1.0.4"
- "@types/prosemirror-model" "^1.13.2"
+ "@types/prosemirror-model" "^1.16.0"
"@types/prosemirror-schema-list" "^1.0.3"
"@types/prosemirror-state" "^1.2.8"
"@types/prosemirror-transform" "^1.1.5"
- "@types/prosemirror-view" "^1.19.2"
- prosemirror-commands "^1.1.12"
+ "@types/prosemirror-view" "^1.23.1"
+ prosemirror-commands "^1.2.1"
prosemirror-keymap "^1.1.5"
prosemirror-model "^1.16.1"
prosemirror-schema-list "^1.1.6"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.3"
- prosemirror-view "^1.23.5"
+ prosemirror-view "^1.23.6"
"@tiptap/extension-blockquote@^2.0.0-beta.26":
version "2.0.0-beta.26"
@@ -1520,13 +1572,13 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.25.tgz#ec19e7c862d25bae49609c5d6a873f372c506dee"
integrity sha512-ZNdgFYDxKo8lAp0Pqzu45I0JH3ah8/X5TCYg9zNg3QwLUFT16g2LlWDMUDGT5pH9aXxgtFaEdoVacu0EyhlPnQ==
-"@tiptap/extension-bubble-menu@^2.0.0-beta.54":
- version "2.0.0-beta.54"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.54.tgz#90ac838cb7899317207037abb74ed2f68528bd22"
- integrity sha512-jSvNy+ZVHIzEvf8BY/pLpir7CB4lWL4RNUWLT6YMmGCzdzYJK3RZ6Qp0Yoo7UMTjA5JDGn3Ax1lDj4qcsoXwzA==
+"@tiptap/extension-bubble-menu@^2.0.0-beta.55":
+ version "2.0.0-beta.55"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.55.tgz#a26ad892cea6af9eeada22235701b06d0921af48"
+ integrity sha512-v32/QnwwRbepdbrho8mTYru1/XNW/rJi3Mjrgo3rrIs67R86aEPmhmdzD3QEQUJhAJkduuwdw8zElmVWqIJQ9w==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.5"
+ prosemirror-view "^1.23.6"
tippy.js "^6.3.7"
"@tiptap/extension-bullet-list@^2.0.0-beta.26":
@@ -1534,22 +1586,22 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.26.tgz#b42126d2d984c04041b14037e8d3ec1bcf16e7ec"
integrity sha512-1n5HV8gY1tLjPk4x48nva6SZlFHoPlRfF6pqSu9JcJxPO7FUSPxUokuz4swYNe0LRrtykfyNz44dUcxKVhoFow==
-"@tiptap/extension-code-block-lowlight@2.0.0-beta.63":
- version "2.0.0-beta.63"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.63.tgz#5d99e7693c2181d15f6599b4a20aa386efdc9c00"
- integrity sha512-Eam+j5YO7ulytOL+NMIhoEPZsAQag9hL19q17ctgl1k1yPwdLuUtU0lkIr0P+qxSzWXUGWX6q/nXM92Vb4hVPA==
+"@tiptap/extension-code-block-lowlight@2.0.0-beta.68":
+ version "2.0.0-beta.68"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.68.tgz#c0da8c327eb2b49d808e3ead303f6ff6b0203e05"
+ integrity sha512-927vw4DJ5pq3lYOdJbBrCjJZ/YsbsEzWkb7SwRsaztDXcgsF2z8gt6dy7onXMaqm5rDx6eNofLPdhUyLCswW8Q==
dependencies:
- "@tiptap/extension-code-block" "^2.0.0-beta.33"
+ "@tiptap/extension-code-block" "^2.0.0-beta.37"
"@types/lowlight" "^0.0.3"
lowlight "^1.20.0"
prosemirror-model "^1.16.1"
prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.5"
+ prosemirror-view "^1.23.6"
-"@tiptap/extension-code-block@^2.0.0-beta.33":
- version "2.0.0-beta.33"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.33.tgz#963b06ec88f97f79e1c90b3b830eff826a4bad88"
- integrity sha512-zKiGxbbnZJrKXr0DtBd0B7yXvY3wRk5Y5BsJqe0ZsyXR8lCEY4+DcOPpr6dja2gpgQIB9+vtqZvgBfnnUXXTcw==
+"@tiptap/extension-code-block@^2.0.0-beta.37":
+ version "2.0.0-beta.37"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.37.tgz#c07c007248a21d9e0434458fd05c363b7078227f"
+ integrity sha512-mJAM+PHaNoKRYwM3D36lZ51/aoPxxvZNQn3UBnZ6G7l0ZJSgB3JvBEzqK6S8nNFeYIIxGwv4QF6vXe4MG9ie2g==
dependencies:
prosemirror-state "^1.3.4"
@@ -1571,13 +1623,13 @@
"@types/prosemirror-dropcursor" "^1.0.3"
prosemirror-dropcursor "^1.4.0"
-"@tiptap/extension-floating-menu@^2.0.0-beta.49":
- version "2.0.0-beta.49"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.49.tgz#36682849f50e217137775d7f738af952a0434113"
- integrity sha512-VY0d+fJmz8FP1CxqB9u09xCZe/9Wtwff+SxY+LGpflVf0JjS+CWcaVIDNF8zHG13SMobQ5xH6RRnSuTzlS2bRA==
+"@tiptap/extension-floating-menu@^2.0.0-beta.50":
+ version "2.0.0-beta.50"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.50.tgz#e8785d5f051a848ae053ce139581dce96b951a35"
+ integrity sha512-aQu1HtthMIYEPylr6kzioLxMiObLbcgwx9xZzF03KwNnkjQLbjZOeJX2RwSYVpiVgtfPBGOm3N/br6NSYec4yQ==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.5"
+ prosemirror-view "^1.23.6"
tippy.js "^6.3.7"
"@tiptap/extension-gapcursor@^2.0.0-beta.34":
@@ -1593,10 +1645,10 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.30.tgz#165494f1194a7bad08907e6d64d349dd15851b72"
integrity sha512-X9xj/S+CikrbIE7ccUFVwit5QHEbflnKVxod+4zPwr1cxogFbE9AyLZE2MpYdx3z9LcnTYYi9leBqFrP4T/Olw==
-"@tiptap/extension-heading@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.24.tgz#52ba163c8d16985739387682d5e5b28ddf242661"
- integrity sha512-5a3vgdO7Cf2+z7sulCGs/1j23gBcKiZe3pA1FrC5h6blwLu86hA1xnMAVBVNilP9b6c9f3lN9yxMzEWsp6ZEkA==
+"@tiptap/extension-heading@^2.0.0-beta.26":
+ version "2.0.0-beta.26"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.26.tgz#112b14b4d488772bda36abbf7cb2bc8aba7c42f5"
+ integrity sha512-nR6W/3rjnZH1Swo7tGBoYsmO6xMvu9MGq6jlm3WVHCB7B3CsrRvCkTwGjVIbKTaZC4bQfx5gvAUpQFvwuU+M5w==
"@tiptap/extension-history@^2.0.0-beta.21":
version "2.0.0-beta.21"
@@ -1606,27 +1658,27 @@
"@types/prosemirror-history" "^1.0.3"
prosemirror-history "^1.2.0"
-"@tiptap/extension-horizontal-rule@^2.0.0-beta.30":
- version "2.0.0-beta.30"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.30.tgz#56d497f1187384d131f3f3320f30748c1e4b766f"
- integrity sha512-h/PlkvfcMuoBGRfD7Cbeh8mxZiEc2pKveLDwOfCES9TKV5i2lqcIgctpohWyISuFcTq4K+OFgr910+Rsp8qwEg==
+"@tiptap/extension-horizontal-rule@^2.0.0-beta.31":
+ version "2.0.0-beta.31"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.31.tgz#efb383a6cedbbf4f2175d7d207eaeeba626faab0"
+ integrity sha512-MNc4retfjRgkv3qxqGya0+/BEd1Kmn+oMsCRvE+8x3sXyKIse+vdqMuG5qUcA6np0ZD/9hh1riiQ1GQdgc23Ng==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-image@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.24.tgz#1010676f79925cbe11a44b6d8eee1251910fbc1d"
- integrity sha512-7oiX/Ovj9WN4xTBqWbQWd4H3SUO2eNzOiKHebVo3eqWG8NxzOGfuU0iRCENtEa7vTiRrFgyeBotneMALDpDnTQ==
+"@tiptap/extension-image@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.25.tgz#7fb001a6449a9a841ae4f42c258ad6a06022b523"
+ integrity sha512-RgW5jFVS2QNDvFhBOz7H1hY6LjYcbVAa/mE4F4c3RPg3o7GJZXNoL9s+k0QkEM2GXAvY6fX+OICMBn8TSENXKA==
"@tiptap/extension-italic@^2.0.0-beta.25":
version "2.0.0-beta.25"
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.25.tgz#c2ec95cc5baf855134883c5e261da4ab0d3b9479"
integrity sha512-7PvhioTX9baVp5+AmmZU0qna+dFPZCRlSEN/GciH57N77d2uhJ/ZW5iQWTbvy5HBNddQB4Jts1UDIaC7WASrGA==
-"@tiptap/extension-link@^2.0.0-beta.34":
- version "2.0.0-beta.34"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.34.tgz#9f07b9db6a3b62192b0162afdab5480fcd93e731"
- integrity sha512-v9qqPWyKfJ9BbV2eWR4a+za1cepZywV/2Rng+1gTivzLpfBgy6Q50vgUyMe7KTZpNZw5MuZO4sBwlvangmj6Vg==
+"@tiptap/extension-link@^2.0.0-beta.36":
+ version "2.0.0-beta.36"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.36.tgz#184bac20f3226b8945e400ebfdce2feabb4f5a3c"
+ integrity sha512-jV0EBM/QPfR4e5FG5OPHZARnYS+CL8yhCzHO4J1Nb1i/+vRY9QpPVBruZABBwt+J+PMdq6t/6vvIXejCR3wyAg==
dependencies:
linkifyjs "^3.0.5"
prosemirror-model "^1.16.1"
@@ -1677,18 +1729,18 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.19.tgz#b45e82f29dfcc7405440ba237b069dbb93d1a94a"
integrity sha512-ldEVDpIUX7ZqbViTy4c/RfyNGRv++O/r3A/Ivuon1PykaDDTbPlp5JM89FunAD39cLAbo2HKtweqdmzCMlZsqA==
-"@tiptap/extension-table@^2.0.0-beta.46":
- version "2.0.0-beta.46"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.46.tgz#cce4d64fe58479031eb975626cc42e3ca9ae26bd"
- integrity sha512-JP0eYb2gS9RW1xzB1yCAgcSX4eg1MvhnYNLOxL6VCKvoHf33RW7zQEGx11W/Lrc3lh5qaMjkWcCdQYq5d8qJOA==
+"@tiptap/extension-table@^2.0.0-beta.48":
+ version "2.0.0-beta.48"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.48.tgz#4b6adfe358fd38199ef5b29dafc9425fd461d1b3"
+ integrity sha512-Hcx3kOBQyazQ3dV0Oq4zKIl1og4EqUuZ5nEWxwcb8HgxSUYIhAJQ7pujPZiRLfkoFy92oVwmh9KhBRfQqRkUpQ==
dependencies:
prosemirror-tables "^1.1.1"
- prosemirror-view "^1.23.5"
+ prosemirror-view "^1.23.6"
-"@tiptap/extension-task-item@^2.0.0-beta.30":
- version "2.0.0-beta.30"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.30.tgz#54c97d2dd84e0ff40689e02f7361dbd903a40161"
- integrity sha512-56hS7vP/Hgv5R6otEPInTnd8z5n6UCBFm4sbMPA8d7yWWJDskkfuMp9YDEu2zgHZtTghPyGkw3wO6yxouGWlkg==
+"@tiptap/extension-task-item@^2.0.0-beta.31":
+ version "2.0.0-beta.31"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.31.tgz#e73f2f1e264d64ac5902ddd13ad3b63cb043b2c9"
+ integrity sha512-9MCInLAf/l/wDD1N3GgOImemloFARi1l9AJ5acfo+sDjN52yfvaLb//lvLJ6IGz4xGepeAyCME8Qns8UGqG4RQ==
"@tiptap/extension-task-list@^2.0.0-beta.26":
version "2.0.0-beta.26"
@@ -1700,14 +1752,14 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz#f08cff1b78f1c6996464dfba1fef8ec1e107617f"
integrity sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA==
-"@tiptap/vue-2@^2.0.0-beta.74":
- version "2.0.0-beta.74"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.74.tgz#da9e56113018525d0cb55812a2452d57b9710d26"
- integrity sha512-OY6RhR2DSvP4iIxtoWeg2qmQ1uYP4kJkdMT5ePQBFqVzs6l5+FpSjETskS8EwZVgM/IrLTMp5lHfKboP/YacOA==
+"@tiptap/vue-2@^2.0.0-beta.77":
+ version "2.0.0-beta.77"
+ resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.77.tgz#d5e7b414bba45d0892e39513dc50387d629b95ca"
+ integrity sha512-/wMi7fkqLqfWGhOpcztiGgVyqiCmOPq7TZ2LFx+cokoMJ1HpM8T7vG12u6ezOubB5Ie7/kL6WBcLJ8hONTdX0Q==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.0-beta.54"
- "@tiptap/extension-floating-menu" "^2.0.0-beta.49"
- prosemirror-view "^1.23.5"
+ "@tiptap/extension-bubble-menu" "^2.0.0-beta.55"
+ "@tiptap/extension-floating-menu" "^2.0.0-beta.50"
+ prosemirror-view "^1.23.6"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
@@ -1762,6 +1814,21 @@
dependencies:
"@babel/types" "^7.3.0"
+"@types/body-parser@*":
+ version "1.19.2"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
+ integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+"@types/bonjour@^3.5.9":
+ version "3.5.10"
+ resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275"
+ integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==
+ dependencies:
+ "@types/node" "*"
+
"@types/codemirror@0.0.71":
version "0.0.71"
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.71.tgz#861f1bcb3100c0a064567c5400f2981cf4ae8ca7"
@@ -1769,6 +1836,21 @@
dependencies:
"@types/tern" "*"
+"@types/connect-history-api-fallback@^1.3.5":
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
+ integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/node" "*"
+
+"@types/connect@*":
+ version "3.4.35"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
+ integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
+ dependencies:
+ "@types/node" "*"
+
"@types/estree@*":
version "0.0.44"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.44.tgz#980cc5a29a3ef3bea6ff1f7d021047d7ea575e21"
@@ -1779,7 +1861,26 @@
resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86"
integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==
-"@types/glob@5 - 7", "@types/glob@^7.1.1":
+"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18":
+ version "4.17.28"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8"
+ integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+
+"@types/express@*", "@types/express@^4.17.13":
+ version "4.17.13"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
+ integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "^4.17.18"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+"@types/glob@5 - 7":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
@@ -1795,6 +1896,13 @@
dependencies:
"@types/node" "*"
+"@types/http-proxy@^1.17.8":
+ version "1.17.8"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55"
+ integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==
+ dependencies:
+ "@types/node" "*"
+
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5"
@@ -1814,10 +1922,10 @@
dependencies:
"@types/istanbul-lib-report" "*"
-"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
- version "7.0.7"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
- integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
+"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+ version "7.0.9"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
+ integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
"@types/json5@^0.0.29":
version "0.0.29"
@@ -1829,12 +1937,10 @@
resolved "https://registry.yarnpkg.com/@types/lowlight/-/lowlight-0.0.3.tgz#433b03dd63894dde17860063f4c90a688431194b"
integrity sha512-R83q/yPX2nIlo9D3WtSjyUDd57t8s+GVLaL8YIv3k7zMMWpYpOXqjJgrWp80qXUJB/a1t76nTyBpxrv0JNYaEg==
-"@types/mdast@^3.0.0":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.3.tgz#2d7d671b1cd1ea3deb306ea75036c2a0407d2deb"
- integrity sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==
- dependencies:
- "@types/unist" "*"
+"@types/mime@^1":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
+ integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
"@types/minimatch@*":
version "3.0.3"
@@ -1842,11 +1948,11 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/minimist@^1.2.0":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
- integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
+ integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
-"@types/node@*", "@types/node@14.17.5", "@types/node@>=6":
+"@types/node@*", "@types/node@14.17.5":
version "14.17.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.5.tgz#b59daf6a7ffa461b5648456ca59050ba8e40ed54"
integrity sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==
@@ -1918,10 +2024,10 @@
"@types/prosemirror-state" "*"
"@types/prosemirror-view" "*"
-"@types/prosemirror-model@*", "@types/prosemirror-model@^1.13.2":
- version "1.13.2"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.13.2.tgz#2adad3ec478f83204f155d7fb94c9dfde2fc3296"
- integrity sha512-a2rDB0aZ+7aIP7uBqQq1wLb4Hg4qqEvpkCqvhsgT/gG8IWC0peCAZfQ24sgTco0qSJLeDgIbtPeU6mgr869/kg==
+"@types/prosemirror-model@*", "@types/prosemirror-model@^1.16.0":
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.16.0.tgz#8b22c7431a4c93f7f550fc89c4b0e2d44d42c8b6"
+ integrity sha512-nv93YLyTEcDDl17OB90EldxZjyJQJll2WSMLDvLzTewbpvE/vtMjHT3j4mik3uSzQ6YD486AcloCO3WODY/lDg==
dependencies:
"@types/orderedmap" "*"
@@ -1950,15 +2056,52 @@
dependencies:
"@types/prosemirror-model" "*"
-"@types/prosemirror-view@*", "@types/prosemirror-view@^1.19.2":
- version "1.19.2"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.19.2.tgz#1bab4daf0f1f14313fe0d3f6b57f0a3b4ef6c50d"
- integrity sha512-pmh2DuMJzva4D7SxspRKIzkV6FK2o52uAqGjq2dPYcQFPwu4+5RcS1TMjFVCh1R+Ia1Rx8wsCNIId/5+6DB0Bg==
+"@types/prosemirror-view@*", "@types/prosemirror-view@^1.23.1":
+ version "1.23.1"
+ resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.23.1.tgz#a9a926bb6b6e6873e3a9d8caa61c32f3402629eb"
+ integrity sha512-6e1B2oKUnhmZPUrsVvYjDqeVjE6jGezygjtoHsAK4ZENAxHzHqy5NT4jUvdPTWjCYeH0t2Y7pSfRPNrPIyQX4A==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-transform" "*"
+"@types/qs@*":
+ version "6.9.7"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
+ integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
+
+"@types/range-parser@*":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
+ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
+
+"@types/retry@^0.12.0":
+ version "0.12.1"
+ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
+ integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
+
+"@types/serve-index@^1.9.1":
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278"
+ integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==
+ dependencies:
+ "@types/express" "*"
+
+"@types/serve-static@*":
+ version "1.13.10"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
+ integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
+ dependencies:
+ "@types/mime" "^1"
+ "@types/node" "*"
+
+"@types/sockjs@^0.3.33":
+ version "0.3.33"
+ resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f"
+ integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==
+ dependencies:
+ "@types/node" "*"
+
"@types/stack-utils@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
@@ -1971,10 +2114,10 @@
dependencies:
"@types/estree" "*"
-"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
- integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
+"@types/ungap__global-this@^0.3.1":
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/@types/ungap__global-this/-/ungap__global-this-0.3.1.tgz#18ce9f657da556037a29d50604335614ce703f4c"
+ integrity sha512-+/DsiV4CxXl6ZWefwHZDXSe1Slitz21tom38qPCaG0DYCS1NnDPIQDTKcmQ/tvK/edJUKkmuIDBJbmKDiB0r/g==
"@types/websocket@1.0.4":
version "1.0.4"
@@ -1983,10 +2126,10 @@
dependencies:
"@types/node" "*"
-"@types/ws@^8.0.0":
- version "8.2.0"
- resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.0.tgz#75faefbe2328f3b833cb8dc640658328990d04f3"
- integrity sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==
+"@types/ws@^8.0.0", "@types/ws@^8.2.2":
+ version "8.2.2"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21"
+ integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==
dependencies:
"@types/node" "*"
@@ -2030,6 +2173,11 @@
semver "^6.3.0"
tsutils "^3.17.1"
+"@ungap/global-this@^0.4.2":
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/@ungap/global-this/-/global-this-0.4.4.tgz#8a1b2cfcd3e26e079a847daba879308c924dd695"
+ integrity sha512-mHkm6FvepJECMNthFuIgpAEFmPOk71UyXuIxYfjytvFTnSDBIz7jmViO+LfHI/AjrazWije0PnSP3+/NlwzqtA==
+
"@vue/component-compiler-utils@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.1.1.tgz#d4ef8f80292674044ad6211e336a302e4d2a6575"
@@ -2199,20 +2347,43 @@
"@webassemblyjs/wast-parser" "1.9.0"
"@xtuc/long" "4.2.2"
-"@wry/context@^0.4.0":
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8"
- integrity sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==
+"@webpack-cli/configtest@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.1.tgz#9f53b1b7946a6efc2a749095a4f450e2932e8356"
+ integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==
+
+"@webpack-cli/info@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.1.tgz#2360ea1710cbbb97ff156a3f0f24556e0fc1ebea"
+ integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==
dependencies:
- "@types/node" ">=6"
- tslib "^1.9.3"
+ envinfo "^7.7.3"
+
+"@webpack-cli/serve@^1.6.1":
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe"
+ integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==
-"@wry/equality@^0.1.2":
- version "0.1.9"
- resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909"
- integrity sha512-mB6ceGjpMGz1ZTza8HYnrPGos2mC6So4NhS1PtZ8s4Qt0K7fBiIGhpSxUbQmhwcSWE3no+bYxmI2OL6KuXYmoQ==
+"@wry/context@^0.5.2":
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.4.tgz#b6c28038872e0a0e1ff14eb40b5bf4cab2ab4e06"
+ integrity sha512-/pktJKHUXDr4D6TJqWgudOPJW2Z+Nb+bqk40jufA3uTkLbnCRKdJPiYDIa/c7mfcPH8Hr6O8zjCERpg5Sq04Zg==
dependencies:
- tslib "^1.9.3"
+ tslib "^1.14.1"
+
+"@wry/equality@^0.3.0":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.3.3.tgz#1ec8f9af01d40a2eb00d055d9a3173315126c648"
+ integrity sha512-pMrKHIgDAWxLDTGsbaVag+USmwZ2+gGrSBrtyGUxp2pxRg1Cad70lI/hd0NTPtJ4zJxN16EQ679U1Rts83AF5g==
+ dependencies:
+ tslib "^1.14.1"
+
+"@wry/trie@^0.2.1":
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.2.2.tgz#99f20f0fcbbcda17006069b155c826cbabfc402f"
+ integrity sha512-OxqBB39x6MfHaa2HpMiRMfhuUnQTddD32Ko020eBeJXq87ivX6xnSSnzKHVbA21p7iqBASz8n/07b6W5wW1BVQ==
+ dependencies:
+ tslib "^1.14.1"
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
@@ -2312,11 +2483,25 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+ajv-keywords@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
+ integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
@@ -2327,10 +2512,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@^8.0.1:
- version "8.6.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571"
- integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==
+ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0:
+ version "8.9.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18"
+ integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
@@ -2344,11 +2529,6 @@ ansi-align@^3.0.0:
dependencies:
string-width "^3.0.0"
-ansi-colors@^3.0.0:
- version "3.2.4"
- resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
- integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-
ansi-colors@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
@@ -2361,16 +2541,11 @@ ansi-escapes@^4.2.1:
dependencies:
type-fest "^0.21.3"
-ansi-html-community@0.0.8:
+ansi-html-community@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
ansi-regex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
@@ -2381,7 +2556,12 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ansi-regex@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
+ integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
+
+ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
@@ -2416,113 +2596,14 @@ anymatch@^3.0.3, anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-apollo-cache-inmemory@^1.6.6:
- version "1.6.6"
- resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.6.tgz#56d1f2a463a6b9db32e9fa990af16d2a008206fd"
- integrity sha512-L8pToTW/+Xru2FFAhkZ1OA9q4V4nuvfoPecBM34DecAugUZEBhI2Hmpgnzq2hTKZ60LAMrlqiASm0aqAY6F8/A==
+apollo-upload-client@^14.1.3:
+ version "14.1.3"
+ resolved "https://registry.yarnpkg.com/apollo-upload-client/-/apollo-upload-client-14.1.3.tgz#91f39011897bd08e99c0de0164e77ad2f3402247"
+ integrity sha512-X2T+7pHk5lcaaWnvP9h2tuAAMCzOW6/9juedQ0ZuGp3Ufl81BpDISlCs0o6u29wBV0RRT/QpMU2gbP+3FCfVpQ==
dependencies:
- apollo-cache "^1.3.5"
- apollo-utilities "^1.3.4"
- optimism "^0.10.0"
- ts-invariant "^0.4.0"
- tslib "^1.10.0"
-
-apollo-cache@1.3.5, apollo-cache@^1.3.5:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.5.tgz#9dbebfc8dbe8fe7f97ba568a224bca2c5d81f461"
- integrity sha512-1XoDy8kJnyWY/i/+gLTEbYLnoiVtS8y7ikBr/IfmML4Qb+CM7dEEbIUOjnY716WqmZ/UpXIxTfJsY7rMcqiCXA==
- dependencies:
- apollo-utilities "^1.3.4"
- tslib "^1.10.0"
-
-apollo-client@^2.6.10:
- version "2.6.10"
- resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.10.tgz#86637047b51d940c8eaa771a4ce1b02df16bea6a"
- integrity sha512-jiPlMTN6/5CjZpJOkGeUV0mb4zxx33uXWdj/xQCfAMkuNAC3HN7CvYDyMHHEzmcQ5GV12LszWoQ/VlxET24CtA==
- dependencies:
- "@types/zen-observable" "^0.8.0"
- apollo-cache "1.3.5"
- apollo-link "^1.0.0"
- apollo-utilities "1.3.4"
- symbol-observable "^1.0.2"
- ts-invariant "^0.4.0"
- tslib "^1.10.0"
- zen-observable "^0.8.0"
-
-apollo-link-batch-http@^1.2.14:
- version "1.2.14"
- resolved "https://registry.yarnpkg.com/apollo-link-batch-http/-/apollo-link-batch-http-1.2.14.tgz#4502109d3f32a94d88eabd3a89274ae3a6e2f56f"
- integrity sha512-LFUmfV3OXR3Er+zSgFxPY/qUe4Wyx0HS1euJZ36RCCaDvPegr24C9OQgKFScHy91VbjRTtFUyjXXVq1xFGPMvQ==
- dependencies:
- apollo-link "^1.2.14"
- apollo-link-batch "^1.1.15"
- apollo-link-http-common "^0.2.16"
- tslib "^1.9.3"
-
-apollo-link-batch@^1.1.15:
- version "1.1.15"
- resolved "https://registry.yarnpkg.com/apollo-link-batch/-/apollo-link-batch-1.1.15.tgz#3a5b8c7d9cf1b7840ce630238249b95070e75e54"
- integrity sha512-XbfQI/FNxJW9RSgJTfAl7RDFxxN77425yDtT7YgsImH4/2NQ+U4SWN6thWE3ZU1Wf7ktXd+XFa3KkenBRTybOQ==
- dependencies:
- apollo-link "^1.2.14"
- tslib "^1.9.3"
-
-apollo-link-error@^1.1.13:
- version "1.1.13"
- resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.13.tgz#c1a1bb876ffe380802c8df0506a32c33aad284cd"
- integrity sha512-jAZOOahJU6bwSqb2ZyskEK1XdgUY9nkmeclCrW7Gddh1uasHVqmoYc4CKdb0/H0Y1J9lvaXKle2Wsw/Zx1AyUg==
- dependencies:
- apollo-link "^1.2.14"
- apollo-link-http-common "^0.2.16"
- tslib "^1.9.3"
-
-apollo-link-http-common@^0.2.14, apollo-link-http-common@^0.2.16:
- version "0.2.16"
- resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz#756749dafc732792c8ca0923f9a40564b7c59ecc"
- integrity sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg==
- dependencies:
- apollo-link "^1.2.14"
- ts-invariant "^0.4.0"
- tslib "^1.9.3"
-
-apollo-link-http@^1.5.17:
- version "1.5.17"
- resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.17.tgz#499e9f1711bf694497f02c51af12d82de5d8d8ba"
- integrity sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg==
- dependencies:
- apollo-link "^1.2.14"
- apollo-link-http-common "^0.2.16"
- tslib "^1.9.3"
-
-apollo-link@^1.0.0, apollo-link@^1.2.12, apollo-link@^1.2.14:
- version "1.2.14"
- resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.14.tgz#3feda4b47f9ebba7f4160bef8b977ba725b684d9"
- integrity sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==
- dependencies:
- apollo-utilities "^1.3.0"
- ts-invariant "^0.4.0"
- tslib "^1.9.3"
- zen-observable-ts "^0.8.21"
-
-apollo-upload-client@^13.0.0:
- version "13.0.0"
- resolved "https://registry.yarnpkg.com/apollo-upload-client/-/apollo-upload-client-13.0.0.tgz#146d1ddd85d711fcac8ca97a72d3ca6787f2b71b"
- integrity sha512-lJ9/bk1BH1lD15WhWRha2J3+LrXrPIX5LP5EwiOUHv8PCORp4EUrcujrA3rI5hZeZygrTX8bshcuMdpqpSrvtA==
- dependencies:
- "@babel/runtime" "^7.9.2"
- apollo-link "^1.2.12"
- apollo-link-http-common "^0.2.14"
- extract-files "^8.0.0"
-
-apollo-utilities@1.3.4, apollo-utilities@^1.3.0, apollo-utilities@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.4.tgz#6129e438e8be201b6c55b0f13ce49d2c7175c9cf"
- integrity sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==
- dependencies:
- "@wry/equality" "^0.1.2"
- fast-json-stable-stringify "^2.0.0"
- ts-invariant "^0.4.0"
- tslib "^1.10.0"
+ "@apollo/client" "^3.2.5"
+ "@babel/runtime" "^7.12.5"
+ extract-files "^9.0.0"
aproba@^1.1.1:
version "1.2.0"
@@ -2595,23 +2676,11 @@ array-includes@^3.1.1:
get-intrinsic "^1.0.1"
is-string "^1.0.5"
-array-union@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
- integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
- dependencies:
- array-uniq "^1.0.1"
-
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
-array-uniq@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
- integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
-
array-unique@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
@@ -2669,11 +2738,6 @@ astral-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
-async-limiter@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
- integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
-
async@^2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@@ -2691,19 +2755,6 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
-autoprefixer@^9.8.6:
- version "9.8.6"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
- integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
- dependencies:
- browserslist "^4.12.0"
- caniuse-lite "^1.0.30001109"
- colorette "^1.2.1"
- normalize-range "^0.1.2"
- num2fraction "^1.2.2"
- postcss "^7.0.32"
- postcss-value-parser "^4.1.0"
-
autosize@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f"
@@ -2858,16 +2909,16 @@ backo2@^1.0.2:
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
-bail@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
- integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==
-
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+balanced-match@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9"
+ integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==
+
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -3085,16 +3136,16 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
-browserslist@^4.12.0, browserslist@^4.16.6:
- version "4.17.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9"
- integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ==
+browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.5:
+ version "4.19.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3"
+ integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==
dependencies:
- caniuse-lite "^1.0.30001259"
- electron-to-chromium "^1.3.846"
+ caniuse-lite "^1.0.30001286"
+ electron-to-chromium "^1.4.17"
escalade "^3.1.1"
- nanocolors "^0.1.5"
- node-releases "^1.1.76"
+ node-releases "^2.0.1"
+ picocolors "^1.0.0"
bser@2.1.1:
version "2.1.1"
@@ -3271,10 +3322,10 @@ camelcase@^6.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
-caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001259:
- version "1.0.30001261"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01"
- integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA==
+caniuse-lite@^1.0.30001286:
+ version "1.0.30001302"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001302.tgz#da57ce61c51177ef3661eeed7faef392d3790aaa"
+ integrity sha512-YYTMO+tfwvgUN+1ZnRViE53Ma1S/oETg+J2lISsqi/ZTNThj3ZYBOKP2rHwJc37oCsPqAzJ3w2puZHn0xlLPPw==
canvas-confetti@^1.4.0:
version "1.4.0"
@@ -3330,21 +3381,6 @@ char-regex@^1.0.2:
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
-character-entities-legacy@^1.0.0:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1"
- integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==
-
-character-entities@^1.0.0:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b"
- integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==
-
-character-reference-invalid@^1.0.0:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
- integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
-
charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@@ -3374,7 +3410,7 @@ cheerio@^1.0.0-rc.9:
parse5-htmlparser2-tree-adapter "^6.0.1"
tslib "^2.2.0"
-"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
+"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.5.3:
version "3.4.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
@@ -3448,15 +3484,6 @@ clipboard@^2.0.0, clipboard@^2.0.8:
select "^1.1.2"
tiny-emitter "^2.0.0"
-cliui@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
- integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
- dependencies:
- string-width "^3.1.0"
- strip-ansi "^5.2.0"
- wrap-ansi "^5.1.0"
-
cliui@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
@@ -3466,6 +3493,15 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
clone-regexp@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
@@ -3551,10 +3587,15 @@ 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, colorette@^1.2.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
- integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
+colord@^2.9.2:
+ version "2.9.2"
+ resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1"
+ integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==
+
+colorette@^2.0.10, colorette@^2.0.14:
+ version "2.0.16"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
+ integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
@@ -3568,16 +3609,21 @@ commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-commander@7:
+commander@7, commander@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
-commander@^6.0.0, commander@^6.1.0, commander@^6.2.0, commander@~6.2.1:
+commander@^6.0.0, commander@^6.1.0, commander@^6.2.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
+commander@~9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-9.0.0.tgz#86d58f24ee98126568936bd1d3574e0308a99a40"
+ integrity sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==
+
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -3785,10 +3831,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.20.2:
- version "3.20.2"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.2.tgz#46468d8601eafc8b266bd2dd6bf9dee622779581"
- integrity sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==
+core-js@^3.21.1:
+ version "3.21.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94"
+ integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==
core-js@~2.3.0:
version "2.3.0"
@@ -3807,7 +3853,7 @@ cosmiconfig-toml-loader@1.0.0:
dependencies:
"@iarna/toml" "^2.2.5"
-cosmiconfig@7.0.1, cosmiconfig@^7.0.0:
+cosmiconfig@7.0.1, cosmiconfig@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
@@ -3870,7 +3916,7 @@ cropper@^2.3.0:
dependencies:
jquery ">= 1.9.1"
-cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -3881,7 +3927,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^7.0.0, cross-spawn@^7.0.2:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -4606,10 +4652,10 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
-debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
- integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
+debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3:
+ version "4.3.3"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
+ integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
dependencies:
ms "2.1.2"
@@ -4653,7 +4699,7 @@ deep-equal@^1.0.1:
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
-deep-extend@^0.6.0, deep-extend@~0.6.0:
+deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
@@ -4668,19 +4714,23 @@ deepmerge@^4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
-default-gateway@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
- integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==
+default-gateway@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
+ integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
dependencies:
- execa "^1.0.0"
- ip-regex "^2.1.0"
+ execa "^5.0.0"
defer-to-connect@^1.0.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -4710,18 +4760,19 @@ define-property@^2.0.2:
is-descriptor "^1.0.2"
isobject "^3.0.1"
-del@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
- integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
- dependencies:
- "@types/glob" "^7.1.1"
- globby "^6.1.0"
- is-path-cwd "^2.0.0"
- is-path-in-cwd "^2.0.0"
- p-map "^2.0.0"
- pify "^4.0.1"
- rimraf "^2.6.3"
+del@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952"
+ integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==
+ dependencies:
+ globby "^11.0.1"
+ graceful-fs "^4.2.4"
+ is-glob "^4.0.1"
+ is-path-cwd "^2.2.0"
+ is-path-inside "^3.0.2"
+ p-map "^4.0.0"
+ rimraf "^3.0.2"
+ slash "^3.0.0"
delaunator@5:
version "5.0.0"
@@ -4763,11 +4814,6 @@ destroy@~1.0.4:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-detect-file@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
- integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
-
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -4820,9 +4866,9 @@ dns-equal@^1.0.0:
integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0=
dns-packet@^1.0.1:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.2.2.tgz#a8a26bec7646438963fc86e06f8f8b16d6c8bf7a"
- integrity sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f"
+ integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -4864,14 +4910,6 @@ dom-event-types@^1.0.0:
resolved "https://registry.yarnpkg.com/dom-event-types/-/dom-event-types-1.0.0.tgz#5830a0a29e1bf837fe50a70cd80a597232813cae"
integrity sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ==
-dom-serializer@0:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
- integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
- dependencies:
- 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"
@@ -4891,11 +4929,6 @@ domain-browser@^1.1.1:
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
integrity sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=
-domelementtype@1, domelementtype@^1.3.1:
- version "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, domelementtype@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
@@ -4908,13 +4941,6 @@ domexception@^2.0.1:
dependencies:
webidl-conversions "^5.0.0"
-domhandler@^2.3.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
- integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
- dependencies:
- domelementtype "1"
-
domhandler@^4.0.0, domhandler@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059"
@@ -4922,18 +4948,15 @@ domhandler@^4.0.0, domhandler@^4.2.0:
dependencies:
domelementtype "^2.2.0"
-dompurify@2.3.4, dompurify@^2.3.4:
+dompurify@2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.4.tgz#1cf5cf0105ccb4debdf6db162525bd41e6ddacc6"
integrity sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ==
-domutils@^1.5.1:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
- integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
- dependencies:
- dom-serializer "0"
- domelementtype "1"
+dompurify@^2.3.5:
+ version "2.3.5"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.5.tgz#c83ed5a3ae5ce23e52efe654ea052ffb358dd7e3"
+ integrity sha512-kD+f8qEaa42+mjdOpKeztu9Mfx5bv9gVLO6K9jRx4uGvh6Wv06Srn4jr1wPNY2OOUGGSKHNFN+A8MA3v0E0QAQ==
domutils@^2.5.2, domutils@^2.6.0:
version "2.6.0"
@@ -5017,10 +5040,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-electron-to-chromium@^1.3.846:
- version "1.3.853"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.853.tgz#f3ed1d31f092cb3a17af188bca6c6a3ec91c3e82"
- integrity sha512-W4U8n+U8I5/SUaFcqZgbKRmYZwcyEIQVBDf+j5QQK6xChjXnQD+wj248eGR9X4u+dDmDR//8vIfbu4PrdBBIoQ==
+electron-to-chromium@^1.4.17:
+ version "1.4.53"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.53.tgz#5d80a91c399b44952ef485857fb5b9d4387d2e60"
+ integrity sha512-rFveSKQczlcav+H3zkKqykU6ANseFwXwkl855jOIap5/0gnEcuIhv2ecz6aoTrXavF6I/CEBeRnBnkB51k06ew==
elliptic@^6.0.0:
version "6.5.4"
@@ -5086,7 +5109,7 @@ enhanced-resolve@^0.9.1:
memory-fs "^0.2.0"
tapable "^0.1.8"
-enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0:
+enhanced-resolve@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
@@ -5102,16 +5125,21 @@ enquirer@^2.3.5:
dependencies:
ansi-colors "^4.1.1"
-entities@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
- integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
+entities@^2.0.0, entities@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
+ integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
-entities@^2.0.0, entities@~2.0.0:
+entities@~2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
+envinfo@^7.7.3:
+ version "7.8.1"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
+ integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
+
errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
@@ -5505,13 +5533,6 @@ events@^3.0.0:
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==
-eventsource@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
- integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
- dependencies:
- original "^1.0.0"
-
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
@@ -5553,6 +5574,21 @@ execa@^4.0.0:
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"
+execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
execall@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45"
@@ -5578,13 +5614,6 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-expand-tilde@^2.0.0, expand-tilde@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
- integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
- dependencies:
- homedir-polyfill "^1.0.1"
-
expect@^26.5.2:
version "26.5.2"
resolved "https://registry.yarnpkg.com/expect/-/expect-26.5.2.tgz#3e0631c4a657a83dbec769ad246a2998953a55a6"
@@ -5648,7 +5677,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
-extend@^3.0.0, extend@~3.0.2:
+extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -5672,10 +5701,10 @@ extract-files@11.0.0:
resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a"
integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==
-extract-files@^8.0.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-8.1.0.tgz#46a0690d0fe77411a2e3804852adeaa65cd59288"
- integrity sha512-PTGtfthZK79WUMk+avLmwx3NGdU8+iVFXC2NMGxKsn0MnihOG2lvumj+AZo8CTwTrwjXDgZ5tztbRlEdRjBonQ==
+extract-files@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a"
+ integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==
extract-from-css@^0.4.4:
version "0.4.4"
@@ -5699,10 +5728,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^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==
-fast-glob@^3.1.1, fast-glob@^3.2.4, fast-glob@^3.2.5:
- version "3.2.7"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
- integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
+fast-glob@^3.2.11, fast-glob@^3.2.4, fast-glob@^3.2.9:
+ version "3.2.11"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
+ integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
@@ -5763,7 +5792,7 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
-file-entry-cache@^6.0.0, file-entry-cache@^6.0.1:
+file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
@@ -5853,16 +5882,6 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
-findup-sync@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
- integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
- dependencies:
- detect-file "^1.0.0"
- is-glob "^4.0.0"
- micromatch "^3.0.4"
- resolve-dir "^1.0.1"
-
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@@ -5885,9 +5904,9 @@ flush-write-stream@^1.0.0:
readable-stream "^2.3.6"
follow-redirects@^1.0.0, follow-redirects@^1.14.4:
- version "1.14.4"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
- integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
+ version "1.14.8"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
+ integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
for-in@^1.0.2:
version "1.0.2"
@@ -5954,6 +5973,11 @@ fs-minipass@^2.0.0:
dependencies:
minipass "^3.0.0"
+fs-monkey@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3"
+ integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==
+
fs-write-stream-atomic@^1.0.8:
version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@@ -6018,11 +6042,16 @@ get-stdin@^6.0.0:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
-get-stdin@^8.0.0, get-stdin@~8.0.0:
+get-stdin@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
+get-stdin@~9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575"
+ integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==
+
get-stream@^4.0.0, get-stream@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
@@ -6037,6 +6066,11 @@ get-stream@^5.0.0, get-stream@^5.1.0:
dependencies:
pump "^3.0.0"
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -6076,10 +6110,10 @@ glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0:
dependencies:
is-glob "^4.0.1"
-"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==
+"glob@5 - 7", glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
+ integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -6095,15 +6129,6 @@ global-dirs@^2.0.1:
dependencies:
ini "^1.3.5"
-global-modules@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
- integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
- dependencies:
- global-prefix "^1.0.1"
- is-windows "^1.0.1"
- resolve-dir "^1.0.0"
-
global-modules@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
@@ -6111,17 +6136,6 @@ global-modules@^2.0.0:
dependencies:
global-prefix "^3.0.0"
-global-prefix@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
- integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
- dependencies:
- expand-tilde "^2.0.2"
- homedir-polyfill "^1.0.1"
- ini "^1.3.4"
- is-windows "^1.0.1"
- which "^1.2.14"
-
global-prefix@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
@@ -6151,41 +6165,23 @@ globals@^13.6.0, globals@^13.9.0:
dependencies:
type-fest "^0.20.2"
-globby@^11.0.1, globby@^11.0.2, globby@^11.0.3:
- version "11.0.4"
- resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
- integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
+globby@^11.0.1, globby@^11.0.3, globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
dependencies:
array-union "^2.1.0"
dir-glob "^3.0.1"
- fast-glob "^3.1.1"
- ignore "^5.1.4"
- merge2 "^1.3.0"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
slash "^3.0.0"
-globby@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
- integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
- dependencies:
- array-union "^1.0.1"
- glob "^7.0.3"
- object-assign "^4.0.1"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
globjoin@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=
-gonzales-pe@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3"
- integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==
- dependencies:
- minimist "^1.2.5"
-
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
@@ -6210,10 +6206,10 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
-graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
- integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
+graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
+ version "4.2.9"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
+ integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
graphlib@^2.1.8:
version "2.1.8"
@@ -6251,10 +6247,12 @@ graphql-sse@^1.0.1:
resolved "https://registry.yarnpkg.com/graphql-sse/-/graphql-sse-1.0.4.tgz#051598b0e06c225327aac659f19fcc18bcaa0191"
integrity sha512-oB43ifRcEdElgep9jTP9qsj5cJ7Ny/1tAFyIl1W3A0hXRRg/P71tUHzMFBrRkEsJ9IA7MTp+RKSJfh52QR6PBQ==
-graphql-tag@^2.11.0:
- version "2.11.0"
- resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd"
- integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==
+graphql-tag@^2.11.0, graphql-tag@^2.12.0:
+ version "2.12.1"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.1.tgz#b065ef885e4800e4afd0842811b718a205f4aa58"
+ integrity sha512-LPewEE1vzGkHnCO8zdOGogKsHHBdtpGyihow1UuMwp6RnZa0lAS7NcbvltLOuo4pi5diQCPASAXZkQq44ffixA==
+ dependencies:
+ tslib "^1.14.1"
graphql-ws@^5.4.1:
version "5.5.3"
@@ -6418,22 +6416,22 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-homedir-polyfill@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc"
- integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw=
+hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
- parse-passwd "^1.0.0"
+ react-is "^16.7.0"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
-hosted-git-info@^3.0.6:
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d"
- integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==
+hosted-git-info@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
+ integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
dependencies:
lru-cache "^6.0.0"
@@ -6454,10 +6452,10 @@ html-encoding-sniffer@^2.0.1:
dependencies:
whatwg-encoding "^1.0.5"
-html-entities@^1.3.1:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc"
- integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==
+html-entities@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488"
+ integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==
html-escaper@^2.0.0:
version "2.0.0"
@@ -6469,18 +6467,6 @@ html-tags@^3.1.0:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
-htmlparser2@^3.10.0:
- version "3.10.1"
- resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
- integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
- dependencies:
- domelementtype "^1.3.1"
- domhandler "^2.3.0"
- domutils "^1.5.1"
- entities "^1.1.1"
- 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"
@@ -6535,17 +6521,18 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
-http-proxy-middleware@0.19.1:
- version "0.19.1"
- resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
- integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==
+http-proxy-middleware@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.2.tgz#94d7593790aad6b3de48164f13792262f656c332"
+ integrity sha512-XtmDN5w+vdFTBZaYhdJAbMqn0DP/EhkUaAeo963mojwpKMMbw6nivtFKw07D7DDOH745L5k0VL0P8KRYNEVF/g==
dependencies:
- http-proxy "^1.17.0"
- is-glob "^4.0.0"
- lodash "^4.17.11"
- micromatch "^3.1.10"
+ "@types/http-proxy" "^1.17.8"
+ http-proxy "^1.18.1"
+ is-glob "^4.0.1"
+ is-plain-obj "^3.0.0"
+ micromatch "^4.0.2"
-http-proxy@^1.17.0:
+http-proxy@^1.18.1:
version "1.18.1"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
@@ -6581,6 +6568,11 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
iconv-lite@0.4, iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -6632,10 +6624,10 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
-ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8:
- version "5.1.8"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
- integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
+ignore@^5.2.0, ignore@~5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
+ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
immediate@~3.0.5:
version "3.0.6"
@@ -6665,14 +6657,6 @@ import-lazy@^4.0.0:
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==
-import-local@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
- integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
- dependencies:
- pkg-dir "^3.0.0"
- resolve-cwd "^2.0.0"
-
import-local@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6"
@@ -6691,11 +6675,6 @@ indent-string@^4.0.0:
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-indexes-of@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
- integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
-
infer-owner@^1.0.3, infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@@ -6734,13 +6713,10 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-internal-ip@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
- integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==
- dependencies:
- default-gateway "^4.2.0"
- ipaddr.js "^1.9.0"
+ini@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
+ integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
"internmap@1 - 2":
version "2.0.3"
@@ -6752,6 +6728,11 @@ interpret@^1.4.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
+interpret@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
+ integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
+
invariant@^2.2.2:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@@ -6764,7 +6745,7 @@ ip-regex@^2.1.0:
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
-ip@^1.1.0, ip@^1.1.5:
+ip@^1.1.0:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
@@ -6774,15 +6755,15 @@ ipaddr.js@1.9.0:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
-ipaddr.js@^1.9.0, ipaddr.js@^1.9.1:
+ipaddr.js@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-is-absolute-url@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698"
- integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==
+ipaddr.js@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0"
+ integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==
is-accessor-descriptor@^0.1.6:
version "0.1.6"
@@ -6798,19 +6779,6 @@ is-accessor-descriptor@^1.0.0:
dependencies:
kind-of "^6.0.0"
-is-alphabetical@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d"
- integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==
-
-is-alphanumerical@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf"
- integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==
- dependencies:
- is-alphabetical "^1.0.0"
- is-decimal "^1.0.0"
-
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -6828,11 +6796,6 @@ is-buffer@^1.1.5, is-buffer@~1.1.1:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-buffer@^2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
- integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
-
is-callable@^1.1.4, is-callable@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
@@ -6845,10 +6808,10 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
-is-core-module@^2.2.0, is-core-module@^2.7.0:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
- integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
+is-core-module@^2.5.0, is-core-module@^2.7.0, is-core-module@^2.8.1:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
+ integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
dependencies:
has "^1.0.3"
@@ -6871,11 +6834,6 @@ is-date-object@^1.0.1:
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
-is-decimal@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
- integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
-
is-descriptor@^0.1.0:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
@@ -6894,7 +6852,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
-is-docker@^2.0.0:
+is-docker@^2.0.0, is-docker@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
@@ -6938,11 +6896,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
-is-hexadecimal@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
- integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==
-
is-installed-globally@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
@@ -6978,39 +6931,25 @@ is-obj@^2.0.0:
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
-is-path-cwd@^2.0.0:
+is-path-cwd@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
-is-path-in-cwd@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb"
- integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==
- dependencies:
- is-path-inside "^2.1.0"
-
-is-path-inside@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2"
- integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==
- dependencies:
- path-is-inside "^1.0.2"
-
-is-path-inside@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017"
- integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==
+is-path-inside@^3.0.1, is-path-inside@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
-is-plain-obj@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
- integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+is-plain-obj@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
+ integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
@@ -7019,6 +6958,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
+is-plain-object@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
+ integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+
is-potential-custom-element-name@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
@@ -7064,17 +7008,12 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-is-unicode-supported@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
- integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
-
is-whitespace@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f"
integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38=
-is-windows@^1.0.1, is-windows@^1.0.2:
+is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
@@ -7638,7 +7577,7 @@ js-cookie@^2.2.1:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@^3.13.1, js-yaml@~3.14.1:
+js-yaml@^3.13.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@@ -7646,6 +7585,13 @@ js-yaml@^3.13.1, js-yaml@~3.14.1:
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
js2xmlparser@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-3.0.0.tgz#3fb60eaa089c5440f9319f51760ccd07e2499733"
@@ -7763,11 +7709,6 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-json3@^3.3.3:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
- integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
-
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
@@ -7837,11 +7778,6 @@ khroma@^1.4.1:
resolved "https://registry.yarnpkg.com/khroma/-/khroma-1.4.1.tgz#ad6a5b6a972befc5112ce5129887a1a83af2c003"
integrity sha512-+GmxKvmiRuCcUYDgR7g5Ngo0JEDeOsGdNONdU2zsiBQaK4z19Y2NvXqfEDE0ZiIrg45GTZyAnPLVsLZZACYm3Q==
-killable@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
- integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==
-
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -7878,10 +7814,10 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-known-css-properties@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.20.0.tgz#0570831661b47dd835293218381166090ff60e96"
- integrity sha512-URvsjaA9ypfreqJ2/ylDr5MUERhJZ+DhguoWRr2xgS5C7aGCalXo+ewL+GixgKBfhT2vuL02nbIgNGqVWgTOYw==
+known-css-properties@^0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.24.0.tgz#19aefd85003ae5698a5560d2b55135bf5432155c"
+ integrity sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==
latest-version@^5.0.0:
version "5.1.0"
@@ -8025,17 +7961,12 @@ lodash.compact@^3.0.1:
resolved "https://registry.yarnpkg.com/lodash.compact/-/lodash.compact-3.0.1.tgz#540ce3837745975807471e16b4a2ba21e7256ca5"
integrity sha1-VAzjg3dFl1gHRx4WtKK6IeclbKU=
-lodash.differencewith@~4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz#bafafbc918b55154e179176a00bb0aefaac854b7"
- integrity sha1-uvr7yRi1UVTheRdqALsK76rIVLc=
-
lodash.find@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1"
integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=
-lodash.flatten@^4.4.0, lodash.flatten@~4.4.0:
+lodash.flatten@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
@@ -8155,30 +8086,12 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
-lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
+lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-log-symbols@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
- integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
- dependencies:
- chalk "^4.1.0"
- is-unicode-supported "^0.1.0"
-
-loglevel@^1.6.8:
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
- integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
-
-longest-streak@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
- integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
-
-loose-envify@^1.0.0:
+loose-envify@^1.0.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -8268,9 +8181,9 @@ map-obj@^1.0.0:
integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
map-obj@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5"
- integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
+ integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
map-visit@^1.0.0:
version "1.0.0"
@@ -8279,13 +8192,13 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-markdown-it@12.0.2:
- version "12.0.2"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.2.tgz#4401beae8df8aa2221fc6565a7188e60a06ef0ed"
- integrity sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA==
+markdown-it@12.3.2:
+ version "12.3.2"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
+ integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
dependencies:
argparse "^2.0.1"
- entities "~2.0.0"
+ entities "~2.1.0"
linkify-it "^3.0.1"
mdurl "^1.0.1"
uc.micro "^1.0.5"
@@ -8301,37 +8214,33 @@ markdown-it@^10.0.0:
mdurl "^1.0.1"
uc.micro "^1.0.5"
-markdownlint-cli@0.26.0:
- version "0.26.0"
- resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.26.0.tgz#cd89e3e39a049303ec125c8aa291da4f3325df29"
- integrity sha512-biLfeGNZG9nw0yJbtFBzRlew2/P5w7JSseKwolSox3zejs7dLpGvPgqbC+iqJnqqGWcWLtXaXh8bBEKWmfl10A==
- dependencies:
- commander "~6.2.1"
- deep-extend "~0.6.0"
- get-stdin "~8.0.0"
- glob "~7.1.6"
- ignore "~5.1.8"
- js-yaml "~3.14.1"
+markdownlint-cli@0.31.0:
+ version "0.31.0"
+ resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.31.0.tgz#a44264a71066475228292b7af19d3d18b827676d"
+ integrity sha512-UCNA10I2evrEqGWUGM4I6ae6LubLeySkKegP1GQaZSES516BYBgOn8Ai8MXU+5rSIeCvMyKi91alqHyRDuUnYA==
+ dependencies:
+ commander "~9.0.0"
+ get-stdin "~9.0.0"
+ glob "~7.2.0"
+ ignore "~5.2.0"
+ js-yaml "^4.1.0"
jsonc-parser "~3.0.0"
- lodash.differencewith "~4.5.0"
- lodash.flatten "~4.4.0"
- markdownlint "~0.22.0"
- markdownlint-rule-helpers "~0.13.0"
+ markdownlint "~0.25.1"
+ markdownlint-rule-helpers "~0.16.0"
minimatch "~3.0.4"
- minimist "~1.2.5"
- rc "~1.2.8"
+ run-con "~1.2.10"
-markdownlint-rule-helpers@~0.13.0:
- version "0.13.0"
- resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.13.0.tgz#7cc6553bc7f8c4c8a43cf66fb2a3a652124f46f9"
- integrity sha512-rRY0itbcHG4e+ntz0bbY3AIceSJMKS0TafEMgEtKVHRZ54/JUSy6/4ypCL618RlJvYRej+xMLxX5nkJqIeTZaQ==
+markdownlint-rule-helpers@~0.16.0:
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz#c327f72782bd2b9475127a240508231f0413a25e"
+ integrity sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==
-markdownlint@~0.22.0:
- version "0.22.0"
- resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.22.0.tgz#4ed95b61c17ae9f4dfca6a01f038c744846c0a72"
- integrity sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w==
+markdownlint@~0.25.1:
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.25.1.tgz#df04536607ebeeda5ccd5e4f38138823ed623788"
+ integrity sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==
dependencies:
- markdown-it "12.0.2"
+ markdown-it "12.3.2"
marked@^0.3.12, marked@~0.3.6:
version "0.3.19"
@@ -8365,34 +8274,6 @@ md5@^2.2.1:
crypt "~0.0.1"
is-buffer "~1.1.1"
-mdast-util-from-markdown@^0.8.0:
- version "0.8.5"
- resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c"
- integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==
- dependencies:
- "@types/mdast" "^3.0.0"
- mdast-util-to-string "^2.0.0"
- micromark "~2.11.0"
- parse-entities "^2.0.0"
- unist-util-stringify-position "^2.0.0"
-
-mdast-util-to-markdown@^0.6.0:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe"
- integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==
- dependencies:
- "@types/unist" "^2.0.0"
- longest-streak "^2.0.0"
- mdast-util-to-string "^2.0.0"
- parse-entities "^2.0.0"
- repeat-string "^1.0.0"
- zwitch "^1.0.0"
-
-mdast-util-to-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
- integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
-
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
@@ -8403,6 +8284,13 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+memfs@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305"
+ integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==
+ dependencies:
+ fs-monkey "1.0.3"
+
memory-fs@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
@@ -8459,7 +8347,7 @@ merge-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-merge2@^1.3.0:
+merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
@@ -8489,15 +8377,7 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-micromark@~2.11.0:
- version "2.11.4"
- resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a"
- integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==
- dependencies:
- debug "^4.0.0"
- parse-entities "^2.0.0"
-
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
+micromatch@^3.1.10, micromatch@^3.1.4:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -8532,24 +8412,24 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.47.0, "mime-db@>= 1.40.0 < 2":
- version "1.47.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
- integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
+mime-db@1.51.0, "mime-db@>= 1.40.0 < 2":
+ version "1.51.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c"
+ integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==
-mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.30"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
- integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+ version "2.1.34"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24"
+ integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==
dependencies:
- mime-db "1.47.0"
+ mime-db "1.51.0"
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-mime@^2.3.1, mime@^2.4.4:
+mime@^2.3.1:
version "2.4.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
@@ -8602,7 +8482,7 @@ minimist-options@4.1.0:
is-plain-obj "^1.1.0"
kind-of "^6.0.3"
-minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5:
+minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@@ -8711,10 +8591,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.3:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-mock-apollo-client@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/mock-apollo-client/-/mock-apollo-client-0.7.0.tgz#5f70e75c842a9f3b3da2252f68fd47f2d9955f77"
- integrity sha512-r0ICU01m007W0MwMej0lzlg1REtepDZ15Fyj8Hz9tiW/1TPb0PyHryGykrg9YhfbB8/+ZF2ovz+88yMF75TDoA==
+mock-apollo-client@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mock-apollo-client/-/mock-apollo-client-1.2.0.tgz#72543df0d74577d29be1b34cecba8898c7e71451"
+ integrity sha512-zCVHv3p7zvUmen9zce9l965ZrI6rMbrm2/oqGaTerVYOaYskl/cVgTG/L7iIToTIpI7onk/f6tu8hxPXZdyy/g==
moment-mini@^2.24.0:
version "2.24.0"
@@ -8785,15 +8665,10 @@ multicast-dns@^6.0.1:
dns-packet "^1.0.1"
thunky "^0.1.0"
-nanocolors@^0.1.5:
- version "0.1.12"
- resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6"
- integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ==
-
-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==
+nanoid@^3.1.30:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
+ integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
nanomatch@^1.2.9:
version "1.2.13"
@@ -8844,10 +8719,10 @@ node-fetch@^2.6.1, node-fetch@^2.6.5:
dependencies:
whatwg-url "^5.0.0"
-node-forge@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
- integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
+node-forge@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c"
+ integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==
node-int64@^0.4.0:
version "0.4.0"
@@ -8900,10 +8775,10 @@ node-notifier@^8.0.0:
uuid "^8.3.0"
which "^2.0.2"
-node-releases@^1.1.76:
- version "1.1.76"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e"
- integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA==
+node-releases@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
+ integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
nodemon@^2.0.4:
version "2.0.4"
@@ -8947,13 +8822,13 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
validate-npm-package-license "^3.0.1"
normalize-package-data@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.0.tgz#1f8a7c423b3d2e85eb36985eaf81de381d01301a"
- integrity sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
+ integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==
dependencies:
- hosted-git-info "^3.0.6"
- resolve "^1.17.0"
- semver "^7.3.2"
+ hosted-git-info "^4.0.1"
+ is-core-module "^2.5.0"
+ semver "^7.3.4"
validate-npm-package-license "^3.0.1"
normalize-path@^2.1.1:
@@ -8968,11 +8843,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-normalize-range@^0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
- integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
-
normalize-selector@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03"
@@ -8990,7 +8860,7 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
-npm-run-path@^4.0.0:
+npm-run-path@^4.0.0, npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@@ -9004,11 +8874,6 @@ nth-check@^2.0.0:
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"
- integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
-
nwsapi@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
@@ -9019,7 +8884,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.0.1:
+object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -9111,31 +8976,34 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
-onetime@^5.1.0:
+onetime@^5.1.0, onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
+open@^8.0.9:
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
+ integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
-opn@^5.5.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
- integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
- dependencies:
- is-wsl "^1.1.0"
-
-optimism@^0.10.0:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.3.tgz#163268fdc741dea2fb50f300bedda80356445fd7"
- integrity sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==
+optimism@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.14.0.tgz#256fb079a3428585b40a3a8462f907e0abd2fc49"
+ integrity sha512-ygbNt8n4DOCVpkwiLF+IrKKeNHOjtr9aXLWGP9HNJGoblSGsnVbJLstcH6/nE9Xy5ZQtlkSioFQNnthmENW6FQ==
dependencies:
- "@wry/context" "^0.4.0"
+ "@wry/context" "^0.5.2"
+ "@wry/trie" "^0.2.1"
optionator@^0.8.1:
version "0.8.3"
@@ -9166,13 +9034,6 @@ orderedmap@^1.1.0:
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.1.tgz#c618e77611b3b21d0fe3edc92586265e0059c789"
integrity sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==
-original@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
- integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==
- dependencies:
- url-parse "^1.4.3"
-
os-browserify@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
@@ -9253,11 +9114,6 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
-p-map@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
- integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
-
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
@@ -9265,12 +9121,13 @@ p-map@^4.0.0:
dependencies:
aggregate-error "^3.0.0"
-p-retry@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328"
- integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==
+p-retry@^4.5.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c"
+ integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==
dependencies:
- retry "^0.12.0"
+ "@types/retry" "^0.12.0"
+ retry "^0.13.1"
p-try@^1.0.0:
version "1.0.0"
@@ -9336,18 +9193,6 @@ parse-color@^1.0.0:
dependencies:
color-convert "~0.5.0"
-parse-entities@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8"
- integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==
- dependencies:
- character-entities "^1.0.0"
- character-entities-legacy "^1.0.0"
- character-reference-invalid "^1.0.0"
- is-alphanumerical "^1.0.0"
- is-decimal "^1.0.0"
- is-hexadecimal "^1.0.0"
-
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
@@ -9365,11 +9210,6 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
-parse-passwd@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
- integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-
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"
@@ -9417,11 +9257,6 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-path-is-inside@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
- integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
-
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
@@ -9432,10 +9267,10 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-path-parse@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
- integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-to-regexp@0.1.7:
version "0.1.7"
@@ -9478,6 +9313,16 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+picocolors@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+ integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
@@ -9498,18 +9343,6 @@ pikaday@^1.8.0:
resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.8.0.tgz#ce930e257042e852e6aadee1115e01554b2d71c5"
integrity sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA==
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
-
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
pirates@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
@@ -9553,7 +9386,7 @@ portal-vue@^2.1.6, portal-vue@^2.1.7:
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.7.tgz#ea08069b25b640ca08a5b86f67c612f15f4e4ad4"
integrity sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==
-portfinder@^1.0.26:
+portfinder@^1.0.28:
version "1.0.28"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==
@@ -9567,20 +9400,6 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-postcss-html@^0.36.0:
- version "0.36.0"
- resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204"
- integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==
- dependencies:
- htmlparser2 "^3.10.0"
-
-postcss-less@^3.1.4:
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad"
- integrity sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==
- dependencies:
- postcss "^7.0.14"
-
postcss-media-query-parser@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
@@ -9623,70 +9442,50 @@ postcss-resolve-nested-selector@^0.1.1:
resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e"
integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=
-postcss-safe-parser@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96"
- integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==
- dependencies:
- postcss "^7.0.26"
-
-postcss-sass@^0.4.4:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.4.4.tgz#91f0f3447b45ce373227a98b61f8d8f0785285a3"
- integrity sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==
- dependencies:
- gonzales-pe "^4.3.0"
- postcss "^7.0.21"
+postcss-safe-parser@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz#bb4c29894171a94bc5c996b9a30317ef402adaa1"
+ integrity sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==
-postcss-scss@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.1.1.tgz#ec3a75fa29a55e016b90bf3269026c53c1d2b383"
- integrity sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==
- dependencies:
- postcss "^7.0.6"
+postcss-scss@4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.3.tgz#36c23c19a804274e722e83a54d20b838ab4767ac"
+ integrity sha512-j4KxzWovfdHsyxwl1BxkUal/O4uirvHgdzMKS1aWJBAV0qh2qj5qAZqpeBfVUYGWv+4iK9Az7SPyZ4fyNju1uA==
-postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
- integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
+postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
+ version "6.0.9"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f"
+ integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==
dependencies:
cssesc "^3.0.0"
- indexes-of "^1.0.1"
- uniq "^1.0.1"
util-deprecate "^1.0.2"
-postcss-syntax@^0.36.2:
- version "0.36.2"
- resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c"
- integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==
-
postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
-postcss-value-parser@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
- integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
+postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
-postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.5, postcss@^7.0.6:
- version "7.0.35"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
- integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
+postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6:
+ version "7.0.39"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+ integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
dependencies:
- chalk "^2.4.2"
+ picocolors "^0.2.1"
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==
+postcss@^8.2.1, postcss@^8.4.5:
+ version "8.4.5"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
+ integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
dependencies:
- colorette "^1.2.2"
- nanoid "^3.1.23"
- source-map "^0.6.1"
+ nanoid "^3.1.30"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.1"
prelude-ls@^1.2.1:
version "1.2.1"
@@ -9799,6 +9598,15 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.4"
+prop-types@^15.7.2:
+ version "15.7.2"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+ integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.8.1"
+
prosemirror-collab@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/prosemirror-collab/-/prosemirror-collab-1.2.2.tgz#8d2c0e82779cfef5d051154bd0836428bd6d9c4a"
@@ -9806,10 +9614,10 @@ prosemirror-collab@^1.2.2:
dependencies:
prosemirror-state "^1.0.0"
-prosemirror-commands@^1.1.12, prosemirror-commands@^1.1.4:
- version "1.1.12"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.12.tgz#5cb0fef4e5a0039e2fa19b42a5626af03d7c2ec3"
- integrity sha512-+CrMs3w/ZVPSkR+REg8KL/clyFLv/1+SgY/OMN+CB22Z24j9TZDje72vL36lOZ/E4NeRXuiCcmENcW/vAcG67A==
+prosemirror-commands@^1.1.4, prosemirror-commands@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.2.1.tgz#eae0cb714df695260659b78ff5d201d3a037e50d"
+ integrity sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
@@ -9924,10 +9732,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.23.5:
- version "1.23.5"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.5.tgz#0f4af48fa9d30aa0b945816e2b8e6cb1c82ac674"
- integrity sha512-GlcCtoFdW17KNOKjOl7OZTU3btENgVfzN/i0RBvy1SEKAZfo88PdvcFrWTraNZHH+y/uhYR3PAdMiDK9DlN5UA==
+prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.6:
+ version "1.23.6"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.6.tgz#f514b3166942cb70aac4ac24d0a28c21c3897608"
+ integrity sha512-B4DAzriNpI/AVoW0Lu6SVfX00jZZQxOVwdBQEjWlRbCdT9V0pvk4GQJ3JTFaib+b6BcPdRZ3MjWXz2xvV1rblA==
dependencies:
prosemirror-model "^1.16.0"
prosemirror-state "^1.0.0"
@@ -10057,11 +9865,6 @@ querystring@0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
-querystringify@^2.1.1:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
- integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
-
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -10117,7 +9920,7 @@ raw-loader@^4.0.2:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
-rc@^1.2.8, rc@~1.2.8:
+rc@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -10127,7 +9930,7 @@ rc@^1.2.8, rc@~1.2.8:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-is@^16.12.0:
+react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -10186,7 +9989,7 @@ read-pkg@^5.2.0:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.0.6, readable-stream@^3.1.1:
+readable-stream@^3.0.6:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -10214,6 +10017,13 @@ readdirp@~3.4.0:
dependencies:
picomatch "^2.2.1"
+rechoir@^0.7.0:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686"
+ integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==
+ dependencies:
+ resolve "^1.9.0"
+
redent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
@@ -10298,29 +10108,6 @@ regjsparser@^0.6.4:
dependencies:
jsesc "~0.5.0"
-remark-parse@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640"
- integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==
- dependencies:
- mdast-util-from-markdown "^0.8.0"
-
-remark-stringify@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894"
- integrity sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==
- dependencies:
- mdast-util-to-markdown "^0.6.0"
-
-remark@^13.0.0:
- version "13.0.0"
- resolved "https://registry.yarnpkg.com/remark/-/remark-13.0.0.tgz#d15d9bf71a402f40287ebe36067b66d54868e425"
- integrity sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==
- dependencies:
- remark-parse "^9.0.0"
- remark-stringify "^9.0.0"
- unified "^9.1.0"
-
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@@ -10331,7 +10118,7 @@ repeat-element@^1.1.2:
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
-repeat-string@^1.0.0, repeat-string@^1.6.1:
+repeat-string@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
@@ -10419,13 +10206,6 @@ requizzle@~0.2.1:
dependencies:
underscore "~1.6.0"
-resolve-cwd@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
- integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=
- dependencies:
- resolve-from "^3.0.0"
-
resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
@@ -10433,24 +10213,11 @@ resolve-cwd@^3.0.0:
dependencies:
resolve-from "^5.0.0"
-resolve-dir@^1.0.0, resolve-dir@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
- integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
- dependencies:
- expand-tilde "^2.0.0"
- global-modules "^1.0.0"
-
resolve-from@5.0.0, resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
-resolve-from@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
- integrity sha1-six699nWiBvItuZTM17rywoYh0g=
-
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -10461,13 +10228,14 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.20.0:
- version "1.20.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
- integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.9.0:
+ version "1.22.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
+ integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
dependencies:
- is-core-module "^2.2.0"
- path-parse "^1.0.6"
+ is-core-module "^2.8.1"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
responselike@^1.0.2:
version "1.0.2"
@@ -10481,10 +10249,10 @@ ret@~0.1.10:
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-retry@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
- integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
+retry@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
+ integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
reusify@^1.0.4:
version "1.0.4"
@@ -10533,6 +10301,16 @@ rsvp@^4.8.4:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
+run-con@~1.2.10:
+ version "1.2.10"
+ resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.10.tgz#90de9d43d20274d00478f4c000495bd72f417d22"
+ integrity sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==
+ dependencies:
+ deep-extend "^0.6.0"
+ ini "~2.0.0"
+ minimist "^1.2.5"
+ strip-json-comments "~3.1.1"
+
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@@ -10630,14 +10408,24 @@ schema-utils@^2.0.0, schema-utils@^2.6.5, schema-utils@^2.7.0:
ajv-keywords "^3.5.2"
schema-utils@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
- integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
+ integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
dependencies:
- "@types/json-schema" "^7.0.6"
+ "@types/json-schema" "^7.0.8"
ajv "^6.12.5"
ajv-keywords "^3.5.2"
+schema-utils@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7"
+ integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.8.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.0.0"
+
scrollparent@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.0.1.tgz#715d5b9cc57760fb22bdccc3befb5bfe06b1a317"
@@ -10658,12 +10446,12 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
-selfsigned@^1.10.8:
- version "1.10.8"
- resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30"
- integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==
+selfsigned@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b"
+ integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==
dependencies:
- node-forge "^0.10.0"
+ node-forge "^1.2.0"
semver-diff@^3.1.1:
version "3.1.1"
@@ -10687,7 +10475,7 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-semver@^7.2.1, semver@^7.3.2:
+semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
@@ -10713,7 +10501,7 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
-serialize-javascript@^2.1.0, serialize-javascript@^2.1.2:
+serialize-javascript@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
@@ -10793,6 +10581,13 @@ sha.js@^2.4.0, sha.js@^2.4.8:
inherits "^2.0.1"
safe-buffer "^5.0.1"
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -10834,10 +10629,10 @@ sigmund@^1.0.1:
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
-signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7"
- integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==
+signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
+ integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
sirv@^1.0.7:
version "1.0.11"
@@ -10906,18 +10701,6 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
-sockjs-client@^1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add"
- integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==
- dependencies:
- debug "^3.2.6"
- eventsource "^1.0.7"
- faye-websocket "^0.11.3"
- inherits "^2.0.4"
- json3 "^3.3.3"
- url-parse "^1.4.7"
-
sockjs@^0.3.21:
version "0.3.21"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417"
@@ -10937,6 +10720,11 @@ source-list-map@^2.0.0:
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==
+source-map-js@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -11151,7 +10939,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-string-width@^3.0.0, string-width@^3.1.0:
+string-width@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
@@ -11197,14 +10985,7 @@ string_decoder@~0.10.x:
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
@@ -11218,6 +10999,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
+strip-ansi@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
+ integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==
+ dependencies:
+ ansi-regex "^6.0.1"
+
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
@@ -11245,7 +11033,7 @@ strip-indent@^3.0.0:
dependencies:
min-indent "^1.0.0"
-strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -11268,85 +11056,77 @@ style-search@^0.1.0:
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=
-stylelint-declaration-strict-value@1.7.7:
- version "1.7.7"
- resolved "https://registry.yarnpkg.com/stylelint-declaration-strict-value/-/stylelint-declaration-strict-value-1.7.7.tgz#d2f0aabc7f3e701a8988207f27d9696bd1d1ed0d"
- integrity sha512-Gr5RZYMIS7af6N6PGRD3vmCJM/NlKY4D/jWdidQqxcXkhBtsmV6C99GjQOB0nfdYtjfJEQZLMlTNBztY4tRGfA==
+stylelint-declaration-strict-value@1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/stylelint-declaration-strict-value/-/stylelint-declaration-strict-value-1.8.0.tgz#d14f368d5974085896d6573cab7c82ad4f415f57"
+ integrity sha512-0+DbPQMgqomlBG+uycI3PZ1BzjJ7mJA065Lx+iTg9tlmjBD36f3ZaIq1ggRZQitE0w+KcbXGzFt6axR1LIP2hw==
dependencies:
css-values "^0.1.0"
shortcss "^0.1.3"
-stylelint-scss@3.18.0:
- version "3.18.0"
- resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.18.0.tgz#8f06371c223909bf3f62e839548af1badeed31e9"
- integrity sha512-LD7+hv/6/ApNGt7+nR/50ft7cezKP2HM5rI8avIdGaUWre3xlHfV4jKO/DRZhscfuN+Ewy9FMhcTq0CcS0C/SA==
+stylelint-scss@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-4.1.0.tgz#39b808696f8152081163d970449257ff80b5c041"
+ integrity sha512-BNYTo7MMamhFOlcaAWp2dMpjg6hPyM/FFqfDIYzmYVLMmQJqc8lWRIiTqP4UX5bresj9Vo0dKC6odSh43VP2NA==
dependencies:
- lodash "^4.17.15"
+ lodash "^4.17.21"
postcss-media-query-parser "^0.2.3"
postcss-resolve-nested-selector "^0.1.1"
- postcss-selector-parser "^6.0.2"
+ postcss-selector-parser "^6.0.6"
postcss-value-parser "^4.1.0"
-stylelint@13.9.0:
- version "13.9.0"
- resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.9.0.tgz#93921ee6e11d4556b9f31131f485dc813b68e32a"
- integrity sha512-VVWH2oixOAxpWL1vH+V42ReCzBjW2AeqskSAbi8+3OjV1Xg3VZkmTcAqBZfRRvJeF4BvYuDLXebW3tIHxgZDEg==
+stylelint@^14.3.0:
+ version "14.3.0"
+ resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.3.0.tgz#26b62730da7b3dc320021fc469d80048d7b77ebe"
+ integrity sha512-PZXSwtJe4f4qBPWBwAbHL0M0Qjrv8iHN+cLpUNsffaVMS3YzpDDRI73+2lsqLAYfQEzxRwpll6BDKImREbpHWA==
dependencies:
- "@stylelint/postcss-css-in-js" "^0.37.2"
- "@stylelint/postcss-markdown" "^0.36.2"
- autoprefixer "^9.8.6"
- balanced-match "^1.0.0"
- chalk "^4.1.0"
- cosmiconfig "^7.0.0"
- debug "^4.3.1"
+ balanced-match "^2.0.0"
+ colord "^2.9.2"
+ cosmiconfig "^7.0.1"
+ debug "^4.3.3"
execall "^2.0.0"
- fast-glob "^3.2.5"
+ fast-glob "^3.2.11"
fastest-levenshtein "^1.0.12"
- file-entry-cache "^6.0.0"
+ file-entry-cache "^6.0.1"
get-stdin "^8.0.0"
global-modules "^2.0.0"
- globby "^11.0.2"
+ globby "^11.1.0"
globjoin "^0.1.4"
html-tags "^3.1.0"
- ignore "^5.1.8"
+ ignore "^5.2.0"
import-lazy "^4.0.0"
imurmurhash "^0.1.4"
- known-css-properties "^0.20.0"
- lodash "^4.17.20"
- log-symbols "^4.0.0"
+ is-plain-object "^5.0.0"
+ known-css-properties "^0.24.0"
mathml-tag-names "^2.1.3"
meow "^9.0.0"
- micromatch "^4.0.2"
+ micromatch "^4.0.4"
+ normalize-path "^3.0.0"
normalize-selector "^0.2.0"
- postcss "^7.0.35"
- postcss-html "^0.36.0"
- postcss-less "^3.1.4"
+ picocolors "^1.0.0"
+ postcss "^8.4.5"
postcss-media-query-parser "^0.2.3"
postcss-resolve-nested-selector "^0.1.1"
- postcss-safe-parser "^4.0.2"
- postcss-sass "^0.4.4"
- postcss-scss "^2.1.1"
- postcss-selector-parser "^6.0.4"
- postcss-syntax "^0.36.2"
- postcss-value-parser "^4.1.0"
+ postcss-safe-parser "^6.0.0"
+ postcss-selector-parser "^6.0.9"
+ postcss-value-parser "^4.2.0"
resolve-from "^5.0.0"
- slash "^3.0.0"
specificity "^0.4.1"
- string-width "^4.2.0"
- strip-ansi "^6.0.0"
+ string-width "^4.2.3"
+ strip-ansi "^6.0.1"
style-search "^0.1.0"
- sugarss "^2.0.0"
+ supports-hyperlinks "^2.2.0"
svg-tags "^1.0.0"
- table "^6.0.7"
- v8-compile-cache "^2.2.0"
- write-file-atomic "^3.0.3"
+ table "^6.8.0"
+ v8-compile-cache "^2.3.0"
+ write-file-atomic "^4.0.0"
stylis@^4.0.10:
version "4.0.10"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240"
integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==
-subscriptions-transport-ws@^0.11.0:
+subscriptions-transport-ws@0.11.0, subscriptions-transport-ws@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.11.0.tgz#baf88f050cba51d52afe781de5e81b3c31f89883"
integrity sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ==
@@ -11357,13 +11137,6 @@ subscriptions-transport-ws@^0.11.0:
symbol-observable "^1.0.4"
ws "^5.2.0 || ^6.0.0 || ^7.0.0"
-sugarss@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
- integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==
- dependencies:
- postcss "^7.0.2"
-
supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -11371,13 +11144,6 @@ supports-color@^5.3.0, supports-color@^5.5.0:
dependencies:
has-flag "^3.0.0"
-supports-color@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
- integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
- dependencies:
- has-flag "^3.0.0"
-
supports-color@^7.0.0, supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -11385,14 +11151,19 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
-supports-hyperlinks@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47"
- integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==
+supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
+ integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==
dependencies:
has-flag "^4.0.0"
supports-color "^7.0.0"
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
svg-tags@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
@@ -11403,11 +11174,16 @@ swagger-ui-dist@^3.52.3:
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.52.3.tgz#a09b5cdccac69e3f5f1cbd258654a110119a7f0e"
integrity sha512-7QSY4milmYx5O8dbzU5tTftiaoZt+4JGxahTTBiLAnbTvhTyzum9rsjDIJjC+xeT8Tt1KfB38UuQQjmrh2THDQ==
-symbol-observable@^1.0.2, symbol-observable@^1.0.4:
+symbol-observable@^1.0.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
+symbol-observable@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a"
+ integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==
+
symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
@@ -11421,10 +11197,10 @@ sync-fetch@0.3.1:
buffer "^5.7.0"
node-fetch "^2.6.1"
-table@^6.0.7, table@^6.0.9:
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/table/-/table-6.7.3.tgz#255388439715a738391bd2ee4cbca89a4d05a9b7"
- integrity sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==
+table@^6.0.9, table@^6.8.0:
+ version "6.8.0"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca"
+ integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==
dependencies:
ajv "^8.0.1"
lodash.truncate "^4.4.2"
@@ -11741,20 +11517,17 @@ tr46@~0.0.3:
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
trim-newlines@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30"
- integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==
-
-trough@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
- integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
+ integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
-ts-invariant@^0.4.0:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86"
- integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==
+ts-invariant@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.6.1.tgz#eb4c52b45daaca8367abbfd6cff998ea871d592d"
+ integrity sha512-QQgN33g8E8yrdDuH29HASveLtbzMnRRgWh0i/JNTW4+zcLsdIOnfsgEDi/NKx4UckQyuMFt9Ujm6TWLWQ58Kvg==
dependencies:
+ "@types/ungap__global-this" "^0.3.1"
+ "@ungap/global-this" "^0.4.2"
tslib "^1.9.3"
ts-node@^9:
@@ -11784,7 +11557,7 @@ tslib@2.3.0, tslib@^2, tslib@^2.2.0, tslib@~2.3.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
-tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+tslib@^1.10.0, tslib@^1.14.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -11872,6 +11645,11 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
+typedarray-to-buffer@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-4.0.0.tgz#cdd2933c61dd3f5f02eda5d012d441f95bfeb50a"
+ integrity sha512-6dOYeZfS3O9RtRD1caom0sMxgK59b27+IwoNy8RDPsmslSGOyU+mpTamlaIW7aNKi90ZQZ9DFaZL3YRoiSCULQ==
+
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@@ -11939,18 +11717,6 @@ unicode-property-aliases-ecmascript@^1.0.4:
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0"
integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==
-unified@^9.1.0:
- version "9.2.0"
- resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8"
- integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==
- dependencies:
- bail "^1.0.0"
- extend "^3.0.0"
- is-buffer "^2.0.0"
- is-plain-obj "^2.0.0"
- trough "^1.0.0"
- vfile "^4.0.0"
-
union-value@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
@@ -11961,11 +11727,6 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^2.0.1"
-uniq@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
- integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
-
unique-filename@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
@@ -11987,25 +11748,6 @@ unique-string@^2.0.0:
dependencies:
crypto-random-string "^2.0.0"
-unist-util-find-all-after@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6"
- integrity sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==
- dependencies:
- unist-util-is "^4.0.0"
-
-unist-util-is@^4.0.0:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.4.tgz#3e9e8de6af2eb0039a59f50c9b3e99698a924f50"
- integrity sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==
-
-unist-util-stringify-position@^2.0.0:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
- integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==
- dependencies:
- "@types/unist" "^2.0.2"
-
unixify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090"
@@ -12073,14 +11815,6 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"
-url-parse@^1.4.3, url-parse@^1.4.7:
- version "1.4.7"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
- integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
- dependencies:
- querystringify "^2.1.1"
- requires-port "^1.0.0"
-
url-search-params-polyfill@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-5.1.0.tgz#f0405dcc2e921bf7f5fdf8c4e616f1e8088ef31b"
@@ -12151,10 +11885,10 @@ uuid@^8.3.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
-v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1, v8-compile-cache@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"
- integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==
+v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
+ integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
v8-to-istanbul@^5.0.1:
version "5.0.1"
@@ -12197,24 +11931,6 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
-vfile-message@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a"
- integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==
- dependencies:
- "@types/unist" "^2.0.0"
- unist-util-stringify-position "^2.0.0"
-
-vfile@^4.0.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624"
- integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==
- dependencies:
- "@types/unist" "^2.0.0"
- is-buffer "^2.0.0"
- unist-util-stringify-position "^2.0.0"
- vfile-message "^2.0.0"
-
visibilityjs@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/visibilityjs/-/visibilityjs-1.2.4.tgz#bff8663da62c8c10ad4ee5ae6a1ae6fac4259d63"
@@ -12297,13 +12013,13 @@ vscode-uri@^2.1.1, vscode-uri@^2.1.2:
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
-vue-apollo@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.3.tgz#7f29558df76eec0f03251847eef153816a261827"
- integrity sha512-WJaQ1v/i46/oIPlKv7J0Tx6tTlbuaeCdhrAbL06h+Zca2gzr5ywjUFpl8ijMTGJsQ+Ph/U4xEpBFBOMxQmL+7g==
+vue-apollo@^3.0.7:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.7.tgz#97a031d45641faa4888a6d5a7f71c40834359704"
+ integrity sha512-EUfIn4cJmoflnDJiSNP8gH4fofIEzd0I2AWnd9nhHB8mddmzIfgSNjIRihDcRB10wypYG1OG0GcU335CFgZRfA==
dependencies:
chalk "^2.4.2"
- serialize-javascript "^2.1.0"
+ serialize-javascript "^4.0.0"
throttle-debounce "^2.1.0"
vue-eslint-parser@^7.0.0, vue-eslint-parser@^7.4.1:
@@ -12501,80 +12217,78 @@ webpack-bundle-analyzer@^4.4.2:
sirv "^1.0.7"
ws "^7.3.1"
-webpack-cli@^3.3.12:
- version "3.3.12"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a"
- integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==
- dependencies:
- chalk "^2.4.2"
- cross-spawn "^6.0.5"
- enhanced-resolve "^4.1.1"
- findup-sync "^3.0.0"
- global-modules "^2.0.0"
- import-local "^2.0.0"
- interpret "^1.4.0"
- loader-utils "^1.4.0"
- supports-color "^6.1.0"
- v8-compile-cache "^2.1.1"
- yargs "^13.3.2"
+webpack-cli@^4.9.2:
+ version "4.9.2"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.2.tgz#77c1adaea020c3f9e2db8aad8ea78d235c83659d"
+ integrity sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^1.1.1"
+ "@webpack-cli/info" "^1.4.1"
+ "@webpack-cli/serve" "^1.6.1"
+ colorette "^2.0.14"
+ commander "^7.0.0"
+ execa "^5.0.0"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^2.2.0"
+ rechoir "^0.7.0"
+ webpack-merge "^5.7.3"
-webpack-dev-middleware@^3.7.2:
- version "3.7.2"
- resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
- integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
+webpack-dev-middleware@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f"
+ integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==
dependencies:
- memory-fs "^0.4.1"
- mime "^2.4.4"
- mkdirp "^0.5.1"
+ colorette "^2.0.10"
+ memfs "^3.4.1"
+ mime-types "^2.1.31"
range-parser "^1.2.1"
- webpack-log "^2.0.0"
-
-webpack-dev-server@^3.11.3:
- version "3.11.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz#8c86b9d2812bf135d3c9bce6f07b718e30f7c3d3"
- integrity sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==
- dependencies:
- ansi-html-community "0.0.8"
+ schema-utils "^4.0.0"
+
+webpack-dev-server@4.7.4:
+ version "4.7.4"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945"
+ integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==
+ dependencies:
+ "@types/bonjour" "^3.5.9"
+ "@types/connect-history-api-fallback" "^1.3.5"
+ "@types/express" "^4.17.13"
+ "@types/serve-index" "^1.9.1"
+ "@types/sockjs" "^0.3.33"
+ "@types/ws" "^8.2.2"
+ ansi-html-community "^0.0.8"
bonjour "^3.5.0"
- chokidar "^2.1.8"
+ chokidar "^3.5.3"
+ colorette "^2.0.10"
compression "^1.7.4"
connect-history-api-fallback "^1.6.0"
- debug "^4.1.1"
- del "^4.1.1"
+ default-gateway "^6.0.3"
+ del "^6.0.0"
express "^4.17.1"
- html-entities "^1.3.1"
- http-proxy-middleware "0.19.1"
- import-local "^2.0.0"
- internal-ip "^4.3.0"
- ip "^1.1.5"
- is-absolute-url "^3.0.3"
- killable "^1.0.1"
- loglevel "^1.6.8"
- opn "^5.5.0"
- p-retry "^3.0.1"
- portfinder "^1.0.26"
- schema-utils "^1.0.0"
- selfsigned "^1.10.8"
- semver "^6.3.0"
+ graceful-fs "^4.2.6"
+ html-entities "^2.3.2"
+ http-proxy-middleware "^2.0.0"
+ ipaddr.js "^2.0.1"
+ open "^8.0.9"
+ p-retry "^4.5.0"
+ portfinder "^1.0.28"
+ schema-utils "^4.0.0"
+ selfsigned "^2.0.0"
serve-index "^1.9.1"
sockjs "^0.3.21"
- sockjs-client "^1.5.0"
spdy "^4.0.2"
- strip-ansi "^3.0.1"
- supports-color "^6.1.0"
- url "^0.11.0"
- webpack-dev-middleware "^3.7.2"
- webpack-log "^2.0.0"
- ws "^6.2.1"
- yargs "^13.3.2"
+ strip-ansi "^7.0.0"
+ webpack-dev-middleware "^5.3.1"
+ ws "^8.4.2"
-webpack-log@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
- integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
+webpack-merge@^5.7.3:
+ version "5.8.0"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61"
+ integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==
dependencies:
- ansi-colors "^3.0.0"
- uuid "^3.3.2"
+ clone-deep "^4.0.1"
+ wildcard "^2.0.0"
webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
version "1.4.3"
@@ -12628,9 +12342,9 @@ websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7"
- integrity sha1-domUmcGEtu91Q3fC27DNbLVdKec=
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
whatwg-encoding@^1.0.5:
version "1.0.5"
@@ -12666,7 +12380,7 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@^1.2.14, which@^1.2.9, which@^1.3.1:
+which@^1.2.9, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -12687,6 +12401,11 @@ widest-line@^3.1.0:
dependencies:
string-width "^4.0.0"
+wildcard@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
+ integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
+
word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
@@ -12707,15 +12426,6 @@ worker-loader@^2.0.0:
loader-utils "^1.0.0"
schema-utils "^0.4.0"
-wrap-ansi@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
- integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
- dependencies:
- ansi-styles "^3.2.0"
- string-width "^3.0.0"
- strip-ansi "^5.0.0"
-
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
@@ -12730,7 +12440,7 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
+write-file-atomic@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
@@ -12740,6 +12450,16 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
+write-file-atomic@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.0.tgz#0eff5dc687d3e22535ca3fca8558124645a4b053"
+ integrity sha512-JhcWoKffJNF7ivO9yflBhc7tn3wKnokMUfWpBriM9yCXj4ePQnRPcWglBkkg1AHC8nsW/EfxwwhqsLtOy59djA==
+ dependencies:
+ imurmurhash "^0.1.4"
+ is-typedarray "^1.0.0"
+ signal-exit "^3.0.2"
+ typedarray-to-buffer "^4.0.0"
+
ws@8.2.3:
version "8.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
@@ -12750,12 +12470,10 @@ ws@8.2.3:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
-ws@^6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
- integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
- dependencies:
- async-limiter "~1.0.0"
+ws@^8.4.2:
+ version "8.5.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
+ integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
xdg-basedir@^4.0.0:
version "4.0.0"
@@ -12860,18 +12578,10 @@ yaml@^1.10.0:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-yaml@^2.0.0-8:
- version "2.0.0-8"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-8.tgz#226365f0d804ba7fb8cc2b527a00a7a4a3d8ea5f"
- integrity sha512-QaYgJZMfWD6fKN/EYMk6w1oLWPCr1xj9QaPSZW5qkDb3y8nGCXhy2Ono+AF4F+CSL/vGcqswcAT0BaS//pgD2A==
-
-yargs-parser@^13.1.2:
- version "13.1.2"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
- integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
+yaml@^2.0.0-10:
+ version "2.0.0-10"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-10.tgz#d5b59e2d14b8683313a534f2bbc648e211a2753e"
+ integrity sha512-FHV8s5ODFFQXX/enJEU2EkanNl1UDBUz8oa4k5Qo/sR+Iq7VmhCDkRMb0/mjJCNeAWQ31W8WV6PYStDE4d9EIw==
yargs-parser@^18.1.2:
version "18.1.3"
@@ -12882,25 +12592,9 @@ yargs-parser@^18.1.2:
decamelize "^1.2.0"
yargs-parser@^20.2.3:
- version "20.2.4"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
- integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
-
-yargs@^13.3.2:
- version "13.3.2"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
- integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
- dependencies:
- cliui "^5.0.0"
- find-up "^3.0.0"
- get-caller-file "^2.0.1"
- require-directory "^2.1.1"
- require-main-filename "^2.0.0"
- set-blocking "^2.0.0"
- string-width "^3.0.0"
- which-module "^2.0.0"
- y18n "^4.0.0"
- yargs-parser "^13.1.2"
+ version "20.2.9"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+ integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs@^15.4.1:
version "15.4.1"
@@ -12945,18 +12639,10 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-zen-observable-ts@^0.8.21:
- version "0.8.21"
- resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d"
- integrity sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==
- dependencies:
- tslib "^1.9.3"
- zen-observable "^0.8.0"
-
-zen-observable@^0.8.0:
- version "0.8.11"
- resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.11.tgz#d3415885eeeb42ee5abb9821c95bb518fcd6d199"
- integrity sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==
+zen-observable@^0.8.14:
+ version "0.8.15"
+ resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
+ integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
zrender@5.2.1:
version "5.2.1"
@@ -12964,8 +12650,3 @@ zrender@5.2.1:
integrity sha512-M3bPGZuyLTNBC6LiNKXJwSCtglMp8XUEqEBG+2MdICDI3d1s500Y4P0CzldQGsqpRVB7fkvf3BKQQRxsEaTlsw==
dependencies:
tslib "2.3.0"
-
-zwitch@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"
- integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==